/*
- * Copyright 2016 Facebook, Inc.
+ * Copyright 2017 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
namespace {
inline FiberManager::Options preprocessOptions(FiberManager::Options opts) {
-#ifdef FOLLY_SANITIZE_ADDRESS
- /* ASAN needs a lot of extra stack space.
+#if defined(FOLLY_SANITIZE_ADDRESS) || defined(UNDEFINED_SANITIZER)
+ /* ASAN/UBSAN needs a lot of extra stack space.
16x is a conservative estimate, 8x also worked with tests
where it mattered. Note that overallocating here does not necessarily
increase RSS, since unused memory is pretty much free. */
loopController_->schedule();
}
-inline intptr_t FiberManager::activateFiber(Fiber* fiber) {
+inline void FiberManager::activateFiber(Fiber* fiber) {
DCHECK_EQ(activeFiber_, (Fiber*)nullptr);
#ifdef FOLLY_SANITIZE_ADDRESS
- registerFiberActivationWithAsan(fiber);
+ DCHECK(!fiber->asanMainStackBase_);
+ DCHECK(!fiber->asanMainStackSize_);
+ auto stack = fiber->getStack();
+ void* asanFakeStack;
+ registerStartSwitchStackWithAsan(&asanFakeStack, stack.first, stack.second);
+ SCOPE_EXIT {
+ registerFinishSwitchStackWithAsan(asanFakeStack, nullptr, nullptr);
+ fiber->asanMainStackBase_ = nullptr;
+ fiber->asanMainStackSize_ = 0;
+ };
#endif
activeFiber_ = fiber;
- return jumpContext(&mainContext_, &fiber->fcontext_, fiber->data_);
+ fiber->fiberImpl_.activate();
}
-inline intptr_t FiberManager::deactivateFiber(Fiber* fiber) {
+inline void FiberManager::deactivateFiber(Fiber* fiber) {
DCHECK_EQ(activeFiber_, fiber);
#ifdef FOLLY_SANITIZE_ADDRESS
- registerFiberDeactivationWithAsan(fiber);
+ DCHECK(fiber->asanMainStackBase_);
+ DCHECK(fiber->asanMainStackSize_);
+
+ registerStartSwitchStackWithAsan(
+ &fiber->asanFakeStack_,
+ fiber->asanMainStackBase_,
+ fiber->asanMainStackSize_);
+ SCOPE_EXIT {
+ registerFinishSwitchStackWithAsan(
+ fiber->asanFakeStack_,
+ &fiber->asanMainStackBase_,
+ &fiber->asanMainStackSize_);
+ fiber->asanFakeStack_ = nullptr;
+ };
#endif
activeFiber_ = nullptr;
- return jumpContext(&fiber->fcontext_, &mainContext_, 0);
+ fiber->fiberImpl_.deactivate();
}
inline void FiberManager::runReadyFiber(Fiber* fiber) {
}
}
-inline bool FiberManager::loopUntilNoReady() {
+inline void FiberManager::loopUntilNoReady() {
+ return loopController_->runLoop();
+}
+
+inline void FiberManager::loopUntilNoReadyImpl() {
#ifndef _WIN32
if (UNLIKELY(!alternateSignalStackRegistered_)) {
registerAlternateSignalStack();
fiber->rcontext_ = std::move(task->rcontext);
fiber->setFunction(std::move(task->func));
- fiber->data_ = reinterpret_cast<intptr_t>(fiber);
if (observer_) {
observer_->runnable(reinterpret_cast<uintptr_t>(fiber));
}
}
}
readyFibers_.splice(readyFibers_.end(), yieldedFibers_);
-
- return fibersActive_ > 0;
}
// We need this to be in a struct, not inlined in addTask, because clang crashes
fiber->setFunction(std::ref(*funcLoc));
}
- fiber->data_ = reinterpret_cast<intptr_t>(fiber);
readyFibers_.push_back(*fiber);
if (observer_) {
observer_->runnable(reinterpret_cast<uintptr_t>(fiber));
fiber->setFunctionFinally(std::ref(*funcLoc), std::ref(*finallyLoc));
}
- fiber->data_ = reinterpret_cast<intptr_t>(fiber);
readyFibers_.push_back(*fiber);
if (observer_) {
observer_->runnable(reinterpret_cast<uintptr_t>(fiber));