13 # define _XOPEN_SOURCE
62 }
catch(std::bad_alloc
const&) {
73 if((res = context->create())) {
81 if(
likely(attr.stackSize > 0)) {
82 #ifdef ZTH_CONTEXT_WINFIBER
87 context, stack.
p, stack.
p + stack.
size - 1u);
121 #ifdef ZTH_ENABLE_ASAN
123 void* fake_stack =
nullptr;
124 __sanitizer_start_switch_fiber(
125 from->alive() ? &fake_stack :
nullptr, to->stackUsable().p, to->stackUsable().size);
129 from->context_switch(*to);
131 #ifdef ZTH_ENABLE_ASAN
132 __sanitizer_finish_switch_fiber(fake_stack,
nullptr,
nullptr);
149 void*
guard =
nullptr;
151 if(f && f->
context() == context) {
154 guard = context->stackGuard(
nullptr);
160 context->stackGuard(
guard);
180 #ifdef ZTH_ENABLE_ASAN
181 __sanitizer_finish_switch_fiber(
nullptr,
nullptr,
nullptr);
188 context->stackGuard();
192 context->attr().entry(context->attr().arg);
201 zth_abort(
"Returned to finished context");
211 #define ZTH_STACK_WATERMARKER ((uint64_t)0x5a7468574de2889eULL)
220 static void stack_watermark_align(
void*& stack,
size_t*& sizeptr,
size_t* size =
nullptr) noexcept
225 uintptr_t stack_ =
reinterpret_cast<uintptr_t
>(stack);
228 stack_ = ((uintptr_t)stack_ +
sizeof(
size_t) - 1) & ~(uintptr_t)(
sizeof(size_t) - 1);
230 sizeptr =
reinterpret_cast<size_t*
>(stack_);
233 stack_ +=
sizeof(size_t);
236 *size -= stack_ -
reinterpret_cast<uintptr_t
>(stack);
238 stack =
reinterpret_cast<void*
>(stack_);
253 size_t* sizeptr =
nullptr;
254 stack_watermark_align(stack, sizeptr, &size);
257 for(
size_t i = 0; i *
sizeof(uint64_t) <= size -
sizeof(uint64_t); i++)
272 size_t* sizeptr =
nullptr;
273 stack_watermark_align(stack, sizeptr);
288 size_t* sizeptr =
nullptr;
289 stack_watermark_align(stack, sizeptr);
290 size_t size = *sizeptr;
294 #ifdef ZTH_USE_VALGRIND
295 VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE(stack, size);
298 for(uint64_t* s =
static_cast<uint64_t*
>(stack);
302 #ifdef ZTH_USE_VALGRIND
303 VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE(stack, size);
306 return size - unused *
sizeof(uint64_t);
322 #ifdef ZTH_STACK_SWITCH
323 void*
zth_stack_switch(
void* stack,
size_t size,
void* (*f)(
void*) noexcept,
void* arg) noexcept
static int init() noexcept
static void deinit() noexcept
Context * context() const noexcept
static safe_ptr< singleton_type >::type instance() noexcept
Return the only instance of T within this thread.
The class that manages the fibers within this thread.
Fiber * currentFiber() const noexcept
static bool stackGrowsDown(void const *reference)
Checks if the stack grows down or up.
void * stack_switch(void *stack, size_t size, void *(*f)(void *) noexcept, void *arg) noexcept
Context switch mechanism implementation.
#define ZTH_STACK_WATERMARKER
void context_entry(zth::Context *context) noexcept
Entry point of the fiber.
#define zth_stack_switch(stack, size, f, arg)
Call the function f using the new stack pointer.
void zth_abort(char const *fmt,...)
Aborts the process after printing the given printf() formatted message.
Worker & currentWorker() noexcept
Return the (thread-local) singleton Worker instance.
void yield(Fiber *preferFiber=nullptr, bool alwaysYield=false, Timestamp const &now=Timestamp::now())
Allow a context switch.
fiber_type< F >::factory fiber(F f, char const *name=nullptr)
Create a new fiber.
constexpr auto guard(T &&g, char const *name=nullptr)
Create a guard from a function.
size_t stack_watermark_remaining(void *stack) noexcept
Return the remaining stack size that was never touched.
void stack_watermark_init(void *stack, size_t size) noexcept
Initialize the memory region for stack high water marking.
size_t stack_watermark_maxused(void *stack) noexcept
Return the high water mark of the stack.
size_t stack_watermark_size(void *stack) noexcept
Return the size of the given stack region.
#define zth_dbg(group, fmt, a...)
Debug printf()-like function.
void context_switch(Context *from, Context *to) noexcept
Perform context switch.
void context_destroy(Context *context) noexcept
Destroy and cleanup a context.
int context_init() noexcept
One-time context mechanism initialization.
string err(int e)
Return a string like strerror() does, but as a zth::string.
void context_deinit() noexcept
Final cleanup.
int context_create(Context *&context, ContextAttr const &attr) noexcept
Create a context.
size_t context_stack_usage(Context *context) noexcept
Return the high water mark of the stack of the given context.
static bool const EnableStackWaterMark
When true, enable stack watermark to detect maximum stack usage.
#define zth_assert(expr)
assert(), but better integrated in Zth.
#define likely(expr)
Marks the given expression to likely be evaluated to true.