- File:
-
- 1 edited
-
libcfa/src/concurrency/locks.cfa (modified) (14 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/locks.cfa
r6a8882c rbe73f30 15 15 this.t = t; 16 16 this.lock = 0p; 17 this.listed = false;18 17 } 19 18 … … 22 21 this.info = info; 23 22 this.lock = 0p; 24 this.listed = false;25 23 } 26 24 … … 51 49 } 52 50 53 void ?{}( single_acquisition_lock & this ) {51 void ?{}( mutex_lock & this ) { 54 52 ((blocking_lock &)this){ false, false }; 55 53 } 56 54 57 void ^?{}( single_acquisition_lock & this ) {55 void ^?{}( mutex_lock & this ) { 58 56 // default 59 57 } … … 67 65 } 68 66 69 void ?{}( multiple_acquisition_lock & this ) {67 void ?{}( recursive_mutex_lock & this ) { 70 68 ((blocking_lock &)this){ true, false }; 71 69 } 72 70 73 void ^?{}( multiple_acquisition_lock & this ) {71 void ^?{}( recursive_mutex_lock & this ) { 74 72 // default 75 73 } 76 74 77 75 void lock( blocking_lock & this ) with( this ) { 76 $thread * thrd = active_thread(); 78 77 lock( lock __cfaabi_dbg_ctx2 ); 79 if ( owner == active_thread()&& !multi_acquisition) {78 if ( owner == thrd && !multi_acquisition) { 80 79 fprintf(stderr, "A single acquisition lock holder attempted to reacquire the lock resulting in a deadlock."); // Possibly throw instead 81 exit(EXIT_FAILURE);82 } else if ( owner != 0p && owner != active_thread()) {83 append( blocked_threads, active_thread());80 exit(EXIT_FAILURE); 81 } else if ( owner != 0p && owner != thrd ) { 82 append( blocked_threads, thrd ); 84 83 wait_count++; 85 84 unlock( lock ); 86 park( );87 } else if ( owner == active_thread()&& multi_acquisition ) {85 park( __cfaabi_dbg_ctx ); 86 } else if ( owner == thrd && multi_acquisition ) { 88 87 recursion_count++; 89 88 unlock( lock ); 90 89 } else { 91 owner = active_thread();90 owner = thrd; 92 91 recursion_count = 1; 93 92 unlock( lock ); … … 96 95 97 96 bool try_lock( blocking_lock & this ) with( this ) { 97 $thread * thrd = active_thread(); 98 98 bool ret = false; 99 99 lock( lock __cfaabi_dbg_ctx2 ); 100 100 if ( owner == 0p ) { 101 owner = active_thread();102 recursion_count = 1;101 owner = thrd; 102 if ( multi_acquisition ) recursion_count = 1; 103 103 ret = true; 104 } else if ( owner == active_thread()&& multi_acquisition ) {104 } else if ( owner == thrd && multi_acquisition ) { 105 105 recursion_count++; 106 106 ret = true; … … 113 113 lock( lock __cfaabi_dbg_ctx2 ); 114 114 if ( owner == 0p ){ // no owner implies lock isn't held 115 fprintf( stderr, "There was an attempt to release a lock that isn't held" ); 115 fprintf( stderr, "There was an attempt to release a lock that isn't held" ); 116 116 return; 117 117 } else if ( strict_owner && owner != active_thread() ) { 118 fprintf( stderr, "A thread other than the owner attempted to release an owner lock" ); 118 fprintf( stderr, "A thread other than the owner attempted to release an owner lock" ); 119 119 return; 120 120 } … … 123 123 $thread * thrd = pop_head( blocked_threads ); 124 124 owner = thrd; 125 recursion_count = ( thrd ? 1 : 0 );125 recursion_count = ( thrd && multi_acquisition ? 1 : 0 ); 126 126 wait_count--; 127 unpark( thrd );127 unpark( thrd __cfaabi_dbg_ctx2 ); 128 128 } 129 129 unlock( lock ); … … 151 151 } else { 152 152 owner = t; 153 recursion_count = 1; 154 #if !defined( __CFA_NO_STATISTICS__ ) 155 //kernelTLS.this_stats = t->curr_cluster->stats; 156 #endif 157 unpark( t ); 153 if ( multi_acquisition ) recursion_count = 1; 154 unpark( t __cfaabi_dbg_ctx2 ); 158 155 unlock( lock ); 159 156 } … … 163 160 lock( lock __cfaabi_dbg_ctx2 ); 164 161 if ( owner == 0p ){ // no owner implies lock isn't held 165 fprintf( stderr, "A lock that is not held was passed to a synchronization lock" ); 162 fprintf( stderr, "A lock that is not held was passed to a synchronization lock" ); 166 163 } else if ( strict_owner && owner != active_thread() ) { 167 fprintf( stderr, "A thread other than the owner of a lock passed it to a synchronization lock" ); 164 fprintf( stderr, "A thread other than the owner of a lock passed it to a synchronization lock" ); 168 165 } else { 169 166 $thread * thrd = pop_head( blocked_threads ); 170 167 owner = thrd; 171 recursion_count = ( thrd ? 1 : 0 );168 recursion_count = ( thrd && multi_acquisition ? 1 : 0 ); 172 169 wait_count--; 173 unpark( thrd );170 unpark( thrd __cfaabi_dbg_ctx2 ); 174 171 } 175 172 unlock( lock ); … … 180 177 /////////////////////////////////////////////////////////////////// 181 178 182 // This is temporary until an inheritance bug is fixed 183 184 void lock( single_acquisition_lock & this ){ 179 // In an ideal world this may not be necessary 180 // Is it possible for nominal inheritance to inherit traits?? 181 // If that occurs we would avoid all this extra code 182 183 void lock( mutex_lock & this ){ 185 184 lock( (blocking_lock &)this ); 186 185 } 187 186 188 void unlock( single_acquisition_lock & this ){187 void unlock( mutex_lock & this ){ 189 188 unlock( (blocking_lock &)this ); 190 189 } 191 190 192 void add_( single_acquisition_lock & this, struct $thread * t ){191 void add_( mutex_lock & this, struct $thread * t ){ 193 192 add_( (blocking_lock &)this, t ); 194 193 } 195 194 196 void remove_( single_acquisition_lock & this ){195 void remove_( mutex_lock & this ){ 197 196 remove_( (blocking_lock &)this ); 198 197 } 199 198 200 void set_recursion_count( single_acquisition_lock & this, size_t recursion ){199 void set_recursion_count( mutex_lock & this, size_t recursion ){ 201 200 set_recursion_count( (blocking_lock &)this, recursion ); 202 201 } 203 202 204 size_t get_recursion_count( single_acquisition_lock & this ){205 returnget_recursion_count( (blocking_lock &)this );206 } 207 208 void lock( owner_lock & this ){203 size_t get_recursion_count( mutex_lock & this ){ 204 get_recursion_count( (blocking_lock &)this ); 205 } 206 207 void lock( recursive_mutex_lock & this ){ 209 208 lock( (blocking_lock &)this ); 210 209 } 211 210 212 void unlock( owner_lock & this ){211 void unlock( recursive_mutex_lock & this ){ 213 212 unlock( (blocking_lock &)this ); 214 213 } 215 214 216 void add_( owner_lock & this, struct $thread * t ){215 void add_( recursive_mutex_lock & this, struct $thread * t ){ 217 216 add_( (blocking_lock &)this, t ); 218 217 } 219 218 220 void remove_( owner_lock & this ){219 void remove_( recursive_mutex_lock & this ){ 221 220 remove_( (blocking_lock &)this ); 222 221 } 223 222 224 void set_recursion_count( owner_lock & this, size_t recursion ){223 void set_recursion_count( recursive_mutex_lock & this, size_t recursion ){ 225 224 set_recursion_count( (blocking_lock &)this, recursion ); 226 225 } 227 226 228 size_t get_recursion_count( owner_lock & this ){ 229 return get_recursion_count( (blocking_lock &)this ); 230 } 231 232 void lock( multiple_acquisition_lock & this ){ 233 lock( (blocking_lock &)this ); 234 } 235 236 void unlock( multiple_acquisition_lock & this ){ 237 unlock( (blocking_lock &)this ); 238 } 239 240 void add_( multiple_acquisition_lock & this, struct $thread * t ){ 241 add_( (blocking_lock &)this, t ); 242 } 243 244 void remove_( multiple_acquisition_lock & this ){ 245 remove_( (blocking_lock &)this ); 246 } 247 248 void set_recursion_count( multiple_acquisition_lock & this, size_t recursion ){ 249 set_recursion_count( (blocking_lock &)this, recursion ); 250 } 251 252 size_t get_recursion_count( multiple_acquisition_lock & this ){ 253 return get_recursion_count( (blocking_lock &)this ); 254 } 255 256 /////////////////////////////////////////////////////////////////// 257 //// condition variable 227 size_t get_recursion_count( recursive_mutex_lock & this ){ 228 get_recursion_count( (blocking_lock &)this ); 229 } 230 231 /////////////////////////////////////////////////////////////////// 232 //// Synchronization Locks 258 233 /////////////////////////////////////////////////////////////////// 259 234 260 235 forall(dtype L | is_blocking_lock(L)) { 261 262 void timeout_handler ( alarm_node_wrap(L) & this ) with( this ) { 263 // This condition_variable member is called from the kernel, and therefore, cannot block, but it can spin. 264 lock( cond->lock __cfaabi_dbg_ctx2 ); 265 if ( (*i)->listed ) { // is thread on queue 266 info_thread(L) * copy = *i; 267 remove( cond->blocked_threads, i ); //remove this thread O(1) 268 cond->count--; 269 if( !copy->lock ) { 270 #if !defined( __CFA_NO_STATISTICS__ ) 271 //kernelTLS.this_stats = copy->t->curr_cluster->stats; 272 #endif 273 unpark( copy->t ); 274 } else { 275 add_(*copy->lock, copy->t); // call lock's add_ 276 } 277 } 278 unlock( cond->lock ); 279 } 280 281 void alarm_node_wrap_cast( alarm_node_t & a ) { 282 timeout_handler( (alarm_node_wrap(L) &)a ); 283 } 284 285 void ?{}( condition_variable(L) & this ){ 236 void ?{}( synchronization_lock(L) & this, bool reacquire_after_signal ){ 286 237 this.lock{}; 287 238 this.blocked_threads{}; 288 239 this.count = 0; 240 this.reacquire_after_signal = reacquire_after_signal; 241 } 242 243 void ^?{}( synchronization_lock(L) & this ){ 244 // default 245 } 246 247 void ?{}( condition_variable(L) & this ){ 248 ((synchronization_lock(L) &)this){ true }; 289 249 } 290 250 … … 293 253 } 294 254 295 void ?{}( alarm_node_wrap(L) & this, $thread * thrd, Time alarm, Duration period, Alarm_Callback callback ){296 this.alarm_node{ thrd, alarm, period, callback};297 } 298 299 void ^?{}( alarm_node_wrap(L) & this ){300 // default 301 } 302 303 bool notify_one( condition_variable(L) & this ) with( this ) {255 void ?{}( thread_queue(L) & this ){ 256 ((synchronization_lock(L) &)this){ false }; 257 } 258 259 void ^?{}( thread_queue(L) & this ){ 260 // default 261 } 262 263 bool notify_one( synchronization_lock(L) & this ) with( this ) { 304 264 lock( lock __cfaabi_dbg_ctx2 ); 305 265 bool ret = !!blocked_threads; 306 266 info_thread(L) * popped = pop_head( blocked_threads ); 307 267 if(popped != 0p) { 308 popped->listed = false; 309 count--; 310 if (popped->lock) { 268 if( reacquire_after_signal ){ 311 269 add_(*popped->lock, popped->t); 312 270 } else { 313 unpark(popped->t); 271 unpark( 272 popped->t __cfaabi_dbg_ctx2 273 ); 314 274 } 315 275 } … … 318 278 } 319 279 320 bool notify_all( condition_variable(L) & this ) with(this) {280 bool notify_all( synchronization_lock(L) & this ) with(this) { 321 281 lock( lock __cfaabi_dbg_ctx2 ); 322 282 bool ret = blocked_threads ? true : false; … … 324 284 info_thread(L) * popped = pop_head( blocked_threads ); 325 285 if(popped != 0p){ 326 popped->listed = false; 327 count--; 328 if (popped->lock) { 286 if( reacquire_after_signal ){ 329 287 add_(*popped->lock, popped->t); 330 288 } else { 331 unpark(popped->t); 289 unpark( 290 popped->t __cfaabi_dbg_ctx2 291 ); 332 292 } 333 293 } … … 337 297 } 338 298 339 uintptr_t front( condition_variable(L) & this ) with(this) { 340 if(!blocked_threads) return NULL; 341 return peek(blocked_threads)->info; 342 } 343 344 bool empty( condition_variable(L) & this ) with(this) { 299 uintptr_t front( synchronization_lock(L) & this ) with(this) { 300 return (*peek(blocked_threads)).info; 301 } 302 303 bool empty( synchronization_lock(L) & this ) with(this) { 345 304 return blocked_threads ? false : true; 346 305 } 347 306 348 int counter( condition_variable(L) & this ) with(this) {307 int counter( synchronization_lock(L) & this ) with(this) { 349 308 return count; 350 309 } 351 310 352 // helper for wait()'s' without a timeout 353 void queue_info_thread( condition_variable(L) & this, info_thread(L) & i ) with(this) { 311 void queue_info_thread( synchronization_lock(L) & this, info_thread(L) & i ) with(this) { 312 lock( lock __cfaabi_dbg_ctx2 ); 313 append( blocked_threads, &i ); 314 count++; 315 unlock( lock ); 316 park( __cfaabi_dbg_ctx ); 317 } 318 319 320 void wait( synchronization_lock(L) & this ) with(this) { 321 info_thread( L ) i = { active_thread() }; 322 queue_info_thread( this, i ); 323 } 324 325 void wait( synchronization_lock(L) & this, uintptr_t info ) with(this) { 326 info_thread( L ) i = { active_thread(), info }; 327 queue_info_thread( this, i ); 328 } 329 // I still need to implement the time delay wait routines 330 bool wait( synchronization_lock(L) & this, Duration duration ) with(this) { 331 timeval tv = { time(0) }; 332 Time t = { tv }; 333 return wait( this, t + duration ); 334 } 335 336 bool wait( synchronization_lock(L) & this, uintptr_t info, Duration duration ) with(this) { 337 // TODO: ADD INFO 338 return wait( this, duration ); 339 } 340 341 bool wait( synchronization_lock(L) & this, Time time ) with(this) { 342 return false; //default 343 } 344 345 bool wait( synchronization_lock(L) & this, uintptr_t info, Time time ) with(this) { 346 // TODO: ADD INFO 347 return wait( this, time ); 348 } 349 350 void queue_info_thread_unlock( synchronization_lock(L) & this, L & l, info_thread(L) & i ) with(this) { 354 351 lock( lock __cfaabi_dbg_ctx2 ); 355 352 append( this.blocked_threads, &i ); 356 353 count++; 357 i.listed = true; 358 size_t recursion_count; 359 if (i.lock) { 360 recursion_count = get_recursion_count(*i.lock); 361 remove_( *i.lock ); 362 } 363 364 unlock( lock ); 365 park( ); // blocks here 366 367 if (i.lock) set_recursion_count(*i.lock, recursion_count); // resets recursion count here after waking 368 } 369 370 // helper for wait()'s' with a timeout 371 void queue_info_thread_timeout( condition_variable(L) & this, info_thread(L) & info, Time t ) with(this) { 372 lock( lock __cfaabi_dbg_ctx2 ); 373 374 info_thread(L) * queue_ptr = &info; 375 376 alarm_node_wrap(L) node_wrap = { info.t, t, 0`s, alarm_node_wrap_cast }; 377 node_wrap.cond = &this; 378 node_wrap.i = &queue_ptr; 379 380 register_self( &node_wrap.alarm_node ); 381 382 append( blocked_threads, queue_ptr ); 383 info.listed = true; 384 count++; 385 386 size_t recursion_count; 387 if (info.lock) { 388 recursion_count = get_recursion_count(*info.lock); 389 remove_( *info.lock ); 390 } 391 392 unlock( lock ); 393 park(); 394 395 if (info.lock) set_recursion_count(*info.lock, recursion_count); 396 } 397 398 void wait( condition_variable(L) & this ) with(this) { 399 info_thread( L ) i = { active_thread() }; 400 queue_info_thread( this, i ); 401 } 402 403 void wait( condition_variable(L) & this, uintptr_t info ) with(this) { 404 info_thread( L ) i = { active_thread(), info }; 405 queue_info_thread( this, i ); 406 } 407 408 void wait( condition_variable(L) & this, Duration duration ) with(this) { 409 info_thread( L ) i = { active_thread() }; 410 queue_info_thread_timeout(this, i, __kernel_get_time() + duration ); 411 } 412 413 void wait( condition_variable(L) & this, uintptr_t info, Duration duration ) with(this) { 414 info_thread( L ) i = { active_thread(), info }; 415 queue_info_thread_timeout(this, i, __kernel_get_time() + duration ); 416 } 417 418 void wait( condition_variable(L) & this, Time time ) with(this) { 419 info_thread( L ) i = { active_thread() }; 420 queue_info_thread_timeout(this, i, time); 421 } 422 423 void wait( condition_variable(L) & this, uintptr_t info, Time time ) with(this) { 424 info_thread( L ) i = { active_thread(), info }; 425 queue_info_thread_timeout(this, i, time); 426 } 427 428 void wait( condition_variable(L) & this, L & l ) with(this) { 354 i.lock = &l; 355 size_t recursion_count = get_recursion_count(l); 356 remove_( l ); 357 unlock( lock ); 358 park( __cfaabi_dbg_ctx ); // blocks here 359 360 set_recursion_count(l, recursion_count); // resets recursion count here after waking 361 } 362 363 void wait( synchronization_lock(L) & this, L & l ) with(this) { 429 364 info_thread(L) i = { active_thread() }; 430 i.lock = &l; 431 queue_info_thread( this, i ); 432 } 433 434 void wait( condition_variable(L) & this, L & l, uintptr_t info ) with(this) { 365 queue_info_thread_unlock( this, l, i ); 366 } 367 368 void wait( synchronization_lock(L) & this, L & l, uintptr_t info ) with(this) { 435 369 info_thread(L) i = { active_thread(), info }; 436 i.lock = &l; 437 queue_info_thread( this, i ); 438 } 439 440 void wait( condition_variable(L) & this, L & l, Duration duration ) with(this) { 441 info_thread(L) i = { active_thread() }; 442 i.lock = &l; 443 queue_info_thread_timeout(this, i, __kernel_get_time() + duration ); 444 } 445 446 void wait( condition_variable(L) & this, L & l, uintptr_t info, Duration duration ) with(this) { 447 info_thread(L) i = { active_thread(), info }; 448 i.lock = &l; 449 queue_info_thread_timeout(this, i, __kernel_get_time() + duration ); 450 } 451 452 void wait( condition_variable(L) & this, L & l, Time time ) with(this) { 453 info_thread(L) i = { active_thread() }; 454 i.lock = &l; 455 queue_info_thread_timeout(this, i, time ); 456 } 457 458 void wait( condition_variable(L) & this, L & l, uintptr_t info, Time time ) with(this) { 459 info_thread(L) i = { active_thread(), info }; 460 i.lock = &l; 461 queue_info_thread_timeout(this, i, time ); 462 } 463 } 464 465 // thread T1 {}; 466 // thread T2 {}; 467 468 // multiple_acquisition_lock m; 469 // condition_variable( multiple_acquisition_lock ) c; 470 471 // void main( T1 & this ) { 472 // printf("T1 start\n"); 473 // lock(m); 474 // printf("%d\n", counter(c)); 475 // if(empty(c)) { 476 // printf("T1 wait\n"); 477 // wait(c,m,12); 478 // }else{ 479 // printf("%d\n", front(c)); 480 // notify_one(c); 481 // } 482 // unlock(m); 483 // printf("curr thd in main %p \n", active_thread()); 484 // printf("T1 waits for 2s\n"); 485 // lock(m); 486 // wait( c, m, 2`s ); 487 // unlock(m); 488 // printf("T1 wakes\n"); 489 // printf("T1 done\n"); 490 // } 491 492 // void main( T2 & this ) { 493 // printf("T2 start\n"); 494 // lock(m); 495 // printf("%d\n", counter(c)); 496 // if(empty(c)) { 497 // printf("T2 wait\n"); 498 // wait(c,m,12); 499 // }else{ 500 // printf("%d\n", front(c)); 501 // notify_one(c); 502 // } 503 // unlock(m); 504 // printf("T2 done\n"); 505 // } 506 507 // int main() { 508 // printf("start\n"); 509 // processor p[2]; 510 // { 511 // T1 t1; 512 // T2 t2; 513 // } 514 // printf("done\n"); 515 // } 370 queue_info_thread_unlock( this, l, i ); 371 } 372 373 bool wait( synchronization_lock(L) & this, L & l, Duration duration ) with(this) { 374 timeval tv = { time(0) }; 375 Time t = { tv }; 376 return wait( this, l, t + duration ); 377 } 378 379 bool wait( synchronization_lock(L) & this, L & l, uintptr_t info, Duration duration ) with(this) { 380 // TODO: ADD INFO 381 return wait( this, l, duration ); 382 } 383 384 bool wait( synchronization_lock(L) & this, L & l, Time time ) with(this) { 385 return false; //default 386 } 387 388 bool wait( synchronization_lock(L) & this, L & l, uintptr_t info, Time time ) with(this) { 389 // TODO: ADD INFO 390 return wait( this, l, time ); 391 } 392 } 393 394 /////////////////////////////////////////////////////////////////// 395 //// condition lock alternative approach 396 /////////////////////////////////////////////////////////////////// 397 398 // the solution below is less efficient but does not require the lock to have a specific add/remove routine 399 400 /////////////////////////////////////////////////////////////////// 401 //// is_simple_lock 402 /////////////////////////////////////////////////////////////////// 403 404 forall(dtype L | is_simple_lock(L)) { 405 void ?{}( condition_lock(L) & this ){ 406 // default 407 } 408 409 void ^?{}( condition_lock(L) & this ){ 410 // default 411 } 412 413 bool notify_one( condition_lock(L) & this ) with(this) { 414 return notify_one( c_var ); 415 } 416 417 bool notify_all( condition_lock(L) & this ) with(this) { 418 return notify_all( c_var ); 419 } 420 421 void wait( condition_lock(L) & this, L & l ) with(this) { 422 lock( m_lock ); 423 size_t recursion = get_recursion_count( l ); 424 unlock( l ); 425 wait( c_var, m_lock ); 426 lock( l ); 427 set_recursion_count( l , recursion ); 428 unlock( m_lock ); 429 } 430 }
Note:
See TracChangeset
for help on using the changeset viewer.