Lely core libraries
2.3.4
|
Go to the documentation of this file.
26 #ifdef _FORTIFY_SOURCE
27 #undef _FORTIFY_SOURCE
44 #if !_WIN32 && !defined(__NEWLIB__)
51 #elif _POSIX_MAPPED_FILES
56 #if !_WIN32 && LELY_HAVE_VALGRIND
57 #include <valgrind/valgrind.h>
60 #ifndef LELY_FIBER_MINSTKSZ
63 #define LELY_FIBER_MINSTKSZ MINSIGSTKSZ
64 #elif __WORDSIZE == 64
65 #define LELY_FIBER_MINSTKSZ 8192
67 #define LELY_FIBER_MINSTKSZ 4096
71 #ifndef LELY_FIBER_STKSZ
72 #define LELY_FIBER_STKSZ 131072
76 #if !_WIN32 && _POSIX_MAPPED_FILES && defined(MAP_ANONYMOUS)
82 static long page_size;
99 static void *guard_mmap(
void *addr,
size_t len,
int prot);
107 static void guard_munmap(
void *addr,
size_t len);
109 #endif // !_WIN32 && _POSIX_MAPPED_FILES && defined(MAP_ANONYMOUS)
112 #if _POSIX_C_SOURCE >= 200112L && (!defined(__NEWLIB__) || defined(__CYGWIN__))
117 static inline void sigjmpto(sigjmp_buf from, sigjmp_buf to,
int savemask);
123 static inline void jmpto(jmp_buf from, jmp_buf to);
147 #if _POSIX_MAPPED_FILES && defined(MAP_ANONYMOUS)
156 #if LELY_HAVE_VALGRIND
160 #if _POSIX_C_SOURCE >= 200112L && (!defined(__NEWLIB__) || defined(__CYGWIN__))
170 #define FIBER_ALIGNOF _Alignof(max_align_t)
171 #define FIBER_SIZEOF ALIGN(sizeof(fiber_t), FIBER_ALIGNOF)
226 dwFlags |= FIBER_FLAG_FLOAT_SWITCH;
227 assert(!thr->
main.lpFiber);
228 thr->
main.lpFiber = ConvertThreadToFiberEx(NULL, dwFlags);
229 if (!thr->
main.lpFiber)
251 assert(thr->
main.lpFiber);
252 ConvertFiberToThread();
253 thr->
main.lpFiber = NULL;
266 #if !_WIN32 && _POSIX_MAPPED_FILES && defined(MAP_ANONYMOUS)
275 data_size =
ALIGN(data_size, FIBER_ALIGNOF);
281 stack_size =
ALIGN(stack_size, FIBER_ALIGNOF);
283 size_t size = FIBER_SIZEOF + data_size;
285 #if _POSIX_MAPPED_FILES && defined(MAP_ANONYMOUS)
298 goto error_malloc_fiber;
316 #if _POSIX_MAPPED_FILES && defined(MAP_ANONYMOUS)
317 fiber->stack_size = 0;
318 fiber->stack_addr = NULL;
324 fiber->stack_size = stack_size;
325 fiber->stack_addr = guard_mmap(NULL,
fiber->stack_size,
326 PROT_READ | PROT_WRITE);
327 if (!
fiber->stack_addr) {
329 goto error_create_stack;
331 sp =
fiber->stack_addr;
335 #
if LELY_HAVE_VALGRIND
337 fiber->id = VALGRIND_STACK_REGISTER(sp, (
char *)sp + stack_size);
345 dwFlags |= FIBER_FLAG_FLOAT_SWITCH;
346 fiber->lpFiber = CreateFiberEx(
348 if (!
fiber->lpFiber) {
350 goto error_CreateFiberEx;
353 #if _POSIX_C_SOURCE >= 200112L && (!defined(__NEWLIB__) || defined(__CYGWIN__))
356 fiber, sp, stack_size) == -1) {
379 #if LELY_HAVE_VALGRIND
380 VALGRIND_STACK_DEREGISTER(
fiber->id);
382 #if _POSIX_MAPPED_FILES && defined(MAP_ANONYMOUS)
384 if (
fiber->stack_addr)
385 guard_munmap(
fiber->stack_addr,
fiber->stack_size);
401 DeleteFiber(
fiber->lpFiber);
403 #if LELY_HAVE_VALGRIND
404 VALGRIND_STACK_DEREGISTER(
fiber->id);
406 #if _POSIX_MAPPED_FILES && defined(MAP_ANONYMOUS)
407 if (
fiber->stack_addr)
408 guard_munmap(
fiber->stack_addr,
fiber->stack_size);
460 dwErrCode = GetLastError();
472 #if !_WIN32 && !defined(__NEWLIB__)
484 SwitchToFiber(to->lpFiber);
485 #elif _POSIX_C_SOURCE >= 200112L \
486 && (!defined(__NEWLIB__) || defined(__CYGWIN__))
497 #if !_WIN32 && !defined(__NEWLIB__)
506 SetLastError(dwErrCode);
525 #if !_WIN32 && _POSIX_MAPPED_FILES && defined(MAP_ANONYMOUS)
528 guard_mmap(
void *addr,
size_t len,
int prot)
531 page_size = sysconf(_SC_PAGE_SIZE);
532 assert(page_size > 0);
537 addr = (
char *)addr - page_size;
540 len =
ALIGN(len, page_size);
546 addr = mmap(addr, len + 2 * page_size, prot,
547 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
548 if (addr == MAP_FAILED) {
552 addr = (
char *)addr + page_size;
555 if (mprotect((
char *)addr - page_size, page_size, PROT_NONE) == -1) {
560 if (mprotect((
char *)addr + len, page_size, PROT_NONE) == -1) {
568 munmap((
char *)addr - page_size, len + 2 * page_size);
575 guard_munmap(
void *addr,
size_t len)
578 assert(page_size > 0);
581 len =
ALIGN(len, page_size);
583 munmap((
char *)addr - page_size, len + 2 * page_size);
587 #endif // _POSIX_MAPPED_FILES && MAP_ANONYMOUS
590 #if _POSIX_C_SOURCE >= 200112L && (!defined(__NEWLIB__) || defined(__CYGWIN__))
592 sigjmpto(sigjmp_buf from, sigjmp_buf to,
int savemask)
594 if (!sigsetjmp(from, savemask))
599 jmpto(jmp_buf from, jmp_buf to)
637 #endif // !LELY_NO_MALLOC
#define FIBER_SAVE_ALL
A combination of those flags in FIBER_SAVE_MASK, FIBER_SAVE_FENV and FIBER_SAVE_ERROR that are suppor...
#define LELY_FIBER_STKSZ
The default size (in bytes) of a fiber stack frame.
fiber_t * curr
A pointer to the fiber currently running on this thread.
void fiber_thrd_fini(void)
Finalizes the fiber associated with the calling thread.
int get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function.
int errno2c(int errnum)
Transforms a standard C error number to a native error code.
int flags
The flags provided to fiber_create().
A thread-local struct containing the fiber associated with the thread and a pointer to the fiber curr...
int fiber_thrd_init(int flags)
Initializes the fiber associated with the calling thread.
#define FIBER_SAVE_MASK
A flag specifying a fiber to save and restore the signal mask (only supported on POSIX platforms).
struct fiber_thrd * thr
A pointer to the thread that resumed this fiber.
size_t refcnt
The reference counter tracking the number of calls to fiber_thrd_init() minus those to fiber_thrd_fin...
#define _Noreturn
A function declared with a _Noreturn function specifier SHALL not return to its caller.
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...
void set_errnum(errnum_t errnum)
Sets the current (thread-specific) platform-independent error number to errnum.
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
sigjmp_buf env
The saved registers and signal mask.
#define ALIGN(x, a)
Rounds x up to the nearest multiple of a.
#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_func_t(fiber_t *fiber, void *arg)
The type of the function executed by a fiber.
@ ERRNUM_INVAL
Invalid argument.
static void sigjmpto(sigjmp_buf from, sigjmp_buf to, int savemask)
Saves the from calling environment with sigsetjmp(from, savemask) and restores the to calling environ...
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().
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 FIBER_SAVE_FENV
A flag specifying a fiber to save and restore the floating-point environment.
fiber_t * from
A pointer to the now suspended fiber that resumed this fiber.
void fiber_destroy(fiber_t *fiber)
Destroys the specified fiber.
static _Noreturn void fiber_start(void *arg)
The function running in a fiber.
fiber_func_t * func
A pointer to the function to be executed in the fiber.
void * arg
The second argument supplied to func.
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 FIBER_SAVE_ERROR
A flag specifying a fiber to save and restore the error values (i.e., errno and GetLastError() on Win...
#define _Thread_local
An object whose identifier is declared with the storage-class specifier _Thread_local has thread stor...
fiber_t main
The fiber representing this thread.
#define powerof2(x)
Returns 1 if x is a power of two, and 0 otherwise.
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 LELY_FIBER_MINSTKSZ
The minimum size (in bytes) of a fiber stack frame.
fiber_t * fiber_resume(fiber_t *fiber)
Equivalent to fiber_resume_with(fiber, NULL, NULL).
void * data
A pointer to the data region.