- File:
-
- 1 edited
-
libcfa/src/concurrency/kernel.cfa (modified) (13 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/kernel.cfa
rb4b63e8 r58688bf 108 108 static $thread * __next_thread_slow(cluster * this); 109 109 static void __run_thread(processor * this, $thread * dst); 110 static void __wake_one( struct __processor_id_t * id,cluster * cltr);110 static void __wake_one(cluster * cltr); 111 111 112 112 static void push (__cluster_idles & idles, processor & proc); … … 252 252 /* paranoid */ verify( kernelTLS.this_thread == thrd_dst ); 253 253 /* paranoid */ verify( thrd_dst->context.SP ); 254 /* paranoid */ verify( thrd_dst->state != Halted ); 254 255 /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) < ((uintptr_t)__get_stack(thrd_dst->curr_cor)->base ) || thrd_dst->curr_cor == proc_cor, "ERROR : Destination $thread %p has been corrupted.\n StackPointer too small.\n", thrd_dst ); // add escape condition if we are setting up the processor 255 256 /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) > ((uintptr_t)__get_stack(thrd_dst->curr_cor)->limit) || thrd_dst->curr_cor == proc_cor, "ERROR : Destination $thread %p has been corrupted.\n StackPointer too large.\n", thrd_dst ); // add escape condition if we are setting up the processor … … 281 282 if(unlikely(thrd_dst->preempted != __NO_PREEMPTION)) { 282 283 // The thread was preempted, reschedule it and reset the flag 283 __schedule_thread( (__processor_id_t*)this,thrd_dst );284 __schedule_thread( thrd_dst ); 284 285 break RUNNING; 285 286 } … … 287 288 if(unlikely(thrd_dst->state == Halted)) { 288 289 // The thread has halted, it should never be scheduled/run again 289 // We may need to wake someone up here since 290 unpark( this->destroyer ); 291 this->destroyer = 0p; 290 // finish the thread 291 __thread_finish( thrd_dst ); 292 292 break RUNNING; 293 293 } … … 299 299 int old_ticket = __atomic_fetch_sub(&thrd_dst->ticket, 1, __ATOMIC_SEQ_CST); 300 300 switch(old_ticket) { 301 case 1:301 case TICKET_RUNNING: 302 302 // This is case 1, the regular case, nothing more is needed 303 303 break RUNNING; 304 case 2:304 case TICKET_UNBLOCK: 305 305 // This is case 2, the racy case, someone tried to run this thread before it finished blocking 306 306 // In this case, just run it again. … … 358 358 // Scheduler routines 359 359 // KERNEL ONLY 360 void __schedule_thread( struct __processor_id_t * id,$thread * thrd ) {360 void __schedule_thread( $thread * thrd ) { 361 361 /* paranoid */ verify( thrd ); 362 362 /* paranoid */ verify( thrd->state != Halted ); 363 363 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 364 /* paranoid */ verify( kernelTLS.this_proc_id ); 364 365 /* paranoid */ #if defined( __CFA_WITH_VERIFY__ ) 365 366 /* paranoid */ if( thrd->state == Blocked || thrd->state == Start ) assertf( thrd->preempted == __NO_PREEMPTION, … … 374 375 if (thrd->preempted == __NO_PREEMPTION) thrd->state = Ready; 375 376 376 ready_schedule_lock ( id);377 ready_schedule_lock(); 377 378 push( thrd->curr_cluster, thrd ); 378 __wake_one( id,thrd->curr_cluster);379 ready_schedule_unlock( id);379 __wake_one(thrd->curr_cluster); 380 ready_schedule_unlock(); 380 381 381 382 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); … … 384 385 // KERNEL ONLY 385 386 static inline $thread * __next_thread(cluster * this) with( *this ) { 386 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 387 388 ready_schedule_lock ( (__processor_id_t*)kernelTLS.this_processor ); 387 /* paranoid */ verify( kernelTLS.this_proc_id ); 388 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 389 390 ready_schedule_lock(); 389 391 $thread * thrd = pop( this ); 390 ready_schedule_unlock( (__processor_id_t*)kernelTLS.this_processor ); 391 392 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 392 ready_schedule_unlock(); 393 394 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 395 /* paranoid */ verify( kernelTLS.this_proc_id ); 393 396 return thrd; 394 397 } … … 396 399 // KERNEL ONLY 397 400 static inline $thread * __next_thread_slow(cluster * this) with( *this ) { 398 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 399 400 ready_schedule_lock ( (__processor_id_t*)kernelTLS.this_processor ); 401 /* paranoid */ verify( kernelTLS.this_proc_id ); 402 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 403 404 ready_schedule_lock(); 401 405 $thread * thrd = pop_slow( this ); 402 ready_schedule_unlock( (__processor_id_t*)kernelTLS.this_processor ); 403 404 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 406 ready_schedule_unlock(); 407 408 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 409 /* paranoid */ verify( kernelTLS.this_proc_id ); 405 410 return thrd; 406 411 } 407 412 408 // KERNEL ONLY unpark with out disabling interrupts 409 void __unpark( struct __processor_id_t * id, $thread * thrd ) { 413 void unpark( $thread * thrd ) { 414 if( !thrd ) return; 415 416 /* paranoid */ verify( kernelTLS.this_proc_id ); 417 bool full = kernelTLS.this_proc_id->full_proc; 418 if(full) disable_interrupts(); 419 420 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 410 421 int old_ticket = __atomic_fetch_add(&thrd->ticket, 1, __ATOMIC_SEQ_CST); 411 422 switch(old_ticket) { 412 case 1:423 case TICKET_RUNNING: 413 424 // Wake won the race, the thread will reschedule/rerun itself 414 425 break; 415 case 0:426 case TICKET_BLOCKED: 416 427 /* paranoid */ verify( ! thrd->preempted != __NO_PREEMPTION ); 417 428 /* paranoid */ verify( thrd->state == Blocked ); 418 429 419 430 // Wake lost the race, 420 __schedule_thread( id,thrd );431 __schedule_thread( thrd ); 421 432 break; 422 433 default: 423 434 // This makes no sense, something is wrong abort 424 abort(); 425 } 426 } 427 428 void unpark( $thread * thrd ) { 429 if( !thrd ) return; 430 431 disable_interrupts(); 432 __unpark( (__processor_id_t*)kernelTLS.this_processor, thrd ); 433 enable_interrupts( __cfaabi_dbg_ctx ); 435 abort("Thread %p (%s) has mismatch park/unpark\n", thrd, thrd->self_cor.name); 436 } 437 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 438 439 if(full) enable_interrupts( __cfaabi_dbg_ctx ); 440 /* paranoid */ verify( kernelTLS.this_proc_id ); 434 441 } 435 442 … … 448 455 } 449 456 450 // KERNEL ONLY 451 void __leave_thread() { 452 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 453 returnToKernel(); 454 abort(); 457 extern "C" { 458 // Leave the thread monitor 459 // last routine called by a thread. 460 // Should never return 461 void __cfactx_thrd_leave() { 462 $thread * thrd = TL_GET( this_thread ); 463 $monitor * this = &thrd->self_mon; 464 465 // Lock the monitor now 466 lock( this->lock __cfaabi_dbg_ctx2 ); 467 468 disable_interrupts(); 469 470 thrd->state = Halted; 471 if( TICKET_RUNNING != thrd->ticket ) { abort( "Thread terminated with pending unpark" ); } 472 if( thrd != this->owner || this->recursion != 1) { abort( "Thread internal monitor has unbalanced recursion" ); } 473 474 // Leave the thread 475 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 476 returnToKernel(); 477 abort(); 478 479 // Control flow should never reach here! 480 } 455 481 } 456 482 … … 486 512 //============================================================================================= 487 513 // Wake a thread from the front if there are any 488 static void __wake_one( struct __processor_id_t * id,cluster * this) {489 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 490 /* paranoid */ verify( ready_schedule_islocked( id) );514 static void __wake_one(cluster * this) { 515 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 516 /* paranoid */ verify( ready_schedule_islocked() ); 491 517 492 518 // Check if there is a sleeping processor … … 506 532 #endif 507 533 508 /* paranoid */ verify( ready_schedule_islocked( id) );534 /* paranoid */ verify( ready_schedule_islocked() ); 509 535 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 510 536 … … 709 735 this.print_halts = true; 710 736 } 737 738 void print_stats_now( cluster & this, int flags ) { 739 __print_stats( this.stats, this.print_stats, true, this.name, (void*)&this ); 740 } 711 741 #endif 712 742 // Local Variables: //
Note:
See TracChangeset
for help on using the changeset viewer.