proxygen
BoostContextCompatibility.h
Go to the documentation of this file.
1 /*
2  * Copyright 2014-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 
18 #include <boost/version.hpp>
19 #if BOOST_VERSION >= 106100
20 #include <boost/context/detail/fcontext.hpp>
21 #else
22 #include <boost/context/fcontext.hpp>
23 #endif
24 #include <glog/logging.h>
25 
39 #include <folly/Function.h>
40 
41 namespace folly {
42 namespace fibers {
43 
44 class FiberImpl {
45 #if BOOST_VERSION >= 106100
46  using FiberContext = boost::context::detail::fcontext_t;
47 #elif BOOST_VERSION >= 105600
48  using FiberContext = boost::context::fcontext_t;
49 #elif BOOST_VERSION >= 105200
50  using FiberContext = boost::context::fcontext_t*;
51 #else
52  using FiberContext = boost::ctx::fcontext_t;
53 #endif
54 
55 #if BOOST_VERSION >= 106100
56  using MainContext = boost::context::detail::fcontext_t;
57 #elif BOOST_VERSION >= 105600
58  using MainContext = boost::context::fcontext_t;
59 #elif BOOST_VERSION >= 105200
60  using MainContext = boost::context::fcontext_t;
61 #else
62  using MainContext = boost::ctx::fcontext_t;
63 #endif
64 
65  public:
67  folly::Function<void()> func,
68  unsigned char* stackLimit,
69  size_t stackSize)
70  : func_(std::move(func)) {
71  auto stackBase = stackLimit + stackSize;
72 #if BOOST_VERSION >= 106100
73  stackBase_ = stackBase;
75  boost::context::detail::make_fcontext(stackBase, stackSize, &fiberFunc);
76 #elif BOOST_VERSION >= 105200
78  boost::context::make_fcontext(stackBase, stackSize, &fiberFunc);
79 #else
80  fiberContext_.fc_stack.limit = stackLimit;
81  fiberContext_.fc_stack.base = stackBase;
82  make_fcontext(&fiberContext_, &fiberFunc);
83 #endif
84  }
85 
86  void activate() {
87 #if BOOST_VERSION >= 106100
88  auto transfer = boost::context::detail::jump_fcontext(fiberContext_, this);
89  fiberContext_ = transfer.fctx;
90  auto context = reinterpret_cast<intptr_t>(transfer.data);
91 #elif BOOST_VERSION >= 105200
92  auto context = boost::context::jump_fcontext(
93  &mainContext_, fiberContext_, reinterpret_cast<intptr_t>(this));
94 #else
95  auto context = jump_fcontext(
96  &mainContext_, &fiberContext_, reinterpret_cast<intptr_t>(this));
97 #endif
98  DCHECK_EQ(0, context);
99  }
100 
101  void deactivate() {
102 #if BOOST_VERSION >= 106100
103  auto transfer =
104  boost::context::detail::jump_fcontext(mainContext_, nullptr);
105  mainContext_ = transfer.fctx;
106  fixStackUnwinding();
107  auto context = reinterpret_cast<intptr_t>(transfer.data);
108 #elif BOOST_VERSION >= 105600
109  auto context =
110  boost::context::jump_fcontext(&fiberContext_, mainContext_, 0);
111 #elif BOOST_VERSION >= 105200
112  auto context =
113  boost::context::jump_fcontext(fiberContext_, &mainContext_, 0);
114 #else
115  auto context = jump_fcontext(&fiberContext_, &mainContext_, 0);
116 #endif
117  DCHECK_EQ(this, reinterpret_cast<FiberImpl*>(context));
118  }
119 
120  private:
121 #if BOOST_VERSION >= 106100
122  static void fiberFunc(boost::context::detail::transfer_t transfer) {
123  auto fiberImpl = reinterpret_cast<FiberImpl*>(transfer.data);
124  fiberImpl->mainContext_ = transfer.fctx;
125  fiberImpl->fixStackUnwinding();
126  fiberImpl->func_();
127  }
128 
129  void fixStackUnwinding() {
130  if (kIsArchAmd64 && kIsLinux) {
131  // Extract RBP and RIP from main context to stitch main context stack and
132  // fiber stack.
133  auto stackBase = reinterpret_cast<void**>(stackBase_);
134  auto mainContext = reinterpret_cast<void**>(mainContext_);
135  stackBase[-2] = mainContext[6];
136  stackBase[-1] = mainContext[7];
137  }
138  }
139 
140  unsigned char* stackBase_;
141 #else
142  static void fiberFunc(intptr_t arg) {
143  auto fiberImpl = reinterpret_cast<FiberImpl*>(arg);
144  fiberImpl->func_();
145  }
146 #endif
147 
151 };
152 } // namespace fibers
153 } // namespace folly
folly::Function< void()> func_
context
Definition: CMakeCache.txt:563
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
STL namespace.
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
boost::ctx::fcontext_t FiberContext
FiberImpl(folly::Function< void()> func, unsigned char *stackLimit, size_t stackSize)
constexpr bool kIsArchAmd64
Definition: Portability.h:102
static void fiberFunc(intptr_t arg)
boost::ctx::fcontext_t MainContext
constexpr auto kIsLinux
Definition: Portability.h:361