- File:
-
- 1 edited
-
libcfa/src/concurrency/preemption.cfa (modified) (12 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/preemption.cfa
r92bfda0 ra3821fa 15 15 16 16 #define __cforall_thread__ 17 // #define __CFA_DEBUG_PRINT_PREEMPTION__ 17 18 18 19 #include "preemption.hfa" … … 28 29 #include "kernel_private.hfa" 29 30 31 30 32 #if !defined(__CFA_DEFAULT_PREEMPTION__) 31 33 #define __CFA_DEFAULT_PREEMPTION__ 10`ms 32 34 #endif 33 35 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; 36 55 } 37 56 … … 98 117 //Loop throught every thing expired 99 118 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); 101 120 Duration period = node->period; 102 121 if( period == 0) { … … 104 123 } 105 124 125 __cfadbg_print_buffer_local( preemption, " KERNEL: alarm ticking node %p.\n", node ); 126 127 106 128 // Check if this is a kernel 107 129 if( node->type == Kernel ) { … … 109 131 } 110 132 else if( node->type == User ) { 133 __cfadbg_print_buffer_local( preemption, " KERNEL: alarm unparking %p.\n", node->thrd ); 111 134 timeout( node->thrd ); 112 135 } … … 117 140 // Check if this is a periodic alarm 118 141 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 ); 120 143 node->alarm = currtime + period; // Alarm is periodic, add currtime to it (used cached current time) 121 144 insert( alarms, node ); // Reinsert the node for the next time it triggers … … 125 148 // If there are still alarms pending, reset the timer 126 149 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);128 150 Duration delta = (*alarms)`first.alarm - currtime; 129 151 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 133 152 __kernel_set_timer( capped ); 134 153 } … … 296 315 // Enable interrupts by decrementing the counter 297 316 // If counter reaches 0, execute any pending __cfactx_switch 298 void enable_interrupts( __cfaabi_dbg_ctx_param) {317 void enable_interrupts( bool poll ) { 299 318 // Cache the processor now since interrupts can start happening after the atomic store 300 319 processor * proc = __cfaabi_tls.this_processor; 301 /* paranoid */ verify( proc );320 /* paranoid */ verify( !poll || proc ); 302 321 303 322 with( __cfaabi_tls.preemption_state ){ … … 321 340 // Signal the compiler that a fence is needed but only for signal handlers 322 341 __atomic_signal_fence(__ATOMIC_RELEASE); 323 if( p roc->pending_preemption ) {342 if( poll && proc->pending_preemption ) { 324 343 proc->pending_preemption = false; 325 344 force_yield( __POLL_PREEMPTION ); 326 345 } 327 346 } 328 }329 330 // For debugging purposes : keep track of the last person to enable the interrupts331 __cfaabi_dbg_debug_do( proc->last_enable = caller; )332 }333 334 // Disable interrupts by incrementint the counter335 // Don't execute any pending __cfactx_switch even if counter reaches 0336 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 interrupts340 /* paranoid */ verifyf( prev != 0u, "Incremented from %u\n", prev );341 if( prev == 1 ) {342 #if GCC_VERSION > 50000343 static_assert(__atomic_always_lock_free(sizeof(__cfaabi_tls.preemption_state.enabled), &__cfaabi_tls.preemption_state.enabled), "Must be lock-free");344 #endif345 // Set enabled flag to true346 // 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 requirements348 __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 handlers351 __atomic_signal_fence(__ATOMIC_RELEASE);352 347 } 353 348 } … … 585 580 586 581 // Setup proper signal handlers 587 __cfaabi_sigaction( SIGUSR1, sigHandler_ctxSwitch, SA_SIGINFO | SA_RESTART); // __cfactx_switch handler588 __cfaabi_sigaction( SIGALRM, sigHandler_alarm , SA_SIGINFO | SA_RESTART); // debug handler582 __cfaabi_sigaction( SIGUSR1, sigHandler_ctxSwitch, SA_SIGINFO ); // __cfactx_switch handler 583 __cfaabi_sigaction( SIGALRM, sigHandler_alarm , SA_SIGINFO ); // debug handler 589 584 590 585 signal_block( SIGALRM ); … … 689 684 } 690 685 691 #if !defined(__CFA_NO_STATISTICS__)692 int __print_alarm_stats = 0;693 #endif694 695 686 // Main of the alarm thread 696 687 // Waits on SIGALRM and send SIGUSR1 to whom ever needs it 697 688 static void * alarm_loop( __attribute__((unused)) void * args ) { 698 689 __processor_id_t id; 699 id.full_proc = false; 700 id.id = doregister(&id); 690 register_proc_id(&id); 701 691 __cfaabi_tls.this_proc_id = &id; 702 692 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 #endif708 693 709 694 // Block sigalrms to control when they arrive … … 764 749 EXIT: 765 750 __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 773 753 return 0p; 774 754 }
Note:
See TracChangeset
for help on using the changeset viewer.