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