- File:
-
- 1 edited
-
libcfa/src/concurrency/kernel.cfa (modified) (40 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/kernel.cfa
re3fea42 ra7b486b 15 15 16 16 #define __cforall_thread__ 17 // #define __CFA_DEBUG_PRINT_RUNTIME_CORE__ 17 18 18 19 //C Includes … … 40 41 #include "invoke.h" 41 42 43 42 44 //----------------------------------------------------------------------------- 43 45 // Some assembly required … … 110 112 //----------------------------------------------------------------------------- 111 113 //Start and stop routine for the kernel, declared first to make sure they run first 112 static void kernel_startup(void) __attribute__(( constructor( STARTUP_PRIORITY_KERNEL ) )); 113 static void kernel_shutdown(void) __attribute__(( destructor ( STARTUP_PRIORITY_KERNEL ) )); 114 static void __kernel_startup (void) __attribute__(( constructor( STARTUP_PRIORITY_KERNEL ) )); 115 static void __kernel_shutdown(void) __attribute__(( destructor ( STARTUP_PRIORITY_KERNEL ) )); 116 117 //----------------------------------------------------------------------------- 118 // Kernel Scheduling logic 119 static $thread * __next_thread(cluster * this); 120 static void __run_thread(processor * this, $thread * dst); 121 static $thread * __halt(processor * this); 122 static bool __wake_one(cluster * cltr, bool was_empty); 123 static bool __wake_proc(processor *); 114 124 115 125 //----------------------------------------------------------------------------- … … 117 127 KERNEL_STORAGE(cluster, mainCluster); 118 128 KERNEL_STORAGE(processor, mainProcessor); 119 KERNEL_STORAGE( thread_desc, mainThread);129 KERNEL_STORAGE($thread, mainThread); 120 130 KERNEL_STORAGE(__stack_t, mainThreadCtx); 121 131 122 132 cluster * mainCluster; 123 133 processor * mainProcessor; 124 thread_desc* mainThread;134 $thread * mainThread; 125 135 126 136 extern "C" { … … 164 174 // Main thread construction 165 175 166 void ?{}( coroutine_desc& this, current_stack_info_t * info) with( this ) {176 void ?{}( $coroutine & this, current_stack_info_t * info) with( this ) { 167 177 stack.storage = info->storage; 168 178 with(*stack.storage) { … … 179 189 } 180 190 181 void ?{}( thread_desc& this, current_stack_info_t * info) with( this ) {191 void ?{}( $thread & this, current_stack_info_t * info) with( this ) { 182 192 state = Start; 183 193 self_cor{ info }; … … 208 218 } 209 219 210 static void start(processor * this); 220 static void * __invoke_processor(void * arg); 221 211 222 void ?{}(processor & this, const char name[], cluster & cltr) with( this ) { 212 223 this.name = name; 213 224 this.cltr = &cltr; 214 225 terminated{ 0 }; 226 destroyer = 0p; 215 227 do_terminate = false; 216 228 preemption_alarm = 0p; … … 218 230 runner.proc = &this; 219 231 220 idleLock{}; 221 222 start( &this ); 232 idle{}; 233 234 __cfadbg_print_safe(runtime_core, "Kernel : Starting core %p\n", &this); 235 236 this.stack = __create_pthread( &this.kernel_thread, __invoke_processor, (void *)&this ); 237 238 __cfadbg_print_safe(runtime_core, "Kernel : core %p created\n", &this); 223 239 } 224 240 225 241 void ^?{}(processor & this) with( this ){ 226 242 if( ! __atomic_load_n(&do_terminate, __ATOMIC_ACQUIRE) ) { 227 __cfa abi_dbg_print_safe("Kernel : core %p signaling termination\n", &this);243 __cfadbg_print_safe(runtime_core, "Kernel : core %p signaling termination\n", &this); 228 244 229 245 __atomic_store_n(&do_terminate, true, __ATOMIC_RELAXED); 230 wake( &this );246 __wake_proc( &this ); 231 247 232 248 P( terminated ); … … 234 250 } 235 251 236 pthread_join( kernel_thread, 0p ); 252 int err = pthread_join( kernel_thread, 0p ); 253 if( err != 0 ) abort("KERNEL ERROR: joining processor %p caused error %s\n", &this, strerror(err)); 254 237 255 free( this.stack ); 238 256 } 239 257 240 void ?{}(cluster & this, const char name[], Duration preemption_rate ) with( this ) {258 void ?{}(cluster & this, const char name[], Duration preemption_rate, int io_flags) with( this ) { 241 259 this.name = name; 242 260 this.preemption_rate = preemption_rate; … … 244 262 ready_queue_lock{}; 245 263 264 #if !defined(__CFA_NO_STATISTICS__) 265 print_stats = false; 266 #endif 267 246 268 procs{ __get }; 247 269 idles{ __get }; 248 270 threads{ __get }; 249 271 272 __kernel_io_startup( this, io_flags, &this == mainCluster ); 273 250 274 doregister(this); 251 275 } 252 276 253 277 void ^?{}(cluster & this) { 278 __kernel_io_shutdown( this, &this == mainCluster ); 279 254 280 unregister(this); 255 281 } … … 258 284 // Kernel Scheduling logic 259 285 //============================================================================================= 260 static void runThread(processor * this, thread_desc * dst);261 static void finishRunning(processor * this);262 static void halt(processor * this);263 264 286 //Main of the processor contexts 265 287 void main(processorCtx_t & runner) { … … 271 293 verify(this); 272 294 273 __cfa abi_dbg_print_safe("Kernel : core %p starting\n", this);295 __cfadbg_print_safe(runtime_core, "Kernel : core %p starting\n", this); 274 296 275 297 doregister(this->cltr, this); … … 279 301 preemption_scope scope = { this }; 280 302 281 __cfa abi_dbg_print_safe("Kernel : core %p started\n", this);282 283 thread_desc* readyThread = 0p;303 __cfadbg_print_safe(runtime_core, "Kernel : core %p started\n", this); 304 305 $thread * readyThread = 0p; 284 306 for( unsigned int spin_count = 0; ! __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST); spin_count++ ) { 285 readyThread = nextThread( this->cltr ); 286 287 if(readyThread) { 288 verify( ! kernelTLS.preemption_state.enabled ); 289 290 runThread(this, readyThread); 291 292 verify( ! kernelTLS.preemption_state.enabled ); 293 294 //Some actions need to be taken from the kernel 295 finishRunning(this); 296 297 spin_count = 0; 298 } else { 299 // spin(this, &spin_count); 300 halt(this); 307 // Try to get the next thread 308 readyThread = __next_thread( this->cltr ); 309 310 // If no ready thread 311 if( readyThread == 0p ) { 312 // Block until a thread is ready 313 readyThread = __halt(this); 314 } 315 316 // Check if we actually found a thread 317 if( readyThread ) { 318 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 319 /* paranoid */ verifyf( readyThread->state == Ready || readyThread->preempted != __NO_PREEMPTION, "state : %d, preempted %d\n", readyThread->state, readyThread->preempted); 320 /* paranoid */ verifyf( readyThread->next == 0p, "Expected null got %p", readyThread->next ); 321 322 // We found a thread run it 323 __run_thread(this, readyThread); 324 325 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 301 326 } 302 327 } 303 328 304 __cfa abi_dbg_print_safe("Kernel : core %p stopping\n", this);329 __cfadbg_print_safe(runtime_core, "Kernel : core %p stopping\n", this); 305 330 } 306 331 … … 309 334 V( this->terminated ); 310 335 311 __cfaabi_dbg_print_safe("Kernel : core %p terminated\n", this); 336 __cfadbg_print_safe(runtime_core, "Kernel : core %p terminated\n", this); 337 338 // HACK : the coroutine context switch expects this_thread to be set 339 // and it make sense for it to be set in all other cases except here 340 // fake it 341 if( this == mainProcessor ) kernelTLS.this_thread = mainThread; 312 342 } 313 343 … … 318 348 // runThread runs a thread by context switching 319 349 // from the processor coroutine to the target thread 320 static void runThread(processor * this, thread_desc * thrd_dst) { 321 coroutine_desc * proc_cor = get_coroutine(this->runner); 322 323 // Reset the terminating actions here 324 this->finish.action_code = No_Action; 350 static void __run_thread(processor * this, $thread * thrd_dst) { 351 $coroutine * proc_cor = get_coroutine(this->runner); 325 352 326 353 // Update global state 327 354 kernelTLS.this_thread = thrd_dst; 328 355 329 // set state of processor coroutine to inactive and the thread to active 330 proc_cor->state = proc_cor->state == Halted ? Halted : Inactive; 331 thrd_dst->state = Active; 332 333 // set context switch to the thread that the processor is executing 334 verify( thrd_dst->context.SP ); 335 CtxSwitch( &proc_cor->context, &thrd_dst->context ); 336 // when CtxSwitch returns we are back in the processor coroutine 337 338 // set state of processor coroutine to active and the thread to inactive 339 thrd_dst->state = thrd_dst->state == Halted ? Halted : Inactive; 356 // set state of processor coroutine to inactive 357 verify(proc_cor->state == Active); 358 proc_cor->state = Blocked; 359 360 // Actually run the thread 361 RUNNING: while(true) { 362 if(unlikely(thrd_dst->preempted)) { 363 thrd_dst->preempted = __NO_PREEMPTION; 364 verify(thrd_dst->state == Active || thrd_dst->state == Rerun); 365 } else { 366 verify(thrd_dst->state == Blocked || thrd_dst->state == Ready); // Ready means scheduled normally, blocked means rerun 367 thrd_dst->state = Active; 368 } 369 370 __cfaabi_dbg_debug_do( 371 thrd_dst->park_stale = true; 372 thrd_dst->unpark_stale = true; 373 ) 374 375 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 376 /* paranoid */ verify( kernelTLS.this_thread == thrd_dst ); 377 /* 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 378 /* 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 379 380 // set context switch to the thread that the processor is executing 381 verify( thrd_dst->context.SP ); 382 __cfactx_switch( &proc_cor->context, &thrd_dst->context ); 383 // when __cfactx_switch returns we are back in the processor coroutine 384 385 /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) > ((uintptr_t)__get_stack(thrd_dst->curr_cor)->limit), "ERROR : Destination $thread %p has been corrupted.\n StackPointer too large.\n", thrd_dst ); 386 /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) < ((uintptr_t)__get_stack(thrd_dst->curr_cor)->base ), "ERROR : Destination $thread %p has been corrupted.\n StackPointer too small.\n", thrd_dst ); 387 /* paranoid */ verify( kernelTLS.this_thread == thrd_dst ); 388 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 389 390 391 // We just finished running a thread, there are a few things that could have happened. 392 // 1 - Regular case : the thread has blocked and now one has scheduled it yet. 393 // 2 - Racy case : the thread has blocked but someone has already tried to schedule it. 394 // 4 - Preempted 395 // In case 1, we may have won a race so we can't write to the state again. 396 // In case 2, we lost the race so we now own the thread. 397 398 if(unlikely(thrd_dst->preempted != __NO_PREEMPTION)) { 399 // The thread was preempted, reschedule it and reset the flag 400 __schedule_thread( thrd_dst ); 401 break RUNNING; 402 } 403 404 // set state of processor coroutine to active and the thread to inactive 405 static_assert(sizeof(thrd_dst->state) == sizeof(int)); 406 enum coroutine_state old_state = __atomic_exchange_n(&thrd_dst->state, Blocked, __ATOMIC_SEQ_CST); 407 __cfaabi_dbg_debug_do( thrd_dst->park_result = old_state; ) 408 switch(old_state) { 409 case Halted: 410 // The thread has halted, it should never be scheduled/run again, leave it back to Halted and move on 411 thrd_dst->state = Halted; 412 413 // We may need to wake someone up here since 414 unpark( this->destroyer __cfaabi_dbg_ctx2 ); 415 this->destroyer = 0p; 416 break RUNNING; 417 case Active: 418 // This is case 1, the regular case, nothing more is needed 419 break RUNNING; 420 case Rerun: 421 // This is case 2, the racy case, someone tried to run this thread before it finished blocking 422 // In this case, just run it again. 423 continue RUNNING; 424 default: 425 // This makes no sense, something is wrong abort 426 abort("Finished running a thread that was Blocked/Start/Primed %d\n", old_state); 427 } 428 } 429 430 // Just before returning to the processor, set the processor coroutine to active 340 431 proc_cor->state = Active; 432 kernelTLS.this_thread = 0p; 341 433 } 342 434 343 435 // KERNEL_ONLY 344 static void returnToKernel() { 345 coroutine_desc * proc_cor = get_coroutine(kernelTLS.this_processor->runner); 346 thread_desc * thrd_src = kernelTLS.this_thread; 347 348 // set state of current coroutine to inactive 349 thrd_src->state = thrd_src->state == Halted ? Halted : Inactive; 350 proc_cor->state = Active; 351 int local_errno = *__volatile_errno(); 352 #if defined( __i386 ) || defined( __x86_64 ) 353 __x87_store; 354 #endif 355 356 // set new coroutine that the processor is executing 357 // and context switch to it 358 verify( proc_cor->context.SP ); 359 CtxSwitch( &thrd_src->context, &proc_cor->context ); 360 361 // set state of new coroutine to active 362 proc_cor->state = proc_cor->state == Halted ? Halted : Inactive; 363 thrd_src->state = Active; 364 365 #if defined( __i386 ) || defined( __x86_64 ) 366 __x87_load; 367 #endif 368 *__volatile_errno() = local_errno; 369 } 370 371 // KERNEL_ONLY 372 // Once a thread has finished running, some of 373 // its final actions must be executed from the kernel 374 static void finishRunning(processor * this) with( this->finish ) { 375 verify( ! kernelTLS.preemption_state.enabled ); 376 choose( action_code ) { 377 case No_Action: 378 break; 379 case Release: 380 unlock( *lock ); 381 case Schedule: 382 ScheduleThread( thrd ); 383 case Release_Schedule: 384 unlock( *lock ); 385 ScheduleThread( thrd ); 386 case Release_Multi: 387 for(int i = 0; i < lock_count; i++) { 388 unlock( *locks[i] ); 389 } 390 case Release_Multi_Schedule: 391 for(int i = 0; i < lock_count; i++) { 392 unlock( *locks[i] ); 393 } 394 for(int i = 0; i < thrd_count; i++) { 395 ScheduleThread( thrds[i] ); 396 } 397 case Callback: 398 callback(); 399 default: 400 abort("KERNEL ERROR: Unexpected action to run after thread"); 401 } 436 void returnToKernel() { 437 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 438 $coroutine * proc_cor = get_coroutine(kernelTLS.this_processor->runner); 439 $thread * thrd_src = kernelTLS.this_thread; 440 441 // Run the thread on this processor 442 { 443 int local_errno = *__volatile_errno(); 444 #if defined( __i386 ) || defined( __x86_64 ) 445 __x87_store; 446 #endif 447 verify( proc_cor->context.SP ); 448 __cfactx_switch( &thrd_src->context, &proc_cor->context ); 449 #if defined( __i386 ) || defined( __x86_64 ) 450 __x87_load; 451 #endif 452 *__volatile_errno() = local_errno; 453 } 454 455 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 456 /* paranoid */ verifyf( ((uintptr_t)thrd_src->context.SP) < ((uintptr_t)__get_stack(thrd_src->curr_cor)->base ), "ERROR : Returning $thread %p has been corrupted.\n StackPointer too small.\n", thrd_src ); 457 /* paranoid */ verifyf( ((uintptr_t)thrd_src->context.SP) > ((uintptr_t)__get_stack(thrd_src->curr_cor)->limit), "ERROR : Returning $thread %p has been corrupted.\n StackPointer too large.\n", thrd_src ); 402 458 } 403 459 … … 406 462 // This is the entry point for processors (kernel threads) 407 463 // It effectively constructs a coroutine by stealing the pthread stack 408 static void * CtxInvokeProcessor(void * arg) {464 static void * __invoke_processor(void * arg) { 409 465 processor * proc = (processor *) arg; 410 466 kernelTLS.this_processor = proc; … … 425 481 426 482 //We now have a proper context from which to schedule threads 427 __cfa abi_dbg_print_safe("Kernel : core %p created (%p, %p)\n", proc, &proc->runner, &ctx);483 __cfadbg_print_safe(runtime_core, "Kernel : core %p created (%p, %p)\n", proc, &proc->runner, &ctx); 428 484 429 485 // SKULLDUGGERY: Since the coroutine doesn't have its own stack, we can't … … 436 492 437 493 // Main routine of the core returned, the core is now fully terminated 438 __cfa abi_dbg_print_safe("Kernel : core %p main ended (%p)\n", proc, &proc->runner);494 __cfadbg_print_safe(runtime_core, "Kernel : core %p main ended (%p)\n", proc, &proc->runner); 439 495 440 496 return 0p; … … 447 503 } // Abort 448 504 449 void * create_pthread( pthread_t * pthread, void * (*start)(void *), void * arg ) {505 void * __create_pthread( pthread_t * pthread, void * (*start)(void *), void * arg ) { 450 506 pthread_attr_t attr; 451 507 … … 469 525 ); 470 526 471 Abort( pthread_attr_setstack( &attr, stack, stacksize ), "pthread_attr_setstack" ); 527 Abort( pthread_attr_setstack( &attr, stack, stacksize ), "pthread_attr_setstack" ); 472 528 473 529 Abort( pthread_create( pthread, &attr, start, arg ), "pthread_create" ); … … 475 531 } 476 532 477 static void start(processor * this) {478 __cfaabi_dbg_print_safe("Kernel : Starting core %p\n", this);479 480 this->stack = create_pthread( &this->kernel_thread, CtxInvokeProcessor, (void *)this );481 482 __cfaabi_dbg_print_safe("Kernel : core %p started\n", this);483 }484 485 533 // KERNEL_ONLY 486 voidkernel_first_resume( processor * this ) {487 thread_desc* src = mainThread;488 coroutine_desc* dst = get_coroutine(this->runner);534 static void __kernel_first_resume( processor * this ) { 535 $thread * src = mainThread; 536 $coroutine * dst = get_coroutine(this->runner); 489 537 490 538 verify( ! kernelTLS.preemption_state.enabled ); 491 539 540 kernelTLS.this_thread->curr_cor = dst; 492 541 __stack_prepare( &dst->stack, 65000 ); 493 CtxStart(&this->runner, CtxInvokeCoroutine);542 __cfactx_start(main, dst, this->runner, __cfactx_invoke_coroutine); 494 543 495 544 verify( ! kernelTLS.preemption_state.enabled ); … … 498 547 dst->starter = dst->starter ? dst->starter : &src->self_cor; 499 548 500 // set state of current coroutine to inactive501 src->state = src->state == Halted ? Halted : Inactive;549 // make sure the current state is still correct 550 /* paranoid */ verify(src->state == Ready); 502 551 503 552 // context switch to specified coroutine 504 553 verify( dst->context.SP ); 505 CtxSwitch( &src->context, &dst->context ); 506 // when CtxSwitch returns we are back in the src coroutine 507 508 // set state of new coroutine to active 509 src->state = Active; 554 __cfactx_switch( &src->context, &dst->context ); 555 // when __cfactx_switch returns we are back in the src coroutine 556 557 mainThread->curr_cor = &mainThread->self_cor; 558 559 // make sure the current state has been update 560 /* paranoid */ verify(src->state == Active); 510 561 511 562 verify( ! kernelTLS.preemption_state.enabled ); … … 513 564 514 565 // KERNEL_ONLY 515 voidkernel_last_resume( processor * this ) {516 coroutine_desc* src = &mainThread->self_cor;517 coroutine_desc* dst = get_coroutine(this->runner);566 static void __kernel_last_resume( processor * this ) { 567 $coroutine * src = &mainThread->self_cor; 568 $coroutine * dst = get_coroutine(this->runner); 518 569 519 570 verify( ! kernelTLS.preemption_state.enabled ); … … 521 572 verify( dst->context.SP ); 522 573 574 // SKULLDUGGERY in debug the processors check that the 575 // stack is still within the limit of the stack limits after running a thread. 576 // that check doesn't make sense if we context switch to the processor using the 577 // coroutine semantics. Since this is a special case, use the current context 578 // info to populate these fields. 579 __cfaabi_dbg_debug_do( 580 __stack_context_t ctx; 581 CtxGet( ctx ); 582 mainThread->context.SP = ctx.SP; 583 mainThread->context.FP = ctx.FP; 584 ) 585 523 586 // context switch to the processor 524 CtxSwitch( &src->context, &dst->context );587 __cfactx_switch( &src->context, &dst->context ); 525 588 } 526 589 527 590 //----------------------------------------------------------------------------- 528 591 // Scheduler routines 529 530 592 // KERNEL ONLY 531 void ScheduleThread( thread_desc * thrd ) { 532 verify( thrd ); 533 verify( thrd->state != Halted ); 534 535 verify( ! kernelTLS.preemption_state.enabled ); 536 537 verifyf( thrd->next == 0p, "Expected null got %p", thrd->next ); 538 539 with( *thrd->curr_cluster ) { 540 lock ( ready_queue_lock __cfaabi_dbg_ctx2 ); 541 bool was_empty = !(ready_queue != 0); 542 append( ready_queue, thrd ); 543 unlock( ready_queue_lock ); 544 545 if(was_empty) { 546 lock (proc_list_lock __cfaabi_dbg_ctx2); 547 if(idles) { 548 wake_fast(idles.head); 549 } 550 unlock (proc_list_lock); 551 } 552 else if( struct processor * idle = idles.head ) { 553 wake_fast(idle); 554 } 555 556 } 557 558 verify( ! kernelTLS.preemption_state.enabled ); 593 void __schedule_thread( $thread * thrd ) with( *thrd->curr_cluster ) { 594 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 595 /* paranoid */ #if defined( __CFA_WITH_VERIFY__ ) 596 /* paranoid */ if( thrd->state == Blocked || thrd->state == Start ) assertf( thrd->preempted == __NO_PREEMPTION, 597 "Error inactive thread marked as preempted, state %d, preemption %d\n", thrd->state, thrd->preempted ); 598 /* paranoid */ if( thrd->preempted != __NO_PREEMPTION ) assertf(thrd->state == Active || thrd->state == Rerun, 599 "Error preempted thread marked as not currently running, state %d, preemption %d\n", thrd->state, thrd->preempted ); 600 /* paranoid */ #endif 601 /* paranoid */ verifyf( thrd->next == 0p, "Expected null got %p", thrd->next ); 602 603 if (thrd->preempted == __NO_PREEMPTION) thrd->state = Ready; 604 605 lock ( ready_queue_lock __cfaabi_dbg_ctx2 ); 606 bool was_empty = !(ready_queue != 0); 607 append( ready_queue, thrd ); 608 unlock( ready_queue_lock ); 609 610 __wake_one(thrd->curr_cluster, was_empty); 611 612 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 559 613 } 560 614 561 615 // KERNEL ONLY 562 thread_desc * nextThread(cluster * this) with( *this ) { 563 verify( ! kernelTLS.preemption_state.enabled ); 616 static $thread * __next_thread(cluster * this) with( *this ) { 617 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 618 564 619 lock( ready_queue_lock __cfaabi_dbg_ctx2 ); 565 thread_desc* head = pop_head( ready_queue );620 $thread * head = pop_head( ready_queue ); 566 621 unlock( ready_queue_lock ); 567 verify( ! kernelTLS.preemption_state.enabled ); 622 623 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 568 624 return head; 569 625 } 570 626 571 void BlockInternal() { 627 // KERNEL ONLY unpark with out disabling interrupts 628 void __unpark( $thread * thrd __cfaabi_dbg_ctx_param2 ) { 629 static_assert(sizeof(thrd->state) == sizeof(int)); 630 631 // record activity 632 __cfaabi_dbg_record_thrd( *thrd, false, caller ); 633 634 enum coroutine_state old_state = __atomic_exchange_n(&thrd->state, Rerun, __ATOMIC_SEQ_CST); 635 __cfaabi_dbg_debug_do( thrd->unpark_result = old_state; ) 636 switch(old_state) { 637 case Active: 638 // Wake won the race, the thread will reschedule/rerun itself 639 break; 640 case Blocked: 641 /* paranoid */ verify( ! thrd->preempted != __NO_PREEMPTION ); 642 643 // Wake lost the race, 644 thrd->state = Blocked; 645 __schedule_thread( thrd ); 646 break; 647 case Rerun: 648 abort("More than one thread attempted to schedule thread %p\n", thrd); 649 break; 650 case Halted: 651 case Start: 652 case Primed: 653 default: 654 // This makes no sense, something is wrong abort 655 abort(); 656 } 657 } 658 659 void unpark( $thread * thrd __cfaabi_dbg_ctx_param2 ) { 660 if( !thrd ) return; 661 572 662 disable_interrupts(); 573 verify( ! kernelTLS.preemption_state.enabled ); 663 __unpark( thrd __cfaabi_dbg_ctx_fwd2 ); 664 enable_interrupts( __cfaabi_dbg_ctx ); 665 } 666 667 void park( __cfaabi_dbg_ctx_param ) { 668 /* paranoid */ verify( kernelTLS.preemption_state.enabled ); 669 disable_interrupts(); 670 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 671 /* paranoid */ verify( kernelTLS.this_thread->preempted == __NO_PREEMPTION ); 672 673 // record activity 674 __cfaabi_dbg_record_thrd( *kernelTLS.this_thread, true, caller ); 675 574 676 returnToKernel(); 575 verify( ! kernelTLS.preemption_state.enabled ); 677 678 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 576 679 enable_interrupts( __cfaabi_dbg_ctx ); 577 } 578 579 void BlockInternal( __spinlock_t * lock ) { 680 /* paranoid */ verify( kernelTLS.preemption_state.enabled ); 681 682 } 683 684 // KERNEL ONLY 685 void __leave_thread() { 686 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 687 returnToKernel(); 688 abort(); 689 } 690 691 // KERNEL ONLY 692 bool force_yield( __Preemption_Reason reason ) { 693 /* paranoid */ verify( kernelTLS.preemption_state.enabled ); 580 694 disable_interrupts(); 581 with( *kernelTLS.this_processor ) { 582 finish.action_code = Release; 583 finish.lock = lock; 584 } 585 586 verify( ! kernelTLS.preemption_state.enabled ); 587 returnToKernel(); 588 verify( ! kernelTLS.preemption_state.enabled ); 589 590 enable_interrupts( __cfaabi_dbg_ctx ); 591 } 592 593 void BlockInternal( thread_desc * thrd ) { 594 disable_interrupts(); 595 with( * kernelTLS.this_processor ) { 596 finish.action_code = Schedule; 597 finish.thrd = thrd; 598 } 599 600 verify( ! kernelTLS.preemption_state.enabled ); 601 returnToKernel(); 602 verify( ! kernelTLS.preemption_state.enabled ); 603 604 enable_interrupts( __cfaabi_dbg_ctx ); 605 } 606 607 void BlockInternal( __spinlock_t * lock, thread_desc * thrd ) { 608 assert(thrd); 609 disable_interrupts(); 610 with( * kernelTLS.this_processor ) { 611 finish.action_code = Release_Schedule; 612 finish.lock = lock; 613 finish.thrd = thrd; 614 } 615 616 verify( ! kernelTLS.preemption_state.enabled ); 617 returnToKernel(); 618 verify( ! kernelTLS.preemption_state.enabled ); 619 620 enable_interrupts( __cfaabi_dbg_ctx ); 621 } 622 623 void BlockInternal(__spinlock_t * locks [], unsigned short count) { 624 disable_interrupts(); 625 with( * kernelTLS.this_processor ) { 626 finish.action_code = Release_Multi; 627 finish.locks = locks; 628 finish.lock_count = count; 629 } 630 631 verify( ! kernelTLS.preemption_state.enabled ); 632 returnToKernel(); 633 verify( ! kernelTLS.preemption_state.enabled ); 634 635 enable_interrupts( __cfaabi_dbg_ctx ); 636 } 637 638 void BlockInternal(__spinlock_t * locks [], unsigned short lock_count, thread_desc * thrds [], unsigned short thrd_count) { 639 disable_interrupts(); 640 with( *kernelTLS.this_processor ) { 641 finish.action_code = Release_Multi_Schedule; 642 finish.locks = locks; 643 finish.lock_count = lock_count; 644 finish.thrds = thrds; 645 finish.thrd_count = thrd_count; 646 } 647 648 verify( ! kernelTLS.preemption_state.enabled ); 649 returnToKernel(); 650 verify( ! kernelTLS.preemption_state.enabled ); 651 652 enable_interrupts( __cfaabi_dbg_ctx ); 653 } 654 655 void BlockInternal(__finish_callback_fptr_t callback) { 656 disable_interrupts(); 657 with( *kernelTLS.this_processor ) { 658 finish.action_code = Callback; 659 finish.callback = callback; 660 } 661 662 verify( ! kernelTLS.preemption_state.enabled ); 663 returnToKernel(); 664 verify( ! kernelTLS.preemption_state.enabled ); 665 666 enable_interrupts( __cfaabi_dbg_ctx ); 667 } 668 669 // KERNEL ONLY 670 void LeaveThread(__spinlock_t * lock, thread_desc * thrd) { 671 verify( ! kernelTLS.preemption_state.enabled ); 672 with( * kernelTLS.this_processor ) { 673 finish.action_code = thrd ? Release_Schedule : Release; 674 finish.lock = lock; 675 finish.thrd = thrd; 676 } 677 678 returnToKernel(); 695 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 696 697 $thread * thrd = kernelTLS.this_thread; 698 /* paranoid */ verify(thrd->state == Active || thrd->state == Rerun); 699 700 // SKULLDUGGERY: It is possible that we are preempting this thread just before 701 // it was going to park itself. If that is the case and it is already using the 702 // intrusive fields then we can't use them to preempt the thread 703 // If that is the case, abandon the preemption. 704 bool preempted = false; 705 if(thrd->next == 0p) { 706 preempted = true; 707 thrd->preempted = reason; 708 returnToKernel(); 709 } 710 711 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 712 enable_interrupts_noPoll(); 713 /* paranoid */ verify( kernelTLS.preemption_state.enabled ); 714 715 return preempted; 679 716 } 680 717 … … 684 721 //----------------------------------------------------------------------------- 685 722 // Kernel boot procedures 686 static void kernel_startup(void) {723 static void __kernel_startup(void) { 687 724 verify( ! kernelTLS.preemption_state.enabled ); 688 __cfa abi_dbg_print_safe("Kernel : Starting\n");725 __cfadbg_print_safe(runtime_core, "Kernel : Starting\n"); 689 726 690 727 __page_size = sysconf( _SC_PAGESIZE ); … … 697 734 (*mainCluster){"Main Cluster"}; 698 735 699 __cfa abi_dbg_print_safe("Kernel : Main cluster ready\n");736 __cfadbg_print_safe(runtime_core, "Kernel : Main cluster ready\n"); 700 737 701 738 // Start by initializing the main thread 702 739 // SKULLDUGGERY: the mainThread steals the process main thread 703 740 // which will then be scheduled by the mainProcessor normally 704 mainThread = ( thread_desc*)&storage_mainThread;741 mainThread = ($thread *)&storage_mainThread; 705 742 current_stack_info_t info; 706 743 info.storage = (__stack_t*)&storage_mainThreadCtx; 707 744 (*mainThread){ &info }; 708 745 709 __cfa abi_dbg_print_safe("Kernel : Main thread ready\n");746 __cfadbg_print_safe(runtime_core, "Kernel : Main thread ready\n"); 710 747 711 748 … … 728 765 729 766 runner{ &this }; 730 __cfa abi_dbg_print_safe("Kernel : constructed main processor context %p\n", &runner);767 __cfadbg_print_safe(runtime_core, "Kernel : constructed main processor context %p\n", &runner); 731 768 } 732 769 … … 745 782 // Add the main thread to the ready queue 746 783 // once resume is called on mainProcessor->runner the mainThread needs to be scheduled like any normal thread 747 ScheduleThread(mainThread);784 __schedule_thread(mainThread); 748 785 749 786 // SKULLDUGGERY: Force a context switch to the main processor to set the main thread's context to the current UNIX 750 // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that787 // context. Hence, the main thread does not begin through __cfactx_invoke_thread, like all other threads. The trick here is that 751 788 // mainThread is on the ready queue when this call is made. 752 kernel_first_resume( kernelTLS.this_processor ); 753 789 __kernel_first_resume( kernelTLS.this_processor ); 754 790 755 791 756 792 // THE SYSTEM IS NOW COMPLETELY RUNNING 757 __cfaabi_dbg_print_safe("Kernel : Started\n--------------------------------------------------\n\n"); 793 794 795 // Now that the system is up, finish creating systems that need threading 796 __kernel_io_finish_start( *mainCluster ); 797 798 799 __cfadbg_print_safe(runtime_core, "Kernel : Started\n--------------------------------------------------\n\n"); 758 800 759 801 verify( ! kernelTLS.preemption_state.enabled ); … … 762 804 } 763 805 764 static void kernel_shutdown(void) { 765 __cfaabi_dbg_print_safe("\n--------------------------------------------------\nKernel : Shutting down\n"); 766 767 verify( TL_GET( preemption_state.enabled ) ); 806 static void __kernel_shutdown(void) { 807 //Before we start shutting things down, wait for systems that need threading to shutdown 808 __kernel_io_prepare_stop( *mainCluster ); 809 810 /* paranoid */ verify( TL_GET( preemption_state.enabled ) ); 768 811 disable_interrupts(); 769 verify( ! kernelTLS.preemption_state.enabled ); 812 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 813 814 __cfadbg_print_safe(runtime_core, "\n--------------------------------------------------\nKernel : Shutting down\n"); 770 815 771 816 // SKULLDUGGERY: Notify the mainProcessor it needs to terminates. … … 773 818 // which is currently here 774 819 __atomic_store_n(&mainProcessor->do_terminate, true, __ATOMIC_RELEASE); 775 kernel_last_resume( kernelTLS.this_processor );820 __kernel_last_resume( kernelTLS.this_processor ); 776 821 mainThread->self_cor.state = Halted; 777 822 … … 783 828 // Destroy the main processor and its context in reverse order of construction 784 829 // These were manually constructed so we need manually destroy them 785 ^(mainProcessor->runner){}; 786 ^(mainProcessor){}; 830 void ^?{}(processor & this) with( this ){ 831 /* paranoid */ verify( this.do_terminate == true ); 832 } 833 834 ^(*mainProcessor){}; 787 835 788 836 // Final step, destroy the main thread since it is no longer needed 789 837 // Since we provided a stack to this taxk it will not destroy anything 790 ^(mainThread){}; 838 /* paranoid */ verify(mainThread->self_cor.stack.storage == (__stack_t*)(((uintptr_t)&storage_mainThreadCtx)| 0x1)); 839 ^(*mainThread){}; 840 841 ^(*mainCluster){}; 791 842 792 843 ^(__cfa_dbg_global_clusters.list){}; 793 844 ^(__cfa_dbg_global_clusters.lock){}; 794 845 795 __cfa abi_dbg_print_safe("Kernel : Shutdown complete\n");846 __cfadbg_print_safe(runtime_core, "Kernel : Shutdown complete\n"); 796 847 } 797 848 798 849 //============================================================================================= 799 // Kernel Quiescing850 // Kernel Idle Sleep 800 851 //============================================================================================= 801 static void halt(processor * this) with( *this ) { 802 // verify( ! __atomic_load_n(&do_terminate, __ATOMIC_SEQ_CST) ); 803 852 static $thread * __halt(processor * this) with( *this ) { 853 if( do_terminate ) return 0p; 854 855 // First, lock the cluster idle 856 lock( cltr->idle_lock __cfaabi_dbg_ctx2 ); 857 858 // Check if we can find a thread 859 if( $thread * found = __next_thread( cltr ) ) { 860 unlock( cltr->idle_lock ); 861 return found; 862 } 863 864 // Move this processor from the active list to the idle list 865 move_to_front(cltr->procs, cltr->idles, *this); 866 867 // Unlock the idle lock so we don't go to sleep with a lock 868 unlock (cltr->idle_lock); 869 870 // We are ready to sleep 871 __cfadbg_print_safe(runtime_core, "Kernel : Processor %p ready to sleep\n", this); 872 wait( idle ); 873 874 // We have woken up 875 __cfadbg_print_safe(runtime_core, "Kernel : Processor %p woke up and ready to run\n", this); 876 877 // Get ourself off the idle list 804 878 with( *cltr ) { 805 lock (proc_list_lock __cfaabi_dbg_ctx2); 806 remove (procs, *this); 807 push_front(idles, *this); 808 unlock (proc_list_lock); 809 } 810 811 __cfaabi_dbg_print_safe("Kernel : Processor %p ready to sleep\n", this); 812 813 wait( idleLock ); 814 815 __cfaabi_dbg_print_safe("Kernel : Processor %p woke up and ready to run\n", this); 816 817 with( *cltr ) { 818 lock (proc_list_lock __cfaabi_dbg_ctx2); 819 remove (idles, *this); 820 push_front(procs, *this); 821 unlock (proc_list_lock); 822 } 879 lock (idle_lock __cfaabi_dbg_ctx2); 880 move_to_front(idles, procs, *this); 881 unlock(idle_lock); 882 } 883 884 // Don't check the ready queue again, we may not be in a position to run a thread 885 return 0p; 886 } 887 888 // Wake a thread from the front if there are any 889 static bool __wake_one(cluster * this, __attribute__((unused)) bool force) { 890 // if we don't want to force check if we know it's false 891 // if( !this->idles.head && !force ) return false; 892 893 // First, lock the cluster idle 894 lock( this->idle_lock __cfaabi_dbg_ctx2 ); 895 896 // Check if there is someone to wake up 897 if( !this->idles.head ) { 898 // Nope unlock and return false 899 unlock( this->idle_lock ); 900 return false; 901 } 902 903 // Wake them up 904 __cfadbg_print_safe(runtime_core, "Kernel : waking Processor %p\n", this->idles.head); 905 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 906 post( this->idles.head->idle ); 907 908 // Unlock and return true 909 unlock( this->idle_lock ); 910 return true; 911 } 912 913 // Unconditionnaly wake a thread 914 static bool __wake_proc(processor * this) { 915 __cfadbg_print_safe(runtime_core, "Kernel : waking Processor %p\n", this); 916 917 disable_interrupts(); 918 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 919 bool ret = post( this->idle ); 920 enable_interrupts( __cfaabi_dbg_ctx ); 921 922 return ret; 823 923 } 824 924 … … 854 954 855 955 void kernel_abort_msg( void * kernel_data, char * abort_text, int abort_text_size ) { 856 thread_desc* thrd = kernel_data;956 $thread * thrd = kernel_data; 857 957 858 958 if(thrd) { … … 902 1002 void ^?{}(semaphore & this) {} 903 1003 904 voidP(semaphore & this) with( this ){1004 bool P(semaphore & this) with( this ){ 905 1005 lock( lock __cfaabi_dbg_ctx2 ); 906 1006 count -= 1; … … 910 1010 911 1011 // atomically release spin lock and block 912 BlockInternal( &lock ); 1012 unlock( lock ); 1013 park( __cfaabi_dbg_ctx ); 1014 return true; 913 1015 } 914 1016 else { 915 1017 unlock( lock ); 916 } 917 } 918 919 void V(semaphore & this) with( this ) { 920 thread_desc * thrd = 0p; 1018 return false; 1019 } 1020 } 1021 1022 bool V(semaphore & this) with( this ) { 1023 $thread * thrd = 0p; 921 1024 lock( lock __cfaabi_dbg_ctx2 ); 922 1025 count += 1; … … 929 1032 930 1033 // make new owner 931 WakeThread( thrd ); 1034 unpark( thrd __cfaabi_dbg_ctx2 ); 1035 1036 return thrd != 0p; 1037 } 1038 1039 bool V(semaphore & this, unsigned diff) with( this ) { 1040 $thread * thrd = 0p; 1041 lock( lock __cfaabi_dbg_ctx2 ); 1042 int release = max(-count, (int)diff); 1043 count += diff; 1044 for(release) { 1045 unpark( pop_head( waiting ) __cfaabi_dbg_ctx2 ); 1046 } 1047 1048 unlock( lock ); 1049 1050 return thrd != 0p; 932 1051 } 933 1052 … … 946 1065 } 947 1066 948 void doregister( cluster * cltr, thread_desc& thrd ) {1067 void doregister( cluster * cltr, $thread & thrd ) { 949 1068 lock (cltr->thread_list_lock __cfaabi_dbg_ctx2); 950 1069 cltr->nthreads += 1; … … 953 1072 } 954 1073 955 void unregister( cluster * cltr, thread_desc& thrd ) {1074 void unregister( cluster * cltr, $thread & thrd ) { 956 1075 lock (cltr->thread_list_lock __cfaabi_dbg_ctx2); 957 1076 remove(cltr->threads, thrd ); … … 961 1080 962 1081 void doregister( cluster * cltr, processor * proc ) { 963 lock (cltr-> proc_list_lock __cfaabi_dbg_ctx2);1082 lock (cltr->idle_lock __cfaabi_dbg_ctx2); 964 1083 cltr->nprocessors += 1; 965 1084 push_front(cltr->procs, *proc); 966 unlock (cltr-> proc_list_lock);1085 unlock (cltr->idle_lock); 967 1086 } 968 1087 969 1088 void unregister( cluster * cltr, processor * proc ) { 970 lock (cltr-> proc_list_lock __cfaabi_dbg_ctx2);1089 lock (cltr->idle_lock __cfaabi_dbg_ctx2); 971 1090 remove(cltr->procs, *proc ); 972 1091 cltr->nprocessors -= 1; 973 unlock(cltr-> proc_list_lock);1092 unlock(cltr->idle_lock); 974 1093 } 975 1094 … … 978 1097 __cfaabi_dbg_debug_do( 979 1098 extern "C" { 980 void __cfaabi_dbg_record (__spinlock_t & this, const char prev_name[]) {1099 void __cfaabi_dbg_record_lock(__spinlock_t & this, const char prev_name[]) { 981 1100 this.prev_name = prev_name; 982 1101 this.prev_thrd = kernelTLS.this_thread; 983 1102 } 1103 1104 void __cfaabi_dbg_record_thrd($thread & this, bool park, const char prev_name[]) { 1105 if(park) { 1106 this.park_caller = prev_name; 1107 this.park_stale = false; 1108 } 1109 else { 1110 this.unpark_caller = prev_name; 1111 this.unpark_stale = false; 1112 } 1113 } 984 1114 } 985 1115 ) … … 987 1117 //----------------------------------------------------------------------------- 988 1118 // Debug 989 bool threading_enabled(void) {1119 bool threading_enabled(void) __attribute__((const)) { 990 1120 return true; 991 1121 }
Note:
See TracChangeset
for help on using the changeset viewer.