Changeset 32cab5b for src/libcfa/concurrency/preemption.c
- Timestamp:
- Apr 17, 2018, 12:01:09 PM (7 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, with_gc
- Children:
- 3265399
- Parents:
- b2fe1c9 (diff), 81bb114 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/libcfa/concurrency/preemption.c
rb2fe1c9 r32cab5b 10 10 // Created On : Mon Jun 5 14:20:42 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Feb 9 16:38:13201813 // Update Count : 1412 // Last Modified On : Mon Apr 9 13:52:39 2018 13 // Update Count : 36 14 14 // 15 15 … … 23 23 } 24 24 25 #include "bits/cfatime.h"26 25 #include "bits/signal.h" 27 26 28 27 #if !defined(__CFA_DEFAULT_PREEMPTION__) 29 #define __CFA_DEFAULT_PREEMPTION__ 10` cfa_ms28 #define __CFA_DEFAULT_PREEMPTION__ 10`ms 30 29 #endif 31 30 32 __cfa_time_tdefault_preemption() __attribute__((weak)) {31 Duration default_preemption() __attribute__((weak)) { 33 32 return __CFA_DEFAULT_PREEMPTION__; 34 33 } … … 78 77 79 78 // Get next expired node 80 static inline alarm_node_t * get_expired( alarm_list_t * alarms, __cfa_time_tcurrtime ) {79 static inline alarm_node_t * get_expired( alarm_list_t * alarms, Time currtime ) { 81 80 if( !alarms->head ) return NULL; // If no alarms return null 82 81 if( alarms->head->alarm >= currtime ) return NULL; // If alarms head not expired return null … … 88 87 alarm_node_t * node = NULL; // Used in the while loop but cannot be declared in the while condition 89 88 alarm_list_t * alarms = &event_kernel->alarms; // Local copy for ease of reading 90 __cfa_time_t currtime = __kernel_get_time();// Check current time once so we everything "happens at once"89 Time currtime = __kernel_get_time(); // Check current time once so we everything "happens at once" 91 90 92 91 //Loop throught every thing expired … … 102 101 103 102 // Check if this is a periodic alarm 104 __cfa_time_tperiod = node->period;103 Duration period = node->period; 105 104 if( period > 0 ) { 106 105 node->alarm = currtime + period; // Alarm is periodic, add currtime to it (used cached current time) … … 117 116 118 117 // Update the preemption of a processor and notify interested parties 119 void update_preemption( processor * this, __cfa_time_tduration ) {118 void update_preemption( processor * this, Duration duration ) { 120 119 alarm_node_t * alarm = this->preemption_alarm; 121 120 122 121 // Alarms need to be enabled 123 if ( duration > 0 && ! alarm->set ) {122 if ( duration > 0 && ! alarm->set ) { 124 123 alarm->alarm = __kernel_get_time() + duration; 125 124 alarm->period = duration; 126 125 register_self( alarm ); 127 126 } 128 // Zero dura ction but alarm is set127 // Zero duration but alarm is set 129 128 else if ( duration == 0 && alarm->set ) { 130 129 unregister_self( alarm ); … … 150 149 // Disable interrupts by incrementing the counter 151 150 void disable_interrupts() { 152 preemption_state.enabled = false;153 __attribute__((unused)) unsigned short new_val = preemption_state.disable_count + 1;154 preemption_state.disable_count = new_val;151 TL_GET( preemption_state ).enabled = false; 152 __attribute__((unused)) unsigned short new_val = TL_GET( preemption_state ).disable_count + 1; 153 TL_GET( preemption_state ).disable_count = new_val; 155 154 verify( new_val < 65_000u ); // If this triggers someone is disabling interrupts without enabling them 156 155 } … … 159 158 // If counter reaches 0, execute any pending CtxSwitch 160 159 void enable_interrupts( __cfaabi_dbg_ctx_param ) { 161 processor * proc = this_processor;// Cache the processor now since interrupts can start happening after the atomic add162 thread_desc * thrd = this_thread;// Cache the thread now since interrupts can start happening after the atomic add163 164 unsigned short prev = preemption_state.disable_count;165 preemption_state.disable_count -= 1;160 processor * proc = TL_GET( this_processor ); // Cache the processor now since interrupts can start happening after the atomic add 161 thread_desc * thrd = TL_GET( this_thread ); // Cache the thread now since interrupts can start happening after the atomic add 162 163 unsigned short prev = TL_GET( preemption_state ).disable_count; 164 TL_GET( preemption_state ).disable_count -= 1; 166 165 verify( prev != 0u ); // If this triggers someone is enabled already enabled interruptsverify( prev != 0u ); 167 166 168 167 // Check if we need to prempt the thread because an interrupt was missed 169 168 if( prev == 1 ) { 170 preemption_state.enabled = true;169 TL_GET( preemption_state ).enabled = true; 171 170 if( proc->pending_preemption ) { 172 171 proc->pending_preemption = false; … … 182 181 // Don't execute any pending CtxSwitch even if counter reaches 0 183 182 void enable_interrupts_noPoll() { 184 unsigned short prev = preemption_state.disable_count;185 preemption_state.disable_count -= 1;183 unsigned short prev = TL_GET( preemption_state ).disable_count; 184 TL_GET( preemption_state ).disable_count -= 1; 186 185 verifyf( prev != 0u, "Incremented from %u\n", prev ); // If this triggers someone is enabled already enabled interrupts 187 186 if( prev == 1 ) { 188 preemption_state.enabled = true;187 TL_GET( preemption_state ).enabled = true; 189 188 } 190 189 } … … 236 235 // If false : preemption is unsafe and marked as pending 237 236 static inline bool preemption_ready() { 238 bool ready = preemption_state.enabled && !preemption_state.in_progress; // Check if preemption is safe239 this_processor->pending_preemption = !ready;// Adjust the pending flag accordingly237 bool ready = TL_GET( preemption_state ).enabled && !TL_GET( preemption_state ).in_progress; // Check if preemption is safe 238 TL_GET( this_processor )->pending_preemption = !ready; // Adjust the pending flag accordingly 240 239 return ready; 241 240 } … … 251 250 252 251 // Start with preemption disabled until ready 253 preemption_state.enabled = false;254 preemption_state.disable_count = 1;252 TL_GET( preemption_state ).enabled = false; 253 TL_GET( preemption_state ).disable_count = 1; 255 254 256 255 // Initialize the event kernel … … 291 290 // Used by thread to control when they want to receive preemption signals 292 291 void ?{}( preemption_scope & this, processor * proc ) { 293 (this.alarm){ proc, 0`cfa_s, 0`cfa_s };292 (this.alarm){ proc, (Time){ 0 }, 0`s }; 294 293 this.proc = proc; 295 294 this.proc->preemption_alarm = &this.alarm; … … 301 300 disable_interrupts(); 302 301 303 update_preemption( this.proc, 0` cfa_s );302 update_preemption( this.proc, 0`s ); 304 303 } 305 304 … … 317 316 // before the kernel thread has even started running. When that happens an iterrupt 318 317 // we a null 'this_processor' will be caught, just ignore it. 319 if(! this_processor) return;318 if(!TL_GET( this_processor )) return; 320 319 321 320 choose(sfp->si_value.sival_int) { 322 321 case PREEMPT_NORMAL : ;// Normal case, nothing to do here 323 case PREEMPT_TERMINATE: verify( this_processor->do_terminate);322 case PREEMPT_TERMINATE: verify(TL_GET( this_processor )->do_terminate); 324 323 default: 325 324 abort( "internal error, signal value is %d", sfp->si_value.sival_int ); … … 331 330 __cfaabi_dbg_print_buffer_decl( " KERNEL: preempting core %p (%p).\n", this_processor, this_thread); 332 331 333 preemption_state.in_progress = true;// Sync flag : prevent recursive calls to the signal handler332 TL_GET( preemption_state ).in_progress = true; // Sync flag : prevent recursive calls to the signal handler 334 333 signal_unblock( SIGUSR1 ); // We are about to CtxSwitch out of the signal handler, let other handlers in 335 preemption_state.in_progress = false;// Clear the in progress flag334 TL_GET( preemption_state ).in_progress = false; // Clear the in progress flag 336 335 337 336 // Preemption can occur here 338 337 339 BlockInternal( (thread_desc*) this_thread );// Do the actual CtxSwitch338 BlockInternal( (thread_desc*)TL_GET( this_thread ) ); // Do the actual CtxSwitch 340 339 } 341 340
Note:
See TracChangeset
for help on using the changeset viewer.