Ignore:
File:
1 edited

Legend:

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

    rfc59df78 rbfcf6b9  
    7777//-----------------------------------------------------------------------------
    7878// I/O
    79 $io_arbiter * create(void);
    80 void destroy($io_arbiter *);
     79void ^?{}(io_context & this, bool );
    8180
    8281//=======================================================================
    8382// Cluster lock API
    8483//=======================================================================
     84// Cells use by the reader writer lock
     85// while not generic it only relies on a opaque pointer
     86struct __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
     100static_assert( sizeof(struct __scheduler_lock_id_t) <= __alignof(struct __scheduler_lock_id_t));
     101
    85102// Lock-Free registering/unregistering of threads
    86103// Register a processor to a given cluster and get its unique id in return
    87 void register_proc_id( struct __processor_id_t * );
     104unsigned doregister( struct __processor_id_t * proc );
    88105
    89106// Unregister a processor from a given cluster using its id, getting back the original pointer
    90 void unregister_proc_id( struct __processor_id_t * proc );
     107void     unregister( struct __processor_id_t * proc );
     108
     109//-----------------------------------------------------------------------
     110// Cluster idle lock/unlock
     111static 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
     122static inline void unlock(__cluster_idles & this) {
     123        /* paranoid */ verify( 1 == (this.lock % 2) );
     124        __atomic_fetch_add( &this.lock, 1, __ATOMIC_SEQ_CST );
     125}
    91126
    92127//=======================================================================
     
    116151        __atomic_store_n(ll, (bool)false, __ATOMIC_RELEASE);
    117152}
    118 
    119 // Cells use by the reader writer lock
    120 // while not generic it only relies on a opaque pointer
    121 struct __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 
    135 static_assert( sizeof(struct __scheduler_lock_id_t) <= __alignof(struct __scheduler_lock_id_t));
    136153
    137154//-----------------------------------------------------------------------
     
    229246void ready_mutate_unlock( uint_fast32_t /* value returned by lock */ );
    230247
    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
    235 static 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
    242 static 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
    249 static 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 
    270 static 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 
    283248//=======================================================================
    284249// Ready-Queue API
     250//-----------------------------------------------------------------------
     251// pop thread from the ready queue of a cluster
     252// returns 0p if empty
     253__attribute__((hot)) bool query(struct cluster * cltr);
     254
    285255//-----------------------------------------------------------------------
    286256// push thread onto a ready queue for a cluster
    287257// returns true if the list was previously empty, false otherwise
    288 __attribute__((hot)) void push(struct cluster * cltr, struct $thread * thrd);
    289 
    290 //-----------------------------------------------------------------------
    291 // pop thread from the local queues of a cluster
     258__attribute__((hot)) bool push(struct cluster * cltr, struct $thread * thrd);
     259
     260//-----------------------------------------------------------------------
     261// pop thread from the ready queue of a cluster
    292262// returns 0p if empty
    293263// May return 0p spuriously
    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
     264__attribute__((hot)) struct $thread * pop(struct cluster * cltr);
     265
     266//-----------------------------------------------------------------------
     267// pop thread from the ready queue of a cluster
    304268// returns 0p if empty
    305269// guaranteed to find any threads added before this call
    306 __attribute__((hot)) struct $thread * pop_search(struct cluster * cltr);
     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
     275bool remove_head(struct cluster * cltr, struct $thread * thrd);
    307276
    308277//-----------------------------------------------------------------------
    309278// Increase the width of the ready queue (number of lanes) by 4
    310 void ready_queue_grow  (struct cluster * cltr);
     279void ready_queue_grow  (struct cluster * cltr, int target);
    311280
    312281//-----------------------------------------------------------------------
    313282// Decrease the width of the ready queue (number of lanes) by 4
    314 void ready_queue_shrink(struct cluster * cltr);
     283void ready_queue_shrink(struct cluster * cltr, int target);
    315284
    316285
Note: See TracChangeset for help on using the changeset viewer.