Ignore:
File:
1 edited

Legend:

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

    r92bfda0 ra3821fa  
    1515
    1616#define __cforall_thread__
     17// #define __CFA_DEBUG_PRINT_PREEMPTION__
    1718
    1819#include "preemption.hfa"
     
    2829#include "kernel_private.hfa"
    2930
     31
    3032#if !defined(__CFA_DEFAULT_PREEMPTION__)
    3133#define __CFA_DEFAULT_PREEMPTION__ 10`ms
    3234#endif
    3335
    34 Duration default_preemption() __attribute__((weak)) {
    35         return __CFA_DEFAULT_PREEMPTION__;
     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;
    3655}
    3756
     
    98117        //Loop throught every thing expired
    99118        while( node = get_expired( alarms, currtime ) ) {
    100                 // __cfaabi_dbg_print_buffer_decl( " KERNEL: preemption tick.\n" );
     119                __cfadbg_print_buffer_decl( preemption, " KERNEL: preemption tick %lu\n", currtime.tn);
    101120                Duration period = node->period;
    102121                if( period == 0) {
     
    104123                }
    105124
     125                __cfadbg_print_buffer_local( preemption, " KERNEL: alarm ticking node %p.\n", node );
     126
     127
    106128                // Check if this is a kernel
    107129                if( node->type == Kernel ) {
     
    109131                }
    110132                else if( node->type == User ) {
     133                        __cfadbg_print_buffer_local( preemption, " KERNEL: alarm unparking %p.\n", node->thrd );
    111134                        timeout( node->thrd );
    112135                }
     
    117140                // Check if this is a periodic alarm
    118141                if( period > 0 ) {
    119                         // __cfaabi_dbg_print_buffer_local( " KERNEL: alarm period is %lu.\n", period.tv );
     142                        __cfadbg_print_buffer_local( preemption, " KERNEL: alarm period is %lu.\n", period`ns );
    120143                        node->alarm = currtime + period;    // Alarm is periodic, add currtime to it (used cached current time)
    121144                        insert( alarms, node );             // Reinsert the node for the next time it triggers
     
    125148        // If there are still alarms pending, reset the timer
    126149        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);
    128150                Duration delta = (*alarms)`first.alarm - currtime;
    129151                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 
    133152                __kernel_set_timer( capped );
    134153        }
     
    296315        // Enable interrupts by decrementing the counter
    297316        // If counter reaches 0, execute any pending __cfactx_switch
    298         void enable_interrupts( __cfaabi_dbg_ctx_param ) {
     317        void enable_interrupts( bool poll ) {
    299318                // Cache the processor now since interrupts can start happening after the atomic store
    300319                processor   * proc = __cfaabi_tls.this_processor;
    301                 /* paranoid */ verify( proc );
     320                /* paranoid */ verify( !poll || proc );
    302321
    303322                with( __cfaabi_tls.preemption_state ){
     
    321340                                // Signal the compiler that a fence is needed but only for signal handlers
    322341                                __atomic_signal_fence(__ATOMIC_RELEASE);
    323                                 if( proc->pending_preemption ) {
     342                                if( poll && proc->pending_preemption ) {
    324343                                        proc->pending_preemption = false;
    325344                                        force_yield( __POLL_PREEMPTION );
    326345                                }
    327346                        }
    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);
    352347                }
    353348        }
     
    585580
    586581        // Setup proper signal handlers
    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
     582        __cfaabi_sigaction( SIGUSR1, sigHandler_ctxSwitch, SA_SIGINFO ); // __cfactx_switch handler
     583        __cfaabi_sigaction( SIGALRM, sigHandler_alarm    , SA_SIGINFO ); // debug handler
    589584
    590585        signal_block( SIGALRM );
     
    689684}
    690685
    691 #if !defined(__CFA_NO_STATISTICS__)
    692         int __print_alarm_stats = 0;
    693 #endif
    694 
    695686// Main of the alarm thread
    696687// Waits on SIGALRM and send SIGUSR1 to whom ever needs it
    697688static void * alarm_loop( __attribute__((unused)) void * args ) {
    698689        __processor_id_t id;
    699         id.full_proc = false;
    700         id.id = doregister(&id);
     690        register_proc_id(&id);
    701691        __cfaabi_tls.this_proc_id = &id;
    702692
    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
    708693
    709694        // Block sigalrms to control when they arrive
     
    764749EXIT:
    765750        __cfaabi_dbg_print_safe( "Kernel : Preemption thread stopping\n" );
    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
     751        register_proc_id(&id);
     752
    773753        return 0p;
    774754}
Note: See TracChangeset for help on using the changeset viewer.