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