Changeset 7f958c4
- Timestamp:
- May 4, 2022, 3:28:00 PM (3 years ago)
- Branches:
- ADT, ast-experimental, master, pthread-emulation, qualifiedEnum
- Children:
- ec57856
- Parents:
- f6737ae1
- Location:
- libcfa/src/concurrency
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/locks.cfa
rf6737ae1 r7f958c4 220 220 221 221 //----------------------------------------------------------------------------- 222 // condition variable222 // Synchronization Locks 223 223 forall(L & | is_blocking_lock(L)) { 224 224 225 //----------------------------------------------------------------------------- 226 // condition variable 225 227 void ?{}( condition_variable(L) & this ){ 226 228 this.lock{}; … … 337 339 bool wait( condition_variable(L) & this, L & l, Duration duration ) with(this) { WAIT_TIME( 0 , &l , duration ) } 338 340 bool wait( condition_variable(L) & this, L & l, uintptr_t info, Duration duration ) with(this) { WAIT_TIME( info, &l , duration ) } 341 342 //----------------------------------------------------------------------------- 343 // fast_cond_var 344 void ?{}( fast_cond_var(L) & this ){ 345 this.blocked_threads{}; 346 #ifdef __CFA_DEBUG__ 347 this.lock_used = 0p; 348 #endif 349 } 350 void ^?{}( fast_cond_var(L) & this ){ } 351 352 bool notify_one( fast_cond_var(L) & this ) with(this) { 353 bool ret = ! blocked_threads`isEmpty; 354 if ( ret ) { 355 info_thread(L) & popped = try_pop_front( blocked_threads ); 356 on_notify(*popped.lock, popped.t); 357 } 358 return ret; 359 } 360 bool notify_all( fast_cond_var(L) & this ) with(this) { 361 bool ret = ! blocked_threads`isEmpty; 362 while( ! blocked_threads`isEmpty ) { 363 info_thread(L) & popped = try_pop_front( blocked_threads ); 364 on_notify(*popped.lock, popped.t); 365 } 366 return ret; 367 } 368 369 uintptr_t front( fast_cond_var(L) & this ) with(this) { return blocked_threads`isEmpty ? NULL : blocked_threads`first.info; } 370 bool empty ( fast_cond_var(L) & this ) with(this) { return blocked_threads`isEmpty; } 371 372 void wait( fast_cond_var(L) & this, L & l ) { 373 wait( this, l, 0 ); 374 } 375 376 void wait( fast_cond_var(L) & this, L & l, uintptr_t info ) with(this) { 377 // brand cond lock with lock 378 #ifdef __CFA_DEBUG__ 379 if ( lock_used == 0p ) lock_used = &l; 380 else { assert(lock_used == &l); } 381 #endif 382 info_thread( L ) i = { active_thread(), info, &l }; 383 insert_last( blocked_threads, i ); 384 size_t recursion_count = on_wait( *i.lock ); 385 park( ); 386 on_wakeup(*i.lock, recursion_count); 387 } 339 388 } 340 389 -
libcfa/src/concurrency/locks.hfa
rf6737ae1 r7f958c4 73 73 static inline void on_notify( owner_lock & this, struct thread$ * t ) { on_notify( (blocking_lock &)this, t ); } 74 74 75 //----------------------------------------------------------------------------- 76 // MCS Lock 75 77 struct mcs_node { 76 78 mcs_node * volatile next; … … 98 100 } 99 101 102 //----------------------------------------------------------------------------- 103 // Linear backoff Spinlock 100 104 struct linear_backoff_then_block_lock { 101 105 // Spin lock used for mutual exclusion … … 199 203 200 204 //----------------------------------------------------------------------------- 205 // Fast Block Lock 206 207 // High efficiency minimal blocking lock 208 // - No reacquire for cond var 209 // - No recursive acquisition 210 // - No ownership 211 struct fast_block_lock { 212 // Spin lock used for mutual exclusion 213 __spinlock_t lock; 214 215 // List of blocked threads 216 dlist( thread$ ) blocked_threads; 217 218 bool held:1; 219 }; 220 221 static inline void ?{}( fast_block_lock & this ) with(this) { 222 lock{}; 223 blocked_threads{}; 224 held = false; 225 } 226 static inline void ^?{}( fast_block_lock & this ) {} 227 static inline void ?{}( fast_block_lock & this, fast_block_lock this2 ) = void; 228 static inline void ?=?( fast_block_lock & this, fast_block_lock this2 ) = void; 229 230 // if this is called recursively IT WILL DEADLOCK!!!!! 231 static inline void lock(fast_block_lock & this) with(this) { 232 lock( lock __cfaabi_dbg_ctx2 ); 233 if (held) { 234 insert_last( blocked_threads, *active_thread() ); 235 unlock( lock ); 236 park( ); 237 return; 238 } 239 held = true; 240 unlock( lock ); 241 } 242 243 static inline void unlock(fast_block_lock & this) with(this) { 244 lock( lock __cfaabi_dbg_ctx2 ); 245 /* paranoid */ verifyf( held != false, "Attempt to release lock %p that isn't held", &this ); 246 thread$ * t = &try_pop_front( blocked_threads ); 247 held = ( t ? true : false ); 248 unpark( t ); 249 unlock( lock ); 250 } 251 252 static inline void on_notify(fast_block_lock & this, struct thread$ * t ) { unpark(t); } 253 static inline size_t on_wait(fast_block_lock & this) { unlock(this); return 0; } 254 static inline void on_wakeup(fast_block_lock & this, size_t recursion ) { } 255 256 //----------------------------------------------------------------------------- 201 257 // is_blocking_lock 202 258 trait is_blocking_lock(L & | sized(L)) { … … 226 282 // Synchronization Locks 227 283 forall(L & | is_blocking_lock(L)) { 284 285 //----------------------------------------------------------------------------- 286 // condition_variable 287 288 // The multi-tool condition variable 289 // - can pass timeouts to wait for either a signal or timeout 290 // - can wait without passing a lock 291 // - can have waiters reacquire different locks while waiting on the same cond var 292 // - has shadow queue 293 // - can be signalled outside of critical sections with no locks held 228 294 struct condition_variable { 229 295 // Spin lock used for mutual exclusion … … 258 324 bool wait( condition_variable(L) & this, L & l, Duration duration ); 259 325 bool wait( condition_variable(L) & this, L & l, uintptr_t info, Duration duration ); 260 } 326 327 //----------------------------------------------------------------------------- 328 // fast_cond_var 329 330 // The trimmed and slim condition variable 331 // - no internal lock so you must hold a lock while using this cond var 332 // - signalling without holding branded lock is UNSAFE! 333 // - only allows usage of one lock, cond var is branded after usage 334 struct fast_cond_var { 335 // List of blocked threads 336 dlist( info_thread(L) ) blocked_threads; 337 338 #ifdef __CFA_DEBUG__ 339 L * lock_used; 340 #endif 341 }; 342 343 344 void ?{}( fast_cond_var(L) & this ); 345 void ^?{}( fast_cond_var(L) & this ); 346 347 bool notify_one( fast_cond_var(L) & this ); 348 bool notify_all( fast_cond_var(L) & this ); 349 350 uintptr_t front( fast_cond_var(L) & this ); 351 352 bool empty ( fast_cond_var(L) & this ); 353 354 void wait( fast_cond_var(L) & this, L & l ); 355 void wait( fast_cond_var(L) & this, L & l, uintptr_t info ); 356 }
Note: See TracChangeset
for help on using the changeset viewer.