Ignore:
File:
1 edited

Legend:

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

    rb5344a3 r1b033b8  
    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 
    221217//----------
    222218// special case for preemption since used often
     
    224220        // create a assembler label before
    225221        // marked as clobber all to avoid movement
    226         __cfaasm_label(check, before);
     222        asm volatile("__cfaasm_check_before:":::"memory");
    227223
    228224        // access tls as normal
     
    231227        // create a assembler label after
    232228        // marked as clobber all to avoid movement
    233         __cfaasm_label(check, after);
     229        asm volatile("__cfaasm_check_after:":::"memory");
    234230        return enabled;
    235231}
     
    250246uintptr_t __cfatls_get( unsigned long int offset ) __attribute__((__noinline__)); //no inline to avoid problems
    251247uintptr_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; });
    252250        // create a assembler label before
    253251        // marked as clobber all to avoid movement
    254         __cfaasm_label(get, before);
     252        asm volatile("__cfaasm_get_before:":::"memory");
    255253
    256254        // access tls as normal (except for pointer arithmetic)
     
    259257        // create a assembler label after
    260258        // marked as clobber all to avoid movement
    261         __cfaasm_label(get, after);
     259        asm volatile("__cfaasm_get_after:":::"memory");
    262260        return val;
    263261}
     
    268266                // create a assembler label before
    269267                // marked as clobber all to avoid movement
    270                 __cfaasm_label(dsable, before);
     268                asm volatile("__cfaasm_dsable_before:":::"memory");
    271269
    272270                with( __cfaabi_tls.preemption_state ) {
     
    290288                // create a assembler label after
    291289                // marked as clobber all to avoid movement
    292                 __cfaasm_label(dsable, after);
    293 
     290                asm volatile("__cfaasm_dsable_after:":::"memory");
    294291        }
    295292
     
    297294        // If counter reaches 0, execute any pending __cfactx_switch
    298295        void enable_interrupts( __cfaabi_dbg_ctx_param ) {
    299                 // Cache the processor now since interrupts can start happening after the atomic store
    300                 processor   * proc = __cfaabi_tls.this_processor;
     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
    301301                /* paranoid */ verify( proc );
    302302
     
    304304                        unsigned short prev = disable_count;
    305305                        disable_count -= 1;
    306 
    307                         // If this triggers someone is enabled already enabled interruptsverify( prev != 0u );
    308                         /* paranoid */ verify( prev != 0u );
     306                        verify( prev != 0u );                     // If this triggers someone is enabled already enabled interruptsverify( prev != 0u );
    309307
    310308                        // Check if we need to prempt the thread because an interrupt was missed
    311309                        if( prev == 1 ) {
    312310                                #if GCC_VERSION > 50000
    313                                         static_assert(__atomic_always_lock_free(sizeof(enabled), &enabled), "Must be lock-free");
     311                                static_assert(__atomic_always_lock_free(sizeof(enabled), &enabled), "Must be lock-free");
    314312                                #endif
    315313
     
    330328                // For debugging purposes : keep track of the last person to enable the interrupts
    331329                __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");
    332334        }
    333335
     
    335337        // Don't execute any pending __cfactx_switch even if counter reaches 0
    336338        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
    337343                unsigned short prev = __cfaabi_tls.preemption_state.disable_count;
    338344                __cfaabi_tls.preemption_state.disable_count -= 1;
    339                 // If this triggers someone is enabled already enabled interrupts
    340                 /* paranoid */ verifyf( prev != 0u, "Incremented from %u\n", prev );
     345                verifyf( prev != 0u, "Incremented from %u\n", prev );                     // If this triggers someone is enabled already enabled interrupts
    341346                if( prev == 1 ) {
    342347                        #if GCC_VERSION > 50000
    343                                 static_assert(__atomic_always_lock_free(sizeof(__cfaabi_tls.preemption_state.enabled), &__cfaabi_tls.preemption_state.enabled), "Must be lock-free");
     348                        static_assert(__atomic_always_lock_free(sizeof(__cfaabi_tls.preemption_state.enabled), &__cfaabi_tls.preemption_state.enabled), "Must be lock-free");
    344349                        #endif
    345350                        // Set enabled flag to true
     
    351356                        __atomic_signal_fence(__ATOMIC_RELEASE);
    352357                }
    353         }
    354 }
    355 
    356 #undef __cfaasm_label
     358
     359                // create a assembler label after
     360                // marked as clobber all to avoid movement
     361                asm volatile("__cfaasm_nopoll_after:":::"memory");
     362        }
     363}
    357364
    358365// sigprocmask wrapper : unblock a single signal
     
    386393// reserved for future use
    387394static void timeout( $thread * this ) {
    388         #if !defined( __CFA_NO_STATISTICS__ )
    389                 kernelTLS().this_stats = this->curr_cluster->stats;
    390         #endif
    391395        unpark( this );
    392396}
     
    439443#elif defined( __aarch64__ )
    440444        #ifdef __PIC__
    441                 // Note that this works only for gcc
    442                 #define __cfaasm_label( label ) static struct asm_region label = \
     445                #define RELOC_TAG "@PLT"
     446        #else
     447                #define RELOC_TAG ""
     448        #endif
     449        #define __cfaasm_label( label ) \
    443450                ({ \
    444451                        struct asm_region region; \
    445452                        asm( \
    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" \
     453                                "mov %[vb], __cfaasm_" #label "_before@GOTPCREL(%%rip)"  "\n\t" \
     454                                "mov %[va], __cfaasm_" #label "_after@GOTPCREL(%%rip)"   "\n\t" \
    450455                                 : [vb]"=r"(region.before), [va]"=r"(region.after) \
    451456                        ); \
    452457                        region; \
    453458                });
    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
    471459#else
    472460        #error unknown hardware architecture
     
    482470        __cfaasm_label( check  );
    483471        __cfaasm_label( dsable );
     472        __cfaasm_label( enble );
     473        __cfaasm_label( nopoll );
    484474
    485475        // Check if preemption is safe
     
    488478        if( __cfaasm_in( ip, check  ) ) { ready = false; goto EXIT; };
    489479        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; };
    490482        if( !__cfaabi_tls.preemption_state.enabled) { ready = false; goto EXIT; };
    491483        if( __cfaabi_tls.preemption_state.in_progress ) { ready = false; goto EXIT; };
     
    614606        abort("SIGALRM should never reach the signal handler");
    615607}
     608
     609#if !defined(__CFA_NO_STATISTICS__)
     610        int __print_alarm_stats = 0;
     611#endif
    616612
    617613// Main of the alarm thread
     
    622618        id.id = doregister(&id);
    623619        __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
    624626
    625627        // Block sigalrms to control when they arrive
     
    681683        __cfaabi_dbg_print_safe( "Kernel : Preemption thread stopping\n" );
    682684        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
    683691        return 0p;
    684692}
Note: See TracChangeset for help on using the changeset viewer.