- File:
-
- 1 edited
-
libcfa/src/concurrency/kernel.cfa (modified) (40 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/kernel.cfa
ra7b486b re3fea42 15 15 16 16 #define __cforall_thread__ 17 // #define __CFA_DEBUG_PRINT_RUNTIME_CORE__18 17 19 18 //C Includes … … 41 40 #include "invoke.h" 42 41 43 44 42 //----------------------------------------------------------------------------- 45 43 // Some assembly required … … 112 110 //----------------------------------------------------------------------------- 113 111 //Start and stop routine for the kernel, declared first to make sure they run first 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 *); 112 static void kernel_startup(void) __attribute__(( constructor( STARTUP_PRIORITY_KERNEL ) )); 113 static void kernel_shutdown(void) __attribute__(( destructor ( STARTUP_PRIORITY_KERNEL ) )); 124 114 125 115 //----------------------------------------------------------------------------- … … 127 117 KERNEL_STORAGE(cluster, mainCluster); 128 118 KERNEL_STORAGE(processor, mainProcessor); 129 KERNEL_STORAGE( $thread, mainThread);119 KERNEL_STORAGE(thread_desc, mainThread); 130 120 KERNEL_STORAGE(__stack_t, mainThreadCtx); 131 121 132 122 cluster * mainCluster; 133 123 processor * mainProcessor; 134 $thread* mainThread;124 thread_desc * mainThread; 135 125 136 126 extern "C" { … … 174 164 // Main thread construction 175 165 176 void ?{}( $coroutine& this, current_stack_info_t * info) with( this ) {166 void ?{}( coroutine_desc & this, current_stack_info_t * info) with( this ) { 177 167 stack.storage = info->storage; 178 168 with(*stack.storage) { … … 189 179 } 190 180 191 void ?{}( $thread& this, current_stack_info_t * info) with( this ) {181 void ?{}( thread_desc & this, current_stack_info_t * info) with( this ) { 192 182 state = Start; 193 183 self_cor{ info }; … … 218 208 } 219 209 220 static void * __invoke_processor(void * arg); 221 210 static void start(processor * this); 222 211 void ?{}(processor & this, const char name[], cluster & cltr) with( this ) { 223 212 this.name = name; 224 213 this.cltr = &cltr; 225 214 terminated{ 0 }; 226 destroyer = 0p;227 215 do_terminate = false; 228 216 preemption_alarm = 0p; … … 230 218 runner.proc = &this; 231 219 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); 220 idleLock{}; 221 222 start( &this ); 239 223 } 240 224 241 225 void ^?{}(processor & this) with( this ){ 242 226 if( ! __atomic_load_n(&do_terminate, __ATOMIC_ACQUIRE) ) { 243 __cfa dbg_print_safe(runtime_core,"Kernel : core %p signaling termination\n", &this);227 __cfaabi_dbg_print_safe("Kernel : core %p signaling termination\n", &this); 244 228 245 229 __atomic_store_n(&do_terminate, true, __ATOMIC_RELAXED); 246 __wake_proc( &this );230 wake( &this ); 247 231 248 232 P( terminated ); … … 250 234 } 251 235 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 236 pthread_join( kernel_thread, 0p ); 255 237 free( this.stack ); 256 238 } 257 239 258 void ?{}(cluster & this, const char name[], Duration preemption_rate , int io_flags) with( this ) {240 void ?{}(cluster & this, const char name[], Duration preemption_rate) with( this ) { 259 241 this.name = name; 260 242 this.preemption_rate = preemption_rate; … … 262 244 ready_queue_lock{}; 263 245 264 #if !defined(__CFA_NO_STATISTICS__)265 print_stats = false;266 #endif267 268 246 procs{ __get }; 269 247 idles{ __get }; 270 248 threads{ __get }; 271 249 272 __kernel_io_startup( this, io_flags, &this == mainCluster );273 274 250 doregister(this); 275 251 } 276 252 277 253 void ^?{}(cluster & this) { 278 __kernel_io_shutdown( this, &this == mainCluster );279 280 254 unregister(this); 281 255 } … … 284 258 // Kernel Scheduling logic 285 259 //============================================================================================= 260 static void runThread(processor * this, thread_desc * dst); 261 static void finishRunning(processor * this); 262 static void halt(processor * this); 263 286 264 //Main of the processor contexts 287 265 void main(processorCtx_t & runner) { … … 293 271 verify(this); 294 272 295 __cfa dbg_print_safe(runtime_core,"Kernel : core %p starting\n", this);273 __cfaabi_dbg_print_safe("Kernel : core %p starting\n", this); 296 274 297 275 doregister(this->cltr, this); … … 301 279 preemption_scope scope = { this }; 302 280 303 __cfa dbg_print_safe(runtime_core,"Kernel : core %p started\n", this);304 305 $thread* readyThread = 0p;281 __cfaabi_dbg_print_safe("Kernel : core %p started\n", this); 282 283 thread_desc * readyThread = 0p; 306 284 for( unsigned int spin_count = 0; ! __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST); spin_count++ ) { 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 ); 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); 326 301 } 327 302 } 328 303 329 __cfa dbg_print_safe(runtime_core,"Kernel : core %p stopping\n", this);304 __cfaabi_dbg_print_safe("Kernel : core %p stopping\n", this); 330 305 } 331 306 … … 334 309 V( this->terminated ); 335 310 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; 311 __cfaabi_dbg_print_safe("Kernel : core %p terminated\n", this); 342 312 } 343 313 … … 348 318 // runThread runs a thread by context switching 349 319 // from the processor coroutine to the target thread 350 static void __run_thread(processor * this, $thread * thrd_dst) { 351 $coroutine * proc_cor = get_coroutine(this->runner); 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; 352 325 353 326 // Update global state 354 327 kernelTLS.this_thread = thrd_dst; 355 328 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; 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; 340 proc_cor->state = Active; 341 } 342 343 // 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] ); 368 389 } 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; 390 case Release_Multi_Schedule: 391 for(int i = 0; i < lock_count; i++) { 392 unlock( *locks[i] ); 402 393 } 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); 394 for(int i = 0; i < thrd_count; i++) { 395 ScheduleThread( thrds[i] ); 427 396 } 428 } 429 430 // Just before returning to the processor, set the processor coroutine to active 431 proc_cor->state = Active; 432 kernelTLS.this_thread = 0p; 433 } 434 435 // KERNEL_ONLY 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 ); 397 case Callback: 398 callback(); 399 default: 400 abort("KERNEL ERROR: Unexpected action to run after thread"); 401 } 458 402 } 459 403 … … 462 406 // This is the entry point for processors (kernel threads) 463 407 // It effectively constructs a coroutine by stealing the pthread stack 464 static void * __invoke_processor(void * arg) {408 static void * CtxInvokeProcessor(void * arg) { 465 409 processor * proc = (processor *) arg; 466 410 kernelTLS.this_processor = proc; … … 481 425 482 426 //We now have a proper context from which to schedule threads 483 __cfa dbg_print_safe(runtime_core,"Kernel : core %p created (%p, %p)\n", proc, &proc->runner, &ctx);427 __cfaabi_dbg_print_safe("Kernel : core %p created (%p, %p)\n", proc, &proc->runner, &ctx); 484 428 485 429 // SKULLDUGGERY: Since the coroutine doesn't have its own stack, we can't … … 492 436 493 437 // Main routine of the core returned, the core is now fully terminated 494 __cfa dbg_print_safe(runtime_core,"Kernel : core %p main ended (%p)\n", proc, &proc->runner);438 __cfaabi_dbg_print_safe("Kernel : core %p main ended (%p)\n", proc, &proc->runner); 495 439 496 440 return 0p; … … 503 447 } // Abort 504 448 505 void * __create_pthread( pthread_t * pthread, void * (*start)(void *), void * arg ) {449 void * create_pthread( pthread_t * pthread, void * (*start)(void *), void * arg ) { 506 450 pthread_attr_t attr; 507 451 … … 525 469 ); 526 470 527 Abort( pthread_attr_setstack( &attr, stack, stacksize ), "pthread_attr_setstack" ); 471 Abort( pthread_attr_setstack( &attr, stack, stacksize ), "pthread_attr_setstack" ); 528 472 529 473 Abort( pthread_create( pthread, &attr, start, arg ), "pthread_create" ); … … 531 475 } 532 476 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 533 485 // KERNEL_ONLY 534 static void __kernel_first_resume( processor * this ) { 535 $thread * src = mainThread; 536 $coroutine * dst = get_coroutine(this->runner); 537 538 verify( ! kernelTLS.preemption_state.enabled ); 539 540 kernelTLS.this_thread->curr_cor = dst; 486 void kernel_first_resume( processor * this ) { 487 thread_desc * src = mainThread; 488 coroutine_desc * dst = get_coroutine(this->runner); 489 490 verify( ! kernelTLS.preemption_state.enabled ); 491 541 492 __stack_prepare( &dst->stack, 65000 ); 542 __cfactx_start(main, dst, this->runner, __cfactx_invoke_coroutine);493 CtxStart(&this->runner, CtxInvokeCoroutine); 543 494 544 495 verify( ! kernelTLS.preemption_state.enabled ); … … 547 498 dst->starter = dst->starter ? dst->starter : &src->self_cor; 548 499 549 // make sure the current state is still correct550 /* paranoid */ verify(src->state == Ready);500 // set state of current coroutine to inactive 501 src->state = src->state == Halted ? Halted : Inactive; 551 502 552 503 // context switch to specified coroutine 553 504 verify( dst->context.SP ); 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); 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; 561 510 562 511 verify( ! kernelTLS.preemption_state.enabled ); … … 564 513 565 514 // KERNEL_ONLY 566 static void __kernel_last_resume( processor * this ) {567 $coroutine* src = &mainThread->self_cor;568 $coroutine* dst = get_coroutine(this->runner);515 void kernel_last_resume( processor * this ) { 516 coroutine_desc * src = &mainThread->self_cor; 517 coroutine_desc * dst = get_coroutine(this->runner); 569 518 570 519 verify( ! kernelTLS.preemption_state.enabled ); … … 572 521 verify( dst->context.SP ); 573 522 574 // SKULLDUGGERY in debug the processors check that the575 // 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 the577 // coroutine semantics. Since this is a special case, use the current context578 // 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 586 523 // context switch to the processor 587 __cfactx_switch( &src->context, &dst->context );524 CtxSwitch( &src->context, &dst->context ); 588 525 } 589 526 590 527 //----------------------------------------------------------------------------- 591 528 // Scheduler routines 529 592 530 // KERNEL ONLY 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 ); 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 ); 559 } 560 561 // KERNEL ONLY 562 thread_desc * nextThread(cluster * this) with( *this ) { 563 verify( ! kernelTLS.preemption_state.enabled ); 564 lock( ready_queue_lock __cfaabi_dbg_ctx2 ); 565 thread_desc * head = pop_head( ready_queue ); 608 566 unlock( ready_queue_lock ); 609 610 __wake_one(thrd->curr_cluster, was_empty); 611 612 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 567 verify( ! kernelTLS.preemption_state.enabled ); 568 return head; 569 } 570 571 void BlockInternal() { 572 disable_interrupts(); 573 verify( ! kernelTLS.preemption_state.enabled ); 574 returnToKernel(); 575 verify( ! kernelTLS.preemption_state.enabled ); 576 enable_interrupts( __cfaabi_dbg_ctx ); 577 } 578 579 void BlockInternal( __spinlock_t * lock ) { 580 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 ); 613 667 } 614 668 615 669 // KERNEL ONLY 616 static $thread * __next_thread(cluster * this) with( *this ) { 617 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 618 619 lock( ready_queue_lock __cfaabi_dbg_ctx2 ); 620 $thread * head = pop_head( ready_queue ); 621 unlock( ready_queue_lock ); 622 623 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 624 return head; 625 } 626 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 662 disable_interrupts(); 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 ); 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 } 675 677 676 678 returnToKernel(); 677 678 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );679 enable_interrupts( __cfaabi_dbg_ctx );680 /* paranoid */ verify( kernelTLS.preemption_state.enabled );681 682 }683 684 // KERNEL ONLY685 void __leave_thread() {686 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );687 returnToKernel();688 abort();689 }690 691 // KERNEL ONLY692 bool force_yield( __Preemption_Reason reason ) {693 /* paranoid */ verify( kernelTLS.preemption_state.enabled );694 disable_interrupts();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 before701 // it was going to park itself. If that is the case and it is already using the702 // intrusive fields then we can't use them to preempt the thread703 // 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;716 679 } 717 680 … … 721 684 //----------------------------------------------------------------------------- 722 685 // Kernel boot procedures 723 static void __kernel_startup(void) {724 verify( ! kernelTLS.preemption_state.enabled ); 725 __cfa dbg_print_safe(runtime_core,"Kernel : Starting\n");686 static void kernel_startup(void) { 687 verify( ! kernelTLS.preemption_state.enabled ); 688 __cfaabi_dbg_print_safe("Kernel : Starting\n"); 726 689 727 690 __page_size = sysconf( _SC_PAGESIZE ); … … 734 697 (*mainCluster){"Main Cluster"}; 735 698 736 __cfa dbg_print_safe(runtime_core,"Kernel : Main cluster ready\n");699 __cfaabi_dbg_print_safe("Kernel : Main cluster ready\n"); 737 700 738 701 // Start by initializing the main thread 739 702 // SKULLDUGGERY: the mainThread steals the process main thread 740 703 // which will then be scheduled by the mainProcessor normally 741 mainThread = ( $thread*)&storage_mainThread;704 mainThread = (thread_desc *)&storage_mainThread; 742 705 current_stack_info_t info; 743 706 info.storage = (__stack_t*)&storage_mainThreadCtx; 744 707 (*mainThread){ &info }; 745 708 746 __cfa dbg_print_safe(runtime_core,"Kernel : Main thread ready\n");709 __cfaabi_dbg_print_safe("Kernel : Main thread ready\n"); 747 710 748 711 … … 765 728 766 729 runner{ &this }; 767 __cfa dbg_print_safe(runtime_core,"Kernel : constructed main processor context %p\n", &runner);730 __cfaabi_dbg_print_safe("Kernel : constructed main processor context %p\n", &runner); 768 731 } 769 732 … … 782 745 // Add the main thread to the ready queue 783 746 // once resume is called on mainProcessor->runner the mainThread needs to be scheduled like any normal thread 784 __schedule_thread(mainThread);747 ScheduleThread(mainThread); 785 748 786 749 // SKULLDUGGERY: Force a context switch to the main processor to set the main thread's context to the current UNIX 787 // context. Hence, the main thread does not begin through __cfactx_invoke_thread, like all other threads. The trick here is that750 // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that 788 751 // mainThread is on the ready queue when this call is made. 789 __kernel_first_resume( kernelTLS.this_processor ); 752 kernel_first_resume( kernelTLS.this_processor ); 753 790 754 791 755 792 756 // THE SYSTEM IS NOW COMPLETELY RUNNING 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"); 757 __cfaabi_dbg_print_safe("Kernel : Started\n--------------------------------------------------\n\n"); 800 758 801 759 verify( ! kernelTLS.preemption_state.enabled ); … … 804 762 } 805 763 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 ) ); 764 static void kernel_shutdown(void) { 765 __cfaabi_dbg_print_safe("\n--------------------------------------------------\nKernel : Shutting down\n"); 766 767 verify( TL_GET( preemption_state.enabled ) ); 811 768 disable_interrupts(); 812 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 813 814 __cfadbg_print_safe(runtime_core, "\n--------------------------------------------------\nKernel : Shutting down\n"); 769 verify( ! kernelTLS.preemption_state.enabled ); 815 770 816 771 // SKULLDUGGERY: Notify the mainProcessor it needs to terminates. … … 818 773 // which is currently here 819 774 __atomic_store_n(&mainProcessor->do_terminate, true, __ATOMIC_RELEASE); 820 __kernel_last_resume( kernelTLS.this_processor );775 kernel_last_resume( kernelTLS.this_processor ); 821 776 mainThread->self_cor.state = Halted; 822 777 … … 828 783 // Destroy the main processor and its context in reverse order of construction 829 784 // These were manually constructed so we need manually destroy them 830 void ^?{}(processor & this) with( this ){ 831 /* paranoid */ verify( this.do_terminate == true ); 832 } 833 834 ^(*mainProcessor){}; 785 ^(mainProcessor->runner){}; 786 ^(mainProcessor){}; 835 787 836 788 // Final step, destroy the main thread since it is no longer needed 837 789 // Since we provided a stack to this taxk it will not destroy anything 838 /* paranoid */ verify(mainThread->self_cor.stack.storage == (__stack_t*)(((uintptr_t)&storage_mainThreadCtx)| 0x1)); 839 ^(*mainThread){}; 840 841 ^(*mainCluster){}; 790 ^(mainThread){}; 842 791 843 792 ^(__cfa_dbg_global_clusters.list){}; 844 793 ^(__cfa_dbg_global_clusters.lock){}; 845 794 846 __cfa dbg_print_safe(runtime_core,"Kernel : Shutdown complete\n");795 __cfaabi_dbg_print_safe("Kernel : Shutdown complete\n"); 847 796 } 848 797 849 798 //============================================================================================= 850 // Kernel Idle Sleep799 // Kernel Quiescing 851 800 //============================================================================================= 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 801 static void halt(processor * this) with( *this ) { 802 // verify( ! __atomic_load_n(&do_terminate, __ATOMIC_SEQ_CST) ); 803 878 804 with( *cltr ) { 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; 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 } 923 823 } 924 824 … … 954 854 955 855 void kernel_abort_msg( void * kernel_data, char * abort_text, int abort_text_size ) { 956 $thread* thrd = kernel_data;856 thread_desc * thrd = kernel_data; 957 857 958 858 if(thrd) { … … 1002 902 void ^?{}(semaphore & this) {} 1003 903 1004 boolP(semaphore & this) with( this ){904 void P(semaphore & this) with( this ){ 1005 905 lock( lock __cfaabi_dbg_ctx2 ); 1006 906 count -= 1; … … 1010 910 1011 911 // atomically release spin lock and block 1012 unlock( lock ); 1013 park( __cfaabi_dbg_ctx ); 1014 return true; 912 BlockInternal( &lock ); 1015 913 } 1016 914 else { 1017 915 unlock( lock ); 1018 return false; 1019 } 1020 } 1021 1022 bool V(semaphore & this) with( this ) { 1023 $thread * thrd = 0p; 916 } 917 } 918 919 void V(semaphore & this) with( this ) { 920 thread_desc * thrd = 0p; 1024 921 lock( lock __cfaabi_dbg_ctx2 ); 1025 922 count += 1; … … 1032 929 1033 930 // make new owner 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; 931 WakeThread( thrd ); 1051 932 } 1052 933 … … 1065 946 } 1066 947 1067 void doregister( cluster * cltr, $thread& thrd ) {948 void doregister( cluster * cltr, thread_desc & thrd ) { 1068 949 lock (cltr->thread_list_lock __cfaabi_dbg_ctx2); 1069 950 cltr->nthreads += 1; … … 1072 953 } 1073 954 1074 void unregister( cluster * cltr, $thread& thrd ) {955 void unregister( cluster * cltr, thread_desc & thrd ) { 1075 956 lock (cltr->thread_list_lock __cfaabi_dbg_ctx2); 1076 957 remove(cltr->threads, thrd ); … … 1080 961 1081 962 void doregister( cluster * cltr, processor * proc ) { 1082 lock (cltr-> idle_lock __cfaabi_dbg_ctx2);963 lock (cltr->proc_list_lock __cfaabi_dbg_ctx2); 1083 964 cltr->nprocessors += 1; 1084 965 push_front(cltr->procs, *proc); 1085 unlock (cltr-> idle_lock);966 unlock (cltr->proc_list_lock); 1086 967 } 1087 968 1088 969 void unregister( cluster * cltr, processor * proc ) { 1089 lock (cltr-> idle_lock __cfaabi_dbg_ctx2);970 lock (cltr->proc_list_lock __cfaabi_dbg_ctx2); 1090 971 remove(cltr->procs, *proc ); 1091 972 cltr->nprocessors -= 1; 1092 unlock(cltr-> idle_lock);973 unlock(cltr->proc_list_lock); 1093 974 } 1094 975 … … 1097 978 __cfaabi_dbg_debug_do( 1098 979 extern "C" { 1099 void __cfaabi_dbg_record _lock(__spinlock_t & this, const char prev_name[]) {980 void __cfaabi_dbg_record(__spinlock_t & this, const char prev_name[]) { 1100 981 this.prev_name = prev_name; 1101 982 this.prev_thrd = kernelTLS.this_thread; 1102 983 } 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 }1114 984 } 1115 985 ) … … 1117 987 //----------------------------------------------------------------------------- 1118 988 // Debug 1119 bool threading_enabled(void) __attribute__((const)){989 bool threading_enabled(void) { 1120 990 return true; 1121 991 }
Note:
See TracChangeset
for help on using the changeset viewer.