X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2Ffibers%2FFiber.cpp;h=afc05200a878ee6b34ef491eb87721b29724eae4;hb=f885995c00a27e0e440c0e5cb66ec3298fc507d4;hp=afb72c07d386fb90bd08c0e274b0c4d4598e0f2a;hpb=c93226d1035504e84e4015593dd8449503c02a2e;p=folly.git diff --git a/folly/fibers/Fiber.cpp b/folly/fibers/Fiber.cpp index afb72c07..afc05200 100644 --- a/folly/fibers/Fiber.cpp +++ b/folly/fibers/Fiber.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -22,7 +22,6 @@ #include #include -#include #include #include #include @@ -38,9 +37,11 @@ std::thread::id localThreadId() { } /* Size of the region from p + nBytes down to the last non-magic value */ -static size_t nonMagicInBytes(const FContext& context) { - uint64_t* begin = static_cast(context.stackLimit()); - uint64_t* end = static_cast(context.stackBase()); +static size_t nonMagicInBytes(unsigned char* stackLimit, size_t stackSize) { + CHECK_EQ(reinterpret_cast(stackLimit) % sizeof(uint64_t), 0u); + CHECK_EQ(stackSize % sizeof(uint64_t), 0u); + uint64_t* begin = reinterpret_cast(stackLimit); + uint64_t* end = reinterpret_cast(stackLimit + stackSize); auto firstNonMagic = std::find_if( begin, end, [](uint64_t val) { return val != kMagic8Bytes; }); @@ -48,11 +49,10 @@ static size_t nonMagicInBytes(const FContext& context) { return (end - firstNonMagic) * sizeof(uint64_t); } -} // anonymous namespace +} // namespace -void Fiber::setData(intptr_t data) { +void Fiber::resume() { DCHECK_EQ(state_, AWAITING); - data_ = data; state_ = READY_TO_RUN; if (fiberManager_.observer_) { @@ -67,12 +67,11 @@ void Fiber::setData(intptr_t data) { } } -Fiber::Fiber(FiberManager& fiberManager) : fiberManager_(fiberManager) { - auto size = fiberManager_.options_.stackSize; - auto limit = fiberManager_.stackAllocator_.allocate(size); - - fcontext_ = makeContext(limit, size, &Fiber::fiberFuncHelper); - +Fiber::Fiber(FiberManager& fiberManager) + : fiberManager_(fiberManager), + fiberStackSize_(fiberManager_.options_.stackSize), + fiberStackLimit_(fiberManager_.stackAllocator_.allocate(fiberStackSize_)), + fiberImpl_([this] { fiberFunc(); }, fiberStackLimit_, fiberStackSize_) { fiberManager_.allFibers_.push_back(*this); } @@ -82,20 +81,20 @@ void Fiber::init(bool recordStackUsed) { #ifndef FOLLY_SANITIZE_ADDRESS recordStackUsed_ = recordStackUsed; if (UNLIKELY(recordStackUsed_ && !stackFilledWithMagic_)) { - auto limit = fcontext_.stackLimit(); - auto base = fcontext_.stackBase(); - + CHECK_EQ( + reinterpret_cast(fiberStackLimit_) % sizeof(uint64_t), 0u); + CHECK_EQ(fiberStackSize_ % sizeof(uint64_t), 0u); std::fill( - static_cast(limit), - static_cast(base), + reinterpret_cast(fiberStackLimit_), + reinterpret_cast(fiberStackLimit_ + fiberStackSize_), kMagic8Bytes); + stackFilledWithMagic_ = true; + // newer versions of boost allocate context on fiber stack, // need to create a new one - auto size = fiberManager_.options_.stackSize; - fcontext_ = makeContext(limit, size, &Fiber::fiberFuncHelper); - - stackFilledWithMagic_ = true; + fiberImpl_ = + FiberImpl([this] { fiberFunc(); }, fiberStackLimit_, fiberStackSize_); } #else (void)recordStackUsed; @@ -104,28 +103,30 @@ void Fiber::init(bool recordStackUsed) { Fiber::~Fiber() { #ifdef FOLLY_SANITIZE_ADDRESS + if (asanFakeStack_ != nullptr) { + fiberManager_.freeFakeStack(asanFakeStack_); + } fiberManager_.unpoisonFiberStack(this); #endif - fiberManager_.stackAllocator_.deallocate( - static_cast(fcontext_.stackLimit()), - fiberManager_.options_.stackSize); + fiberManager_.stackAllocator_.deallocate(fiberStackLimit_, fiberStackSize_); } void Fiber::recordStackPosition() { int stackDummy; auto currentPosition = static_cast( - static_cast(fcontext_.stackBase()) - + fiberStackLimit_ + fiberStackSize_ - static_cast(static_cast(&stackDummy))); fiberManager_.stackHighWatermark_ = std::max(fiberManager_.stackHighWatermark_, currentPosition); VLOG(4) << "Stack usage: " << currentPosition; } -void Fiber::fiberFuncHelper(intptr_t fiber) { - reinterpret_cast(fiber)->fiberFunc(); -} +[[noreturn]] void Fiber::fiberFunc() { +#ifdef FOLLY_SANITIZE_ADDRESS + fiberManager_.registerFinishSwitchStackWithAsan( + nullptr, &asanMainStackBase_, &asanMainStackSize_); +#endif -void Fiber::fiberFunc() { while (true) { DCHECK_EQ(state_, NOT_STARTED); @@ -149,7 +150,8 @@ void Fiber::fiberFunc() { if (UNLIKELY(recordStackUsed_)) { fiberManager_.stackHighWatermark_ = std::max( - fiberManager_.stackHighWatermark_, nonMagicInBytes(fcontext_)); + fiberManager_.stackHighWatermark_, + nonMagicInBytes(fiberStackLimit_, fiberStackSize_)); VLOG(3) << "Max stack usage: " << fiberManager_.stackHighWatermark_; CHECK( fiberManager_.stackHighWatermark_ < @@ -159,15 +161,11 @@ void Fiber::fiberFunc() { state_ = INVALID; - auto context = fiberManager_.deactivateFiber(this); - - DCHECK_EQ(reinterpret_cast(context), this); + fiberManager_.deactivateFiber(this); } } -intptr_t Fiber::preempt(State state) { - intptr_t ret; - +void Fiber::preempt(State state) { auto preemptImpl = [&]() mutable { DCHECK_EQ(fiberManager_.activeFiber_, this); DCHECK_EQ(state_, RUNNING); @@ -177,7 +175,7 @@ intptr_t Fiber::preempt(State state) { recordStackPosition(); - ret = fiberManager_.deactivateFiber(this); + fiberManager_.deactivateFiber(this); DCHECK_EQ(fiberManager_.activeFiber_, this); DCHECK_EQ(state_, READY_TO_RUN); @@ -189,8 +187,10 @@ intptr_t Fiber::preempt(State state) { } else { preemptImpl(); } +} - return ret; +Fiber::LocalData::~LocalData() { + reset(); } Fiber::LocalData::LocalData(const LocalData& other) : data_(nullptr) { @@ -235,5 +235,5 @@ void* Fiber::LocalData::allocateHeapBuffer(size_t size) { void Fiber::LocalData::freeHeapBuffer(void* buffer) { delete[] reinterpret_cast(buffer); } -} -} +} // namespace fibers +} // namespace folly