Ignore:
File:
1 edited

Legend:

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

    re3fea42 ra7b486b  
    1515
    1616#define __cforall_thread__
     17// #define __CFA_DEBUG_PRINT_RUNTIME_CORE__
    1718
    1819//C Includes
     
    4041#include "invoke.h"
    4142
     43
    4244//-----------------------------------------------------------------------------
    4345// Some assembly required
     
    110112//-----------------------------------------------------------------------------
    111113//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 ) ));
     114static void __kernel_startup (void) __attribute__(( constructor( STARTUP_PRIORITY_KERNEL ) ));
     115static void __kernel_shutdown(void) __attribute__(( destructor ( STARTUP_PRIORITY_KERNEL ) ));
     116
     117//-----------------------------------------------------------------------------
     118// Kernel Scheduling logic
     119static $thread * __next_thread(cluster * this);
     120static void __run_thread(processor * this, $thread * dst);
     121static $thread * __halt(processor * this);
     122static bool __wake_one(cluster * cltr, bool was_empty);
     123static bool __wake_proc(processor *);
    114124
    115125//-----------------------------------------------------------------------------
     
    117127KERNEL_STORAGE(cluster,         mainCluster);
    118128KERNEL_STORAGE(processor,       mainProcessor);
    119 KERNEL_STORAGE(thread_desc,     mainThread);
     129KERNEL_STORAGE($thread, mainThread);
    120130KERNEL_STORAGE(__stack_t,       mainThreadCtx);
    121131
    122132cluster     * mainCluster;
    123133processor   * mainProcessor;
    124 thread_desc * mainThread;
     134$thread * mainThread;
    125135
    126136extern "C" {
     
    164174// Main thread construction
    165175
    166 void ?{}( coroutine_desc & this, current_stack_info_t * info) with( this ) {
     176void ?{}( $coroutine & this, current_stack_info_t * info) with( this ) {
    167177        stack.storage = info->storage;
    168178        with(*stack.storage) {
     
    179189}
    180190
    181 void ?{}( thread_desc & this, current_stack_info_t * info) with( this ) {
     191void ?{}( $thread & this, current_stack_info_t * info) with( this ) {
    182192        state = Start;
    183193        self_cor{ info };
     
    208218}
    209219
    210 static void start(processor * this);
     220static void * __invoke_processor(void * arg);
     221
    211222void ?{}(processor & this, const char name[], cluster & cltr) with( this ) {
    212223        this.name = name;
    213224        this.cltr = &cltr;
    214225        terminated{ 0 };
     226        destroyer = 0p;
    215227        do_terminate = false;
    216228        preemption_alarm = 0p;
     
    218230        runner.proc = &this;
    219231
    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);
    223239}
    224240
    225241void ^?{}(processor & this) with( this ){
    226242        if( ! __atomic_load_n(&do_terminate, __ATOMIC_ACQUIRE) ) {
    227                 __cfaabi_dbg_print_safe("Kernel : core %p signaling termination\n", &this);
     243                __cfadbg_print_safe(runtime_core, "Kernel : core %p signaling termination\n", &this);
    228244
    229245                __atomic_store_n(&do_terminate, true, __ATOMIC_RELAXED);
    230                 wake( &this );
     246                __wake_proc( &this );
    231247
    232248                P( terminated );
     
    234250        }
    235251
    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
    237255        free( this.stack );
    238256}
    239257
    240 void ?{}(cluster & this, const char name[], Duration preemption_rate) with( this ) {
     258void ?{}(cluster & this, const char name[], Duration preemption_rate, int io_flags) with( this ) {
    241259        this.name = name;
    242260        this.preemption_rate = preemption_rate;
     
    244262        ready_queue_lock{};
    245263
     264        #if !defined(__CFA_NO_STATISTICS__)
     265                print_stats = false;
     266        #endif
     267
    246268        procs{ __get };
    247269        idles{ __get };
    248270        threads{ __get };
    249271
     272        __kernel_io_startup( this, io_flags, &this == mainCluster );
     273
    250274        doregister(this);
    251275}
    252276
    253277void ^?{}(cluster & this) {
     278        __kernel_io_shutdown( this, &this == mainCluster );
     279
    254280        unregister(this);
    255281}
     
    258284// Kernel Scheduling logic
    259285//=============================================================================================
    260 static void runThread(processor * this, thread_desc * dst);
    261 static void finishRunning(processor * this);
    262 static void halt(processor * this);
    263 
    264286//Main of the processor contexts
    265287void main(processorCtx_t & runner) {
     
    271293        verify(this);
    272294
    273         __cfaabi_dbg_print_safe("Kernel : core %p starting\n", this);
     295        __cfadbg_print_safe(runtime_core, "Kernel : core %p starting\n", this);
    274296
    275297        doregister(this->cltr, this);
     
    279301                preemption_scope scope = { this };
    280302
    281                 __cfaabi_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;
    284306                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 );
    301326                        }
    302327                }
    303328
    304                 __cfaabi_dbg_print_safe("Kernel : core %p stopping\n", this);
     329                __cfadbg_print_safe(runtime_core, "Kernel : core %p stopping\n", this);
    305330        }
    306331
     
    309334        V( this->terminated );
    310335
    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;
    312342}
    313343
     
    318348// runThread runs a thread by context switching
    319349// 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;
     350static void __run_thread(processor * this, $thread * thrd_dst) {
     351        $coroutine * proc_cor = get_coroutine(this->runner);
    325352
    326353        // Update global state
    327354        kernelTLS.this_thread = thrd_dst;
    328355
    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
    340431        proc_cor->state = Active;
     432        kernelTLS.this_thread = 0p;
    341433}
    342434
    343435// 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         }
     436void 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 );
    402458}
    403459
     
    406462// This is the entry point for processors (kernel threads)
    407463// It effectively constructs a coroutine by stealing the pthread stack
    408 static void * CtxInvokeProcessor(void * arg) {
     464static void * __invoke_processor(void * arg) {
    409465        processor * proc = (processor *) arg;
    410466        kernelTLS.this_processor = proc;
     
    425481
    426482        //We now have a proper context from which to schedule threads
    427         __cfaabi_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);
    428484
    429485        // SKULLDUGGERY: Since the coroutine doesn't have its own stack, we can't
     
    436492
    437493        // Main routine of the core returned, the core is now fully terminated
    438         __cfaabi_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);
    439495
    440496        return 0p;
     
    447503} // Abort
    448504
    449 void * create_pthread( pthread_t * pthread, void * (*start)(void *), void * arg ) {
     505void * __create_pthread( pthread_t * pthread, void * (*start)(void *), void * arg ) {
    450506        pthread_attr_t attr;
    451507
     
    469525        );
    470526
    471         Abort( pthread_attr_setstack( &attr, stack, stacksize ), "pthread_attr_setstack" ); 
     527        Abort( pthread_attr_setstack( &attr, stack, stacksize ), "pthread_attr_setstack" );
    472528
    473529        Abort( pthread_create( pthread, &attr, start, arg ), "pthread_create" );
     
    475531}
    476532
    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 
    485533// KERNEL_ONLY
    486 void kernel_first_resume( processor * this ) {
    487         thread_desc * src = mainThread;
    488         coroutine_desc * dst = get_coroutine(this->runner);
     534static void __kernel_first_resume( processor * this ) {
     535        $thread * src = mainThread;
     536        $coroutine * dst = get_coroutine(this->runner);
    489537
    490538        verify( ! kernelTLS.preemption_state.enabled );
    491539
     540        kernelTLS.this_thread->curr_cor = dst;
    492541        __stack_prepare( &dst->stack, 65000 );
    493         CtxStart(&this->runner, CtxInvokeCoroutine);
     542        __cfactx_start(main, dst, this->runner, __cfactx_invoke_coroutine);
    494543
    495544        verify( ! kernelTLS.preemption_state.enabled );
     
    498547        dst->starter = dst->starter ? dst->starter : &src->self_cor;
    499548
    500         // set state of current coroutine to inactive
    501         src->state = src->state == Halted ? Halted : Inactive;
     549        // make sure the current state is still correct
     550        /* paranoid */ verify(src->state == Ready);
    502551
    503552        // context switch to specified coroutine
    504553        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);
    510561
    511562        verify( ! kernelTLS.preemption_state.enabled );
     
    513564
    514565// KERNEL_ONLY
    515 void kernel_last_resume( processor * this ) {
    516         coroutine_desc * src = &mainThread->self_cor;
    517         coroutine_desc * dst = get_coroutine(this->runner);
     566static void __kernel_last_resume( processor * this ) {
     567        $coroutine * src = &mainThread->self_cor;
     568        $coroutine * dst = get_coroutine(this->runner);
    518569
    519570        verify( ! kernelTLS.preemption_state.enabled );
     
    521572        verify( dst->context.SP );
    522573
     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
    523586        // context switch to the processor
    524         CtxSwitch( &src->context, &dst->context );
     587        __cfactx_switch( &src->context, &dst->context );
    525588}
    526589
    527590//-----------------------------------------------------------------------------
    528591// Scheduler routines
    529 
    530592// 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 );
     593void __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 );
    559613}
    560614
    561615// KERNEL ONLY
    562 thread_desc * nextThread(cluster * this) with( *this ) {
    563         verify( ! kernelTLS.preemption_state.enabled );
     616static $thread * __next_thread(cluster * this) with( *this ) {
     617        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     618
    564619        lock( ready_queue_lock __cfaabi_dbg_ctx2 );
    565         thread_desc * head = pop_head( ready_queue );
     620        $thread * head = pop_head( ready_queue );
    566621        unlock( ready_queue_lock );
    567         verify( ! kernelTLS.preemption_state.enabled );
     622
     623        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    568624        return head;
    569625}
    570626
    571 void BlockInternal() {
     627// KERNEL ONLY unpark with out disabling interrupts
     628void __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
     659void unpark( $thread * thrd __cfaabi_dbg_ctx_param2 ) {
     660        if( !thrd ) return;
     661
    572662        disable_interrupts();
    573         verify( ! kernelTLS.preemption_state.enabled );
     663        __unpark( thrd __cfaabi_dbg_ctx_fwd2 );
     664        enable_interrupts( __cfaabi_dbg_ctx );
     665}
     666
     667void 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
    574676        returnToKernel();
    575         verify( ! kernelTLS.preemption_state.enabled );
     677
     678        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    576679        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
     685void __leave_thread() {
     686        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     687        returnToKernel();
     688        abort();
     689}
     690
     691// KERNEL ONLY
     692bool force_yield( __Preemption_Reason reason ) {
     693        /* paranoid */ verify( kernelTLS.preemption_state.enabled );
    580694        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;
    679716}
    680717
     
    684721//-----------------------------------------------------------------------------
    685722// Kernel boot procedures
    686 static void kernel_startup(void) {
     723static void __kernel_startup(void) {
    687724        verify( ! kernelTLS.preemption_state.enabled );
    688         __cfaabi_dbg_print_safe("Kernel : Starting\n");
     725        __cfadbg_print_safe(runtime_core, "Kernel : Starting\n");
    689726
    690727        __page_size = sysconf( _SC_PAGESIZE );
     
    697734        (*mainCluster){"Main Cluster"};
    698735
    699         __cfaabi_dbg_print_safe("Kernel : Main cluster ready\n");
     736        __cfadbg_print_safe(runtime_core, "Kernel : Main cluster ready\n");
    700737
    701738        // Start by initializing the main thread
    702739        // SKULLDUGGERY: the mainThread steals the process main thread
    703740        // which will then be scheduled by the mainProcessor normally
    704         mainThread = (thread_desc *)&storage_mainThread;
     741        mainThread = ($thread *)&storage_mainThread;
    705742        current_stack_info_t info;
    706743        info.storage = (__stack_t*)&storage_mainThreadCtx;
    707744        (*mainThread){ &info };
    708745
    709         __cfaabi_dbg_print_safe("Kernel : Main thread ready\n");
     746        __cfadbg_print_safe(runtime_core, "Kernel : Main thread ready\n");
    710747
    711748
     
    728765
    729766                runner{ &this };
    730                 __cfaabi_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);
    731768        }
    732769
     
    745782        // Add the main thread to the ready queue
    746783        // once resume is called on mainProcessor->runner the mainThread needs to be scheduled like any normal thread
    747         ScheduleThread(mainThread);
     784        __schedule_thread(mainThread);
    748785
    749786        // 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 that
     787        // context. Hence, the main thread does not begin through __cfactx_invoke_thread, like all other threads. The trick here is that
    751788        // 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 );
    754790
    755791
    756792        // 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");
    758800
    759801        verify( ! kernelTLS.preemption_state.enabled );
     
    762804}
    763805
    764 static void kernel_shutdown(void) {
    765         __cfaabi_dbg_print_safe("\n--------------------------------------------------\nKernel : Shutting down\n");
    766 
    767         verify( TL_GET( preemption_state.enabled ) );
     806static 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 ) );
    768811        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");
    770815
    771816        // SKULLDUGGERY: Notify the mainProcessor it needs to terminates.
     
    773818        // which is currently here
    774819        __atomic_store_n(&mainProcessor->do_terminate, true, __ATOMIC_RELEASE);
    775         kernel_last_resume( kernelTLS.this_processor );
     820        __kernel_last_resume( kernelTLS.this_processor );
    776821        mainThread->self_cor.state = Halted;
    777822
     
    783828        // Destroy the main processor and its context in reverse order of construction
    784829        // 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){};
    787835
    788836        // Final step, destroy the main thread since it is no longer needed
    789837        // 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){};
    791842
    792843        ^(__cfa_dbg_global_clusters.list){};
    793844        ^(__cfa_dbg_global_clusters.lock){};
    794845
    795         __cfaabi_dbg_print_safe("Kernel : Shutdown complete\n");
     846        __cfadbg_print_safe(runtime_core, "Kernel : Shutdown complete\n");
    796847}
    797848
    798849//=============================================================================================
    799 // Kernel Quiescing
     850// Kernel Idle Sleep
    800851//=============================================================================================
    801 static void halt(processor * this) with( *this ) {
    802         // verify( ! __atomic_load_n(&do_terminate, __ATOMIC_SEQ_CST) );
    803 
     852static $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
    804878        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
     889static 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
     914static 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;
    823923}
    824924
     
    854954
    855955void kernel_abort_msg( void * kernel_data, char * abort_text, int abort_text_size ) {
    856         thread_desc * thrd = kernel_data;
     956        $thread * thrd = kernel_data;
    857957
    858958        if(thrd) {
     
    9021002void ^?{}(semaphore & this) {}
    9031003
    904 void P(semaphore & this) with( this ){
     1004bool P(semaphore & this) with( this ){
    9051005        lock( lock __cfaabi_dbg_ctx2 );
    9061006        count -= 1;
     
    9101010
    9111011                // atomically release spin lock and block
    912                 BlockInternal( &lock );
     1012                unlock( lock );
     1013                park( __cfaabi_dbg_ctx );
     1014                return true;
    9131015        }
    9141016        else {
    9151017            unlock( lock );
    916         }
    917 }
    918 
    919 void V(semaphore & this) with( this ) {
    920         thread_desc * thrd = 0p;
     1018            return false;
     1019        }
     1020}
     1021
     1022bool V(semaphore & this) with( this ) {
     1023        $thread * thrd = 0p;
    9211024        lock( lock __cfaabi_dbg_ctx2 );
    9221025        count += 1;
     
    9291032
    9301033        // make new owner
    931         WakeThread( thrd );
     1034        unpark( thrd __cfaabi_dbg_ctx2 );
     1035
     1036        return thrd != 0p;
     1037}
     1038
     1039bool 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;
    9321051}
    9331052
     
    9461065}
    9471066
    948 void doregister( cluster * cltr, thread_desc & thrd ) {
     1067void doregister( cluster * cltr, $thread & thrd ) {
    9491068        lock      (cltr->thread_list_lock __cfaabi_dbg_ctx2);
    9501069        cltr->nthreads += 1;
     
    9531072}
    9541073
    955 void unregister( cluster * cltr, thread_desc & thrd ) {
     1074void unregister( cluster * cltr, $thread & thrd ) {
    9561075        lock  (cltr->thread_list_lock __cfaabi_dbg_ctx2);
    9571076        remove(cltr->threads, thrd );
     
    9611080
    9621081void doregister( cluster * cltr, processor * proc ) {
    963         lock      (cltr->proc_list_lock __cfaabi_dbg_ctx2);
     1082        lock      (cltr->idle_lock __cfaabi_dbg_ctx2);
    9641083        cltr->nprocessors += 1;
    9651084        push_front(cltr->procs, *proc);
    966         unlock    (cltr->proc_list_lock);
     1085        unlock    (cltr->idle_lock);
    9671086}
    9681087
    9691088void unregister( cluster * cltr, processor * proc ) {
    970         lock  (cltr->proc_list_lock __cfaabi_dbg_ctx2);
     1089        lock  (cltr->idle_lock __cfaabi_dbg_ctx2);
    9711090        remove(cltr->procs, *proc );
    9721091        cltr->nprocessors -= 1;
    973         unlock(cltr->proc_list_lock);
     1092        unlock(cltr->idle_lock);
    9741093}
    9751094
     
    9781097__cfaabi_dbg_debug_do(
    9791098        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[]) {
    9811100                        this.prev_name = prev_name;
    9821101                        this.prev_thrd = kernelTLS.this_thread;
    9831102                }
     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                }
    9841114        }
    9851115)
     
    9871117//-----------------------------------------------------------------------------
    9881118// Debug
    989 bool threading_enabled(void) {
     1119bool threading_enabled(void) __attribute__((const)) {
    9901120        return true;
    9911121}
Note: See TracChangeset for help on using the changeset viewer.