Ignore:
File:
1 edited

Legend:

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

    rcd17862 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 
     324       
    326325        pthread_create( &this->kernel_thread, NULL, CtxInvokeProcessor, (void*)this );
    327326
    328         LIB_DEBUG_PRINT_SAFE("Kernel : core %p started\n", this);
     327        LIB_DEBUG_PRINT_SAFE("Kernel : core %p started\n", this);       
    329328}
    330329
     
    332331// Scheduler routines
    333332void ScheduleThread( thread_desc * thrd ) {
    334         // if( !thrd ) return;
    335         assert( thrd );
    336         assert( thrd->cor.state != Halted );
    337 
    338         verify( disable_preempt_count > 0 );
     333        if( !thrd ) return;
    339334
    340335        verifyf( thrd->next == NULL, "Expected null got %p", thrd->next );
    341 
    342         lock( &systemProcessor->proc.cltr->lock DEBUG_CTX2 );
     336       
     337        lock( &systemProcessor->proc.cltr->lock );
    343338        append( &systemProcessor->proc.cltr->ready_queue, thrd );
    344339        unlock( &systemProcessor->proc.cltr->lock );
    345 
    346         verify( disable_preempt_count > 0 );
    347340}
    348341
    349342thread_desc * nextThread(cluster * this) {
    350         verify( disable_preempt_count > 0 );
    351         lock( &this->lock DEBUG_CTX2 );
     343        lock( &this->lock );
    352344        thread_desc * head = pop_head( &this->ready_queue );
    353345        unlock( &this->lock );
    354         verify( disable_preempt_count > 0 );
    355346        return head;
    356347}
    357348
    358 void BlockInternal() {
    359         disable_interrupts();
    360         verify( disable_preempt_count > 0 );
     349void ScheduleInternal() {
    361350        suspend();
    362         verify( disable_preempt_count > 0 );
    363         enable_interrupts( DEBUG_CTX );
    364 }
    365 
    366 void BlockInternal( spinlock * lock ) {
    367         disable_interrupts();
     351}
     352
     353void ScheduleInternal( spinlock * lock ) {
    368354        this_processor->finish.action_code = Release;
    369355        this_processor->finish.lock = lock;
    370 
    371         verify( disable_preempt_count > 0 );
    372356        suspend();
    373         verify( disable_preempt_count > 0 );
    374 
    375         enable_interrupts( DEBUG_CTX );
    376 }
    377 
    378 void BlockInternal( thread_desc * thrd ) {
    379         disable_interrupts();
    380         assert( thrd->cor.state != Halted );
     357}
     358
     359void ScheduleInternal( thread_desc * thrd ) {
    381360        this_processor->finish.action_code = Schedule;
    382361        this_processor->finish.thrd = thrd;
    383 
    384         verify( disable_preempt_count > 0 );
    385362        suspend();
    386         verify( disable_preempt_count > 0 );
    387 
    388         enable_interrupts( DEBUG_CTX );
    389 }
    390 
    391 void BlockInternal( spinlock * lock, thread_desc * thrd ) {
    392         disable_interrupts();
     363}
     364
     365void ScheduleInternal( spinlock * lock, thread_desc * thrd ) {
    393366        this_processor->finish.action_code = Release_Schedule;
    394367        this_processor->finish.lock = lock;
    395368        this_processor->finish.thrd = thrd;
    396 
    397         verify( disable_preempt_count > 0 );
    398369        suspend();
    399         verify( disable_preempt_count > 0 );
    400 
    401         enable_interrupts( DEBUG_CTX );
    402 }
    403 
    404 void BlockInternal(spinlock ** locks, unsigned short count) {
    405         disable_interrupts();
     370}
     371
     372void ScheduleInternal(spinlock ** locks, unsigned short count) {
    406373        this_processor->finish.action_code = Release_Multi;
    407374        this_processor->finish.locks = locks;
    408375        this_processor->finish.lock_count = count;
    409 
    410         verify( disable_preempt_count > 0 );
    411376        suspend();
    412         verify( disable_preempt_count > 0 );
    413 
    414         enable_interrupts( DEBUG_CTX );
    415 }
    416 
    417 void BlockInternal(spinlock ** locks, unsigned short lock_count, thread_desc ** thrds, unsigned short thrd_count) {
    418         disable_interrupts();
     377}
     378
     379void ScheduleInternal(spinlock ** locks, unsigned short lock_count, thread_desc ** thrds, unsigned short thrd_count) {
    419380        this_processor->finish.action_code = Release_Multi_Schedule;
    420381        this_processor->finish.locks = locks;
     
    422383        this_processor->finish.thrds = thrds;
    423384        this_processor->finish.thrd_count = thrd_count;
    424 
    425         verify( disable_preempt_count > 0 );
    426385        suspend();
    427         verify( disable_preempt_count > 0 );
    428 
    429         enable_interrupts( DEBUG_CTX );
    430386}
    431387
     
    436392// Kernel boot procedures
    437393void kernel_startup(void) {
    438         LIB_DEBUG_PRINT_SAFE("Kernel : Starting\n");
     394        LIB_DEBUG_PRINT_SAFE("Kernel : Starting\n");   
    439395
    440396        // Start by initializing the main thread
    441         // SKULLDUGGERY: the mainThread steals the process main thread
     397        // SKULLDUGGERY: the mainThread steals the process main thread 
    442398        // which will then be scheduled by the systemProcessor normally
    443399        mainThread = (thread_desc *)&mainThread_storage;
     
    447403        LIB_DEBUG_PRINT_SAFE("Kernel : Main thread ready\n");
    448404
     405        // Enable preemption
     406        kernel_start_preemption();
     407
    449408        // Initialize the system cluster
    450409        systemCluster = (cluster *)&systemCluster_storage;
     
    458417        systemProcessor{ systemCluster, (processorCtx_t *)&systemProcessorCtx_storage };
    459418
    460         // Add the main thread to the ready queue
     419        // Add the main thread to the ready queue 
    461420        // once resume is called on systemProcessor->runner the mainThread needs to be scheduled like any normal thread
    462421        ScheduleThread(mainThread);
     
    464423        //initialize the global state variables
    465424        this_processor = &systemProcessor->proc;
    466         this_thread = mainThread;
    467         this_coroutine = &mainThread->cor;
    468         disable_preempt_count = 1;
    469 
    470         // Enable preemption
    471         kernel_start_preemption();
     425        this_processor->current_thread = mainThread;
     426        this_processor->current_coroutine = &mainThread->cor;
    472427
    473428        // SKULLDUGGERY: Force a context switch to the system processor to set the main thread's context to the current UNIX
    474429        // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that
    475         // mainThread is on the ready queue when this call is made.
     430        // mainThread is on the ready queue when this call is made. 
    476431        resume( systemProcessor->proc.runner );
    477432
     
    480435        // THE SYSTEM IS NOW COMPLETELY RUNNING
    481436        LIB_DEBUG_PRINT_SAFE("Kernel : Started\n--------------------------------------------------\n\n");
    482 
    483         enable_interrupts( DEBUG_CTX );
    484437}
    485438
    486439void kernel_shutdown(void) {
    487440        LIB_DEBUG_PRINT_SAFE("\n--------------------------------------------------\nKernel : Shutting down\n");
    488 
    489         disable_interrupts();
    490441
    491442        // SKULLDUGGERY: Notify the systemProcessor it needs to terminates.
     
    497448        // THE SYSTEM IS NOW COMPLETELY STOPPED
    498449
    499         // Disable preemption
    500         kernel_stop_preemption();
    501 
    502450        // Destroy the system processor and its context in reverse order of construction
    503451        // These were manually constructed so we need manually destroy them
     
    509457        ^(mainThread){};
    510458
    511         LIB_DEBUG_PRINT_SAFE("Kernel : Shutdown complete\n");
     459        LIB_DEBUG_PRINT_SAFE("Kernel : Shutdown complete\n");   
    512460}
    513461
     
    519467        // abort cannot be recursively entered by the same or different processors because all signal handlers return when
    520468        // the globalAbort flag is true.
    521         lock( &kernel_abort_lock DEBUG_CTX2 );
     469        lock( &kernel_abort_lock );
    522470
    523471        // first task to abort ?
     
    525473                kernel_abort_called = true;
    526474                unlock( &kernel_abort_lock );
    527         }
     475        } 
    528476        else {
    529477                unlock( &kernel_abort_lock );
    530 
     478               
    531479                sigset_t mask;
    532480                sigemptyset( &mask );
     
    534482                sigaddset( &mask, SIGUSR1 );                    // block SIGUSR1 signals
    535483                sigsuspend( &mask );                            // block the processor to prevent further damage during abort
    536                 _exit( EXIT_FAILURE );                          // if processor unblocks before it is killed, terminate it
    537         }
    538 
    539         return this_thread;
     484                _exit( EXIT_FAILURE );                          // if processor unblocks before it is killed, terminate it             
     485        }
     486
     487        return this_thread();
    540488}
    541489
     
    546494        __lib_debug_write( STDERR_FILENO, abort_text, len );
    547495
    548         if ( thrd != this_coroutine ) {
    549                 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() );
    550498                __lib_debug_write( STDERR_FILENO, abort_text, len );
    551         }
     499        } 
    552500        else {
    553501                __lib_debug_write( STDERR_FILENO, ".\n", 2 );
     
    557505extern "C" {
    558506        void __lib_debug_acquire() {
    559                 lock( &kernel_debug_lock DEBUG_CTX2 );
     507                lock(&kernel_debug_lock);
    560508        }
    561509
    562510        void __lib_debug_release() {
    563                 unlock( &kernel_debug_lock );
     511                unlock(&kernel_debug_lock);
    564512        }
    565513}
     
    577525}
    578526
    579 bool try_lock( spinlock * this DEBUG_CTX_PARAM2 ) {
     527bool try_lock( spinlock * this ) {
    580528        return this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0;
    581529}
    582530
    583 void lock( spinlock * this DEBUG_CTX_PARAM2 ) {
     531void lock( spinlock * this ) {
    584532        for ( unsigned int i = 1;; i += 1 ) {
    585                 if ( this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0 ) { break; }
    586         }
    587         LIB_DEBUG_DO(
    588                 this->prev_name = caller;
    589                 this->prev_thrd = this_thread;
    590         )
    591 }
    592 
    593 void lock_yield( spinlock * this DEBUG_CTX_PARAM2 ) {
    594         for ( unsigned int i = 1;; i += 1 ) {
    595                 if ( this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0 ) { break; }
    596                 yield();
    597         }
    598         LIB_DEBUG_DO(
    599                 this->prev_name = caller;
    600                 this->prev_thrd = this_thread;
    601         )
    602 }
    603 
     533                if ( this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0 ) break;
     534        }
     535}
    604536
    605537void unlock( spinlock * this ) {
     
    615547
    616548void wait( signal_once * this ) {
    617         lock( &this->lock DEBUG_CTX2 );
     549        lock( &this->lock );
    618550        if( !this->cond ) {
    619                 append( &this->blocked, (thread_desc*)this_thread );
    620                 BlockInternal( &this->lock );
    621         }
    622         else {
    623                 unlock( &this->lock );
    624         }
     551                append( &this->blocked, this_thread() );
     552                ScheduleInternal( &this->lock );
     553                lock( &this->lock );
     554        }
     555        unlock( &this->lock );
    625556}
    626557
    627558void signal( signal_once * this ) {
    628         lock( &this->lock DEBUG_CTX2 );
     559        lock( &this->lock );
    629560        {
    630561                this->cond = true;
    631562
    632                 disable_interrupts();
    633563                thread_desc * it;
    634564                while( it = pop_head( &this->blocked) ) {
    635565                        ScheduleThread( it );
    636566                }
    637                 enable_interrupts( DEBUG_CTX );
    638567        }
    639568        unlock( &this->lock );
     
    661590                }
    662591                head->next = NULL;
    663         }
     592        }       
    664593        return head;
    665594}
     
    680609                this->top = top->next;
    681610                top->next = NULL;
    682         }
     611        }       
    683612        return top;
    684613}
Note: See TracChangeset for help on using the changeset viewer.