Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/concurrency/kernel.cfa

    r92e7631 rf0ce5f4  
    114114
    115115//-----------------------------------------------------------------------------
    116 // Kernel Scheduling logic
    117 static $thread * __next_thread(cluster * this);
    118 static void __run_thread(processor * this, $thread * dst);
    119 static $thread * __halt(processor * this);
    120 static bool __wake_one(cluster * cltr, bool was_empty);
    121 static bool __wake_proc(processor *);
    122 
    123 //-----------------------------------------------------------------------------
    124116// Kernel storage
    125117KERNEL_STORAGE(cluster,         mainCluster);
     
    228220        runner.proc = &this;
    229221
    230         idle{};
     222        idleLock{};
    231223
    232224        __cfaabi_dbg_print_safe("Kernel : Starting core %p\n", &this);
     
    242234
    243235                __atomic_store_n(&do_terminate, true, __ATOMIC_RELAXED);
    244                 __wake_proc( &this );
     236                wake( &this );
    245237
    246238                P( terminated );
     
    272264// Kernel Scheduling logic
    273265//=============================================================================================
     266static $thread * __next_thread(cluster * this);
     267static void __run_thread(processor * this, $thread * dst);
     268static void __halt(processor * this);
     269
    274270//Main of the processor contexts
    275271void main(processorCtx_t & runner) {
     
    293289                $thread * readyThread = 0p;
    294290                for( unsigned int spin_count = 0; ! __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST); spin_count++ ) {
    295                         // Try to get the next thread
    296291                        readyThread = __next_thread( this->cltr );
    297292
    298                         // If no ready thread
    299                         if( readyThread == 0p ) {
    300                                 // Block until a thread is ready
    301                                 readyThread = __halt(this);
    302                         }
    303 
    304                         // Check if we actually found a thread
    305                         if( readyThread ) {
     293                        if(readyThread) {
    306294                                /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    307                                 /* paranoid */ verifyf( readyThread->state == Ready || readyThread->preempted != __NO_PREEMPTION, "state : %d, preempted %d\n", readyThread->state, readyThread->preempted);
     295                                /* paranoid */ verifyf( readyThread->state == Blocked || readyThread->state == Start || readyThread->preempted != __NO_PREEMPTION, "state : %d, preempted %d\n", readyThread->state, readyThread->preempted);
    308296                                /* paranoid */ verifyf( readyThread->next == 0p, "Expected null got %p", readyThread->next );
    309297
    310                                 // We found a thread run it
    311298                                __run_thread(this, readyThread);
    312299
    313300                                /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     301
     302                                spin_count = 0;
     303                        } else {
     304                                // spin(this, &spin_count);
     305                                __halt(this);
    314306                        }
    315307                }
     
    320312        unregister(this->cltr, this);
    321313
    322         V( this->terminated );
     314        bool signalled = V( this->terminated );
     315        if(signalled)
    323316
    324317        __cfaabi_dbg_print_safe("Kernel : core %p terminated\n", this);
    325 
    326         // HACK : the coroutine context switch expects this_thread to be set
    327         // and it make sense for it to be set in all other cases except here
    328         // fake it
    329         if( this == mainProcessor ) kernelTLS.this_thread = mainThread;
    330318}
    331319
     
    350338                if(unlikely(thrd_dst->preempted)) {
    351339                        thrd_dst->preempted = __NO_PREEMPTION;
    352                         verify(thrd_dst->state == Active  || thrd_dst->state == Rerun);
     340                        verify(thrd_dst->state == Active || thrd_dst->state == Rerun);
    353341                } else {
    354                         verify(thrd_dst->state == Blocked || thrd_dst->state == Ready); // Ready means scheduled normally, blocked means rerun
     342                        verify(thrd_dst->state == Start || thrd_dst->state == Primed || thrd_dst->state == Blocked);
    355343                        thrd_dst->state = Active;
    356344                }
     
    533521        dst->starter = dst->starter ? dst->starter : &src->self_cor;
    534522
    535         // make sure the current state is still correct
    536         /* paranoid */ verify(src->state == Ready);
     523        // set state of current coroutine to inactive
     524        src->state = src->state == Halted ? Halted : Blocked;
    537525
    538526        // context switch to specified coroutine
     
    543531        mainThread->curr_cor = &mainThread->self_cor;
    544532
    545         // make sure the current state has been update
    546         /* paranoid */ verify(src->state == Active);
     533        // set state of new coroutine to active
     534        src->state = Active;
    547535
    548536        verify( ! kernelTLS.preemption_state.enabled );
     
    582570        unlock( ready_queue_lock );
    583571
    584         __wake_one(thrd->curr_cluster, was_empty);
     572        if(was_empty) {
     573                lock      (proc_list_lock __cfaabi_dbg_ctx2);
     574                if(idles) {
     575                        wake_fast(idles.head);
     576                }
     577                unlock    (proc_list_lock);
     578        }
     579        else if( struct processor * idle = idles.head ) {
     580                wake_fast(idle);
     581        }
    585582
    586583        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     
    771768        __cfaabi_dbg_print_safe("\n--------------------------------------------------\nKernel : Shutting down\n");
    772769
    773         /* paranoid */ verify( TL_GET( preemption_state.enabled ) );
     770        verify( TL_GET( preemption_state.enabled ) );
    774771        disable_interrupts();
    775         /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     772        verify( ! kernelTLS.preemption_state.enabled );
    776773
    777774        // SKULLDUGGERY: Notify the mainProcessor it needs to terminates.
     
    803800
    804801//=============================================================================================
    805 // Kernel Idle Sleep
     802// Kernel Quiescing
    806803//=============================================================================================
    807 static $thread * __halt(processor * this) with( *this ) {
    808         if( do_terminate ) return 0p;
    809 
    810         // First, lock the cluster idle
    811         lock( cltr->idle_lock __cfaabi_dbg_ctx2 );
    812 
    813         // Check if we can find a thread
    814         if( $thread * found = __next_thread( cltr ) ) {
    815                 unlock( cltr->idle_lock );
    816                 return found;
    817         }
    818 
    819         // Move this processor from the active list to the idle list
    820         move_to_front(cltr->procs, cltr->idles, *this);
    821 
    822         // Unlock the idle lock so we don't go to sleep with a lock
    823         unlock    (cltr->idle_lock);
    824 
    825         // We are ready to sleep
     804static void __halt(processor * this) with( *this ) {
     805        // verify( ! __atomic_load_n(&do_terminate, __ATOMIC_SEQ_CST) );
     806
     807        with( *cltr ) {
     808                lock      (proc_list_lock __cfaabi_dbg_ctx2);
     809                remove    (procs, *this);
     810                push_front(idles, *this);
     811                unlock    (proc_list_lock);
     812        }
     813
    826814        __cfaabi_dbg_print_safe("Kernel : Processor %p ready to sleep\n", this);
    827         wait( idle );
    828 
    829         // We have woken up
     815
     816        wait( idleLock );
     817
    830818        __cfaabi_dbg_print_safe("Kernel : Processor %p woke up and ready to run\n", this);
    831819
    832         // Get ourself off the idle list
    833820        with( *cltr ) {
    834                 lock  (idle_lock __cfaabi_dbg_ctx2);
    835                 move_to_front(idles, procs, *this);
    836                 unlock(idle_lock);
    837         }
    838 
    839         // Don't check the ready queue again, we may not be in a position to run a thread
    840         return 0p;
    841 }
    842 
    843 // Wake a thread from the front if there are any
    844 static bool __wake_one(cluster * this, __attribute__((unused)) bool force) {
    845         // if we don't want to force check if we know it's false
    846         if( !this->idles.head && !force ) return false;
    847 
    848         // First, lock the cluster idle
    849         lock( this->idle_lock __cfaabi_dbg_ctx2 );
    850 
    851         // Check if there is someone to wake up
    852         if( !this->idles.head ) {
    853                 // Nope unlock and return false
    854                 unlock( this->idle_lock );
    855                 return false;
    856         }
    857 
    858         // Wake them up
    859         post( this->idles.head->idle );
    860 
    861         // Unlock and return true
    862         unlock( this->idle_lock );
    863         return true;
    864 }
    865 
    866 // Unconditionnaly wake a thread
    867 static bool __wake_proc(processor * this) {
    868         return post( this->idle );
     821                lock      (proc_list_lock __cfaabi_dbg_ctx2);
     822                remove    (idles, *this);
     823                push_front(procs, *this);
     824                unlock    (proc_list_lock);
     825        }
    869826}
    870827
     
    1010967
    1011968void doregister( cluster * cltr, processor * proc ) {
    1012         lock      (cltr->idle_lock __cfaabi_dbg_ctx2);
     969        lock      (cltr->proc_list_lock __cfaabi_dbg_ctx2);
    1013970        cltr->nprocessors += 1;
    1014971        push_front(cltr->procs, *proc);
    1015         unlock    (cltr->idle_lock);
     972        unlock    (cltr->proc_list_lock);
    1016973}
    1017974
    1018975void unregister( cluster * cltr, processor * proc ) {
    1019         lock  (cltr->idle_lock __cfaabi_dbg_ctx2);
     976        lock  (cltr->proc_list_lock __cfaabi_dbg_ctx2);
    1020977        remove(cltr->procs, *proc );
    1021978        cltr->nprocessors -= 1;
    1022         unlock(cltr->idle_lock);
     979        unlock(cltr->proc_list_lock);
    1023980}
    1024981
Note: See TracChangeset for help on using the changeset viewer.