Ignore:
Timestamp:
Jul 12, 2017, 9:50:58 PM (4 years ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, deferred_resn, demangler, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, resolv-new, with_gc
Children:
1a6e855
Parents:
8b47e50 (diff), acb89ed (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg2:software/cfa/cfa-cc

File:
1 edited

Legend:

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

    r8b47e50 ref6851a  
    1515//
    1616
    17 #include "startup.h"
    18 
    19 //Start and stop routine for the kernel, declared first to make sure they run first
    20 void kernel_startup(void)  __attribute__(( constructor( STARTUP_PRIORITY_KERNEL ) ));
    21 void kernel_shutdown(void) __attribute__(( destructor ( STARTUP_PRIORITY_KERNEL ) ));
    22 
    23 //Header
    24 #include "kernel_private.h"
     17#include "libhdr.h"
    2518
    2619//C Includes
     
    3528
    3629//CFA Includes
    37 #include "libhdr.h"
     30#include "kernel_private.h"
    3831#include "preemption.h"
     32#include "startup.h"
    3933
    4034//Private includes
     
    4236#include "invoke.h"
    4337
     38//Start and stop routine for the kernel, declared first to make sure they run first
     39void kernel_startup(void)  __attribute__(( constructor( STARTUP_PRIORITY_KERNEL ) ));
     40void kernel_shutdown(void) __attribute__(( destructor ( STARTUP_PRIORITY_KERNEL ) ));
     41
    4442//-----------------------------------------------------------------------------
    4543// Kernel storage
    46 #define KERNEL_STORAGE(T,X) static char X##_storage[sizeof(T)]
     44#define KERNEL_STORAGE(T,X) static char X##Storage[sizeof(T)]
    4745
    4846KERNEL_STORAGE(processorCtx_t, systemProcessorCtx);
     
    5048KERNEL_STORAGE(system_proc_t, systemProcessor);
    5149KERNEL_STORAGE(thread_desc, mainThread);
    52 KERNEL_STORAGE(machine_context_t, mainThread_context);
     50KERNEL_STORAGE(machine_context_t, mainThreadCtx);
    5351
    5452cluster * systemCluster;
     
    5957// Global state
    6058
    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 }
     59volatile thread_local processor * this_processor;
     60volatile thread_local coroutine_desc * this_coroutine;
     61volatile thread_local thread_desc * this_thread;
     62volatile thread_local unsigned short disable_preempt_count = 1;
    7063
    7164//-----------------------------------------------------------------------------
     
    9184
    9285        this->limit = (void *)(((intptr_t)this->base) - this->size);
    93         this->context = &mainThread_context_storage;
     86        this->context = &mainThreadCtxStorage;
    9487        this->top = this->base;
    9588}
     
    136129void ?{}(processor * this, cluster * cltr) {
    137130        this->cltr = cltr;
    138         this->current_coroutine = NULL;
    139         this->current_thread = NULL;
    140         (&this->terminated){};
     131        (&this->terminated){ 0 };
    141132        this->is_terminated = false;
    142133        this->preemption_alarm = NULL;
    143134        this->preemption = default_preemption();
    144         this->disable_preempt_count = 1;                //Start with interrupts disabled
    145135        this->pending_preemption = false;
    146136
     
    150140void ?{}(processor * this, cluster * cltr, processorCtx_t * runner) {
    151141        this->cltr = cltr;
    152         this->current_coroutine = NULL;
    153         this->current_thread = NULL;
    154         (&this->terminated){};
     142        (&this->terminated){ 0 };
    155143        this->is_terminated = false;
    156         this->disable_preempt_count = 0;
     144        this->preemption_alarm = NULL;
     145        this->preemption = default_preemption();
    157146        this->pending_preemption = false;
     147        this->kernel_thread = pthread_self();
    158148
    159149        this->runner = runner;
    160         LIB_DEBUG_PRINT_SAFE("Kernel : constructing processor context %p\n", runner);
     150        LIB_DEBUG_PRINT_SAFE("Kernel : constructing system processor context %p\n", runner);
    161151        runner{ this };
    162152}
     153
     154LIB_DEBUG_DO( bool validate( alarm_list_t * this ); )
    163155
    164156void ?{}(system_proc_t * this, cluster * cltr, processorCtx_t * runner) {
     
    168160
    169161        (&this->proc){ cltr, runner };
     162
     163        verify( validate( &this->alarms ) );
    170164}
    171165
     
    174168                LIB_DEBUG_PRINT_SAFE("Kernel : core %p signaling termination\n", this);
    175169                this->is_terminated = true;
    176                 wait( &this->terminated );
     170                P( &this->terminated );
     171                pthread_join( this->kernel_thread, NULL );
    177172        }
    178173}
     
    209204                        if(readyThread)
    210205                        {
     206                                verify( disable_preempt_count > 0 );
     207
    211208                                runThread(this, readyThread);
     209
     210                                verify( disable_preempt_count > 0 );
    212211
    213212                                //Some actions need to be taken from the kernel
     
    225224        }
    226225
    227         signal( &this->terminated );
     226        V( &this->terminated );
     227
    228228        LIB_DEBUG_PRINT_SAFE("Kernel : core %p terminated\n", this);
    229229}
     
    239239
    240240        //Update global state
    241         this->current_thread = dst;
     241        this_thread = dst;
    242242
    243243        // Context Switch to the thread
     
    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
     
    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
     
    331334// Scheduler routines
    332335void ScheduleThread( thread_desc * thrd ) {
    333         if( !thrd ) return;
     336        // if( !thrd ) return;
     337        assert( thrd );
     338        assert( thrd->cor.state != Halted );
     339
     340        verify( disable_preempt_count > 0 );
    334341
    335342        verifyf( thrd->next == NULL, "Expected null got %p", thrd->next );
    336343
    337         lock( &systemProcessor->proc.cltr->lock );
     344        lock( &systemProcessor->proc.cltr->lock DEBUG_CTX2 );
    338345        append( &systemProcessor->proc.cltr->ready_queue, thrd );
    339346        unlock( &systemProcessor->proc.cltr->lock );
     347
     348        verify( disable_preempt_count > 0 );
    340349}
    341350
    342351thread_desc * nextThread(cluster * this) {
    343         lock( &this->lock );
     352        verify( disable_preempt_count > 0 );
     353        lock( &this->lock DEBUG_CTX2 );
    344354        thread_desc * head = pop_head( &this->ready_queue );
    345355        unlock( &this->lock );
     356        verify( disable_preempt_count > 0 );
    346357        return head;
    347358}
    348359
    349 void ScheduleInternal() {
     360void BlockInternal() {
     361        disable_interrupts();
     362        verify( disable_preempt_count > 0 );
    350363        suspend();
    351 }
    352 
    353 void ScheduleInternal( spinlock * lock ) {
     364        verify( disable_preempt_count > 0 );
     365        enable_interrupts( DEBUG_CTX );
     366}
     367
     368void BlockInternal( spinlock * lock ) {
     369        disable_interrupts();
    354370        this_processor->finish.action_code = Release;
    355371        this_processor->finish.lock = lock;
     372
     373        verify( disable_preempt_count > 0 );
    356374        suspend();
    357 }
    358 
    359 void ScheduleInternal( thread_desc * thrd ) {
     375        verify( disable_preempt_count > 0 );
     376
     377        enable_interrupts( DEBUG_CTX );
     378}
     379
     380void BlockInternal( thread_desc * thrd ) {
     381        disable_interrupts();
     382        assert( thrd->cor.state != Halted );
    360383        this_processor->finish.action_code = Schedule;
    361384        this_processor->finish.thrd = thrd;
     385
     386        verify( disable_preempt_count > 0 );
    362387        suspend();
    363 }
    364 
    365 void ScheduleInternal( spinlock * lock, thread_desc * thrd ) {
     388        verify( disable_preempt_count > 0 );
     389
     390        enable_interrupts( DEBUG_CTX );
     391}
     392
     393void BlockInternal( spinlock * lock, thread_desc * thrd ) {
     394        disable_interrupts();
    366395        this_processor->finish.action_code = Release_Schedule;
    367396        this_processor->finish.lock = lock;
    368397        this_processor->finish.thrd = thrd;
     398
     399        verify( disable_preempt_count > 0 );
    369400        suspend();
    370 }
    371 
    372 void ScheduleInternal(spinlock ** locks, unsigned short count) {
     401        verify( disable_preempt_count > 0 );
     402
     403        enable_interrupts( DEBUG_CTX );
     404}
     405
     406void BlockInternal(spinlock ** locks, unsigned short count) {
     407        disable_interrupts();
    373408        this_processor->finish.action_code = Release_Multi;
    374409        this_processor->finish.locks = locks;
    375410        this_processor->finish.lock_count = count;
     411
     412        verify( disable_preempt_count > 0 );
    376413        suspend();
    377 }
    378 
    379 void ScheduleInternal(spinlock ** locks, unsigned short lock_count, thread_desc ** thrds, unsigned short thrd_count) {
     414        verify( disable_preempt_count > 0 );
     415
     416        enable_interrupts( DEBUG_CTX );
     417}
     418
     419void BlockInternal(spinlock ** locks, unsigned short lock_count, thread_desc ** thrds, unsigned short thrd_count) {
     420        disable_interrupts();
    380421        this_processor->finish.action_code = Release_Multi_Schedule;
    381422        this_processor->finish.locks = locks;
     
    383424        this_processor->finish.thrds = thrds;
    384425        this_processor->finish.thrd_count = thrd_count;
     426
     427        verify( disable_preempt_count > 0 );
     428        suspend();
     429        verify( disable_preempt_count > 0 );
     430
     431        enable_interrupts( DEBUG_CTX );
     432}
     433
     434void LeaveThread(spinlock * lock, thread_desc * thrd) {
     435        verify( disable_preempt_count > 0 );
     436        this_processor->finish.action_code = thrd ? Release_Schedule : Release;
     437        this_processor->finish.lock = lock;
     438        this_processor->finish.thrd = thrd;
     439
    385440        suspend();
    386441}
     
    397452        // SKULLDUGGERY: the mainThread steals the process main thread
    398453        // which will then be scheduled by the systemProcessor normally
    399         mainThread = (thread_desc *)&mainThread_storage;
     454        mainThread = (thread_desc *)&mainThreadStorage;
    400455        current_stack_info_t info;
    401456        mainThread{ &info };
     
    403458        LIB_DEBUG_PRINT_SAFE("Kernel : Main thread ready\n");
    404459
    405         // Enable preemption
    406         kernel_start_preemption();
    407 
    408460        // Initialize the system cluster
    409         systemCluster = (cluster *)&systemCluster_storage;
     461        systemCluster = (cluster *)&systemClusterStorage;
    410462        systemCluster{};
    411463
     
    414466        // Initialize the system processor and the system processor ctx
    415467        // (the coroutine that contains the processing control flow)
    416         systemProcessor = (system_proc_t *)&systemProcessor_storage;
    417         systemProcessor{ systemCluster, (processorCtx_t *)&systemProcessorCtx_storage };
     468        systemProcessor = (system_proc_t *)&systemProcessorStorage;
     469        systemProcessor{ systemCluster, (processorCtx_t *)&systemProcessorCtxStorage };
    418470
    419471        // Add the main thread to the ready queue
     
    423475        //initialize the global state variables
    424476        this_processor = &systemProcessor->proc;
    425         this_processor->current_thread = mainThread;
    426         this_processor->current_coroutine = &mainThread->cor;
     477        this_thread = mainThread;
     478        this_coroutine = &mainThread->cor;
     479        disable_preempt_count = 1;
     480
     481        // Enable preemption
     482        kernel_start_preemption();
    427483
    428484        // SKULLDUGGERY: Force a context switch to the system processor to set the main thread's context to the current UNIX
     
    435491        // THE SYSTEM IS NOW COMPLETELY RUNNING
    436492        LIB_DEBUG_PRINT_SAFE("Kernel : Started\n--------------------------------------------------\n\n");
     493
     494        enable_interrupts( DEBUG_CTX );
    437495}
    438496
    439497void kernel_shutdown(void) {
    440498        LIB_DEBUG_PRINT_SAFE("\n--------------------------------------------------\nKernel : Shutting down\n");
     499
     500        disable_interrupts();
    441501
    442502        // SKULLDUGGERY: Notify the systemProcessor it needs to terminates.
     
    448508        // THE SYSTEM IS NOW COMPLETELY STOPPED
    449509
     510        // Disable preemption
     511        kernel_stop_preemption();
     512
    450513        // Destroy the system processor and its context in reverse order of construction
    451514        // These were manually constructed so we need manually destroy them
     
    467530        // abort cannot be recursively entered by the same or different processors because all signal handlers return when
    468531        // the globalAbort flag is true.
    469         lock( &kernel_abort_lock );
     532        lock( &kernel_abort_lock DEBUG_CTX2 );
    470533
    471534        // first task to abort ?
     
    485548        }
    486549
    487         return this_thread();
     550        return this_thread;
    488551}
    489552
     
    494557        __lib_debug_write( STDERR_FILENO, abort_text, len );
    495558
    496         if ( thrd != this_coroutine() ) {
    497                 len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", this_coroutine()->name, this_coroutine() );
     559        if ( thrd != this_coroutine ) {
     560                len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", this_coroutine->name, this_coroutine );
    498561                __lib_debug_write( STDERR_FILENO, abort_text, len );
    499562        }
     
    505568extern "C" {
    506569        void __lib_debug_acquire() {
    507                 lock(&kernel_debug_lock);
     570                lock( &kernel_debug_lock DEBUG_CTX2 );
    508571        }
    509572
    510573        void __lib_debug_release() {
    511                 unlock(&kernel_debug_lock);
     574                unlock( &kernel_debug_lock );
    512575        }
    513576}
     
    525588}
    526589
    527 bool try_lock( spinlock * this ) {
     590bool try_lock( spinlock * this DEBUG_CTX_PARAM2 ) {
    528591        return this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0;
    529592}
    530593
    531 void lock( spinlock * this ) {
     594void lock( spinlock * this DEBUG_CTX_PARAM2 ) {
    532595        for ( unsigned int i = 1;; i += 1 ) {
    533                 if ( this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0 ) break;
    534         }
    535 }
     596                if ( this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0 ) { break; }
     597        }
     598        LIB_DEBUG_DO(
     599                this->prev_name = caller;
     600                this->prev_thrd = this_thread;
     601        )
     602}
     603
     604void lock_yield( spinlock * this DEBUG_CTX_PARAM2 ) {
     605        for ( unsigned int i = 1;; i += 1 ) {
     606                if ( this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0 ) { break; }
     607                yield();
     608        }
     609        LIB_DEBUG_DO(
     610                this->prev_name = caller;
     611                this->prev_thrd = this_thread;
     612        )
     613}
     614
    536615
    537616void unlock( spinlock * this ) {
     
    539618}
    540619
    541 void ?{}( signal_once * this ) {
    542         this->cond = false;
    543 }
    544 void ^?{}( signal_once * this ) {
    545 
    546 }
    547 
    548 void wait( signal_once * this ) {
    549         lock( &this->lock );
    550         if( !this->cond ) {
    551                 append( &this->blocked, this_thread() );
    552                 ScheduleInternal( &this->lock );
    553                 lock( &this->lock );
    554         }
     620void  ?{}( semaphore * this, int count = 1 ) {
     621        (&this->lock){};
     622        this->count = count;
     623        (&this->waiting){};
     624}
     625void ^?{}(semaphore * this) {}
     626
     627void P(semaphore * this) {
     628        lock( &this->lock DEBUG_CTX2 );
     629        this->count -= 1;
     630        if ( this->count < 0 ) {
     631                // queue current task
     632                append( &this->waiting, (thread_desc *)this_thread );
     633
     634                // atomically release spin lock and block
     635                BlockInternal( &this->lock );
     636        }
     637        else {
     638            unlock( &this->lock );
     639        }
     640}
     641
     642void V(semaphore * this) {
     643        thread_desc * thrd = NULL;
     644        lock( &this->lock DEBUG_CTX2 );
     645        this->count += 1;
     646        if ( this->count <= 0 ) {
     647                // remove task at head of waiting list
     648                thrd = pop_head( &this->waiting );
     649        }
     650
    555651        unlock( &this->lock );
    556 }
    557 
    558 void signal( signal_once * this ) {
    559         lock( &this->lock );
    560         {
    561                 this->cond = true;
    562 
    563                 thread_desc * it;
    564                 while( it = pop_head( &this->blocked) ) {
    565                         ScheduleThread( it );
    566                 }
    567         }
    568         unlock( &this->lock );
     652
     653        // make new owner
     654        WakeThread( thrd );
    569655}
    570656
Note: See TracChangeset for help on using the changeset viewer.