- File:
-
- 1 edited
-
libcfa/src/concurrency/kernel_private.hfa (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/kernel_private.hfa
r431cd4f rbd0bdd37 83 83 // Cluster lock API 84 84 //======================================================================= 85 // Cells use by the reader writer lock 86 // while not generic it only relies on a opaque pointer 87 struct __attribute__((aligned(128))) __scheduler_lock_id_t { 88 // Spin lock used as the underlying lock 89 volatile bool lock; 90 91 // Handle pointing to the proc owning this cell 92 // Used for allocating cells and debugging 93 __processor_id_t * volatile handle; 94 95 #ifdef __CFA_WITH_VERIFY__ 96 // Debug, check if this is owned for reading 97 bool owned; 98 #endif 99 }; 100 101 static_assert( sizeof(struct __scheduler_lock_id_t) <= __alignof(struct __scheduler_lock_id_t)); 102 85 103 // Lock-Free registering/unregistering of threads 86 104 // Register a processor to a given cluster and get its unique id in return 87 void register_proc_id( struct __processor_id_t *);105 unsigned doregister( struct __processor_id_t * proc ); 88 106 89 107 // 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 ); 108 void unregister( struct __processor_id_t * proc ); 109 110 //----------------------------------------------------------------------- 111 // Cluster idle lock/unlock 112 static inline void lock(__cluster_idles & this) { 113 for() { 114 uint64_t l = this.lock; 115 if( 116 (0 == (l % 2)) 117 && __atomic_compare_exchange_n(&this.lock, &l, l + 1, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) 118 ) return; 119 Pause(); 120 } 121 } 122 123 static inline void unlock(__cluster_idles & this) { 124 /* paranoid */ verify( 1 == (this.lock % 2) ); 125 __atomic_fetch_add( &this.lock, 1, __ATOMIC_SEQ_CST ); 126 } 91 127 92 128 //======================================================================= … … 116 152 __atomic_store_n(ll, (bool)false, __ATOMIC_RELEASE); 117 153 } 118 119 // Cells use by the reader writer lock120 // while not generic it only relies on a opaque pointer121 struct __attribute__((aligned(128))) __scheduler_lock_id_t {122 // Spin lock used as the underlying lock123 volatile bool lock;124 125 // Handle pointing to the proc owning this cell126 // Used for allocating cells and debugging127 __processor_id_t * volatile handle;128 129 #ifdef __CFA_WITH_VERIFY__130 // Debug, check if this is owned for reading131 bool owned;132 #endif133 };134 135 static_assert( sizeof(struct __scheduler_lock_id_t) <= __alignof(struct __scheduler_lock_id_t));136 154 137 155 //----------------------------------------------------------------------- … … 229 247 void ready_mutate_unlock( uint_fast32_t /* value returned by lock */ ); 230 248 231 //-----------------------------------------------------------------------232 // Lock-Free registering/unregistering of threads233 // Register a processor to a given cluster and get its unique id in return234 // For convenience, also acquires the lock235 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 pointer241 // assumes the lock is acquired242 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/unlock249 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 is253 // adding/removing processors while we mess with the idle lock254 ready_schedule_lock();255 256 // Simple counting lock, acquired, acquired by incrementing the counter257 // to an odd number258 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 number275 __atomic_fetch_add( &this.lock, 1, __ATOMIC_SEQ_CST );276 277 // Release the global lock, which we acquired when locking278 ready_schedule_unlock();279 280 /* paranoid */ verify( ! __preemption_enabled() );281 }282 283 249 //======================================================================= 284 250 // Ready-Queue API 251 //----------------------------------------------------------------------- 252 // pop thread from the ready queue of a cluster 253 // returns 0p if empty 254 __attribute__((hot)) bool query(struct cluster * cltr); 255 285 256 //----------------------------------------------------------------------- 286 257 // push thread onto a ready queue for a cluster 287 258 // returns true if the list was previously empty, false otherwise 288 __attribute__((hot)) voidpush(struct cluster * cltr, struct $thread * thrd);259 __attribute__((hot)) bool push(struct cluster * cltr, struct $thread * thrd); 289 260 290 261 //----------------------------------------------------------------------- … … 292 263 // returns 0p if empty 293 264 // May return 0p spuriously 294 __attribute__((hot)) struct $thread * pop _fast(struct cluster * cltr);265 __attribute__((hot)) struct $thread * pop(struct cluster * cltr); 295 266 296 267 //----------------------------------------------------------------------- … … 301 272 302 273 //----------------------------------------------------------------------- 274 // remove thread from the ready queue of a cluster 275 // returns bool if it wasn't found 276 bool remove_head(struct cluster * cltr, struct $thread * thrd); 277 278 //----------------------------------------------------------------------- 303 279 // Increase the width of the ready queue (number of lanes) by 4 304 void ready_queue_grow (struct cluster * cltr);280 unsigned ready_queue_grow (struct cluster * cltr, int target); 305 281 306 282 //----------------------------------------------------------------------- 307 283 // Decrease the width of the ready queue (number of lanes) by 4 308 void ready_queue_shrink(struct cluster * cltr );284 void ready_queue_shrink(struct cluster * cltr, int target); 309 285 310 286
Note:
See TracChangeset
for help on using the changeset viewer.