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