Ignore:
File:
1 edited

Legend:

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

    rde94a60 rde6319f  
    4949thread_desc * mainThread;
    5050
    51 struct { __dllist_t(thread_desc) list; __spinlock_t lock; } global_threads ;
    52 struct { __dllist_t(cluster    ) list; __spinlock_t lock; } global_clusters;
    53 
    5451//-----------------------------------------------------------------------------
    5552// Global state
     
    5956// volatile thread_local unsigned short disable_preempt_count = 1;
    6057
    61 thread_local struct KernelThreadData kernelTLS = {
     58thread_local struct KernelThreadData kernelThreadData = {
    6259        NULL,
    6360        NULL,
     
    120117        self_mon_p = &self_mon;
    121118        next = NULL;
    122 
    123         node.next = NULL;
    124         node.prev = NULL;
    125         doregister(this);
     119        __cfaabi_dbg_debug_do(
     120                dbg_next = NULL;
     121                dbg_prev = NULL;
     122                __cfaabi_dbg_thread_register(&this);
     123        )
    126124
    127125        monitors{ &self_mon_p, 1, (fptr_t)0 };
     
    157155                terminate(&this);
    158156                verify(this.do_terminate);
    159                 verify( kernelTLS.this_processor != &this);
     157                verify(TL_GET( this_processor ) != &this);
    160158                P( terminated );
    161                 verify( kernelTLS.this_processor != &this);
     159                verify(TL_GET( this_processor ) != &this);
    162160                pthread_join( kernel_thread, NULL );
    163161        }
     
    169167        ready_queue{};
    170168        ready_queue_lock{};
    171 
    172         procs{ __get };
    173         idles{ __get };
    174 
    175         doregister(this);
    176169}
    177170
    178171void ^?{}(cluster & this) {
    179         unregister(this);
     172
    180173}
    181174
     
    190183        __cfaabi_dbg_print_safe("Kernel : core %p starting\n", this);
    191184
    192         doregister(this->cltr, this);
    193 
    194185        {
    195186                // Setup preemption data
     
    205196                        if(readyThread)
    206197                        {
    207                                 verify( ! kernelTLS.preemption_state.enabled );
     198                                verify( ! TL_GET( preemption_state ).enabled );
    208199
    209200                                runThread(this, readyThread);
    210201
    211                                 verify( ! kernelTLS.preemption_state.enabled );
     202                                verify( ! TL_GET( preemption_state ).enabled );
    212203
    213204                                //Some actions need to be taken from the kernel
     
    225216        }
    226217
    227         unregister(this->cltr, this);
    228 
    229218        V( this->terminated );
    230219
     
    232221}
    233222
    234 // KERNEL ONLY
    235223// runThread runs a thread by context switching
    236224// from the processor coroutine to the target thread
     
    240228        coroutine_desc * thrd_cor = dst->curr_cor;
    241229
    242         // Reset the terminating actions here
     230        //Reset the terminating actions here
    243231        this->finish.action_code = No_Action;
    244232
    245         // Update global state
    246         kernelTLS.this_thread = dst;
     233        //Update global state
     234        TL_SET( this_thread, dst );
    247235
    248236        // Context Switch to the thread
     
    251239}
    252240
    253 // KERNEL_ONLY
    254241void returnToKernel() {
    255         coroutine_desc * proc_cor = get_coroutine(kernelTLS.this_processor->runner);
    256         coroutine_desc * thrd_cor = kernelTLS.this_thread->curr_cor = kernelTLS.this_coroutine;
     242        coroutine_desc * proc_cor = get_coroutine(TL_GET( this_processor )->runner);
     243        coroutine_desc * thrd_cor = TL_GET( this_thread )->curr_cor = TL_GET( this_coroutine );
    257244        ThreadCtxSwitch(thrd_cor, proc_cor);
    258245}
    259246
    260 // KERNEL_ONLY
    261247// Once a thread has finished running, some of
    262248// its final actions must be executed from the kernel
    263249void finishRunning(processor * this) with( this->finish ) {
    264250        if( action_code == Release ) {
    265                 verify( ! kernelTLS.preemption_state.enabled );
     251                verify( ! TL_GET( preemption_state ).enabled );
    266252                unlock( *lock );
    267253        }
     
    270256        }
    271257        else if( action_code == Release_Schedule ) {
    272                 verify( ! kernelTLS.preemption_state.enabled );
     258                verify( ! TL_GET( preemption_state ).enabled );
    273259                unlock( *lock );
    274260                ScheduleThread( thrd );
    275261        }
    276262        else if( action_code == Release_Multi ) {
    277                 verify( ! kernelTLS.preemption_state.enabled );
     263                verify( ! TL_GET( preemption_state ).enabled );
    278264                for(int i = 0; i < lock_count; i++) {
    279265                        unlock( *locks[i] );
     
    299285}
    300286
    301 // KERNEL_ONLY
    302287// Context invoker for processors
    303288// This is the entry point for processors (kernel threads)
     
    305290void * CtxInvokeProcessor(void * arg) {
    306291        processor * proc = (processor *) arg;
    307         kernelTLS.this_processor = proc;
    308         kernelTLS.this_coroutine = NULL;
    309         kernelTLS.this_thread    = NULL;
    310         kernelTLS.preemption_state.[enabled, disable_count] = [false, 1];
     292        TL_SET( this_processor, proc );
     293        TL_SET( this_coroutine, NULL );
     294        TL_SET( this_thread, NULL );
     295        TL_GET( preemption_state ).[enabled, disable_count] = [false, 1];
    311296        // SKULLDUGGERY: We want to create a context for the processor coroutine
    312297        // which is needed for the 2-step context switch. However, there is no reason
     
    320305
    321306        //Set global state
    322         kernelTLS.this_coroutine = get_coroutine(proc->runner);
    323         kernelTLS.this_thread    = NULL;
     307        TL_SET( this_coroutine, get_coroutine(proc->runner) );
     308        TL_SET( this_thread, NULL );
    324309
    325310        //We now have a proper context from which to schedule threads
     
    348333}
    349334
    350 // KERNEL_ONLY
    351335void kernel_first_resume(processor * this) {
    352         coroutine_desc * src = kernelTLS.this_coroutine;
     336        coroutine_desc * src = TL_GET( this_coroutine );
    353337        coroutine_desc * dst = get_coroutine(this->runner);
    354338
    355         verify( ! kernelTLS.preemption_state.enabled );
     339        verify( ! TL_GET( preemption_state ).enabled );
    356340
    357341        create_stack(&dst->stack, dst->stack.size);
    358342        CtxStart(&this->runner, CtxInvokeCoroutine);
    359343
    360         verify( ! kernelTLS.preemption_state.enabled );
     344        verify( ! TL_GET( preemption_state ).enabled );
    361345
    362346        dst->last = src;
     
    367351
    368352        // set new coroutine that task is executing
    369         kernelTLS.this_coroutine = dst;
     353        TL_SET( this_coroutine, dst );
    370354
    371355        // SKULLDUGGERY normally interrupts are enable before leaving a coroutine ctxswitch.
     
    384368        src->state = Active;
    385369
    386         verify( ! kernelTLS.preemption_state.enabled );
     370        verify( ! TL_GET( preemption_state ).enabled );
    387371}
    388372
    389373//-----------------------------------------------------------------------------
    390374// Scheduler routines
    391 
    392 // KERNEL ONLY
    393375void ScheduleThread( thread_desc * thrd ) {
     376        // if( ! thrd ) return;
    394377        verify( thrd );
    395378        verify( thrd->self_cor.state != Halted );
    396379
    397         verify( ! kernelTLS.preemption_state.enabled );
     380        verify( ! TL_GET( preemption_state ).enabled );
    398381
    399382        verifyf( thrd->next == NULL, "Expected null got %p", thrd->next );
     
    405388        }
    406389
    407         verify( ! kernelTLS.preemption_state.enabled );
    408 }
    409 
    410 // KERNEL ONLY
     390        verify( ! TL_GET( preemption_state ).enabled );
     391}
     392
    411393thread_desc * nextThread(cluster * this) with( *this ) {
    412         verify( ! kernelTLS.preemption_state.enabled );
     394        verify( ! TL_GET( preemption_state ).enabled );
    413395        lock( ready_queue_lock __cfaabi_dbg_ctx2 );
    414396        thread_desc * head = pop_head( ready_queue );
    415397        unlock( ready_queue_lock );
    416         verify( ! kernelTLS.preemption_state.enabled );
     398        verify( ! TL_GET( preemption_state ).enabled );
    417399        return head;
    418400}
     
    420402void BlockInternal() {
    421403        disable_interrupts();
    422         verify( ! kernelTLS.preemption_state.enabled );
     404        verify( ! TL_GET( preemption_state ).enabled );
    423405        returnToKernel();
    424         verify( ! kernelTLS.preemption_state.enabled );
     406        verify( ! TL_GET( preemption_state ).enabled );
    425407        enable_interrupts( __cfaabi_dbg_ctx );
    426408}
     
    428410void BlockInternal( __spinlock_t * lock ) {
    429411        disable_interrupts();
    430         with( *kernelTLS.this_processor ) {
     412        with( *TL_GET( this_processor ) ) {
    431413                finish.action_code = Release;
    432414                finish.lock        = lock;
    433415        }
    434416
    435         verify( ! kernelTLS.preemption_state.enabled );
     417        verify( ! TL_GET( preemption_state ).enabled );
    436418        returnToKernel();
    437         verify( ! kernelTLS.preemption_state.enabled );
     419        verify( ! TL_GET( preemption_state ).enabled );
    438420
    439421        enable_interrupts( __cfaabi_dbg_ctx );
     
    442424void BlockInternal( thread_desc * thrd ) {
    443425        disable_interrupts();
    444         with( * kernelTLS.this_processor ) {
     426        with( *TL_GET( this_processor ) ) {
    445427                finish.action_code = Schedule;
    446428                finish.thrd        = thrd;
    447429        }
    448430
    449         verify( ! kernelTLS.preemption_state.enabled );
     431        verify( ! TL_GET( preemption_state ).enabled );
    450432        returnToKernel();
    451         verify( ! kernelTLS.preemption_state.enabled );
     433        verify( ! TL_GET( preemption_state ).enabled );
    452434
    453435        enable_interrupts( __cfaabi_dbg_ctx );
     
    457439        assert(thrd);
    458440        disable_interrupts();
    459         with( * kernelTLS.this_processor ) {
     441        with( *TL_GET( this_processor ) ) {
    460442                finish.action_code = Release_Schedule;
    461443                finish.lock        = lock;
     
    463445        }
    464446
    465         verify( ! kernelTLS.preemption_state.enabled );
     447        verify( ! TL_GET( preemption_state ).enabled );
    466448        returnToKernel();
    467         verify( ! kernelTLS.preemption_state.enabled );
     449        verify( ! TL_GET( preemption_state ).enabled );
    468450
    469451        enable_interrupts( __cfaabi_dbg_ctx );
     
    472454void BlockInternal(__spinlock_t * locks [], unsigned short count) {
    473455        disable_interrupts();
    474         with( * kernelTLS.this_processor ) {
     456        with( *TL_GET( this_processor ) ) {
    475457                finish.action_code = Release_Multi;
    476458                finish.locks       = locks;
     
    478460        }
    479461
    480         verify( ! kernelTLS.preemption_state.enabled );
     462        verify( ! TL_GET( preemption_state ).enabled );
    481463        returnToKernel();
    482         verify( ! kernelTLS.preemption_state.enabled );
     464        verify( ! TL_GET( preemption_state ).enabled );
    483465
    484466        enable_interrupts( __cfaabi_dbg_ctx );
     
    487469void BlockInternal(__spinlock_t * locks [], unsigned short lock_count, thread_desc * thrds [], unsigned short thrd_count) {
    488470        disable_interrupts();
    489         with( *kernelTLS.this_processor ) {
     471        with( *TL_GET( this_processor ) ) {
    490472                finish.action_code = Release_Multi_Schedule;
    491473                finish.locks       = locks;
     
    495477        }
    496478
    497         verify( ! kernelTLS.preemption_state.enabled );
     479        verify( ! TL_GET( preemption_state ).enabled );
    498480        returnToKernel();
    499         verify( ! kernelTLS.preemption_state.enabled );
     481        verify( ! TL_GET( preemption_state ).enabled );
    500482
    501483        enable_interrupts( __cfaabi_dbg_ctx );
    502484}
    503485
    504 // KERNEL ONLY
    505486void LeaveThread(__spinlock_t * lock, thread_desc * thrd) {
    506         verify( ! kernelTLS.preemption_state.enabled );
    507         with( * kernelTLS.this_processor ) {
     487        verify( ! TL_GET( preemption_state ).enabled );
     488        with( *TL_GET( this_processor ) ) {
    508489                finish.action_code = thrd ? Release_Schedule : Release;
    509490                finish.lock        = lock;
     
    520501// Kernel boot procedures
    521502void kernel_startup(void) {
    522         verify( ! kernelTLS.preemption_state.enabled );
     503        verify( ! TL_GET( preemption_state ).enabled );
    523504        __cfaabi_dbg_print_safe("Kernel : Starting\n");
    524 
    525         global_threads. list{ __get };
    526         global_threads. lock{};
    527         global_clusters.list{ __get };
    528         global_clusters.lock{};
    529505
    530506        // Initialize the main cluster
     
    571547
    572548        //initialize the global state variables
    573         kernelTLS.this_processor = mainProcessor;
    574         kernelTLS.this_thread    = mainThread;
    575         kernelTLS.this_coroutine = &mainThread->self_cor;
     549        TL_SET( this_processor, mainProcessor );
     550        TL_SET( this_thread, mainThread );
     551        TL_SET( this_coroutine, &mainThread->self_cor );
    576552
    577553        // Enable preemption
     
    585561        // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that
    586562        // mainThread is on the ready queue when this call is made.
    587         kernel_first_resume( kernelTLS.this_processor );
     563        kernel_first_resume( TL_GET( this_processor ) );
    588564
    589565
     
    592568        __cfaabi_dbg_print_safe("Kernel : Started\n--------------------------------------------------\n\n");
    593569
    594         verify( ! kernelTLS.preemption_state.enabled );
     570        verify( ! TL_GET( preemption_state ).enabled );
    595571        enable_interrupts( __cfaabi_dbg_ctx );
    596         verify( TL_GET( preemption_state.enabled ) );
     572        verify( TL_GET( preemption_state ).enabled );
    597573}
    598574
     
    600576        __cfaabi_dbg_print_safe("\n--------------------------------------------------\nKernel : Shutting down\n");
    601577
    602         verify( TL_GET( preemption_state.enabled ) );
     578        verify( TL_GET( preemption_state ).enabled );
    603579        disable_interrupts();
    604         verify( ! kernelTLS.preemption_state.enabled );
     580        verify( ! TL_GET( preemption_state ).enabled );
    605581
    606582        // SKULLDUGGERY: Notify the mainProcessor it needs to terminates.
     
    628604
    629605//=============================================================================================
    630 // Kernel Quiescing
    631 //=============================================================================================
    632 
    633 // void halt(processor * this) with( this ) {
    634 //      pthread_mutex_lock( &idle.lock );
    635 
    636 
    637 
    638 //      // SKULLDUGGERY: Even if spurious wake-up is a thing
    639 //      // spuriously waking up a kernel thread is not a big deal
    640 //      // if it is very rare.
    641 //      pthread_cond_wait( &idle.cond, &idle.lock);
    642 //      pthread_mutex_unlock( &idle.lock );
    643 // }
    644 
    645 // void wake(processor * this) with( this ) {
    646 //      pthread_mutex_lock  (&idle.lock);
    647 //      pthread_cond_signal (&idle.cond);
    648 //      pthread_mutex_unlock(&idle.lock);
    649 // }
    650 
    651 //=============================================================================================
    652606// Unexpected Terminating logic
    653607//=============================================================================================
     
    655609
    656610static __spinlock_t kernel_abort_lock;
     611static __spinlock_t kernel_debug_lock;
    657612static bool kernel_abort_called = false;
    658613
    659 void * kernel_abort(void) __attribute__ ((__nothrow__)) {
     614void * kernel_abort    (void) __attribute__ ((__nothrow__)) {
    660615        // abort cannot be recursively entered by the same or different processors because all signal handlers return when
    661616        // the globalAbort flag is true.
     
    663618
    664619        // first task to abort ?
    665         if ( kernel_abort_called ) {                    // not first task to abort ?
     620        if ( ! kernel_abort_called ) {                  // not first task to abort ?
     621                kernel_abort_called = true;
     622                unlock( kernel_abort_lock );
     623        }
     624        else {
    666625                unlock( kernel_abort_lock );
    667626
    668627                sigset_t mask;
    669628                sigemptyset( &mask );
    670                 sigaddset( &mask, SIGALRM );            // block SIGALRM signals
    671                 sigsuspend( &mask );                    // block the processor to prevent further damage during abort
    672                 _exit( EXIT_FAILURE );                  // if processor unblocks before it is killed, terminate it
    673         }
    674         else {
    675                 kernel_abort_called = true;
    676                 unlock( kernel_abort_lock );
    677         }
    678 
    679         return kernelTLS.this_thread;
     629                sigaddset( &mask, SIGALRM );                    // block SIGALRM signals
     630                sigaddset( &mask, SIGUSR1 );                    // block SIGUSR1 signals
     631                sigsuspend( &mask );                            // block the processor to prevent further damage during abort
     632                _exit( EXIT_FAILURE );                          // if processor unblocks before it is killed, terminate it
     633        }
     634
     635        return TL_GET( this_thread );
    680636}
    681637
     
    683639        thread_desc * thrd = kernel_data;
    684640
    685         if(thrd) {
    686                 int len = snprintf( abort_text, abort_text_size, "Error occurred while executing thread %.256s (%p)", thrd->self_cor.name, thrd );
     641        int len = snprintf( abort_text, abort_text_size, "Error occurred while executing task %.256s (%p)", thrd->self_cor.name, thrd );
     642        __cfaabi_dbg_bits_write( abort_text, len );
     643
     644        if ( get_coroutine(thrd) != TL_GET( this_coroutine ) ) {
     645                len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", TL_GET( this_coroutine )->name, TL_GET( this_coroutine ) );
    687646                __cfaabi_dbg_bits_write( abort_text, len );
    688 
    689                 if ( get_coroutine(thrd) != kernelTLS.this_coroutine ) {
    690                         len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", kernelTLS.this_coroutine->name, kernelTLS.this_coroutine );
    691                         __cfaabi_dbg_bits_write( abort_text, len );
    692                 }
    693                 else {
    694                         __cfaabi_dbg_bits_write( ".\n", 2 );
    695                 }
    696647        }
    697648        else {
    698                 int len = snprintf( abort_text, abort_text_size, "Error occurred outside of any thread.\n" );
     649                __cfaabi_dbg_bits_write( ".\n", 2 );
    699650        }
    700651}
    701652
    702653int kernel_abort_lastframe( void ) __attribute__ ((__nothrow__)) {
    703         return get_coroutine(kernelTLS.this_thread) == get_coroutine(mainThread) ? 4 : 2;
    704 }
    705 
    706 static __spinlock_t kernel_debug_lock;
     654        return get_coroutine(TL_GET( this_thread )) == get_coroutine(mainThread) ? 4 : 2;
     655}
    707656
    708657extern "C" {
     
    733682        if ( count < 0 ) {
    734683                // queue current task
    735                 append( waiting, kernelTLS.this_thread );
     684                append( waiting, (thread_desc *)TL_GET( this_thread ) );
    736685
    737686                // atomically release spin lock and block
     
    759708
    760709//-----------------------------------------------------------------------------
    761 // Global Queues
    762 void doregister( thread_desc & thrd ) {
    763         // lock      ( global_thread.lock );
    764         // push_front( global_thread.list, thrd );
    765         // unlock    ( global_thread.lock );
    766 }
    767 
    768 void unregister( thread_desc & thrd ) {
    769         // lock  ( global_thread.lock );
    770         // remove( global_thread.list, thrd );
    771         // unlock( global_thread.lock );
    772 }
    773 
    774 void doregister( cluster     & cltr ) {
    775         // lock      ( global_cluster.lock );
    776         // push_front( global_cluster.list, cltr );
    777         // unlock    ( global_cluster.lock );
    778 }
    779 
    780 void unregister( cluster     & cltr ) {
    781         // lock  ( global_cluster.lock );
    782         // remove( global_cluster.list, cltr );
    783         // unlock( global_cluster.lock );
    784 }
    785 
    786 
    787 void doregister( cluster * cltr, processor * proc ) {
    788         // lock      (cltr->proc_list_lock __cfaabi_dbg_ctx2);
    789         // push_front(cltr->procs, *proc);
    790         // unlock    (cltr->proc_list_lock);
    791 }
    792 
    793 void unregister( cluster * cltr, processor * proc ) {
    794         // lock  (cltr->proc_list_lock __cfaabi_dbg_ctx2);
    795         // remove(cltr->procs, *proc );
    796         // unlock(cltr->proc_list_lock);
    797 }
    798 
    799 //-----------------------------------------------------------------------------
    800710// Debug
    801711__cfaabi_dbg_debug_do(
     712        struct {
     713                thread_desc * tail;
     714        } __cfaabi_dbg_thread_list = { NULL };
     715
     716        void __cfaabi_dbg_thread_register( thread_desc * thrd ) {
     717                if( !__cfaabi_dbg_thread_list.tail ) {
     718                        __cfaabi_dbg_thread_list.tail = thrd;
     719                        return;
     720                }
     721                __cfaabi_dbg_thread_list.tail->dbg_next = thrd;
     722                thrd->dbg_prev = __cfaabi_dbg_thread_list.tail;
     723                __cfaabi_dbg_thread_list.tail = thrd;
     724        }
     725
     726        void __cfaabi_dbg_thread_unregister( thread_desc * thrd ) {
     727                thread_desc * prev = thrd->dbg_prev;
     728                thread_desc * next = thrd->dbg_next;
     729
     730                if( next ) { next->dbg_prev = prev; }
     731                else       {
     732                        assert( __cfaabi_dbg_thread_list.tail == thrd );
     733                        __cfaabi_dbg_thread_list.tail = prev;
     734                }
     735
     736                if( prev ) { prev->dbg_next = next; }
     737
     738                thrd->dbg_prev = NULL;
     739                thrd->dbg_next = NULL;
     740        }
     741
    802742        void __cfaabi_dbg_record(__spinlock_t & this, const char * prev_name) {
    803743                this.prev_name = prev_name;
    804                 this.prev_thrd = kernelTLS.this_thread;
     744                this.prev_thrd = TL_GET( this_thread );
    805745        }
    806746)
Note: See TracChangeset for help on using the changeset viewer.