// // Cforall Version 1.0.0 Copyright (C) 2020 University of Waterloo // // The contents of this file are covered under the licence agreement in the // file "LICENCE" distributed with Cforall. // // kernel/fwd.hfa -- // // Author : Thierry Delisle // Created On : Thu Jul 30 16:46:41 2020 // Last Modified By : // Last Modified On : // Update Count : // #pragma once #include "bits/defs.hfa" #include "bits/debug.hfa" #ifdef __cforall #include "bits/random.hfa" #endif struct $thread; struct processor; struct cluster; enum __Preemption_Reason { __NO_PREEMPTION, __ALARM_PREEMPTION, __POLL_PREEMPTION, __MANUAL_PREEMPTION }; #define KERNEL_STORAGE(T,X) __attribute((aligned(__alignof__(T)))) static char storage_##X[sizeof(T)] #ifdef __cforall extern "C" { extern "Cforall" { extern __attribute__((aligned(128))) thread_local struct KernelThreadData { struct $thread * volatile this_thread; struct processor * volatile this_processor; struct __stats_t * volatile this_stats; struct { volatile unsigned short disable_count; volatile bool enabled; volatile bool in_progress; } preemption_state; #if defined(__SIZEOF_INT128__) __uint128_t rand_seed; #else uint64_t rand_seed; #endif } kernelTLS __attribute__ ((tls_model ( "initial-exec" ))); static inline uint64_t __tls_rand() { #if defined(__SIZEOF_INT128__) return __lehmer64( kernelTLS.rand_seed ); #else return __xorshift64( kernelTLS.rand_seed ); #endif } } #ifdef __ARM_ARCH // function prototypes are only really used by these macros on ARM void disable_global_interrupts(); void enable_global_interrupts(); #define TL_GET( member ) ( { __typeof__( kernelTLS.member ) target; \ disable_global_interrupts(); \ target = kernelTLS.member; \ enable_global_interrupts(); \ target; } ) #define TL_SET( member, value ) disable_global_interrupts(); \ kernelTLS.member = value; \ enable_global_interrupts(); #else #define TL_GET( member ) kernelTLS.member #define TL_SET( member, value ) kernelTLS.member = value; #endif extern void disable_interrupts(); extern void enable_interrupts_noPoll(); extern void enable_interrupts( __cfaabi_dbg_ctx_param ); extern "Cforall" { extern void park( __cfaabi_dbg_ctx_param ); extern void unpark( struct $thread * this __cfaabi_dbg_ctx_param2 ); static inline struct $thread * active_thread () { return TL_GET( this_thread ); } extern bool force_yield( enum __Preemption_Reason ); static inline void yield() { force_yield(__MANUAL_PREEMPTION); } // Yield: yield N times static inline void yield( unsigned times ) { for( times ) { yield(); } } //----------------------------------------------------------------------- // Statics call at the end of each thread to register statistics #if !defined(__CFA_NO_STATISTICS__) static inline struct __stats_t * __tls_stats() { /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); /* paranoid */ verify( kernelTLS.this_stats ); return kernelTLS.this_stats; } #define __STATS__(in_kernel, ...) { \ if( !(in_kernel) ) disable_interrupts(); \ with( *__tls_stats() ) { \ __VA_ARGS__ \ } \ if( !(in_kernel) ) enable_interrupts( __cfaabi_dbg_ctx ); \ } #else #define __STATS__(in_kernel, ...) #endif } } #endif