Select Git revision
cabal.project
-
Hans-Peter Deifel authoredHans-Peter Deifel authored
fibril.hpp 4.02 KiB
// SPDX-License-Identifier: LGPL-3.0-or-later
// Copyright © 2021 Florian Schmaus
#pragma once
// This is the combination of fibril.h and fibrile.h where fibril_fork
// uses lambda functions instead of inner C functions (which are a GCC
// extension and do not work with C++). Hence part of this is MIT
// licensed.
#ifdef __cplusplus
extern "C" {
#endif
#include "fibril/fibrili.h"
#define FIBRIL_SUCCESS 0
#define FIBRIL_FAILURE -1
/**
* These are special arguments to fibril_rt_init().
* FIBRIL_NPROCS tells the runtime to fetch the number of processors
* from the environment variable FIBRIL_NPROCS (getenv(FIBRIL_NPROCS)).
* FIBRIL_NPROCS_ONLN tells the runtime to use all available processors
* in the system (sysconf(_SC_NPROCESSORS_ONLN)).
*/
#define FIBRIL_NPROCS 0
#define FIBRIL_NPROCS_ONLN -1
/** fibril. */
#define fibril __attribute__((optimize("no-omit-frame-pointer")))
/** fibril_t. */
typedef struct _fibril_t fibril_t;
/** fibril_init. */
__attribute__((always_inline)) extern inline void fibril_init(fibril_t* frptr) {
register void* rbp asm("rbp");
register void* rsp asm("rsp");
frptr->lock = 0;
frptr->unmapped = 0;
frptr->count = -1;
// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.Assign)
frptr->stack.btm = rbp;
frptr->stack.top = rsp;
}
/** fibril_join. */
__attribute__((always_inline)) extern inline void fibril_join(fibril_t* frptr) {
if (frptr->count > -1) {
fibrili_membar(fibrili_join(frptr));
}
}
#include "fibril/fork.h"
/** _fibril_fork_nrt. */
#define fibril_fork_nrt(fp, fn, ag) \
do { \
auto _fibril_##fn##_fork = [](_fibril_defs ag fibril_t* f) \
__attribute__((noinline, hot, optimize(3))) { \
fibrili_push(f); \
fn(_fibril_args ag); \
if (!fibrili_pop()) fibrili_resume(f); \
}; \
fibrili_membar(_fibril_##fn##_fork(_fibril_expand ag fp)); \
} while (0)
/** _fibril_fork_wrt. */
#define fibril_fork_wrt(fp, rtp, fn, ag) \
do { \
auto _fibril_##fn##_fork = [](_fibril_defs ag fibril_t* f, __typeof__(rtp) p) \
__attribute__((noinline, hot, optimize(3))) { \
fibrili_push(f); \
*p = fn(_fibril_args ag); \
if (!fibrili_pop()) fibrili_resume(f); \
}; \
fibrili_membar(_fibril_##fn##_fork(_fibril_expand ag fp, rtp)); \
} while (0)
extern int fibril_rt_init(int nprocs);
extern int fibril_rt_exit();
extern int fibril_rt_nprocs();
/** fibril_fork has two versions: one with return value and one without. */
#define fibril_fork(...) _fibril_fork_(_fibril_nth(__VA_ARGS__), __VA_ARGS__)
#define _fibril_fork_(n, ...) _fibril_concat(_fibril_fork_, n)(__VA_ARGS__)
/** If nargs is 3, use the no-return-value version. */
#define _fibril_fork_3(...) fibril_fork_nrt(__VA_ARGS__)
/** If nargs is 4, use the with-return-value version. */
#define _fibril_fork_4(...) fibril_fork_wrt(__VA_ARGS__)
/** Helper macros to count number of arguments. */
#define _fibril_nth(...) \
_fibril_nth_(__VA_ARGS__, ##__VA_ARGS__, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, \
9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 0)
#define _fibril_nth_(_1, _1_, _2, _2_, _3, _3_, _4, _4_, _5, _5_, _6, _6_, _7, _7_, _8, _8_, _9, \
_9_, _10, _10_, _11, _11_, _12, _12_, _13, _13_, _14, _14_, _15, _15_, _16, \
_16_, N, ...) \
N
#define _fibril_concat(left, right) left##right
#ifdef __cplusplus
}
#endif