Changes in src/libcfa/concurrency/kernel.c [de6319f:de94a60]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/libcfa/concurrency/kernel.c
rde6319f rde94a60 49 49 thread_desc * mainThread; 50 50 51 struct { __dllist_t(thread_desc) list; __spinlock_t lock; } global_threads ; 52 struct { __dllist_t(cluster ) list; __spinlock_t lock; } global_clusters; 53 51 54 //----------------------------------------------------------------------------- 52 55 // Global state … … 56 59 // volatile thread_local unsigned short disable_preempt_count = 1; 57 60 58 thread_local struct KernelThreadData kernelT hreadData= {61 thread_local struct KernelThreadData kernelTLS = { 59 62 NULL, 60 63 NULL, … … 117 120 self_mon_p = &self_mon; 118 121 next = NULL; 119 __cfaabi_dbg_debug_do( 120 dbg_next = NULL; 121 dbg_prev = NULL; 122 __cfaabi_dbg_thread_register(&this); 123 ) 122 123 node.next = NULL; 124 node.prev = NULL; 125 doregister(this); 124 126 125 127 monitors{ &self_mon_p, 1, (fptr_t)0 }; … … 155 157 terminate(&this); 156 158 verify(this.do_terminate); 157 verify( TL_GET( this_processor )!= &this);159 verify( kernelTLS.this_processor != &this); 158 160 P( terminated ); 159 verify( TL_GET( this_processor )!= &this);161 verify( kernelTLS.this_processor != &this); 160 162 pthread_join( kernel_thread, NULL ); 161 163 } … … 167 169 ready_queue{}; 168 170 ready_queue_lock{}; 171 172 procs{ __get }; 173 idles{ __get }; 174 175 doregister(this); 169 176 } 170 177 171 178 void ^?{}(cluster & this) { 172 179 unregister(this); 173 180 } 174 181 … … 183 190 __cfaabi_dbg_print_safe("Kernel : core %p starting\n", this); 184 191 192 doregister(this->cltr, this); 193 185 194 { 186 195 // Setup preemption data … … 196 205 if(readyThread) 197 206 { 198 verify( ! TL_GET( preemption_state ).enabled );207 verify( ! kernelTLS.preemption_state.enabled ); 199 208 200 209 runThread(this, readyThread); 201 210 202 verify( ! TL_GET( preemption_state ).enabled );211 verify( ! kernelTLS.preemption_state.enabled ); 203 212 204 213 //Some actions need to be taken from the kernel … … 216 225 } 217 226 227 unregister(this->cltr, this); 228 218 229 V( this->terminated ); 219 230 … … 221 232 } 222 233 234 // KERNEL ONLY 223 235 // runThread runs a thread by context switching 224 236 // from the processor coroutine to the target thread … … 228 240 coroutine_desc * thrd_cor = dst->curr_cor; 229 241 230 // Reset the terminating actions here242 // Reset the terminating actions here 231 243 this->finish.action_code = No_Action; 232 244 233 // Update global state234 TL_SET( this_thread, dst );245 // Update global state 246 kernelTLS.this_thread = dst; 235 247 236 248 // Context Switch to the thread … … 239 251 } 240 252 253 // KERNEL_ONLY 241 254 void returnToKernel() { 242 coroutine_desc * proc_cor = get_coroutine( TL_GET( this_processor )->runner);243 coroutine_desc * thrd_cor = TL_GET( this_thread )->curr_cor = TL_GET( this_coroutine );255 coroutine_desc * proc_cor = get_coroutine(kernelTLS.this_processor->runner); 256 coroutine_desc * thrd_cor = kernelTLS.this_thread->curr_cor = kernelTLS.this_coroutine; 244 257 ThreadCtxSwitch(thrd_cor, proc_cor); 245 258 } 246 259 260 // KERNEL_ONLY 247 261 // Once a thread has finished running, some of 248 262 // its final actions must be executed from the kernel 249 263 void finishRunning(processor * this) with( this->finish ) { 250 264 if( action_code == Release ) { 251 verify( ! TL_GET( preemption_state ).enabled );265 verify( ! kernelTLS.preemption_state.enabled ); 252 266 unlock( *lock ); 253 267 } … … 256 270 } 257 271 else if( action_code == Release_Schedule ) { 258 verify( ! TL_GET( preemption_state ).enabled );272 verify( ! kernelTLS.preemption_state.enabled ); 259 273 unlock( *lock ); 260 274 ScheduleThread( thrd ); 261 275 } 262 276 else if( action_code == Release_Multi ) { 263 verify( ! TL_GET( preemption_state ).enabled );277 verify( ! kernelTLS.preemption_state.enabled ); 264 278 for(int i = 0; i < lock_count; i++) { 265 279 unlock( *locks[i] ); … … 285 299 } 286 300 301 // KERNEL_ONLY 287 302 // Context invoker for processors 288 303 // This is the entry point for processors (kernel threads) … … 290 305 void * CtxInvokeProcessor(void * arg) { 291 306 processor * proc = (processor *) arg; 292 TL_SET( this_processor, proc );293 TL_SET( this_coroutine, NULL );294 TL_SET( this_thread, NULL );295 TL_GET( preemption_state ).[enabled, disable_count] = [false, 1];307 kernelTLS.this_processor = proc; 308 kernelTLS.this_coroutine = NULL; 309 kernelTLS.this_thread = NULL; 310 kernelTLS.preemption_state.[enabled, disable_count] = [false, 1]; 296 311 // SKULLDUGGERY: We want to create a context for the processor coroutine 297 312 // which is needed for the 2-step context switch. However, there is no reason … … 305 320 306 321 //Set global state 307 TL_SET( this_coroutine, get_coroutine(proc->runner));308 TL_SET( this_thread, NULL );322 kernelTLS.this_coroutine = get_coroutine(proc->runner); 323 kernelTLS.this_thread = NULL; 309 324 310 325 //We now have a proper context from which to schedule threads … … 333 348 } 334 349 350 // KERNEL_ONLY 335 351 void kernel_first_resume(processor * this) { 336 coroutine_desc * src = TL_GET( this_coroutine );352 coroutine_desc * src = kernelTLS.this_coroutine; 337 353 coroutine_desc * dst = get_coroutine(this->runner); 338 354 339 verify( ! TL_GET( preemption_state ).enabled );355 verify( ! kernelTLS.preemption_state.enabled ); 340 356 341 357 create_stack(&dst->stack, dst->stack.size); 342 358 CtxStart(&this->runner, CtxInvokeCoroutine); 343 359 344 verify( ! TL_GET( preemption_state ).enabled );360 verify( ! kernelTLS.preemption_state.enabled ); 345 361 346 362 dst->last = src; … … 351 367 352 368 // set new coroutine that task is executing 353 TL_SET( this_coroutine, dst );369 kernelTLS.this_coroutine = dst; 354 370 355 371 // SKULLDUGGERY normally interrupts are enable before leaving a coroutine ctxswitch. … … 368 384 src->state = Active; 369 385 370 verify( ! TL_GET( preemption_state ).enabled );386 verify( ! kernelTLS.preemption_state.enabled ); 371 387 } 372 388 373 389 //----------------------------------------------------------------------------- 374 390 // Scheduler routines 391 392 // KERNEL ONLY 375 393 void ScheduleThread( thread_desc * thrd ) { 376 // if( ! thrd ) return;377 394 verify( thrd ); 378 395 verify( thrd->self_cor.state != Halted ); 379 396 380 verify( ! TL_GET( preemption_state ).enabled );397 verify( ! kernelTLS.preemption_state.enabled ); 381 398 382 399 verifyf( thrd->next == NULL, "Expected null got %p", thrd->next ); … … 388 405 } 389 406 390 verify( ! TL_GET( preemption_state ).enabled ); 391 } 392 407 verify( ! kernelTLS.preemption_state.enabled ); 408 } 409 410 // KERNEL ONLY 393 411 thread_desc * nextThread(cluster * this) with( *this ) { 394 verify( ! TL_GET( preemption_state ).enabled );412 verify( ! kernelTLS.preemption_state.enabled ); 395 413 lock( ready_queue_lock __cfaabi_dbg_ctx2 ); 396 414 thread_desc * head = pop_head( ready_queue ); 397 415 unlock( ready_queue_lock ); 398 verify( ! TL_GET( preemption_state ).enabled );416 verify( ! kernelTLS.preemption_state.enabled ); 399 417 return head; 400 418 } … … 402 420 void BlockInternal() { 403 421 disable_interrupts(); 404 verify( ! TL_GET( preemption_state ).enabled );422 verify( ! kernelTLS.preemption_state.enabled ); 405 423 returnToKernel(); 406 verify( ! TL_GET( preemption_state ).enabled );424 verify( ! kernelTLS.preemption_state.enabled ); 407 425 enable_interrupts( __cfaabi_dbg_ctx ); 408 426 } … … 410 428 void BlockInternal( __spinlock_t * lock ) { 411 429 disable_interrupts(); 412 with( * TL_GET( this_processor )) {430 with( *kernelTLS.this_processor ) { 413 431 finish.action_code = Release; 414 432 finish.lock = lock; 415 433 } 416 434 417 verify( ! TL_GET( preemption_state ).enabled );435 verify( ! kernelTLS.preemption_state.enabled ); 418 436 returnToKernel(); 419 verify( ! TL_GET( preemption_state ).enabled );437 verify( ! kernelTLS.preemption_state.enabled ); 420 438 421 439 enable_interrupts( __cfaabi_dbg_ctx ); … … 424 442 void BlockInternal( thread_desc * thrd ) { 425 443 disable_interrupts(); 426 with( * TL_GET( this_processor )) {444 with( * kernelTLS.this_processor ) { 427 445 finish.action_code = Schedule; 428 446 finish.thrd = thrd; 429 447 } 430 448 431 verify( ! TL_GET( preemption_state ).enabled );449 verify( ! kernelTLS.preemption_state.enabled ); 432 450 returnToKernel(); 433 verify( ! TL_GET( preemption_state ).enabled );451 verify( ! kernelTLS.preemption_state.enabled ); 434 452 435 453 enable_interrupts( __cfaabi_dbg_ctx ); … … 439 457 assert(thrd); 440 458 disable_interrupts(); 441 with( * TL_GET( this_processor )) {459 with( * kernelTLS.this_processor ) { 442 460 finish.action_code = Release_Schedule; 443 461 finish.lock = lock; … … 445 463 } 446 464 447 verify( ! TL_GET( preemption_state ).enabled );465 verify( ! kernelTLS.preemption_state.enabled ); 448 466 returnToKernel(); 449 verify( ! TL_GET( preemption_state ).enabled );467 verify( ! kernelTLS.preemption_state.enabled ); 450 468 451 469 enable_interrupts( __cfaabi_dbg_ctx ); … … 454 472 void BlockInternal(__spinlock_t * locks [], unsigned short count) { 455 473 disable_interrupts(); 456 with( * TL_GET( this_processor )) {474 with( * kernelTLS.this_processor ) { 457 475 finish.action_code = Release_Multi; 458 476 finish.locks = locks; … … 460 478 } 461 479 462 verify( ! TL_GET( preemption_state ).enabled );480 verify( ! kernelTLS.preemption_state.enabled ); 463 481 returnToKernel(); 464 verify( ! TL_GET( preemption_state ).enabled );482 verify( ! kernelTLS.preemption_state.enabled ); 465 483 466 484 enable_interrupts( __cfaabi_dbg_ctx ); … … 469 487 void BlockInternal(__spinlock_t * locks [], unsigned short lock_count, thread_desc * thrds [], unsigned short thrd_count) { 470 488 disable_interrupts(); 471 with( * TL_GET( this_processor )) {489 with( *kernelTLS.this_processor ) { 472 490 finish.action_code = Release_Multi_Schedule; 473 491 finish.locks = locks; … … 477 495 } 478 496 479 verify( ! TL_GET( preemption_state ).enabled );497 verify( ! kernelTLS.preemption_state.enabled ); 480 498 returnToKernel(); 481 verify( ! TL_GET( preemption_state ).enabled );499 verify( ! kernelTLS.preemption_state.enabled ); 482 500 483 501 enable_interrupts( __cfaabi_dbg_ctx ); 484 502 } 485 503 504 // KERNEL ONLY 486 505 void LeaveThread(__spinlock_t * lock, thread_desc * thrd) { 487 verify( ! TL_GET( preemption_state ).enabled );488 with( * TL_GET( this_processor )) {506 verify( ! kernelTLS.preemption_state.enabled ); 507 with( * kernelTLS.this_processor ) { 489 508 finish.action_code = thrd ? Release_Schedule : Release; 490 509 finish.lock = lock; … … 501 520 // Kernel boot procedures 502 521 void kernel_startup(void) { 503 verify( ! TL_GET( preemption_state ).enabled );522 verify( ! kernelTLS.preemption_state.enabled ); 504 523 __cfaabi_dbg_print_safe("Kernel : Starting\n"); 524 525 global_threads. list{ __get }; 526 global_threads. lock{}; 527 global_clusters.list{ __get }; 528 global_clusters.lock{}; 505 529 506 530 // Initialize the main cluster … … 547 571 548 572 //initialize the global state variables 549 TL_SET( this_processor, mainProcessor );550 TL_SET( this_thread, mainThread );551 TL_SET( this_coroutine, &mainThread->self_cor );573 kernelTLS.this_processor = mainProcessor; 574 kernelTLS.this_thread = mainThread; 575 kernelTLS.this_coroutine = &mainThread->self_cor; 552 576 553 577 // Enable preemption … … 561 585 // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that 562 586 // mainThread is on the ready queue when this call is made. 563 kernel_first_resume( TL_GET( this_processor ));587 kernel_first_resume( kernelTLS.this_processor ); 564 588 565 589 … … 568 592 __cfaabi_dbg_print_safe("Kernel : Started\n--------------------------------------------------\n\n"); 569 593 570 verify( ! TL_GET( preemption_state ).enabled );594 verify( ! kernelTLS.preemption_state.enabled ); 571 595 enable_interrupts( __cfaabi_dbg_ctx ); 572 verify( TL_GET( preemption_state ).enabled);596 verify( TL_GET( preemption_state.enabled ) ); 573 597 } 574 598 … … 576 600 __cfaabi_dbg_print_safe("\n--------------------------------------------------\nKernel : Shutting down\n"); 577 601 578 verify( TL_GET( preemption_state ).enabled);602 verify( TL_GET( preemption_state.enabled ) ); 579 603 disable_interrupts(); 580 verify( ! TL_GET( preemption_state ).enabled );604 verify( ! kernelTLS.preemption_state.enabled ); 581 605 582 606 // SKULLDUGGERY: Notify the mainProcessor it needs to terminates. … … 604 628 605 629 //============================================================================================= 630 // Kernel Quiescing 631 //============================================================================================= 632 633 // void halt(processor * this) with( this ) { 634 // pthread_mutex_lock( &idle.lock ); 635 636 637 638 // // SKULLDUGGERY: Even if spurious wake-up is a thing 639 // // spuriously waking up a kernel thread is not a big deal 640 // // if it is very rare. 641 // pthread_cond_wait( &idle.cond, &idle.lock); 642 // pthread_mutex_unlock( &idle.lock ); 643 // } 644 645 // void wake(processor * this) with( this ) { 646 // pthread_mutex_lock (&idle.lock); 647 // pthread_cond_signal (&idle.cond); 648 // pthread_mutex_unlock(&idle.lock); 649 // } 650 651 //============================================================================================= 606 652 // Unexpected Terminating logic 607 653 //============================================================================================= … … 609 655 610 656 static __spinlock_t kernel_abort_lock; 611 static __spinlock_t kernel_debug_lock;612 657 static bool kernel_abort_called = false; 613 658 614 void * kernel_abort 659 void * kernel_abort(void) __attribute__ ((__nothrow__)) { 615 660 // abort cannot be recursively entered by the same or different processors because all signal handlers return when 616 661 // the globalAbort flag is true. … … 618 663 619 664 // first task to abort ? 620 if ( ! kernel_abort_called ) { // not first task to abort ? 665 if ( kernel_abort_called ) { // not first task to abort ? 666 unlock( kernel_abort_lock ); 667 668 sigset_t mask; 669 sigemptyset( &mask ); 670 sigaddset( &mask, SIGALRM ); // block SIGALRM signals 671 sigsuspend( &mask ); // block the processor to prevent further damage during abort 672 _exit( EXIT_FAILURE ); // if processor unblocks before it is killed, terminate it 673 } 674 else { 621 675 kernel_abort_called = true; 622 676 unlock( kernel_abort_lock ); 623 677 } 624 else { 625 unlock( kernel_abort_lock ); 626 627 sigset_t mask; 628 sigemptyset( &mask ); 629 sigaddset( &mask, SIGALRM ); // block SIGALRM signals 630 sigaddset( &mask, SIGUSR1 ); // block SIGUSR1 signals 631 sigsuspend( &mask ); // block the processor to prevent further damage during abort 632 _exit( EXIT_FAILURE ); // if processor unblocks before it is killed, terminate it 633 } 634 635 return TL_GET( this_thread ); 678 679 return kernelTLS.this_thread; 636 680 } 637 681 … … 639 683 thread_desc * thrd = kernel_data; 640 684 641 int len = snprintf( abort_text, abort_text_size, "Error occurred while executing task %.256s (%p)", thrd->self_cor.name, thrd ); 642 __cfaabi_dbg_bits_write( abort_text, len ); 643 644 if ( get_coroutine(thrd) != TL_GET( this_coroutine ) ) { 645 len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", TL_GET( this_coroutine )->name, TL_GET( this_coroutine ) ); 685 if(thrd) { 686 int len = snprintf( abort_text, abort_text_size, "Error occurred while executing thread %.256s (%p)", thrd->self_cor.name, thrd ); 646 687 __cfaabi_dbg_bits_write( abort_text, len ); 688 689 if ( get_coroutine(thrd) != kernelTLS.this_coroutine ) { 690 len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", kernelTLS.this_coroutine->name, kernelTLS.this_coroutine ); 691 __cfaabi_dbg_bits_write( abort_text, len ); 692 } 693 else { 694 __cfaabi_dbg_bits_write( ".\n", 2 ); 695 } 647 696 } 648 697 else { 649 __cfaabi_dbg_bits_write( ".\n", 2);698 int len = snprintf( abort_text, abort_text_size, "Error occurred outside of any thread.\n" ); 650 699 } 651 700 } 652 701 653 702 int kernel_abort_lastframe( void ) __attribute__ ((__nothrow__)) { 654 return get_coroutine(TL_GET( this_thread )) == get_coroutine(mainThread) ? 4 : 2; 655 } 703 return get_coroutine(kernelTLS.this_thread) == get_coroutine(mainThread) ? 4 : 2; 704 } 705 706 static __spinlock_t kernel_debug_lock; 656 707 657 708 extern "C" { … … 682 733 if ( count < 0 ) { 683 734 // queue current task 684 append( waiting, (thread_desc *)TL_GET( this_thread ));735 append( waiting, kernelTLS.this_thread ); 685 736 686 737 // atomically release spin lock and block … … 708 759 709 760 //----------------------------------------------------------------------------- 761 // Global Queues 762 void doregister( thread_desc & thrd ) { 763 // lock ( global_thread.lock ); 764 // push_front( global_thread.list, thrd ); 765 // unlock ( global_thread.lock ); 766 } 767 768 void unregister( thread_desc & thrd ) { 769 // lock ( global_thread.lock ); 770 // remove( global_thread.list, thrd ); 771 // unlock( global_thread.lock ); 772 } 773 774 void doregister( cluster & cltr ) { 775 // lock ( global_cluster.lock ); 776 // push_front( global_cluster.list, cltr ); 777 // unlock ( global_cluster.lock ); 778 } 779 780 void unregister( cluster & cltr ) { 781 // lock ( global_cluster.lock ); 782 // remove( global_cluster.list, cltr ); 783 // unlock( global_cluster.lock ); 784 } 785 786 787 void doregister( cluster * cltr, processor * proc ) { 788 // lock (cltr->proc_list_lock __cfaabi_dbg_ctx2); 789 // push_front(cltr->procs, *proc); 790 // unlock (cltr->proc_list_lock); 791 } 792 793 void unregister( cluster * cltr, processor * proc ) { 794 // lock (cltr->proc_list_lock __cfaabi_dbg_ctx2); 795 // remove(cltr->procs, *proc ); 796 // unlock(cltr->proc_list_lock); 797 } 798 799 //----------------------------------------------------------------------------- 710 800 // Debug 711 801 __cfaabi_dbg_debug_do( 712 struct {713 thread_desc * tail;714 } __cfaabi_dbg_thread_list = { NULL };715 716 void __cfaabi_dbg_thread_register( thread_desc * thrd ) {717 if( !__cfaabi_dbg_thread_list.tail ) {718 __cfaabi_dbg_thread_list.tail = thrd;719 return;720 }721 __cfaabi_dbg_thread_list.tail->dbg_next = thrd;722 thrd->dbg_prev = __cfaabi_dbg_thread_list.tail;723 __cfaabi_dbg_thread_list.tail = thrd;724 }725 726 void __cfaabi_dbg_thread_unregister( thread_desc * thrd ) {727 thread_desc * prev = thrd->dbg_prev;728 thread_desc * next = thrd->dbg_next;729 730 if( next ) { next->dbg_prev = prev; }731 else {732 assert( __cfaabi_dbg_thread_list.tail == thrd );733 __cfaabi_dbg_thread_list.tail = prev;734 }735 736 if( prev ) { prev->dbg_next = next; }737 738 thrd->dbg_prev = NULL;739 thrd->dbg_next = NULL;740 }741 742 802 void __cfaabi_dbg_record(__spinlock_t & this, const char * prev_name) { 743 803 this.prev_name = prev_name; 744 this.prev_thrd = TL_GET( this_thread );804 this.prev_thrd = kernelTLS.this_thread; 745 805 } 746 806 )
Note: See TracChangeset
for help on using the changeset viewer.