Ignore:
File:
1 edited

Legend:

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

    ra12810d 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
     
    405412                #define RELOC_SUFFIX ""
    406413        #endif
    407         #define __cfaasm_label( label ) struct asm_region label = \
     414        #define __cfaasm_label( label ) static struct asm_region label = \
    408415                ({ \
    409416                        struct asm_region region; \
     
    424431                #define RELOC_SUFFIX ""
    425432        #endif
    426         #define __cfaasm_label( label ) struct asm_region label = \
     433        #define __cfaasm_label( label ) static struct asm_region label = \
    427434                ({ \
    428435                        struct asm_region region; \
     
    436443#elif defined( __aarch64__ )
    437444        #ifdef __PIC__
    438                 // Note that this works only for gcc
    439                 #define __cfaasm_label( label ) struct asm_region label = \
     445                #define RELOC_TAG "@PLT"
     446        #else
     447                #define RELOC_TAG ""
     448        #endif
     449        #define __cfaasm_label( label ) \
    440450                ({ \
    441451                        struct asm_region region; \
    442452                        asm( \
    443                                 "adrp %[vb], _GLOBAL_OFFSET_TABLE_"                              "\n\t" \
    444                                 "ldr  %[vb], [%[vb], #:gotpage_lo15:__cfaasm_" #label "_before]" "\n\t" \
    445                                 "adrp %[va], _GLOBAL_OFFSET_TABLE_"                              "\n\t" \
    446                                 "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" \
    447455                                 : [vb]"=r"(region.before), [va]"=r"(region.after) \
    448456                        ); \
    449457                        region; \
    450458                });
    451         #else
    452                 #error this is not the right thing to do
    453                 /*
    454                 #define __cfaasm_label( label ) struct asm_region label = \
    455                 ({ \
    456                         struct asm_region region; \
    457                         asm( \
    458                                 "adrp %[vb], __cfaasm_" #label "_before"              "\n\t" \
    459                                 "add  %[vb], %[vb], :lo12:__cfaasm_" #label "_before" "\n\t" \
    460                                 "adrp %[va], :got:__cfaasm_" #label "_after"          "\n\t" \
    461                                 "add  %[va], %[va], :lo12:__cfaasm_" #label "_after"  "\n\t" \
    462                                  : [vb]"=r"(region.before), [va]"=r"(region.after) \
    463                         ); \
    464                         region; \
    465                 });
    466                 */
    467         #endif
    468459#else
    469460        #error unknown hardware architecture
     
    479470        __cfaasm_label( check  );
    480471        __cfaasm_label( dsable );
     472        __cfaasm_label( enble );
     473        __cfaasm_label( nopoll );
    481474
    482475        // Check if preemption is safe
     
    485478        if( __cfaasm_in( ip, check  ) ) { ready = false; goto EXIT; };
    486479        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; };
    487482        if( !__cfaabi_tls.preemption_state.enabled) { ready = false; goto EXIT; };
    488483        if( __cfaabi_tls.preemption_state.in_progress ) { ready = false; goto EXIT; };
Note: See TracChangeset for help on using the changeset viewer.