- File:
-
- 1 edited
-
libcfa/src/concurrency/kernel.cfa (modified) (13 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/kernel.cfa
r58688bf rb4b63e8 108 108 static $thread * __next_thread_slow(cluster * this); 109 109 static void __run_thread(processor * this, $thread * dst); 110 static void __wake_one( cluster * cltr);110 static void __wake_one(struct __processor_id_t * id, 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 );255 254 /* 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 256 255 /* 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 … … 282 281 if(unlikely(thrd_dst->preempted != __NO_PREEMPTION)) { 283 282 // The thread was preempted, reschedule it and reset the flag 284 __schedule_thread( thrd_dst );283 __schedule_thread( (__processor_id_t*)this, thrd_dst ); 285 284 break RUNNING; 286 285 } … … 288 287 if(unlikely(thrd_dst->state == Halted)) { 289 288 // The thread has halted, it should never be scheduled/run again 290 // finish the thread 291 __thread_finish( thrd_dst ); 289 // We may need to wake someone up here since 290 unpark( this->destroyer ); 291 this->destroyer = 0p; 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 TICKET_RUNNING:301 case 1: 302 302 // This is case 1, the regular case, nothing more is needed 303 303 break RUNNING; 304 case TICKET_UNBLOCK:304 case 2: 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( $thread * thrd ) {360 void __schedule_thread( struct __processor_id_t * id, $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 );365 364 /* paranoid */ #if defined( __CFA_WITH_VERIFY__ ) 366 365 /* paranoid */ if( thrd->state == Blocked || thrd->state == Start ) assertf( thrd->preempted == __NO_PREEMPTION, … … 375 374 if (thrd->preempted == __NO_PREEMPTION) thrd->state = Ready; 376 375 377 ready_schedule_lock ();376 ready_schedule_lock ( id ); 378 377 push( thrd->curr_cluster, thrd ); 379 __wake_one( thrd->curr_cluster);380 ready_schedule_unlock( );378 __wake_one(id, thrd->curr_cluster); 379 ready_schedule_unlock( id ); 381 380 382 381 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); … … 385 384 // KERNEL ONLY 386 385 static inline $thread * __next_thread(cluster * this) with( *this ) { 387 /* paranoid */ verify( kernelTLS.this_proc_id ); 388 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 389 390 ready_schedule_lock(); 386 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 387 388 ready_schedule_lock ( (__processor_id_t*)kernelTLS.this_processor ); 391 389 $thread * thrd = pop( this ); 392 ready_schedule_unlock(); 393 394 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 395 /* paranoid */ verify( kernelTLS.this_proc_id ); 390 ready_schedule_unlock( (__processor_id_t*)kernelTLS.this_processor ); 391 392 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 396 393 return thrd; 397 394 } … … 399 396 // KERNEL ONLY 400 397 static inline $thread * __next_thread_slow(cluster * this) with( *this ) { 401 /* paranoid */ verify( kernelTLS.this_proc_id ); 402 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 403 404 ready_schedule_lock(); 398 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 399 400 ready_schedule_lock ( (__processor_id_t*)kernelTLS.this_processor ); 405 401 $thread * thrd = pop_slow( this ); 406 ready_schedule_unlock(); 407 408 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 409 /* paranoid */ verify( kernelTLS.this_proc_id ); 402 ready_schedule_unlock( (__processor_id_t*)kernelTLS.this_processor ); 403 404 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 410 405 return thrd; 411 406 } 412 407 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 ); 408 // KERNEL ONLY unpark with out disabling interrupts 409 void __unpark( struct __processor_id_t * id, $thread * thrd ) { 421 410 int old_ticket = __atomic_fetch_add(&thrd->ticket, 1, __ATOMIC_SEQ_CST); 422 411 switch(old_ticket) { 423 case TICKET_RUNNING:412 case 1: 424 413 // Wake won the race, the thread will reschedule/rerun itself 425 414 break; 426 case TICKET_BLOCKED:415 case 0: 427 416 /* paranoid */ verify( ! thrd->preempted != __NO_PREEMPTION ); 428 417 /* paranoid */ verify( thrd->state == Blocked ); 429 418 430 419 // Wake lost the race, 431 __schedule_thread( thrd );420 __schedule_thread( id, thrd ); 432 421 break; 433 422 default: 434 423 // This makes no sense, something is wrong abort 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 ); 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 ); 441 434 } 442 435 … … 455 448 } 456 449 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 } 450 // KERNEL ONLY 451 void __leave_thread() { 452 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 453 returnToKernel(); 454 abort(); 481 455 } 482 456 … … 512 486 //============================================================================================= 513 487 // Wake a thread from the front if there are any 514 static void __wake_one( cluster * this) {515 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 516 /* paranoid */ verify( ready_schedule_islocked( ) );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 ) ); 517 491 518 492 // Check if there is a sleeping processor … … 532 506 #endif 533 507 534 /* paranoid */ verify( ready_schedule_islocked( ) );508 /* paranoid */ verify( ready_schedule_islocked( id ) ); 535 509 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 536 510 … … 735 709 this.print_halts = true; 736 710 } 737 738 void print_stats_now( cluster & this, int flags ) {739 __print_stats( this.stats, this.print_stats, true, this.name, (void*)&this );740 }741 711 #endif 742 712 // Local Variables: //
Note:
See TracChangeset
for help on using the changeset viewer.