Changes in src/libcfa/concurrency/kernel.c [094476d:b10affd]
- File:
-
- 1 edited
-
src/libcfa/concurrency/kernel.c (modified) (32 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/libcfa/concurrency/kernel.c
r094476d rb10affd 10 10 // Created On : Tue Jan 17 12:27:26 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Feb 8 23:52:19201813 // Update Count : 512 // Last Modified On : Fri Mar 30 18:26:11 2018 13 // Update Count : 23 14 14 // 15 15 … … 52 52 // Global state 53 53 54 thread_local coroutine_desc * volatile this_coroutine;55 thread_local thread_desc * volatile this_thread;56 thread_local processor * volatile this_processor;57 58 54 // volatile thread_local bool preemption_in_progress = 0; 59 55 // volatile thread_local bool preemption_enabled = false; 60 56 // volatile thread_local unsigned short disable_preempt_count = 1; 61 57 62 volatile thread_local __cfa_kernel_preemption_state_t preemption_state = { false, false, 1 }; 58 thread_local struct KernelThreadData kernelThreadData = { 59 NULL, 60 NULL, 61 NULL, 62 { 1, false, false } 63 }; 63 64 64 65 //----------------------------------------------------------------------------- … … 172 173 terminate(&this); 173 174 verify(this.do_terminate); 174 verify( this_processor!= &this);175 verify(TL_GET( this_processor ) != &this); 175 176 P( terminated ); 176 verify( this_processor!= &this);177 verify(TL_GET( this_processor ) != &this); 177 178 pthread_join( kernel_thread, NULL ); 178 179 } … … 213 214 if(readyThread) 214 215 { 215 verify( ! preemption_state.enabled );216 verify( ! TL_GET( preemption_state ).enabled ); 216 217 217 218 runThread(this, readyThread); 218 219 219 verify( ! preemption_state.enabled );220 verify( ! TL_GET( preemption_state ).enabled ); 220 221 221 222 //Some actions need to be taken from the kernel … … 249 250 250 251 //Update global state 251 this_thread = dst;252 TL_SET( this_thread, dst ); 252 253 253 254 // Context Switch to the thread … … 257 258 258 259 void returnToKernel() { 259 coroutine_desc * proc_cor = get_coroutine( this_processor->runner);260 coroutine_desc * thrd_cor = this_thread->curr_cor = this_coroutine;260 coroutine_desc * proc_cor = get_coroutine(TL_GET( this_processor )->runner); 261 coroutine_desc * thrd_cor = TL_GET( this_thread )->curr_cor = TL_GET( this_coroutine ); 261 262 ThreadCtxSwitch(thrd_cor, proc_cor); 262 263 } … … 266 267 void finishRunning(processor * this) with( this->finish ) { 267 268 if( action_code == Release ) { 268 verify( ! preemption_state.enabled );269 verify( ! TL_GET( preemption_state ).enabled ); 269 270 unlock( *lock ); 270 271 } … … 273 274 } 274 275 else if( action_code == Release_Schedule ) { 275 verify( ! preemption_state.enabled );276 verify( ! TL_GET( preemption_state ).enabled ); 276 277 unlock( *lock ); 277 278 ScheduleThread( thrd ); 278 279 } 279 280 else if( action_code == Release_Multi ) { 280 verify( ! preemption_state.enabled );281 verify( ! TL_GET( preemption_state ).enabled ); 281 282 for(int i = 0; i < lock_count; i++) { 282 283 unlock( *locks[i] ); … … 307 308 void * CtxInvokeProcessor(void * arg) { 308 309 processor * proc = (processor *) arg; 309 this_processor = proc;310 this_coroutine = NULL;311 this_thread = NULL;312 preemption_state.enabled = false;313 preemption_state.disable_count = 1;310 TL_SET( this_processor, proc ); 311 TL_SET( this_coroutine, NULL ); 312 TL_SET( this_thread, NULL ); 313 TL_GET( preemption_state ).enabled = false; 314 TL_GET( preemption_state ).disable_count = 1; 314 315 // SKULLDUGGERY: We want to create a context for the processor coroutine 315 316 // which is needed for the 2-step context switch. However, there is no reason … … 323 324 324 325 //Set global state 325 this_coroutine = get_coroutine(proc->runner);326 this_thread = NULL;326 TL_SET( this_coroutine, get_coroutine(proc->runner) ); 327 TL_SET( this_thread, NULL ); 327 328 328 329 //We now have a proper context from which to schedule threads … … 352 353 353 354 void kernel_first_resume(processor * this) { 354 coroutine_desc * src = this_coroutine;355 coroutine_desc * src = TL_GET( this_coroutine ); 355 356 coroutine_desc * dst = get_coroutine(this->runner); 356 357 357 verify( ! preemption_state.enabled );358 verify( ! TL_GET( preemption_state ).enabled ); 358 359 359 360 create_stack(&dst->stack, dst->stack.size); 360 361 CtxStart(&this->runner, CtxInvokeCoroutine); 361 362 362 verify( ! preemption_state.enabled );363 verify( ! TL_GET( preemption_state ).enabled ); 363 364 364 365 dst->last = src; … … 369 370 370 371 // set new coroutine that task is executing 371 this_coroutine = dst;372 TL_SET( this_coroutine, dst ); 372 373 373 374 // SKULLDUGGERY normally interrupts are enable before leaving a coroutine ctxswitch. … … 386 387 src->state = Active; 387 388 388 verify( ! preemption_state.enabled );389 verify( ! TL_GET( preemption_state ).enabled ); 389 390 } 390 391 … … 392 393 // Scheduler routines 393 394 void ScheduleThread( thread_desc * thrd ) { 394 // if( ! thrd ) return;395 // if( ! thrd ) return; 395 396 verify( thrd ); 396 397 verify( thrd->self_cor.state != Halted ); 397 398 398 verify( ! preemption_state.enabled );399 verify( ! TL_GET( preemption_state ).enabled ); 399 400 400 401 verifyf( thrd->next == NULL, "Expected null got %p", thrd->next ); 401 402 402 with( * this_processor->cltr ) {403 with( *TL_GET( this_processor )->cltr ) { 403 404 lock ( ready_queue_lock __cfaabi_dbg_ctx2 ); 404 405 append( ready_queue, thrd ); … … 406 407 } 407 408 408 verify( ! preemption_state.enabled );409 verify( ! TL_GET( preemption_state ).enabled ); 409 410 } 410 411 411 412 thread_desc * nextThread(cluster * this) with( *this ) { 412 verify( ! preemption_state.enabled );413 verify( ! TL_GET( preemption_state ).enabled ); 413 414 lock( ready_queue_lock __cfaabi_dbg_ctx2 ); 414 415 thread_desc * head = pop_head( ready_queue ); 415 416 unlock( ready_queue_lock ); 416 verify( ! preemption_state.enabled );417 verify( ! TL_GET( preemption_state ).enabled ); 417 418 return head; 418 419 } … … 420 421 void BlockInternal() { 421 422 disable_interrupts(); 422 verify( ! preemption_state.enabled );423 verify( ! TL_GET( preemption_state ).enabled ); 423 424 returnToKernel(); 424 verify( ! preemption_state.enabled );425 verify( ! TL_GET( preemption_state ).enabled ); 425 426 enable_interrupts( __cfaabi_dbg_ctx ); 426 427 } … … 428 429 void BlockInternal( __spinlock_t * lock ) { 429 430 disable_interrupts(); 430 this_processor->finish.action_code = Release;431 this_processor->finish.lock = lock;432 433 verify( ! preemption_state.enabled );431 TL_GET( this_processor )->finish.action_code = Release; 432 TL_GET( this_processor )->finish.lock = lock; 433 434 verify( ! TL_GET( preemption_state ).enabled ); 434 435 returnToKernel(); 435 verify( ! preemption_state.enabled );436 verify( ! TL_GET( preemption_state ).enabled ); 436 437 437 438 enable_interrupts( __cfaabi_dbg_ctx ); … … 440 441 void BlockInternal( thread_desc * thrd ) { 441 442 disable_interrupts(); 442 this_processor->finish.action_code = Schedule;443 this_processor->finish.thrd = thrd;444 445 verify( ! preemption_state.enabled );443 TL_GET( this_processor )->finish.action_code = Schedule; 444 TL_GET( this_processor )->finish.thrd = thrd; 445 446 verify( ! TL_GET( preemption_state ).enabled ); 446 447 returnToKernel(); 447 verify( ! preemption_state.enabled );448 verify( ! TL_GET( preemption_state ).enabled ); 448 449 449 450 enable_interrupts( __cfaabi_dbg_ctx ); … … 453 454 assert(thrd); 454 455 disable_interrupts(); 455 this_processor->finish.action_code = Release_Schedule;456 this_processor->finish.lock = lock;457 this_processor->finish.thrd = thrd;458 459 verify( ! preemption_state.enabled );456 TL_GET( this_processor )->finish.action_code = Release_Schedule; 457 TL_GET( this_processor )->finish.lock = lock; 458 TL_GET( this_processor )->finish.thrd = thrd; 459 460 verify( ! TL_GET( preemption_state ).enabled ); 460 461 returnToKernel(); 461 verify( ! preemption_state.enabled );462 verify( ! TL_GET( preemption_state ).enabled ); 462 463 463 464 enable_interrupts( __cfaabi_dbg_ctx ); … … 466 467 void BlockInternal(__spinlock_t * locks [], unsigned short count) { 467 468 disable_interrupts(); 468 this_processor->finish.action_code = Release_Multi;469 this_processor->finish.locks = locks;470 this_processor->finish.lock_count = count;471 472 verify( ! preemption_state.enabled );469 TL_GET( this_processor )->finish.action_code = Release_Multi; 470 TL_GET( this_processor )->finish.locks = locks; 471 TL_GET( this_processor )->finish.lock_count = count; 472 473 verify( ! TL_GET( preemption_state ).enabled ); 473 474 returnToKernel(); 474 verify( ! preemption_state.enabled );475 verify( ! TL_GET( preemption_state ).enabled ); 475 476 476 477 enable_interrupts( __cfaabi_dbg_ctx ); … … 479 480 void BlockInternal(__spinlock_t * locks [], unsigned short lock_count, thread_desc * thrds [], unsigned short thrd_count) { 480 481 disable_interrupts(); 481 this_processor->finish.action_code = Release_Multi_Schedule;482 this_processor->finish.locks = locks;483 this_processor->finish.lock_count = lock_count;484 this_processor->finish.thrds = thrds;485 this_processor->finish.thrd_count = thrd_count;486 487 verify( ! preemption_state.enabled );482 TL_GET( this_processor )->finish.action_code = Release_Multi_Schedule; 483 TL_GET( this_processor )->finish.locks = locks; 484 TL_GET( this_processor )->finish.lock_count = lock_count; 485 TL_GET( this_processor )->finish.thrds = thrds; 486 TL_GET( this_processor )->finish.thrd_count = thrd_count; 487 488 verify( ! TL_GET( preemption_state ).enabled ); 488 489 returnToKernel(); 489 verify( ! preemption_state.enabled );490 verify( ! TL_GET( preemption_state ).enabled ); 490 491 491 492 enable_interrupts( __cfaabi_dbg_ctx ); … … 493 494 494 495 void LeaveThread(__spinlock_t * lock, thread_desc * thrd) { 495 verify( ! preemption_state.enabled );496 this_processor->finish.action_code = thrd ? Release_Schedule : Release;497 this_processor->finish.lock = lock;498 this_processor->finish.thrd = thrd;496 verify( ! TL_GET( preemption_state ).enabled ); 497 TL_GET( this_processor )->finish.action_code = thrd ? Release_Schedule : Release; 498 TL_GET( this_processor )->finish.lock = lock; 499 TL_GET( this_processor )->finish.thrd = thrd; 499 500 500 501 returnToKernel(); … … 507 508 // Kernel boot procedures 508 509 void kernel_startup(void) { 509 verify( ! preemption_state.enabled );510 verify( ! TL_GET( preemption_state ).enabled ); 510 511 __cfaabi_dbg_print_safe("Kernel : Starting\n"); 511 512 … … 531 532 532 533 //initialize the global state variables 533 this_processor = mainProcessor;534 this_thread = mainThread;535 this_coroutine = &mainThread->self_cor;534 TL_SET( this_processor, mainProcessor ); 535 TL_SET( this_thread, mainThread ); 536 TL_SET( this_coroutine, &mainThread->self_cor ); 536 537 537 538 // Enable preemption … … 545 546 // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that 546 547 // mainThread is on the ready queue when this call is made. 547 kernel_first_resume( this_processor);548 kernel_first_resume( TL_GET( this_processor ) ); 548 549 549 550 … … 552 553 __cfaabi_dbg_print_safe("Kernel : Started\n--------------------------------------------------\n\n"); 553 554 554 verify( ! preemption_state.enabled );555 verify( ! TL_GET( preemption_state ).enabled ); 555 556 enable_interrupts( __cfaabi_dbg_ctx ); 556 verify( preemption_state.enabled );557 verify( TL_GET( preemption_state ).enabled ); 557 558 } 558 559 … … 560 561 __cfaabi_dbg_print_safe("\n--------------------------------------------------\nKernel : Shutting down\n"); 561 562 562 verify( preemption_state.enabled );563 verify( TL_GET( preemption_state ).enabled ); 563 564 disable_interrupts(); 564 verify( ! preemption_state.enabled );565 verify( ! TL_GET( preemption_state ).enabled ); 565 566 566 567 // SKULLDUGGERY: Notify the mainProcessor it needs to terminates. … … 602 603 603 604 // first task to abort ? 604 if ( ! kernel_abort_called ) { // not first task to abort ?605 if ( ! kernel_abort_called ) { // not first task to abort ? 605 606 kernel_abort_called = true; 606 607 unlock( kernel_abort_lock ); … … 617 618 } 618 619 619 return this_thread;620 return TL_GET( this_thread ); 620 621 } 621 622 … … 626 627 __cfaabi_dbg_bits_write( abort_text, len ); 627 628 628 if ( thrd != this_coroutine) {629 len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", this_coroutine->name, this_coroutine);629 if ( thrd != TL_GET( this_coroutine ) ) { 630 len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", TL_GET( this_coroutine )->name, TL_GET( this_coroutine ) ); 630 631 __cfaabi_dbg_bits_write( abort_text, len ); 631 632 } … … 636 637 637 638 int kernel_abort_lastframe( void ) __attribute__ ((__nothrow__)) { 638 return get_coroutine( this_thread) == get_coroutine(mainThread) ? 4 : 2;639 return get_coroutine(TL_GET( this_thread )) == get_coroutine(mainThread) ? 4 : 2; 639 640 } 640 641 … … 666 667 if ( count < 0 ) { 667 668 // queue current task 668 append( waiting, (thread_desc *) this_thread);669 append( waiting, (thread_desc *)TL_GET( this_thread ) ); 669 670 670 671 // atomically release spin lock and block
Note:
See TracChangeset
for help on using the changeset viewer.