Ignore:
Timestamp:
May 1, 2023, 4:00:06 PM (13 months ago)
Author:
caparsons <caparson@…>
Branches:
ADT, ast-experimental, master
Children:
73bf7ddc
Parents:
bb7422a
Message:

some cleanup and a bunch of changes to support waituntil statement

File:
1 edited

Legend:

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

    rbb7422a rbeeff61e  
    7979        // lock is held by some other thread
    8080        if ( owner != 0p && owner != thrd ) {
    81                 insert_last( blocked_threads, *thrd );
     81        select_node node;
     82                insert_last( blocked_threads, node );
    8283                wait_count++;
    8384                unlock( lock );
    8485                park( );
    85         }
    86         // multi acquisition lock is held by current thread
    87         else if ( owner == thrd && multi_acquisition ) {
     86        return;
     87        } else if ( owner == thrd && multi_acquisition ) { // multi acquisition lock is held by current thread
    8888                recursion_count++;
    89                 unlock( lock );
    90         }
    91         // lock isn't held
    92         else {
     89        } else {  // lock isn't held
    9390                owner = thrd;
    9491                recursion_count = 1;
    95                 unlock( lock );
    96         }
     92        }
     93    unlock( lock );
    9794}
    9895
     
    117114}
    118115
    119 static void pop_and_set_new_owner( blocking_lock & this ) with( this ) {
    120         thread$ * t = &try_pop_front( blocked_threads );
    121         owner = t;
    122         recursion_count = ( t ? 1 : 0 );
    123         if ( t ) wait_count--;
    124         unpark( t );
     116// static void pop_and_set_new_owner( blocking_lock & this ) with( this ) {
     117//      thread$ * t = &try_pop_front( blocked_threads );
     118//      owner = t;
     119//      recursion_count = ( t ? 1 : 0 );
     120//      if ( t ) wait_count--;
     121//      unpark( t );
     122// }
     123
     124static inline void pop_node( blocking_lock & this ) with( this ) {
     125    __handle_waituntil_OR( blocked_threads );
     126    select_node * node = &try_pop_front( blocked_threads );
     127    if ( node ) {
     128        wait_count--;
     129        owner = node->blocked_thread;
     130        recursion_count = 1;
     131        // if ( !node->clause_status || __make_select_node_available( *node ) ) unpark( node->blocked_thread );
     132        wake_one( blocked_threads, *node );
     133    } else {
     134        owner = 0p;
     135        recursion_count = 0;
     136    }
    125137}
    126138
     
    134146        recursion_count--;
    135147        if ( recursion_count == 0 ) {
    136                 pop_and_set_new_owner( this );
     148                pop_node( this );
    137149        }
    138150        unlock( lock );
     
    147159        // lock held
    148160        if ( owner != 0p ) {
    149                 insert_last( blocked_threads, *t );
     161                insert_last( blocked_threads, *(select_node *)t->link_node );
    150162                wait_count++;
    151                 unlock( lock );
    152163        }
    153164        // lock not held
     
    156167                recursion_count = 1;
    157168                unpark( t );
    158                 unlock( lock );
    159         }
     169        }
     170    unlock( lock );
    160171}
    161172
     
    167178        size_t ret = recursion_count;
    168179
    169         pop_and_set_new_owner( this );
     180        pop_node( this );
     181
     182    select_node node;
     183    active_thread()->link_node = (void *)&node;
    170184        unlock( lock );
     185
     186    park();
     187
    171188        return ret;
    172189}
     
    175192        recursion_count = recursion;
    176193}
     194
     195// waituntil() support
     196bool register_select( blocking_lock & this, select_node & node ) with(this) {
     197    lock( lock __cfaabi_dbg_ctx2 );
     198        thread$ * thrd = active_thread();
     199
     200        // single acquisition lock is held by current thread
     201        /* paranoid */ verifyf( owner != thrd || multi_acquisition, "Single acquisition lock holder (%p) attempted to reacquire the lock %p resulting in a deadlock.", owner, &this );
     202
     203    if ( !node.park_counter && ( (owner == thrd && multi_acquisition) || owner == 0p ) ) { // OR special case
     204        if ( !__make_select_node_available( node ) ) { // we didn't win the race so give up on registering
     205           unlock( lock );
     206           return false;
     207        }
     208    }
     209
     210        // lock is held by some other thread
     211        if ( owner != 0p && owner != thrd ) {
     212                insert_last( blocked_threads, node );
     213                wait_count++;
     214                unlock( lock );
     215        return false;
     216        } else if ( owner == thrd && multi_acquisition ) { // multi acquisition lock is held by current thread
     217                recursion_count++;
     218        } else {  // lock isn't held
     219                owner = thrd;
     220                recursion_count = 1;
     221        }
     222
     223    if ( node.park_counter ) __make_select_node_available( node );
     224    unlock( lock );
     225    return true;
     226}
     227
     228bool unregister_select( blocking_lock & this, select_node & node ) with(this) {
     229    lock( lock __cfaabi_dbg_ctx2 );
     230    if ( node`isListed ) {
     231        remove( node );
     232        wait_count--;
     233        unlock( lock );
     234        return false;
     235    }
     236   
     237    if ( owner == active_thread() ) {
     238        /* 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 );
     239        // if recursion count is zero release lock and set new owner if one is waiting
     240        recursion_count--;
     241        if ( recursion_count == 0 ) {
     242            pop_node( this );
     243        }
     244    }
     245        unlock( lock );
     246    return false;
     247}
     248
     249bool on_selected( blocking_lock & this, select_node & node ) { return true; }
    177250
    178251//-----------------------------------------------------------------------------
     
    311384        int counter( condition_variable(L) & this ) with(this) { return count; }
    312385
    313         static size_t queue_and_get_recursion( condition_variable(L) & this, info_thread(L) * i ) with(this) {
     386        static void enqueue_thread( condition_variable(L) & this, info_thread(L) * i ) with(this) {
    314387                // add info_thread to waiting queue
    315388                insert_last( blocked_threads, *i );
    316389                count++;
    317                 size_t recursion_count = 0;
    318                 if (i->lock) {
     390                // size_t recursion_count = 0;
     391                // if (i->lock) {
     392                //      // if lock was passed get recursion count to reset to after waking thread
     393                //      recursion_count = on_wait( *i->lock );
     394                // }
     395                // return recursion_count;
     396        }
     397
     398    static size_t block_and_get_recursion( info_thread(L) & i ) {
     399        size_t recursion_count = 0;
     400                if ( i.lock ) {
    319401                        // if lock was passed get recursion count to reset to after waking thread
    320                         recursion_count = on_wait( *i->lock );
    321                 }
    322                 return recursion_count;
    323         }
     402                        recursion_count = on_wait( *i.lock ); // this call blocks
     403                } else park( );
     404        return recursion_count;
     405    }
    324406
    325407        // helper for wait()'s' with no timeout
    326408        static void queue_info_thread( condition_variable(L) & this, info_thread(L) & i ) with(this) {
    327409                lock( lock __cfaabi_dbg_ctx2 );
    328                 size_t recursion_count = queue_and_get_recursion(this, &i);
     410        enqueue_thread( this, &i );
     411                // size_t recursion_count = queue_and_get_recursion( this, &i );
    329412                unlock( lock );
    330413
    331414                // blocks here
    332                 park( );
     415        size_t recursion_count = block_and_get_recursion( i );
     416                // park( );
    333417
    334418                // resets recursion count here after waking
    335                 if (i.lock) on_wakeup(*i.lock, recursion_count);
     419                if ( i.lock ) on_wakeup( *i.lock, recursion_count );
    336420        }
    337421
     
    343427        static void queue_info_thread_timeout( condition_variable(L) & this, info_thread(L) & info, Duration t, Alarm_Callback callback ) with(this) {
    344428                lock( lock __cfaabi_dbg_ctx2 );
    345                 size_t recursion_count = queue_and_get_recursion(this, &info);
     429        enqueue_thread( this, &info );
     430                // size_t recursion_count = queue_and_get_recursion( this, &info );
    346431                alarm_node_wrap(L) node_wrap = { t, 0`s, callback, &this, &info };
    347432                unlock( lock );
     
    351436
    352437                // blocks here
    353                 park();
     438        size_t recursion_count = block_and_get_recursion( info );
     439                // park();
    354440
    355441                // unregisters alarm so it doesn't go off if this happens first
     
    357443
    358444                // resets recursion count here after waking
    359                 if (info.lock) on_wakeup(*info.lock, recursion_count);
     445                if ( info.lock ) on_wakeup( *info.lock, recursion_count );
    360446        }
    361447
     
    417503                info_thread( L ) i = { active_thread(), info, &l };
    418504                insert_last( blocked_threads, i );
    419                 size_t recursion_count = on_wait( *i.lock );
    420                 park( );
     505                size_t recursion_count = on_wait( *i.lock ); // blocks here
     506                // park( );
    421507                on_wakeup(*i.lock, recursion_count);
    422508        }
     
    459545        bool empty ( pthread_cond_var(L) & this ) with(this) { return blocked_threads`isEmpty; }
    460546
    461         static size_t queue_and_get_recursion( pthread_cond_var(L) & this, info_thread(L) * i ) with(this) {
    462                 // add info_thread to waiting queue
    463                 insert_last( blocked_threads, *i );
    464                 size_t recursion_count = 0;
    465                 recursion_count = on_wait( *i->lock );
    466                 return recursion_count;
    467         }
     547        // static size_t queue_and_get_recursion( pthread_cond_var(L) & this, info_thread(L) * i ) with(this) {
     548        //      // add info_thread to waiting queue
     549        //      insert_last( blocked_threads, *i );
     550        //      size_t recursion_count = 0;
     551        //      recursion_count = on_wait( *i->lock );
     552        //      return recursion_count;
     553        // }
     554
    468555       
    469556        static void queue_info_thread_timeout( pthread_cond_var(L) & this, info_thread(L) & info, Duration t, Alarm_Callback callback ) with(this) {
    470557                lock( lock __cfaabi_dbg_ctx2 );
    471                 size_t recursion_count = queue_and_get_recursion(this, &info);
     558                // size_t recursion_count = queue_and_get_recursion(this, &info);
     559        insert_last( blocked_threads, info );
    472560                pthread_alarm_node_wrap(L) node_wrap = { t, 0`s, callback, &this, &info };
    473561                unlock( lock );
     
    477565
    478566                // blocks here
    479                 park();
     567        size_t recursion_count = block_and_get_recursion( info );
     568                // park();
    480569
    481570                // unregisters alarm so it doesn't go off if this happens first
     
    483572
    484573                // resets recursion count here after waking
    485                 if (info.lock) on_wakeup(*info.lock, recursion_count);
     574                if ( info.lock ) on_wakeup( *info.lock, recursion_count );
    486575        }
    487576
     
    493582                lock( lock __cfaabi_dbg_ctx2 );
    494583                info_thread( L ) i = { active_thread(), info, &l };
    495                 size_t recursion_count = queue_and_get_recursion(this, &i);
    496                 unlock( lock );
    497                 park( );
    498                 on_wakeup(*i.lock, recursion_count);
     584        insert_last( blocked_threads, i );
     585                // size_t recursion_count = queue_and_get_recursion( this, &i );
     586                unlock( lock );
     587
     588        // blocks here
     589                size_t recursion_count = block_and_get_recursion( i );
     590                // park();
     591                on_wakeup( *i.lock, recursion_count );
    499592        }
    500593
Note: See TracChangeset for help on using the changeset viewer.