Ignore:
File:
1 edited

Legend:

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

    r6b33e89 rb93bf85  
    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 = &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         }
     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    }
    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;
     174    select_node node;
     175    active_thread()->link_node = (void *)&node;
    176176        unlock( lock );
    177177
    178         pre_park_then_park( pp_fn, pp_datum );
     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 );
     215    if ( node.park_counter ) __make_select_node_available( node );
     216    unlock( lock );
     217    return true;
     218}
     219
     220bool 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    }
    216237        unlock( lock );
    217         return true;
    218 }
    219 
    220 bool unregister_select( blocking_lock & this, select_node & node ) with(this) {
    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;
     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 ( isListed( *info_thd ) ) {                                  // is thread on queue
     267                if ( (*info_thd)`isListed ) {   // 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 ( isListed( *info_thd ) ) {                                  // is thread on queue
     306                if ( (*info_thd)`isListed ) {   // 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 = ! isEmpty( blocked_threads );
    350                 process_popped(this, remove_first( blocked_threads ));
     349                bool ret = ! blocked_threads`isEmpty;
     350                process_popped(this, try_pop_front( 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 = ! isEmpty( blocked_threads );
    358                 while( ! isEmpty( blocked_threads ) ) {
    359                         process_popped(this, remove_first( blocked_threads ));
     357                bool ret = ! blocked_threads`isEmpty;
     358                while( ! blocked_threads`isEmpty ) {
     359                        process_popped(this, try_pop_front( blocked_threads ));
    360360                }
    361361                unlock( lock );
     
    364364
    365365        uintptr_t front( condition_variable(L) & this ) with(this) {
    366                 return isEmpty( blocked_threads ) ? NULL : first( blocked_threads ).info;
     366                return blocked_threads`isEmpty ? NULL : blocked_threads`first.info;
    367367        }
    368368
    369369        bool empty( condition_variable(L) & this ) with(this) {
    370370                lock( lock __cfaabi_dbg_ctx2 );
    371                 bool ret = isEmpty( blocked_threads );
     371                bool ret = blocked_threads`isEmpty;
    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 = ! isEmpty( blocked_threads );
     457                bool ret = ! blocked_threads`isEmpty;
    458458                if ( ret ) {
    459                         info_thread(L) & popped = remove_first( blocked_threads );
     459                        info_thread(L) & popped = try_pop_front( 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 = ! isEmpty( blocked_threads );
    466                 while( ! isEmpty( blocked_threads ) ) {
    467                         info_thread(L) & popped = remove_first( blocked_threads );
     465                bool ret = ! blocked_threads`isEmpty;
     466                while( ! blocked_threads`isEmpty ) {
     467                        info_thread(L) & popped = try_pop_front( blocked_threads );
    468468                        on_notify(*popped.lock, popped.t);
    469469                }
     
    471471        }
    472472
    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 ); }
     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; }
    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 = ! isEmpty( blocked_threads );
     505                bool ret = ! blocked_threads`isEmpty;
    506506                if ( ret ) {
    507                         info_thread(L) & popped = remove_first( blocked_threads );
     507                        info_thread(L) & popped = try_pop_front( 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 = ! isEmpty( blocked_threads );
    518                 while( ! isEmpty( blocked_threads ) ) {
    519                         info_thread(L) & popped = remove_first( blocked_threads );
     517                bool ret = ! blocked_threads`isEmpty;
     518                while( ! blocked_threads`isEmpty ) {
     519                        info_thread(L) & popped = try_pop_front( 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 isEmpty( blocked_threads ) ? NULL : first( blocked_threads ).info; }
    528         bool empty ( pthread_cond_var(L) & this ) with(this) { return isEmpty( blocked_threads ); }
     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; }
    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         } else {
    606                 unlock( lock );
    607                 return false;
     605        }
     606        else {
     607            unlock( lock );
     608            return false;
    608609        }
    609610}
     
    621622
    622623        // make new owner
    623         if ( doUnpark ) unpark( thrd );
     624        if( doUnpark ) unpark( thrd );
    624625
    625626        return thrd;
Note: See TracChangeset for help on using the changeset viewer.