Ignore:
File:
1 edited

Legend:

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

    r504a7dc rdd4e2d7  
    7777//-----------------------------------------------------------------------------
    7878// I/O
    79 void __kernel_io_startup     ( cluster &, int, bool );
     79void __kernel_io_startup     ( cluster &, unsigned, bool );
    8080void __kernel_io_finish_start( cluster & );
    8181void __kernel_io_prepare_stop( cluster & );
     
    8484//-----------------------------------------------------------------------------
    8585// Utils
    86 #define KERNEL_STORAGE(T,X) __attribute((aligned(__alignof__(T)))) static char storage_##X[sizeof(T)]
     86#define KERNEL_STORAGE(T,X) static char storage_##X[sizeof(T)]
    8787
    8888static inline uint32_t __tls_rand() {
     
    103103void unregister( struct cluster * cltr, struct processor * proc );
    104104
    105 //=======================================================================
    106 // Cluster lock API
    107 //=======================================================================
    108 struct __attribute__((aligned(64))) __processor_id {
    109         processor * volatile handle;
    110         volatile bool lock;
    111 };
    112 
    113 // Lock-Free registering/unregistering of threads
    114 // Register a processor to a given cluster and get its unique id in return
    115 unsigned doregister2( struct cluster * cltr, struct processor * proc );
    116 
    117 // Unregister a processor from a given cluster using its id, getting back the original pointer
    118 void     unregister2( struct cluster * cltr, struct processor * proc );
    119 
    120 //=======================================================================
    121 // Reader-writer lock implementation
    122 // Concurrent with doregister/unregister,
    123 //    i.e., threads can be added at any point during or between the entry/exit
    124 
    125 //-----------------------------------------------------------------------
    126 // simple spinlock underlying the RWLock
    127 // Blocking acquire
    128 static inline void __atomic_acquire(volatile bool * ll) {
    129         while( __builtin_expect(__atomic_exchange_n(ll, (bool)true, __ATOMIC_SEQ_CST), false) ) {
    130                 while(__atomic_load_n(ll, (int)__ATOMIC_RELAXED))
    131                         asm volatile("pause");
    132         }
    133         /* paranoid */ verify(*ll);
    134 }
    135 
    136 // Non-Blocking acquire
    137 static inline bool __atomic_try_acquire(volatile bool * ll) {
    138         return !__atomic_exchange_n(ll, (bool)true, __ATOMIC_SEQ_CST);
    139 }
    140 
    141 // Release
    142 static inline void __atomic_unlock(volatile bool * ll) {
    143         /* paranoid */ verify(*ll);
    144         __atomic_store_n(ll, (bool)false, __ATOMIC_RELEASE);
    145 }
    146 
    147 //-----------------------------------------------------------------------
    148 // Reader side : acquire when using the ready queue to schedule but not
    149 //  creating/destroying queues
    150 static inline void ready_schedule_lock( struct cluster * cltr, struct processor * proc) with(cltr->ready_lock) {
    151         unsigned iproc = proc->id;
    152         /*paranoid*/ verify(data[iproc].handle == proc);
    153         /*paranoid*/ verify(iproc < ready);
    154 
    155         // Step 1 : make sure no writer are in the middle of the critical section
    156         while(__atomic_load_n(&lock, (int)__ATOMIC_RELAXED))
    157                 asm volatile("pause");
    158 
    159         // Fence needed because we don't want to start trying to acquire the lock
    160         // before we read a false.
    161         // Not needed on x86
    162         // std::atomic_thread_fence(std::memory_order_seq_cst);
    163 
    164         // Step 2 : acquire our local lock
    165         __atomic_acquire( &data[iproc].lock );
    166         /*paranoid*/ verify(data[iproc].lock);
    167 }
    168 
    169 static inline void ready_schedule_unlock( struct cluster * cltr, struct processor * proc) with(cltr->ready_lock) {
    170         unsigned iproc = proc->id;
    171         /*paranoid*/ verify(data[iproc].handle == proc);
    172         /*paranoid*/ verify(iproc < ready);
    173         /*paranoid*/ verify(data[iproc].lock);
    174         __atomic_unlock(&data[iproc].lock);
    175 }
    176 
    177 //-----------------------------------------------------------------------
    178 // Writer side : acquire when changing the ready queue, e.g. adding more
    179 //  queues or removing them.
    180 uint_fast32_t ready_mutate_lock( struct cluster & cltr );
    181 
    182 void ready_mutate_unlock( struct cluster & cltr, uint_fast32_t /* value returned by lock */ );
    183 
    184 //=======================================================================
    185 // Ready-Queue API
    186 //-----------------------------------------------------------------------
    187 // push thread onto a ready queue for a cluster
    188 // returns true if the list was previously empty, false otherwise
    189 __attribute__((hot)) bool push(struct cluster * cltr, struct $thread * thrd);
    190 
    191 //-----------------------------------------------------------------------
    192 // pop thread from the ready queue of a cluster
    193 // returns 0p if empty
    194 __attribute__((hot)) struct $thread * pop(struct cluster * cltr);
    195 
    196 //-----------------------------------------------------------------------
    197 // Increase the width of the ready queue (number of lanes) by 4
    198 void ready_queue_grow  (struct cluster * cltr);
    199 
    200 //-----------------------------------------------------------------------
    201 // Decrease the width of the ready queue (number of lanes) by 4
    202 void ready_queue_shrink(struct cluster * cltr);
    203 
    204 //-----------------------------------------------------------------------
    205 // Statics call at the end of each thread to register statistics
    206 #if !defined(__CFA_NO_STATISTICS__)
    207 void stats_tls_tally(struct cluster * cltr);
    208 #else
    209 static inline void stats_tls_tally(struct cluster * cltr) {}
    210 #endif
    211 
    212105// Local Variables: //
    213106// mode: c //
Note: See TracChangeset for help on using the changeset viewer.