- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/kernel_private.hfa
r504a7dc rdd4e2d7 77 77 //----------------------------------------------------------------------------- 78 78 // I/O 79 void __kernel_io_startup ( cluster &, int, bool );79 void __kernel_io_startup ( cluster &, unsigned, bool ); 80 80 void __kernel_io_finish_start( cluster & ); 81 81 void __kernel_io_prepare_stop( cluster & ); … … 84 84 //----------------------------------------------------------------------------- 85 85 // 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)] 87 87 88 88 static inline uint32_t __tls_rand() { … … 103 103 void unregister( struct cluster * cltr, struct processor * proc ); 104 104 105 //=======================================================================106 // Cluster lock API107 //=======================================================================108 struct __attribute__((aligned(64))) __processor_id {109 processor * volatile handle;110 volatile bool lock;111 };112 113 // Lock-Free registering/unregistering of threads114 // Register a processor to a given cluster and get its unique id in return115 unsigned doregister2( struct cluster * cltr, struct processor * proc );116 117 // Unregister a processor from a given cluster using its id, getting back the original pointer118 void unregister2( struct cluster * cltr, struct processor * proc );119 120 //=======================================================================121 // Reader-writer lock implementation122 // Concurrent with doregister/unregister,123 // i.e., threads can be added at any point during or between the entry/exit124 125 //-----------------------------------------------------------------------126 // simple spinlock underlying the RWLock127 // Blocking acquire128 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 acquire137 static inline bool __atomic_try_acquire(volatile bool * ll) {138 return !__atomic_exchange_n(ll, (bool)true, __ATOMIC_SEQ_CST);139 }140 141 // Release142 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 not149 // creating/destroying queues150 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 section156 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 lock160 // before we read a false.161 // Not needed on x86162 // std::atomic_thread_fence(std::memory_order_seq_cst);163 164 // Step 2 : acquire our local lock165 __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 more179 // 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 API186 //-----------------------------------------------------------------------187 // push thread onto a ready queue for a cluster188 // returns true if the list was previously empty, false otherwise189 __attribute__((hot)) bool push(struct cluster * cltr, struct $thread * thrd);190 191 //-----------------------------------------------------------------------192 // pop thread from the ready queue of a cluster193 // returns 0p if empty194 __attribute__((hot)) struct $thread * pop(struct cluster * cltr);195 196 //-----------------------------------------------------------------------197 // Increase the width of the ready queue (number of lanes) by 4198 void ready_queue_grow (struct cluster * cltr);199 200 //-----------------------------------------------------------------------201 // Decrease the width of the ready queue (number of lanes) by 4202 void ready_queue_shrink(struct cluster * cltr);203 204 //-----------------------------------------------------------------------205 // Statics call at the end of each thread to register statistics206 #if !defined(__CFA_NO_STATISTICS__)207 void stats_tls_tally(struct cluster * cltr);208 #else209 static inline void stats_tls_tally(struct cluster * cltr) {}210 #endif211 212 105 // Local Variables: // 213 106 // mode: c //
Note:
See TracChangeset
for help on using the changeset viewer.