- File:
-
- 1 edited
-
libcfa/src/concurrency/locks.hfa (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/locks.hfa
ra45e21c rd30e3eb 32 32 #include <fstream.hfa> 33 33 34 34 35 // futex headers 35 36 #include <linux/futex.h> /* Definition of FUTEX_* constants */ … … 154 155 // futex_mutex 155 156 157 // - No cond var support 156 158 // - Kernel thd blocking alternative to the spinlock 157 159 // - No ownership (will deadlock on reacq) … … 183 185 int state; 184 186 185 for( int spin = 4; spin < 1024; spin += spin) { 186 state = 0; 187 // if unlocked, lock and return 188 if (internal_try_lock(this, state)) return; 189 if (2 == state) break; 190 for (int i = 0; i < spin; i++) Pause(); 191 } 192 193 // // no contention try to acquire 194 // if (internal_try_lock(this, state)) return; 187 188 // // linear backoff omitted for now 189 // for( int spin = 4; spin < 1024; spin += spin) { 190 // state = 0; 191 // // if unlocked, lock and return 192 // if (internal_try_lock(this, state)) return; 193 // if (2 == state) break; 194 // for (int i = 0; i < spin; i++) Pause(); 195 // } 196 197 // no contention try to acquire 198 if (internal_try_lock(this, state)) return; 195 199 196 200 // if not in contended state, set to be in contended state … … 205 209 206 210 static inline void unlock(futex_mutex & this) with(this) { 207 // if uncontended do atomic unlock and then return208 if (__atomic_exchange_n(&val, 0, __ATOMIC_RELEASE) == 1) return; 211 // if uncontended do atomice unlock and then return 212 if (__atomic_fetch_sub(&val, 1, __ATOMIC_RELEASE) == 1) return; // TODO: try acq/rel 209 213 210 214 // otherwise threads are blocked so we must wake one 215 __atomic_store_n((int *)&val, 0, __ATOMIC_RELEASE); 211 216 futex((int *)&val, FUTEX_WAKE, 1); 212 217 } … … 217 222 // to set recursion count after getting signalled; 218 223 static inline void on_wakeup( futex_mutex & f, size_t recursion ) {} 219 220 //-----------------------------------------------------------------------------221 // go_mutex222 223 // - Kernel thd blocking alternative to the spinlock224 // - No ownership (will deadlock on reacq)225 // - Golang's flavour of mutex226 // - Impl taken from Golang: src/runtime/lock_futex.go227 struct go_mutex {228 // lock state any state other than UNLOCKED is locked229 // enum LockState { UNLOCKED = 0, LOCKED = 1, SLEEPING = 2 };230 231 // stores a lock state232 int val;233 };234 235 static inline void ?{}( go_mutex & this ) with(this) { val = 0; }236 237 static inline bool internal_try_lock(go_mutex & this, int & compare_val, int new_val ) with(this) {238 return __atomic_compare_exchange_n((int*)&val, (int*)&compare_val, new_val, false, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);239 }240 241 static inline int internal_exchange(go_mutex & this, int swap ) with(this) {242 return __atomic_exchange_n((int*)&val, swap, __ATOMIC_ACQUIRE);243 }244 245 const int __go_mtx_spins = 4;246 const int __go_mtx_pauses = 30;247 // if this is called recursively IT WILL DEADLOCK!!!!!248 static inline void lock(go_mutex & this) with(this) {249 int state, init_state;250 251 // speculative grab252 state = internal_exchange(this, 1);253 if ( !state ) return; // state == 0254 init_state = state;255 for (;;) {256 for( int i = 0; i < __go_mtx_spins; i++ ) {257 while( !val ) { // lock unlocked258 state = 0;259 if (internal_try_lock(this, state, init_state)) return;260 }261 for (int i = 0; i < __go_mtx_pauses; i++) Pause();262 }263 264 while( !val ) { // lock unlocked265 state = 0;266 if (internal_try_lock(this, state, init_state)) return;267 }268 sched_yield();269 270 // if not in contended state, set to be in contended state271 state = internal_exchange(this, 2);272 if ( !state ) return; // state == 0273 init_state = 2;274 futex((int*)&val, FUTEX_WAIT, 2); // if val is not 2 this returns with EWOULDBLOCK275 }276 }277 278 static inline void unlock( go_mutex & this ) with(this) {279 // if uncontended do atomic unlock and then return280 if (__atomic_exchange_n(&val, 0, __ATOMIC_RELEASE) == 1) return;281 282 // otherwise threads are blocked so we must wake one283 futex((int *)&val, FUTEX_WAKE, 1);284 }285 286 static inline void on_notify( go_mutex & f, thread$ * t){ unpark(t); }287 static inline size_t on_wait( go_mutex & f ) {unlock(f); return 0;}288 static inline void on_wakeup( go_mutex & f, size_t recursion ) {}289 224 290 225 //----------------------------------------------------------------------------- … … 336 271 this.lock_value = 0; 337 272 } 338 339 static inline void ^?{}( exp_backoff_then_block_lock & this ){}340 273 341 274 static inline bool internal_try_lock(exp_backoff_then_block_lock & this, size_t & compare_val) with(this) {
Note:
See TracChangeset
for help on using the changeset viewer.