- File:
-
- 1 edited
-
src/libcfa/concurrency/kernel.c (modified) (22 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/libcfa/concurrency/kernel.c
r135b431 r83a071f9 1 // -*- Mode: CFA -*- 1 2 // 2 3 // Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo … … 9 10 // Author : Thierry Delisle 10 11 // Created On : Tue Jan 17 12:27:26 2017 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Fri Jul 21 22:33:18 201713 // Update Count : 212 // Last Modified By : Thierry Delisle 13 // Last Modified On : -- 14 // Update Count : 0 14 15 // 15 16 … … 41 42 //----------------------------------------------------------------------------- 42 43 // Kernel storage 43 KERNEL_STORAGE(cluster, mainCluster); 44 KERNEL_STORAGE(processor, mainProcessor); 45 KERNEL_STORAGE(processorCtx_t, mainProcessorCtx); 46 KERNEL_STORAGE(thread_desc, mainThread); 44 #define KERNEL_STORAGE(T,X) static char X##Storage[sizeof(T)] 45 46 KERNEL_STORAGE(processorCtx_t, systemProcessorCtx); 47 KERNEL_STORAGE(cluster, systemCluster); 48 KERNEL_STORAGE(system_proc_t, systemProcessor); 49 KERNEL_STORAGE(thread_desc, mainThread); 47 50 KERNEL_STORAGE(machine_context_t, mainThreadCtx); 48 51 49 cluster * mainCluster;50 processor * mainProcessor;52 cluster * systemCluster; 53 system_proc_t * systemProcessor; 51 54 thread_desc * mainThread; 52 55 … … 54 57 // Global state 55 58 56 thread_local coroutine_desc * volatile this_coroutine; 57 thread_local thread_desc * volatile this_thread; 58 thread_local processor * volatile this_processor; 59 59 volatile thread_local processor * this_processor; 60 volatile thread_local coroutine_desc * this_coroutine; 61 volatile thread_local thread_desc * this_thread; 60 62 volatile thread_local bool preemption_in_progress = 0; 61 63 volatile thread_local unsigned short disable_preempt_count = 1; … … 73 75 }; 74 76 75 void ?{}( current_stack_info_t *this ) {76 CtxGet( this ->ctx );77 this ->base = this->ctx.FP;78 this ->storage = this->ctx.SP;77 void ?{}( current_stack_info_t & this ) { 78 CtxGet( this.ctx ); 79 this.base = this.ctx.FP; 80 this.storage = this.ctx.SP; 79 81 80 82 rlimit r; 81 83 getrlimit( RLIMIT_STACK, &r); 82 this ->size = r.rlim_cur;83 84 this ->limit = (void *)(((intptr_t)this->base) - this->size);85 this ->context = &storage_mainThreadCtx;86 this ->top = this->base;87 } 88 89 void ?{}( coStack_t *this, current_stack_info_t * info) {90 this ->size = info->size;91 this ->storage = info->storage;92 this ->limit = info->limit;93 this ->base = info->base;94 this ->context = info->context;95 this ->top = info->top;96 this ->userStack = true;97 } 98 99 void ?{}( coroutine_desc *this, current_stack_info_t * info) {100 ( &this->stack){ info };101 this ->name = "Main Thread";102 this ->errno_ = 0;103 this ->state = Start;104 } 105 106 void ?{}( thread_desc *this, current_stack_info_t * info) {107 ( &this->cor){ info };84 this.size = r.rlim_cur; 85 86 this.limit = (void *)(((intptr_t)this.base) - this.size); 87 this.context = &mainThreadCtxStorage; 88 this.top = this.base; 89 } 90 91 void ?{}( coStack_t & this, current_stack_info_t * info) { 92 this.size = info->size; 93 this.storage = info->storage; 94 this.limit = info->limit; 95 this.base = info->base; 96 this.context = info->context; 97 this.top = info->top; 98 this.userStack = true; 99 } 100 101 void ?{}( coroutine_desc & this, current_stack_info_t * info) { 102 (this.stack){ info }; 103 this.name = "Main Thread"; 104 this.errno_ = 0; 105 this.state = Start; 106 } 107 108 void ?{}( thread_desc & this, current_stack_info_t * info) { 109 (this.cor){ info }; 108 110 } 109 111 110 112 //----------------------------------------------------------------------------- 111 113 // Processor coroutine 112 void ?{}(processorCtx_t * this, processor * proc) { 113 (&this->__cor){ "Processor" }; 114 this->proc = proc; 115 proc->runner = this; 116 } 117 118 void ?{}(processorCtx_t * this, processor * proc, current_stack_info_t * info) { 119 (&this->__cor){ info }; 120 this->proc = proc; 121 proc->runner = this; 122 } 123 124 void ?{}(processor * this) { 125 this{ mainCluster }; 126 } 127 128 void ?{}(processor * this, cluster * cltr) { 129 this->cltr = cltr; 130 (&this->terminated){ 0 }; 131 this->do_terminate = false; 132 this->preemption_alarm = NULL; 133 this->pending_preemption = false; 134 135 start( this ); 136 } 137 138 void ?{}(processor * this, cluster * cltr, processorCtx_t * runner) { 139 this->cltr = cltr; 140 (&this->terminated){ 0 }; 141 this->do_terminate = false; 142 this->preemption_alarm = NULL; 143 this->pending_preemption = false; 144 this->kernel_thread = pthread_self(); 145 146 this->runner = runner; 147 LIB_DEBUG_PRINT_SAFE("Kernel : constructing main processor context %p\n", runner); 148 runner{ this }; 149 } 150 151 void ^?{}(processor * this) { 152 if( ! this->do_terminate ) { 153 LIB_DEBUG_PRINT_SAFE("Kernel : core %p signaling termination\n", this); 154 this->do_terminate = true; 155 P( &this->terminated ); 156 pthread_join( this->kernel_thread, NULL ); 157 } 158 } 159 160 void ?{}(cluster * this) { 161 ( &this->ready_queue ){}; 162 ( &this->ready_queue_lock ){}; 163 164 this->preemption = default_preemption(); 165 } 166 167 void ^?{}(cluster * this) { 114 void ?{}(processorCtx_t & this, processor * proc) { 115 (this.__cor){ "Processor" }; 116 this.proc = proc; 117 proc->runner = &this; 118 } 119 120 void ?{}(processorCtx_t & this, processor * proc, current_stack_info_t * info) { 121 (this.__cor){ info }; 122 this.proc = proc; 123 proc->runner = &this; 124 } 125 126 void ?{}(processor & this) { 127 this{ systemCluster }; 128 } 129 130 void ?{}(processor & this, cluster * cltr) { 131 this.cltr = cltr; 132 (this.terminated){ 0 }; 133 this.is_terminated = false; 134 this.preemption_alarm = NULL; 135 this.preemption = default_preemption(); 136 this.pending_preemption = false; 137 138 start( &this ); 139 } 140 141 void ?{}(processor & this, cluster * cltr, processorCtx_t & runner) { 142 this.cltr = cltr; 143 (this.terminated){ 0 }; 144 this.is_terminated = false; 145 this.preemption_alarm = NULL; 146 this.preemption = default_preemption(); 147 this.pending_preemption = false; 148 this.kernel_thread = pthread_self(); 149 150 this.runner = &runner; 151 LIB_DEBUG_PRINT_SAFE("Kernel : constructing system processor context %p\n", &runner); 152 runner{ &this }; 153 } 154 155 LIB_DEBUG_DO( bool validate( alarm_list_t * this ); ) 156 157 void ?{}(system_proc_t & this, cluster * cltr, processorCtx_t & runner) { 158 (this.alarms){}; 159 (this.alarm_lock){}; 160 this.pending_alarm = false; 161 162 (this.proc){ cltr, runner }; 163 164 verify( validate( &this.alarms ) ); 165 } 166 167 void ^?{}(processor & this) { 168 if( ! this.is_terminated ) { 169 LIB_DEBUG_PRINT_SAFE("Kernel : core %p signaling termination\n", &this); 170 this.is_terminated = true; 171 P( &this.terminated ); 172 pthread_join( this.kernel_thread, NULL ); 173 } 174 } 175 176 void ?{}(cluster & this) { 177 ( this.ready_queue ){}; 178 ( this.lock ){}; 179 } 180 181 void ^?{}(cluster & this) { 168 182 169 183 } … … 173 187 //============================================================================================= 174 188 //Main of the processor contexts 175 void main(processorCtx_t *runner) {176 processor * this = runner ->proc;189 void main(processorCtx_t & runner) { 190 processor * this = runner.proc; 177 191 178 192 LIB_DEBUG_PRINT_SAFE("Kernel : core %p starting\n", this); … … 185 199 186 200 thread_desc * readyThread = NULL; 187 for( unsigned int spin_count = 0; ! this-> do_terminate; spin_count++ )201 for( unsigned int spin_count = 0; ! this->is_terminated; spin_count++ ) 188 202 { 189 203 readyThread = nextThread( this->cltr ); … … 219 233 // from the processor coroutine to the target thread 220 234 void runThread(processor * this, thread_desc * dst) { 221 coroutine_desc * proc_cor = get_coroutine( this->runner);235 coroutine_desc * proc_cor = get_coroutine(*this->runner); 222 236 coroutine_desc * thrd_cor = get_coroutine(dst); 223 237 … … 301 315 // appropriate stack. 302 316 proc_cor_storage.__cor.state = Active; 303 main( &proc_cor_storage );317 main( proc_cor_storage ); 304 318 proc_cor_storage.__cor.state = Halted; 305 319 … … 322 336 void ScheduleThread( thread_desc * thrd ) { 323 337 // if( !thrd ) return; 324 verify( thrd );325 verify( thrd->cor.state != Halted );338 assert( thrd ); 339 assert( thrd->cor.state != Halted ); 326 340 327 341 verify( disable_preempt_count > 0 ); … … 329 343 verifyf( thrd->next == NULL, "Expected null got %p", thrd->next ); 330 344 331 lock( &this_processor->cltr->ready_queue_lock DEBUG_CTX2 );332 append( & this_processor->cltr->ready_queue, thrd );333 unlock( & this_processor->cltr->ready_queue_lock );345 lock( &systemProcessor->proc.cltr->lock DEBUG_CTX2 ); 346 append( &systemProcessor->proc.cltr->ready_queue, thrd ); 347 unlock( &systemProcessor->proc.cltr->lock ); 334 348 335 349 verify( disable_preempt_count > 0 ); … … 338 352 thread_desc * nextThread(cluster * this) { 339 353 verify( disable_preempt_count > 0 ); 340 lock( &this-> ready_queue_lock DEBUG_CTX2 );354 lock( &this->lock DEBUG_CTX2 ); 341 355 thread_desc * head = pop_head( &this->ready_queue ); 342 unlock( &this-> ready_queue_lock );356 unlock( &this->lock ); 343 357 verify( disable_preempt_count > 0 ); 344 358 return head; … … 366 380 367 381 void BlockInternal( thread_desc * thrd ) { 368 assert(thrd);369 382 disable_interrupts(); 370 383 assert( thrd->cor.state != Halted ); … … 380 393 381 394 void BlockInternal( spinlock * lock, thread_desc * thrd ) { 382 assert(thrd);383 395 disable_interrupts(); 384 396 this_processor->finish.action_code = Release_Schedule; … … 440 452 // Start by initializing the main thread 441 453 // SKULLDUGGERY: the mainThread steals the process main thread 442 // which will then be scheduled by the mainProcessor normally443 mainThread = (thread_desc *)& storage_mainThread;454 // which will then be scheduled by the systemProcessor normally 455 mainThread = (thread_desc *)&mainThreadStorage; 444 456 current_stack_info_t info; 445 mainThread{ &info };457 (*mainThread){ &info }; 446 458 447 459 LIB_DEBUG_PRINT_SAFE("Kernel : Main thread ready\n"); 448 460 449 // Initialize the maincluster450 mainCluster = (cluster *)&storage_mainCluster;451 mainCluster{};452 453 LIB_DEBUG_PRINT_SAFE("Kernel : maincluster ready\n");454 455 // Initialize the main processor and the mainprocessor ctx461 // Initialize the system cluster 462 systemCluster = (cluster *)&systemClusterStorage; 463 (*systemCluster){}; 464 465 LIB_DEBUG_PRINT_SAFE("Kernel : System cluster ready\n"); 466 467 // Initialize the system processor and the system processor ctx 456 468 // (the coroutine that contains the processing control flow) 457 mainProcessor = (processor *)&storage_mainProcessor; 458 mainProcessor{ mainCluster, (processorCtx_t *)&storage_mainProcessorCtx }; 469 systemProcessor = (system_proc_t *)&systemProcessorStorage; 470 (*systemProcessor){ systemCluster, *(processorCtx_t *)&systemProcessorCtxStorage }; 471 472 // Add the main thread to the ready queue 473 // once resume is called on systemProcessor->runner the mainThread needs to be scheduled like any normal thread 474 ScheduleThread(mainThread); 459 475 460 476 //initialize the global state variables 461 this_processor = mainProcessor;477 this_processor = &systemProcessor->proc; 462 478 this_thread = mainThread; 463 479 this_coroutine = &mainThread->cor; 480 disable_preempt_count = 1; 464 481 465 482 // Enable preemption 466 483 kernel_start_preemption(); 467 484 468 // Add the main thread to the ready queue 469 // once resume is called on mainProcessor->runner the mainThread needs to be scheduled like any normal thread 470 ScheduleThread(mainThread); 471 472 // SKULLDUGGERY: Force a context switch to the main processor to set the main thread's context to the current UNIX 485 // SKULLDUGGERY: Force a context switch to the system processor to set the main thread's context to the current UNIX 473 486 // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that 474 487 // mainThread is on the ready queue when this call is made. 475 resume( mainProcessor->runner );488 resume( *systemProcessor->proc.runner ); 476 489 477 490 … … 488 501 disable_interrupts(); 489 502 490 // SKULLDUGGERY: Notify the mainProcessor it needs to terminates.503 // SKULLDUGGERY: Notify the systemProcessor it needs to terminates. 491 504 // When its coroutine terminates, it return control to the mainThread 492 505 // which is currently here 493 mainProcessor->do_terminate= true;506 systemProcessor->proc.is_terminated = true; 494 507 suspend(); 495 508 … … 499 512 kernel_stop_preemption(); 500 513 501 // Destroy the mainprocessor and its context in reverse order of construction514 // Destroy the system processor and its context in reverse order of construction 502 515 // These were manually constructed so we need manually destroy them 503 ^( mainProcessor->runner){};504 ^( mainProcessor){};516 ^(*systemProcessor->proc.runner){}; 517 ^(systemProcessor){}; 505 518 506 519 // Final step, destroy the main thread since it is no longer needed … … 569 582 //----------------------------------------------------------------------------- 570 583 // Locks 571 void ?{}( spinlock *this ) {572 this ->lock = 0;573 } 574 void ^?{}( spinlock *this ) {584 void ?{}( spinlock & this ) { 585 this.lock = 0; 586 } 587 void ^?{}( spinlock & this ) { 575 588 576 589 } … … 606 619 } 607 620 608 void ?{}( semaphore *this, int count = 1 ) {609 ( &this->lock){};610 this ->count = count;611 ( &this->waiting){};612 } 613 void ^?{}(semaphore *this) {}621 void ?{}( semaphore & this, int count = 1 ) { 622 (this.lock){}; 623 this.count = count; 624 (this.waiting){}; 625 } 626 void ^?{}(semaphore & this) {} 614 627 615 628 void P(semaphore * this) { … … 645 658 //----------------------------------------------------------------------------- 646 659 // Queues 647 void ?{}( __thread_queue_t *this ) {648 this ->head = NULL;649 this ->tail = &this->head;660 void ?{}( __thread_queue_t & this ) { 661 this.head = NULL; 662 this.tail = &this.head; 650 663 } 651 664 … … 668 681 } 669 682 670 thread_desc * remove( __thread_queue_t * this, thread_desc ** it ) { 671 thread_desc * thrd = *it; 672 verify( thrd ); 673 674 (*it) = thrd->next; 675 676 if( this->tail == &thrd->next ) { 677 this->tail = it; 678 } 679 680 thrd->next = NULL; 681 682 verify( (this->head == NULL) == (&this->head == this->tail) ); 683 verify( *this->tail == NULL ); 684 return thrd; 685 } 686 687 688 689 void ?{}( __condition_stack_t * this ) { 690 this->top = NULL; 683 void ?{}( __condition_stack_t & this ) { 684 this.top = NULL; 691 685 } 692 686 … … 705 699 return top; 706 700 } 707 708 701 // Local Variables: // 709 702 // mode: c //
Note:
See TracChangeset
for help on using the changeset viewer.