- File:
-
- 1 edited
-
src/libcfa/concurrency/monitor.c (modified) (24 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/libcfa/concurrency/monitor.c
r4cc9b13 r80c72a7 24 24 // Forward declarations 25 25 static inline void set_owner( monitor_desc * this, thread_desc * owner ); 26 static inline void set_owner( monitor_desc ** storage, short count, thread_desc * owner );27 static inline void set_mask ( monitor_desc ** storage, short count, const __waitfor_mask_t & mask );28 29 26 static inline thread_desc * next_thread( monitor_desc * this ); 30 static inline bool is_accepted( monitor_desc * this, const __monitor_group_t & monitors);27 static inline int is_accepted( thread_desc * owner, monitor_desc * this, monitor_desc ** group, int group_cnt, void (*func)() ); 31 28 32 29 static inline void lock_all( spinlock ** locks, unsigned short count ); … … 35 32 static inline void unlock_all( monitor_desc ** locks, unsigned short count ); 36 33 37 static inline void save ( monitor_desc ** ctx, short count, spinlock ** locks, unsigned int * /*out*/ recursions, __waitfor_mask_t * /*out*/ masks);38 static inline void restore ( monitor_desc ** ctx, short count, spinlock ** locks, unsigned int * /*in */ recursions, __waitfor_mask_t * /*in */ masks);34 static inline void save_recursion ( monitor_desc ** ctx, unsigned int * /*out*/ recursions, unsigned short count ); 35 static inline void restore_recursion( monitor_desc ** ctx, unsigned int * /*in */ recursions, unsigned short count ); 39 36 40 37 static inline void init ( int count, monitor_desc ** monitors, __condition_node_t * waiter, __condition_criterion_t * criteria ); 41 38 static inline void init_push( int count, monitor_desc ** monitors, __condition_node_t * waiter, __condition_criterion_t * criteria ); 42 39 43 static inline thread_desc * check_condition ( __condition_criterion_t * ); 44 static inline void brand_condition ( condition * ); 45 static inline [thread_desc *, int] search_entry_queue( const __waitfor_mask_t &, monitor_desc ** monitors, int count ); 46 47 forall(dtype T | sized( T )) 48 static inline short insert_unique( T ** array, short & size, T * val ); 49 static inline short count_max ( const __waitfor_mask_t & mask ); 50 static inline short aggregate ( monitor_desc ** storage, const __waitfor_mask_t & mask ); 40 static inline thread_desc * check_condition( __condition_criterion_t * ); 41 static inline void brand_condition( condition * ); 42 static inline unsigned short insert_unique( thread_desc ** thrds, unsigned short end, thread_desc * val ); 43 44 static inline thread_desc * search_entry_queue( __acceptable_t * acceptables, int acc_count, monitor_desc ** monitors, int count ); 51 45 52 46 //----------------------------------------------------------------------------- 53 47 // Useful defines 54 #define wait_ctx(thrd, user_info) /* Create the necessary information to use the signaller stack */ \ 55 __condition_node_t waiter = { thrd, count, user_info }; /* Create the node specific to this wait operation */ \ 56 __condition_criterion_t criteria[count]; /* Create the creteria this wait operation needs to wake up */ \ 57 init( count, monitors, &waiter, criteria ); /* Link everything together */ \ 58 59 #define wait_ctx_primed(thrd, user_info) /* Create the necessary information to use the signaller stack */ \ 60 __condition_node_t waiter = { thrd, count, user_info }; /* Create the node specific to this wait operation */ \ 61 __condition_criterion_t criteria[count]; /* Create the creteria this wait operation needs to wake up */ \ 62 init_push( count, monitors, &waiter, criteria ); /* Link everything together and push it to the AS-Stack */ \ 63 64 #define monitor_ctx( mons, cnt ) /* Define that create the necessary struct for internal/external scheduling operations */ \ 65 monitor_desc ** monitors = mons; /* Save the targeted monitors */ \ 66 unsigned short count = cnt; /* Save the count to a local variable */ \ 67 unsigned int recursions[ count ]; /* Save the current recursion levels to restore them later */ \ 68 __waitfor_mask_t masks[ count ]; /* Save the current waitfor masks to restore them later */ \ 69 spinlock * locks [ count ]; /* We need to pass-in an array of locks to BlockInternal */ \ 70 71 #define monitor_save save ( monitors, count, locks, recursions, masks ) 72 #define monitor_restore restore( monitors, count, locks, recursions, masks ) 73 74 #define blockAndWake( thrd, cnt ) /* Create the necessary information to use the signaller stack */ \ 75 monitor_save; /* Save monitor states */ \ 76 BlockInternal( locks, count, thrd, cnt ); /* Everything is ready to go to sleep */ \ 77 monitor_restore; /* We are back, restore the owners and recursions */ \ 78 48 #define wait_ctx(thrd, user_info) /* Create the necessary information to use the signaller stack */ \ 49 __condition_node_t waiter = { thrd, count, user_info }; /* Create the node specific to this wait operation */ \ 50 __condition_criterion_t criteria[count]; /* Create the creteria this wait operation needs to wake up */ \ 51 init( count, monitors, &waiter, criteria ); /* Link everything together */ \ 52 53 #define wait_ctx_primed(thrd, user_info) /* Create the necessary information to use the signaller stack */ \ 54 __condition_node_t waiter = { thrd, count, user_info }; /* Create the node specific to this wait operation */ \ 55 __condition_criterion_t criteria[count]; /* Create the creteria this wait operation needs to wake up */ \ 56 init_push( count, monitors, &waiter, criteria ); /* Link everything together and push it to the AS-Stack */ \ 57 58 #define monitor_ctx( mons, cnt ) /* Define that create the necessary struct for internal/external scheduling operations */ \ 59 monitor_desc ** monitors = mons; /* Save the targeted monitors */ \ 60 unsigned short count = cnt; /* Save the count to a local variable */ \ 61 unsigned int recursions[ count ]; /* Save the current recursion levels to restore them later */ \ 62 spinlock * locks [ count ]; /* We need to pass-in an array of locks to BlockInternal */ \ 79 63 80 64 //----------------------------------------------------------------------------- … … 84 68 extern "C" { 85 69 // Enter single monitor 86 static void __enter_monitor_desc( monitor_desc * this, const __monitor_group_t & group) {70 static void __enter_monitor_desc( monitor_desc * this, monitor_desc ** group, int group_cnt, void (*func)() ) { 87 71 // Lock the monitor spinlock, lock_yield to reduce contention 88 72 lock_yield( &this->lock DEBUG_CTX2 ); … … 91 75 LIB_DEBUG_PRINT_SAFE("Kernel : %10p Entering mon %p (%p)\n", thrd, this, this->owner); 92 76 77 this->accepted_index = -1; 93 78 if( !this->owner ) { 94 79 // No one has the monitor, just take it … … 104 89 LIB_DEBUG_PRINT_SAFE("Kernel : mon already owned \n"); 105 90 } 106 else if( is_accepted( this, group)) {91 else if( (this->accepted_index = is_accepted( thrd, this, group, group_cnt, func)) >= 0 ) { 107 92 // Some one was waiting for us, enter 108 93 set_owner( this, thrd ); … … 135 120 lock_yield( &this->lock DEBUG_CTX2 ); 136 121 137 LIB_DEBUG_PRINT_SAFE("Kernel : %10p Leaving mon %p (%p)\n", this_thread, this, this->owner); 138 139 verifyf( this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", this_thread, this->owner, this->recursion, this ); 122 verifyf( this_thread == this->owner, "Expected owner to be %p, got %p (r: %i)", this_thread, this->owner, this->recursion ); 140 123 141 124 // Leaving a recursion level, decrement the counter … … 163 146 // Should never return 164 147 void __leave_thread_monitor( thread_desc * thrd ) { 165 monitor_desc * this = &thrd-> self_mon;148 monitor_desc * this = &thrd->mon; 166 149 167 150 // Lock the monitor now … … 170 153 disable_interrupts(); 171 154 172 thrd-> self_cor.state = Halted;173 174 verifyf( thrd == this->owner, "Expected owner to be %p, got %p (r: %i , m: %p)", thrd, this->owner, this->recursion, this);155 thrd->cor.state = Halted; 156 157 verifyf( thrd == this->owner, "Expected owner to be %p, got %p (r: %i)", thrd, this->owner, this->recursion ); 175 158 176 159 // Leaving a recursion level, decrement the counter … … 195 178 // Enter multiple monitor 196 179 // relies on the monitor array being sorted 197 static inline void enter( __monitor_group_t monitors) {198 for(int i = 0; i < monitors.size; i++) {199 __enter_monitor_desc( monitors .list[i], monitors);180 static inline void enter(monitor_desc ** monitors, int count, void (*func)() ) { 181 for(int i = 0; i < count; i++) { 182 __enter_monitor_desc( monitors[i], monitors, count, func ); 200 183 } 201 184 } … … 211 194 // Ctor for monitor guard 212 195 // Sorts monitors before entering 213 void ?{}( monitor_guard_t &this, monitor_desc ** m, int count, void (*func)() ) {196 void ?{}( monitor_guard_t * this, monitor_desc ** m, int count, void (*func)() ) { 214 197 // Store current array 215 this .m = m;216 this .count = count;198 this->m = m; 199 this->count = count; 217 200 218 201 // Sort monitors based on address -> TODO use a sort specialized for small numbers 219 qsort(this .m, count);202 qsort(this->m, count); 220 203 221 204 // Save previous thread context 222 this .prev_mntrs = this_thread->monitors.list;223 this .prev_count = this_thread->monitors.size;224 this .prev_func = this_thread->monitors.func;205 this->prev_mntrs = this_thread->current_monitors; 206 this->prev_count = this_thread->current_monitor_count; 207 this->prev_func = this_thread->current_monitor_func; 225 208 226 209 // Update thread context (needed for conditions) 227 this_thread->monitors.list = m; 228 this_thread->monitors.size = count; 229 this_thread->monitors.func = func; 230 231 LIB_DEBUG_PRINT_SAFE("MGUARD : enter %d\n", count); 210 this_thread->current_monitors = m; 211 this_thread->current_monitor_count = count; 212 this_thread->current_monitor_func = func; 232 213 233 214 // Enter the monitors in order 234 __monitor_group_t group = {this.m, this.count, func}; 235 enter( group ); 236 237 LIB_DEBUG_PRINT_SAFE("MGUARD : entered\n"); 238 } 239 215 enter( this->m, this->count, func ); 216 } 240 217 241 218 // Dtor for monitor guard 242 void ^?{}( monitor_guard_t & this ) { 243 LIB_DEBUG_PRINT_SAFE("MGUARD : leaving %d\n", this.count); 244 219 void ^?{}( monitor_guard_t * this ) { 245 220 // Leave the monitors in order 246 leave( this.m, this.count ); 247 248 LIB_DEBUG_PRINT_SAFE("MGUARD : left\n"); 221 leave( this->m, this->count ); 249 222 250 223 // Restore thread context 251 this_thread-> monitors.list = this.prev_mntrs;252 this_thread-> monitors.size = this.prev_count;253 this_thread-> monitors.func = this.prev_func;224 this_thread->current_monitors = this->prev_mntrs; 225 this_thread->current_monitor_count = this->prev_count; 226 this_thread->current_monitor_func = this->prev_func; 254 227 } 255 228 256 229 //----------------------------------------------------------------------------- 257 230 // Internal scheduling types 258 void ?{}(__condition_node_t & this, thread_desc * waiting_thread, unsigned short count, uintptr_t user_info ) { 259 this.waiting_thread = waiting_thread; 260 this.count = count; 261 this.next = NULL; 262 this.user_info = user_info; 263 } 264 265 void ?{}(__condition_criterion_t & this ) { 266 this.ready = false; 267 this.target = NULL; 268 this.owner = NULL; 269 this.next = NULL; 270 } 271 272 void ?{}(__condition_criterion_t & this, monitor_desc * target, __condition_node_t * owner ) { 273 this.ready = false; 274 this.target = target; 275 this.owner = owner; 276 this.next = NULL; 231 232 void ?{}(__condition_node_t * this, thread_desc * waiting_thread, unsigned short count, uintptr_t user_info ) { 233 this->waiting_thread = waiting_thread; 234 this->count = count; 235 this->next = NULL; 236 this->user_info = user_info; 237 } 238 239 void ?{}(__condition_criterion_t * this ) { 240 this->ready = false; 241 this->target = NULL; 242 this->owner = NULL; 243 this->next = NULL; 244 } 245 246 void ?{}(__condition_criterion_t * this, monitor_desc * target, __condition_node_t * owner ) { 247 this->ready = false; 248 this->target = target; 249 this->owner = owner; 250 this->next = NULL; 277 251 } 278 252 … … 297 271 append( &this->blocked, &waiter ); 298 272 299 // Lock all monitors (aggregates the lock sas well)273 // Lock all monitors (aggregates the lock them as well) 300 274 lock_all( monitors, locks, count ); 301 275 276 // DON'T unlock, ask the kernel to do it 277 278 // Save monitor state 279 save_recursion( monitors, recursions, count ); 280 302 281 // Find the next thread(s) to run 303 short thread_count = 0;282 unsigned short thread_count = 0; 304 283 thread_desc * threads[ count ]; 305 284 for(int i = 0; i < count; i++) { … … 307 286 } 308 287 309 // Save monitor states310 monitor_save;311 312 288 // Remove any duplicate threads 313 289 for( int i = 0; i < count; i++) { 314 290 thread_desc * new_owner = next_thread( monitors[i] ); 315 insert_unique( threads, thread_count, new_owner );291 thread_count = insert_unique( threads, thread_count, new_owner ); 316 292 } 317 293 … … 319 295 BlockInternal( locks, count, threads, thread_count ); 320 296 297 298 // WE WOKE UP 299 300 321 301 // We are back, restore the owners and recursions 322 monitor_restore; 302 lock_all( locks, count ); 303 restore_recursion( monitors, recursions, count ); 304 unlock_all( locks, count ); 323 305 } 324 306 … … 333 315 LIB_DEBUG_DO( 334 316 thread_desc * this_thrd = this_thread; 335 if ( this->monitor_count != this_thrd-> monitors.size) {336 abortf( "Signal on condition %p made with different number of monitor(s), expected %i got %i", this, this->monitor_count, this_thrd-> monitors.size);317 if ( this->monitor_count != this_thrd->current_monitor_count ) { 318 abortf( "Signal on condition %p made with different number of monitor(s), expected %i got %i", this, this->monitor_count, this_thrd->current_monitor_count ); 337 319 } 338 320 339 321 for(int i = 0; i < this->monitor_count; i++) { 340 if ( this->monitors[i] != this_thrd-> monitors.list[i] ) {341 abortf( "Signal on condition %p made with different monitor, expected %p got %i", this, this->monitors[i], this_thrd-> monitors.list[i] );322 if ( this->monitors[i] != this_thrd->current_monitors[i] ) { 323 abortf( "Signal on condition %p made with different monitor, expected %p got %i", this, this->monitors[i], this_thrd->current_monitors[i] ); 342 324 } 343 325 } … … 382 364 383 365 //save contexts 384 monitor_save;366 save_recursion( monitors, recursions, count ); 385 367 386 368 //Find the thread to run 387 369 thread_desc * signallee = pop_head( &this->blocked )->waiting_thread; 388 set_owner( monitors, count, signallee ); 370 for(int i = 0; i < count; i++) { 371 set_owner( monitors[i], signallee ); 372 } 389 373 390 374 //Everything is ready to go to sleep … … 395 379 396 380 397 //We are back, restore the masks and recursions 398 monitor_restore; 381 //We are back, restore the owners and recursions 382 lock_all( locks, count ); 383 restore_recursion( monitors, recursions, count ); 384 unlock_all( locks, count ); 399 385 400 386 return true; … … 411 397 412 398 //----------------------------------------------------------------------------- 413 // External scheduling 414 // cases to handle : 415 // - target already there : 416 // block and wake 417 // - dtor already there 418 // put thread on signaller stack 419 // - non-blocking 420 // return else 421 // - timeout 422 // return timeout 423 // - block 424 // setup mask 425 // block 426 void __waitfor_internal( const __waitfor_mask_t & mask, int duration ) { 427 // This statment doesn't have a contiguous list of monitors... 428 // Create one! 429 short max = count_max( mask ); 430 monitor_desc * mon_storage[max]; 431 short actual_count = aggregate( mon_storage, mask ); 432 433 if(actual_count == 0) return; 399 // Internal scheduling 400 int __accept_internal( unsigned short acc_count, __acceptable_t * acceptables ) { 401 thread_desc * thrd = this_thread; 434 402 435 403 // Create storage for monitor context 436 monitor_ctx( mon_storage, actual_count );437 438 // Lock all monitors (aggregates the lock sas well)404 monitor_ctx( acceptables->monitors, acceptables->count ); 405 406 // Lock all monitors (aggregates the lock them as well) 439 407 lock_all( monitors, locks, count ); 440 408 441 { 442 // Check if the entry queue 443 thread_desc * next; int index; 444 [next, index] = search_entry_queue( mask, monitors, count ); 445 446 if( next ) { 447 if( mask.clauses[index].is_dtor ) { 448 #warning case not implemented 449 } 450 else { 451 blockAndWake( &next, 1 ); 452 } 453 454 return index; 455 } 456 } 457 458 459 if( duration == 0 ) { 460 unlock_all( locks, count ); 461 return; 462 } 463 464 465 verifyf( duration < 0, "Timeout on waitfor statments not supported yet."); 466 467 468 monitor_save; 469 set_mask( monitors, count, mask ); 470 471 BlockInternal( locks, count ); // Everything is ready to go to sleep 409 // Create the node specific to this wait operation 410 wait_ctx_primed( thrd, 0 ); 411 412 // Check if the entry queue 413 thread_desc * next = search_entry_queue( acceptables, acc_count, monitors, count ); 414 415 LIB_DEBUG_PRINT_SAFE("Owner(s) :"); 416 for(int i = 0; i < count; i++) { 417 LIB_DEBUG_PRINT_SAFE(" %p", monitors[i]->owner ); 418 } 419 LIB_DEBUG_PRINT_SAFE("\n"); 420 421 LIB_DEBUG_PRINT_SAFE("Passing mon to %p\n", next); 422 423 if( !next ) { 424 // Update acceptables on the current monitors 425 for(int i = 0; i < count; i++) { 426 monitors[i]->acceptables = acceptables; 427 monitors[i]->acceptable_count = acc_count; 428 } 429 } 430 else { 431 for(int i = 0; i < count; i++) { 432 set_owner( monitors[i], next ); 433 } 434 } 435 436 437 save_recursion( monitors, recursions, count ); 438 439 440 // Everything is ready to go to sleep 441 BlockInternal( locks, count, &next, next ? 1 : 0 ); 442 443 472 444 //WE WOKE UP 473 monitor_restore; //We are back, restore the masks and recursions 445 446 447 //We are back, restore the owners and recursions 448 lock_all( locks, count ); 449 restore_recursion( monitors, recursions, count ); 450 int acc_idx = monitors[0]->accepted_index; 451 unlock_all( locks, count ); 452 453 return acc_idx; 474 454 } 475 455 … … 478 458 479 459 static inline void set_owner( monitor_desc * this, thread_desc * owner ) { 480 LIB_DEBUG_PRINT_SAFE("Kernal : Setting owner of %p to %p ( was %p)\n", this, owner, this->owner );481 482 460 //Pass the monitor appropriately 483 461 this->owner = owner; … … 485 463 //We are passing the monitor to someone else, which means recursion level is not 0 486 464 this->recursion = owner ? 1 : 0; 487 }488 489 static inline void set_owner( monitor_desc ** monitors, short count, thread_desc * owner ) {490 for( int i = 0; i < count; i++ ) {491 set_owner( monitors[i], owner );492 }493 }494 495 static inline void set_mask( monitor_desc ** storage, short count, const __waitfor_mask_t & mask ) {496 for(int i = 0; i < count; i++) {497 storage[i]->mask = mask;498 }499 465 } 500 466 … … 519 485 } 520 486 521 static inline bool is_accepted( monitor_desc * this, const __monitor_group_t & group) {522 __acceptable_t * it = this->mask.clauses; // Optim523 int count = this->mask.size;487 static inline int is_accepted( thread_desc * owner, monitor_desc * this, monitor_desc ** group, int group_cnt, void (*func)() ) { 488 __acceptable_t* accs = this->acceptables; // Optim 489 int acc_cnt = this->acceptable_count; 524 490 525 491 // Check if there are any acceptable functions 526 if( ! it ) return false;492 if( !accs ) return -1; 527 493 528 494 // If this isn't the first monitor to test this, there is no reason to repeat the test. 529 if( this != group[0] ) return group[0]-> mask.accepted >= 0;495 if( this != group[0] ) return group[0]->accepted_index; 530 496 531 497 // For all acceptable functions check if this is the current function. 532 for( short i = 0; i < count; i++, it++ ) { 533 if( *it == group ) { 534 *this->mask.accepted = i; 535 return true; 498 OUT_LOOP: 499 for( int i = 0; i < acc_cnt; i++ ) { 500 __acceptable_t * acc = &accs[i]; 501 502 // if function matches, check the monitors 503 if( acc->func == func ) { 504 505 // If the group count is different then it can't be a match 506 if( acc->count != group_cnt ) return -1; 507 508 // Check that all the monitors match 509 for( int j = 0; j < group_cnt; j++ ) { 510 // If not a match, check next function 511 if( acc->monitors[j] != group[j] ) continue OUT_LOOP; 512 } 513 514 // It's a complete match, accept the call 515 return i; 536 516 } 537 517 } 538 518 539 519 // No function matched 540 return false;520 return -1; 541 521 } 542 522 543 523 static inline void init( int count, monitor_desc ** monitors, __condition_node_t * waiter, __condition_criterion_t * criteria ) { 544 524 for(int i = 0; i < count; i++) { 545 ( criteria[i]){ monitors[i], waiter };525 (&criteria[i]){ monitors[i], waiter }; 546 526 } 547 527 … … 551 531 static inline void init_push( int count, monitor_desc ** monitors, __condition_node_t * waiter, __condition_criterion_t * criteria ) { 552 532 for(int i = 0; i < count; i++) { 553 ( criteria[i]){ monitors[i], waiter };533 (&criteria[i]){ monitors[i], waiter }; 554 534 push( &criteria[i].target->signal_stack, &criteria[i] ); 555 535 } … … 584 564 } 585 565 586 static inline void save ( monitor_desc ** ctx, short count, __attribute((unused)) spinlock ** locks, unsigned int * /*out*/ recursions, __waitfor_mask_t * /*out*/ masks ) { 566 567 static inline void save_recursion ( monitor_desc ** ctx, unsigned int * /*out*/ recursions, unsigned short count ) { 587 568 for( int i = 0; i < count; i++ ) { 588 569 recursions[i] = ctx[i]->recursion; 589 masks[i] = ctx[i]->mask; 590 } 591 } 592 593 static inline void restore( monitor_desc ** ctx, short count, spinlock ** locks, unsigned int * /*out*/ recursions, __waitfor_mask_t * /*out*/ masks ) { 594 lock_all( locks, count ); 570 } 571 } 572 573 static inline void restore_recursion( monitor_desc ** ctx, unsigned int * /*in */ recursions, unsigned short count ) { 595 574 for( int i = 0; i < count; i++ ) { 596 575 ctx[i]->recursion = recursions[i]; 597 ctx[i]->mask = masks[i]; 598 } 599 unlock_all( locks, count ); 576 } 600 577 } 601 578 … … 630 607 if( !this->monitors ) { 631 608 // LIB_DEBUG_PRINT_SAFE("Branding\n"); 632 assertf( thrd-> monitors.list != NULL, "No current monitor to brand condition %p", thrd->monitors.list);633 this->monitor_count = thrd-> monitors.size;609 assertf( thrd->current_monitors != NULL, "No current monitor to brand condition %p", thrd->current_monitors ); 610 this->monitor_count = thrd->current_monitor_count; 634 611 635 612 this->monitors = malloc( this->monitor_count * sizeof( *this->monitors ) ); 636 613 for( int i = 0; i < this->monitor_count; i++ ) { 637 this->monitors[i] = thrd->monitors.list[i]; 638 } 639 } 640 } 641 642 static inline [thread_desc *, int] search_entry_queue( const __waitfor_mask_t & mask, monitor_desc ** monitors, int count ) { 614 this->monitors[i] = thrd->current_monitors[i]; 615 } 616 } 617 } 618 619 static inline unsigned short insert_unique( thread_desc ** thrds, unsigned short end, thread_desc * val ) { 620 if( !val ) return end; 621 622 for(int i = 0; i <= end; i++) { 623 if( thrds[i] == val ) return end; 624 } 625 626 thrds[end] = val; 627 return end + 1; 628 } 629 630 static inline bool match( __acceptable_t * acc, thread_desc * thrd ) { 631 verify( thrd ); 632 verify( acc ); 633 if( acc->func != thrd->current_monitor_func ) return false; 634 635 return true; 636 } 637 638 static inline thread_desc * search_entry_queue( __acceptable_t * acceptables, int acc_count, monitor_desc ** monitors, int count ) { 643 639 644 640 __thread_queue_t * entry_queue = &monitors[0]->entry_queue; … … 647 643 for( thread_desc ** thrd_it = &entry_queue->head; 648 644 *thrd_it; 649 thrd_it = &(*thrd_it)->next 650 ){645 thrd_it = &(*thrd_it)->next) 646 { 651 647 // For each acceptable check if it matches 652 int i = 0; 653 __acceptable_t * end = mask.clauses + mask.size; 654 for( __acceptable_t * it = mask.clauses; it != end; it++, i++ ) { 648 __acceptable_t * acc_end = acceptables + acc_count; 649 for( __acceptable_t * acc_it = acceptables; acc_it != acc_end; acc_it++ ) { 655 650 // Check if we have a match 656 if( *it == (*thrd_it)->monitors) {651 if( match( acc_it, *thrd_it ) ) { 657 652 658 653 // If we have a match return it 659 654 // after removeing it from the entry queue 660 return [remove( entry_queue, thrd_it ), i];655 return remove( entry_queue, thrd_it ); 661 656 } 662 657 } 663 658 } 664 659 665 return [0, -1]; 666 } 667 668 forall(dtype T | sized( T )) 669 static inline short insert_unique( T ** array, short & size, T * val ) { 670 if( !val ) return size; 671 672 for(int i = 0; i <= size; i++) { 673 if( array[i] == val ) return size; 674 } 675 676 array[size] = val; 677 size = size + 1; 678 return size; 679 } 680 681 static inline short count_max( const __waitfor_mask_t & mask ) { 682 short max = 0; 683 for( int i = 0; i < mask.size; i++ ) { 684 max += mask.clauses[i].size; 685 } 686 return max; 687 } 688 689 static inline short aggregate( monitor_desc ** storage, const __waitfor_mask_t & mask ) { 690 short size = 0; 691 for( int i = 0; i < mask.size; i++ ) { 692 for( int j = 0; j < mask.clauses[i].size; j++) { 693 insert_unique( storage, size, mask.clauses[i].list[j] ); 694 } 695 } 696 qsort( storage, size ); 697 return size; 698 } 699 700 void ?{}( __condition_blocked_queue_t & this ) { 701 this.head = NULL; 702 this.tail = &this.head; 660 return NULL; 661 } 662 663 void ?{}( __condition_blocked_queue_t * this ) { 664 this->head = NULL; 665 this->tail = &this->head; 703 666 } 704 667
Note:
See TracChangeset
for help on using the changeset viewer.