Skip to content
Snippets Groups Projects
Select Git revision
  • rationals
  • master default protected
  • debug-partition-size
  • wta-generator
  • fixes
  • bench-hex
  • ci-artifacts
  • new-monoids
  • stack
  • sumbag
  • tutorial
  • web
  • features/disable-sanity
  • ghc-8.4.4
  • linux-bin-artifacts
  • syntax-doc
  • ci-stack
  • double-round
  • init-time
  • group-weight
20 results

cabal.project

Blame
  • 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