23 #include <glog/logging.h> 33 #ifdef FOLLY_SANITIZE_ADDRESS 37 static void __sanitizer_start_switch_fiber_weak(
38 void** fake_stack_save,
39 void const* fiber_stack_base,
40 size_t fiber_stack_extent)
41 __attribute__((__weakref__(
"__sanitizer_start_switch_fiber")));
42 static void __sanitizer_finish_switch_fiber_weak(
43 void* fake_stack_save,
44 void const** old_stack_base,
45 size_t* old_stack_extent)
46 __attribute__((__weakref__(
"__sanitizer_finish_switch_fiber")));
47 static void __asan_unpoison_memory_region_weak(
48 void const volatile*
addr,
51 typedef void (*AsanStartSwitchStackFuncPtr)(
void**,
void const*, size_t);
52 typedef void (*AsanFinishSwitchStackFuncPtr)(
void*,
void const**,
size_t*);
53 typedef void (*AsanUnpoisonMemoryRegionFuncPtr)(
60 static AsanStartSwitchStackFuncPtr getStartSwitchStackFunc();
61 static AsanFinishSwitchStackFuncPtr getFinishSwitchStackFunc();
62 static AsanUnpoisonMemoryRegionFuncPtr getUnpoisonMemoryRegionFunc();
74 std::unique_ptr<LoopController> loopController,
105 Fiber* fiber =
nullptr;
113 fiber =
new Fiber(*
this);
128 fiber->
init(recordStack);
174 assert(fiber !=
nullptr);
185 fiberManager_.doFibersPoolResizing();
186 fiberManager_.timeoutManager_->registerTimeout(
188 std::chrono::milliseconds(
189 fiberManager_.options_.fibersPoolResizePeriodMs));
192 #ifdef FOLLY_SANITIZE_ADDRESS 194 void FiberManager::registerStartSwitchStackWithAsan(
195 void** saveFakeStack,
196 const void* stackBottom,
199 static AsanStartSwitchStackFuncPtr fn = getStartSwitchStackFunc();
201 LOG(
FATAL) <<
"The version of ASAN in use doesn't support fibers";
203 fn(saveFakeStack, stackBottom, stackSize);
207 void FiberManager::registerFinishSwitchStackWithAsan(
209 const void** saveStackBottom,
210 size_t* saveStackSize) {
212 static AsanFinishSwitchStackFuncPtr fn = getFinishSwitchStackFunc();
214 LOG(
FATAL) <<
"The version of ASAN in use doesn't support fibers";
216 fn(saveFakeStack, saveStackBottom, saveStackSize);
220 void FiberManager::freeFakeStack(
void* fakeStack) {
221 static AsanStartSwitchStackFuncPtr fnStart = getStartSwitchStackFunc();
222 static AsanFinishSwitchStackFuncPtr fnFinish = getFinishSwitchStackFunc();
223 if (fnStart ==
nullptr || fnFinish ==
nullptr) {
224 LOG(
FATAL) <<
"The version of ASAN in use doesn't support fibers";
228 const void* stackBottom;
230 fnStart(&saveFakeStack,
nullptr, 0);
231 fnFinish(fakeStack, &stackBottom, &stackSize);
232 fnStart(
nullptr, stackBottom, stackSize);
233 fnFinish(saveFakeStack,
nullptr,
nullptr);
236 void FiberManager::unpoisonFiberStack(
const Fiber* fiber) {
240 static AsanUnpoisonMemoryRegionFuncPtr fn = getUnpoisonMemoryRegionFunc();
242 LOG(
FATAL) <<
"This version of ASAN doesn't support memory unpoisoning";
244 fn(stack.first, stack.second);
248 static AsanStartSwitchStackFuncPtr getStartSwitchStackFunc() {
249 AsanStartSwitchStackFuncPtr fn{
nullptr};
252 if (
nullptr != (fn = &::__sanitizer_start_switch_fiber_weak)) {
258 (fn = (AsanStartSwitchStackFuncPtr)dlsym(
259 RTLD_DEFAULT,
"__sanitizer_start_switch_fiber"))) {
267 static AsanFinishSwitchStackFuncPtr getFinishSwitchStackFunc() {
268 AsanFinishSwitchStackFuncPtr fn{
nullptr};
271 if (
nullptr != (fn = &::__sanitizer_finish_switch_fiber_weak)) {
277 (fn = (AsanFinishSwitchStackFuncPtr)dlsym(
278 RTLD_DEFAULT,
"__sanitizer_finish_switch_fiber"))) {
286 static AsanUnpoisonMemoryRegionFuncPtr getUnpoisonMemoryRegionFunc() {
287 AsanUnpoisonMemoryRegionFuncPtr fn{
nullptr};
290 if (
nullptr != (fn = &::__asan_unpoison_memory_region_weak)) {
296 (fn = (AsanUnpoisonMemoryRegionFuncPtr)dlsym(
297 RTLD_DEFAULT,
"__asan_unpoison_memory_region"))) {
305 #endif // FOLLY_SANITIZE_ADDRESS 314 bool hasAlternateStack() {
316 sigaltstack(
nullptr, &ss);
317 return !(ss.ss_flags & SS_DISABLE);
320 int setAlternateStack(
char* sp,
size_t size) {
325 return sigaltstack(&ss,
nullptr);
328 int unsetAlternateStack() {
330 ss.ss_flags = SS_DISABLE;
331 return sigaltstack(&ss,
nullptr);
334 class ScopedAlternateSignalStack {
336 ScopedAlternateSignalStack() {
337 if (hasAlternateStack()) {
341 stack_ = std::make_unique<AltStackBuffer>();
346 ScopedAlternateSignalStack(ScopedAlternateSignalStack&&) =
default;
347 ScopedAlternateSignalStack&
operator=(ScopedAlternateSignalStack&&) =
default;
349 ~ScopedAlternateSignalStack() {
351 unsetAlternateStack();
356 using AltStackBuffer = std::array<char, kAltStackSize>;
std::pair< void *, size_t > getStack() const
size_t stackHighWatermark_
size_t fibersAllocated() const
void doFibersPoolResizing()
FiberTailQueue readyFibers_
void setPreemptRunner(InlineFunctionRunner *preemptRunner)
constexpr detail::Map< Move > move
static FOLLY_TLS FiberManager * currentFiberManager_
void registerAlternateSignalStack()
—— Concurrent Priority Queue Implementation ——
virtual void runnable(uintptr_t id) noexcept=0
constexpr T constexpr_max(T a)
bool fibersPoolResizerScheduled_
std::unique_ptr< LoopController > loopController_
Single-threaded task execution engine.
constexpr auto size(C const &c) -> decltype(c.size())
Fiber object used by FiberManager to execute tasks.
InlineFunctionRunner * preemptRunner_
uint32_t fibersPoolResizePeriodMs
void remoteReadyInsert(Fiber *fiber)
size_t maxFibersActiveLastPeriod_
void init(bool recordStackUsed)
ExecutionObserver * observer_
std::unique_ptr< AltStackBuffer > stack_
LoopController & loopController()
FiberTailQueue fibersPool_
void setExceptionCallback(ExceptionCallback ec)
bool alternateSignalStackRegistered_
folly::AtomicIntrusiveLinkedList< Fiber,&Fiber::nextRemoteReady_ > remoteReadyQueue_
FiberManager & operator=(const FiberManager &)=delete
FOLLY_EXPORT static FOLLY_ALWAYS_INLINE T & get()
FibersPoolResizer fibersPoolResizer_
__attribute__((noinline, noclone)) VirtualBase *makeVirtual()
void setObserver(ExecutionObserver *observer)
ExceptionCallback exceptionCallback_
size_t stackHighWatermark() const
folly::AtomicIntrusiveLinkedList< RemoteTask,&RemoteTask::nextRemoteTask > remoteTaskQueue_
FiberManager(const FiberManager &)=delete
ThreadPoolListHook * addr
ExecutionObserver * getObserver()
size_t fibersPoolSize() const