Changeset 23a08aa0 for libcfa


Ignore:
Timestamp:
Sep 19, 2022, 8:11:02 PM (3 years ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
ADT, ast-experimental, master, pthread-emulation
Children:
aa9f215
Parents:
ebf8ca5 (diff), ae1d151 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

fix merge conflict

Location:
libcfa
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • libcfa/prelude/Makefile.am

    rebf8ca5 r23a08aa0  
    5050
    5151prelude.cfa : prelude-gen.cc
    52         ${AM_V_GEN}${CXX} ${AM_CXXFLAGS} ${CXXFLAGS} ${AM_CFLAGS} ${<} -o prelude-gen -Wall -Wextra -O2 -g -std=c++14
     52        ${AM_V_GEN}${CXX} ${AM_CXXFLAGS} ${CXXFLAGS} ${AM_CFLAGS} ${<} -o prelude-gen -Wall -Wextra -O2 -g -std=c++17
    5353        @./prelude-gen > ${@}
    5454        @rm ./prelude-gen
     
    7676
    7777if ENABLE_DISTCC
    78 distribution: @LOCAL_CFACC@ @LOCAL_CC1@ @CFACPP@ gcc-builtins.cf builtins.cf extras.cf prelude.cfa bootloader.c $(srcdir)/../../tools/build/push2dist.sh
     78distribution: @LOCAL_CFACC@ @LOCAL_CC1@ @CFACPP@ defines.hfa gcc-builtins.cf builtins.cf extras.cf prelude.cfa bootloader.c $(srcdir)/../../tools/build/push2dist.sh
    7979        ${AM_V_GEN}$(srcdir)/../../tools/build/push2dist.sh @CFADIR_HASH@ @DIST_BWLIMIT@
    8080        @echo "Dummy file to track distribution to remote hosts" > ${@}
  • libcfa/prelude/defines.hfa.in

    rebf8ca5 r23a08aa0  
    141141
    142142/* Defined if io_uring support is present when compiling libcfathread and
     143   supports the flag IORING_REGISTER_IOWQ_MAX_WORKERS. */
     144#undef CFA_HAVE_IORING_REGISTER_IOWQ_MAX_WORKERS
     145
     146/* Defined if io_uring support is present when compiling libcfathread and
    143147   supports the flag IORING_SETUP_ATTACH_WQ. */
    144148#undef CFA_HAVE_IORING_SETUP_ATTACH_WQ
  • libcfa/src/Makefile.am

    rebf8ca5 r23a08aa0  
    186186if ENABLE_DISTCC
    187187
    188 ../prelude/distribution: @LOCAL_CFACC@ @LOCAL_CC1@ @CFACPP@ ../prelude/gcc-builtins.cf ../prelude/builtins.cf ../prelude/extras.cf ../prelude/prelude.cfa ../prelude/bootloader.c $(srcdir)/../../tools/build/push2dist.sh
     188../prelude/distribution: @LOCAL_CFACC@ @LOCAL_CC1@ @CFACPP@ ../prelude/defines.hfa ../prelude/gcc-builtins.cf ../prelude/builtins.cf ../prelude/extras.cf ../prelude/prelude.cfa ../prelude/bootloader.c $(srcdir)/../../tools/build/push2dist.sh
    189189        @+make -C ../prelude distribution
    190190
  • libcfa/src/bits/defs.hfa

    rebf8ca5 r23a08aa0  
    2424#define likely(x)   __builtin_expect(!!(x), 1)
    2525#define unlikely(x) __builtin_expect(!!(x), 0)
    26 #define thread_local _Thread_local
    2726
    2827typedef void (*fptr_t)();
     
    3736#endif
    3837
     38
     39#if defined(__has_attribute)
     40#if !__has_attribute(__noclone__)
     41#define ATTRIBUTE_NOCLONE
     42#endif
     43#endif
     44#ifndef ATTRIBUTE_NOCLONE
     45#define ATTRIBUTE_NOCLONE __attribute__((__noclone__))
     46#endif
     47
    3948#define libcfa_public __attribute__((visibility("default")))
     49#define libcfa_nopreempt __attribute__((section("cfatext_nopreempt"))) __attribute__((__noinline__)) ATTRIBUTE_NOCLONE
     50
     51struct __cfa_nopreempt_region {
     52        void * start;
     53        void * stop;
     54};
    4055
    4156#ifdef __cforall
  • libcfa/src/bits/locks.hfa

    rebf8ca5 r23a08aa0  
    1313// Created On       : Tue Oct 31 15:14:38 2017
    1414// Last Modified By : Peter A. Buhr
    15 // Last Modified On : Sat Aug 27 15:06:39 2022
    16 // Update Count     : 15
     15// Last Modified On : Mon Sep 19 18:39:45 2022
     16// Update Count     : 16
    1717//
    1818
  • libcfa/src/concurrency/io/call.cfa.in

    rebf8ca5 r23a08aa0  
    202202                struct io_context$ * ctx = cfa_io_allocate( &sqe, &idx, 1 );
    203203
     204                memset(sqe, 0, sizeof(*sqe));
    204205                sqe->opcode = IORING_OP_{op};
     206                sqe->flags = sflags;
    205207                sqe->user_data = (uintptr_t)&future;
    206                 sqe->flags = sflags;
    207                 sqe->ioprio = 0;
    208                 sqe->fd = 0;
    209                 sqe->off = 0;
    210                 sqe->addr = 0;
    211                 sqe->len = 0;
    212                 sqe->fsync_flags = 0;
    213                 sqe->__pad2[0] = 0;
    214                 sqe->__pad2[1] = 0;
    215                 sqe->__pad2[2] = 0;{body}
     208                {body}
    216209
    217210                asm volatile("": : :"memory");
  • libcfa/src/concurrency/io/setup.cfa

    rebf8ca5 r23a08aa0  
    228228
    229229                #if !defined(CFA_WITH_IO_URING_IDLE)
     230                {
    230231                        // Step 4 : eventfd
    231232                        __cfadbg_print_safe(io_core, "Kernel I/O : registering %d for completion with ring %d\n", procfd, fd);
     
    237238
    238239                        __cfadbg_print_safe(io_core, "Kernel I/O : registered %d for completion with ring %d\n", procfd, fd);
    239                 #endif
    240 
     240                }
     241                #endif
     242
     243                // TODO: implement a proper version of this.
     244                // I have not found a better maximum that works in general but users should be able to configure it
     245                // the same way they configure other I/O options
    241246                // #if defined(CFA_HAVE_IORING_REGISTER_IOWQ_MAX_WORKERS)
     247                // {
    242248                //      // Step 5 : max worker count
    243249                //      __cfadbg_print_safe(io_core, "Kernel I/O : lmiting max workers for ring %d\n", fd);
     
    252258
    253259                //      __cfadbg_print_safe(io_core, "Kernel I/O : lmited max workers for ring %d\n", fd);
     260                // }
    254261                // #endif
    255262
  • libcfa/src/concurrency/kernel/cluster.hfa

    rebf8ca5 r23a08aa0  
    6363                }
    6464        }
    65         return (max + 2 * max) / 2;
     65        return 8 * max;
    6666}
    6767
  • libcfa/src/concurrency/kernel/fwd.hfa

    rebf8ca5 r23a08aa0  
    3535extern "C" {
    3636        extern "Cforall" {
    37                 extern __attribute__((aligned(64))) thread_local struct KernelThreadData {
     37                extern __attribute__((aligned(64))) __thread struct KernelThreadData {
    3838                        struct thread$          * volatile this_thread;
    3939                        struct processor        * volatile this_processor;
     
    179179                // Similar to a binary semaphore with a 'one shot' semantic
    180180                // is expected to be discarded after each party call their side
     181                enum(struct thread$ *) { oneshot_ARMED = 0p, oneshot_FULFILLED = 1p };
    181182                struct oneshot {
    182183                        // Internal state :
    183                         //     0p     : is initial state (wait will block)
    184                         //     1p     : fulfilled (wait won't block)
     184                        // armed      : initial state, wait will block
     185                        // fulfilled  : wait won't block
    185186                        // any thread : a thread is currently waiting
    186187                        struct thread$ * volatile ptr;
     
    189190                static inline {
    190191                        void  ?{}(oneshot & this) {
    191                                 this.ptr = 0p;
     192                                this.ptr = oneshot_ARMED;
    192193                        }
    193194
     
    199200                                for() {
    200201                                        struct thread$ * expected = this.ptr;
    201                                         if(expected == 1p) return false;
     202                                        if(expected == oneshot_FULFILLED) return false;
    202203                                        if(__atomic_compare_exchange_n(&this.ptr, &expected, active_thread(), false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
    203204                                                park();
    204                                                 /* paranoid */ verify( this.ptr == 1p );
     205                                                /* paranoid */ verify( this.ptr == oneshot_FULFILLED );
    205206                                                return true;
    206207                                        }
     
    211212                        // return true if a thread was unparked
    212213                        thread$ * post(oneshot & this, bool do_unpark = true) {
    213                                 struct thread$ * got = __atomic_exchange_n( &this.ptr, 1p, __ATOMIC_SEQ_CST);
    214                                 if( got == 0p || got == 1p ) return 0p;
     214                                struct thread$ * got = __atomic_exchange_n( &this.ptr, oneshot_FULFILLED, __ATOMIC_SEQ_CST);
     215                                if( got == oneshot_ARMED || got == oneshot_FULFILLED ) return 0p;
    215216                                if(do_unpark) unpark( got );
    216217                                return got;
     
    223224                // thread on "any of" [a given set of] futures.
    224225                // does not support multiple threads waiting on the same future
     226                enum(struct oneshot *) { future_ARMED = 0p, future_FULFILLED = 1p, future_PROGRESS = 2p, future_ABANDONED = 3p };
    225227                struct future_t {
    226228                        // Internal state :
    227                         //     0p      : is initial state (wait will block)
    228                         //     1p      : fulfilled (wait won't block)
    229                         //     2p      : in progress ()
    230                         //     3p      : abandoned, server should delete
     229                        // armed       : initial state, wait will block
     230                        // fulfilled   : result is ready, wait won't block
     231                        // progress    : someone else is in the process of fulfilling this
     232                        // abandoned   : client no longer cares, server should delete
    231233                        // any oneshot : a context has been setup to wait, a thread could wait on it
    232234                        struct oneshot * volatile ptr;
     
    235237                static inline {
    236238                        void  ?{}(future_t & this) {
    237                                 this.ptr = 0p;
     239                                this.ptr = future_ARMED;
    238240                        }
    239241
     
    242244                        void reset(future_t & this) {
    243245                                // needs to be in 0p or 1p
    244                                 __atomic_exchange_n( &this.ptr, 0p, __ATOMIC_SEQ_CST);
     246                                __atomic_exchange_n( &this.ptr, future_ARMED, __ATOMIC_SEQ_CST);
    245247                        }
    246248
    247249                        // check if the future is available
    248250                        bool available( future_t & this ) {
    249                                 while( this.ptr == 2p ) Pause();
    250                                 return this.ptr == 1p;
     251                                while( this.ptr == future_PROGRESS ) Pause();
     252                                return this.ptr == future_FULFILLED;
    251253                        }
    252254
     
    254256                        // intented to be use by wait, wait_any, waitfor, etc. rather than used directly
    255257                        bool setup( future_t & this, oneshot & wait_ctx ) {
    256                                 /* paranoid */ verify( wait_ctx.ptr == 0p || wait_ctx.ptr == 1p );
     258                                /* paranoid */ verify( wait_ctx.ptr == oneshot_ARMED || wait_ctx.ptr == oneshot_FULFILLED );
    257259                                // The future needs to set the wait context
    258260                                for() {
    259261                                        struct oneshot * expected = this.ptr;
    260262                                        // Is the future already fulfilled?
    261                                         if(expected == 1p) return false; // Yes, just return false (didn't block)
     263                                        if(expected == future_FULFILLED) return false; // Yes, just return false (didn't block)
    262264
    263265                                        // The future is not fulfilled, try to setup the wait context
     
    277279
    278280                                // attempt to remove the context so it doesn't get consumed.
    279                                 if(__atomic_compare_exchange_n( &this.ptr, &expected, 0p, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
     281                                if(__atomic_compare_exchange_n( &this.ptr, &expected, future_ARMED, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
    280282                                        // we still have the original context, then no one else saw it
    281283                                        return false;
    282284                                }
    283285
    284                                 // expected == 0p: future was never actually setup, just return
    285                                 if( expected == 0p ) return false;
    286 
    287                                 // expected == 1p: the future is ready and the context was fully consumed
     286                                // expected == ARMED: future was never actually setup, just return
     287                                if( expected == future_ARMED ) return false;
     288
     289                                // expected == FULFILLED: the future is ready and the context was fully consumed
    288290                                // the server won't use the pointer again
    289291                                // It is safe to delete (which could happen after the return)
    290                                 if( expected == 1p ) return true;
    291 
    292                                 // expected == 2p: the future is ready but the context hasn't fully been consumed
     292                                if( expected == future_FULFILLED ) return true;
     293
     294                                // expected == PROGRESS: the future is ready but the context hasn't fully been consumed
    293295                                // spin until it is safe to move on
    294                                 if( expected == 2p ) {
    295                                         while( this.ptr != 1p ) Pause();
    296                                         /* paranoid */ verify( this.ptr == 1p );
     296                                if( expected == future_PROGRESS ) {
     297                                        while( this.ptr != future_FULFILLED ) Pause();
     298                                        /* paranoid */ verify( this.ptr == future_FULFILLED );
    297299                                        return true;
    298300                                }
     
    305307                        // Mark the future as abandoned, meaning it will be deleted by the server
    306308                        bool abandon( future_t & this ) {
    307                                 /* paranoid */ verify( this.ptr != 3p );
     309                                /* paranoid */ verify( this.ptr != future_ABANDONED );
    308310
    309311                                // Mark the future as abandonned
    310                                 struct oneshot * got = __atomic_exchange_n( &this.ptr, 3p, __ATOMIC_SEQ_CST);
     312                                struct oneshot * got = __atomic_exchange_n( &this.ptr, future_ABANDONED, __ATOMIC_SEQ_CST);
    311313
    312314                                // If the future isn't already fulfilled, let the server delete it
    313                                 if( got == 0p ) return false;
    314 
    315                                 // got == 2p: the future is ready but the context hasn't fully been consumed
     315                                if( got == future_ARMED ) return false;
     316
     317                                // got == PROGRESS: the future is ready but the context hasn't fully been consumed
    316318                                // spin until it is safe to move on
    317                                 if( got == 2p ) {
    318                                         while( this.ptr != 1p ) Pause();
    319                                         got = 1p;
     319                                if( got == future_PROGRESS ) {
     320                                        while( this.ptr != future_FULFILLED ) Pause();
     321                                        got = future_FULFILLED;
    320322                                }
    321323
    322324                                // The future is completed delete it now
    323                                 /* paranoid */ verify( this.ptr != 1p );
     325                                /* paranoid */ verify( this.ptr != future_FULFILLED );
    324326                                free( &this );
    325327                                return true;
     
    336338                                                #pragma GCC diagnostic ignored "-Wfree-nonheap-object"
    337339                                        #endif
    338                                                 if( expected == 3p ) { free( &this ); return 0p; }
     340                                                if( expected == future_ABANDONED ) { free( &this ); return 0p; }
    339341                                        #if defined(__GNUC__) && __GNUC__ >= 7
    340342                                                #pragma GCC diagnostic pop
    341343                                        #endif
    342344
    343                                         /* paranoid */ verify( expected != 1p ); // Future is already fulfilled, should not happen
    344                                         /* paranoid */ verify( expected != 2p ); // Future is bein fulfilled by someone else, this is even less supported then the previous case.
     345                                        /* paranoid */ verify( expected != future_FULFILLED ); // Future is already fulfilled, should not happen
     346                                        /* paranoid */ verify( expected != future_PROGRESS ); // Future is bein fulfilled by someone else, this is even less supported then the previous case.
    345347
    346348                                        // If there is a wait context, we need to consume it and mark it as consumed after
    347349                                        // If there is no context then we can skip the in progress phase
    348                                         struct oneshot * want = expected == 0p ? 1p : 2p;
     350                                        struct oneshot * want = expected == future_ARMED ? future_FULFILLED : future_PROGRESS;
    349351                                        if(__atomic_compare_exchange_n(&this.ptr, &expected, want, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
    350                                                 if( expected == 0p ) { return 0p; }
     352                                                if( expected == future_ARMED ) { return 0p; }
    351353                                                thread$ * ret = post( *expected, do_unpark );
    352                                                 __atomic_store_n( &this.ptr, 1p, __ATOMIC_SEQ_CST);
     354                                                __atomic_store_n( &this.ptr, future_FULFILLED, __ATOMIC_SEQ_CST);
    353355                                                return ret;
    354356                                        }
     
    366368
    367369                                // Wait for the future to tru
    368                                 while( this.ptr == 2p ) Pause();
     370                                while( this.ptr == future_PROGRESS ) Pause();
    369371                                // Make sure the state makes sense
    370372                                // Should be fulfilled, could be in progress but it's out of date if so
     
    372374                                // and the oneshot should not be needed any more
    373375                                __attribute__((unused)) struct oneshot * was = this.ptr;
    374                                 /* paranoid */ verifyf( was == 1p, "Expected this.ptr to be 1p, was %p\n", was );
     376                                /* paranoid */ verifyf( was == future_FULFILLED, "Expected this.ptr to be 1p, was %p\n", was );
    375377
    376378                                // Mark the future as fulfilled, to be consistent
  • libcfa/src/concurrency/kernel/private.hfa

    rebf8ca5 r23a08aa0  
    8888#elif defined(CFA_HAVE_LINUX_RSEQ_H)
    8989        extern "Cforall" {
    90                 extern __attribute__((aligned(64))) thread_local volatile struct rseq __cfaabi_rseq;
     90                extern __attribute__((aligned(64))) __thread volatile struct rseq __cfaabi_rseq;
    9191        }
    9292#else
     
    161161// Blocking acquire
    162162static inline void __atomic_acquire(volatile bool * ll) {
     163        /* paranoid */ verify( ! __preemption_enabled() );
     164        /* paranoid */ verify(ll);
     165
    163166        while( __builtin_expect(__atomic_exchange_n(ll, (bool)true, __ATOMIC_SEQ_CST), false) ) {
    164167                while(__atomic_load_n(ll, (int)__ATOMIC_RELAXED))
     
    166169        }
    167170        /* paranoid */ verify(*ll);
     171        /* paranoid */ verify( ! __preemption_enabled() );
    168172}
    169173
    170174// Non-Blocking acquire
    171175static inline bool __atomic_try_acquire(volatile bool * ll) {
     176        /* paranoid */ verify( ! __preemption_enabled() );
     177        /* paranoid */ verify(ll);
     178
    172179        return !__atomic_exchange_n(ll, (bool)true, __ATOMIC_SEQ_CST);
    173180}
     
    175182// Release
    176183static inline void __atomic_unlock(volatile bool * ll) {
     184        /* paranoid */ verify( ! __preemption_enabled() );
     185        /* paranoid */ verify(ll);
    177186        /* paranoid */ verify(*ll);
    178187        __atomic_store_n(ll, (bool)false, __ATOMIC_RELEASE);
  • libcfa/src/concurrency/kernel/startup.cfa

    rebf8ca5 r23a08aa0  
    133133//-----------------------------------------------------------------------------
    134134// Global state
    135 thread_local struct KernelThreadData __cfaabi_tls __attribute__ ((tls_model ( "initial-exec" ))) @= {
     135__thread struct KernelThreadData __cfaabi_tls __attribute__ ((tls_model ( "initial-exec" ))) @= {
    136136        NULL,                                                                                           // cannot use 0p
    137137        NULL,
     
    153153#elif defined(CFA_HAVE_LINUX_RSEQ_H)
    154154        extern "Cforall" {
    155                 __attribute__((aligned(64))) thread_local volatile struct rseq __cfaabi_rseq @= {
     155                __attribute__((aligned(64))) __thread volatile struct rseq __cfaabi_rseq @= {
    156156                        .cpu_id : RSEQ_CPU_ID_UNINITIALIZED,
    157157                };
  • libcfa/src/concurrency/preemption.cfa

    rebf8ca5 r23a08aa0  
    238238//----------
    239239// special case for preemption since used often
    240 __attribute__((optimize("no-reorder-blocks"))) bool __preemption_enabled() libcfa_public {
     240__attribute__((optimize("no-reorder-blocks"))) bool __preemption_enabled() libcfa_nopreempt libcfa_public {
    241241        // create a assembler label before
    242242        // marked as clobber all to avoid movement
     
    272272}
    273273
     274extern "C" {
     275        __attribute__((visibility("hidden"))) extern void * const __start_cfatext_nopreempt;
     276        __attribute__((visibility("hidden"))) extern void * const __stop_cfatext_nopreempt;
     277
     278        extern const __cfa_nopreempt_region __libcfa_nopreempt;
     279        __attribute__((visibility("protected"))) const __cfa_nopreempt_region __libcfathrd_nopreempt @= {
     280                (void * const)&__start_cfatext_nopreempt,
     281                (void * const)&__stop_cfatext_nopreempt
     282        };
     283}
     284
     285static inline bool __cfaabi_in( void * const ip, const struct __cfa_nopreempt_region & const region ) {
     286        return ip >= region.start && ip <= region.stop;
     287}
     288
    274289
    275290//----------
    276291// Get data from the TLS block
    277292// struct asm_region __cfaasm_get;
    278 uintptr_t __cfatls_get( unsigned long int offset ) __attribute__((__noinline__, visibility("default"))); //no inline to avoid problems
     293uintptr_t __cfatls_get( unsigned long int offset ) libcfa_nopreempt libcfa_public; //no inline to avoid problems
    279294uintptr_t __cfatls_get( unsigned long int offset ) {
    280295        // create a assembler label before
     
    295310extern "C" {
    296311        // Disable interrupts by incrementing the counter
    297         __attribute__((__noinline__, visibility("default"))) void disable_interrupts() libcfa_public {
     312        void disable_interrupts() libcfa_nopreempt libcfa_public {
    298313                // create a assembler label before
    299314                // marked as clobber all to avoid movement
     
    326341        // Enable interrupts by decrementing the counter
    327342        // If counter reaches 0, execute any pending __cfactx_switch
    328         void enable_interrupts( bool poll ) libcfa_public {
     343        void enable_interrupts( bool poll ) libcfa_nopreempt libcfa_public {
    329344                // Cache the processor now since interrupts can start happening after the atomic store
    330345                processor   * proc = __cfaabi_tls.this_processor;
     
    358373                }
    359374        }
     375
     376        // Check whether or not there is pending preemption
     377        // force_yield( __POLL_PREEMPTION ) if appropriate
     378        // return true if the thread was in an interruptable state
     379        // i.e. on a real processor and not in the kernel
     380        // (can return true even if no preemption was pending)
     381        bool poll_interrupts() libcfa_public {
     382                // Cache the processor now since interrupts can start happening after the atomic store
     383                processor   * proc = publicTLS_get( this_processor );
     384                if ( ! proc ) return false;
     385                if ( ! __preemption_enabled() ) return false;
     386
     387                with( __cfaabi_tls.preemption_state ){
     388                        // Signal the compiler that a fence is needed but only for signal handlers
     389                        __atomic_signal_fence(__ATOMIC_RELEASE);
     390                        if( proc->pending_preemption ) {
     391                                proc->pending_preemption = false;
     392                                force_yield( __POLL_PREEMPTION );
     393                        }
     394                }
     395
     396                return true;
     397        }
    360398}
    361399
     
    463501
    464502//-----------------------------------------------------------------------------
    465 // Some assembly required
    466 #if defined( __i386 )
    467         #ifdef __PIC__
    468                 #define RELOC_PRELUDE( label ) \
    469                         "calll   .Lcfaasm_prelude_" #label "$pb\n\t" \
    470                         ".Lcfaasm_prelude_" #label "$pb:\n\t" \
    471                         "popl    %%eax\n\t" \
    472                         ".Lcfaasm_prelude_" #label "_end:\n\t" \
    473                         "addl    $_GLOBAL_OFFSET_TABLE_+(.Lcfaasm_prelude_" #label "_end-.Lcfaasm_prelude_" #label "$pb), %%eax\n\t"
    474                 #define RELOC_PREFIX ""
    475                 #define RELOC_SUFFIX "@GOT(%%eax)"
    476         #else
    477                 #define RELOC_PREFIX "$"
    478                 #define RELOC_SUFFIX ""
    479         #endif
    480         #define __cfaasm_label( label ) struct asm_region label = \
    481                 ({ \
    482                         struct asm_region region; \
    483                         asm( \
    484                                 RELOC_PRELUDE( label ) \
    485                                 "movl " RELOC_PREFIX "__cfaasm_" #label "_before" RELOC_SUFFIX ", %[vb]\n\t" \
    486                                 "movl " RELOC_PREFIX "__cfaasm_" #label "_after"  RELOC_SUFFIX ", %[va]\n\t" \
    487                                  : [vb]"=r"(region.before), [va]"=r"(region.after) \
    488                         ); \
    489                         region; \
    490                 });
    491 #elif defined( __x86_64 )
    492         #ifdef __PIC__
    493                 #define RELOC_PREFIX ""
    494                 #define RELOC_SUFFIX "@GOTPCREL(%%rip)"
    495         #else
    496                 #define RELOC_PREFIX "$"
    497                 #define RELOC_SUFFIX ""
    498         #endif
    499         #define __cfaasm_label( label ) struct asm_region label = \
    500                 ({ \
    501                         struct asm_region region; \
    502                         asm( \
    503                                 "movq " RELOC_PREFIX "__cfaasm_" #label "_before" RELOC_SUFFIX ", %[vb]\n\t" \
    504                                 "movq " RELOC_PREFIX "__cfaasm_" #label "_after"  RELOC_SUFFIX ", %[va]\n\t" \
    505                                  : [vb]"=r"(region.before), [va]"=r"(region.after) \
    506                         ); \
    507                         region; \
    508                 });
    509 #elif defined( __aarch64__ )
    510         #ifdef __PIC__
    511                 // Note that this works only for gcc
    512                 #define __cfaasm_label( label ) struct asm_region label = \
    513                 ({ \
    514                         struct asm_region region; \
    515                         asm( \
    516                                 "adrp %[vb], _GLOBAL_OFFSET_TABLE_"                              "\n\t" \
    517                                 "ldr  %[vb], [%[vb], #:gotpage_lo15:__cfaasm_" #label "_before]" "\n\t" \
    518                                 "adrp %[va], _GLOBAL_OFFSET_TABLE_"                              "\n\t" \
    519                                 "ldr  %[va], [%[va], #:gotpage_lo15:__cfaasm_" #label "_after]"  "\n\t" \
    520                                  : [vb]"=r"(region.before), [va]"=r"(region.after) \
    521                         ); \
    522                         region; \
    523                 });
    524         #else
    525                 #error this is not the right thing to do
    526                 /*
    527                 #define __cfaasm_label( label ) struct asm_region label = \
    528                 ({ \
    529                         struct asm_region region; \
    530                         asm( \
    531                                 "adrp %[vb], __cfaasm_" #label "_before"              "\n\t" \
    532                                 "add  %[vb], %[vb], :lo12:__cfaasm_" #label "_before" "\n\t" \
    533                                 "adrp %[va], :got:__cfaasm_" #label "_after"          "\n\t" \
    534                                 "add  %[va], %[va], :lo12:__cfaasm_" #label "_after"  "\n\t" \
    535                                  : [vb]"=r"(region.before), [va]"=r"(region.after) \
    536                         ); \
    537                         region; \
    538                 });
    539                 */
    540         #endif
    541 #else
    542         #error unknown hardware architecture
    543 #endif
    544 
    545503// KERNEL ONLY
    546504// Check if a __cfactx_switch signal handler shoud defer
     
    548506// If false : preemption is unsafe and marked as pending
    549507static inline bool preemption_ready( void * ip ) {
    550         // Get all the region for which it is not safe to preempt
    551         __cfaasm_label( get    );
    552         __cfaasm_label( check  );
    553         __cfaasm_label( dsable );
    554         // __cfaasm_label( debug  );
    555 
    556508        // Check if preemption is safe
    557509        bool ready = true;
    558         if( __cfaasm_in( ip, get    ) ) { ready = false; goto EXIT; };
    559         if( __cfaasm_in( ip, check  ) ) { ready = false; goto EXIT; };
    560         if( __cfaasm_in( ip, dsable ) ) { ready = false; goto EXIT; };
    561         // if( __cfaasm_in( ip, debug  ) ) { ready = false; goto EXIT; };
     510        if( __cfaabi_in( ip, __libcfa_nopreempt ) ) { ready = false; goto EXIT; };
     511        if( __cfaabi_in( ip, __libcfathrd_nopreempt ) ) { ready = false; goto EXIT; };
     512
    562513        if( !__cfaabi_tls.preemption_state.enabled) { ready = false; goto EXIT; };
    563514        if( __cfaabi_tls.preemption_state.in_progress ) { ready = false; goto EXIT; };
     
    643594// Kernel Signal Handlers
    644595//=============================================================================================
    645 __cfaabi_dbg_debug_do( static thread_local void * last_interrupt = 0; )
     596__cfaabi_dbg_debug_do( static __thread void * last_interrupt = 0; )
    646597
    647598// Context switch signal handler
  • libcfa/src/startup.cfa

    rebf8ca5 r23a08aa0  
    4141        } // __cfaabi_appready_shutdown
    4242
    43         void disable_interrupts() __attribute__(( weak )) libcfa_public {}
    44         void enable_interrupts() __attribute__(( weak )) libcfa_public {}
     43        void disable_interrupts() __attribute__(( weak )) libcfa_nopreempt libcfa_public {}
     44        void enable_interrupts() __attribute__(( weak )) libcfa_nopreempt libcfa_public {}
     45        bool poll_interrupts() __attribute__(( weak )) libcfa_nopreempt libcfa_public { return false; }
     46
     47        __attribute__((visibility("hidden"))) extern void * const __start_cfatext_nopreempt;
     48        __attribute__((visibility("hidden"))) extern void * const __stop_cfatext_nopreempt;
     49
     50        __attribute__((visibility("protected"))) const __cfa_nopreempt_region __libcfa_nopreempt @= {
     51                (void * const)&__start_cfatext_nopreempt,
     52                (void * const)&__stop_cfatext_nopreempt
     53        };
    4554
    4655
Note: See TracChangeset for help on using the changeset viewer.