Ignore:
File:
1 edited

Legend:

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

    ra3821fa r92bfda0  
    1515
    1616#define __cforall_thread__
    17 // #define __CFA_DEBUG_PRINT_PREEMPTION__
    1817
    1918#include "preemption.hfa"
     
    2928#include "kernel_private.hfa"
    3029
    31 
    3230#if !defined(__CFA_DEFAULT_PREEMPTION__)
    3331#define __CFA_DEFAULT_PREEMPTION__ 10`ms
    3432#endif
    3533
    36 __attribute__((weak)) Duration default_preemption() {
    37         const char * preempt_rate_s = getenv("CFA_DEFAULT_PREEMPTION");
    38         if(!preempt_rate_s) {
    39                 __cfadbg_print_safe(preemption, "No CFA_DEFAULT_PREEMPTION in ENV\n");
    40                 return __CFA_DEFAULT_PREEMPTION__;
    41         }
    42 
    43         char * endptr = 0p;
    44         long int preempt_rate_l = strtol(preempt_rate_s, &endptr, 10);
    45         if(preempt_rate_l < 0 || preempt_rate_l > 65535) {
    46                 __cfadbg_print_safe(preemption, "CFA_DEFAULT_PREEMPTION out of range : %ld\n", preempt_rate_l);
    47                 return __CFA_DEFAULT_PREEMPTION__;
    48         }
    49         if('\0' != *endptr) {
    50                 __cfadbg_print_safe(preemption, "CFA_DEFAULT_PREEMPTION not a decimal number : %s\n", preempt_rate_s);
    51                 return __CFA_DEFAULT_PREEMPTION__;
    52         }
    53 
    54         return preempt_rate_l`ms;
     34Duration default_preemption() __attribute__((weak)) {
     35        return __CFA_DEFAULT_PREEMPTION__;
    5536}
    5637
     
    11798        //Loop throught every thing expired
    11899        while( node = get_expired( alarms, currtime ) ) {
    119                 __cfadbg_print_buffer_decl( preemption, " KERNEL: preemption tick %lu\n", currtime.tn);
     100                // __cfaabi_dbg_print_buffer_decl( " KERNEL: preemption tick.\n" );
    120101                Duration period = node->period;
    121102                if( period == 0) {
     
    123104                }
    124105
    125                 __cfadbg_print_buffer_local( preemption, " KERNEL: alarm ticking node %p.\n", node );
    126 
    127 
    128106                // Check if this is a kernel
    129107                if( node->type == Kernel ) {
     
    131109                }
    132110                else if( node->type == User ) {
    133                         __cfadbg_print_buffer_local( preemption, " KERNEL: alarm unparking %p.\n", node->thrd );
    134111                        timeout( node->thrd );
    135112                }
     
    140117                // Check if this is a periodic alarm
    141118                if( period > 0 ) {
    142                         __cfadbg_print_buffer_local( preemption, " KERNEL: alarm period is %lu.\n", period`ns );
     119                        // __cfaabi_dbg_print_buffer_local( " KERNEL: alarm period is %lu.\n", period.tv );
    143120                        node->alarm = currtime + period;    // Alarm is periodic, add currtime to it (used cached current time)
    144121                        insert( alarms, node );             // Reinsert the node for the next time it triggers
     
    148125        // If there are still alarms pending, reset the timer
    149126        if( & (*alarms)`first ) {
     127                __cfadbg_print_buffer_decl(preemption, " KERNEL: @%ju(%ju) resetting alarm to %ju.\n", currtime.tv, __kernel_get_time().tv, (alarms->head->alarm - currtime).tv);
    150128                Duration delta = (*alarms)`first.alarm - currtime;
    151129                Duration capped = max(delta, 50`us);
     130                // itimerval tim  = { caped };
     131                // __cfaabi_dbg_print_buffer_local( "    Values are %lu, %lu, %lu %lu.\n", delta.tv, caped.tv, tim.it_value.tv_sec, tim.it_value.tv_usec);
     132
    152133                __kernel_set_timer( capped );
    153134        }
     
    315296        // Enable interrupts by decrementing the counter
    316297        // If counter reaches 0, execute any pending __cfactx_switch
    317         void enable_interrupts( bool poll ) {
     298        void enable_interrupts( __cfaabi_dbg_ctx_param ) {
    318299                // Cache the processor now since interrupts can start happening after the atomic store
    319300                processor   * proc = __cfaabi_tls.this_processor;
    320                 /* paranoid */ verify( !poll || proc );
     301                /* paranoid */ verify( proc );
    321302
    322303                with( __cfaabi_tls.preemption_state ){
     
    340321                                // Signal the compiler that a fence is needed but only for signal handlers
    341322                                __atomic_signal_fence(__ATOMIC_RELEASE);
    342                                 if( poll && proc->pending_preemption ) {
     323                                if( proc->pending_preemption ) {
    343324                                        proc->pending_preemption = false;
    344325                                        force_yield( __POLL_PREEMPTION );
    345326                                }
    346327                        }
     328                }
     329
     330                // For debugging purposes : keep track of the last person to enable the interrupts
     331                __cfaabi_dbg_debug_do( proc->last_enable = caller; )
     332        }
     333
     334        // Disable interrupts by incrementint the counter
     335        // Don't execute any pending __cfactx_switch even if counter reaches 0
     336        void enable_interrupts_noPoll() {
     337                unsigned short prev = __cfaabi_tls.preemption_state.disable_count;
     338                __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 );
     341                if( prev == 1 ) {
     342                        #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");
     344                        #endif
     345                        // Set enabled flag to true
     346                        // should be atomic to avoid preemption in the middle of the operation.
     347                        // use memory order RELAXED since there is no inter-thread on this variable requirements
     348                        __atomic_store_n(&__cfaabi_tls.preemption_state.enabled, true, __ATOMIC_RELAXED);
     349
     350                        // Signal the compiler that a fence is needed but only for signal handlers
     351                        __atomic_signal_fence(__ATOMIC_RELEASE);
    347352                }
    348353        }
     
    580585
    581586        // Setup proper signal handlers
    582         __cfaabi_sigaction( SIGUSR1, sigHandler_ctxSwitch, SA_SIGINFO ); // __cfactx_switch handler
    583         __cfaabi_sigaction( SIGALRM, sigHandler_alarm    , SA_SIGINFO ); // debug handler
     587        __cfaabi_sigaction( SIGUSR1, sigHandler_ctxSwitch, SA_SIGINFO | SA_RESTART ); // __cfactx_switch handler
     588        __cfaabi_sigaction( SIGALRM, sigHandler_alarm    , SA_SIGINFO | SA_RESTART ); // debug handler
    584589
    585590        signal_block( SIGALRM );
     
    684689}
    685690
     691#if !defined(__CFA_NO_STATISTICS__)
     692        int __print_alarm_stats = 0;
     693#endif
     694
    686695// Main of the alarm thread
    687696// Waits on SIGALRM and send SIGUSR1 to whom ever needs it
    688697static void * alarm_loop( __attribute__((unused)) void * args ) {
    689698        __processor_id_t id;
    690         register_proc_id(&id);
     699        id.full_proc = false;
     700        id.id = doregister(&id);
    691701        __cfaabi_tls.this_proc_id = &id;
    692702
     703        #if !defined(__CFA_NO_STATISTICS__)
     704                struct __stats_t local_stats;
     705                __cfaabi_tls.this_stats = &local_stats;
     706                __init_stats( &local_stats );
     707        #endif
    693708
    694709        // Block sigalrms to control when they arrive
     
    749764EXIT:
    750765        __cfaabi_dbg_print_safe( "Kernel : Preemption thread stopping\n" );
    751         register_proc_id(&id);
    752 
     766        unregister(&id);
     767
     768        #if !defined(__CFA_NO_STATISTICS__)
     769                if( 0 != __print_alarm_stats ) {
     770                        __print_stats( &local_stats, __print_alarm_stats, "Alarm", "Thread", 0p );
     771                }
     772        #endif
    753773        return 0p;
    754774}
Note: See TracChangeset for help on using the changeset viewer.