- File:
-
- 1 edited
-
src/libcfa/concurrency/monitor.c (modified) (46 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/libcfa/concurrency/monitor.c
r34c6c767 rde737c8 17 17 18 18 #include <stdlib> 19 #include <inttypes.h>20 19 21 20 #include "libhdr.h" … … 27 26 // Forward declarations 28 27 static inline void set_owner ( monitor_desc * this, thread_desc * owner ); 29 static inline void set_owner ( monitor_desc * storage [], __lock_size_t count, thread_desc * owner );30 static inline void set_mask ( monitor_desc * storage [], __lock_size_t count, const __waitfor_mask_t & mask );28 static inline void set_owner ( monitor_desc ** storage, short count, thread_desc * owner ); 29 static inline void set_mask ( monitor_desc ** storage, short count, const __waitfor_mask_t & mask ); 31 30 static inline void reset_mask( monitor_desc * this ); 32 31 … … 34 33 static inline bool is_accepted( monitor_desc * this, const __monitor_group_t & monitors ); 35 34 36 static inline void lock_all ( __spinlock_t * locks [], __lock_size_t count );37 static inline void lock_all ( monitor_desc * source [], __spinlock_t * /*out*/ locks [], __lock_size_t count );38 static inline void unlock_all( __spinlock_t * locks [], __lock_size_t count );39 static inline void unlock_all( monitor_desc * locks [], __lock_size_t count );40 41 static inline void save ( monitor_desc * ctx [], __lock_size_t count, __spinlock_t * locks [], unsigned int /*out*/ recursions [], __waitfor_mask_t /*out*/ masks []);42 static inline void restore( monitor_desc * ctx [], __lock_size_t count, __spinlock_t * locks [], unsigned int /*in */ recursions [], __waitfor_mask_t /*in */ masks []);43 44 static inline void init ( __lock_size_t count, monitor_desc * monitors [], __condition_node_t & waiter, __condition_criterion_t criteria []);45 static inline void init_push( __lock_size_t count, monitor_desc * monitors [], __condition_node_t & waiter, __condition_criterion_t criteria []);35 static inline void lock_all( spinlock ** locks, unsigned short count ); 36 static inline void lock_all( monitor_desc ** source, spinlock ** /*out*/ locks, unsigned short count ); 37 static inline void unlock_all( spinlock ** locks, unsigned short count ); 38 static inline void unlock_all( monitor_desc ** locks, unsigned short count ); 39 40 static inline void save ( monitor_desc ** ctx, short count, spinlock ** locks, unsigned int * /*out*/ recursions, __waitfor_mask_t * /*out*/ masks ); 41 static inline void restore( monitor_desc ** ctx, short count, spinlock ** locks, unsigned int * /*in */ recursions, __waitfor_mask_t * /*in */ masks ); 42 43 static inline void init ( int count, monitor_desc ** monitors, __condition_node_t * waiter, __condition_criterion_t * criteria ); 44 static inline void init_push( int count, monitor_desc ** monitors, __condition_node_t * waiter, __condition_criterion_t * criteria ); 46 45 47 46 static inline thread_desc * check_condition ( __condition_criterion_t * ); 48 static inline void brand_condition ( condition &);49 static inline [thread_desc *, int] search_entry_queue( const __waitfor_mask_t &, monitor_desc * monitors [], __lock_size_t count );47 static inline void brand_condition ( condition * ); 48 static inline [thread_desc *, int] search_entry_queue( const __waitfor_mask_t &, monitor_desc ** monitors, int count ); 50 49 51 50 forall(dtype T | sized( T )) 52 static inline __lock_size_t insert_unique( T * array [], __lock_size_t & size, T * val ); 53 static inline __lock_size_t count_max ( const __waitfor_mask_t & mask ); 54 static inline __lock_size_t aggregate ( monitor_desc * storage [], const __waitfor_mask_t & mask ); 55 56 #ifndef __CFA_LOCK_NO_YIELD 57 #define DO_LOCK lock_yield 58 #else 59 #define DO_LOCK lock 60 #endif 51 static inline short insert_unique( T ** array, short & size, T * val ); 52 static inline short count_max ( const __waitfor_mask_t & mask ); 53 static inline short aggregate ( monitor_desc ** storage, const __waitfor_mask_t & mask ); 61 54 62 55 //----------------------------------------------------------------------------- … … 65 58 __condition_node_t waiter = { thrd, count, user_info }; /* Create the node specific to this wait operation */ \ 66 59 __condition_criterion_t criteria[count]; /* Create the creteria this wait operation needs to wake up */ \ 67 init( count, monitors, waiter, criteria );/* Link everything together */ \60 init( count, monitors, &waiter, criteria ); /* Link everything together */ \ 68 61 69 62 #define wait_ctx_primed(thrd, user_info) /* Create the necessary information to use the signaller stack */ \ 70 63 __condition_node_t waiter = { thrd, count, user_info }; /* Create the node specific to this wait operation */ \ 71 64 __condition_criterion_t criteria[count]; /* Create the creteria this wait operation needs to wake up */ \ 72 init_push( count, monitors, waiter, criteria );/* Link everything together and push it to the AS-Stack */ \65 init_push( count, monitors, &waiter, criteria ); /* Link everything together and push it to the AS-Stack */ \ 73 66 74 67 #define monitor_ctx( mons, cnt ) /* Define that create the necessary struct for internal/external scheduling operations */ \ 75 68 monitor_desc ** monitors = mons; /* Save the targeted monitors */ \ 76 __lock_size_t count = cnt;/* Save the count to a local variable */ \69 unsigned short count = cnt; /* Save the count to a local variable */ \ 77 70 unsigned int recursions[ count ]; /* Save the current recursion levels to restore them later */ \ 78 __waitfor_mask_t masks [ count ];/* Save the current waitfor masks to restore them later */ \79 __spinlock_t * locks[ count ]; /* We need to pass-in an array of locks to BlockInternal */ \71 __waitfor_mask_t masks[ count ]; /* Save the current waitfor masks to restore them later */ \ 72 spinlock * locks [ count ]; /* We need to pass-in an array of locks to BlockInternal */ \ 80 73 81 74 #define monitor_save save ( monitors, count, locks, recursions, masks ) … … 90 83 // Enter single monitor 91 84 static void __enter_monitor_desc( monitor_desc * this, const __monitor_group_t & group ) { 92 // Lock the monitor spinlock 93 DO_LOCK(this->lock DEBUG_CTX2 );85 // Lock the monitor spinlock, lock_yield to reduce contention 86 lock_yield( &this->lock DEBUG_CTX2 ); 94 87 thread_desc * thrd = this_thread; 95 88 … … 121 114 122 115 // Some one else has the monitor, wait in line for it 123 append( this->entry_queue, thrd );116 append( &this->entry_queue, thrd ); 124 117 BlockInternal( &this->lock ); 125 118 … … 133 126 134 127 // Release the lock and leave 135 unlock( this->lock );128 unlock( &this->lock ); 136 129 return; 137 130 } 138 131 139 132 static void __enter_monitor_dtor( monitor_desc * this, fptr_t func ) { 140 // Lock the monitor spinlock 141 DO_LOCK(this->lock DEBUG_CTX2 );133 // Lock the monitor spinlock, lock_yield to reduce contention 134 lock_yield( &this->lock DEBUG_CTX2 ); 142 135 thread_desc * thrd = this_thread; 143 136 … … 151 144 set_owner( this, thrd ); 152 145 153 unlock( this->lock );146 unlock( &this->lock ); 154 147 return; 155 148 } … … 160 153 } 161 154 162 __lock_size_t count = 1;155 int count = 1; 163 156 monitor_desc ** monitors = &this; 164 157 __monitor_group_t group = { &this, 1, func }; … … 167 160 168 161 // Wake the thread that is waiting for this 169 __condition_criterion_t * urgent = pop( this->signal_stack );162 __condition_criterion_t * urgent = pop( &this->signal_stack ); 170 163 verify( urgent ); 171 164 … … 189 182 190 183 // Some one else has the monitor, wait in line for it 191 append( this->entry_queue, thrd );184 append( &this->entry_queue, thrd ); 192 185 BlockInternal( &this->lock ); 193 186 … … 202 195 // Leave single monitor 203 196 void __leave_monitor_desc( monitor_desc * this ) { 204 // Lock the monitor spinlock, DO_LOCKto reduce contention205 DO_LOCK(this->lock DEBUG_CTX2 );197 // Lock the monitor spinlock, lock_yield to reduce contention 198 lock_yield( &this->lock DEBUG_CTX2 ); 206 199 207 200 LIB_DEBUG_PRINT_SAFE("Kernel : %10p Leaving mon %p (%p)\n", this_thread, this, this->owner); … … 216 209 if( this->recursion != 0) { 217 210 LIB_DEBUG_PRINT_SAFE("Kernel : recursion still %d\n", this->recursion); 218 unlock( this->lock );211 unlock( &this->lock ); 219 212 return; 220 213 } … … 224 217 225 218 // We can now let other threads in safely 226 unlock( this->lock );219 unlock( &this->lock ); 227 220 228 221 //We need to wake-up the thread … … 249 242 250 243 // Lock the monitor now 251 DO_LOCK(this->lock DEBUG_CTX2 );244 lock_yield( &this->lock DEBUG_CTX2 ); 252 245 253 246 disable_interrupts(); … … 279 272 // relies on the monitor array being sorted 280 273 static inline void enter( __monitor_group_t monitors ) { 281 for( __lock_size_t i = 0; i < monitors.size; i++) {274 for(int i = 0; i < monitors.size; i++) { 282 275 __enter_monitor_desc( monitors.list[i], monitors ); 283 276 } … … 286 279 // Leave multiple monitor 287 280 // relies on the monitor array being sorted 288 static inline void leave(monitor_desc * monitors [], __lock_size_t count) {289 for( __lock_size_t i = count - 1; i >= 0; i--) {281 static inline void leave(monitor_desc ** monitors, int count) { 282 for(int i = count - 1; i >= 0; i--) { 290 283 __leave_monitor_desc( monitors[i] ); 291 284 } … … 294 287 // Ctor for monitor guard 295 288 // Sorts monitors before entering 296 void ?{}( monitor_guard_t & this, monitor_desc * m [], __lock_size_t count, fptr_t func ) {289 void ?{}( monitor_guard_t & this, monitor_desc ** m, int count, fptr_t func ) { 297 290 // Store current array 298 291 this.m = m; … … 303 296 304 297 // Save previous thread context 305 this.[prev_mntrs, prev_count, prev_func] = this_thread->monitors.[list, size, func]; 298 this.prev_mntrs = this_thread->monitors.list; 299 this.prev_count = this_thread->monitors.size; 300 this.prev_func = this_thread->monitors.func; 306 301 307 302 // Update thread context (needed for conditions) 308 this_thread->monitors.[list, size, func] = [m, count, func]; 303 this_thread->monitors.list = m; 304 this_thread->monitors.size = count; 305 this_thread->monitors.func = func; 309 306 310 307 // LIB_DEBUG_PRINT_SAFE("MGUARD : enter %d\n", count); … … 328 325 329 326 // Restore thread context 330 this_thread->monitors.[list, size, func] = this.[prev_mntrs, prev_count, prev_func]; 331 } 327 this_thread->monitors.list = this.prev_mntrs; 328 this_thread->monitors.size = this.prev_count; 329 this_thread->monitors.func = this.prev_func; 330 } 331 332 332 333 333 // Ctor for monitor guard 334 334 // Sorts monitors before entering 335 void ?{}( monitor_dtor_guard_t & this, monitor_desc * m [], fptr_t func ) {335 void ?{}( monitor_dtor_guard_t & this, monitor_desc ** m, fptr_t func ) { 336 336 // Store current array 337 337 this.m = *m; 338 338 339 339 // Save previous thread context 340 this.[prev_mntrs, prev_count, prev_func] = this_thread->monitors.[list, size, func]; 340 this.prev_mntrs = this_thread->monitors.list; 341 this.prev_count = this_thread->monitors.size; 342 this.prev_func = this_thread->monitors.func; 341 343 342 344 // Update thread context (needed for conditions) 343 this_thread->monitors.[list, size, func] = [m, 1, func]; 345 this_thread->monitors.list = m; 346 this_thread->monitors.size = 1; 347 this_thread->monitors.func = func; 344 348 345 349 __enter_monitor_dtor( this.m, func ); 346 350 } 351 347 352 348 353 // Dtor for monitor guard … … 352 357 353 358 // Restore thread context 354 this_thread->monitors.[list, size, func] = this.[prev_mntrs, prev_count, prev_func]; 359 this_thread->monitors.list = this.prev_mntrs; 360 this_thread->monitors.size = this.prev_count; 361 this_thread->monitors.func = this.prev_func; 355 362 } 356 363 357 364 //----------------------------------------------------------------------------- 358 365 // Internal scheduling types 359 void ?{}(__condition_node_t & this, thread_desc * waiting_thread, __lock_size_t count, uintptr_t user_info ) {366 void ?{}(__condition_node_t & this, thread_desc * waiting_thread, unsigned short count, uintptr_t user_info ) { 360 367 this.waiting_thread = waiting_thread; 361 368 this.count = count; … … 371 378 } 372 379 373 void ?{}(__condition_criterion_t & this, monitor_desc * target, __condition_node_t &owner ) {380 void ?{}(__condition_criterion_t & this, monitor_desc * target, __condition_node_t * owner ) { 374 381 this.ready = false; 375 382 this.target = target; 376 this.owner = &owner;383 this.owner = owner; 377 384 this.next = NULL; 378 385 } … … 380 387 //----------------------------------------------------------------------------- 381 388 // Internal scheduling 382 void wait( condition &this, uintptr_t user_info = 0 ) {389 void wait( condition * this, uintptr_t user_info = 0 ) { 383 390 brand_condition( this ); 384 391 385 392 // Check that everything is as expected 386 assertf( this .monitors != NULL, "Waiting with no monitors (%p)", this.monitors );387 verifyf( this .monitor_count != 0, "Waiting with 0 monitors (%"PRIiFAST16")", this.monitor_count );388 verifyf( this .monitor_count < 32u, "Excessive monitor count (%"PRIiFAST16")", this.monitor_count );393 assertf( this->monitors != NULL, "Waiting with no monitors (%p)", this->monitors ); 394 verifyf( this->monitor_count != 0, "Waiting with 0 monitors (%i)", this->monitor_count ); 395 verifyf( this->monitor_count < 32u, "Excessive monitor count (%i)", this->monitor_count ); 389 396 390 397 // Create storage for monitor context 391 monitor_ctx( this .monitors, this.monitor_count );398 monitor_ctx( this->monitors, this->monitor_count ); 392 399 393 400 // Create the node specific to this wait operation … … 396 403 // Append the current wait operation to the ones already queued on the condition 397 404 // We don't need locks for that since conditions must always be waited on inside monitor mutual exclusion 398 append( this.blocked, &waiter );405 append( &this->blocked, &waiter ); 399 406 400 407 // Lock all monitors (aggregates the locks as well) … … 402 409 403 410 // Find the next thread(s) to run 404 __lock_size_t thread_count = 0;411 short thread_count = 0; 405 412 thread_desc * threads[ count ]; 406 413 __builtin_memset( threads, 0, sizeof( threads ) ); … … 410 417 411 418 // Remove any duplicate threads 412 for( __lock_size_t i = 0; i < count; i++) {419 for( int i = 0; i < count; i++) { 413 420 thread_desc * new_owner = next_thread( monitors[i] ); 414 421 insert_unique( threads, thread_count, new_owner ); … … 422 429 } 423 430 424 bool signal( condition &this ) {431 bool signal( condition * this ) { 425 432 if( is_empty( this ) ) { return false; } 426 433 427 434 //Check that everything is as expected 428 verify( this .monitors );429 verify( this .monitor_count != 0 );435 verify( this->monitors ); 436 verify( this->monitor_count != 0 ); 430 437 431 438 //Some more checking in debug 432 439 LIB_DEBUG_DO( 433 440 thread_desc * this_thrd = this_thread; 434 if ( this .monitor_count != this_thrd->monitors.size ) {435 abortf( "Signal on condition %p made with different number of monitor(s), expected %i got %i", &this, this.monitor_count, this_thrd->monitors.size );436 } 437 438 for(int i = 0; i < this .monitor_count; i++) {439 if ( this .monitors[i] != this_thrd->monitors.list[i] ) {440 abortf( "Signal on condition %p made with different monitor, expected %p got %i", &this, this.monitors[i], this_thrd->monitors.list[i] );441 if ( this->monitor_count != this_thrd->monitors.size ) { 442 abortf( "Signal on condition %p made with different number of monitor(s), expected %i got %i", this, this->monitor_count, this_thrd->monitors.size ); 443 } 444 445 for(int i = 0; i < this->monitor_count; i++) { 446 if ( this->monitors[i] != this_thrd->monitors.list[i] ) { 447 abortf( "Signal on condition %p made with different monitor, expected %p got %i", this, this->monitors[i], this_thrd->monitors.list[i] ); 441 448 } 442 449 } 443 450 ); 444 451 445 __lock_size_t count = this.monitor_count;452 unsigned short count = this->monitor_count; 446 453 447 454 // Lock all monitors 448 lock_all( this .monitors, NULL, count );455 lock_all( this->monitors, NULL, count ); 449 456 450 457 //Pop the head of the waiting queue 451 __condition_node_t * node = pop_head( this.blocked );458 __condition_node_t * node = pop_head( &this->blocked ); 452 459 453 460 //Add the thread to the proper AS stack … … 455 462 __condition_criterion_t * crit = &node->criteria[i]; 456 463 assert( !crit->ready ); 457 push( crit->target->signal_stack, crit );464 push( &crit->target->signal_stack, crit ); 458 465 } 459 466 460 467 //Release 461 unlock_all( this .monitors, count );468 unlock_all( this->monitors, count ); 462 469 463 470 return true; 464 471 } 465 472 466 bool signal_block( condition &this ) {467 if( !this .blocked.head ) { return false; }473 bool signal_block( condition * this ) { 474 if( !this->blocked.head ) { return false; } 468 475 469 476 //Check that everything is as expected 470 verifyf( this .monitors != NULL, "Waiting with no monitors (%p)", this.monitors );471 verifyf( this .monitor_count != 0, "Waiting with 0 monitors (%"PRIiFAST16")", this.monitor_count );477 verifyf( this->monitors != NULL, "Waiting with no monitors (%p)", this->monitors ); 478 verifyf( this->monitor_count != 0, "Waiting with 0 monitors (%i)", this->monitor_count ); 472 479 473 480 // Create storage for monitor context 474 monitor_ctx( this .monitors, this.monitor_count );481 monitor_ctx( this->monitors, this->monitor_count ); 475 482 476 483 // Lock all monitors (aggregates the locks them as well) … … 484 491 485 492 //Find the thread to run 486 thread_desc * signallee = pop_head( this.blocked )->waiting_thread;493 thread_desc * signallee = pop_head( &this->blocked )->waiting_thread; 487 494 set_owner( monitors, count, signallee ); 488 495 489 LIB_DEBUG_PRINT_BUFFER_DECL( "Kernel : signal_block condition %p (s: %p)\n", &this, signallee );496 LIB_DEBUG_PRINT_BUFFER_DECL( "Kernel : signal_block condition %p (s: %p)\n", this, signallee ); 490 497 491 498 //Everything is ready to go to sleep … … 505 512 506 513 // Access the user_info of the thread waiting at the front of the queue 507 uintptr_t front( condition &this ) {514 uintptr_t front( condition * this ) { 508 515 verifyf( !is_empty(this), 509 516 "Attempt to access user data on an empty condition.\n" 510 517 "Possible cause is not checking if the condition is empty before reading stored data." 511 518 ); 512 return this .blocked.head->user_info;519 return this->blocked.head->user_info; 513 520 } 514 521 … … 530 537 // This statment doesn't have a contiguous list of monitors... 531 538 // Create one! 532 __lock_size_t max = count_max( mask );539 short max = count_max( mask ); 533 540 monitor_desc * mon_storage[max]; 534 541 __builtin_memset( mon_storage, 0, sizeof( mon_storage ) ); 535 __lock_size_t actual_count = aggregate( mon_storage, mask );536 537 LIB_DEBUG_PRINT_BUFFER_DECL( "Kernel : waitfor %d (s: %d, m: %d)\n", actual_count, mask.size, ( __lock_size_t)max);542 short actual_count = aggregate( mon_storage, mask ); 543 544 LIB_DEBUG_PRINT_BUFFER_DECL( "Kernel : waitfor %d (s: %d, m: %d)\n", actual_count, mask.size, (short)max); 538 545 539 546 if(actual_count == 0) return; … … 562 569 563 570 __condition_criterion_t * dtor_crit = mon2dtor->dtor_node->criteria; 564 push( mon2dtor->signal_stack, dtor_crit );571 push( &mon2dtor->signal_stack, dtor_crit ); 565 572 566 573 unlock_all( locks, count ); … … 622 629 set_mask( monitors, count, mask ); 623 630 624 for( __lock_size_t i = 0; i < count; i++) {631 for(int i = 0; i < count; i++) { 625 632 verify( monitors[i]->owner == this_thread ); 626 633 } … … 654 661 } 655 662 656 static inline void set_owner( monitor_desc * monitors [], __lock_size_t count, thread_desc * owner ) {663 static inline void set_owner( monitor_desc ** monitors, short count, thread_desc * owner ) { 657 664 monitors[0]->owner = owner; 658 665 monitors[0]->recursion = 1; 659 for( __lock_size_t i = 1; i < count; i++ ) {666 for( int i = 1; i < count; i++ ) { 660 667 monitors[i]->owner = owner; 661 668 monitors[i]->recursion = 0; … … 663 670 } 664 671 665 static inline void set_mask( monitor_desc * storage [], __lock_size_t count, const __waitfor_mask_t & mask ) {666 for( __lock_size_t i = 0; i < count; i++) {672 static inline void set_mask( monitor_desc ** storage, short count, const __waitfor_mask_t & mask ) { 673 for(int i = 0; i < count; i++) { 667 674 storage[i]->mask = mask; 668 675 } … … 678 685 //Check the signaller stack 679 686 LIB_DEBUG_PRINT_SAFE("Kernel : mon %p AS-stack top %p\n", this, this->signal_stack.top); 680 __condition_criterion_t * urgent = pop( this->signal_stack );687 __condition_criterion_t * urgent = pop( &this->signal_stack ); 681 688 if( urgent ) { 682 689 //The signaller stack is not empty, … … 690 697 // No signaller thread 691 698 // Get the next thread in the entry_queue 692 thread_desc * new_owner = pop_head( this->entry_queue );699 thread_desc * new_owner = pop_head( &this->entry_queue ); 693 700 set_owner( this, new_owner ); 694 701 … … 698 705 static inline bool is_accepted( monitor_desc * this, const __monitor_group_t & group ) { 699 706 __acceptable_t * it = this->mask.clauses; // Optim 700 __lock_size_t count = this->mask.size;707 int count = this->mask.size; 701 708 702 709 // Check if there are any acceptable functions … … 707 714 708 715 // For all acceptable functions check if this is the current function. 709 for( __lock_size_t i = 0; i < count; i++, it++ ) {716 for( short i = 0; i < count; i++, it++ ) { 710 717 if( *it == group ) { 711 718 *this->mask.accepted = i; … … 718 725 } 719 726 720 static inline void init( __lock_size_t count, monitor_desc * monitors [], __condition_node_t & waiter, __condition_criterion_t criteria []) {721 for( __lock_size_t i = 0; i < count; i++) {727 static inline void init( int count, monitor_desc ** monitors, __condition_node_t * waiter, __condition_criterion_t * criteria ) { 728 for(int i = 0; i < count; i++) { 722 729 (criteria[i]){ monitors[i], waiter }; 723 730 } 724 731 725 waiter .criteria = criteria;726 } 727 728 static inline void init_push( __lock_size_t count, monitor_desc * monitors [], __condition_node_t & waiter, __condition_criterion_t criteria []) {729 for( __lock_size_t i = 0; i < count; i++) {732 waiter->criteria = criteria; 733 } 734 735 static inline void init_push( int count, monitor_desc ** monitors, __condition_node_t * waiter, __condition_criterion_t * criteria ) { 736 for(int i = 0; i < count; i++) { 730 737 (criteria[i]){ monitors[i], waiter }; 731 738 LIB_DEBUG_PRINT_SAFE( "Kernel : target %p = %p\n", criteria[i].target, &criteria[i] ); 732 push( criteria[i].target->signal_stack, &criteria[i] );733 } 734 735 waiter .criteria = criteria;736 } 737 738 static inline void lock_all( __spinlock_t * locks [], __lock_size_t count ) {739 for( __lock_size_t i = 0; i < count; i++ ) {740 DO_LOCK( *locks[i] DEBUG_CTX2 );741 } 742 } 743 744 static inline void lock_all( monitor_desc * source [], __spinlock_t * /*out*/ locks [], __lock_size_t count ) {745 for( __lock_size_t i = 0; i < count; i++ ) {746 __spinlock_t* l = &source[i]->lock;747 DO_LOCK( *l DEBUG_CTX2 );739 push( &criteria[i].target->signal_stack, &criteria[i] ); 740 } 741 742 waiter->criteria = criteria; 743 } 744 745 static inline void lock_all( spinlock ** locks, unsigned short count ) { 746 for( int i = 0; i < count; i++ ) { 747 lock_yield( locks[i] DEBUG_CTX2 ); 748 } 749 } 750 751 static inline void lock_all( monitor_desc ** source, spinlock ** /*out*/ locks, unsigned short count ) { 752 for( int i = 0; i < count; i++ ) { 753 spinlock * l = &source[i]->lock; 754 lock_yield( l DEBUG_CTX2 ); 748 755 if(locks) locks[i] = l; 749 756 } 750 757 } 751 758 752 static inline void unlock_all( __spinlock_t * locks [], __lock_size_t count ) { 753 for( __lock_size_t i = 0; i < count; i++ ) { 754 unlock( *locks[i] ); 755 } 756 } 757 758 static inline void unlock_all( monitor_desc * locks [], __lock_size_t count ) { 759 for( __lock_size_t i = 0; i < count; i++ ) { 760 unlock( locks[i]->lock ); 761 } 762 } 763 764 static inline void save( 765 monitor_desc * ctx [], 766 __lock_size_t count, 767 __attribute((unused)) __spinlock_t * locks [], 768 unsigned int /*out*/ recursions [], 769 __waitfor_mask_t /*out*/ masks [] 770 ) { 771 for( __lock_size_t i = 0; i < count; i++ ) { 759 static inline void unlock_all( spinlock ** locks, unsigned short count ) { 760 for( int i = 0; i < count; i++ ) { 761 unlock( locks[i] ); 762 } 763 } 764 765 static inline void unlock_all( monitor_desc ** locks, unsigned short count ) { 766 for( int i = 0; i < count; i++ ) { 767 unlock( &locks[i]->lock ); 768 } 769 } 770 771 static inline void save( monitor_desc ** ctx, short count, __attribute((unused)) spinlock ** locks, unsigned int * /*out*/ recursions, __waitfor_mask_t * /*out*/ masks ) { 772 for( int i = 0; i < count; i++ ) { 772 773 recursions[i] = ctx[i]->recursion; 773 774 masks[i] = ctx[i]->mask; … … 775 776 } 776 777 777 static inline void restore( 778 monitor_desc * ctx [], 779 __lock_size_t count, 780 __spinlock_t * locks [], 781 unsigned int /*out*/ recursions [], 782 __waitfor_mask_t /*out*/ masks [] 783 ) { 778 static inline void restore( monitor_desc ** ctx, short count, spinlock ** locks, unsigned int * /*out*/ recursions, __waitfor_mask_t * /*out*/ masks ) { 784 779 lock_all( locks, count ); 785 for( __lock_size_t i = 0; i < count; i++ ) {780 for( int i = 0; i < count; i++ ) { 786 781 ctx[i]->recursion = recursions[i]; 787 782 ctx[i]->mask = masks[i]; … … 816 811 } 817 812 818 static inline void brand_condition( condition &this ) {813 static inline void brand_condition( condition * this ) { 819 814 thread_desc * thrd = this_thread; 820 if( !this .monitors ) {815 if( !this->monitors ) { 821 816 // LIB_DEBUG_PRINT_SAFE("Branding\n"); 822 817 assertf( thrd->monitors.list != NULL, "No current monitor to brand condition %p", thrd->monitors.list ); 823 this .monitor_count = thrd->monitors.size;824 825 this .monitors = malloc( this.monitor_count * sizeof( *this.monitors ) );826 for( int i = 0; i < this .monitor_count; i++ ) {827 this .monitors[i] = thrd->monitors.list[i];828 } 829 } 830 } 831 832 static inline [thread_desc *, int] search_entry_queue( const __waitfor_mask_t & mask, monitor_desc * monitors [], __lock_size_t count ) {833 834 __thread_queue_t & entry_queue =monitors[0]->entry_queue;818 this->monitor_count = thrd->monitors.size; 819 820 this->monitors = malloc( this->monitor_count * sizeof( *this->monitors ) ); 821 for( int i = 0; i < this->monitor_count; i++ ) { 822 this->monitors[i] = thrd->monitors.list[i]; 823 } 824 } 825 } 826 827 static inline [thread_desc *, int] search_entry_queue( const __waitfor_mask_t & mask, monitor_desc ** monitors, int count ) { 828 829 __thread_queue_t * entry_queue = &monitors[0]->entry_queue; 835 830 836 831 // For each thread in the entry-queue 837 for( thread_desc ** thrd_it = &entry_queue .head;832 for( thread_desc ** thrd_it = &entry_queue->head; 838 833 *thrd_it; 839 834 thrd_it = &(*thrd_it)->next … … 857 852 858 853 forall(dtype T | sized( T )) 859 static inline __lock_size_t insert_unique( T * array [], __lock_size_t & size, T * val ) {854 static inline short insert_unique( T ** array, short & size, T * val ) { 860 855 if( !val ) return size; 861 856 862 for( __lock_size_t i = 0; i <= size; i++) {857 for(int i = 0; i <= size; i++) { 863 858 if( array[i] == val ) return size; 864 859 } … … 869 864 } 870 865 871 static inline __lock_size_t count_max( const __waitfor_mask_t & mask ) {872 __lock_size_t max = 0;873 for( __lock_size_t i = 0; i < mask.size; i++ ) {866 static inline short count_max( const __waitfor_mask_t & mask ) { 867 short max = 0; 868 for( int i = 0; i < mask.size; i++ ) { 874 869 max += mask.clauses[i].size; 875 870 } … … 877 872 } 878 873 879 static inline __lock_size_t aggregate( monitor_desc * storage [], const __waitfor_mask_t & mask ) {880 __lock_size_t size = 0;881 for( __lock_size_t i = 0; i < mask.size; i++ ) {874 static inline short aggregate( monitor_desc ** storage, const __waitfor_mask_t & mask ) { 875 short size = 0; 876 for( int i = 0; i < mask.size; i++ ) { 882 877 __libcfa_small_sort( mask.clauses[i].list, mask.clauses[i].size ); 883 for( __lock_size_t j = 0; j < mask.clauses[i].size; j++) {878 for( int j = 0; j < mask.clauses[i].size; j++) { 884 879 insert_unique( storage, size, mask.clauses[i].list[j] ); 885 880 } … … 895 890 } 896 891 897 void append( __condition_blocked_queue_t &this, __condition_node_t * c ) {898 verify(this .tail != NULL);899 *this .tail = c;900 this .tail = &c->next;901 } 902 903 __condition_node_t * pop_head( __condition_blocked_queue_t &this ) {904 __condition_node_t * head = this .head;892 void append( __condition_blocked_queue_t * this, __condition_node_t * c ) { 893 verify(this->tail != NULL); 894 *this->tail = c; 895 this->tail = &c->next; 896 } 897 898 __condition_node_t * pop_head( __condition_blocked_queue_t * this ) { 899 __condition_node_t * head = this->head; 905 900 if( head ) { 906 this .head = head->next;901 this->head = head->next; 907 902 if( !head->next ) { 908 this .tail = &this.head;903 this->tail = &this->head; 909 904 } 910 905 head->next = NULL;
Note:
See TracChangeset
for help on using the changeset viewer.