Ignore:
File:
1 edited

Legend:

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

    r1b033b8 rb5344a3  
    215215// available.
    216216
     217//-----------------------------------------------------------------------------
     218// Some assembly required
     219#define __cfaasm_label(label, when) when: asm volatile goto(".global __cfaasm_" #label "_" #when "\n" "__cfaasm_" #label "_" #when ":":::"memory":when)
     220
    217221//----------
    218222// special case for preemption since used often
     
    220224        // create a assembler label before
    221225        // marked as clobber all to avoid movement
    222         asm volatile("__cfaasm_check_before:":::"memory");
     226        __cfaasm_label(check, before);
    223227
    224228        // access tls as normal
     
    227231        // create a assembler label after
    228232        // marked as clobber all to avoid movement
    229         asm volatile("__cfaasm_check_after:":::"memory");
     233        __cfaasm_label(check, after);
    230234        return enabled;
    231235}
     
    246250uintptr_t __cfatls_get( unsigned long int offset ) __attribute__((__noinline__)); //no inline to avoid problems
    247251uintptr_t __cfatls_get( unsigned long int offset ) {
    248         // __cfaasm_get.before = ({ void * value; asm("movq $__cfaasm_get_before, %[v]\n\t" : [v]"=r"(value) ); value; });
    249         // __cfaasm_get.after  = ({ void * value; asm("movq $__cfaasm_get_after , %[v]\n\t" : [v]"=r"(value) ); value; });
    250252        // create a assembler label before
    251253        // marked as clobber all to avoid movement
    252         asm volatile("__cfaasm_get_before:":::"memory");
     254        __cfaasm_label(get, before);
    253255
    254256        // access tls as normal (except for pointer arithmetic)
     
    257259        // create a assembler label after
    258260        // marked as clobber all to avoid movement
    259         asm volatile("__cfaasm_get_after:":::"memory");
     261        __cfaasm_label(get, after);
    260262        return val;
    261263}
     
    266268                // create a assembler label before
    267269                // marked as clobber all to avoid movement
    268                 asm volatile("__cfaasm_dsable_before:":::"memory");
     270                __cfaasm_label(dsable, before);
    269271
    270272                with( __cfaabi_tls.preemption_state ) {
     
    288290                // create a assembler label after
    289291                // marked as clobber all to avoid movement
    290                 asm volatile("__cfaasm_dsable_after:":::"memory");
     292                __cfaasm_label(dsable, after);
     293
    291294        }
    292295
     
    294297        // If counter reaches 0, execute any pending __cfactx_switch
    295298        void enable_interrupts( __cfaabi_dbg_ctx_param ) {
    296                 // create a assembler label before
    297                 // marked as clobber all to avoid movement
    298                 asm volatile("__cfaasm_enble_before:":::"memory");
    299 
    300                 processor   * proc = __cfaabi_tls.this_processor; // Cache the processor now since interrupts can start happening after the atomic store
     299                // Cache the processor now since interrupts can start happening after the atomic store
     300                processor   * proc = __cfaabi_tls.this_processor;
    301301                /* paranoid */ verify( proc );
    302302
     
    304304                        unsigned short prev = disable_count;
    305305                        disable_count -= 1;
    306                         verify( prev != 0u );                     // If this triggers someone is enabled already enabled interruptsverify( prev != 0u );
     306
     307                        // If this triggers someone is enabled already enabled interruptsverify( prev != 0u );
     308                        /* paranoid */ verify( prev != 0u );
    307309
    308310                        // Check if we need to prempt the thread because an interrupt was missed
    309311                        if( prev == 1 ) {
    310312                                #if GCC_VERSION > 50000
    311                                 static_assert(__atomic_always_lock_free(sizeof(enabled), &enabled), "Must be lock-free");
     313                                        static_assert(__atomic_always_lock_free(sizeof(enabled), &enabled), "Must be lock-free");
    312314                                #endif
    313315
     
    328330                // For debugging purposes : keep track of the last person to enable the interrupts
    329331                __cfaabi_dbg_debug_do( proc->last_enable = caller; )
    330 
    331                 // create a assembler label after
    332                 // marked as clobber all to avoid movement
    333                 asm volatile("__cfaasm_enble_after:":::"memory");
    334332        }
    335333
     
    337335        // Don't execute any pending __cfactx_switch even if counter reaches 0
    338336        void enable_interrupts_noPoll() {
    339                 // create a assembler label before
    340                 // marked as clobber all to avoid movement
    341                 asm volatile("__cfaasm_nopoll_before:":::"memory");
    342 
    343337                unsigned short prev = __cfaabi_tls.preemption_state.disable_count;
    344338                __cfaabi_tls.preemption_state.disable_count -= 1;
    345                 verifyf( prev != 0u, "Incremented from %u\n", prev );                     // If this triggers someone is enabled already enabled interrupts
     339                // If this triggers someone is enabled already enabled interrupts
     340                /* paranoid */ verifyf( prev != 0u, "Incremented from %u\n", prev );
    346341                if( prev == 1 ) {
    347342                        #if GCC_VERSION > 50000
    348                         static_assert(__atomic_always_lock_free(sizeof(__cfaabi_tls.preemption_state.enabled), &__cfaabi_tls.preemption_state.enabled), "Must be lock-free");
     343                                static_assert(__atomic_always_lock_free(sizeof(__cfaabi_tls.preemption_state.enabled), &__cfaabi_tls.preemption_state.enabled), "Must be lock-free");
    349344                        #endif
    350345                        // Set enabled flag to true
     
    356351                        __atomic_signal_fence(__ATOMIC_RELEASE);
    357352                }
    358 
    359                 // create a assembler label after
    360                 // marked as clobber all to avoid movement
    361                 asm volatile("__cfaasm_nopoll_after:":::"memory");
    362         }
    363 }
     353        }
     354}
     355
     356#undef __cfaasm_label
    364357
    365358// sigprocmask wrapper : unblock a single signal
     
    393386// reserved for future use
    394387static void timeout( $thread * this ) {
     388        #if !defined( __CFA_NO_STATISTICS__ )
     389                kernelTLS().this_stats = this->curr_cluster->stats;
     390        #endif
    395391        unpark( this );
    396392}
     
    443439#elif defined( __aarch64__ )
    444440        #ifdef __PIC__
    445                 #define RELOC_TAG "@PLT"
    446         #else
    447                 #define RELOC_TAG ""
    448         #endif
    449         #define __cfaasm_label( label ) \
     441                // Note that this works only for gcc
     442                #define __cfaasm_label( label ) static struct asm_region label = \
    450443                ({ \
    451444                        struct asm_region region; \
    452445                        asm( \
    453                                 "mov %[vb], __cfaasm_" #label "_before@GOTPCREL(%%rip)"  "\n\t" \
    454                                 "mov %[va], __cfaasm_" #label "_after@GOTPCREL(%%rip)"   "\n\t" \
     446                                "adrp %[vb], _GLOBAL_OFFSET_TABLE_"                              "\n\t" \
     447                                "ldr  %[vb], [%[vb], #:gotpage_lo15:__cfaasm_" #label "_before]" "\n\t" \
     448                                "adrp %[va], _GLOBAL_OFFSET_TABLE_"                              "\n\t" \
     449                                "ldr  %[va], [%[va], #:gotpage_lo15:__cfaasm_" #label "_after]"  "\n\t" \
    455450                                 : [vb]"=r"(region.before), [va]"=r"(region.after) \
    456451                        ); \
    457452                        region; \
    458453                });
     454        #else
     455                #error this is not the right thing to do
     456                /*
     457                #define __cfaasm_label( label ) static struct asm_region label = \
     458                ({ \
     459                        struct asm_region region; \
     460                        asm( \
     461                                "adrp %[vb], __cfaasm_" #label "_before"              "\n\t" \
     462                                "add  %[vb], %[vb], :lo12:__cfaasm_" #label "_before" "\n\t" \
     463                                "adrp %[va], :got:__cfaasm_" #label "_after"          "\n\t" \
     464                                "add  %[va], %[va], :lo12:__cfaasm_" #label "_after"  "\n\t" \
     465                                 : [vb]"=r"(region.before), [va]"=r"(region.after) \
     466                        ); \
     467                        region; \
     468                });
     469                */
     470        #endif
    459471#else
    460472        #error unknown hardware architecture
     
    470482        __cfaasm_label( check  );
    471483        __cfaasm_label( dsable );
    472         __cfaasm_label( enble );
    473         __cfaasm_label( nopoll );
    474484
    475485        // Check if preemption is safe
     
    478488        if( __cfaasm_in( ip, check  ) ) { ready = false; goto EXIT; };
    479489        if( __cfaasm_in( ip, dsable ) ) { ready = false; goto EXIT; };
    480         if( __cfaasm_in( ip, enble  ) ) { ready = false; goto EXIT; };
    481         if( __cfaasm_in( ip, nopoll ) ) { ready = false; goto EXIT; };
    482490        if( !__cfaabi_tls.preemption_state.enabled) { ready = false; goto EXIT; };
    483491        if( __cfaabi_tls.preemption_state.in_progress ) { ready = false; goto EXIT; };
     
    606614        abort("SIGALRM should never reach the signal handler");
    607615}
    608 
    609 #if !defined(__CFA_NO_STATISTICS__)
    610         int __print_alarm_stats = 0;
    611 #endif
    612616
    613617// Main of the alarm thread
     
    618622        id.id = doregister(&id);
    619623        __cfaabi_tls.this_proc_id = &id;
    620 
    621         #if !defined(__CFA_NO_STATISTICS__)
    622                 struct __stats_t local_stats;
    623                 __cfaabi_tls.this_stats = &local_stats;
    624                 __init_stats( &local_stats );
    625         #endif
    626624
    627625        // Block sigalrms to control when they arrive
     
    683681        __cfaabi_dbg_print_safe( "Kernel : Preemption thread stopping\n" );
    684682        unregister(&id);
    685 
    686         #if !defined(__CFA_NO_STATISTICS__)
    687                 if( 0 != __print_alarm_stats ) {
    688                         __print_stats( &local_stats, __print_alarm_stats, "Alarm", "Thread", 0p );
    689                 }
    690         #endif
    691683        return 0p;
    692684}
Note: See TracChangeset for help on using the changeset viewer.