25 #ifdef _FORTIFY_SOURCE 26 #undef _FORTIFY_SOURCE 45 #if _POSIX_MAPPED_FILES 50 #if LELY_HAVE_VALGRIND 51 #include <valgrind/valgrind.h> 54 #if _POSIX_MAPPED_FILES && defined(MAP_ANONYMOUS) 55 #ifndef LELY_FIBER_MMAPSZ 60 #define LELY_FIBER_MMAPSZ 131072 73 #if _POSIX_MAPPED_FILES && defined(MAP_ANONYMOUS) 77 #if LELY_HAVE_VALGRIND 80 #if _POSIX_C_SOURCE >= 200112L && (!defined(__NEWLIB__) || defined(__CYGWIN__)) 91 #define FIBER_SIZE ALIGN(sizeof(fiber_t), _Alignof(max_align_t)) 103 static _Noreturn void fiber_start(
void *arg);
122 assert(!thr->main.thr);
123 assert(!thr->main.from);
126 thr->main.flags = flags;
129 thr->curr = &thr->main;
140 if (!--thr->refcnt) {
141 assert(thr->curr == &thr->main);
145 thr->main.from = NULL;
146 thr->main.thr = NULL;
155 #if _POSIX_MAPPED_FILES && defined(MAP_ANONYMOUS) 171 size_t size = FIBER_SIZE + data_size;
172 #if _POSIX_MAPPED_FILES && defined(MAP_ANONYMOUS) 175 >= LELY_FIBER_MMAPSZ;
183 #if _POSIX_MAPPED_FILES && defined(MAP_ANONYMOUS) 185 fiber = malloc(size);
188 fiber = malloc(size + stack_size);
192 goto error_malloc_fiber;
197 fiber->flags = flags;
199 fiber->data = (
char *)fiber + FIBER_SIZE;
205 #if _POSIX_MAPPED_FILES && defined(MAP_ANONYMOUS) 209 long page_size = sysconf(_SC_PAGE_SIZE);
210 assert(page_size > 0);
212 stack_size =
ALIGN(stack_size, page_size);
214 fiber->size = stack_size;
220 fiber->size += 2 * page_size;
222 fiber->sp = mmap(NULL, fiber->size,
223 PROT_READ | PROT_WRITE | PROT_EXEC,
224 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
225 if (fiber->sp == MAP_FAILED)
226 fiber->sp = mmap(NULL, fiber->size,
227 PROT_READ | PROT_WRITE,
228 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
229 if (fiber->sp == MAP_FAILED) {
237 sp = (
char *)sp + page_size;
239 if (mprotect((
char *)sp - page_size, page_size,
246 if (mprotect((
char *)sp + stack_size, page_size,
254 #endif // _POSIX_MAPPED_FILES && MAP_ANONYMOUS 255 sp = (
char *)fiber + size;
257 #if LELY_HAVE_VALGRIND 258 fiber->id = VALGRIND_STACK_REGISTER(sp, (
char *)sp + stack_size);
261 #if _POSIX_C_SOURCE >= 200112L && (!defined(__NEWLIB__) || defined(__CYGWIN__)) 264 fiber, sp, stack_size) == -1) {
267 if (
mkjmp(fiber->env, &fiber_start, fiber, sp, stack_size) == -1) {
283 #if LELY_HAVE_VALGRIND 284 VALGRIND_STACK_DEREGISTER(fiber->id);
286 #if _POSIX_MAPPED_FILES && defined(MAP_ANONYMOUS) 289 munmap(fiber->sp, fiber->size);
301 if (fiber && fiber->data) {
302 #if LELY_HAVE_VALGRIND 303 VALGRIND_STACK_DEREGISTER(fiber->id);
305 #if _POSIX_MAPPED_FILES && defined(MAP_ANONYMOUS) 307 munmap(fiber->sp, fiber->size);
318 return fiber ? fiber->data :
fiber_thrd.curr->data;
327 if (fiber == fiber->thr->curr)
328 return fiber->from = fiber;
330 return fiber_switch(fiber);
339 if (fiber == fiber->thr->curr)
340 return fiber->from = func ? func(fiber, arg) : fiber;
345 return fiber_switch(fiber);
349 fiber_start(
void *arg)
368 void *arg = fiber->arg;
370 fiber = func(fiber, arg);
374 fiber = func(fiber, arg);
393 assert(fiber != curr);
400 fegetenv(&curr->fenv);
403 #if _POSIX_C_SOURCE >= 200112L && (!defined(__NEWLIB__) || defined(__CYGWIN__)) 406 if (!setjmp(curr->env)) {
408 fiber->from = thr->curr;
410 #if _POSIX_C_SOURCE >= 200112L && (!defined(__NEWLIB__) || defined(__CYGWIN__)) 411 siglongjmp(fiber->env, 1);
413 longjmp(fiber->env, 1);
420 fesetenv(&curr->fenv);
429 void *arg = curr->arg;
431 curr->from = func(curr->from, arg);
#define LELY_FIBER_STKSZ
The default size (in bytes) of a fiber stack frame.
This header file is part of the utilities library; it contains the fiber declarations.
#define powerof2(x)
Returns 1 if x is a power of two, and 0 otherwise.
This header file is part of the utilities library; it contains the mkjmp() and sigmkjmp() function de...
#define _Alignof(x)
Specifies the alignment requirement of the declared object or member.
#define FIBER_SAVE_ALL
A combination of those flags in FIBER_SAVE_MASK, FIBER_SAVE_FENV and FIBER_SAVE_ERROR that are suppor...
void fiber_destroy(fiber_t *fiber)
Destroys the specified fiber.
int mkjmp(jmp_buf env, void(*func)(void *), void *arg, void *sp, size_t size)
Creates and stores a calling environment with a user-provided stack suitable for use by longjmp()...
int sigmkjmp(sigjmp_buf env, int savemask, void(*func)(void *), void *arg, void *sp, size_t size)
Creates and stores a calling environment with a user-provided stack suitable for use by siglongjmp()...
fiber_t * fiber_resume_with(fiber_t *fiber, fiber_func_t *func, void *arg)
Suspends the calling fiber and resumes the specified fiber, optionally executing a function before re...
This header file is part of the utilities library; it contains the native and platform-independent er...
#define FIBER_SAVE_FENV
A flag specifying a fiber to save and restore the floating-point environment.
#define FIBER_GUARD_STACK
A flag specifying a fiber to add a guard page when allocating the stack frame so that the kernel gene...
An object type whose alignment is as great as is supported by the implementation in all contexts...
This header file is part of the C11 and POSIX compatibility library; it includes <unistd.h>, if it exists, and defines any missing functionality.
#define LELY_FIBER_MINSTKSZ
The minimum size (in bytes) of a fiber stack frame.
This header file is part of the C11 and POSIX compatibility library; it includes <stddef.h> and defines any missing functionality.
#define ALIGN(x, a)
Rounds x up to the nearest multiple of a.
fiber_t * fiber_resume(fiber_t *fiber)
Equivalent to fiber_resume_with(fiber, NULL, NULL).
fiber_t * fiber_func_t(fiber_t *fiber, void *arg)
The type of the function executed by a fiber.
int fiber_thrd_init(int flags)
Initializes the fiber associated with the calling thread.
void * fiber_data(const fiber_t *fiber)
Returns a pointer to the data region of the specified fiber, or of the calling fiber if fiber is NULL...
#define _Thread_local
An object whose identifier is declared with the storage-class specifier _Thread_local has thread stor...
void fiber_thrd_fini(void)
Finalizes the fiber associated with the calling thread.
#define FIBER_SAVE_ERROR
A flag specifying a fiber to save and restore the error values (i.e., errno and GetLastError() on Win...
#define FIBER_SAVE_MASK
A flag specifying a fiber to save and restore the signal mask (only supported on POSIX platforms)...
This header file is part of the C11 and POSIX compatibility library; it includes <stdlib.h> and defines any missing functionality.
#define _Noreturn
A function declared with a _Noreturn function specifier SHALL not return to its caller.
fiber_t * fiber_create(fiber_func_t *func, void *arg, int flags, size_t data_size, size_t stack_size)
Creates a new fiber, allocates a stack and sets up a calling environment to begin executing the speci...