return threadId;
}
-static void fillMagic(const FContext& context) {
- uint64_t* begin = static_cast<uint64_t*>(context.stackLimit());
- uint64_t* end = static_cast<uint64_t*>(context.stackBase());
-
- std::fill(begin, end, kMagic8Bytes);
-}
-
/* 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<uint64_t*>(context.stackLimit());
auto limit = fiberManager_.stackAllocator_.allocate(size);
fcontext_ = makeContext(limit, size, &Fiber::fiberFuncHelper);
+}
+
+void Fiber::init(bool recordStackUsed) {
+ recordStackUsed_ = recordStackUsed;
+ if (UNLIKELY(recordStackUsed_ && !stackFilledWithMagic_)) {
+ auto limit = fcontext_.stackLimit();
+ auto base = fcontext_.stackBase();
+
+ std::fill(static_cast<uint64_t*>(limit),
+ static_cast<uint64_t*>(base),
+ kMagic8Bytes);
+
+ // 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);
- if (UNLIKELY(fiberManager_.options_.debugRecordStackUsed)) {
- fillMagic(fcontext_);
+ stackFilledWithMagic_ = true;
}
}
void Fiber::recordStackPosition() {
int stackDummy;
+ auto currentPosition = static_cast<size_t>(
+ static_cast<unsigned char*>(fcontext_.stackBase()) -
+ static_cast<unsigned char*>(static_cast<void*>(&stackDummy)));
fiberManager_.stackHighWatermark_ =
- std::max(fiberManager_.stackHighWatermark_,
- static_cast<size_t>(
- static_cast<unsigned char*>(fcontext_.stackBase()) -
- static_cast<unsigned char*>(
- static_cast<void*>(&stackDummy))));
+ std::max(fiberManager_.stackHighWatermark_, currentPosition);
+ VLOG(4) << "Stack usage: " << currentPosition;
}
void Fiber::fiberFuncHelper(intptr_t fiber) {
"running Fiber func_/resultFunc_");
}
- if (UNLIKELY(fiberManager_.options_.debugRecordStackUsed)) {
+ if (UNLIKELY(recordStackUsed_)) {
fiberManager_.stackHighWatermark_ =
std::max(fiberManager_.stackHighWatermark_,
nonMagicInBytes(fcontext_));
+ VLOG(3) << "Max stack usage: " << fiberManager_.stackHighWatermark_;
+ CHECK(fiberManager_.stackHighWatermark_ <
+ fiberManager_.options_.stackSize - 64) << "Fiber stack overflow";
}
state_ = INVALID;
friend class FiberManager;
explicit Fiber(FiberManager& fiberManager);
+ void init(bool recordStackUsed);
template <typename F>
void setFunction(F&& func);
FContext fcontext_; /**< current task execution context */
intptr_t data_; /**< Used to keep some data with the Fiber */
std::function<void()> func_; /**< task function */
+ bool recordStackUsed_{false};
+ bool stackFilledWithMagic_{false};
/**
* Points to next fiber in remote ready list
* This is fairly expensive: we fill each newly allocated stack
* with some known value and find the boundary of unused stack
* with linear search every time we surrender the stack back to fibersPool.
+ * 0 disables stack recording.
*/
- bool debugRecordStackUsed{false};
+ size_t recordStackEvery{0};
/**
* Keep at most this many free fibers in the pool.
/**
* return true if running activeFiber_ is not nullptr.
*/
- bool hasActiveFiber();
+ bool hasActiveFiber() const;
/**
* @return What was the most observed fiber stack usage (in bytes).
size_t fibersAllocated_{0}; /**< total number of fibers allocated */
size_t fibersPoolSize_{0}; /**< total number of fibers in the free pool */
size_t fibersActive_{0}; /**< number of running or blocked fibers */
+ size_t fiberId_{0}; /**< id of last fiber used */
FContext::ContextStruct mainContext_; /**< stores loop function context */