Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/concurrency/kernel_private.hfa

    rbfcf6b9 rfc59df78  
    7777//-----------------------------------------------------------------------------
    7878// I/O
    79 void ^?{}(io_context & this, bool );
     79$io_arbiter * create(void);
     80void destroy($io_arbiter *);
    8081
    8182//=======================================================================
    8283// Cluster lock API
    8384//=======================================================================
    84 // Cells use by the reader writer lock
    85 // while not generic it only relies on a opaque pointer
    86 struct __attribute__((aligned(128))) __scheduler_lock_id_t {
    87         // Spin lock used as the underlying lock
    88         volatile bool lock;
    89 
    90         // Handle pointing to the proc owning this cell
    91         // Used for allocating cells and debugging
    92         __processor_id_t * volatile handle;
    93 
    94         #ifdef __CFA_WITH_VERIFY__
    95                 // Debug, check if this is owned for reading
    96                 bool owned;
    97         #endif
    98 };
    99 
    100 static_assert( sizeof(struct __scheduler_lock_id_t) <= __alignof(struct __scheduler_lock_id_t));
    101 
    10285// Lock-Free registering/unregistering of threads
    10386// Register a processor to a given cluster and get its unique id in return
    104 unsigned doregister( struct __processor_id_t * proc );
     87void register_proc_id( struct __processor_id_t * );
    10588
    10689// Unregister a processor from a given cluster using its id, getting back the original pointer
    107 void     unregister( struct __processor_id_t * proc );
    108 
    109 //-----------------------------------------------------------------------
    110 // Cluster idle lock/unlock
    111 static inline void lock(__cluster_idles & this) {
    112         for() {
    113                 uint64_t l = this.lock;
    114                 if(
    115                         (0 == (l % 2))
    116                         && __atomic_compare_exchange_n(&this.lock, &l, l + 1, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
    117                 ) return;
    118                 Pause();
    119         }
    120 }
    121 
    122 static inline void unlock(__cluster_idles & this) {
    123         /* paranoid */ verify( 1 == (this.lock % 2) );
    124         __atomic_fetch_add( &this.lock, 1, __ATOMIC_SEQ_CST );
    125 }
     90void unregister_proc_id( struct __processor_id_t * proc );
    12691
    12792//=======================================================================
     
    151116        __atomic_store_n(ll, (bool)false, __ATOMIC_RELEASE);
    152117}
     118
     119// Cells use by the reader writer lock
     120// while not generic it only relies on a opaque pointer
     121struct __attribute__((aligned(128))) __scheduler_lock_id_t {
     122        // Spin lock used as the underlying lock
     123        volatile bool lock;
     124
     125        // Handle pointing to the proc owning this cell
     126        // Used for allocating cells and debugging
     127        __processor_id_t * volatile handle;
     128
     129        #ifdef __CFA_WITH_VERIFY__
     130                // Debug, check if this is owned for reading
     131                bool owned;
     132        #endif
     133};
     134
     135static_assert( sizeof(struct __scheduler_lock_id_t) <= __alignof(struct __scheduler_lock_id_t));
    153136
    154137//-----------------------------------------------------------------------
     
    246229void ready_mutate_unlock( uint_fast32_t /* value returned by lock */ );
    247230
     231//-----------------------------------------------------------------------
     232// Lock-Free registering/unregistering of threads
     233// Register a processor to a given cluster and get its unique id in return
     234// For convenience, also acquires the lock
     235static inline uint_fast32_t ready_mutate_register( struct __processor_id_t * proc ) {
     236        register_proc_id( proc );
     237        return ready_mutate_lock();
     238}
     239
     240// Unregister a processor from a given cluster using its id, getting back the original pointer
     241// assumes the lock is acquired
     242static inline void ready_mutate_unregister( struct __processor_id_t * proc, uint_fast32_t last_s ) {
     243        ready_mutate_unlock( last_s );
     244        unregister_proc_id( proc );
     245}
     246
     247//-----------------------------------------------------------------------
     248// Cluster idle lock/unlock
     249static inline void lock(__cluster_proc_list & this) {
     250        /* paranoid */ verify( ! __preemption_enabled() );
     251
     252        // Start by locking the global RWlock so that we know no-one is
     253        // adding/removing processors while we mess with the idle lock
     254        ready_schedule_lock();
     255
     256        // Simple counting lock, acquired, acquired by incrementing the counter
     257        // to an odd number
     258        for() {
     259                uint64_t l = this.lock;
     260                if(
     261                        (0 == (l % 2))
     262                        && __atomic_compare_exchange_n(&this.lock, &l, l + 1, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
     263                ) return;
     264                Pause();
     265        }
     266
     267        /* paranoid */ verify( ! __preemption_enabled() );
     268}
     269
     270static inline void unlock(__cluster_proc_list & this) {
     271        /* paranoid */ verify( ! __preemption_enabled() );
     272
     273        /* paranoid */ verify( 1 == (this.lock % 2) );
     274        // Simple couting lock, release by incrementing to an even number
     275        __atomic_fetch_add( &this.lock, 1, __ATOMIC_SEQ_CST );
     276
     277        // Release the global lock, which we acquired when locking
     278        ready_schedule_unlock();
     279
     280        /* paranoid */ verify( ! __preemption_enabled() );
     281}
     282
    248283//=======================================================================
    249284// Ready-Queue API
    250285//-----------------------------------------------------------------------
    251 // pop thread from the ready queue of a cluster
    252 // returns 0p if empty
    253 __attribute__((hot)) bool query(struct cluster * cltr);
    254 
    255 //-----------------------------------------------------------------------
    256286// push thread onto a ready queue for a cluster
    257287// returns true if the list was previously empty, false otherwise
    258 __attribute__((hot)) bool push(struct cluster * cltr, struct $thread * thrd);
    259 
    260 //-----------------------------------------------------------------------
    261 // pop thread from the ready queue of a cluster
     288__attribute__((hot)) void push(struct cluster * cltr, struct $thread * thrd);
     289
     290//-----------------------------------------------------------------------
     291// pop thread from the local queues of a cluster
    262292// returns 0p if empty
    263293// May return 0p spuriously
    264 __attribute__((hot)) struct $thread * pop(struct cluster * cltr);
    265 
    266 //-----------------------------------------------------------------------
    267 // pop thread from the ready queue of a cluster
     294__attribute__((hot)) struct $thread * pop_fast(struct cluster * cltr);
     295
     296//-----------------------------------------------------------------------
     297// pop thread from any ready queue of a cluster
     298// returns 0p if empty
     299// May return 0p spuriously
     300__attribute__((hot)) struct $thread * pop_slow(struct cluster * cltr);
     301
     302//-----------------------------------------------------------------------
     303// search all ready queues of a cluster for any thread
    268304// returns 0p if empty
    269305// guaranteed to find any threads added before this call
    270 __attribute__((hot)) struct $thread * pop_slow(struct cluster * cltr);
    271 
    272 //-----------------------------------------------------------------------
    273 // remove thread from the ready queue of a cluster
    274 // returns bool if it wasn't found
    275 bool remove_head(struct cluster * cltr, struct $thread * thrd);
     306__attribute__((hot)) struct $thread * pop_search(struct cluster * cltr);
    276307
    277308//-----------------------------------------------------------------------
    278309// Increase the width of the ready queue (number of lanes) by 4
    279 void ready_queue_grow  (struct cluster * cltr, int target);
     310void ready_queue_grow  (struct cluster * cltr);
    280311
    281312//-----------------------------------------------------------------------
    282313// Decrease the width of the ready queue (number of lanes) by 4
    283 void ready_queue_shrink(struct cluster * cltr, int target);
     314void ready_queue_shrink(struct cluster * cltr);
    284315
    285316
Note: See TracChangeset for help on using the changeset viewer.