Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/concurrency/locks.cfa

    rb93bf85 r6b33e89  
    7979        // lock is held by some other thread
    8080        if ( owner != 0p && owner != thrd ) {
    81         select_node node;
     81                select_node node;
    8282                insert_last( blocked_threads, node );
    8383                wait_count++;
    8484                unlock( lock );
    8585                park( );
    86         return;
     86                return;
    8787        } else if ( owner == thrd && multi_acquisition ) { // multi acquisition lock is held by current thread
    8888                recursion_count++;
     
    9191                recursion_count = 1;
    9292        }
    93     unlock( lock );
     93        unlock( lock );
    9494}
    9595
     
    115115
    116116static inline void pop_node( blocking_lock & this ) with( this ) {
    117     __handle_waituntil_OR( blocked_threads );
    118     select_node * node = &try_pop_front( blocked_threads );
    119     if ( node ) {
    120         wait_count--;
    121         owner = node->blocked_thread;
    122         recursion_count = 1;
    123         // if ( !node->clause_status || __make_select_node_available( *node ) ) unpark( node->blocked_thread );
    124         wake_one( blocked_threads, *node );
    125     } else {
    126         owner = 0p;
    127         recursion_count = 0;
    128     }
     117        __handle_waituntil_OR( blocked_threads );
     118        select_node * node = &remove_first( blocked_threads );
     119        if ( node ) {
     120                wait_count--;
     121                owner = node->blocked_thread;
     122                recursion_count = 1;
     123                // if ( !node->clause_status || __make_select_node_available( *node ) ) unpark( node->blocked_thread );
     124                wake_one( blocked_threads, *node );
     125        } else {
     126                owner = 0p;
     127                recursion_count = 0;
     128        }
    129129}
    130130
     
    160160                unpark( t );
    161161        }
    162     unlock( lock );
     162        unlock( lock );
    163163}
    164164
     
    172172        pop_node( this );
    173173
    174     select_node node;
    175     active_thread()->link_node = (void *)&node;
    176         unlock( lock );
    177 
    178     pre_park_then_park( pp_fn, pp_datum );
     174        select_node node;
     175        active_thread()->link_node = (void *)&node;
     176        unlock( lock );
     177
     178        pre_park_then_park( pp_fn, pp_datum );
    179179
    180180        return ret;
     
    187187// waituntil() support
    188188bool register_select( blocking_lock & this, select_node & node ) with(this) {
    189     lock( lock __cfaabi_dbg_ctx2 );
     189        lock( lock __cfaabi_dbg_ctx2 );
    190190        thread$ * thrd = active_thread();
    191191
     
    193193        /* paranoid */ verifyf( owner != thrd || multi_acquisition, "Single acquisition lock holder (%p) attempted to reacquire the lock %p resulting in a deadlock.", owner, &this );
    194194
    195     if ( !node.park_counter && ( (owner == thrd && multi_acquisition) || owner == 0p ) ) { // OR special case
    196         if ( !__make_select_node_available( node ) ) { // we didn't win the race so give up on registering
    197            unlock( lock );
    198            return false;
    199         }
    200     }
     195        if ( !node.park_counter && ( (owner == thrd && multi_acquisition) || owner == 0p ) ) { // OR special case
     196                if ( !__make_select_node_available( node ) ) { // we didn't win the race so give up on registering
     197                        unlock( lock );
     198                        return false;
     199                }
     200        }
    201201
    202202        // lock is held by some other thread
     
    205205                wait_count++;
    206206                unlock( lock );
    207         return false;
     207                return false;
    208208        } else if ( owner == thrd && multi_acquisition ) { // multi acquisition lock is held by current thread
    209209                recursion_count++;
     
    213213        }
    214214
    215     if ( node.park_counter ) __make_select_node_available( node );
    216     unlock( lock );
    217     return true;
     215        if ( node.park_counter ) __make_select_node_available( node );
     216        unlock( lock );
     217        return true;
    218218}
    219219
    220220bool unregister_select( blocking_lock & this, select_node & node ) with(this) {
    221     lock( lock __cfaabi_dbg_ctx2 );
    222     if ( node`isListed ) {
    223         remove( node );
    224         wait_count--;
    225         unlock( lock );
    226         return false;
    227     }
    228    
    229     if ( owner == active_thread() ) {
    230         /* paranoid */ verifyf( recursion_count == 1 || multi_acquisition, "Thread %p attempted to unlock owner lock %p in waituntil unregister, which is not recursive but has a recursive count of %zu", active_thread(), &this, recursion_count );
    231         // if recursion count is zero release lock and set new owner if one is waiting
    232         recursion_count--;
    233         if ( recursion_count == 0 ) {
    234             pop_node( this );
    235         }
    236     }
    237         unlock( lock );
    238     return false;
     221        lock( lock __cfaabi_dbg_ctx2 );
     222        if ( isListed( node ) ) {
     223                remove( node );
     224                wait_count--;
     225                unlock( lock );
     226                return false;
     227        }
     228       
     229        if ( owner == active_thread() ) {
     230                /* paranoid */ verifyf( recursion_count == 1 || multi_acquisition, "Thread %p attempted to unlock owner lock %p in waituntil unregister, which is not recursive but has a recursive count of %zu", active_thread(), &this, recursion_count );
     231                // if recursion count is zero release lock and set new owner if one is waiting
     232                recursion_count--;
     233                if ( recursion_count == 0 ) {
     234                        pop_node( this );
     235                }
     236        }
     237        unlock( lock );
     238        return false;
    239239}
    240240
     
    265265                //      may still be called after a thread has been removed from the queue but
    266266                //      before the alarm is unregistered
    267                 if ( (*info_thd)`isListed ) {   // is thread on queue
     267                if ( isListed( *info_thd ) ) {                                  // is thread on queue
    268268                        info_thd->signalled = false;
    269269                        // remove this thread O(1)
    270270                        remove( *info_thd );
    271271                        cond->count--;
    272                         if( info_thd->lock ) {
     272                        if ( info_thd->lock ) {
    273273                                // call lock's on_notify if a lock was passed
    274274                                on_notify(*info_thd->lock, info_thd->t);
     
    304304                //      may still be called after a thread has been removed from the queue but
    305305                //      before the alarm is unregistered
    306                 if ( (*info_thd)`isListed ) {   // is thread on queue
     306                if ( isListed( *info_thd ) ) {                                  // is thread on queue
    307307                        info_thd->signalled = false;
    308308                        // remove this thread O(1)
     
    332332
    333333        static void process_popped( condition_variable(L) & this, info_thread(L) & popped ) with( this ) {
    334                 if(&popped != 0p) {
     334                if (&popped != 0p) {
    335335                        popped.signalled = true;
    336336                        count--;
     
    347347        bool notify_one( condition_variable(L) & this ) with( this ) {
    348348                lock( lock __cfaabi_dbg_ctx2 );
    349                 bool ret = ! blocked_threads`isEmpty;
    350                 process_popped(this, try_pop_front( blocked_threads ));
     349                bool ret = ! isEmpty( blocked_threads );
     350                process_popped(this, remove_first( blocked_threads ));
    351351                unlock( lock );
    352352                return ret;
     
    355355        bool notify_all( condition_variable(L) & this ) with(this) {
    356356                lock( lock __cfaabi_dbg_ctx2 );
    357                 bool ret = ! blocked_threads`isEmpty;
    358                 while( ! blocked_threads`isEmpty ) {
    359                         process_popped(this, try_pop_front( blocked_threads ));
     357                bool ret = ! isEmpty( blocked_threads );
     358                while( ! isEmpty( blocked_threads ) ) {
     359                        process_popped(this, remove_first( blocked_threads ));
    360360                }
    361361                unlock( lock );
     
    364364
    365365        uintptr_t front( condition_variable(L) & this ) with(this) {
    366                 return blocked_threads`isEmpty ? NULL : blocked_threads`first.info;
     366                return isEmpty( blocked_threads ) ? NULL : first( blocked_threads ).info;
    367367        }
    368368
    369369        bool empty( condition_variable(L) & this ) with(this) {
    370370                lock( lock __cfaabi_dbg_ctx2 );
    371                 bool ret = blocked_threads`isEmpty;
     371                bool ret = isEmpty( blocked_threads );
    372372                unlock( lock );
    373373                return ret;
     
    382382        }
    383383
    384     static size_t block_and_get_recursion( info_thread(L) & i, __cfa_pre_park pp_fn, void * pp_datum ) {
    385         size_t recursion_count = 0;
     384        static size_t block_and_get_recursion( info_thread(L) & i, __cfa_pre_park pp_fn, void * pp_datum ) {
     385                size_t recursion_count = 0;
    386386                if ( i.lock ) // if lock was passed get recursion count to reset to after waking thread
    387387                        recursion_count = on_wait( *i.lock, pp_fn, pp_datum ); // this call blocks
    388388                else
    389             pre_park_then_park( pp_fn, pp_datum );
    390         return recursion_count;
    391     }
    392     static size_t block_and_get_recursion( info_thread(L) & i ) { return block_and_get_recursion( i, pre_park_noop, 0p ); }
     389                        pre_park_then_park( pp_fn, pp_datum );
     390                return recursion_count;
     391        }
     392        static size_t block_and_get_recursion( info_thread(L) & i ) { return block_and_get_recursion( i, pre_park_noop, 0p ); }
    393393
    394394        // helper for wait()'s' with no timeout
    395395        static void queue_info_thread( condition_variable(L) & this, info_thread(L) & i ) with(this) {
    396396                lock( lock __cfaabi_dbg_ctx2 );
    397         enqueue_thread( this, &i );
     397                enqueue_thread( this, &i );
    398398                unlock( lock );
    399399
    400400                // blocks here
    401         size_t recursion_count = block_and_get_recursion( i );
     401                size_t recursion_count = block_and_get_recursion( i );
    402402
    403403                // resets recursion count here after waking
     
    409409                queue_info_thread( this, i );
    410410
    411     static void cond_alarm_register( void * node_ptr ) { register_self( (alarm_node_t *)node_ptr ); }
     411        static void cond_alarm_register( void * node_ptr ) { register_self( (alarm_node_t *)node_ptr ); }
    412412
    413413        // helper for wait()'s' with a timeout
    414414        static void queue_info_thread_timeout( condition_variable(L) & this, info_thread(L) & info, Duration t, Alarm_Callback callback ) with(this) {
    415415                lock( lock __cfaabi_dbg_ctx2 );
    416         enqueue_thread( this, &info );
     416                enqueue_thread( this, &info );
    417417                alarm_node_wrap(L) node_wrap = { t, 0`s, callback, &this, &info };
    418418                unlock( lock );
    419419
    420420                // blocks here and registers alarm node before blocking after releasing locks to avoid deadlock
    421         size_t recursion_count = block_and_get_recursion( info, cond_alarm_register, (void *)(&node_wrap.alarm_node) );
     421                size_t recursion_count = block_and_get_recursion( info, cond_alarm_register, (void *)(&node_wrap.alarm_node) );
    422422                // park();
    423423
     
    434434                return i.signalled;
    435435
    436         void wait( condition_variable(L) & this                        ) with(this) { WAIT( 0, 0p    ) }
    437         void wait( condition_variable(L) & this, uintptr_t info        ) with(this) { WAIT( info, 0p ) }
    438         void wait( condition_variable(L) & this, L & l                 ) with(this) { WAIT( 0, &l    ) }
     436        void wait( condition_variable(L) & this ) with(this) { WAIT( 0, 0p ) }
     437        void wait( condition_variable(L) & this, uintptr_t info ) with(this) { WAIT( info, 0p ) }
     438        void wait( condition_variable(L) & this, L & l  ) with(this) { WAIT( 0, &l ) }
    439439        void wait( condition_variable(L) & this, L & l, uintptr_t info ) with(this) { WAIT( info, &l ) }
    440440
    441         bool wait( condition_variable(L) & this, Duration duration                        ) with(this) { WAIT_TIME( 0  , 0p , duration ) }
    442         bool wait( condition_variable(L) & this, uintptr_t info, Duration duration        ) with(this) { WAIT_TIME( info, 0p , duration ) }
    443         bool wait( condition_variable(L) & this, L & l, Duration duration                 ) with(this) { WAIT_TIME( 0  , &l , duration ) }
     441        bool wait( condition_variable(L) & this, Duration duration ) with(this) { WAIT_TIME( 0 , 0p , duration ) }
     442        bool wait( condition_variable(L) & this, uintptr_t info, Duration duration ) with(this) { WAIT_TIME( info, 0p , duration ) }
     443        bool wait( condition_variable(L) & this, L & l, Duration duration  ) with(this) { WAIT_TIME( 0 , &l , duration ) }
    444444        bool wait( condition_variable(L) & this, L & l, uintptr_t info, Duration duration ) with(this) { WAIT_TIME( info, &l , duration ) }
    445445
    446446        //-----------------------------------------------------------------------------
    447447        // fast_cond_var
    448         void  ?{}( fast_cond_var(L) & this ){
     448        void ?{}( fast_cond_var(L) & this ){
    449449                this.blocked_threads{};
    450450                #ifdef __CFA_DEBUG__
     
    455455
    456456        bool notify_one( fast_cond_var(L) & this ) with(this) {
    457                 bool ret = ! blocked_threads`isEmpty;
     457                bool ret = ! isEmpty( blocked_threads );
    458458                if ( ret ) {
    459                         info_thread(L) & popped = try_pop_front( blocked_threads );
     459                        info_thread(L) & popped = remove_first( blocked_threads );
    460460                        on_notify(*popped.lock, popped.t);
    461461                }
     
    463463        }
    464464        bool notify_all( fast_cond_var(L) & this ) with(this) {
    465                 bool ret = ! blocked_threads`isEmpty;
    466                 while( ! blocked_threads`isEmpty ) {
    467                         info_thread(L) & popped = try_pop_front( blocked_threads );
     465                bool ret = ! isEmpty( blocked_threads );
     466                while( ! isEmpty( blocked_threads ) ) {
     467                        info_thread(L) & popped = remove_first( blocked_threads );
    468468                        on_notify(*popped.lock, popped.t);
    469469                }
     
    471471        }
    472472
    473         uintptr_t front( fast_cond_var(L) & this ) with(this) { return blocked_threads`isEmpty ? NULL : blocked_threads`first.info; }
    474         bool empty ( fast_cond_var(L) & this ) with(this) { return blocked_threads`isEmpty; }
     473        uintptr_t front( fast_cond_var(L) & this ) with(this) { return isEmpty( blocked_threads ) ? NULL : first( blocked_threads ).info; }
     474        bool empty ( fast_cond_var(L) & this ) with(this) { return isEmpty( blocked_threads ); }
    475475
    476476        void wait( fast_cond_var(L) & this, L & l ) {
     
    494494        // pthread_cond_var
    495495
    496         void  ?{}( pthread_cond_var(L) & this ) with(this) {
     496        void ?{}( pthread_cond_var(L) & this ) with(this) {
    497497                blocked_threads{};
    498498                lock{};
     
    503503        bool notify_one( pthread_cond_var(L) & this ) with(this) {
    504504                lock( lock __cfaabi_dbg_ctx2 );
    505                 bool ret = ! blocked_threads`isEmpty;
     505                bool ret = ! isEmpty( blocked_threads );
    506506                if ( ret ) {
    507                         info_thread(L) & popped = try_pop_front( blocked_threads );
     507                        info_thread(L) & popped = remove_first( blocked_threads );
    508508                        popped.signalled = true;
    509509                        on_notify(*popped.lock, popped.t);
     
    515515        bool notify_all( pthread_cond_var(L) & this ) with(this) {
    516516                lock( lock __cfaabi_dbg_ctx2 );
    517                 bool ret = ! blocked_threads`isEmpty;
    518                 while( ! blocked_threads`isEmpty ) {
    519                         info_thread(L) & popped = try_pop_front( blocked_threads );
     517                bool ret = ! isEmpty( blocked_threads );
     518                while( ! isEmpty( blocked_threads ) ) {
     519                        info_thread(L) & popped = remove_first( blocked_threads );
    520520                        popped.signalled = true;
    521521                        on_notify(*popped.lock, popped.t);
     
    525525        }
    526526
    527         uintptr_t front( pthread_cond_var(L) & this ) with(this) { return blocked_threads`isEmpty ? NULL : blocked_threads`first.info; }
    528         bool empty ( pthread_cond_var(L) & this ) with(this) { return blocked_threads`isEmpty; }
     527        uintptr_t front( pthread_cond_var(L) & this ) with(this) { return isEmpty( blocked_threads ) ? NULL : first( blocked_threads ).info; }
     528        bool empty ( pthread_cond_var(L) & this ) with(this) { return isEmpty( blocked_threads ); }
    529529
    530530        static void queue_info_thread_timeout( pthread_cond_var(L) & this, info_thread(L) & info, Duration t, Alarm_Callback callback ) with(this) {
    531531                lock( lock __cfaabi_dbg_ctx2 );
    532         insert_last( blocked_threads, info );
     532                insert_last( blocked_threads, info );
    533533                pthread_alarm_node_wrap(L) node_wrap = { t, 0`s, callback, &this, &info };
    534534                unlock( lock );
    535535
    536536                // blocks here and registers alarm node before blocking after releasing locks to avoid deadlock
    537         size_t recursion_count = block_and_get_recursion( info, cond_alarm_register, (void *)(&node_wrap.alarm_node) );
     537                size_t recursion_count = block_and_get_recursion( info, cond_alarm_register, (void *)(&node_wrap.alarm_node) );
    538538
    539539                // unregisters alarm so it doesn't go off if signal happens first
     
    551551                lock( lock __cfaabi_dbg_ctx2 );
    552552                info_thread( L ) i = { active_thread(), info, &l };
    553         insert_last( blocked_threads, i );
    554                 unlock( lock );
    555 
    556         // blocks here
     553                insert_last( blocked_threads, i );
     554                unlock( lock );
     555
     556                // blocks here
    557557                size_t recursion_count = block_and_get_recursion( i );
    558558
     
    579579        }
    580580       
    581         bool wait( pthread_cond_var(L) & this, L & l, uintptr_t info, timespec t  ) {
     581        bool wait( pthread_cond_var(L) & this, L & l, uintptr_t info, timespec t ) {
    582582                PTHREAD_WAIT_TIME( info, &l , getDuration( t ) )
    583583        }
     
    585585//-----------------------------------------------------------------------------
    586586// Semaphore
    587 void  ?{}( semaphore & this, int count = 1 ) {
     587void ?{}( semaphore & this, int count = 1 ) {
    588588        (this.lock){};
    589589        this.count = count;
     
    603603                park();
    604604                return true;
    605         }
    606         else {
    607             unlock( lock );
    608             return false;
     605        } else {
     606                unlock( lock );
     607                return false;
    609608        }
    610609}
     
    622621
    623622        // make new owner
    624         if( doUnpark ) unpark( thrd );
     623        if ( doUnpark ) unpark( thrd );
    625624
    626625        return thrd;
Note: See TracChangeset for help on using the changeset viewer.