- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/libcfa/concurrency/preemption.c
r381fdee rb69ea6b 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 1 4:42:34201813 // Update Count : 2512 // Last Modified On : Fri Feb 9 16:38:13 2018 13 // Update Count : 14 14 14 // 15 15 … … 67 67 } 68 68 69 enum { 70 PREEMPT_NORMAL = 0, 71 PREEMPT_TERMINATE = 1, 72 }; 73 69 74 //============================================================================================= 70 75 // Kernel Preemption logic … … 144 149 // Disable interrupts by incrementing the counter 145 150 void disable_interrupts() { 146 preemption _enabled = false;147 __attribute__((unused)) unsigned short new_val = disable_preempt_count + 1;148 disable_preempt_count = new_val;151 preemption.enabled = false; 152 __attribute__((unused)) unsigned short new_val = preemption.disable_count + 1; 153 preemption.disable_count = new_val; 149 154 verify( new_val < 65_000u ); // If this triggers someone is disabling interrupts without enabling them 150 155 } … … 156 161 thread_desc * thrd = this_thread; // Cache the thread now since interrupts can start happening after the atomic add 157 162 158 unsigned short prev = disable_preempt_count;159 disable_preempt_count -= 1;163 unsigned short prev = preemption.disable_count; 164 preemption.disable_count -= 1; 160 165 verify( prev != 0u ); // If this triggers someone is enabled already enabled interruptsverify( prev != 0u ); 161 166 162 167 // Check if we need to prempt the thread because an interrupt was missed 163 168 if( prev == 1 ) { 164 preemption _enabled = true;169 preemption.enabled = true; 165 170 if( proc->pending_preemption ) { 166 171 proc->pending_preemption = false; … … 176 181 // Don't execute any pending CtxSwitch even if counter reaches 0 177 182 void enable_interrupts_noPoll() { 178 unsigned short prev = disable_preempt_count;179 disable_preempt_count -= 1;183 unsigned short prev = preemption.disable_count; 184 preemption.disable_count -= 1; 180 185 verifyf( prev != 0u, "Incremented from %u\n", prev ); // If this triggers someone is enabled already enabled interrupts 181 186 if( prev == 1 ) { 182 preemption _enabled = true;187 preemption.enabled = true; 183 188 } 184 189 } … … 192 197 193 198 if ( pthread_sigmask( SIG_UNBLOCK, &mask, NULL ) == -1 ) { 194 abort f( "internal error, pthread_sigmask" );199 abort( "internal error, pthread_sigmask" ); 195 200 } 196 201 } … … 203 208 204 209 if ( pthread_sigmask( SIG_BLOCK, &mask, NULL ) == -1 ) { 205 abort f( "internal error, pthread_sigmask" );210 abort( "internal error, pthread_sigmask" ); 206 211 } 207 212 } … … 209 214 // kill wrapper : signal a processor 210 215 static void preempt( processor * this ) { 211 pthread_kill( this->kernel_thread, SIGUSR1 ); 216 sigval_t value = { PREEMPT_NORMAL }; 217 pthread_sigqueue( this->kernel_thread, SIGUSR1, value ); 218 } 219 220 // kill wrapper : signal a processor 221 void terminate(processor * this) { 222 this->do_terminate = true; 223 sigval_t value = { PREEMPT_TERMINATE }; 224 pthread_sigqueue( this->kernel_thread, SIGUSR1, value ); 212 225 } 213 226 … … 222 235 // If false : preemption is unsafe and marked as pending 223 236 static inline bool preemption_ready() { 224 bool ready = preemption _enabled && !preemption_in_progress; // Check if preemption is safe237 bool ready = preemption.enabled && !preemption.in_progress; // Check if preemption is safe 225 238 this_processor->pending_preemption = !ready; // Adjust the pending flag accordingly 226 239 return ready; … … 234 247 // Called from kernel_startup 235 248 void kernel_start_preemption() { 236 __cfaabi_dbg_print_safe( "Kernel : Starting preemption\n");249 __cfaabi_dbg_print_safe( "Kernel : Starting preemption\n" ); 237 250 238 251 // Start with preemption disabled until ready 239 preemption _enabled = false;240 disable_preempt_count = 1;252 preemption.enabled = false; 253 preemption.disable_count = 1; 241 254 242 255 // Initialize the event kernel … … 255 268 // Called from kernel_shutdown 256 269 void kernel_stop_preemption() { 257 __cfaabi_dbg_print_safe( "Kernel : Preemption stopping\n");270 __cfaabi_dbg_print_safe( "Kernel : Preemption stopping\n" ); 258 271 259 272 // Block all signals since we are already shutting down … … 271 284 // Preemption is now fully stopped 272 285 273 __cfaabi_dbg_print_safe( "Kernel : Preemption stopped\n");286 __cfaabi_dbg_print_safe( "Kernel : Preemption stopped\n" ); 274 287 } 275 288 … … 277 290 // Used by thread to control when they want to receive preemption signals 278 291 void ?{}( preemption_scope & this, processor * proc ) { 279 (this.alarm){ proc, zero_time, zero_time};292 (this.alarm){ proc, 0`cfa_s, 0`cfa_s }; 280 293 this.proc = proc; 281 294 this.proc->preemption_alarm = &this.alarm; … … 287 300 disable_interrupts(); 288 301 289 update_preemption( this.proc, zero_time);302 update_preemption( this.proc, 0`cfa_s ); 290 303 } 291 304 … … 299 312 __cfaabi_dbg_debug_do( last_interrupt = (void *)(cxt->uc_mcontext.CFA_REG_IP); ) 300 313 314 // SKULLDUGGERY: if a thread creates a processor and the immediately deletes it, 315 // the interrupt that is supposed to force the kernel thread to preempt might arrive 316 // before the kernel thread has even started running. When that happens an iterrupt 317 // we a null 'this_processor' will be caught, just ignore it. 318 if(!this_processor) return; 319 320 choose(sfp->si_value.sival_int) { 321 case PREEMPT_NORMAL : ;// Normal case, nothing to do here 322 case PREEMPT_TERMINATE: verify(this_processor->do_terminate); 323 default: 324 abort( "internal error, signal value is %d", sfp->si_value.sival_int ); 325 } 326 301 327 // Check if it is safe to preempt here 302 328 if( !preemption_ready() ) { return; } 303 329 304 __cfaabi_dbg_print_buffer_decl( " KERNEL: preempting core %p (%p).\n", this_processor, this_thread);305 306 preemption _in_progress = true; // Sync flag : prevent recursive calls to the signal handler330 __cfaabi_dbg_print_buffer_decl( " KERNEL: preempting core %p (%p).\n", this_processor, this_thread); 331 332 preemption.in_progress = true; // Sync flag : prevent recursive calls to the signal handler 307 333 signal_unblock( SIGUSR1 ); // We are about to CtxSwitch out of the signal handler, let other handlers in 308 preemption _in_progress = false; // Clear the in progress flag334 preemption.in_progress = false; // Clear the in progress flag 309 335 310 336 // Preemption can occur here … … 322 348 323 349 if ( pthread_sigmask( SIG_BLOCK, &mask, NULL ) == -1 ) { 324 abort f( "internal error, pthread_sigmask" );350 abort( "internal error, pthread_sigmask" ); 325 351 } 326 352 … … 339 365 continue; 340 366 case EINVAL : 341 abort f("Timeout was invalid.");367 abort( "Timeout was invalid." ); 342 368 default: 343 abort f("Unhandled error %d", err);369 abort( "Unhandled error %d", err); 344 370 } 345 371 } … … 348 374 assertf(sig == SIGALRM, "Kernel Internal Error, sigwait: Unexpected signal %d (%d : %d)\n", sig, info.si_code, info.si_value.sival_int); 349 375 350 // __cfaabi_dbg_print_safe( "Kernel : Caught alarm from %d with %d\n", info.si_code, info.si_value.sival_int );376 // __cfaabi_dbg_print_safe( "Kernel : Caught alarm from %d with %d\n", info.si_code, info.si_value.sival_int ); 351 377 // Switch on the code (a.k.a. the sender) to 352 378 switch( info.si_code ) … … 356 382 case SI_TIMER: 357 383 case SI_KERNEL: 358 // __cfaabi_dbg_print_safe( "Kernel : Preemption thread tick\n");384 // __cfaabi_dbg_print_safe( "Kernel : Preemption thread tick\n" ); 359 385 lock( event_kernel->lock __cfaabi_dbg_ctx2 ); 360 386 tick_preemption(); … … 370 396 371 397 EXIT: 372 __cfaabi_dbg_print_safe( "Kernel : Preemption thread stopping\n");398 __cfaabi_dbg_print_safe( "Kernel : Preemption thread stopping\n" ); 373 399 return NULL; 374 400 }
Note:
See TracChangeset
for help on using the changeset viewer.