Changeset 926d358 for libcfa/src


Ignore:
Timestamp:
Oct 11, 2022, 4:50:36 PM (19 months ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, ast-experimental, master
Children:
e5256bd
Parents:
3fcb5921
Message:

Removed old asm_labels.
Modified preemption check to no longer poll interrupts.
Modified poll_interrupts to be lighter weight and remove redundant checks/safeties.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/concurrency/preemption.cfa

    r3fcb5921 r926d358  
    232232// available.
    233233
    234 //-----------------------------------------------------------------------------
    235 // Some assembly required
    236 #define __cfaasm_label(label, when) when: asm volatile goto(".global __cfaasm_" #label "_" #when "\n" "__cfaasm_" #label "_" #when ":":::"memory":when)
    237 
    238234//----------
    239235// special case for preemption since used often
    240 __attribute__((optimize("no-reorder-blocks"))) bool __preemption_enabled() libcfa_nopreempt libcfa_public {
    241         // create a assembler label before
    242         // marked as clobber all to avoid movement
    243         __cfaasm_label(check, before);
    244 
     236bool __preemption_enabled() libcfa_nopreempt libcfa_public {
    245237        // access tls as normal
    246         bool enabled = __cfaabi_tls.preemption_state.enabled;
    247 
    248         // Check if there is a pending preemption
    249         processor   * proc = __cfaabi_tls.this_processor;
    250         bool pending = proc ? proc->pending_preemption : false;
    251         if( enabled && pending ) proc->pending_preemption = false;
    252 
    253         // create a assembler label after
    254         // marked as clobber all to avoid movement
    255         __cfaasm_label(check, after);
    256 
    257         // If we can preempt and there is a pending one
    258         // this is a good time to yield
    259         if( enabled && pending ) {
    260                 force_yield( __POLL_PREEMPTION );
    261         }
    262         return enabled;
    263 }
    264 
    265 struct asm_region {
    266         void * before;
    267         void * after;
    268 };
    269 
    270 static inline bool __cfaasm_in( void * ip, struct asm_region & region ) {
    271         return ip >= region.before && ip <= region.after;
     238        return __cfaabi_tls.preemption_state.enabled;
    272239}
    273240
     
    293260uintptr_t __cfatls_get( unsigned long int offset ) libcfa_nopreempt libcfa_public; //no inline to avoid problems
    294261uintptr_t __cfatls_get( unsigned long int offset ) {
    295         // create a assembler label before
    296         // marked as clobber all to avoid movement
    297         __cfaasm_label(get, before);
    298 
    299262        // access tls as normal (except for pointer arithmetic)
    300263        uintptr_t val = *(uintptr_t*)((uintptr_t)&__cfaabi_tls + offset);
    301264
    302         // create a assembler label after
    303         // marked as clobber all to avoid movement
    304         __cfaasm_label(get, after);
    305 
    306265        // This is used everywhere, to avoid cost, we DO NOT poll pending preemption
    307266        return val;
     
    310269extern "C" {
    311270        // Disable interrupts by incrementing the counter
    312         void disable_interrupts() libcfa_nopreempt libcfa_public {
    313                 // create a assembler label before
    314                 // marked as clobber all to avoid movement
    315                 __cfaasm_label(dsable, before);
    316 
    317                 with( __cfaabi_tls.preemption_state ) {
    318                         #if GCC_VERSION > 50000
    319                         static_assert(__atomic_always_lock_free(sizeof(enabled), &enabled), "Must be lock-free");
    320                         #endif
    321 
    322                         // Set enabled flag to false
    323                         // should be atomic to avoid preemption in the middle of the operation.
    324                         // use memory order RELAXED since there is no inter-thread on this variable requirements
    325                         __atomic_store_n(&enabled, false, __ATOMIC_RELAXED);
    326 
    327                         // Signal the compiler that a fence is needed but only for signal handlers
    328                         __atomic_signal_fence(__ATOMIC_ACQUIRE);
    329 
    330                         __attribute__((unused)) unsigned short new_val = disable_count + 1;
    331                         disable_count = new_val;
    332                         verify( new_val < 65_000u );              // If this triggers someone is disabling interrupts without enabling them
    333                 }
    334 
    335                 // create a assembler label after
    336                 // marked as clobber all to avoid movement
    337                 __cfaasm_label(dsable, after);
    338 
     271        void disable_interrupts() libcfa_nopreempt libcfa_public with( __cfaabi_tls.preemption_state ) {
     272                #if GCC_VERSION > 50000
     273                static_assert(__atomic_always_lock_free(sizeof(enabled), &enabled), "Must be lock-free");
     274                #endif
     275
     276                // Set enabled flag to false
     277                // should be atomic to avoid preemption in the middle of the operation.
     278                // use memory order RELAXED since there is no inter-thread on this variable requirements
     279                __atomic_store_n(&enabled, false, __ATOMIC_RELAXED);
     280
     281                // Signal the compiler that a fence is needed but only for signal handlers
     282                __atomic_signal_fence(__ATOMIC_ACQUIRE);
     283
     284                __attribute__((unused)) unsigned short new_val = disable_count + 1;
     285                disable_count = new_val;
     286                verify( new_val < 65_000u );              // If this triggers someone is disabling interrupts without enabling them
    339287        }
    340288
     
    379327        // i.e. on a real processor and not in the kernel
    380328        // (can return true even if no preemption was pending)
    381         bool poll_interrupts() libcfa_public {
     329        bool poll_interrupts() libcfa_nopreempt libcfa_public {
    382330                // Cache the processor now since interrupts can start happening after the atomic store
    383                 processor   * proc = publicTLS_get( this_processor );
     331                processor   * proc =  __cfaabi_tls.this_processor;
    384332                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                         }
     333                if ( ! __cfaabi_tls.preemption_state.enabled ) return false;
     334
     335                // Signal the compiler that a fence is needed but only for signal handlers
     336                __atomic_signal_fence(__ATOMIC_RELEASE);
     337                if( unlikely( proc->pending_preemption ) ) {
     338                        proc->pending_preemption = false;
     339                        force_yield( __POLL_PREEMPTION );
    394340                }
    395341
Note: See TracChangeset for help on using the changeset viewer.