Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/libcfa/concurrency/monitor.c

    r80c72a7 r38ef0de  
    2525static inline void set_owner( monitor_desc * this, thread_desc * owner );
    2626static inline thread_desc * next_thread( monitor_desc * this );
    27 static inline int is_accepted( thread_desc * owner, monitor_desc * this, monitor_desc ** group, int group_cnt, void (*func)() );
    2827
    2928static inline void lock_all( spinlock ** locks, unsigned short count );
     
    3534static inline void restore_recursion( monitor_desc ** ctx, unsigned int * /*in */ recursions, unsigned short count );
    3635
    37 static inline void init     ( int count, monitor_desc ** monitors, __condition_node_t * waiter, __condition_criterion_t * criteria );
    38 static inline void init_push( int count, monitor_desc ** monitors, __condition_node_t * waiter, __condition_criterion_t * criteria );
    39 
    4036static inline thread_desc * check_condition( __condition_criterion_t * );
    4137static inline void brand_condition( condition * );
    4238static inline unsigned short insert_unique( thread_desc ** thrds, unsigned short end, thread_desc * val );
    4339
    44 static inline thread_desc * search_entry_queue( __acceptable_t * acceptables, int acc_count, monitor_desc ** monitors, int count );
    45 
    46 //-----------------------------------------------------------------------------
    47 // Useful defines
    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                               */ \
    63 
    6440//-----------------------------------------------------------------------------
    6541// Enter/Leave routines
     
    6743
    6844extern "C" {
    69         // Enter single monitor
    70         static void __enter_monitor_desc( monitor_desc * this, monitor_desc ** group, int group_cnt, void (*func)() ) {
    71                 // Lock the monitor spinlock, lock_yield to reduce contention
     45        void __enter_monitor_desc( monitor_desc * this ) {
    7246                lock_yield( &this->lock DEBUG_CTX2 );
    7347                thread_desc * thrd = this_thread;
    7448
    75                 LIB_DEBUG_PRINT_SAFE("Kernel : %10p Entering mon %p (%p)\n", thrd, this, this->owner);
    76 
    77                 this->accepted_index = -1;
     49                // LIB_DEBUG_PRINT_SAFE("%p Entering %p (o: %p, r: %i)\n", thrd, this, this->owner, this->recursion);
     50
    7851                if( !this->owner ) {
    79                         // No one has the monitor, just take it
     52                        //No one has the monitor, just take it
    8053                        set_owner( this, thrd );
    81 
    82                         LIB_DEBUG_PRINT_SAFE("Kernel :  mon is free \n");
    8354                }
    8455                else if( this->owner == thrd) {
    85                         // We already have the monitor, just not how many times we took it
     56                        //We already have the monitor, just not how many times we took it
    8657                        verify( this->recursion > 0 );
    8758                        this->recursion += 1;
    88 
    89                         LIB_DEBUG_PRINT_SAFE("Kernel :  mon already owned \n");
    90                 }
    91                 else if( (this->accepted_index = is_accepted( thrd, this, group, group_cnt, func)) >= 0 ) {
    92                         // Some one was waiting for us, enter
    93                         set_owner( this, thrd );
    94 
    95                         LIB_DEBUG_PRINT_SAFE("Kernel :  mon accepts \n");
    9659                }
    9760                else {
    98                         LIB_DEBUG_PRINT_SAFE("Kernel :  blocking \n");
    99 
    100                         // Some one else has the monitor, wait in line for it
     61                        //Some one else has the monitor, wait in line for it
    10162                        append( &this->entry_queue, thrd );
     63                        // LIB_DEBUG_PRINT_SAFE("%p Blocking on entry\n", thrd);
    10264                        BlockInternal( &this->lock );
    10365
    104                         LIB_DEBUG_PRINT_SAFE("Kernel : %10p Entered  mon %p\n", thrd, this);
    105 
    106                         // BlockInternal will unlock spinlock, no need to unlock ourselves
     66                        //BlockInternal will unlock spinlock, no need to unlock ourselves
    10767                        return;
    10868                }
    10969
    110                 LIB_DEBUG_PRINT_SAFE("Kernel : %10p Entered  mon %p\n", thrd, this);
    111 
    112                 // Release the lock and leave
    11370                unlock( &this->lock );
    11471                return;
    11572        }
    11673
    117         // Leave single monitor
     74        // leave pseudo code :
     75        //      TODO
    11876        void __leave_monitor_desc( monitor_desc * this ) {
    119                 // Lock the monitor spinlock, lock_yield to reduce contention
    12077                lock_yield( &this->lock DEBUG_CTX2 );
    12178
     79                // LIB_DEBUG_PRINT_SAFE("%p Leaving %p (o: %p, r: %i). ", this_thread, this, this->owner, this->recursion);
    12280                verifyf( this_thread == this->owner, "Expected owner to be %p, got %p (r: %i)", this_thread, this->owner, this->recursion );
    12381
    124                 // Leaving a recursion level, decrement the counter
     82                //Leaving a recursion level, decrement the counter
    12583                this->recursion -= 1;
    12684
    127                 // If we haven't left the last level of recursion
    128                 // it means we don't need to do anything
     85                //If we haven't left the last level of recursion
     86                //it means we don't need to do anything
    12987                if( this->recursion != 0) {
    13088                        unlock( &this->lock );
     
    13290                }
    13391
    134                 // Get the next thread, will be null on low contention monitor
    13592                thread_desc * new_owner = next_thread( this );
    13693
    137                 // We can now let other threads in safely
     94                //We can now let other threads in safely
    13895                unlock( &this->lock );
     96
     97                // LIB_DEBUG_PRINT_SAFE("Next owner is %p\n", new_owner);
    13998
    14099                //We need to wake-up the thread
     
    142101        }
    143102
    144         // Leave the thread monitor
    145         // last routine called by a thread.
    146         // Should never return
    147103        void __leave_thread_monitor( thread_desc * thrd ) {
    148104                monitor_desc * this = &thrd->mon;
    149 
    150                 // Lock the monitor now
    151105                lock_yield( &this->lock DEBUG_CTX2 );
    152106
     
    157111                verifyf( thrd == this->owner, "Expected owner to be %p, got %p (r: %i)", thrd, this->owner, this->recursion );
    158112
    159                 // Leaving a recursion level, decrement the counter
     113                //Leaving a recursion level, decrement the counter
    160114                this->recursion -= 1;
    161115
    162                 // If we haven't left the last level of recursion
    163                 // it must mean there is an error
    164                 if( this->recursion != 0) { abortf("Thread internal monitor has unbalanced recursion"); }
    165 
    166                 // Fetch the next thread, can be null
     116                //If we haven't left the last level of recursion
     117                //it means we don't need to do anything
     118                if( this->recursion != 0) {
     119                        unlock( &this->lock );
     120                        return;
     121                }
     122
    167123                thread_desc * new_owner = next_thread( this );
    168124
    169                 // Leave the thread, this will unlock the spinlock
    170                 // Use leave thread instead of BlockInternal which is
    171                 // specialized for this case and supports null new_owner
    172125                LeaveThread( &this->lock, new_owner );
    173 
    174                 // Control flow should never reach here!
    175         }
    176 }
    177 
    178 // Enter multiple monitor
    179 // relies on the monitor array being sorted
    180 static inline void enter(monitor_desc ** monitors, int count, void (*func)() ) {
     126        }
     127}
     128
     129static inline void enter(monitor_desc ** monitors, int count) {
    181130        for(int i = 0; i < count; i++) {
    182                 __enter_monitor_desc( monitors[i], monitors, count, func );
    183         }
    184 }
    185 
    186 // Leave multiple monitor
    187 // relies on the monitor array being sorted
     131                __enter_monitor_desc( monitors[i] );
     132        }
     133}
     134
    188135static inline void leave(monitor_desc ** monitors, int count) {
    189136        for(int i = count - 1; i >= 0; i--) {
     
    192139}
    193140
    194 // Ctor for monitor guard
    195 // Sorts monitors before entering
    196 void ?{}( monitor_guard_t * this, monitor_desc ** m, int count, void (*func)() ) {
    197         // Store current array
     141void ?{}( monitor_guard_t * this, monitor_desc ** m, int count ) {
    198142        this->m = m;
    199143        this->count = count;
    200 
    201         // Sort monitors based on address -> TODO use a sort specialized for small numbers
    202144        qsort(this->m, count);
    203 
    204         // Save previous thread context
     145        enter( this->m, this->count );
     146
    205147        this->prev_mntrs = this_thread->current_monitors;
    206148        this->prev_count = this_thread->current_monitor_count;
    207         this->prev_func  = this_thread->current_monitor_func;
    208 
    209         // Update thread context (needed for conditions)
     149
    210150        this_thread->current_monitors      = m;
    211151        this_thread->current_monitor_count = count;
    212         this_thread->current_monitor_func  = func;
    213 
    214         // Enter the monitors in order
    215         enter( this->m, this->count, func );
    216 }
    217 
    218 // Dtor for monitor guard
     152}
     153
    219154void ^?{}( monitor_guard_t * this ) {
    220         // Leave the monitors in order
    221155        leave( this->m, this->count );
    222156
    223         // Restore thread context
    224157        this_thread->current_monitors      = this->prev_mntrs;
    225158        this_thread->current_monitor_count = this->prev_count;
    226         this_thread->current_monitor_func  = this->prev_func;
    227 }
    228 
    229 //-----------------------------------------------------------------------------
    230 // Internal scheduling types
     159}
    231160
    232161void ?{}(__condition_node_t * this, thread_desc * waiting_thread, unsigned short count, uintptr_t user_info ) {
     
    254183// Internal scheduling
    255184void wait( condition * this, uintptr_t user_info = 0 ) {
     185        // LIB_DEBUG_PRINT_SAFE("Waiting\n");
     186
    256187        brand_condition( this );
    257188
    258         // Check that everything is as expected
     189        //Check that everything is as expected
    259190        assertf( this->monitors != NULL, "Waiting with no monitors (%p)", this->monitors );
    260191        verifyf( this->monitor_count != 0, "Waiting with 0 monitors (%i)", this->monitor_count );
    261192        verifyf( this->monitor_count < 32u, "Excessive monitor count (%i)", this->monitor_count );
    262193
    263         // Create storage for monitor context
    264         monitor_ctx( this->monitors, this->monitor_count );
    265 
    266         // Create the node specific to this wait operation
    267         wait_ctx( this_thread, user_info );
    268 
    269         // Append the current wait operation to the ones already queued on the condition
    270         // We don't need locks for that since conditions must always be waited on inside monitor mutual exclusion
     194        unsigned short count = this->monitor_count;
     195        unsigned int recursions[ count ];               //Save the current recursion levels to restore them later
     196        spinlock *   locks     [ count ];               //We need to pass-in an array of locks to BlockInternal
     197
     198        // LIB_DEBUG_PRINT_SAFE("count %i\n", count);
     199
     200        __condition_node_t waiter = { (thread_desc*)this_thread, count, user_info };
     201
     202        __condition_criterion_t criteria[count];
     203        for(int i = 0; i < count; i++) {
     204                (&criteria[i]){ this->monitors[i], &waiter };
     205                // LIB_DEBUG_PRINT_SAFE( "Criterion %p\n", &criteria[i] );
     206        }
     207
     208        waiter.criteria = criteria;
    271209        append( &this->blocked, &waiter );
    272210
    273         // Lock all monitors (aggregates the lock them as well)
    274         lock_all( monitors, locks, count );
    275 
    276         // DON'T unlock, ask the kernel to do it
    277 
    278         // Save monitor state
    279         save_recursion( monitors, recursions, count );
    280 
    281         // Find the next thread(s) to run
     211        lock_all( this->monitors, locks, count );
     212        save_recursion( this->monitors, recursions, count );
     213        //DON'T unlock, ask the kernel to do it
     214
     215        //Find the next thread(s) to run
    282216        unsigned short thread_count = 0;
    283217        thread_desc * threads[ count ];
     
    286220        }
    287221
    288         // Remove any duplicate threads
    289222        for( int i = 0; i < count; i++) {
    290                 thread_desc * new_owner = next_thread( monitors[i] );
     223                thread_desc * new_owner = next_thread( this->monitors[i] );
    291224                thread_count = insert_unique( threads, thread_count, new_owner );
    292225        }
     226
     227        // LIB_DEBUG_PRINT_SAFE("Will unblock: ");
     228        for(int i = 0; i < thread_count; i++) {
     229                // LIB_DEBUG_PRINT_SAFE("%p ", threads[i]);
     230        }
     231        // LIB_DEBUG_PRINT_SAFE("\n");
    293232
    294233        // Everything is ready to go to sleep
     
    296235
    297236
    298         // WE WOKE UP
    299 
    300 
    301         // We are back, restore the owners and recursions
     237        //WE WOKE UP
     238
     239
     240        //We are back, restore the owners and recursions
    302241        lock_all( locks, count );
    303         restore_recursion( monitors, recursions, count );
     242        restore_recursion( this->monitors, recursions, count );
    304243        unlock_all( locks, count );
    305244}
    306245
    307246bool signal( condition * this ) {
    308         if( is_empty( this ) ) { return false; }
     247        if( is_empty( this ) ) {
     248                // LIB_DEBUG_PRINT_SAFE("Nothing to signal\n");
     249                return false;
     250        }
    309251
    310252        //Check that everything is as expected
    311253        verify( this->monitors );
    312254        verify( this->monitor_count != 0 );
     255
     256        unsigned short count = this->monitor_count;
    313257
    314258        //Some more checking in debug
     
    317261                if ( this->monitor_count != this_thrd->current_monitor_count ) {
    318262                        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 );
    319                 }
     263                } // if
    320264
    321265                for(int i = 0; i < this->monitor_count; i++) {
    322266                        if ( this->monitors[i] != this_thrd->current_monitors[i] ) {
    323267                                abortf( "Signal on condition %p made with different monitor, expected %p got %i", this, this->monitors[i], this_thrd->current_monitors[i] );
    324                         }
     268                        } // if
    325269                }
    326270        );
    327271
    328         unsigned short count = this->monitor_count;
    329 
    330         // Lock all monitors
     272        //Lock all the monitors
    331273        lock_all( this->monitors, NULL, count );
     274        // LIB_DEBUG_PRINT_SAFE("Signalling");
    332275
    333276        //Pop the head of the waiting queue
     
    337280        for(int i = 0; i < count; i++) {
    338281                __condition_criterion_t * crit = &node->criteria[i];
     282                // LIB_DEBUG_PRINT_SAFE(" %p", crit->target);
    339283                assert( !crit->ready );
    340284                push( &crit->target->signal_stack, crit );
    341285        }
    342286
     287        // LIB_DEBUG_PRINT_SAFE("\n");
     288
    343289        //Release
    344290        unlock_all( this->monitors, count );
     
    348294
    349295bool signal_block( condition * this ) {
    350         if( !this->blocked.head ) { return false; }
     296        if( !this->blocked.head ) {
     297                LIB_DEBUG_PRINT_SAFE("Nothing to signal\n");
     298                return false;
     299        }
    351300
    352301        //Check that everything is as expected
     
    354303        verifyf( this->monitor_count != 0, "Waiting with 0 monitors (%i)", this->monitor_count );
    355304
    356         // Create storage for monitor context
    357         monitor_ctx( this->monitors, this->monitor_count );
    358 
    359         // Lock all monitors (aggregates the locks them as well)
    360         lock_all( monitors, locks, count );
    361 
    362         // Create the node specific to this wait operation
    363         wait_ctx_primed( this_thread, 0 )
     305        unsigned short count = this->monitor_count;
     306        unsigned int recursions[ count ];               //Save the current recursion levels to restore them later
     307        spinlock *   locks     [ count ];               //We need to pass-in an array of locks to BlockInternal
     308
     309        lock_all( this->monitors, locks, count );
     310
     311        //create creteria
     312        __condition_node_t waiter = { (thread_desc*)this_thread, count, 0 };
     313
     314        __condition_criterion_t criteria[count];
     315        for(int i = 0; i < count; i++) {
     316                (&criteria[i]){ this->monitors[i], &waiter };
     317                // LIB_DEBUG_PRINT_SAFE( "Criterion %p\n", &criteria[i] );
     318                push( &criteria[i].target->signal_stack, &criteria[i] );
     319        }
     320
     321        waiter.criteria = criteria;
    364322
    365323        //save contexts
    366         save_recursion( monitors, recursions, count );
     324        save_recursion( this->monitors, recursions, count );
    367325
    368326        //Find the thread to run
    369327        thread_desc * signallee = pop_head( &this->blocked )->waiting_thread;
    370328        for(int i = 0; i < count; i++) {
    371                 set_owner( monitors[i], signallee );
    372         }
     329                set_owner( this->monitors[i], signallee );
     330        }
     331
     332        LIB_DEBUG_PRINT_SAFE( "Waiting on signal block\n" );
    373333
    374334        //Everything is ready to go to sleep
     
    376336
    377337
    378         // WE WOKE UP
    379 
     338
     339
     340        LIB_DEBUG_PRINT_SAFE( "Back from signal block\n" );
    380341
    381342        //We are back, restore the owners and recursions
    382343        lock_all( locks, count );
    383         restore_recursion( monitors, recursions, count );
     344        restore_recursion( this->monitors, recursions, count );
    384345        unlock_all( locks, count );
    385346
     
    387348}
    388349
    389 // Access the user_info of the thread waiting at the front of the queue
    390350uintptr_t front( condition * this ) {
    391351        verifyf( !is_empty(this),
     
    398358//-----------------------------------------------------------------------------
    399359// Internal scheduling
    400 int __accept_internal( unsigned short acc_count, __acceptable_t * acceptables ) {
    401         thread_desc * thrd = this_thread;
    402 
    403         // Create storage for monitor context
    404         monitor_ctx( acceptables->monitors, acceptables->count );
    405 
    406         // Lock all monitors (aggregates the lock them as well)
    407         lock_all( monitors, locks, count );
    408 
    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 
    444         //WE WOKE UP
    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;
     360void __accept_internal( unsigned short count, __acceptable_t * acceptables, void (*func)(void) ) {
     361        // thread_desc * this = this_thread;
     362
     363        // unsigned short count = this->current_monitor_count;
     364        // unsigned int recursions[ count ];            //Save the current recursion levels to restore them later
     365        // spinlock *   locks     [ count ];            //We need to pass-in an array of locks to BlockInternal
     366
     367        // lock_all( this->current_monitors, locks, count );
     368
     369
     370
     371
     372
     373        // // // Everything is ready to go to sleep
     374        // // BlockInternal( locks, count, threads, thread_count );
     375
     376
     377        // //WE WOKE UP
     378
     379
     380        // //We are back, restore the owners and recursions
     381        // lock_all( locks, count );
     382        // restore_recursion( this->monitors, recursions, count );
     383        // unlock_all( locks, count );
    454384}
    455385
     
    485415}
    486416
    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;
    490 
    491         // Check if there are any acceptable functions
    492         if( !accs ) return -1;
    493 
    494         // If this isn't the first monitor to test this, there is no reason to repeat the test.
    495         if( this != group[0] ) return group[0]->accepted_index;
    496 
    497         // For all acceptable functions check if this is the current function.
    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;
    516                 }
    517         }
    518 
    519         // No function matched
    520         return -1;
    521 }
    522 
    523 static inline void init( int count, monitor_desc ** monitors, __condition_node_t * waiter, __condition_criterion_t * criteria ) {
    524         for(int i = 0; i < count; i++) {
    525                 (&criteria[i]){ monitors[i], waiter };
    526         }
    527 
    528         waiter->criteria = criteria;
    529 }
    530 
    531 static inline void init_push( int count, monitor_desc ** monitors, __condition_node_t * waiter, __condition_criterion_t * criteria ) {
    532         for(int i = 0; i < count; i++) {
    533                 (&criteria[i]){ monitors[i], waiter };
    534                 push( &criteria[i].target->signal_stack, &criteria[i] );
    535         }
    536 
    537         waiter->criteria = criteria;
    538 }
    539 
    540417static inline void lock_all( spinlock ** locks, unsigned short count ) {
    541418        for( int i = 0; i < count; i++ ) {
     
    628505}
    629506
    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 ) {
    639 
    640         __thread_queue_t * entry_queue = &monitors[0]->entry_queue;
    641 
    642         // For each thread in the entry-queue
    643         for(    thread_desc ** thrd_it = &entry_queue->head;
    644                 *thrd_it;
    645                 thrd_it = &(*thrd_it)->next)
    646         {
    647                 // For each acceptable check if it matches
    648                 __acceptable_t * acc_end = acceptables + acc_count;
    649                 for( __acceptable_t * acc_it = acceptables; acc_it != acc_end; acc_it++ ) {
    650                         // Check if we have a match
    651                         if( match( acc_it, *thrd_it ) ) {
    652 
    653                                 // If we have a match return it
    654                                 // after removeing it from the entry queue
    655                                 return remove( entry_queue, thrd_it );
    656                         }
    657                 }
    658         }
    659 
    660         return NULL;
    661 }
    662 
    663507void ?{}( __condition_blocked_queue_t * this ) {
    664508        this->head = NULL;
Note: See TracChangeset for help on using the changeset viewer.