Ignore:
File:
1 edited

Legend:

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

    rb227f68 r4aa2fb2  
    1515//
    1616
    17 #include "libhdr.h"
     17#include "startup.h"
     18
     19//Start and stop routine for the kernel, declared first to make sure they run first
     20void kernel_startup(void)  __attribute__(( constructor( STARTUP_PRIORITY_KERNEL ) ));
     21void kernel_shutdown(void) __attribute__(( destructor ( STARTUP_PRIORITY_KERNEL ) ));
     22
     23//Header
     24#include "kernel_private.h"
    1825
    1926//C Includes
     
    2835
    2936//CFA Includes
    30 #include "kernel_private.h"
     37#include "libhdr.h"
    3138#include "preemption.h"
    32 #include "startup.h"
    3339
    3440//Private includes
    3541#define __CFA_INVOKE_PRIVATE__
    3642#include "invoke.h"
    37 
    38 //Start and stop routine for the kernel, declared first to make sure they run first
    39 void kernel_startup(void)  __attribute__(( constructor( STARTUP_PRIORITY_KERNEL ) ));
    40 void kernel_shutdown(void) __attribute__(( destructor ( STARTUP_PRIORITY_KERNEL ) ));
    4143
    4244//-----------------------------------------------------------------------------
     
    5759// Global state
    5860
    59 volatile thread_local processor * this_processor;
    60 volatile thread_local coroutine_desc * this_coroutine;
    61 volatile thread_local thread_desc * this_thread;
    62 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}
    6370
    6471//-----------------------------------------------------------------------------
    6572// Main thread construction
    6673struct current_stack_info_t {
    67         machine_context_t ctx;
     74        machine_context_t ctx; 
    6875        unsigned int size;              // size of stack
    6976        void *base;                             // base of stack
     
    99106
    100107void ?{}( coroutine_desc * this, current_stack_info_t * info) {
    101         (&this->stack){ info };
     108        (&this->stack){ info }; 
    102109        this->name = "Main Thread";
    103110        this->errno_ = 0;
     
    129136void ?{}(processor * this, cluster * cltr) {
    130137        this->cltr = cltr;
     138        this->current_coroutine = NULL;
     139        this->current_thread = NULL;
    131140        (&this->terminated){};
    132141        this->is_terminated = false;
    133142        this->preemption_alarm = NULL;
    134143        this->preemption = default_preemption();
     144        this->disable_preempt_count = 1;                //Start with interrupts disabled
    135145        this->pending_preemption = false;
    136146
     
    140150void ?{}(processor * this, cluster * cltr, processorCtx_t * runner) {
    141151        this->cltr = cltr;
     152        this->current_coroutine = NULL;
     153        this->current_thread = NULL;
    142154        (&this->terminated){};
    143155        this->is_terminated = false;
    144         this->preemption_alarm = NULL;
    145         this->preemption = default_preemption();
     156        this->disable_preempt_count = 0;
    146157        this->pending_preemption = false;
    147         this->kernel_thread = pthread_self();
    148158
    149159        this->runner = runner;
    150         LIB_DEBUG_PRINT_SAFE("Kernel : constructing system processor context %p\n", runner);
     160        LIB_DEBUG_PRINT_SAFE("Kernel : constructing processor context %p\n", runner);
    151161        runner{ this };
    152162}
    153 
    154 LIB_DEBUG_DO( bool validate( alarm_list_t * this ); )
    155163
    156164void ?{}(system_proc_t * this, cluster * cltr, processorCtx_t * runner) {
     
    160168
    161169        (&this->proc){ cltr, runner };
    162 
    163         verify( validate( &this->alarms ) );
    164170}
    165171
     
    178184
    179185void ^?{}(cluster * this) {
    180 
     186       
    181187}
    182188
     
    197203
    198204                thread_desc * readyThread = NULL;
    199                 for( unsigned int spin_count = 0; ! this->is_terminated; spin_count++ )
     205                for( unsigned int spin_count = 0; ! this->is_terminated; spin_count++ ) 
    200206                {
    201207                        readyThread = nextThread( this->cltr );
     
    203209                        if(readyThread)
    204210                        {
    205                                 verify( disable_preempt_count > 0 );
    206 
    207211                                runThread(this, readyThread);
    208 
    209                                 verify( disable_preempt_count > 0 );
    210212
    211213                                //Some actions need to be taken from the kernel
     
    227229}
    228230
    229 // runThread runs a thread by context switching
    230 // 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 
    231233void runThread(processor * this, thread_desc * dst) {
    232234        coroutine_desc * proc_cor = get_coroutine(this->runner);
    233235        coroutine_desc * thrd_cor = get_coroutine(dst);
    234 
     236       
    235237        //Reset the terminating actions here
    236238        this->finish.action_code = No_Action;
    237239
    238240        //Update global state
    239         this_thread = dst;
     241        this->current_thread = dst;
    240242
    241243        // Context Switch to the thread
     
    244246}
    245247
    246 // Once a thread has finished running, some of
     248// Once a thread has finished running, some of 
    247249// its final actions must be executed from the kernel
    248250void finishRunning(processor * this) {
     
    254256        }
    255257        else if( this->finish.action_code == Release_Schedule ) {
    256                 unlock( this->finish.lock );
     258                unlock( this->finish.lock );           
    257259                ScheduleThread( this->finish.thrd );
    258260        }
     
    287289        processor * proc = (processor *) arg;
    288290        this_processor = proc;
    289         this_coroutine = NULL;
    290         this_thread = NULL;
    291         disable_preempt_count = 1;
    292291        // SKULLDUGGERY: We want to create a context for the processor coroutine
    293292        // which is needed for the 2-step context switch. However, there is no reason
    294         // to waste the perfectly valid stack create by pthread.
     293        // to waste the perfectly valid stack create by pthread. 
    295294        current_stack_info_t info;
    296295        machine_context_t ctx;
     
    301300
    302301        //Set global state
    303         this_coroutine = &proc->runner->__cor;
    304         this_thread = NULL;
     302        proc->current_coroutine = &proc->runner->__cor;
     303        proc->current_thread = NULL;
    305304
    306305        //We now have a proper context from which to schedule threads
    307306        LIB_DEBUG_PRINT_SAFE("Kernel : core %p created (%p, %p)\n", proc, proc->runner, &ctx);
    308307
    309         // SKULLDUGGERY: Since the coroutine doesn't have its own stack, we can't
    310         // resume it to start it like it normally would, it will just context switch
    311         // 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 
    312311        // appropriate stack.
    313312        proc_cor_storage.__cor.state = Active;
     
    316315
    317316        // Main routine of the core returned, the core is now fully terminated
    318         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); 
    319318
    320319        return NULL;
     
    323322void start(processor * this) {
    324323        LIB_DEBUG_PRINT_SAFE("Kernel : Starting core %p\n", this);
    325 
    326         // SIGALRM must only be caught by the system processor
    327         sigset_t old_mask;
    328         bool is_system_proc = this_processor == &systemProcessor->proc;
    329         if ( is_system_proc ) {
    330                 // Child kernel-thread inherits the signal mask from the parent kernel-thread. So one special case for the
    331                 // system processor creating the user processor => toggle the blocking SIGALRM on system processor, create user
    332                 // processor, and toggle back (below) previous signal mask of the system processor.
    333 
    334                 sigset_t new_mask;
    335                 sigemptyset( &new_mask );
    336                 sigemptyset( &old_mask );
    337                 sigaddset( &new_mask, SIGALRM );
    338 
    339                 if ( sigprocmask( SIG_BLOCK, &new_mask, &old_mask ) == -1 ) {
    340                         abortf( "internal error, sigprocmask" );
    341                 }
    342 
    343                 assert( ! sigismember( &old_mask, SIGALRM ) );
    344         }
    345 
     324       
    346325        pthread_create( &this->kernel_thread, NULL, CtxInvokeProcessor, (void*)this );
    347326
    348         // Toggle back previous signal mask of system processor.
    349         if ( is_system_proc ) {
    350                 if ( sigprocmask( SIG_SETMASK, &old_mask, NULL ) == -1 ) {
    351                         abortf( "internal error, sigprocmask" );
    352                 } // if
    353         } // if
    354 
    355         LIB_DEBUG_PRINT_SAFE("Kernel : core %p started\n", this);
     327        LIB_DEBUG_PRINT_SAFE("Kernel : core %p started\n", this);       
    356328}
    357329
     
    359331// Scheduler routines
    360332void ScheduleThread( thread_desc * thrd ) {
    361         // if( !thrd ) return;
    362         assert( thrd );
    363         assert( thrd->cor.state != Halted );
    364 
    365         verify( disable_preempt_count > 0 );
     333        if( !thrd ) return;
    366334
    367335        verifyf( thrd->next == NULL, "Expected null got %p", thrd->next );
    368 
    369         lock( &systemProcessor->proc.cltr->lock DEBUG_CTX2 );
     336       
     337        lock( &systemProcessor->proc.cltr->lock );
    370338        append( &systemProcessor->proc.cltr->ready_queue, thrd );
    371339        unlock( &systemProcessor->proc.cltr->lock );
    372 
    373         verify( disable_preempt_count > 0 );
    374340}
    375341
    376342thread_desc * nextThread(cluster * this) {
    377         verify( disable_preempt_count > 0 );
    378         lock( &this->lock DEBUG_CTX2 );
     343        lock( &this->lock );
    379344        thread_desc * head = pop_head( &this->ready_queue );
    380345        unlock( &this->lock );
    381         verify( disable_preempt_count > 0 );
    382346        return head;
    383347}
    384348
    385 void BlockInternal() {
    386         disable_interrupts();
    387         verify( disable_preempt_count > 0 );
     349void ScheduleInternal() {
    388350        suspend();
    389         verify( disable_preempt_count > 0 );
    390         enable_interrupts( DEBUG_CTX );
    391 }
    392 
    393 void BlockInternal( spinlock * lock ) {
    394         disable_interrupts();
     351}
     352
     353void ScheduleInternal( spinlock * lock ) {
    395354        this_processor->finish.action_code = Release;
    396355        this_processor->finish.lock = lock;
    397 
    398         verify( disable_preempt_count > 0 );
    399356        suspend();
    400         verify( disable_preempt_count > 0 );
    401 
    402         enable_interrupts( DEBUG_CTX );
    403 }
    404 
    405 void BlockInternal( thread_desc * thrd ) {
    406         disable_interrupts();
    407         assert( thrd->cor.state != Halted );
     357}
     358
     359void ScheduleInternal( thread_desc * thrd ) {
    408360        this_processor->finish.action_code = Schedule;
    409361        this_processor->finish.thrd = thrd;
    410 
    411         verify( disable_preempt_count > 0 );
    412362        suspend();
    413         verify( disable_preempt_count > 0 );
    414 
    415         enable_interrupts( DEBUG_CTX );
    416 }
    417 
    418 void BlockInternal( spinlock * lock, thread_desc * thrd ) {
    419         disable_interrupts();
     363}
     364
     365void ScheduleInternal( spinlock * lock, thread_desc * thrd ) {
    420366        this_processor->finish.action_code = Release_Schedule;
    421367        this_processor->finish.lock = lock;
    422368        this_processor->finish.thrd = thrd;
    423 
    424         verify( disable_preempt_count > 0 );
    425369        suspend();
    426         verify( disable_preempt_count > 0 );
    427 
    428         enable_interrupts( DEBUG_CTX );
    429 }
    430 
    431 void BlockInternal(spinlock ** locks, unsigned short count) {
    432         disable_interrupts();
     370}
     371
     372void ScheduleInternal(spinlock ** locks, unsigned short count) {
    433373        this_processor->finish.action_code = Release_Multi;
    434374        this_processor->finish.locks = locks;
    435375        this_processor->finish.lock_count = count;
    436 
    437         verify( disable_preempt_count > 0 );
    438376        suspend();
    439         verify( disable_preempt_count > 0 );
    440 
    441         enable_interrupts( DEBUG_CTX );
    442 }
    443 
    444 void BlockInternal(spinlock ** locks, unsigned short lock_count, thread_desc ** thrds, unsigned short thrd_count) {
    445         disable_interrupts();
     377}
     378
     379void ScheduleInternal(spinlock ** locks, unsigned short lock_count, thread_desc ** thrds, unsigned short thrd_count) {
    446380        this_processor->finish.action_code = Release_Multi_Schedule;
    447381        this_processor->finish.locks = locks;
     
    449383        this_processor->finish.thrds = thrds;
    450384        this_processor->finish.thrd_count = thrd_count;
    451 
    452         verify( disable_preempt_count > 0 );
    453385        suspend();
    454         verify( disable_preempt_count > 0 );
    455 
    456         enable_interrupts( DEBUG_CTX );
    457386}
    458387
     
    463392// Kernel boot procedures
    464393void kernel_startup(void) {
    465         LIB_DEBUG_PRINT_SAFE("Kernel : Starting\n");
     394        LIB_DEBUG_PRINT_SAFE("Kernel : Starting\n");   
    466395
    467396        // Start by initializing the main thread
    468         // SKULLDUGGERY: the mainThread steals the process main thread
     397        // SKULLDUGGERY: the mainThread steals the process main thread 
    469398        // which will then be scheduled by the systemProcessor normally
    470399        mainThread = (thread_desc *)&mainThread_storage;
     
    474403        LIB_DEBUG_PRINT_SAFE("Kernel : Main thread ready\n");
    475404
     405        // Enable preemption
     406        kernel_start_preemption();
     407
    476408        // Initialize the system cluster
    477409        systemCluster = (cluster *)&systemCluster_storage;
     
    485417        systemProcessor{ systemCluster, (processorCtx_t *)&systemProcessorCtx_storage };
    486418
    487         // Add the main thread to the ready queue
     419        // Add the main thread to the ready queue 
    488420        // once resume is called on systemProcessor->runner the mainThread needs to be scheduled like any normal thread
    489421        ScheduleThread(mainThread);
     
    491423        //initialize the global state variables
    492424        this_processor = &systemProcessor->proc;
    493         this_thread = mainThread;
    494         this_coroutine = &mainThread->cor;
    495         disable_preempt_count = 1;
    496 
    497         // Enable preemption
    498         kernel_start_preemption();
     425        this_processor->current_thread = mainThread;
     426        this_processor->current_coroutine = &mainThread->cor;
    499427
    500428        // SKULLDUGGERY: Force a context switch to the system processor to set the main thread's context to the current UNIX
    501429        // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that
    502         // mainThread is on the ready queue when this call is made.
     430        // mainThread is on the ready queue when this call is made. 
    503431        resume( systemProcessor->proc.runner );
    504432
     
    507435        // THE SYSTEM IS NOW COMPLETELY RUNNING
    508436        LIB_DEBUG_PRINT_SAFE("Kernel : Started\n--------------------------------------------------\n\n");
    509 
    510         enable_interrupts( DEBUG_CTX );
    511437}
    512438
    513439void kernel_shutdown(void) {
    514440        LIB_DEBUG_PRINT_SAFE("\n--------------------------------------------------\nKernel : Shutting down\n");
    515 
    516         disable_interrupts();
    517441
    518442        // SKULLDUGGERY: Notify the systemProcessor it needs to terminates.
     
    524448        // THE SYSTEM IS NOW COMPLETELY STOPPED
    525449
    526         // Disable preemption
    527         kernel_stop_preemption();
    528 
    529450        // Destroy the system processor and its context in reverse order of construction
    530451        // These were manually constructed so we need manually destroy them
     
    536457        ^(mainThread){};
    537458
    538         LIB_DEBUG_PRINT_SAFE("Kernel : Shutdown complete\n");
     459        LIB_DEBUG_PRINT_SAFE("Kernel : Shutdown complete\n");   
    539460}
    540461
     
    546467        // abort cannot be recursively entered by the same or different processors because all signal handlers return when
    547468        // the globalAbort flag is true.
    548         lock( &kernel_abort_lock DEBUG_CTX2 );
     469        lock( &kernel_abort_lock );
    549470
    550471        // first task to abort ?
     
    552473                kernel_abort_called = true;
    553474                unlock( &kernel_abort_lock );
    554         }
     475        } 
    555476        else {
    556477                unlock( &kernel_abort_lock );
    557 
     478               
    558479                sigset_t mask;
    559480                sigemptyset( &mask );
     
    561482                sigaddset( &mask, SIGUSR1 );                    // block SIGUSR1 signals
    562483                sigsuspend( &mask );                            // block the processor to prevent further damage during abort
    563                 _exit( EXIT_FAILURE );                          // if processor unblocks before it is killed, terminate it
    564         }
    565 
    566         return this_thread;
     484                _exit( EXIT_FAILURE );                          // if processor unblocks before it is killed, terminate it             
     485        }
     486
     487        return this_thread();
    567488}
    568489
     
    573494        __lib_debug_write( STDERR_FILENO, abort_text, len );
    574495
    575         if ( thrd != this_coroutine ) {
    576                 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() );
    577498                __lib_debug_write( STDERR_FILENO, abort_text, len );
    578         }
     499        } 
    579500        else {
    580501                __lib_debug_write( STDERR_FILENO, ".\n", 2 );
     
    584505extern "C" {
    585506        void __lib_debug_acquire() {
    586                 lock( &kernel_debug_lock DEBUG_CTX2 );
     507                lock(&kernel_debug_lock);
    587508        }
    588509
    589510        void __lib_debug_release() {
    590                 unlock( &kernel_debug_lock );
     511                unlock(&kernel_debug_lock);
    591512        }
    592513}
     
    604525}
    605526
    606 bool try_lock( spinlock * this DEBUG_CTX_PARAM2 ) {
     527bool try_lock( spinlock * this ) {
    607528        return this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0;
    608529}
    609530
    610 void lock( spinlock * this DEBUG_CTX_PARAM2 ) {
     531void lock( spinlock * this ) {
    611532        for ( unsigned int i = 1;; i += 1 ) {
    612                 if ( this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0 ) { break; }
    613         }
    614         LIB_DEBUG_DO(
    615                 this->prev_name = caller;
    616                 this->prev_thrd = this_thread;
    617         )
    618 }
    619 
    620 void lock_yield( spinlock * this DEBUG_CTX_PARAM2 ) {
    621         for ( unsigned int i = 1;; i += 1 ) {
    622                 if ( this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0 ) { break; }
    623                 yield();
    624         }
    625         LIB_DEBUG_DO(
    626                 this->prev_name = caller;
    627                 this->prev_thrd = this_thread;
    628         )
    629 }
    630 
     533                if ( this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0 ) break;
     534        }
     535}
    631536
    632537void unlock( spinlock * this ) {
     
    642547
    643548void wait( signal_once * this ) {
    644         lock( &this->lock DEBUG_CTX2 );
     549        lock( &this->lock );
    645550        if( !this->cond ) {
    646                 append( &this->blocked, (thread_desc*)this_thread );
    647                 BlockInternal( &this->lock );
    648         }
    649         else {
    650                 unlock( &this->lock );
    651         }
     551                append( &this->blocked, this_thread() );
     552                ScheduleInternal( &this->lock );
     553                lock( &this->lock );
     554        }
     555        unlock( &this->lock );
    652556}
    653557
    654558void signal( signal_once * this ) {
    655         lock( &this->lock DEBUG_CTX2 );
     559        lock( &this->lock );
    656560        {
    657561                this->cond = true;
    658562
    659                 disable_interrupts();
    660563                thread_desc * it;
    661564                while( it = pop_head( &this->blocked) ) {
    662565                        ScheduleThread( it );
    663566                }
    664                 enable_interrupts( DEBUG_CTX );
    665567        }
    666568        unlock( &this->lock );
     
    688590                }
    689591                head->next = NULL;
    690         }
     592        }       
    691593        return head;
    692594}
     
    707609                this->top = top->next;
    708610                top->next = NULL;
    709         }
     611        }       
    710612        return top;
    711613}
Note: See TracChangeset for help on using the changeset viewer.