- File:
-
- 1 edited
-
libcfa/src/concurrency/kernel.cfa (modified) (32 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/kernel.cfa
rc33c2af r1f45c7d 22 22 #include <errno.h> 23 23 #include <stdio.h> 24 #include <string.h>25 24 #include <signal.h> 26 25 #include <unistd.h> … … 32 31 #include "kernel_private.hfa" 33 32 #include "preemption.hfa" 34 #include "strstream.hfa"35 #include "device/cpu.hfa"36 33 37 34 //Private includes … … 113 110 #endif 114 111 115 extern thread$* mainThread;112 extern $thread * mainThread; 116 113 extern processor * mainProcessor; 117 114 118 115 //----------------------------------------------------------------------------- 119 116 // Kernel Scheduling logic 120 static thread$* __next_thread(cluster * this);121 static thread$* __next_thread_slow(cluster * this);122 static inline bool __must_unpark( thread$* thrd ) __attribute((nonnull(1)));123 static void __run_thread(processor * this, thread$* dst);117 static $thread * __next_thread(cluster * this); 118 static $thread * __next_thread_slow(cluster * this); 119 static inline bool __must_unpark( $thread * thrd ) __attribute((nonnull(1))); 120 static void __run_thread(processor * this, $thread * dst); 124 121 static void __wake_one(cluster * cltr); 125 122 … … 184 181 __cfadbg_print_safe(runtime_core, "Kernel : core %p started\n", this); 185 182 186 thread$* readyThread = 0p;183 $thread * readyThread = 0p; 187 184 MAIN_LOOP: 188 185 for() { … … 196 193 197 194 if( !readyThread ) { 198 ready_schedule_lock();199 195 __cfa_io_flush( this ); 200 ready_schedule_unlock();201 202 196 readyThread = __next_thread_slow( this->cltr ); 203 197 } … … 237 231 __cfadbg_print_safe(runtime_core, "Kernel : core %p waiting on eventfd %d\n", this, this->idle); 238 232 239 { 240 eventfd_t val; 241 ssize_t ret = read( this->idle, &val, sizeof(val) ); 242 if(ret < 0) { 243 switch((int)errno) { 244 case EAGAIN: 245 #if EAGAIN != EWOULDBLOCK 246 case EWOULDBLOCK: 247 #endif 248 case EINTR: 249 // No need to do anything special here, just assume it's a legitimate wake-up 250 break; 251 default: 252 abort( "KERNEL : internal error, read failure on idle eventfd, error(%d) %s.", (int)errno, strerror( (int)errno ) ); 253 } 254 } 255 } 233 __disable_interrupts_hard(); 234 eventfd_t val; 235 eventfd_read( this->idle, &val ); 236 __enable_interrupts_hard(); 256 237 257 238 #if !defined(__CFA_NO_STATISTICS__) … … 280 261 281 262 if(this->io.pending && !this->io.dirty) { 282 ready_schedule_lock();283 263 __cfa_io_flush( this ); 284 ready_schedule_unlock();285 264 } 286 265 … … 322 301 323 302 // Don't block if we are done 324 if( __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST) ) { 325 ready_schedule_unlock(); 326 break MAIN_LOOP; 327 } 303 if( __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST) ) break MAIN_LOOP; 328 304 329 305 __STATS( __tls_stats()->ready.sleep.halts++; ) … … 349 325 } 350 326 351 __STATS( if(this->print_halts) __cfaabi_bits_print_safe( STDOUT_FILENO, "PH:%d - %lld 0\n", this->unique_id, rdtscl()); )327 __STATS( if(this->print_halts) __cfaabi_bits_print_safe( STDOUT_FILENO, "PH:%d - %lld 0\n", this->unique_id, rdtscl()); ) 352 328 __cfadbg_print_safe(runtime_core, "Kernel : core %p waiting on eventfd %d\n", this, this->idle); 353 329 354 { 355 eventfd_t val; 356 ssize_t ret = read( this->idle, &val, sizeof(val) ); 357 if(ret < 0) { 358 switch((int)errno) { 359 case EAGAIN: 360 #if EAGAIN != EWOULDBLOCK 361 case EWOULDBLOCK: 362 #endif 363 case EINTR: 364 // No need to do anything special here, just assume it's a legitimate wake-up 365 break; 366 default: 367 abort( "KERNEL : internal error, read failure on idle eventfd, error(%d) %s.", (int)errno, strerror( (int)errno ) ); 368 } 369 } 370 } 330 // __disable_interrupts_hard(); 331 eventfd_t val; 332 eventfd_read( this->idle, &val ); 333 // __enable_interrupts_hard(); 371 334 372 335 __STATS( if(this->print_halts) __cfaabi_bits_print_safe( STDOUT_FILENO, "PH:%d - %lld 1\n", this->unique_id, rdtscl()); ) … … 425 388 // runThread runs a thread by context switching 426 389 // from the processor coroutine to the target thread 427 static void __run_thread(processor * this, thread$* thrd_dst) {390 static void __run_thread(processor * this, $thread * thrd_dst) { 428 391 /* paranoid */ verify( ! __preemption_enabled() ); 429 392 /* paranoid */ verifyf( thrd_dst->state == Ready || thrd_dst->preempted != __NO_PREEMPTION, "state : %d, preempted %d\n", thrd_dst->state, thrd_dst->preempted); … … 431 394 __builtin_prefetch( thrd_dst->context.SP ); 432 395 396 int curr = __kernel_getcpu(); 397 if(thrd_dst->last_cpu != curr) { 398 int64_t l = thrd_dst->last_cpu; 399 int64_t c = curr; 400 int64_t v = (l << 32) | c; 401 __push_stat( __tls_stats(), v, false, "Processor", this ); 402 } 403 404 thrd_dst->last_cpu = curr; 405 433 406 __cfadbg_print_safe(runtime_core, "Kernel : core %p running thread %p (%s)\n", this, thrd_dst, thrd_dst->self_cor.name); 434 407 435 coroutine$* proc_cor = get_coroutine(this->runner);408 $coroutine * proc_cor = get_coroutine(this->runner); 436 409 437 410 // set state of processor coroutine to inactive … … 452 425 /* paranoid */ verify( thrd_dst->context.SP ); 453 426 /* paranoid */ verify( thrd_dst->state != Halted ); 454 /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) < ((uintptr_t)__get_stack(thrd_dst->curr_cor)->base ) || thrd_dst->curr_cor == proc_cor || thrd_dst->corctx_flag, "ERROR : Destination thread$%p has been corrupted.\n StackPointer too small.\n", thrd_dst ); // add escape condition if we are setting up the processor455 /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) > ((uintptr_t)__get_stack(thrd_dst->curr_cor)->limit) || thrd_dst->curr_cor == proc_cor || thrd_dst->corctx_flag, "ERROR : Destination thread$%p has been corrupted.\n StackPointer too large.\n", thrd_dst ); // add escape condition if we are setting up the processor427 /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) < ((uintptr_t)__get_stack(thrd_dst->curr_cor)->base ) || thrd_dst->curr_cor == proc_cor || thrd_dst->corctx_flag, "ERROR : Destination $thread %p has been corrupted.\n StackPointer too small.\n", thrd_dst ); // add escape condition if we are setting up the processor 428 /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) > ((uintptr_t)__get_stack(thrd_dst->curr_cor)->limit) || thrd_dst->curr_cor == proc_cor || thrd_dst->corctx_flag, "ERROR : Destination $thread %p has been corrupted.\n StackPointer too large.\n", thrd_dst ); // add escape condition if we are setting up the processor 456 429 /* paranoid */ verify( 0x0D15EA5E0D15EA5Ep == thrd_dst->canary ); 457 430 … … 465 438 466 439 /* paranoid */ verify( 0x0D15EA5E0D15EA5Ep == thrd_dst->canary ); 467 /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) > ((uintptr_t)__get_stack(thrd_dst->curr_cor)->limit) || thrd_dst->corctx_flag, "ERROR : Destination thread$%p has been corrupted.\n StackPointer too large.\n", thrd_dst );468 /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) < ((uintptr_t)__get_stack(thrd_dst->curr_cor)->base ) || thrd_dst->corctx_flag, "ERROR : Destination thread$%p has been corrupted.\n StackPointer too small.\n", thrd_dst );440 /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) > ((uintptr_t)__get_stack(thrd_dst->curr_cor)->limit) || thrd_dst->corctx_flag, "ERROR : Destination $thread %p has been corrupted.\n StackPointer too large.\n", thrd_dst ); 441 /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) < ((uintptr_t)__get_stack(thrd_dst->curr_cor)->base ) || thrd_dst->corctx_flag, "ERROR : Destination $thread %p has been corrupted.\n StackPointer too small.\n", thrd_dst ); 469 442 /* paranoid */ verify( thrd_dst->context.SP ); 470 443 /* paranoid */ verify( thrd_dst->curr_cluster == this->cltr ); … … 484 457 if(unlikely(thrd_dst->preempted != __NO_PREEMPTION)) { 485 458 // The thread was preempted, reschedule it and reset the flag 486 schedule_thread$( thrd_dst , UNPARK_LOCAL);459 schedule_thread$( thrd_dst ); 487 460 break RUNNING; 488 461 } … … 532 505 void returnToKernel() { 533 506 /* paranoid */ verify( ! __preemption_enabled() ); 534 coroutine$* proc_cor = get_coroutine(kernelTLS().this_processor->runner);535 thread$* thrd_src = kernelTLS().this_thread;507 $coroutine * proc_cor = get_coroutine(kernelTLS().this_processor->runner); 508 $thread * thrd_src = kernelTLS().this_thread; 536 509 537 510 __STATS( thrd_src->last_proc = kernelTLS().this_processor; ) … … 561 534 562 535 /* paranoid */ verify( ! __preemption_enabled() ); 563 /* paranoid */ verifyf( ((uintptr_t)thrd_src->context.SP) < ((uintptr_t)__get_stack(thrd_src->curr_cor)->base ) || thrd_src->corctx_flag, "ERROR : Returning thread$%p has been corrupted.\n StackPointer too small.\n", thrd_src );564 /* paranoid */ verifyf( ((uintptr_t)thrd_src->context.SP) > ((uintptr_t)__get_stack(thrd_src->curr_cor)->limit) || thrd_src->corctx_flag, "ERROR : Returning thread$%p has been corrupted.\n StackPointer too large.\n", thrd_src );536 /* paranoid */ verifyf( ((uintptr_t)thrd_src->context.SP) < ((uintptr_t)__get_stack(thrd_src->curr_cor)->base ) || thrd_src->corctx_flag, "ERROR : Returning $thread %p has been corrupted.\n StackPointer too small.\n", thrd_src ); 537 /* paranoid */ verifyf( ((uintptr_t)thrd_src->context.SP) > ((uintptr_t)__get_stack(thrd_src->curr_cor)->limit) || thrd_src->corctx_flag, "ERROR : Returning $thread %p has been corrupted.\n StackPointer too large.\n", thrd_src ); 565 538 } 566 539 … … 568 541 // Scheduler routines 569 542 // KERNEL ONLY 570 static void __schedule_thread( thread$ * thrd, unpark_hint hint) {543 static void __schedule_thread( $thread * thrd ) { 571 544 /* paranoid */ verify( ! __preemption_enabled() ); 572 545 /* paranoid */ verify( ready_schedule_islocked()); … … 588 561 // Dereference the thread now because once we push it, there is not guaranteed it's still valid. 589 562 struct cluster * cl = thrd->curr_cluster; 590 __STATS(bool outside = hint == UNPARK_LOCAL &&thrd->last_proc && thrd->last_proc != kernelTLS().this_processor; )563 __STATS(bool outside = thrd->last_proc && thrd->last_proc != kernelTLS().this_processor; ) 591 564 592 565 // push the thread to the cluster ready-queue 593 push( cl, thrd, hint);566 push( cl, thrd, local ); 594 567 595 568 // variable thrd is no longer safe to use … … 616 589 } 617 590 618 void schedule_thread$( thread$ * thrd, unpark_hint hint) {591 void schedule_thread$( $thread * thrd ) { 619 592 ready_schedule_lock(); 620 __schedule_thread( thrd , hint);593 __schedule_thread( thrd ); 621 594 ready_schedule_unlock(); 622 595 } 623 596 624 597 // KERNEL ONLY 625 static inline thread$* __next_thread(cluster * this) with( *this ) {598 static inline $thread * __next_thread(cluster * this) with( *this ) { 626 599 /* paranoid */ verify( ! __preemption_enabled() ); 627 600 628 601 ready_schedule_lock(); 629 thread$* thrd = pop_fast( this );602 $thread * thrd = pop_fast( this ); 630 603 ready_schedule_unlock(); 631 604 … … 635 608 636 609 // KERNEL ONLY 637 static inline thread$* __next_thread_slow(cluster * this) with( *this ) {610 static inline $thread * __next_thread_slow(cluster * this) with( *this ) { 638 611 /* paranoid */ verify( ! __preemption_enabled() ); 639 612 640 613 ready_schedule_lock(); 641 thread$* thrd;614 $thread * thrd; 642 615 for(25) { 643 616 thrd = pop_slow( this ); … … 653 626 } 654 627 655 static inline bool __must_unpark( thread$* thrd ) {628 static inline bool __must_unpark( $thread * thrd ) { 656 629 int old_ticket = __atomic_fetch_add(&thrd->ticket, 1, __ATOMIC_SEQ_CST); 657 630 switch(old_ticket) { … … 669 642 } 670 643 671 void __kernel_unpark( thread$ * thrd, unpark_hint hint) {644 void __kernel_unpark( $thread * thrd ) { 672 645 /* paranoid */ verify( ! __preemption_enabled() ); 673 646 /* paranoid */ verify( ready_schedule_islocked()); … … 677 650 if(__must_unpark(thrd)) { 678 651 // Wake lost the race, 679 __schedule_thread( thrd , hint);652 __schedule_thread( thrd ); 680 653 } 681 654 … … 684 657 } 685 658 686 void unpark( thread$ * thrd, unpark_hint hint) {659 void unpark( $thread * thrd ) { 687 660 if( !thrd ) return; 688 661 … … 690 663 disable_interrupts(); 691 664 // Wake lost the race, 692 schedule_thread$( thrd , hint);665 schedule_thread$( thrd ); 693 666 enable_interrupts(false); 694 667 } … … 708 681 // Should never return 709 682 void __cfactx_thrd_leave() { 710 thread$* thrd = active_thread();711 monitor$* this = &thrd->self_mon;683 $thread * thrd = active_thread(); 684 $monitor * this = &thrd->self_mon; 712 685 713 686 // Lock the monitor now … … 721 694 /* paranoid */ verify( kernelTLS().this_thread == thrd ); 722 695 /* paranoid */ verify( thrd->context.SP ); 723 /* paranoid */ verifyf( ((uintptr_t)thrd->context.SP) > ((uintptr_t)__get_stack(thrd->curr_cor)->limit), "ERROR : thread$%p has been corrupted.\n StackPointer too large.\n", thrd );724 /* paranoid */ verifyf( ((uintptr_t)thrd->context.SP) < ((uintptr_t)__get_stack(thrd->curr_cor)->base ), "ERROR : thread$%p has been corrupted.\n StackPointer too small.\n", thrd );696 /* paranoid */ verifyf( ((uintptr_t)thrd->context.SP) > ((uintptr_t)__get_stack(thrd->curr_cor)->limit), "ERROR : $thread %p has been corrupted.\n StackPointer too large.\n", thrd ); 697 /* paranoid */ verifyf( ((uintptr_t)thrd->context.SP) < ((uintptr_t)__get_stack(thrd->curr_cor)->base ), "ERROR : $thread %p has been corrupted.\n StackPointer too small.\n", thrd ); 725 698 726 699 thrd->state = Halting; … … 740 713 bool force_yield( __Preemption_Reason reason ) { 741 714 __disable_interrupts_checked(); 742 thread$* thrd = kernelTLS().this_thread;715 $thread * thrd = kernelTLS().this_thread; 743 716 /* paranoid */ verify(thrd->state == Active); 744 717 … … 852 825 //============================================================================================= 853 826 void __kernel_abort_msg( char * abort_text, int abort_text_size ) { 854 thread$* thrd = __cfaabi_tls.this_thread;827 $thread * thrd = __cfaabi_tls.this_thread; 855 828 856 829 if(thrd) { … … 947 920 /* paranoid */ verifyf( it, "Unexpected null iterator, at index %u of %u\n", i, count); 948 921 /* paranoid */ verify( it->local_data->this_stats ); 949 // __print_stats( it->local_data->this_stats, cltr->print_stats, "Processor", it->name, (void*)it );950 922 __tally_stats( cltr->stats, it->local_data->this_stats ); 951 923 it = &(*it)`next; … … 957 929 // this doesn't solve all problems but does solve many 958 930 // so it's probably good enough 959 disable_interrupts();960 931 uint_fast32_t last_size = ready_mutate_lock(); 961 932 … … 965 936 // Unlock the RWlock 966 937 ready_mutate_unlock( last_size ); 967 enable_interrupts();968 938 } 969 939
Note:
See TracChangeset
for help on using the changeset viewer.