Ignore:
File:
1 edited

Legend:

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

    r1c273d0 r4aa2fb2  
    5959// Global state
    6060
    61 volatile thread_local processor * this_processor;
    62 volatile thread_local coroutine_desc * this_coroutine;
    63 volatile thread_local thread_desc * this_thread;
    64 volatile thread_local unsigned short disable_preempt_count = 1;
     61thread_local processor * this_processor;
     62
     63coroutine_desc * this_coroutine(void) {
     64        return this_processor->current_coroutine;
     65}
     66
     67thread_desc * this_thread(void) {
     68        return this_processor->current_thread;
     69}
    6570
    6671//-----------------------------------------------------------------------------
    6772// Main thread construction
    6873struct current_stack_info_t {
    69         machine_context_t ctx;
     74        machine_context_t ctx; 
    7075        unsigned int size;              // size of stack
    7176        void *base;                             // base of stack
     
    101106
    102107void ?{}( coroutine_desc * this, current_stack_info_t * info) {
    103         (&this->stack){ info };
     108        (&this->stack){ info }; 
    104109        this->name = "Main Thread";
    105110        this->errno_ = 0;
     
    131136void ?{}(processor * this, cluster * cltr) {
    132137        this->cltr = cltr;
     138        this->current_coroutine = NULL;
     139        this->current_thread = NULL;
    133140        (&this->terminated){};
    134141        this->is_terminated = false;
    135142        this->preemption_alarm = NULL;
    136143        this->preemption = default_preemption();
     144        this->disable_preempt_count = 1;                //Start with interrupts disabled
    137145        this->pending_preemption = false;
    138146
     
    142150void ?{}(processor * this, cluster * cltr, processorCtx_t * runner) {
    143151        this->cltr = cltr;
     152        this->current_coroutine = NULL;
     153        this->current_thread = NULL;
    144154        (&this->terminated){};
    145155        this->is_terminated = false;
    146         this->preemption_alarm = NULL;
    147         this->preemption = default_preemption();
     156        this->disable_preempt_count = 0;
    148157        this->pending_preemption = false;
    149         this->kernel_thread = pthread_self();
    150158
    151159        this->runner = runner;
    152         LIB_DEBUG_PRINT_SAFE("Kernel : constructing system processor context %p\n", runner);
     160        LIB_DEBUG_PRINT_SAFE("Kernel : constructing processor context %p\n", runner);
    153161        runner{ this };
    154162}
    155 
    156 LIB_DEBUG_DO( bool validate( alarm_list_t * this ); )
    157163
    158164void ?{}(system_proc_t * this, cluster * cltr, processorCtx_t * runner) {
     
    162168
    163169        (&this->proc){ cltr, runner };
    164 
    165         verify( validate( &this->alarms ) );
    166170}
    167171
     
    180184
    181185void ^?{}(cluster * this) {
    182 
     186       
    183187}
    184188
     
    199203
    200204                thread_desc * readyThread = NULL;
    201                 for( unsigned int spin_count = 0; ! this->is_terminated; spin_count++ )
     205                for( unsigned int spin_count = 0; ! this->is_terminated; spin_count++ ) 
    202206                {
    203207                        readyThread = nextThread( this->cltr );
     
    205209                        if(readyThread)
    206210                        {
    207                                 verify( disable_preempt_count > 0 );
    208 
    209211                                runThread(this, readyThread);
    210 
    211                                 verify( disable_preempt_count > 0 );
    212212
    213213                                //Some actions need to be taken from the kernel
     
    229229}
    230230
    231 // runThread runs a thread by context switching
    232 // from the processor coroutine to the target thread
     231// runThread runs a thread by context switching 
     232// from the processor coroutine to the target thread 
    233233void runThread(processor * this, thread_desc * dst) {
    234234        coroutine_desc * proc_cor = get_coroutine(this->runner);
    235235        coroutine_desc * thrd_cor = get_coroutine(dst);
    236 
     236       
    237237        //Reset the terminating actions here
    238238        this->finish.action_code = No_Action;
    239239
    240240        //Update global state
    241         this_thread = dst;
     241        this->current_thread = dst;
    242242
    243243        // Context Switch to the thread
     
    246246}
    247247
    248 // Once a thread has finished running, some of
     248// Once a thread has finished running, some of 
    249249// its final actions must be executed from the kernel
    250250void finishRunning(processor * this) {
     
    256256        }
    257257        else if( this->finish.action_code == Release_Schedule ) {
    258                 unlock( this->finish.lock );
     258                unlock( this->finish.lock );           
    259259                ScheduleThread( this->finish.thrd );
    260260        }
     
    289289        processor * proc = (processor *) arg;
    290290        this_processor = proc;
    291         this_coroutine = NULL;
    292         this_thread = NULL;
    293         disable_preempt_count = 1;
    294291        // SKULLDUGGERY: We want to create a context for the processor coroutine
    295292        // which is needed for the 2-step context switch. However, there is no reason
    296         // to waste the perfectly valid stack create by pthread.
     293        // to waste the perfectly valid stack create by pthread. 
    297294        current_stack_info_t info;
    298295        machine_context_t ctx;
     
    303300
    304301        //Set global state
    305         this_coroutine = &proc->runner->__cor;
    306         this_thread = NULL;
     302        proc->current_coroutine = &proc->runner->__cor;
     303        proc->current_thread = NULL;
    307304
    308305        //We now have a proper context from which to schedule threads
    309306        LIB_DEBUG_PRINT_SAFE("Kernel : core %p created (%p, %p)\n", proc, proc->runner, &ctx);
    310307
    311         // SKULLDUGGERY: Since the coroutine doesn't have its own stack, we can't
    312         // resume it to start it like it normally would, it will just context switch
    313         // back to here. Instead directly call the main since we already are on the
     308        // SKULLDUGGERY: Since the coroutine doesn't have its own stack, we can't 
     309        // resume it to start it like it normally would, it will just context switch 
     310        // back to here. Instead directly call the main since we already are on the 
    314311        // appropriate stack.
    315312        proc_cor_storage.__cor.state = Active;
     
    318315
    319316        // Main routine of the core returned, the core is now fully terminated
    320         LIB_DEBUG_PRINT_SAFE("Kernel : core %p main ended (%p)\n", proc, proc->runner);
     317        LIB_DEBUG_PRINT_SAFE("Kernel : core %p main ended (%p)\n", proc, proc->runner); 
    321318
    322319        return NULL;
     
    325322void start(processor * this) {
    326323        LIB_DEBUG_PRINT_SAFE("Kernel : Starting core %p\n", this);
    327 
    328         // SIGALRM must only be caught by the system processor
    329         sigset_t old_mask;
    330         bool is_system_proc = this_processor == &systemProcessor->proc;
    331         if ( is_system_proc ) {
    332                 // Child kernel-thread inherits the signal mask from the parent kernel-thread. So one special case for the
    333                 // system processor creating the user processor => toggle the blocking SIGALRM on system processor, create user
    334                 // processor, and toggle back (below) previous signal mask of the system processor.
    335 
    336                 sigset_t new_mask;
    337                 sigemptyset( &new_mask );
    338                 sigemptyset( &old_mask );
    339                 sigaddset( &new_mask, SIGALRM );
    340 
    341                 if ( sigprocmask( SIG_BLOCK, &new_mask, &old_mask ) == -1 ) {
    342                         abortf( "internal error, sigprocmask" );
    343                 }
    344 
    345                 assert( ! sigismember( &old_mask, SIGALRM ) );
    346         }
    347 
     324       
    348325        pthread_create( &this->kernel_thread, NULL, CtxInvokeProcessor, (void*)this );
    349326
    350         // Toggle back previous signal mask of system processor.
    351         if ( is_system_proc ) {
    352                 if ( sigprocmask( SIG_SETMASK, &old_mask, NULL ) == -1 ) {
    353                         abortf( "internal error, sigprocmask" );
    354                 } // if
    355         } // if
    356 
    357         LIB_DEBUG_PRINT_SAFE("Kernel : core %p started\n", this);
     327        LIB_DEBUG_PRINT_SAFE("Kernel : core %p started\n", this);       
    358328}
    359329
     
    361331// Scheduler routines
    362332void ScheduleThread( thread_desc * thrd ) {
    363         // if( !thrd ) return;
    364         assert( thrd );
    365         assert( thrd->cor.state != Halted );
    366 
    367         verify( disable_preempt_count > 0 );
     333        if( !thrd ) return;
    368334
    369335        verifyf( thrd->next == NULL, "Expected null got %p", thrd->next );
    370 
    371         lock( &systemProcessor->proc.cltr->lock, __PRETTY_FUNCTION__ );
     336       
     337        lock( &systemProcessor->proc.cltr->lock );
    372338        append( &systemProcessor->proc.cltr->ready_queue, thrd );
    373339        unlock( &systemProcessor->proc.cltr->lock );
    374 
    375         verify( disable_preempt_count > 0 );
    376340}
    377341
    378342thread_desc * nextThread(cluster * this) {
    379         verify( disable_preempt_count > 0 );
    380         lock( &this->lock, __PRETTY_FUNCTION__ );
     343        lock( &this->lock );
    381344        thread_desc * head = pop_head( &this->ready_queue );
    382345        unlock( &this->lock );
    383         verify( disable_preempt_count > 0 );
    384346        return head;
    385347}
    386348
    387 void BlockInternal() {
    388         disable_interrupts();
    389         verify( disable_preempt_count > 0 );
     349void ScheduleInternal() {
    390350        suspend();
    391         verify( disable_preempt_count > 0 );
    392         enable_interrupts( __PRETTY_FUNCTION__ );
    393 }
    394 
    395 void BlockInternal( spinlock * lock ) {
    396         disable_interrupts();
     351}
     352
     353void ScheduleInternal( spinlock * lock ) {
    397354        this_processor->finish.action_code = Release;
    398355        this_processor->finish.lock = lock;
    399 
    400         verify( disable_preempt_count > 0 );
    401356        suspend();
    402         verify( disable_preempt_count > 0 );
    403 
    404         enable_interrupts( __PRETTY_FUNCTION__ );
    405 }
    406 
    407 void BlockInternal( thread_desc * thrd ) {
    408         disable_interrupts();
    409         assert( thrd->cor.state != Halted );
     357}
     358
     359void ScheduleInternal( thread_desc * thrd ) {
    410360        this_processor->finish.action_code = Schedule;
    411361        this_processor->finish.thrd = thrd;
    412 
    413         verify( disable_preempt_count > 0 );
    414362        suspend();
    415         verify( disable_preempt_count > 0 );
    416 
    417         enable_interrupts( __PRETTY_FUNCTION__ );
    418 }
    419 
    420 void BlockInternal( spinlock * lock, thread_desc * thrd ) {
    421         disable_interrupts();
     363}
     364
     365void ScheduleInternal( spinlock * lock, thread_desc * thrd ) {
    422366        this_processor->finish.action_code = Release_Schedule;
    423367        this_processor->finish.lock = lock;
    424368        this_processor->finish.thrd = thrd;
    425 
    426         verify( disable_preempt_count > 0 );
    427369        suspend();
    428         verify( disable_preempt_count > 0 );
    429 
    430         enable_interrupts( __PRETTY_FUNCTION__ );
    431 }
    432 
    433 void BlockInternal(spinlock ** locks, unsigned short count) {
    434         disable_interrupts();
     370}
     371
     372void ScheduleInternal(spinlock ** locks, unsigned short count) {
    435373        this_processor->finish.action_code = Release_Multi;
    436374        this_processor->finish.locks = locks;
    437375        this_processor->finish.lock_count = count;
    438 
    439         verify( disable_preempt_count > 0 );
    440376        suspend();
    441         verify( disable_preempt_count > 0 );
    442 
    443         enable_interrupts( __PRETTY_FUNCTION__ );
    444 }
    445 
    446 void BlockInternal(spinlock ** locks, unsigned short lock_count, thread_desc ** thrds, unsigned short thrd_count) {
    447         disable_interrupts();
     377}
     378
     379void ScheduleInternal(spinlock ** locks, unsigned short lock_count, thread_desc ** thrds, unsigned short thrd_count) {
    448380        this_processor->finish.action_code = Release_Multi_Schedule;
    449381        this_processor->finish.locks = locks;
     
    451383        this_processor->finish.thrds = thrds;
    452384        this_processor->finish.thrd_count = thrd_count;
    453 
    454         verify( disable_preempt_count > 0 );
    455385        suspend();
    456         verify( disable_preempt_count > 0 );
    457 
    458         enable_interrupts( __PRETTY_FUNCTION__ );
    459386}
    460387
     
    465392// Kernel boot procedures
    466393void kernel_startup(void) {
    467         LIB_DEBUG_PRINT_SAFE("Kernel : Starting\n");
     394        LIB_DEBUG_PRINT_SAFE("Kernel : Starting\n");   
    468395
    469396        // Start by initializing the main thread
    470         // SKULLDUGGERY: the mainThread steals the process main thread
     397        // SKULLDUGGERY: the mainThread steals the process main thread 
    471398        // which will then be scheduled by the systemProcessor normally
    472399        mainThread = (thread_desc *)&mainThread_storage;
     
    476403        LIB_DEBUG_PRINT_SAFE("Kernel : Main thread ready\n");
    477404
     405        // Enable preemption
     406        kernel_start_preemption();
     407
    478408        // Initialize the system cluster
    479409        systemCluster = (cluster *)&systemCluster_storage;
     
    487417        systemProcessor{ systemCluster, (processorCtx_t *)&systemProcessorCtx_storage };
    488418
    489         // Add the main thread to the ready queue
     419        // Add the main thread to the ready queue 
    490420        // once resume is called on systemProcessor->runner the mainThread needs to be scheduled like any normal thread
    491421        ScheduleThread(mainThread);
     
    493423        //initialize the global state variables
    494424        this_processor = &systemProcessor->proc;
    495         this_thread = mainThread;
    496         this_coroutine = &mainThread->cor;
    497         disable_preempt_count = 1;
    498 
    499         // Enable preemption
    500         kernel_start_preemption();
     425        this_processor->current_thread = mainThread;
     426        this_processor->current_coroutine = &mainThread->cor;
    501427
    502428        // SKULLDUGGERY: Force a context switch to the system processor to set the main thread's context to the current UNIX
    503429        // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that
    504         // mainThread is on the ready queue when this call is made.
     430        // mainThread is on the ready queue when this call is made. 
    505431        resume( systemProcessor->proc.runner );
    506432
     
    509435        // THE SYSTEM IS NOW COMPLETELY RUNNING
    510436        LIB_DEBUG_PRINT_SAFE("Kernel : Started\n--------------------------------------------------\n\n");
    511 
    512         enable_interrupts( __PRETTY_FUNCTION__ );
    513437}
    514438
    515439void kernel_shutdown(void) {
    516440        LIB_DEBUG_PRINT_SAFE("\n--------------------------------------------------\nKernel : Shutting down\n");
    517 
    518         disable_interrupts();
    519441
    520442        // SKULLDUGGERY: Notify the systemProcessor it needs to terminates.
     
    526448        // THE SYSTEM IS NOW COMPLETELY STOPPED
    527449
    528         // Disable preemption
    529         kernel_stop_preemption();
    530 
    531450        // Destroy the system processor and its context in reverse order of construction
    532451        // These were manually constructed so we need manually destroy them
     
    538457        ^(mainThread){};
    539458
    540         LIB_DEBUG_PRINT_SAFE("Kernel : Shutdown complete\n");
     459        LIB_DEBUG_PRINT_SAFE("Kernel : Shutdown complete\n");   
    541460}
    542461
     
    548467        // abort cannot be recursively entered by the same or different processors because all signal handlers return when
    549468        // the globalAbort flag is true.
    550         lock( &kernel_abort_lock, __PRETTY_FUNCTION__ );
     469        lock( &kernel_abort_lock );
    551470
    552471        // first task to abort ?
     
    554473                kernel_abort_called = true;
    555474                unlock( &kernel_abort_lock );
    556         }
     475        } 
    557476        else {
    558477                unlock( &kernel_abort_lock );
    559 
     478               
    560479                sigset_t mask;
    561480                sigemptyset( &mask );
     
    563482                sigaddset( &mask, SIGUSR1 );                    // block SIGUSR1 signals
    564483                sigsuspend( &mask );                            // block the processor to prevent further damage during abort
    565                 _exit( EXIT_FAILURE );                          // if processor unblocks before it is killed, terminate it
    566         }
    567 
    568         return this_thread;
     484                _exit( EXIT_FAILURE );                          // if processor unblocks before it is killed, terminate it             
     485        }
     486
     487        return this_thread();
    569488}
    570489
     
    575494        __lib_debug_write( STDERR_FILENO, abort_text, len );
    576495
    577         if ( thrd != this_coroutine ) {
    578                 len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", this_coroutine->name, this_coroutine );
     496        if ( thrd != this_coroutine() ) {
     497                len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", this_coroutine()->name, this_coroutine() );
    579498                __lib_debug_write( STDERR_FILENO, abort_text, len );
    580         }
     499        } 
    581500        else {
    582501                __lib_debug_write( STDERR_FILENO, ".\n", 2 );
     
    586505extern "C" {
    587506        void __lib_debug_acquire() {
    588                 lock(&kernel_debug_lock, __PRETTY_FUNCTION__);
     507                lock(&kernel_debug_lock);
    589508        }
    590509
     
    606525}
    607526
    608 bool try_lock( spinlock * this, const char * caller ) {
    609         bool ret = this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0;
    610         this->prev = caller;
    611         return ret;
    612 }
    613 
    614 void lock( spinlock * this, const char * caller ) {
     527bool try_lock( spinlock * this ) {
     528        return this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0;
     529}
     530
     531void lock( spinlock * this ) {
    615532        for ( unsigned int i = 1;; i += 1 ) {
    616533                if ( this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0 ) break;
    617534        }
    618         this->prev = caller;
    619535}
    620536
     
    631547
    632548void wait( signal_once * this ) {
    633         lock( &this->lock, __PRETTY_FUNCTION__ );
     549        lock( &this->lock );
    634550        if( !this->cond ) {
    635                 append( &this->blocked, (thread_desc*)this_thread );
    636                 BlockInternal( &this->lock );
    637         }
    638         else {
    639                 unlock( &this->lock );
    640         }
     551                append( &this->blocked, this_thread() );
     552                ScheduleInternal( &this->lock );
     553                lock( &this->lock );
     554        }
     555        unlock( &this->lock );
    641556}
    642557
    643558void signal( signal_once * this ) {
    644         lock( &this->lock, __PRETTY_FUNCTION__ );
     559        lock( &this->lock );
    645560        {
    646561                this->cond = true;
    647562
    648                 disable_interrupts();
    649563                thread_desc * it;
    650564                while( it = pop_head( &this->blocked) ) {
    651565                        ScheduleThread( it );
    652566                }
    653                 enable_interrupts( __PRETTY_FUNCTION__ );
    654567        }
    655568        unlock( &this->lock );
     
    677590                }
    678591                head->next = NULL;
    679         }
     592        }       
    680593        return head;
    681594}
     
    696609                this->top = top->next;
    697610                top->next = NULL;
    698         }
     611        }       
    699612        return top;
    700613}
Note: See TracChangeset for help on using the changeset viewer.