Changeset cad1df1 for libcfa/src
- Timestamp:
- Dec 3, 2020, 4:24:36 PM (4 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 4aeaee5, c74e601
- Parents:
- aeb31b1
- Location:
- libcfa/src/concurrency
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/locks.cfa
raeb31b1 rcad1df1 11 11 //// info_thread 12 12 /////////////////////////////////////////////////////////////////// 13 13 14 forall(dtype L | is_blocking_lock(L)) { 14 15 void ?{}( info_thread(L) & this, $thread * t ) { 16 ((Seqable &) this){}; 15 17 this.t = t; 16 18 this.lock = 0p; … … 19 21 20 22 void ?{}( info_thread(L) & this, $thread * t, uintptr_t info ) { 23 ((Seqable &) this){}; 21 24 this.t = t; 22 25 this.info = info; … … 25 28 } 26 29 27 void ^?{}( info_thread(L) & this ){ 28 // default 29 } 30 31 info_thread(L) *& get_next( info_thread(L) & this ) { 32 return this.next; 33 } 34 } 30 void ^?{}( info_thread(L) & this ){ } 31 } 32 35 33 /////////////////////////////////////////////////////////////////// 36 34 //// Blocking Locks … … 47 45 } 48 46 49 void ^?{}( blocking_lock & this ) { 50 // default 51 } 52 53 void ?{}( single_acquisition_lock & this ) { 54 ((blocking_lock &)this){ false, false }; 55 } 56 57 void ^?{}( single_acquisition_lock & this ) { 58 // default 59 } 60 61 void ?{}( owner_lock & this ) { 62 ((blocking_lock &)this){ true, true }; 63 } 64 65 void ^?{}( owner_lock & this ) { 66 // default 67 } 68 69 void ?{}( multiple_acquisition_lock & this ) { 70 ((blocking_lock &)this){ true, false }; 71 } 72 73 void ^?{}( multiple_acquisition_lock & this ) { 74 // default 75 } 47 void ^?{}( blocking_lock & this ) {} 48 void ?{}( single_acquisition_lock & this ) {((blocking_lock &)this){ false, false };} 49 void ^?{}( single_acquisition_lock & this ) {} 50 void ?{}( owner_lock & this ) {((blocking_lock &)this){ true, true };} 51 void ^?{}( owner_lock & this ) {} 52 void ?{}( multiple_acquisition_lock & this ) {((blocking_lock &)this){ true, false };} 53 void ^?{}( multiple_acquisition_lock & this ) {} 76 54 77 55 void lock( blocking_lock & this ) with( this ) { 78 56 lock( lock __cfaabi_dbg_ctx2 ); 79 57 if ( owner == active_thread() && !multi_acquisition) { 80 fprintf(stderr, "A single acquisition lock holder attempted to reacquire the lock resulting in a deadlock."); // Possibly throw instead 81 exit(EXIT_FAILURE); 58 abort("A single acquisition lock holder attempted to reacquire the lock resulting in a deadlock."); 82 59 } else if ( owner != 0p && owner != active_thread() ) { 83 60 append( blocked_threads, active_thread() ); … … 110 87 } 111 88 89 void unlock_error_check( blocking_lock & this ) with( this ) { 90 if ( owner == 0p ){ // no owner implies lock isn't held 91 abort( "There was an attempt to release a lock that isn't held" ); 92 } else if ( strict_owner && owner != active_thread() ) { 93 abort( "A thread other than the owner attempted to release an owner lock" ); 94 } 95 } 96 97 void pop_and_set_new_owner( blocking_lock & this ) with( this ) { 98 $thread * t = pop_head( blocked_threads ); 99 owner = t; 100 recursion_count = ( t ? 1 : 0 ); 101 wait_count--; 102 unpark( t ); 103 } 104 112 105 void unlock( blocking_lock & this ) with( this ) { 113 106 lock( lock __cfaabi_dbg_ctx2 ); 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" ); 116 return; 117 } else if ( strict_owner && owner != active_thread() ) { 118 fprintf( stderr, "A thread other than the owner attempted to release an owner lock" ); 119 return; 120 } 107 unlock_error_check( this ); 121 108 recursion_count--; 122 109 if ( recursion_count == 0 ) { 123 $thread * thrd = pop_head( blocked_threads ); 124 owner = thrd; 125 recursion_count = ( thrd ? 1 : 0 ); 126 wait_count--; 127 unpark( thrd ); 110 pop_and_set_new_owner( this ); 128 111 } 129 112 unlock( lock ); … … 133 116 return wait_count; 134 117 } 135 136 118 137 119 void set_recursion_count( blocking_lock & this, size_t recursion ) with( this ) { … … 152 134 owner = t; 153 135 recursion_count = 1; 154 #if !defined( __CFA_NO_STATISTICS__ )155 //kernelTLS.this_stats = t->curr_cluster->stats;156 #endif157 136 unpark( t ); 158 137 unlock( lock ); … … 162 141 void remove_( blocking_lock & this ) with( this ) { 163 142 lock( lock __cfaabi_dbg_ctx2 ); 164 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" ); 166 } 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" ); 168 } else { 169 $thread * thrd = pop_head( blocked_threads ); 170 owner = thrd; 171 recursion_count = ( thrd ? 1 : 0 ); 172 wait_count--; 173 unpark( thrd ); 174 } 143 unlock_error_check( this ); 144 pop_and_set_new_owner( this ); 175 145 unlock( lock ); 176 146 } … … 182 152 // This is temporary until an inheritance bug is fixed 183 153 184 void lock( single_acquisition_lock & this ){ 185 lock( (blocking_lock &)this ); 186 } 187 188 void unlock( single_acquisition_lock & this ){ 189 unlock( (blocking_lock &)this ); 190 } 191 192 void add_( single_acquisition_lock & this, struct $thread * t ){ 193 add_( (blocking_lock &)this, t ); 194 } 195 196 void remove_( single_acquisition_lock & this ){ 197 remove_( (blocking_lock &)this ); 198 } 199 200 void set_recursion_count( single_acquisition_lock & this, size_t recursion ){ 201 set_recursion_count( (blocking_lock &)this, recursion ); 202 } 203 204 size_t get_recursion_count( single_acquisition_lock & this ){ 205 return get_recursion_count( (blocking_lock &)this ); 206 } 207 208 void lock( owner_lock & this ){ 209 lock( (blocking_lock &)this ); 210 } 211 212 void unlock( owner_lock & this ){ 213 unlock( (blocking_lock &)this ); 214 } 215 216 void add_( owner_lock & this, struct $thread * t ){ 217 add_( (blocking_lock &)this, t ); 218 } 219 220 void remove_( owner_lock & this ){ 221 remove_( (blocking_lock &)this ); 222 } 223 224 void set_recursion_count( owner_lock & this, size_t recursion ){ 225 set_recursion_count( (blocking_lock &)this, recursion ); 226 } 227 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 } 154 void lock( single_acquisition_lock & this ){ lock( (blocking_lock &)this ); } 155 void unlock( single_acquisition_lock & this ){ unlock( (blocking_lock &)this ); } 156 void add_( single_acquisition_lock & this, struct $thread * t ){ add_( (blocking_lock &)this, t ); } 157 void remove_( single_acquisition_lock & this ){ remove_( (blocking_lock &)this ); } 158 void set_recursion_count( single_acquisition_lock & this, size_t recursion ){ set_recursion_count( (blocking_lock &)this, recursion ); } 159 size_t get_recursion_count( single_acquisition_lock & this ){ return get_recursion_count( (blocking_lock &)this ); } 160 161 void lock( owner_lock & this ){ lock( (blocking_lock &)this ); } 162 void unlock( owner_lock & this ){ unlock( (blocking_lock &)this ); } 163 void add_( owner_lock & this, struct $thread * t ){ add_( (blocking_lock &)this, t ); } 164 void remove_( owner_lock & this ){ remove_( (blocking_lock &)this ); } 165 void set_recursion_count( owner_lock & this, size_t recursion ){ set_recursion_count( (blocking_lock &)this, recursion ); } 166 size_t get_recursion_count( owner_lock & this ){ return get_recursion_count( (blocking_lock &)this ); } 167 168 void lock( multiple_acquisition_lock & this ){ lock( (blocking_lock &)this ); } 169 void unlock( multiple_acquisition_lock & this ){ unlock( (blocking_lock &)this ); } 170 void add_( multiple_acquisition_lock & this, struct $thread * t ){ add_( (blocking_lock &)this, t ); } 171 void remove_( multiple_acquisition_lock & this ){ remove_( (blocking_lock &)this ); } 172 void set_recursion_count( multiple_acquisition_lock & this, size_t recursion ){ set_recursion_count( (blocking_lock &)this, recursion ); } 173 size_t get_recursion_count( multiple_acquisition_lock & this ){ return get_recursion_count( (blocking_lock &)this ); } 255 174 256 175 /////////////////////////////////////////////////////////////////// … … 263 182 // This condition_variable member is called from the kernel, and therefore, cannot block, but it can spin. 264 183 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) 184 185 if ( i->listed ) { // is thread on queue 186 cond->last_thread = i; // REMOVE THIS AFTER DEBUG 187 remove( cond->blocked_threads, *i ); //remove this thread O(1) 268 188 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 ); 189 if( !i->lock ) { 190 unpark( i->t ); 274 191 } else { 275 add_(* copy->lock, copy->t); // call lock's add_192 add_(*i->lock, i->t); // call lock's add_ 276 193 } 277 194 } … … 279 196 } 280 197 281 void alarm_node_wrap_cast( alarm_node_t & a ) { 282 timeout_handler( (alarm_node_wrap(L) &)a ); 283 } 198 void alarm_node_wrap_cast( alarm_node_t & a ) { timeout_handler( (alarm_node_wrap(L) &)a ); } 284 199 285 200 void ?{}( condition_variable(L) & this ){ … … 287 202 this.blocked_threads{}; 288 203 this.count = 0; 289 } 290 291 void ^?{}( condition_variable(L) & this ){ 292 // default 293 } 204 this.last_thread = 0p; // REMOVE AFTER DEBUG 205 } 206 207 void ^?{}( condition_variable(L) & this ){ } 294 208 295 209 void ?{}( alarm_node_wrap(L) & this, $thread * thrd, Time alarm, Duration period, Alarm_Callback callback ) { … … 297 211 } 298 212 299 void ^?{}( alarm_node_wrap(L) & this ) { 300 // default 213 void ^?{}( alarm_node_wrap(L) & this ) { } 214 215 void process_popped( condition_variable(L) & this, info_thread(L) & popped ) with( this ) { 216 if(&popped != 0p) { 217 popped.listed = false; 218 count--; 219 if (popped.lock) { 220 add_(*popped.lock, popped.t); 221 } else { 222 unpark(popped.t); 223 } 224 } 301 225 } 302 226 303 227 bool notify_one( condition_variable(L) & this ) with( this ) { 304 228 lock( lock __cfaabi_dbg_ctx2 ); 305 bool ret = !!blocked_threads; 306 info_thread(L) * popped = pop_head( blocked_threads ); 307 if(popped != 0p) { 308 popped->listed = false; 309 count--; 310 if (popped->lock) { 311 add_(*popped->lock, popped->t); 312 } else { 313 unpark(popped->t); 314 } 315 } 229 bool ret = !empty(blocked_threads); 230 process_popped(this, dropHead( blocked_threads )); 316 231 unlock( lock ); 317 232 return ret; … … 320 235 bool notify_all( condition_variable(L) & this ) with(this) { 321 236 lock( lock __cfaabi_dbg_ctx2 ); 322 bool ret = blocked_threads ? true : false; 323 while( blocked_threads ) { 324 info_thread(L) * popped = pop_head( blocked_threads ); 325 if(popped != 0p){ 326 popped->listed = false; 327 count--; 328 if (popped->lock) { 329 add_(*popped->lock, popped->t); 330 } else { 331 unpark(popped->t); 332 } 333 } 237 bool ret = !empty(blocked_threads); 238 while( !empty(blocked_threads) ) { 239 process_popped(this, dropHead( blocked_threads )); 334 240 } 335 241 unlock( lock ); … … 338 244 339 245 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) { 345 return blocked_threads ? false : true; 346 } 347 348 int counter( condition_variable(L) & this ) with(this) { 349 return count; 350 } 351 352 // helper for wait()'s' without a timeout 246 return empty(blocked_threads) ? NULL : head(blocked_threads).info; 247 } 248 249 bool empty( condition_variable(L) & this ) with(this) { return empty(blocked_threads); } 250 251 int counter( condition_variable(L) & this ) with(this) { return count; } 252 253 size_t queue_and_get_recursion( condition_variable(L) & this, info_thread(L) * i ) with(this) { 254 addTail( blocked_threads, *i ); 255 count++; 256 i->listed = true; 257 size_t recursion_count = 0; 258 if (i->lock) { 259 i->t->link.next = 1p; 260 recursion_count = get_recursion_count(*i->lock); 261 remove_( *i->lock ); 262 } 263 return recursion_count; 264 } 265 266 // helper for wait()'s' with no timeout 353 267 void queue_info_thread( condition_variable(L) & this, info_thread(L) & i ) with(this) { 354 268 lock( lock __cfaabi_dbg_ctx2 ); 355 append( this.blocked_threads, &i ); 356 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 269 size_t recursion_count = queue_and_get_recursion(this, &i); 364 270 unlock( lock ); 365 271 park( ); // blocks here 366 367 272 if (i.lock) set_recursion_count(*i.lock, recursion_count); // resets recursion count here after waking 368 273 } … … 371 276 void queue_info_thread_timeout( condition_variable(L) & this, info_thread(L) & info, Time t ) with(this) { 372 277 lock( lock __cfaabi_dbg_ctx2 ); 373 374 info_thread(L) * queue_ptr = &info; 375 278 size_t recursion_count = queue_and_get_recursion(this, &info); 376 279 alarm_node_wrap(L) node_wrap = { info.t, t, 0`s, alarm_node_wrap_cast }; 377 280 node_wrap.cond = &this; 378 node_wrap.i = &queue_ptr; 379 281 node_wrap.i = &info; 380 282 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 283 unlock( lock ); 393 284 park(); 394 285 unregister_self( &node_wrap.alarm_node ); 395 286 if (info.lock) set_recursion_count(*info.lock, recursion_count); 396 287 } … … 462 353 } 463 354 } 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 // } -
libcfa/src/concurrency/locks.hfa
raeb31b1 rcad1df1 5 5 #include "bits/algorithm.hfa" 6 6 #include "bits/locks.hfa" 7 #include "bits/sequence.hfa" 7 8 #include "bits/containers.hfa" 8 9 … … 31 32 forall(dtype L | is_blocking_lock(L)) { 32 33 struct info_thread { 34 inline Seqable; 33 35 struct $thread * t; 34 36 uintptr_t info; 35 info_thread(L) * next;36 37 L * lock; 37 38 bool listed; // true if info_thread is on queue, false otherwise; … … 42 43 void ?{}( info_thread(L) & this, $thread * t, uintptr_t info ); 43 44 void ^?{}( info_thread(L) & this ); 44 45 info_thread(L) *& get_next( info_thread(L) & this );46 45 } 47 46 … … 50 49 /////////////////////////////////////////////////////////////////// 51 50 51 // struct lock_thread { 52 // struct $thread * t; 53 // lock_thread * next; 54 // }; 55 56 // void ?{}( lock_thread & this, struct $thread * thd ); 57 // void ^?{}( lock_thread & this ); 58 59 // lock_thread *& get_next( lock_thread & ); 60 52 61 struct blocking_lock { 53 62 // Spin lock used for mutual exclusion … … 55 64 56 65 // List of blocked threads 57 __queue_t( struct$thread ) blocked_threads;66 __queue_t( $thread ) blocked_threads; 58 67 59 68 // Count of current blocked threads … … 135 144 __spinlock_t lock; 136 145 146 info_thread(L) * last_thread; 147 137 148 // List of blocked threads 138 __queue_t( info_thread(L) ) blocked_threads;149 Sequence( info_thread(L) ) blocked_threads; 139 150 140 151 // Count of current blocked threads … … 150 161 condition_variable(L) * cond; 151 162 152 info_thread(L) * *i;163 info_thread(L) * i; 153 164 }; 154 165
Note: See TracChangeset
for help on using the changeset viewer.