Changes in src/libcfa/concurrency/kernel.c [4aa2fb2:2ac095d]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/libcfa/concurrency/kernel.c
r4aa2fb2 r2ac095d 15 15 // 16 16 17 #include "startup.h" 18 19 //Start and stop routine for the kernel, declared first to make sure they run first 20 void kernel_startup(void) __attribute__(( constructor( STARTUP_PRIORITY_KERNEL ) )); 21 void kernel_shutdown(void) __attribute__(( destructor ( STARTUP_PRIORITY_KERNEL ) )); 22 23 //Header 24 #include "kernel_private.h" 17 #include "libhdr.h" 25 18 26 19 //C Includes … … 35 28 36 29 //CFA Includes 37 #include " libhdr.h"30 #include "kernel_private.h" 38 31 #include "preemption.h" 32 #include "startup.h" 39 33 40 34 //Private includes 41 35 #define __CFA_INVOKE_PRIVATE__ 42 36 #include "invoke.h" 37 38 //Start and stop routine for the kernel, declared first to make sure they run first 39 void kernel_startup(void) __attribute__(( constructor( STARTUP_PRIORITY_KERNEL ) )); 40 void kernel_shutdown(void) __attribute__(( destructor ( STARTUP_PRIORITY_KERNEL ) )); 43 41 44 42 //----------------------------------------------------------------------------- … … 59 57 // Global state 60 58 61 thread_local processor * this_processor; 62 63 coroutine_desc * this_coroutine(void) { 64 return this_processor->current_coroutine; 65 } 66 67 thread_desc * this_thread(void) { 68 return this_processor->current_thread; 69 } 59 volatile thread_local processor * this_processor; 60 volatile thread_local coroutine_desc * this_coroutine; 61 volatile thread_local thread_desc * this_thread; 62 volatile thread_local unsigned short disable_preempt_count = 1; 70 63 71 64 //----------------------------------------------------------------------------- 72 65 // Main thread construction 73 66 struct current_stack_info_t { 74 machine_context_t ctx; 67 machine_context_t ctx; 75 68 unsigned int size; // size of stack 76 69 void *base; // base of stack … … 106 99 107 100 void ?{}( coroutine_desc * this, current_stack_info_t * info) { 108 (&this->stack){ info }; 101 (&this->stack){ info }; 109 102 this->name = "Main Thread"; 110 103 this->errno_ = 0; … … 136 129 void ?{}(processor * this, cluster * cltr) { 137 130 this->cltr = cltr; 138 this->current_coroutine = NULL;139 this->current_thread = NULL;140 131 (&this->terminated){}; 141 132 this->is_terminated = false; 142 133 this->preemption_alarm = NULL; 143 134 this->preemption = default_preemption(); 144 this->disable_preempt_count = 1; //Start with interrupts disabled145 135 this->pending_preemption = false; 146 136 … … 150 140 void ?{}(processor * this, cluster * cltr, processorCtx_t * runner) { 151 141 this->cltr = cltr; 152 this->current_coroutine = NULL;153 this->current_thread = NULL;154 142 (&this->terminated){}; 155 143 this->is_terminated = false; 156 this->disable_preempt_count = 0; 144 this->preemption_alarm = NULL; 145 this->preemption = default_preemption(); 157 146 this->pending_preemption = false; 147 this->kernel_thread = pthread_self(); 158 148 159 149 this->runner = runner; 160 LIB_DEBUG_PRINT_SAFE("Kernel : constructing processor context %p\n", runner);150 LIB_DEBUG_PRINT_SAFE("Kernel : constructing system processor context %p\n", runner); 161 151 runner{ this }; 162 152 } 153 154 LIB_DEBUG_DO( bool validate( alarm_list_t * this ); ) 163 155 164 156 void ?{}(system_proc_t * this, cluster * cltr, processorCtx_t * runner) { … … 168 160 169 161 (&this->proc){ cltr, runner }; 162 163 verify( validate( &this->alarms ) ); 170 164 } 171 165 … … 184 178 185 179 void ^?{}(cluster * this) { 186 180 187 181 } 188 182 … … 203 197 204 198 thread_desc * readyThread = NULL; 205 for( unsigned int spin_count = 0; ! this->is_terminated; spin_count++ ) 199 for( unsigned int spin_count = 0; ! this->is_terminated; spin_count++ ) 206 200 { 207 201 readyThread = nextThread( this->cltr ); … … 209 203 if(readyThread) 210 204 { 205 verify( disable_preempt_count > 0 ); 206 211 207 runThread(this, readyThread); 208 209 verify( disable_preempt_count > 0 ); 212 210 213 211 //Some actions need to be taken from the kernel … … 229 227 } 230 228 231 // runThread runs a thread by context switching 232 // from the processor coroutine to the target thread 229 // runThread runs a thread by context switching 230 // from the processor coroutine to the target thread 233 231 void runThread(processor * this, thread_desc * dst) { 234 232 coroutine_desc * proc_cor = get_coroutine(this->runner); 235 233 coroutine_desc * thrd_cor = get_coroutine(dst); 236 234 237 235 //Reset the terminating actions here 238 236 this->finish.action_code = No_Action; 239 237 240 238 //Update global state 241 this ->current_thread = dst;239 this_thread = dst; 242 240 243 241 // Context Switch to the thread … … 246 244 } 247 245 248 // Once a thread has finished running, some of 246 // Once a thread has finished running, some of 249 247 // its final actions must be executed from the kernel 250 248 void finishRunning(processor * this) { … … 256 254 } 257 255 else if( this->finish.action_code == Release_Schedule ) { 258 unlock( this->finish.lock ); 256 unlock( this->finish.lock ); 259 257 ScheduleThread( this->finish.thrd ); 260 258 } … … 289 287 processor * proc = (processor *) arg; 290 288 this_processor = proc; 289 this_coroutine = NULL; 290 this_thread = NULL; 291 disable_preempt_count = 1; 291 292 // SKULLDUGGERY: We want to create a context for the processor coroutine 292 293 // which is needed for the 2-step context switch. However, there is no reason 293 // to waste the perfectly valid stack create by pthread. 294 // to waste the perfectly valid stack create by pthread. 294 295 current_stack_info_t info; 295 296 machine_context_t ctx; … … 300 301 301 302 //Set global state 302 proc->current_coroutine = &proc->runner->__cor;303 proc->current_thread = NULL;303 this_coroutine = &proc->runner->__cor; 304 this_thread = NULL; 304 305 305 306 //We now have a proper context from which to schedule threads 306 307 LIB_DEBUG_PRINT_SAFE("Kernel : core %p created (%p, %p)\n", proc, proc->runner, &ctx); 307 308 308 // SKULLDUGGERY: Since the coroutine doesn't have its own stack, we can't 309 // resume it to start it like it normally would, it will just context switch 310 // back to here. Instead directly call the main since we already are on the 309 // SKULLDUGGERY: Since the coroutine doesn't have its own stack, we can't 310 // resume it to start it like it normally would, it will just context switch 311 // back to here. Instead directly call the main since we already are on the 311 312 // appropriate stack. 312 313 proc_cor_storage.__cor.state = Active; … … 315 316 316 317 // Main routine of the core returned, the core is now fully terminated 317 LIB_DEBUG_PRINT_SAFE("Kernel : core %p main ended (%p)\n", proc, proc->runner); 318 LIB_DEBUG_PRINT_SAFE("Kernel : core %p main ended (%p)\n", proc, proc->runner); 318 319 319 320 return NULL; … … 322 323 void start(processor * this) { 323 324 LIB_DEBUG_PRINT_SAFE("Kernel : Starting core %p\n", this); 324 325 326 // SIGALRM must only be caught by the system processor 327 sigset_t old_mask; 328 bool is_system_proc = this_processor == &systemProcessor->proc; 329 if ( is_system_proc ) { 330 // Child kernel-thread inherits the signal mask from the parent kernel-thread. So one special case for the 331 // system processor creating the user processor => toggle the blocking SIGALRM on system processor, create user 332 // processor, and toggle back (below) previous signal mask of the system processor. 333 334 sigset_t new_mask; 335 sigemptyset( &new_mask ); 336 sigemptyset( &old_mask ); 337 sigaddset( &new_mask, SIGALRM ); 338 339 if ( sigprocmask( SIG_BLOCK, &new_mask, &old_mask ) == -1 ) { 340 abortf( "internal error, sigprocmask" ); 341 } 342 343 assert( ! sigismember( &old_mask, SIGALRM ) ); 344 } 345 325 346 pthread_create( &this->kernel_thread, NULL, CtxInvokeProcessor, (void*)this ); 326 347 327 LIB_DEBUG_PRINT_SAFE("Kernel : core %p started\n", this); 348 // Toggle back previous signal mask of system processor. 349 if ( is_system_proc ) { 350 if ( sigprocmask( SIG_SETMASK, &old_mask, NULL ) == -1 ) { 351 abortf( "internal error, sigprocmask" ); 352 } // if 353 } // if 354 355 LIB_DEBUG_PRINT_SAFE("Kernel : core %p started\n", this); 328 356 } 329 357 … … 331 359 // Scheduler routines 332 360 void ScheduleThread( thread_desc * thrd ) { 333 if( !thrd ) return; 361 // if( !thrd ) return; 362 assert( thrd ); 363 assert( thrd->cor.state != Halted ); 364 365 verify( disable_preempt_count > 0 ); 334 366 335 367 verifyf( thrd->next == NULL, "Expected null got %p", thrd->next ); 336 337 lock( &systemProcessor->proc.cltr->lock );368 369 lock( &systemProcessor->proc.cltr->lock DEBUG_CTX2 ); 338 370 append( &systemProcessor->proc.cltr->ready_queue, thrd ); 339 371 unlock( &systemProcessor->proc.cltr->lock ); 372 373 verify( disable_preempt_count > 0 ); 340 374 } 341 375 342 376 thread_desc * nextThread(cluster * this) { 343 lock( &this->lock ); 377 verify( disable_preempt_count > 0 ); 378 lock( &this->lock DEBUG_CTX2 ); 344 379 thread_desc * head = pop_head( &this->ready_queue ); 345 380 unlock( &this->lock ); 381 verify( disable_preempt_count > 0 ); 346 382 return head; 347 383 } 348 384 349 void ScheduleInternal() { 385 void BlockInternal() { 386 disable_interrupts(); 387 verify( disable_preempt_count > 0 ); 350 388 suspend(); 351 } 352 353 void ScheduleInternal( spinlock * lock ) { 389 verify( disable_preempt_count > 0 ); 390 enable_interrupts( DEBUG_CTX ); 391 } 392 393 void BlockInternal( spinlock * lock ) { 394 disable_interrupts(); 354 395 this_processor->finish.action_code = Release; 355 396 this_processor->finish.lock = lock; 397 398 verify( disable_preempt_count > 0 ); 356 399 suspend(); 357 } 358 359 void ScheduleInternal( thread_desc * thrd ) { 400 verify( disable_preempt_count > 0 ); 401 402 enable_interrupts( DEBUG_CTX ); 403 } 404 405 void BlockInternal( thread_desc * thrd ) { 406 disable_interrupts(); 407 assert( thrd->cor.state != Halted ); 360 408 this_processor->finish.action_code = Schedule; 361 409 this_processor->finish.thrd = thrd; 410 411 verify( disable_preempt_count > 0 ); 362 412 suspend(); 363 } 364 365 void ScheduleInternal( spinlock * lock, thread_desc * thrd ) { 413 verify( disable_preempt_count > 0 ); 414 415 enable_interrupts( DEBUG_CTX ); 416 } 417 418 void BlockInternal( spinlock * lock, thread_desc * thrd ) { 419 disable_interrupts(); 366 420 this_processor->finish.action_code = Release_Schedule; 367 421 this_processor->finish.lock = lock; 368 422 this_processor->finish.thrd = thrd; 423 424 verify( disable_preempt_count > 0 ); 369 425 suspend(); 370 } 371 372 void ScheduleInternal(spinlock ** locks, unsigned short count) { 426 verify( disable_preempt_count > 0 ); 427 428 enable_interrupts( DEBUG_CTX ); 429 } 430 431 void BlockInternal(spinlock ** locks, unsigned short count) { 432 disable_interrupts(); 373 433 this_processor->finish.action_code = Release_Multi; 374 434 this_processor->finish.locks = locks; 375 435 this_processor->finish.lock_count = count; 436 437 verify( disable_preempt_count > 0 ); 376 438 suspend(); 377 } 378 379 void ScheduleInternal(spinlock ** locks, unsigned short lock_count, thread_desc ** thrds, unsigned short thrd_count) { 439 verify( disable_preempt_count > 0 ); 440 441 enable_interrupts( DEBUG_CTX ); 442 } 443 444 void BlockInternal(spinlock ** locks, unsigned short lock_count, thread_desc ** thrds, unsigned short thrd_count) { 445 disable_interrupts(); 380 446 this_processor->finish.action_code = Release_Multi_Schedule; 381 447 this_processor->finish.locks = locks; … … 383 449 this_processor->finish.thrds = thrds; 384 450 this_processor->finish.thrd_count = thrd_count; 451 452 verify( disable_preempt_count > 0 ); 385 453 suspend(); 454 verify( disable_preempt_count > 0 ); 455 456 enable_interrupts( DEBUG_CTX ); 386 457 } 387 458 … … 392 463 // Kernel boot procedures 393 464 void kernel_startup(void) { 394 LIB_DEBUG_PRINT_SAFE("Kernel : Starting\n"); 465 LIB_DEBUG_PRINT_SAFE("Kernel : Starting\n"); 395 466 396 467 // Start by initializing the main thread 397 // SKULLDUGGERY: the mainThread steals the process main thread 468 // SKULLDUGGERY: the mainThread steals the process main thread 398 469 // which will then be scheduled by the systemProcessor normally 399 470 mainThread = (thread_desc *)&mainThread_storage; … … 403 474 LIB_DEBUG_PRINT_SAFE("Kernel : Main thread ready\n"); 404 475 405 // Enable preemption406 kernel_start_preemption();407 408 476 // Initialize the system cluster 409 477 systemCluster = (cluster *)&systemCluster_storage; … … 417 485 systemProcessor{ systemCluster, (processorCtx_t *)&systemProcessorCtx_storage }; 418 486 419 // Add the main thread to the ready queue 487 // Add the main thread to the ready queue 420 488 // once resume is called on systemProcessor->runner the mainThread needs to be scheduled like any normal thread 421 489 ScheduleThread(mainThread); … … 423 491 //initialize the global state variables 424 492 this_processor = &systemProcessor->proc; 425 this_processor->current_thread = mainThread; 426 this_processor->current_coroutine = &mainThread->cor; 493 this_thread = mainThread; 494 this_coroutine = &mainThread->cor; 495 disable_preempt_count = 1; 496 497 // Enable preemption 498 kernel_start_preemption(); 427 499 428 500 // SKULLDUGGERY: Force a context switch to the system processor to set the main thread's context to the current UNIX 429 501 // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that 430 // mainThread is on the ready queue when this call is made. 502 // mainThread is on the ready queue when this call is made. 431 503 resume( systemProcessor->proc.runner ); 432 504 … … 435 507 // THE SYSTEM IS NOW COMPLETELY RUNNING 436 508 LIB_DEBUG_PRINT_SAFE("Kernel : Started\n--------------------------------------------------\n\n"); 509 510 enable_interrupts( DEBUG_CTX ); 437 511 } 438 512 439 513 void kernel_shutdown(void) { 440 514 LIB_DEBUG_PRINT_SAFE("\n--------------------------------------------------\nKernel : Shutting down\n"); 515 516 disable_interrupts(); 441 517 442 518 // SKULLDUGGERY: Notify the systemProcessor it needs to terminates. … … 448 524 // THE SYSTEM IS NOW COMPLETELY STOPPED 449 525 526 // Disable preemption 527 kernel_stop_preemption(); 528 450 529 // Destroy the system processor and its context in reverse order of construction 451 530 // These were manually constructed so we need manually destroy them … … 457 536 ^(mainThread){}; 458 537 459 LIB_DEBUG_PRINT_SAFE("Kernel : Shutdown complete\n"); 538 LIB_DEBUG_PRINT_SAFE("Kernel : Shutdown complete\n"); 460 539 } 461 540 … … 467 546 // abort cannot be recursively entered by the same or different processors because all signal handlers return when 468 547 // the globalAbort flag is true. 469 lock( &kernel_abort_lock );548 lock( &kernel_abort_lock DEBUG_CTX2 ); 470 549 471 550 // first task to abort ? … … 473 552 kernel_abort_called = true; 474 553 unlock( &kernel_abort_lock ); 475 } 554 } 476 555 else { 477 556 unlock( &kernel_abort_lock ); 478 557 479 558 sigset_t mask; 480 559 sigemptyset( &mask ); … … 482 561 sigaddset( &mask, SIGUSR1 ); // block SIGUSR1 signals 483 562 sigsuspend( &mask ); // block the processor to prevent further damage during abort 484 _exit( EXIT_FAILURE ); // if processor unblocks before it is killed, terminate it 485 } 486 487 return this_thread ();563 _exit( EXIT_FAILURE ); // if processor unblocks before it is killed, terminate it 564 } 565 566 return this_thread; 488 567 } 489 568 … … 494 573 __lib_debug_write( STDERR_FILENO, abort_text, len ); 495 574 496 if ( thrd != this_coroutine ()) {497 len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", this_coroutine ()->name, this_coroutine());575 if ( thrd != this_coroutine ) { 576 len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", this_coroutine->name, this_coroutine ); 498 577 __lib_debug_write( STDERR_FILENO, abort_text, len ); 499 } 578 } 500 579 else { 501 580 __lib_debug_write( STDERR_FILENO, ".\n", 2 ); … … 505 584 extern "C" { 506 585 void __lib_debug_acquire() { 507 lock( &kernel_debug_lock);586 lock( &kernel_debug_lock DEBUG_CTX2 ); 508 587 } 509 588 510 589 void __lib_debug_release() { 511 unlock( &kernel_debug_lock);590 unlock( &kernel_debug_lock ); 512 591 } 513 592 } … … 525 604 } 526 605 527 bool try_lock( spinlock * this ) { 528 return this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0; 529 } 530 531 void lock( spinlock * this ) { 606 bool try_lock( spinlock * this DEBUG_CTX_PARAM2 ) { 607 bool ret = this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0; 608 LIB_DEBUG_DO( this->prev = caller; ) 609 return ret; 610 } 611 612 void lock( spinlock * this DEBUG_CTX_PARAM2 ) { 532 613 for ( unsigned int i = 1;; i += 1 ) { 533 614 if ( this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0 ) break; 534 615 } 616 LIB_DEBUG_DO( this->prev = caller; ) 535 617 } 536 618 … … 547 629 548 630 void wait( signal_once * this ) { 549 lock( &this->lock );631 lock( &this->lock DEBUG_CTX2 ); 550 632 if( !this->cond ) { 551 append( &this->blocked, this_thread() ); 552 ScheduleInternal( &this->lock ); 553 lock( &this->lock ); 554 } 555 unlock( &this->lock ); 633 append( &this->blocked, (thread_desc*)this_thread ); 634 BlockInternal( &this->lock ); 635 } 636 else { 637 unlock( &this->lock ); 638 } 556 639 } 557 640 558 641 void signal( signal_once * this ) { 559 lock( &this->lock );642 lock( &this->lock DEBUG_CTX2 ); 560 643 { 561 644 this->cond = true; 562 645 646 disable_interrupts(); 563 647 thread_desc * it; 564 648 while( it = pop_head( &this->blocked) ) { 565 649 ScheduleThread( it ); 566 650 } 651 enable_interrupts( DEBUG_CTX ); 567 652 } 568 653 unlock( &this->lock ); … … 590 675 } 591 676 head->next = NULL; 592 } 677 } 593 678 return head; 594 679 } … … 609 694 this->top = top->next; 610 695 top->next = NULL; 611 } 696 } 612 697 return top; 613 698 }
Note: See TracChangeset
for help on using the changeset viewer.