Changeset 58fe85a for libcfa/src/concurrency/monitor.cfa
- Timestamp:
- Jan 7, 2021, 3:27:00 PM (5 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 2b4daf2, 64aeca0
- Parents:
- 3c64c668 (diff), eef8dfb (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/monitor.cfa
r3c64c668 r58fe85a 82 82 // Enter single monitor 83 83 static void __enter( $monitor * this, const __monitor_group_t & group ) { 84 $thread * thrd = active_thread(); 85 84 86 // Lock the monitor spinlock 85 87 lock( this->lock __cfaabi_dbg_ctx2 ); 86 // Interrupts disable inside critical section87 $thread * thrd = kernelTLS.this_thread;88 88 89 89 __cfaabi_dbg_print_safe( "Kernel : %10p Entering mon %p (%p)\n", thrd, this, this->owner); 90 90 91 if( !this->owner ) { 91 if( unlikely(0 != (0x1 & (uintptr_t)this->owner)) ) { 92 abort( "Attempt by thread \"%.256s\" (%p) to access joined monitor %p.", thrd->self_cor.name, thrd, this ); 93 } 94 else if( !this->owner ) { 92 95 // No one has the monitor, just take it 93 96 __set_owner( this, thrd ); … … 114 117 115 118 // Some one else has the monitor, wait in line for it 116 /* paranoid */ verify( thrd-> next == 0p );119 /* paranoid */ verify( thrd->link.next == 0p ); 117 120 append( this->entry_queue, thrd ); 118 /* paranoid */ verify( thrd-> next == 1p );121 /* paranoid */ verify( thrd->link.next == 1p ); 119 122 120 123 unlock( this->lock ); … … 123 126 __cfaabi_dbg_print_safe( "Kernel : %10p Entered mon %p\n", thrd, this); 124 127 125 /* paranoid */ verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );128 /* paranoid */ verifyf( active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this ); 126 129 return; 127 130 } … … 129 132 __cfaabi_dbg_print_safe( "Kernel : %10p Entered mon %p\n", thrd, this); 130 133 131 /* paranoid */ verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );134 /* paranoid */ verifyf( active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this ); 132 135 /* paranoid */ verify( this->lock.lock ); 133 136 … … 137 140 } 138 141 139 static void __dtor_enter( $monitor * this, fptr_t func ) { 142 static void __dtor_enter( $monitor * this, fptr_t func, bool join ) { 143 $thread * thrd = active_thread(); 144 #if defined( __CFA_WITH_VERIFY__ ) 145 bool is_thrd = this == &thrd->self_mon; 146 #endif 147 140 148 // Lock the monitor spinlock 141 149 lock( this->lock __cfaabi_dbg_ctx2 ); 142 // Interrupts disable inside critical section143 $thread * thrd = kernelTLS.this_thread;144 150 145 151 __cfaabi_dbg_print_safe( "Kernel : %10p Entering dtor for mon %p (%p)\n", thrd, this, this->owner); … … 152 158 __set_owner( this, thrd ); 153 159 154 verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this ); 160 /* paranoid */ verifyf( active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this ); 161 /* paranoid */ verify( !is_thrd || thrd->state == Halted || thrd->state == Cancelled ); 155 162 156 163 unlock( this->lock ); 157 164 return; 158 165 } 159 else if( this->owner == thrd ) {166 else if( this->owner == thrd && !join) { 160 167 // We already have the monitor... but where about to destroy it so the nesting will fail 161 168 // Abort! 162 169 abort( "Attempt to destroy monitor %p by thread \"%.256s\" (%p) in nested mutex.", this, thrd->self_cor.name, thrd ); 163 170 } 171 // SKULLDUGGERY: join will act as a dtor so it would normally trigger to above check 172 // because join will not release the monitor after it executed. 173 // to avoid that it sets the owner to the special value thrd | 1p before exiting 174 else if( this->owner == ($thread*)(1 | (uintptr_t)thrd) ) { 175 // restore the owner and just return 176 __cfaabi_dbg_print_safe( "Kernel : Destroying free mon %p\n", this); 177 178 // No one has the monitor, just take it 179 __set_owner( this, thrd ); 180 181 /* paranoid */ verifyf( active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this ); 182 /* paranoid */ verify( !is_thrd || thrd->state == Halted || thrd->state == Cancelled ); 183 184 unlock( this->lock ); 185 return; 186 } 187 188 // The monitor is busy, if this is a thread and the thread owns itself, it better be active 189 /* paranoid */ verify( !is_thrd || this->owner != thrd || (thrd->state != Halted && thrd->state != Cancelled) ); 164 190 165 191 __lock_size_t count = 1; … … 183 209 184 210 // Release the next thread 185 /* paranoid */ verifyf( urgent->owner->waiting_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );211 /* paranoid */ verifyf( urgent->owner->waiting_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this ); 186 212 unpark( urgent->owner->waiting_thread ); 187 213 … … 190 216 191 217 // Some one was waiting for us, enter 192 /* paranoid */ verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this ); 218 /* paranoid */ verifyf( active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this ); 219 220 __cfaabi_dbg_print_safe( "Kernel : Destroying %p\n", this); 221 return; 193 222 } 194 223 else { … … 199 228 200 229 // Some one else has the monitor, wait in line for it 201 /* paranoid */ verify( thrd-> next == 0p );230 /* paranoid */ verify( thrd->link.next == 0p ); 202 231 append( this->entry_queue, thrd ); 203 /* paranoid */ verify( thrd-> next == 1p );232 /* paranoid */ verify( thrd->link.next == 1p ); 204 233 unlock( this->lock ); 205 234 … … 207 236 park(); 208 237 209 /* paranoid */ verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );238 /* paranoid */ verifyf( active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this ); 210 239 return; 211 240 } 212 213 __cfaabi_dbg_print_safe( "Kernel : Destroying %p\n", this);214 215 241 } 216 242 … … 220 246 lock( this->lock __cfaabi_dbg_ctx2 ); 221 247 222 __cfaabi_dbg_print_safe( "Kernel : %10p Leaving mon %p (%p)\n", kernelTLS.this_thread, this, this->owner);223 224 /* paranoid */ verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );248 __cfaabi_dbg_print_safe( "Kernel : %10p Leaving mon %p (%p)\n", active_thread(), this, this->owner); 249 250 /* paranoid */ verifyf( active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this ); 225 251 226 252 // Leaving a recursion level, decrement the counter … … 251 277 252 278 // Leave single monitor for the last time 253 void __dtor_leave( $monitor * this ) {279 void __dtor_leave( $monitor * this, bool join ) { 254 280 __cfaabi_dbg_debug_do( 255 if( TL_GET( this_thread) != this->owner ) {256 abort( "Destroyed monitor %p has inconsistent owner, expected %p got %p.\n", this, TL_GET( this_thread), this->owner);281 if( active_thread() != this->owner ) { 282 abort( "Destroyed monitor %p has inconsistent owner, expected %p got %p.\n", this, active_thread(), this->owner); 257 283 } 258 if( this->recursion != 1 ) {284 if( this->recursion != 1 && !join ) { 259 285 abort( "Destroyed monitor %p has %d outstanding nested calls.\n", this, this->recursion - 1); 260 286 } 261 287 ) 262 } 263 264 extern "C" { 265 // Leave the thread monitor 266 // last routine called by a thread. 267 // Should never return 268 void __cfactx_thrd_leave() { 269 $thread * thrd = TL_GET( this_thread ); 270 $monitor * this = &thrd->self_mon; 271 272 // Lock the monitor now 273 lock( this->lock __cfaabi_dbg_ctx2 ); 274 275 disable_interrupts(); 276 277 thrd->state = Halted; 278 279 /* paranoid */ verifyf( thrd == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", thrd, this->owner, this->recursion, this ); 280 281 // Leaving a recursion level, decrement the counter 282 this->recursion -= 1; 283 284 // If we haven't left the last level of recursion 285 // it must mean there is an error 286 if( this->recursion != 0) { abort( "Thread internal monitor has unbalanced recursion" ); } 287 288 // Fetch the next thread, can be null 289 $thread * new_owner = next_thread( this ); 290 291 // Release the monitor lock 292 unlock( this->lock ); 293 294 // Unpark the next owner if needed 295 /* paranoid */ verifyf( !new_owner || new_owner == this->owner, "Expected owner to be %p, got %p (m: %p)", new_owner, this->owner, this ); 296 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 297 /* paranoid */ verify( ! kernelTLS.this_processor->destroyer ); 298 /* paranoid */ verify( thrd->state == Halted ); 299 300 kernelTLS.this_processor->destroyer = new_owner; 301 302 // Leave the thread 303 __leave_thread(); 304 305 // Control flow should never reach here! 306 } 288 289 this->owner = ($thread*)(1 | (uintptr_t)this->owner); 290 } 291 292 void __thread_finish( $thread * thrd ) { 293 $monitor * this = &thrd->self_mon; 294 295 // Lock the monitor now 296 /* paranoid */ verify( 0x0D15EA5E0D15EA5Ep == thrd->canary ); 297 /* paranoid */ verify( this->lock.lock ); 298 /* paranoid */ verify( thrd->context.SP ); 299 /* paranoid */ verifyf( ((uintptr_t)thrd->context.SP) > ((uintptr_t)__get_stack(thrd->curr_cor)->limit), "ERROR : $thread %p has been corrupted.\n StackPointer too large.\n", thrd ); 300 /* paranoid */ verifyf( ((uintptr_t)thrd->context.SP) < ((uintptr_t)__get_stack(thrd->curr_cor)->base ), "ERROR : $thread %p has been corrupted.\n StackPointer too small.\n", thrd ); 301 /* paranoid */ verify( ! __preemption_enabled() ); 302 303 /* paranoid */ verifyf( thrd == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", thrd, this->owner, this->recursion, this ); 304 /* paranoid */ verify( thrd->state == Halting ); 305 /* paranoid */ verify( this->recursion == 1 ); 306 307 // Leaving a recursion level, decrement the counter 308 this->recursion -= 1; 309 this->owner = 0p; 310 311 // Fetch the next thread, can be null 312 $thread * new_owner = next_thread( this ); 313 314 // Mark the state as fully halted 315 thrd->state = Halted; 316 317 // Release the monitor lock 318 unlock( this->lock ); 319 320 // Unpark the next owner if needed 321 /* paranoid */ verifyf( !new_owner || new_owner == this->owner, "Expected owner to be %p, got %p (m: %p)", new_owner, this->owner, this ); 322 /* paranoid */ verify( ! __preemption_enabled() ); 323 /* paranoid */ verify( thrd->state == Halted ); 324 unpark( new_owner ); 307 325 } 308 326 … … 326 344 // Sorts monitors before entering 327 345 void ?{}( monitor_guard_t & this, $monitor * m [], __lock_size_t count, fptr_t func ) { 328 $thread * thrd = TL_GET( this_thread);346 $thread * thrd = active_thread(); 329 347 330 348 // Store current array … … 361 379 362 380 // Restore thread context 363 TL_GET( this_thread)->monitors = this.prev;381 active_thread()->monitors = this.prev; 364 382 } 365 383 366 384 // Ctor for monitor guard 367 385 // Sorts monitors before entering 368 void ?{}( monitor_dtor_guard_t & this, $monitor * m [], fptr_t func ) {386 void ?{}( monitor_dtor_guard_t & this, $monitor * m [], fptr_t func, bool join ) { 369 387 // optimization 370 $thread * thrd = TL_GET( this_thread);388 $thread * thrd = active_thread(); 371 389 372 390 // Store current array … … 376 394 this.prev = thrd->monitors; 377 395 396 // Save whether we are in a join or not 397 this.join = join; 398 378 399 // Update thread context (needed for conditions) 379 400 (thrd->monitors){m, 1, func}; 380 401 381 __dtor_enter( this.m, func );402 __dtor_enter( this.m, func, join ); 382 403 } 383 404 … … 385 406 void ^?{}( monitor_dtor_guard_t & this ) { 386 407 // Leave the monitors in order 387 __dtor_leave( this.m );408 __dtor_leave( this.m, this.join ); 388 409 389 410 // Restore thread context 390 TL_GET( this_thread)->monitors = this.prev;411 active_thread()->monitors = this.prev; 391 412 } 392 413 … … 428 449 429 450 // Create the node specific to this wait operation 430 wait_ctx( TL_GET( this_thread), user_info );451 wait_ctx( active_thread(), user_info ); 431 452 432 453 // Append the current wait operation to the ones already queued on the condition … … 479 500 //Some more checking in debug 480 501 __cfaabi_dbg_debug_do( 481 $thread * this_thrd = TL_GET( this_thread);502 $thread * this_thrd = active_thread(); 482 503 if ( this.monitor_count != this_thrd->monitors.size ) { 483 504 abort( "Signal on condition %p made with different number of monitor(s), expected %zi got %zi", &this, this.monitor_count, this_thrd->monitors.size ); … … 527 548 528 549 // Create the node specific to this wait operation 529 wait_ctx_primed( kernelTLS.this_thread, 0 )550 wait_ctx_primed( active_thread(), 0 ) 530 551 531 552 //save contexts … … 534 555 //Find the thread to run 535 556 $thread * signallee = pop_head( this.blocked )->waiting_thread; 536 /* paranoid */ verify( signallee->next == 0p );537 557 __set_owner( monitors, count, signallee ); 538 558 … … 627 647 628 648 // Create the node specific to this wait operation 629 wait_ctx_primed( kernelTLS.this_thread, 0 );649 wait_ctx_primed( active_thread(), 0 ); 630 650 631 651 // Save monitor states … … 679 699 680 700 // Create the node specific to this wait operation 681 wait_ctx_primed( kernelTLS.this_thread, 0 );701 wait_ctx_primed( active_thread(), 0 ); 682 702 683 703 monitor_save; … … 685 705 686 706 for( __lock_size_t i = 0; i < count; i++) { 687 verify( monitors[i]->owner == kernelTLS.this_thread);707 verify( monitors[i]->owner == active_thread() ); 688 708 } 689 709 … … 721 741 static inline void __set_owner( $monitor * monitors [], __lock_size_t count, $thread * owner ) { 722 742 /* paranoid */ verify ( monitors[0]->lock.lock ); 723 /* paranoid */ verifyf( monitors[0]->owner == kernelTLS.this_thread, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, monitors[0]->owner, monitors[0]->recursion, monitors[0] );743 /* paranoid */ verifyf( monitors[0]->owner == active_thread(), "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), monitors[0]->owner, monitors[0]->recursion, monitors[0] ); 724 744 monitors[0]->owner = owner; 725 745 monitors[0]->recursion = 1; 726 746 for( __lock_size_t i = 1; i < count; i++ ) { 727 747 /* paranoid */ verify ( monitors[i]->lock.lock ); 728 /* paranoid */ verifyf( monitors[i]->owner == kernelTLS.this_thread, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, monitors[i]->owner, monitors[i]->recursion, monitors[i] );748 /* paranoid */ verifyf( monitors[i]->owner == active_thread(), "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), monitors[i]->owner, monitors[i]->recursion, monitors[i] ); 729 749 monitors[i]->owner = owner; 730 750 monitors[i]->recursion = 0; … … 752 772 //regardless of if we are ready to baton pass, 753 773 //we need to set the monitor as in use 754 /* paranoid */ verifyf( !this->owner || kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );774 /* paranoid */ verifyf( !this->owner || active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this ); 755 775 __set_owner( this, urgent->owner->waiting_thread ); 756 776 … … 761 781 // Get the next thread in the entry_queue 762 782 $thread * new_owner = pop_head( this->entry_queue ); 763 /* paranoid */ verifyf( !this->owner || kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );764 /* paranoid */ verify( !new_owner || new_owner-> next == 0p );783 /* paranoid */ verifyf( !this->owner || active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this ); 784 /* paranoid */ verify( !new_owner || new_owner->link.next == 0p ); 765 785 __set_owner( this, new_owner ); 766 786 … … 884 904 } 885 905 886 __cfaabi_dbg_print_safe( "Kernel : Runing %i (%p)\n", ready2run, ready2run ? node->waiting_thread :0p );906 __cfaabi_dbg_print_safe( "Kernel : Runing %i (%p)\n", ready2run, ready2run ? (thread*)node->waiting_thread : (thread*)0p ); 887 907 return ready2run ? node->waiting_thread : 0p; 888 908 } 889 909 890 910 static inline void brand_condition( condition & this ) { 891 $thread * thrd = TL_GET( this_thread);911 $thread * thrd = active_thread(); 892 912 if( !this.monitors ) { 893 913 // __cfaabi_dbg_print_safe( "Branding\n" ); … … 908 928 // For each thread in the entry-queue 909 929 for( $thread ** thrd_it = &entry_queue.head; 910 *thrd_it!= 1p;911 thrd_it = &(*thrd_it)-> next930 (*thrd_it) != 1p; 931 thrd_it = &(*thrd_it)->link.next 912 932 ) { 913 933 // For each acceptable check if it matches
Note:
See TracChangeset
for help on using the changeset viewer.