Changeset 90152a4 for libcfa/src/concurrency/monitor.cfa
- Timestamp:
- Aug 27, 2018, 4:40:34 PM (7 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, cleanup-dtors, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- b7c89aa
- Parents:
- f9feab8 (diff), 305581d (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 moved
-
libcfa/src/concurrency/monitor.cfa (moved) (moved from src/libcfa/concurrency/monitor.c ) (41 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/monitor.cfa
rf9feab8 r90152a4 10 10 // Created On : Thd Feb 23 12:27:26 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Jul 31 14:59:05 201713 // Update Count : 312 // Last Modified On : Fri Mar 30 14:30:26 2018 13 // Update Count : 9 14 14 // 15 15 16 #include "monitor "17 18 #include <stdlib >16 #include "monitor.hfa" 17 18 #include <stdlib.hfa> 19 19 #include <inttypes.h> 20 20 21 #include "kernel_private.h "22 23 #include "bits/algorithm s.h"21 #include "kernel_private.hfa" 22 23 #include "bits/algorithm.hfa" 24 24 25 25 //----------------------------------------------------------------------------- … … 53 53 static inline __lock_size_t aggregate ( monitor_desc * storage [], const __waitfor_mask_t & mask ); 54 54 55 #ifndef __CFA_LOCK_NO_YIELD56 #define DO_LOCK lock_yield57 #else58 #define DO_LOCK lock59 #endif60 61 55 //----------------------------------------------------------------------------- 62 56 // Useful defines … … 90 84 static void __enter_monitor_desc( monitor_desc * this, const __monitor_group_t & group ) { 91 85 // Lock the monitor spinlock 92 DO_LOCK( this->lock __cfaabi_dbg_ctx2 ); 93 thread_desc * thrd = this_thread; 94 95 __cfaabi_dbg_print_safe("Kernel : %10p Entering mon %p (%p)\n", thrd, this, this->owner); 86 lock( this->lock __cfaabi_dbg_ctx2 ); 87 // Interrupts disable inside critical section 88 thread_desc * thrd = kernelTLS.this_thread; 89 90 __cfaabi_dbg_print_safe( "Kernel : %10p Entering mon %p (%p)\n", thrd, this, this->owner); 96 91 97 92 if( !this->owner ) { … … 99 94 set_owner( this, thrd ); 100 95 101 __cfaabi_dbg_print_safe( "Kernel : mon is free \n");96 __cfaabi_dbg_print_safe( "Kernel : mon is free \n" ); 102 97 } 103 98 else if( this->owner == thrd) { … … 105 100 this->recursion += 1; 106 101 107 __cfaabi_dbg_print_safe( "Kernel : mon already owned \n");102 __cfaabi_dbg_print_safe( "Kernel : mon already owned \n" ); 108 103 } 109 104 else if( is_accepted( this, group) ) { … … 114 109 reset_mask( this ); 115 110 116 __cfaabi_dbg_print_safe( "Kernel : mon accepts \n");111 __cfaabi_dbg_print_safe( "Kernel : mon accepts \n" ); 117 112 } 118 113 else { 119 __cfaabi_dbg_print_safe( "Kernel : blocking \n");114 __cfaabi_dbg_print_safe( "Kernel : blocking \n" ); 120 115 121 116 // Some one else has the monitor, wait in line for it 122 117 append( this->entry_queue, thrd ); 118 123 119 BlockInternal( &this->lock ); 124 120 125 __cfaabi_dbg_print_safe( "Kernel : %10p Entered mon %p\n", thrd, this);121 __cfaabi_dbg_print_safe( "Kernel : %10p Entered mon %p\n", thrd, this); 126 122 127 123 // BlockInternal will unlock spinlock, no need to unlock ourselves … … 129 125 } 130 126 131 __cfaabi_dbg_print_safe( "Kernel : %10p Entered mon %p\n", thrd, this);127 __cfaabi_dbg_print_safe( "Kernel : %10p Entered mon %p\n", thrd, this); 132 128 133 129 // Release the lock and leave … … 138 134 static void __enter_monitor_dtor( monitor_desc * this, fptr_t func ) { 139 135 // Lock the monitor spinlock 140 DO_LOCK( this->lock __cfaabi_dbg_ctx2 ); 141 thread_desc * thrd = this_thread; 142 143 __cfaabi_dbg_print_safe("Kernel : %10p Entering dtor for mon %p (%p)\n", thrd, this, this->owner); 136 lock( this->lock __cfaabi_dbg_ctx2 ); 137 // Interrupts disable inside critical section 138 thread_desc * thrd = kernelTLS.this_thread; 139 140 __cfaabi_dbg_print_safe( "Kernel : %10p Entering dtor for mon %p (%p)\n", thrd, this, this->owner); 144 141 145 142 146 143 if( !this->owner ) { 147 __cfaabi_dbg_print_safe( "Kernel : Destroying free mon %p\n", this);144 __cfaabi_dbg_print_safe( "Kernel : Destroying free mon %p\n", this); 148 145 149 146 // No one has the monitor, just take it … … 156 153 // We already have the monitor... but where about to destroy it so the nesting will fail 157 154 // Abort! 158 abort f("Attempt to destroy monitor %p by thread \"%.256s\" (%p) in nested mutex.");155 abort( "Attempt to destroy monitor %p by thread \"%.256s\" (%p) in nested mutex.", this, thrd->self_cor.name, thrd ); 159 156 } 160 157 … … 163 160 __monitor_group_t group = { &this, 1, func }; 164 161 if( is_accepted( this, group) ) { 165 __cfaabi_dbg_print_safe( "Kernel : mon accepts dtor, block and signal it \n");162 __cfaabi_dbg_print_safe( "Kernel : mon accepts dtor, block and signal it \n" ); 166 163 167 164 // Wake the thread that is waiting for this … … 173 170 174 171 // Create the node specific to this wait operation 175 wait_ctx_primed( th is_thread, 0 )172 wait_ctx_primed( thrd, 0 ) 176 173 177 174 // Some one else has the monitor, wait for him to finish and then run … … 182 179 } 183 180 else { 184 __cfaabi_dbg_print_safe( "Kernel : blocking \n");185 186 wait_ctx( th is_thread, 0 )181 __cfaabi_dbg_print_safe( "Kernel : blocking \n" ); 182 183 wait_ctx( thrd, 0 ) 187 184 this->dtor_node = &waiter; 188 185 … … 195 192 } 196 193 197 __cfaabi_dbg_print_safe( "Kernel : Destroying %p\n", this);194 __cfaabi_dbg_print_safe( "Kernel : Destroying %p\n", this); 198 195 199 196 } … … 201 198 // Leave single monitor 202 199 void __leave_monitor_desc( monitor_desc * this ) { 203 // Lock the monitor spinlock , DO_LOCK to reduce contention204 DO_LOCK( this->lock __cfaabi_dbg_ctx2 );205 206 __cfaabi_dbg_print_safe( "Kernel : %10p Leaving mon %p (%p)\n",this_thread, this, this->owner);207 208 verifyf( this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)",this_thread, this->owner, this->recursion, this );200 // Lock the monitor spinlock 201 lock( this->lock __cfaabi_dbg_ctx2 ); 202 203 __cfaabi_dbg_print_safe( "Kernel : %10p Leaving mon %p (%p)\n", kernelTLS.this_thread, this, this->owner); 204 205 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 ); 209 206 210 207 // Leaving a recursion level, decrement the counter … … 214 211 // it means we don't need to do anything 215 212 if( this->recursion != 0) { 216 __cfaabi_dbg_print_safe( "Kernel : recursion still %d\n", this->recursion);213 __cfaabi_dbg_print_safe( "Kernel : recursion still %d\n", this->recursion); 217 214 unlock( this->lock ); 218 215 return; … … 232 229 void __leave_dtor_monitor_desc( monitor_desc * this ) { 233 230 __cfaabi_dbg_debug_do( 234 if( this_thread!= this->owner ) {235 abort f("Destroyed monitor %p has inconsistent owner, expected %p got %p.\n", this, this_thread, this->owner);231 if( TL_GET( this_thread ) != this->owner ) { 232 abort( "Destroyed monitor %p has inconsistent owner, expected %p got %p.\n", this, TL_GET( this_thread ), this->owner); 236 233 } 237 234 if( this->recursion != 1 ) { 238 abort f("Destroyed monitor %p has %d outstanding nested calls.\n", this, this->recursion - 1);235 abort( "Destroyed monitor %p has %d outstanding nested calls.\n", this, this->recursion - 1); 239 236 } 240 237 ) … … 248 245 249 246 // Lock the monitor now 250 DO_LOCK( this->lock __cfaabi_dbg_ctx2 );247 lock( this->lock __cfaabi_dbg_ctx2 ); 251 248 252 249 disable_interrupts(); … … 261 258 // If we haven't left the last level of recursion 262 259 // it must mean there is an error 263 if( this->recursion != 0) { abort f("Thread internal monitor has unbalanced recursion"); }260 if( this->recursion != 0) { abort( "Thread internal monitor has unbalanced recursion" ); } 264 261 265 262 // Fetch the next thread, can be null … … 294 291 // Sorts monitors before entering 295 292 void ?{}( monitor_guard_t & this, monitor_desc * m [], __lock_size_t count, fptr_t func ) { 293 thread_desc * thrd = TL_GET( this_thread ); 294 296 295 // Store current array 297 296 this.m = m; 298 297 this.count = count; 299 298 300 // Sort monitors based on address -> TODO use a sort specialized for small numbers299 // Sort monitors based on address 301 300 __libcfa_small_sort(this.m, count); 302 301 303 302 // Save previous thread context 304 this.prev = th is_thread->monitors;303 this.prev = thrd->monitors; 305 304 306 305 // Update thread context (needed for conditions) 307 (th is_thread->monitors){m, count, func};308 309 // __cfaabi_dbg_print_safe( "MGUARD : enter %d\n", count);306 (thrd->monitors){m, count, func}; 307 308 // __cfaabi_dbg_print_safe( "MGUARD : enter %d\n", count); 310 309 311 310 // Enter the monitors in order … … 313 312 enter( group ); 314 313 315 // __cfaabi_dbg_print_safe( "MGUARD : entered\n");314 // __cfaabi_dbg_print_safe( "MGUARD : entered\n" ); 316 315 } 317 316 … … 319 318 // Dtor for monitor guard 320 319 void ^?{}( monitor_guard_t & this ) { 321 // __cfaabi_dbg_print_safe( "MGUARD : leaving %d\n", this.count);320 // __cfaabi_dbg_print_safe( "MGUARD : leaving %d\n", this.count); 322 321 323 322 // Leave the monitors in order 324 323 leave( this.m, this.count ); 325 324 326 // __cfaabi_dbg_print_safe( "MGUARD : left\n");325 // __cfaabi_dbg_print_safe( "MGUARD : left\n" ); 327 326 328 327 // Restore thread context 329 this_thread->monitors = this.prev;328 TL_GET( this_thread )->monitors = this.prev; 330 329 } 331 330 … … 333 332 // Sorts monitors before entering 334 333 void ?{}( monitor_dtor_guard_t & this, monitor_desc * m [], fptr_t func ) { 334 // optimization 335 thread_desc * thrd = TL_GET( this_thread ); 336 335 337 // Store current array 336 338 this.m = *m; 337 339 338 340 // Save previous thread context 339 this.prev = th is_thread->monitors;341 this.prev = thrd->monitors; 340 342 341 343 // Update thread context (needed for conditions) 342 (th is_thread->monitors){m, 1, func};344 (thrd->monitors){m, 1, func}; 343 345 344 346 __enter_monitor_dtor( this.m, func ); … … 351 353 352 354 // Restore thread context 353 this_thread->monitors = this.prev;355 TL_GET( this_thread )->monitors = this.prev; 354 356 } 355 357 … … 363 365 } 364 366 365 void ?{}(__condition_criterion_t & this ) {366 this.ready = false;367 t his.target = NULL;368 this.owner = NULL;369 this.next = NULL;367 void ?{}(__condition_criterion_t & this ) with( this ) { 368 ready = false; 369 target = NULL; 370 owner = NULL; 371 next = NULL; 370 372 } 371 373 … … 391 393 392 394 // Create the node specific to this wait operation 393 wait_ctx( this_thread, user_info );395 wait_ctx( TL_GET( this_thread ), user_info ); 394 396 395 397 // Append the current wait operation to the ones already queued on the condition … … 430 432 //Some more checking in debug 431 433 __cfaabi_dbg_debug_do( 432 thread_desc * this_thrd = this_thread;434 thread_desc * this_thrd = TL_GET( this_thread ); 433 435 if ( this.monitor_count != this_thrd->monitors.size ) { 434 abort f( "Signal on condition %p made with different number of monitor(s), expected %i got %i", &this, this.monitor_count, this_thrd->monitors.size );436 abort( "Signal on condition %p made with different number of monitor(s), expected %zi got %zi", &this, this.monitor_count, this_thrd->monitors.size ); 435 437 } 436 438 437 439 for(int i = 0; i < this.monitor_count; i++) { 438 440 if ( this.monitors[i] != this_thrd->monitors[i] ) { 439 abort f( "Signal on condition %p made with different monitor, expected %p got %i", &this, this.monitors[i], this_thrd->monitors[i] );441 abort( "Signal on condition %p made with different monitor, expected %p got %p", &this, this.monitors[i], this_thrd->monitors[i] ); 440 442 } 441 443 } … … 476 478 lock_all( monitors, locks, count ); 477 479 480 478 481 // Create the node specific to this wait operation 479 wait_ctx_primed( this_thread, 0 )482 wait_ctx_primed( kernelTLS.this_thread, 0 ) 480 483 481 484 //save contexts … … 534 537 __lock_size_t actual_count = aggregate( mon_storage, mask ); 535 538 536 __cfaabi_dbg_print_buffer_decl( "Kernel : waitfor % d (s: %d, m: %d)\n", actual_count, mask.size, (__lock_size_t)max);539 __cfaabi_dbg_print_buffer_decl( "Kernel : waitfor %"PRIdFAST16" (s: %"PRIdFAST16", m: %"PRIdFAST16")\n", actual_count, mask.size, (__lock_size_t)max); 537 540 538 541 if(actual_count == 0) return; 539 542 540 __cfaabi_dbg_print_buffer_local( "Kernel : waitfor internal proceeding\n" );543 __cfaabi_dbg_print_buffer_local( "Kernel : waitfor internal proceeding\n" ); 541 544 542 545 // Create storage for monitor context … … 555 558 __acceptable_t& accepted = mask[index]; 556 559 if( accepted.is_dtor ) { 557 __cfaabi_dbg_print_buffer_local( "Kernel : dtor already there\n" );560 __cfaabi_dbg_print_buffer_local( "Kernel : dtor already there\n" ); 558 561 verifyf( accepted.size == 1, "ERROR: Accepted dtor has more than 1 mutex parameter." ); 559 562 … … 567 570 } 568 571 else { 569 __cfaabi_dbg_print_buffer_local( "Kernel : thread present, baton-passing\n" );572 __cfaabi_dbg_print_buffer_local( "Kernel : thread present, baton-passing\n" ); 570 573 571 574 // Create the node specific to this wait operation 572 wait_ctx_primed( this_thread, 0 );575 wait_ctx_primed( kernelTLS.this_thread, 0 ); 573 576 574 577 // Save monitor states 575 578 monitor_save; 576 579 577 __cfaabi_dbg_print_buffer_local( "Kernel : baton of % dmonitors : ", count );580 __cfaabi_dbg_print_buffer_local( "Kernel : baton of %"PRIdFAST16" monitors : ", count ); 578 581 #ifdef __CFA_DEBUG_PRINT__ 579 582 for( int i = 0; i < count; i++) { … … 581 584 } 582 585 #endif 583 __cfaabi_dbg_print_buffer_local( "\n" );586 __cfaabi_dbg_print_buffer_local( "\n" ); 584 587 585 588 // Set the owners to be the next thread … … 592 595 monitor_restore; 593 596 594 __cfaabi_dbg_print_buffer_local( "Kernel : thread present, returned\n" );597 __cfaabi_dbg_print_buffer_local( "Kernel : thread present, returned\n" ); 595 598 } 596 599 … … 602 605 603 606 if( duration == 0 ) { 604 __cfaabi_dbg_print_buffer_local( "Kernel : non-blocking, exiting\n" );607 __cfaabi_dbg_print_buffer_local( "Kernel : non-blocking, exiting\n" ); 605 608 606 609 unlock_all( locks, count ); … … 611 614 612 615 613 verifyf( duration < 0, "Timeout on waitfor statments not supported yet." );614 615 __cfaabi_dbg_print_buffer_local( "Kernel : blocking waitfor\n" );616 verifyf( duration < 0, "Timeout on waitfor statments not supported yet." ); 617 618 __cfaabi_dbg_print_buffer_local( "Kernel : blocking waitfor\n" ); 616 619 617 620 // Create the node specific to this wait operation 618 wait_ctx_primed( this_thread, 0 );621 wait_ctx_primed( kernelTLS.this_thread, 0 ); 619 622 620 623 monitor_save; … … 622 625 623 626 for( __lock_size_t i = 0; i < count; i++) { 624 verify( monitors[i]->owner == this_thread );627 verify( monitors[i]->owner == kernelTLS.this_thread ); 625 628 } 626 629 … … 635 638 monitor_restore; 636 639 637 __cfaabi_dbg_print_buffer_local( "Kernel : exiting\n" );640 __cfaabi_dbg_print_buffer_local( "Kernel : exiting\n" ); 638 641 639 642 __cfaabi_dbg_print_buffer_local( "Kernel : accepted %d\n", *mask.accepted); … … 644 647 645 648 static inline void set_owner( monitor_desc * this, thread_desc * owner ) { 646 // __cfaabi_dbg_print_safe( "Kernal : Setting owner of %p to %p ( was %p)\n", this, owner, this->owner );649 // __cfaabi_dbg_print_safe( "Kernal : Setting owner of %p to %p ( was %p)\n", this, owner, this->owner ); 647 650 648 651 //Pass the monitor appropriately … … 676 679 static inline thread_desc * next_thread( monitor_desc * this ) { 677 680 //Check the signaller stack 678 __cfaabi_dbg_print_safe( "Kernel : mon %p AS-stack top %p\n", this, this->signal_stack.top);681 __cfaabi_dbg_print_safe( "Kernel : mon %p AS-stack top %p\n", this, this->signal_stack.top); 679 682 __condition_criterion_t * urgent = pop( this->signal_stack ); 680 683 if( urgent ) { … … 737 740 static inline void lock_all( __spinlock_t * locks [], __lock_size_t count ) { 738 741 for( __lock_size_t i = 0; i < count; i++ ) { 739 DO_LOCK( *locks[i] __cfaabi_dbg_ctx2 );742 lock( *locks[i] __cfaabi_dbg_ctx2 ); 740 743 } 741 744 } … … 744 747 for( __lock_size_t i = 0; i < count; i++ ) { 745 748 __spinlock_t * l = &source[i]->lock; 746 DO_LOCK( *l __cfaabi_dbg_ctx2 );749 lock( *l __cfaabi_dbg_ctx2 ); 747 750 if(locks) locks[i] = l; 748 751 } … … 816 819 817 820 static inline void brand_condition( condition & this ) { 818 thread_desc * thrd = this_thread;821 thread_desc * thrd = TL_GET( this_thread ); 819 822 if( !this.monitors ) { 820 // __cfaabi_dbg_print_safe( "Branding\n");823 // __cfaabi_dbg_print_safe( "Branding\n" ); 821 824 assertf( thrd->monitors.data != NULL, "No current monitor to brand condition %p", thrd->monitors.data ); 822 825 this.monitor_count = thrd->monitors.size;
Note:
See TracChangeset
for help on using the changeset viewer.