Lely core libraries
2.2.5
|
Go to the documentation of this file.
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;
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;
223 PROT_READ | PROT_WRITE | PROT_EXEC,
224 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
225 if (
fiber->sp == MAP_FAILED)
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) {
283 #if LELY_HAVE_VALGRIND
284 VALGRIND_STACK_DEREGISTER(
fiber->id);
286 #if _POSIX_MAPPED_FILES && defined(MAP_ANONYMOUS)
302 #if LELY_HAVE_VALGRIND
303 VALGRIND_STACK_DEREGISTER(
fiber->id);
305 #if _POSIX_MAPPED_FILES && defined(MAP_ANONYMOUS)
330 return fiber_switch(
fiber);
345 return fiber_switch(
fiber);
349 fiber_start(
void *arg)
368 void *arg =
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);
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...
int fiber_thrd_init(int flags)
Initializes the fiber associated with the calling thread.
#define LELY_FIBER_STKSZ
The default size (in bytes) of a fiber stack frame.
#define FIBER_SAVE_MASK
A flag specifying a fiber to save and restore the signal mask (only supported on POSIX platforms).
#define LELY_FIBER_MINSTKSZ
The minimum size (in bytes) of a fiber stack frame.
void fiber_destroy(fiber_t *fiber)
Destroys the specified fiber.
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 _Noreturn
A function declared with a _Noreturn function specifier SHALL not return to its caller.
#define FIBER_GUARD_STACK
A flag specifying a fiber to add a guard page when allocating the stack frame so that the kernel gene...
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...
#define FIBER_SAVE_ERROR
A flag specifying a fiber to save and restore the error values (i.e., errno and GetLastError() on Win...
#define ALIGN(x, a)
Rounds x up to the nearest multiple of a.
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().
An object type whose alignment is as great as is supported by the implementation in all contexts.
fiber_t * fiber_func_t(fiber_t *fiber, void *arg)
The type of the function executed by a fiber.
fiber_t * fiber_resume(fiber_t *fiber)
Equivalent to fiber_resume_with(fiber, NULL, NULL).
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().
#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 powerof2(x)
Returns 1 if x is a power of two, and 0 otherwise.
#define FIBER_SAVE_ALL
A combination of those flags in FIBER_SAVE_MASK, FIBER_SAVE_FENV and FIBER_SAVE_ERROR that are suppor...
#define _Alignof(x)
Specifies the alignment requirement of the declared object or member.
#define FIBER_SAVE_FENV
A flag specifying a fiber to save and restore the floating-point environment.