Changeset 9b1dcc2


Ignore:
Timestamp:
Jun 12, 2020, 1:49:17 PM (15 months ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
arm-eh, jacob/cs343-translation, master, new-ast, new-ast-unique-expr
Children:
cb196f2
Parents:
b388ee8
Message:

Changed scheduling API to adapt to non-Processors scheduling threads.

Location:
libcfa/src/concurrency
Files:
6 edited

Legend:

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

    rb388ee8 r9b1dcc2  
    300300        // register the processor unless it's the main thread which is handled in the boot sequence
    301301        if(this != mainProcessor) {
    302                 this->id = doregister(this);
     302                this->id = doregister((__processor_id_t*)this);
    303303                ready_queue_grow( this->cltr );
    304304        }
     
    346346        if(this != mainProcessor) {
    347347                ready_queue_shrink( this->cltr );
    348                 unregister(this);
     348                unregister((__processor_id_t*)this);
    349349        }
    350350        else {
     
    416416                if(unlikely(thrd_dst->preempted != __NO_PREEMPTION)) {
    417417                        // The thread was preempted, reschedule it and reset the flag
    418                         __schedule_thread( thrd_dst );
     418                        __schedule_thread( (__processor_id_t*)this, thrd_dst );
    419419                        break RUNNING;
    420420                }
     
    609609// Scheduler routines
    610610// KERNEL ONLY
    611 void __schedule_thread( $thread * thrd ) {
     611void __schedule_thread( struct __processor_id_t * id, $thread * thrd ) {
    612612        /* paranoid */ verify( thrd );
    613613        /* paranoid */ verify( thrd->state != Halted );
     
    623623        if (thrd->preempted == __NO_PREEMPTION) thrd->state = Ready;
    624624
    625         ready_schedule_lock( kernelTLS.this_processor );
     625        ready_schedule_lock  ( id );
    626626                push( thrd->curr_cluster, thrd );
    627627
    628628                __wake_one(thrd->curr_cluster);
    629         ready_schedule_unlock( kernelTLS.this_processor );
     629        ready_schedule_unlock( id );
    630630
    631631        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     
    636636        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    637637
    638         ready_schedule_lock( kernelTLS.this_processor );
     638        ready_schedule_lock  ( (__processor_id_t*)kernelTLS.this_processor );
    639639                $thread * head = pop( this );
    640         ready_schedule_unlock( kernelTLS.this_processor );
     640        ready_schedule_unlock( (__processor_id_t*)kernelTLS.this_processor );
    641641
    642642        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     
    645645
    646646// KERNEL ONLY unpark with out disabling interrupts
    647 void __unpark( $thread * thrd __cfaabi_dbg_ctx_param2 ) {
     647void __unpark(  struct __processor_id_t * id, $thread * thrd __cfaabi_dbg_ctx_param2 ) {
    648648        static_assert(sizeof(thrd->state) == sizeof(int));
    649649
     
    663663                        // Wake lost the race,
    664664                        thrd->state = Blocked;
    665                         __schedule_thread( thrd );
     665                        __schedule_thread( id, thrd );
    666666                        break;
    667667                case Rerun:
     
    681681
    682682        disable_interrupts();
    683         __unpark( thrd __cfaabi_dbg_ctx_fwd2 );
     683        __unpark( (__processor_id_t*)kernelTLS.this_processor, thrd __cfaabi_dbg_ctx_fwd2 );
    684684        enable_interrupts( __cfaabi_dbg_ctx );
    685685}
     
    798798        (*mainProcessor){};
    799799
    800         mainProcessor->id = doregister(mainProcessor);
     800        mainProcessor->id = doregister( (__processor_id_t*)mainProcessor);
    801801
    802802        //initialize the global state variables
     
    809809        // Add the main thread to the ready queue
    810810        // once resume is called on mainProcessor->runner the mainThread needs to be scheduled like any normal thread
    811         __schedule_thread(mainThread);
     811        __schedule_thread((__processor_id_t *)mainProcessor, mainThread);
    812812
    813813        // SKULLDUGGERY: Force a context switch to the main processor to set the main thread's context to the current UNIX
     
    853853        kernel_stop_preemption();
    854854
    855         unregister(mainProcessor);
     855        unregister((__processor_id_t*)mainProcessor);
    856856
    857857        // Destroy the main processor and its context in reverse order of construction
  • libcfa/src/concurrency/kernel.hfa

    rb388ee8 r9b1dcc2  
    4747extern struct cluster * mainCluster;
    4848
    49 // Processor
     49// Processor id, required for scheduling threads
     50struct __processor_id_t {
     51        unsigned id;
     52};
     53
    5054coroutine processorCtx_t {
    5155        struct processor * proc;
     
    5458// Wrapper around kernel threads
    5559struct processor {
     60        inline __processor_id_t;
     61
    5662        // Main state
    5763        // Coroutine ctx who does keeps the state of the processor
     
    6066        // Cluster from which to get threads
    6167        struct cluster * cltr;
    62         unsigned int id;
    6368
    6469        // Name of the processor
  • libcfa/src/concurrency/kernel_private.hfa

    rb388ee8 r9b1dcc2  
    2525// Scheduler
    2626
     27struct __attribute__((aligned(64))) __scheduler_lock_id_t;
     28
    2729extern "C" {
    2830        void disable_interrupts() OPTIONAL_THREAD;
     
    3133}
    3234
    33 void __schedule_thread( $thread * ) __attribute__((nonnull (1)));
     35void __schedule_thread( struct __processor_id_t *, $thread * ) __attribute__((nonnull (2)));
    3436
    3537//Block current thread and release/wake-up the following resources
     
    7375
    7476// KERNEL ONLY unpark with out disabling interrupts
    75 void __unpark( $thread * thrd __cfaabi_dbg_ctx_param2 );
     77void __unpark( struct __processor_id_t *, $thread * thrd __cfaabi_dbg_ctx_param2 );
    7678
    7779//-----------------------------------------------------------------------------
     
    108110// Cells use by the reader writer lock
    109111// while not generic it only relies on a opaque pointer
    110 struct __attribute__((aligned(64))) __processor_id {
    111         processor * volatile handle;
     112struct __attribute__((aligned(64))) __scheduler_lock_id_t {
     113        __processor_id_t * volatile handle;
    112114        volatile bool lock;
    113115};
     
    115117// Lock-Free registering/unregistering of threads
    116118// Register a processor to a given cluster and get its unique id in return
    117 unsigned doregister( struct processor * proc );
     119unsigned doregister( struct __processor_id_t * proc );
    118120
    119121// Unregister a processor from a given cluster using its id, getting back the original pointer
    120 void     unregister( struct processor * proc );
     122void     unregister( struct __processor_id_t * proc );
    121123
    122124//=======================================================================
     
    167169
    168170        // data pointer
    169         __processor_id * data;
     171        __scheduler_lock_id_t * data;
    170172};
    171173
     
    178180// Reader side : acquire when using the ready queue to schedule but not
    179181//  creating/destroying queues
    180 static inline void ready_schedule_lock( struct processor * proc) with(*__scheduler_lock) {
     182static inline void ready_schedule_lock( struct __processor_id_t * proc) with(*__scheduler_lock) {
    181183        unsigned iproc = proc->id;
    182184        /*paranoid*/ verify(data[iproc].handle == proc);
     
    197199}
    198200
    199 static inline void ready_schedule_unlock( struct processor * proc) with(*__scheduler_lock) {
     201static inline void ready_schedule_unlock( struct __processor_id_t * proc) with(*__scheduler_lock) {
    200202        unsigned iproc = proc->id;
    201203        /*paranoid*/ verify(data[iproc].handle == proc);
  • libcfa/src/concurrency/preemption.cfa

    rb388ee8 r9b1dcc2  
    3939// FwdDeclarations : timeout handlers
    4040static void preempt( processor   * this );
    41 static void timeout( $thread * this );
     41static void timeout( struct __processor_id_t * id, $thread * this );
    4242
    4343// FwdDeclarations : Signal handlers
     
    9090
    9191// Tick one frame of the Discrete Event Simulation for alarms
    92 static void tick_preemption() {
     92static void tick_preemption( struct __processor_id_t * id ) {
    9393        alarm_node_t * node = 0p;                                                       // Used in the while loop but cannot be declared in the while condition
    9494        alarm_list_t * alarms = &event_kernel->alarms;          // Local copy for ease of reading
     
    108108                }
    109109                else {
    110                         timeout( node->thrd );
     110                        timeout( id, node->thrd );
    111111                }
    112112
     
    268268
    269269// reserved for future use
    270 static void timeout( $thread * this ) {
    271         __unpark( this __cfaabi_dbg_ctx2 );
     270static void timeout( struct __processor_id_t * id, $thread * this ) {
     271        __unpark( id, this __cfaabi_dbg_ctx2 );
    272272}
    273273
     
    405405// Waits on SIGALRM and send SIGUSR1 to whom ever needs it
    406406static void * alarm_loop( __attribute__((unused)) void * args ) {
     407        __processor_id_t id;
     408        id.id = doregister(&id);
     409
    407410        // Block sigalrms to control when they arrive
    408411        sigset_t mask;
     
    449452                        // __cfaabi_dbg_print_safe( "Kernel : Preemption thread tick\n" );
    450453                        lock( event_kernel->lock __cfaabi_dbg_ctx2 );
    451                         tick_preemption();
     454                        tick_preemption( &id );
    452455                        unlock( event_kernel->lock );
    453456                        break;
     
    462465EXIT:
    463466        __cfaabi_dbg_print_safe( "Kernel : Preemption thread stopping\n" );
     467        unregister(&id);
    464468        return 0p;
    465469}
  • libcfa/src/concurrency/ready_queue.cfa

    rb388ee8 r9b1dcc2  
    7474}
    7575
    76 void ?{}( __processor_id & this, struct processor * proc ) {
     76void ?{}( __scheduler_lock_id_t & this, __processor_id_t * proc ) {
    7777        this.handle = proc;
    7878        this.lock   = false;
     
    8181//=======================================================================
    8282// Lock-Free registering/unregistering of threads
    83 unsigned doregister( struct processor * proc ) with(*__scheduler_lock) {
     83unsigned doregister( struct __processor_id_t * proc ) with(*__scheduler_lock) {
    8484        __cfadbg_print_safe(ready_queue, "Kernel : Registering proc %p for RW-Lock\n", proc);
    8585
     
    8989        // Check among all the ready
    9090        for(uint_fast32_t i = 0; i < s; i++) {
    91                 processor * null = 0p; // Re-write every loop since compare thrashes it
     91                __processor_id_t * null = 0p; // Re-write every loop since compare thrashes it
    9292                if( __atomic_load_n(&data[i].handle, (int)__ATOMIC_RELAXED) == null
    9393                        && __atomic_compare_exchange_n( &data[i].handle, &null, proc, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
     
    106106
    107107        // Step - 3 : Mark space as used and then publish it.
    108         __processor_id * storage = (__processor_id *)&data[n];
     108        __scheduler_lock_id_t * storage = (__scheduler_lock_id_t *)&data[n];
    109109        (*storage){ proc };
    110110        while(true) {
     
    125125}
    126126
    127 void unregister( struct processor * proc ) with(*__scheduler_lock) {
     127void unregister( struct __processor_id_t * proc ) with(*__scheduler_lock) {
    128128        unsigned id = proc->id;
    129129        /*paranoid*/ verify(id < ready);
     
    188188        } before, after;
    189189
    190 #if defined(__CFA_WITH_VERIFY__)
    191         // id of last processor to acquire the lock
    192         // needed only to check for mutual exclusion violations
    193         unsigned int last_id;
    194 
    195         // number of items on this list
    196         // needed only to check for deadlocks
    197         unsigned int count;
    198 #endif
    199 
    200190        // Optional statistic counters
    201191        #if !defined(__CFA_NO_SCHED_STATS__)
     
    235225void ?{}( __intrusive_lane_t & this ) {
    236226        this.lock = false;
    237         #if defined(__CFA_WITH_VERIFY__)
    238                 this.last_id = -1u;
    239                 this.count = 0u;
    240         #endif
    241227
    242228        this.before.link.prev = 0p;
     
    279265        /* paranoid */ verify(tail(this)->link.next == 0p );
    280266        /* paranoid */ verify(tail(this)->link.prev == head(this) );
    281         /* paranoid */ verify(this.count == 0u );
    282267}
    283268
     
    293278                /* paranoid */ verify(head(this)->link.prev == 0p);
    294279
    295                 this.count++;
    296 
    297280                if(this.before.link.ts == 0l) {
    298281                        /* paranoid */ verify(tail(this)->link.prev == head(this));
     
    346329        $thread * next = node->link.next;
    347330
    348         #if defined(__CFA_WITH_VERIFY__)
    349                 this.count--;
    350                 /* paranoid */ verify(node != tail);
    351                 /* paranoid */ verify(node);
    352         #endif
     331        /* paranoid */ verify(node != tail);
     332        /* paranoid */ verify(node);
    353333
    354334        // Do the pop
     
    637617        } while( !__atomic_try_acquire( &lanes.data[i].lock ) );
    638618
    639         #if defined(__CFA_WITH_VERIFY__)
    640                 /* paranoid */ verify(lanes.data[i].last_id == -1u);
    641                 /* paranoid */ lanes.data[i].last_id = kernelTLS.this_processor->id;
    642         #endif
    643 
    644619        bool first = false;
    645620
     
    655630                arrive( snzi, i );
    656631        }
    657 
    658         #if defined(__CFA_WITH_VERIFY__)
    659                 /* paranoid */ verifyf( lanes.data[i].last_id == kernelTLS.this_processor->id, "Expected last processor to lock queue %u to be %u, was %u\n", i, lanes.data[i].last_id, kernelTLS.this_processor->id );
    660                 /* paranoid */ verifyf( lanes.data[i].lock, "List %u is not locked\n", i );
    661                 /* paranoid */ lanes.data[i].last_id = -1u;
    662         #endif
    663632
    664633        // Unlock and return
     
    698667        if( !__atomic_try_acquire(&lane.lock) ) return 0p;
    699668
    700         #if defined(__CFA_WITH_VERIFY__)
    701                 /* paranoid */ verify(lane.last_id == -1u);
    702                 /* paranoid */ lane.last_id = kernelTLS.this_processor->id;
    703         #endif
    704 
    705669
    706670        // If list is empty, unlock and retry
    707671        if( is_empty(lane) ) {
    708                 #if defined(__CFA_WITH_VERIFY__)
    709                         /* paranoid */ verify(lane.last_id == kernelTLS.this_processor->id);
    710                         /* paranoid */ lane.last_id = -1u;
    711                 #endif
    712 
    713672                __atomic_unlock(&lane.lock);
    714673                return 0p;
     
    721680
    722681        /* paranoid */ verify(thrd);
    723         /* paranoid */ verify(lane.last_id == kernelTLS.this_processor->id);
    724682        /* paranoid */ verify(lane.lock);
    725683
     
    728686                depart( snzi, w );
    729687        }
    730 
    731         #if defined(__CFA_WITH_VERIFY__)
    732                 /* paranoid */ verify(lane.last_id == kernelTLS.this_processor->id);
    733                 /* paranoid */ lane.last_id = -1u;
    734         #endif
    735688
    736689        // Unlock and return
     
    874827                ^(snzi){};
    875828
    876                 // Make sure that the total thread count stays the same
    877                 #if defined(__CFA_WITH_VERIFY__)
    878                         size_t nthreads = 0;
    879                         for( idx; (size_t)lanes.count ) {
    880                                 nthreads += lanes.data[idx].count;
    881                         }
    882                 #endif
    883 
    884829                size_t ocount = lanes.count;
    885830                // Check that we have some space left
     
    940885                        }
    941886                }
    942 
    943                 // Make sure that the total thread count stayed the same
    944                 #if defined(__CFA_WITH_VERIFY__)
    945                         for( idx; (size_t)lanes.count ) {
    946                                 nthreads -= lanes.data[idx].count;
    947                         }
    948                         verifyf(nthreads == 0, "Shrinking changed number of threads");
    949                 #endif
    950887        }
    951888
  • libcfa/src/concurrency/thread.cfa

    rb388ee8 r9b1dcc2  
    6262        verify( this_thrd->context.SP );
    6363
    64         __schedule_thread(this_thrd);
     64        __schedule_thread( (__processor_id_t *)kernelTLS.this_processor, this_thrd);
    6565        enable_interrupts( __cfaabi_dbg_ctx );
    6666}
Note: See TracChangeset for help on using the changeset viewer.