Ignore:
File:
1 edited

Legend:

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

    r4aa2fb2 r1c273d0  
    5959// Global state
    6060
    61 thread_local processor * this_processor;
    62 
    63 coroutine_desc * this_coroutine(void) {
    64         return this_processor->current_coroutine;
    65 }
    66 
    67 thread_desc * this_thread(void) {
    68         return this_processor->current_thread;
    69 }
     61volatile thread_local processor * this_processor;
     62volatile thread_local coroutine_desc * this_coroutine;
     63volatile thread_local thread_desc * this_thread;
     64volatile thread_local unsigned short disable_preempt_count = 1;
    7065
    7166//-----------------------------------------------------------------------------
    7267// Main thread construction
    7368struct current_stack_info_t {
    74         machine_context_t ctx; 
     69        machine_context_t ctx;
    7570        unsigned int size;              // size of stack
    7671        void *base;                             // base of stack
     
    106101
    107102void ?{}( coroutine_desc * this, current_stack_info_t * info) {
    108         (&this->stack){ info }; 
     103        (&this->stack){ info };
    109104        this->name = "Main Thread";
    110105        this->errno_ = 0;
     
    136131void ?{}(processor * this, cluster * cltr) {
    137132        this->cltr = cltr;
    138         this->current_coroutine = NULL;
    139         this->current_thread = NULL;
    140133        (&this->terminated){};
    141134        this->is_terminated = false;
    142135        this->preemption_alarm = NULL;
    143136        this->preemption = default_preemption();
    144         this->disable_preempt_count = 1;                //Start with interrupts disabled
    145137        this->pending_preemption = false;
    146138
     
    150142void ?{}(processor * this, cluster * cltr, processorCtx_t * runner) {
    151143        this->cltr = cltr;
    152         this->current_coroutine = NULL;
    153         this->current_thread = NULL;
    154144        (&this->terminated){};
    155145        this->is_terminated = false;
    156         this->disable_preempt_count = 0;
     146        this->preemption_alarm = NULL;
     147        this->preemption = default_preemption();
    157148        this->pending_preemption = false;
     149        this->kernel_thread = pthread_self();
    158150
    159151        this->runner = runner;
    160         LIB_DEBUG_PRINT_SAFE("Kernel : constructing processor context %p\n", runner);
     152        LIB_DEBUG_PRINT_SAFE("Kernel : constructing system processor context %p\n", runner);
    161153        runner{ this };
    162154}
     155
     156LIB_DEBUG_DO( bool validate( alarm_list_t * this ); )
    163157
    164158void ?{}(system_proc_t * this, cluster * cltr, processorCtx_t * runner) {
     
    168162
    169163        (&this->proc){ cltr, runner };
     164
     165        verify( validate( &this->alarms ) );
    170166}
    171167
     
    184180
    185181void ^?{}(cluster * this) {
    186        
     182
    187183}
    188184
     
    203199
    204200                thread_desc * readyThread = NULL;
    205                 for( unsigned int spin_count = 0; ! this->is_terminated; spin_count++ ) 
     201                for( unsigned int spin_count = 0; ! this->is_terminated; spin_count++ )
    206202                {
    207203                        readyThread = nextThread( this->cltr );
     
    209205                        if(readyThread)
    210206                        {
     207                                verify( disable_preempt_count > 0 );
     208
    211209                                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->current_thread = dst;
     241        this_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;
    291294        // SKULLDUGGERY: We want to create a context for the processor coroutine
    292295        // which is needed for the 2-step context switch. However, there is no reason
    293         // to waste the perfectly valid stack create by pthread. 
     296        // to waste the perfectly valid stack create by pthread.
    294297        current_stack_info_t info;
    295298        machine_context_t ctx;
     
    300303
    301304        //Set global state
    302         proc->current_coroutine = &proc->runner->__cor;
    303         proc->current_thread = NULL;
     305        this_coroutine = &proc->runner->__cor;
     306        this_thread = NULL;
    304307
    305308        //We now have a proper context from which to schedule threads
    306309        LIB_DEBUG_PRINT_SAFE("Kernel : core %p created (%p, %p)\n", proc, proc->runner, &ctx);
    307310
    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 
     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
    311314        // appropriate stack.
    312315        proc_cor_storage.__cor.state = Active;
     
    315318
    316319        // Main routine of the core returned, the core is now fully terminated
    317         LIB_DEBUG_PRINT_SAFE("Kernel : core %p main ended (%p)\n", proc, proc->runner); 
     320        LIB_DEBUG_PRINT_SAFE("Kernel : core %p main ended (%p)\n", proc, proc->runner);
    318321
    319322        return NULL;
     
    322325void start(processor * this) {
    323326        LIB_DEBUG_PRINT_SAFE("Kernel : Starting core %p\n", this);
    324        
     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
    325348        pthread_create( &this->kernel_thread, NULL, CtxInvokeProcessor, (void*)this );
    326349
    327         LIB_DEBUG_PRINT_SAFE("Kernel : core %p started\n", this);       
     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);
    328358}
    329359
     
    331361// Scheduler routines
    332362void ScheduleThread( thread_desc * thrd ) {
    333         if( !thrd ) return;
     363        // if( !thrd ) return;
     364        assert( thrd );
     365        assert( thrd->cor.state != Halted );
     366
     367        verify( disable_preempt_count > 0 );
    334368
    335369        verifyf( thrd->next == NULL, "Expected null got %p", thrd->next );
    336        
    337         lock( &systemProcessor->proc.cltr->lock );
     370
     371        lock( &systemProcessor->proc.cltr->lock, __PRETTY_FUNCTION__ );
    338372        append( &systemProcessor->proc.cltr->ready_queue, thrd );
    339373        unlock( &systemProcessor->proc.cltr->lock );
     374
     375        verify( disable_preempt_count > 0 );
    340376}
    341377
    342378thread_desc * nextThread(cluster * this) {
    343         lock( &this->lock );
     379        verify( disable_preempt_count > 0 );
     380        lock( &this->lock, __PRETTY_FUNCTION__ );
    344381        thread_desc * head = pop_head( &this->ready_queue );
    345382        unlock( &this->lock );
     383        verify( disable_preempt_count > 0 );
    346384        return head;
    347385}
    348386
    349 void ScheduleInternal() {
     387void BlockInternal() {
     388        disable_interrupts();
     389        verify( disable_preempt_count > 0 );
    350390        suspend();
    351 }
    352 
    353 void ScheduleInternal( spinlock * lock ) {
     391        verify( disable_preempt_count > 0 );
     392        enable_interrupts( __PRETTY_FUNCTION__ );
     393}
     394
     395void BlockInternal( spinlock * lock ) {
     396        disable_interrupts();
    354397        this_processor->finish.action_code = Release;
    355398        this_processor->finish.lock = lock;
     399
     400        verify( disable_preempt_count > 0 );
    356401        suspend();
    357 }
    358 
    359 void ScheduleInternal( thread_desc * thrd ) {
     402        verify( disable_preempt_count > 0 );
     403
     404        enable_interrupts( __PRETTY_FUNCTION__ );
     405}
     406
     407void BlockInternal( thread_desc * thrd ) {
     408        disable_interrupts();
     409        assert( thrd->cor.state != Halted );
    360410        this_processor->finish.action_code = Schedule;
    361411        this_processor->finish.thrd = thrd;
     412
     413        verify( disable_preempt_count > 0 );
    362414        suspend();
    363 }
    364 
    365 void ScheduleInternal( spinlock * lock, thread_desc * thrd ) {
     415        verify( disable_preempt_count > 0 );
     416
     417        enable_interrupts( __PRETTY_FUNCTION__ );
     418}
     419
     420void BlockInternal( spinlock * lock, thread_desc * thrd ) {
     421        disable_interrupts();
    366422        this_processor->finish.action_code = Release_Schedule;
    367423        this_processor->finish.lock = lock;
    368424        this_processor->finish.thrd = thrd;
     425
     426        verify( disable_preempt_count > 0 );
    369427        suspend();
    370 }
    371 
    372 void ScheduleInternal(spinlock ** locks, unsigned short count) {
     428        verify( disable_preempt_count > 0 );
     429
     430        enable_interrupts( __PRETTY_FUNCTION__ );
     431}
     432
     433void BlockInternal(spinlock ** locks, unsigned short count) {
     434        disable_interrupts();
    373435        this_processor->finish.action_code = Release_Multi;
    374436        this_processor->finish.locks = locks;
    375437        this_processor->finish.lock_count = count;
     438
     439        verify( disable_preempt_count > 0 );
    376440        suspend();
    377 }
    378 
    379 void ScheduleInternal(spinlock ** locks, unsigned short lock_count, thread_desc ** thrds, unsigned short thrd_count) {
     441        verify( disable_preempt_count > 0 );
     442
     443        enable_interrupts( __PRETTY_FUNCTION__ );
     444}
     445
     446void BlockInternal(spinlock ** locks, unsigned short lock_count, thread_desc ** thrds, unsigned short thrd_count) {
     447        disable_interrupts();
    380448        this_processor->finish.action_code = Release_Multi_Schedule;
    381449        this_processor->finish.locks = locks;
     
    383451        this_processor->finish.thrds = thrds;
    384452        this_processor->finish.thrd_count = thrd_count;
     453
     454        verify( disable_preempt_count > 0 );
    385455        suspend();
     456        verify( disable_preempt_count > 0 );
     457
     458        enable_interrupts( __PRETTY_FUNCTION__ );
    386459}
    387460
     
    392465// Kernel boot procedures
    393466void kernel_startup(void) {
    394         LIB_DEBUG_PRINT_SAFE("Kernel : Starting\n");   
     467        LIB_DEBUG_PRINT_SAFE("Kernel : Starting\n");
    395468
    396469        // Start by initializing the main thread
    397         // SKULLDUGGERY: the mainThread steals the process main thread 
     470        // SKULLDUGGERY: the mainThread steals the process main thread
    398471        // which will then be scheduled by the systemProcessor normally
    399472        mainThread = (thread_desc *)&mainThread_storage;
     
    403476        LIB_DEBUG_PRINT_SAFE("Kernel : Main thread ready\n");
    404477
    405         // Enable preemption
    406         kernel_start_preemption();
    407 
    408478        // Initialize the system cluster
    409479        systemCluster = (cluster *)&systemCluster_storage;
     
    417487        systemProcessor{ systemCluster, (processorCtx_t *)&systemProcessorCtx_storage };
    418488
    419         // Add the main thread to the ready queue 
     489        // Add the main thread to the ready queue
    420490        // once resume is called on systemProcessor->runner the mainThread needs to be scheduled like any normal thread
    421491        ScheduleThread(mainThread);
     
    423493        //initialize the global state variables
    424494        this_processor = &systemProcessor->proc;
    425         this_processor->current_thread = mainThread;
    426         this_processor->current_coroutine = &mainThread->cor;
     495        this_thread = mainThread;
     496        this_coroutine = &mainThread->cor;
     497        disable_preempt_count = 1;
     498
     499        // Enable preemption
     500        kernel_start_preemption();
    427501
    428502        // SKULLDUGGERY: Force a context switch to the system processor to set the main thread's context to the current UNIX
    429503        // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that
    430         // mainThread is on the ready queue when this call is made. 
     504        // mainThread is on the ready queue when this call is made.
    431505        resume( systemProcessor->proc.runner );
    432506
     
    435509        // THE SYSTEM IS NOW COMPLETELY RUNNING
    436510        LIB_DEBUG_PRINT_SAFE("Kernel : Started\n--------------------------------------------------\n\n");
     511
     512        enable_interrupts( __PRETTY_FUNCTION__ );
    437513}
    438514
    439515void kernel_shutdown(void) {
    440516        LIB_DEBUG_PRINT_SAFE("\n--------------------------------------------------\nKernel : Shutting down\n");
     517
     518        disable_interrupts();
    441519
    442520        // SKULLDUGGERY: Notify the systemProcessor it needs to terminates.
     
    448526        // THE SYSTEM IS NOW COMPLETELY STOPPED
    449527
     528        // Disable preemption
     529        kernel_stop_preemption();
     530
    450531        // Destroy the system processor and its context in reverse order of construction
    451532        // These were manually constructed so we need manually destroy them
     
    457538        ^(mainThread){};
    458539
    459         LIB_DEBUG_PRINT_SAFE("Kernel : Shutdown complete\n");   
     540        LIB_DEBUG_PRINT_SAFE("Kernel : Shutdown complete\n");
    460541}
    461542
     
    467548        // abort cannot be recursively entered by the same or different processors because all signal handlers return when
    468549        // the globalAbort flag is true.
    469         lock( &kernel_abort_lock );
     550        lock( &kernel_abort_lock, __PRETTY_FUNCTION__ );
    470551
    471552        // first task to abort ?
     
    473554                kernel_abort_called = true;
    474555                unlock( &kernel_abort_lock );
    475         } 
     556        }
    476557        else {
    477558                unlock( &kernel_abort_lock );
    478                
     559
    479560                sigset_t mask;
    480561                sigemptyset( &mask );
     
    482563                sigaddset( &mask, SIGUSR1 );                    // block SIGUSR1 signals
    483564                sigsuspend( &mask );                            // block the processor to prevent further damage during abort
    484                 _exit( EXIT_FAILURE );                          // if processor unblocks before it is killed, terminate it             
    485         }
    486 
    487         return this_thread();
     565                _exit( EXIT_FAILURE );                          // if processor unblocks before it is killed, terminate it
     566        }
     567
     568        return this_thread;
    488569}
    489570
     
    494575        __lib_debug_write( STDERR_FILENO, abort_text, len );
    495576
    496         if ( thrd != this_coroutine() ) {
    497                 len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", this_coroutine()->name, this_coroutine() );
     577        if ( thrd != this_coroutine ) {
     578                len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", this_coroutine->name, this_coroutine );
    498579                __lib_debug_write( STDERR_FILENO, abort_text, len );
    499         } 
     580        }
    500581        else {
    501582                __lib_debug_write( STDERR_FILENO, ".\n", 2 );
     
    505586extern "C" {
    506587        void __lib_debug_acquire() {
    507                 lock(&kernel_debug_lock);
     588                lock(&kernel_debug_lock, __PRETTY_FUNCTION__);
    508589        }
    509590
     
    525606}
    526607
    527 bool try_lock( spinlock * this ) {
    528         return this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0;
    529 }
    530 
    531 void lock( spinlock * this ) {
     608bool 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
     614void lock( spinlock * this, const char * caller ) {
    532615        for ( unsigned int i = 1;; i += 1 ) {
    533616                if ( this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0 ) break;
    534617        }
     618        this->prev = caller;
    535619}
    536620
     
    547631
    548632void wait( signal_once * this ) {
    549         lock( &this->lock );
     633        lock( &this->lock, __PRETTY_FUNCTION__ );
    550634        if( !this->cond ) {
    551                 append( &this->blocked, this_thread() );
    552                 ScheduleInternal( &this->lock );
    553                 lock( &this->lock );
    554         }
    555         unlock( &this->lock );
     635                append( &this->blocked, (thread_desc*)this_thread );
     636                BlockInternal( &this->lock );
     637        }
     638        else {
     639                unlock( &this->lock );
     640        }
    556641}
    557642
    558643void signal( signal_once * this ) {
    559         lock( &this->lock );
     644        lock( &this->lock, __PRETTY_FUNCTION__ );
    560645        {
    561646                this->cond = true;
    562647
     648                disable_interrupts();
    563649                thread_desc * it;
    564650                while( it = pop_head( &this->blocked) ) {
    565651                        ScheduleThread( it );
    566652                }
     653                enable_interrupts( __PRETTY_FUNCTION__ );
    567654        }
    568655        unlock( &this->lock );
     
    590677                }
    591678                head->next = NULL;
    592         }       
     679        }
    593680        return head;
    594681}
     
    609696                this->top = top->next;
    610697                top->next = NULL;
    611         }       
     698        }
    612699        return top;
    613700}
Note: See TracChangeset for help on using the changeset viewer.