Commit 602fdec0 authored by Florian Schmaus's avatar Florian Schmaus
Browse files

Ensure that the current fiber is recycled in discardAndResume()

We also put the currentFiber no longer into a thread local storage,
but into the currentContext. Using only a thread local storage would
yield wrong results in case a blocked context is resumed on another
worker thread.
parent 1a0ced03
......@@ -10,6 +10,8 @@
#include "Debug.hpp"
class Context;
class Dispatcher;
class Fiber;
extern "C" [[noreturn]] void switch_and_load_context(void** toTos);
// *Not* marked as 'noreturn' because save_and_switch_context does
......@@ -24,6 +26,8 @@ private:
static thread_local Context* currentContext;
const Fiber* currentFiber;
void* const tos;
// unsigned valgrindStackId;
......@@ -52,6 +56,20 @@ private:
context->mainFunction();
}
friend Dispatcher;
static void setCurrentFiber(const Fiber* fiber) {
assert(currentContext);
currentContext->currentFiber = fiber;
}
static const Fiber* getCurrentFiber() {
assert(currentContext);
return currentContext->currentFiber;
}
public:
// cppcheck-suppress noExplicitConstructor selfInitialization
Context(func_t mainFunction)
......
......@@ -5,6 +5,7 @@
#include "Runtime.hpp"
#include "Debug.hpp"
#include "Context.hpp"
#include "Dispatcher.hpp"
ContextManager::ContextManager(Runtime& runtime) : MemoryManager(runtime), runtime(runtime) {
auto newWorkerHook = [this]() {
......@@ -64,5 +65,12 @@ void ContextManager::discardAndResume(Context* context) {
LOGD("Freeing context " << contextToFree);
putFreeContext(contextToFree);
});
// Since we are going to discard this context, it will never reach
// the end of its dispatch loop, and hence we need to ensure that
// the fiber is recycled.
const Fiber* currentFiber = Dispatcher::getCurrentFiberPtr();
Dispatcher::recycle(currentFiber);
contextToFree->discardAndResume(context);
}
......@@ -6,8 +6,6 @@
#include "Runtime.hpp"
#include "Debug.hpp"
thread_local const Fiber* Dispatcher::currentFiber;
func_t Dispatcher::getDispatchLoop() {
return std::bind(&Dispatcher::dispatchLoop, this);
}
......
#pragma once
#include "Common.hpp"
#include "Context.hpp"
#include "Fiber.hpp"
#include "Debug.hpp"
......@@ -9,8 +10,6 @@ class ContextManager;
class Dispatcher : public Logger<LogSubsystem::DISP> {
protected:
static thread_local const Fiber* currentFiber;
Runtime& runtime;
virtual void dispatchLoop() = 0;
......@@ -19,7 +18,7 @@ protected:
inline void dispatch(const Fiber* fiber) {
LOGD("executing fiber " << fiber);
currentFiber = fiber;
Context::setCurrentFiber(fiber);
fiber->run();
}
......@@ -35,7 +34,7 @@ protected:
return fiber->doAtomicDecrRefCount();
}
inline void recycle(const Fiber* fiber) {
static inline void recycle(const Fiber* fiber) {
delete fiber;
}
......@@ -52,12 +51,11 @@ public:
}
static const Fiber* getCurrentFiberPtr() {
assert(currentFiber);
return currentFiber;
return Context::getCurrentFiber();
}
static bool isDispatchedControlFlow() {
return currentFiber != nullptr;
return getCurrentFiberPtr() != nullptr;
}
friend ContextManager;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment