Changeset 22b7579


Ignore:
Timestamp:
Mar 31, 2021, 1:48:15 PM (3 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
c7c178b
Parents:
f621e43f
Message:

Changed is_blocking_lock trait to use on_wakeup.
Fixed fast_lock to work with conditions.

Files:
6 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/bits/weakso_locks.cfa

    rf621e43f r22b7579  
    1818#include "bits/weakso_locks.hfa"
    1919
    20 void  ?{}( blocking_lock & this, bool multi_acquisition, bool strict_owner ) {}
    21 void ^?{}( blocking_lock & this ) {}
     20void  ?{}( blocking_lock &, bool, bool ) {}
     21void ^?{}( blocking_lock & ) {}
    2222
    23 void lock( blocking_lock & this ) {}
    24 bool try_lock( blocking_lock & this ) { return false; }
    25 void unlock( blocking_lock & this ) {}
    26 void on_notify( blocking_lock & this, struct $thread * t ) {}
    27 void on_wait( blocking_lock & this ) {}
    28 size_t wait_count( blocking_lock & this ) { return 0; }
    29 void set_recursion_count( blocking_lock & this, size_t recursion ) {}
    30 size_t get_recursion_count( blocking_lock & this ) { return 0; }
     23void lock( blocking_lock & ) {}
     24bool try_lock( blocking_lock & ) { return false; }
     25void unlock( blocking_lock & ) {}
     26void on_notify( blocking_lock &, struct $thread * ) {}
     27size_t on_wait( blocking_lock & ) {}
     28void on_wakeup( blocking_lock &, size_t ) {}
     29size_t wait_count( blocking_lock & ) { return 0; }
  • libcfa/src/bits/weakso_locks.hfa

    rf621e43f r22b7579  
    5656void unlock( blocking_lock & this ) OPTIONAL_THREAD;
    5757void on_notify( blocking_lock & this, struct $thread * t ) OPTIONAL_THREAD;
    58 void on_wait( blocking_lock & this ) OPTIONAL_THREAD;
     58size_t on_wait( blocking_lock & this ) OPTIONAL_THREAD;
     59void on_wakeup( blocking_lock & this, size_t ) OPTIONAL_THREAD;
    5960size_t wait_count( blocking_lock & this ) OPTIONAL_THREAD;
    60 void set_recursion_count( blocking_lock & this, size_t recursion ) OPTIONAL_THREAD;
    61 size_t get_recursion_count( blocking_lock & this ) OPTIONAL_THREAD;
    6261
    6362//----------
     
    7271static inline bool   try_lock ( multiple_acquisition_lock & this ) { return try_lock( (blocking_lock &)this ); }
    7372static inline void   unlock   ( multiple_acquisition_lock & this ) { unlock  ( (blocking_lock &)this ); }
    74 static inline void   on_wait  ( multiple_acquisition_lock & this ) { on_wait ( (blocking_lock &)this ); }
     73static inline size_t on_wait  ( multiple_acquisition_lock & this ) { return on_wait ( (blocking_lock &)this ); }
     74static inline void   on_wakeup( multiple_acquisition_lock & this, size_t v ) { on_wakeup ( (blocking_lock &)this, v ); }
    7575static inline void   on_notify( multiple_acquisition_lock & this, struct $thread * t ){ on_notify( (blocking_lock &)this, t ); }
    76 static inline void   set_recursion_count( multiple_acquisition_lock & this, size_t recursion ){ set_recursion_count( (blocking_lock &)this, recursion ); }
    77 static inline size_t get_recursion_count( multiple_acquisition_lock & this ){ return get_recursion_count( (blocking_lock &)this ); }
  • libcfa/src/concurrency/locks.cfa

    rf621e43f r22b7579  
    134134        lock( lock __cfaabi_dbg_ctx2 );
    135135        /* paranoid */ verifyf( owner != 0p, "Attempt to release lock %p that isn't held", &this );
    136         /* paranoid */ verifyf( owner == active_thread() || !strict_owner, "Thread %p other than the owner %p attempted to release owner lock %p", owner, active_thread(), &this );
     136        /* paranoid */ verifyf( owner == active_thread() || !strict_owner , "Thread %p other than the owner %p attempted to release owner lock %p", owner, active_thread(), &this );
     137        /* paranoid */ verifyf( recursion_count == 1 || multi_acquisition, "Thread %p attempted to release owner lock %p which is not recursive but has a recursive count of %zu", active_thread(), &this, recursion_count );
    137138
    138139        // if recursion count is zero release lock and set new owner if one is waiting
     
    146147size_t wait_count( blocking_lock & this ) with( this ) {
    147148        return wait_count;
    148 }
    149 
    150 void set_recursion_count( blocking_lock & this, size_t recursion ) with( this ) {
    151         recursion_count = recursion;
    152 }
    153 
    154 size_t get_recursion_count( blocking_lock & this ) with( this ) {
    155         return recursion_count;
    156149}
    157150
     
    173166}
    174167
    175 void on_wait( blocking_lock & this ) with( this ) {
     168size_t on_wait( blocking_lock & this ) with( this ) {
    176169        lock( lock __cfaabi_dbg_ctx2 );
    177170        /* paranoid */ verifyf( owner != 0p, "Attempt to release lock %p that isn't held", &this );
    178171        /* paranoid */ verifyf( owner == active_thread() || !strict_owner, "Thread %p other than the owner %p attempted to release owner lock %p", owner, active_thread(), &this );
    179172
     173        size_t ret = recursion_count;
     174
    180175        pop_and_set_new_owner( this );
    181176        unlock( lock );
     177        return ret;
     178}
     179
     180void on_wakeup( blocking_lock & this, size_t recursion ) with( this ) {
     181        recursion_count = recursion;
    182182}
    183183
     
    274274        }
    275275
    276         bool empty( condition_variable(L) & this ) with(this) { return empty(blocked_threads); }
     276        bool empty( condition_variable(L) & this ) with(this) {
     277                lock( lock __cfaabi_dbg_ctx2 );
     278                bool ret = empty(blocked_threads);
     279                unlock( lock );
     280                return ret;
     281        }
    277282
    278283        int counter( condition_variable(L) & this ) with(this) { return count; }
     
    285290                if (i->lock) {
    286291                        // if lock was passed get recursion count to reset to after waking thread
    287                         recursion_count = get_recursion_count(*i->lock);
    288                         on_wait( *i->lock );
     292                        recursion_count = on_wait( *i->lock );
    289293                }
    290294                return recursion_count;
     
    301305
    302306                // resets recursion count here after waking
    303                 if (i.lock) set_recursion_count(*i.lock, recursion_count);
     307                if (i.lock) on_wakeup(*i.lock, recursion_count);
    304308        }
    305309
     
    323327
    324328                // resets recursion count here after waking
    325                 if (info.lock) set_recursion_count(*info.lock, recursion_count);
     329                if (info.lock) on_wakeup(*info.lock, recursion_count);
    326330        }
    327331
     
    373377}
    374378
    375 bool V(semaphore & this) with( this ) {
     379$thread * V (semaphore & this, const bool doUnpark ) with( this ) {
    376380        $thread * thrd = 0p;
    377381        lock( lock __cfaabi_dbg_ctx2 );
     
    385389
    386390        // make new owner
    387         unpark( thrd );
    388 
     391        if( doUnpark ) unpark( thrd );
     392
     393        return thrd;
     394}
     395
     396bool V(semaphore & this) with( this ) {
     397        $thread * thrd = V(this, true);
    389398        return thrd != 0p;
    390399}
  • libcfa/src/concurrency/locks.hfa

    rf621e43f r22b7579  
    119119
    120120static inline bool P(ThreadBenaphore & this)              { return P(this.ben) ? false : P(this.sem); }
    121 static inline bool P(ThreadBenaphore & this, $thread * t) { return P(this.ben) ? false : P(this.sem, t ); }
    122121static inline bool tryP(ThreadBenaphore & this)           { return tryP(this.ben); }
    123122static inline bool P(ThreadBenaphore & this, bool wait)   { return wait ? P(this) : tryP(this); }
     
    141140bool   V (semaphore & this);
    142141bool   V (semaphore & this, unsigned count);
     142$thread * V (semaphore & this, bool );
    143143
    144144//----------
     
    149149static inline void  ?{}( single_acquisition_lock & this ) {((blocking_lock &)this){ false, false };}
    150150static inline void ^?{}( single_acquisition_lock & this ) {}
    151 static inline void   lock      ( single_acquisition_lock & this ) { lock    ( (blocking_lock &)this ); }
    152 static inline bool   try_lock  ( single_acquisition_lock & this ) { return try_lock( (blocking_lock &)this ); }
    153 static inline void   unlock    ( single_acquisition_lock & this ) { unlock  ( (blocking_lock &)this ); }
    154 static inline void   on_wait   ( single_acquisition_lock & this ) { on_wait ( (blocking_lock &)this ); }
    155 static inline void   on_notify ( single_acquisition_lock & this, struct $thread * t ) { on_notify( (blocking_lock &)this, t ); }
    156 static inline void   set_recursion_count( single_acquisition_lock & this, size_t recursion ) { set_recursion_count( (blocking_lock &)this, recursion ); }
    157 static inline size_t get_recursion_count( single_acquisition_lock & this ) { return get_recursion_count( (blocking_lock &)this ); }
     151static inline void   lock     ( single_acquisition_lock & this ) { lock    ( (blocking_lock &)this ); }
     152static inline bool   try_lock ( single_acquisition_lock & this ) { return try_lock( (blocking_lock &)this ); }
     153static inline void   unlock   ( single_acquisition_lock & this ) { unlock  ( (blocking_lock &)this ); }
     154static inline size_t on_wait  ( single_acquisition_lock & this ) { return on_wait ( (blocking_lock &)this ); }
     155static inline void   on_wakeup( single_acquisition_lock & this, size_t v ) { on_wakeup ( (blocking_lock &)this, v ); }
     156static inline void   on_notify( single_acquisition_lock & this, struct $thread * t ) { on_notify( (blocking_lock &)this, t ); }
    158157
    159158//----------
     
    167166static inline bool   try_lock ( owner_lock & this ) { return try_lock( (blocking_lock &)this ); }
    168167static inline void   unlock   ( owner_lock & this ) { unlock  ( (blocking_lock &)this ); }
    169 static inline void   on_wait  ( owner_lock & this ) { on_wait ( (blocking_lock &)this ); }
     168static inline size_t on_wait  ( owner_lock & this ) { return on_wait ( (blocking_lock &)this ); }
     169static inline void   on_wakeup( owner_lock & this, size_t v ) { on_wakeup ( (blocking_lock &)this, v ); }
    170170static inline void   on_notify( owner_lock & this, struct $thread * t ) { on_notify( (blocking_lock &)this, t ); }
    171 static inline void   set_recursion_count( owner_lock & this, size_t recursion ) { set_recursion_count( (blocking_lock &)this, recursion ); }
    172 static inline size_t get_recursion_count( owner_lock & this ) { return get_recursion_count( (blocking_lock &)this ); }
    173171
    174172struct fast_lock {
     
    182180}
    183181
    184 static inline void $lock(fast_lock & this, $thread * thrd) {
    185         /* paranoid */verify(thrd != this.owner);
    186 
    187         for (;;) {
    188                 if ($try_lock(this, thrd)) return;
    189                 P(this.sem, thrd);
    190         }
    191 }
    192 
     182static inline void lock( fast_lock & this ) __attribute__((artificial));
    193183static inline void lock( fast_lock & this ) {
    194184        $thread * thrd = active_thread();
     
    201191}
    202192
    203 static inline void try_lock ( fast_lock & this ) {
     193static inline bool try_lock( fast_lock & this ) __attribute__((artificial));
     194static inline bool try_lock ( fast_lock & this ) {
    204195        $thread * thrd = active_thread();
    205196        /* paranoid */ verify(thrd != this.owner);
     
    207198}
    208199
    209 static inline void unlock( fast_lock & this ) {
     200static inline $thread * unlock( fast_lock & this ) __attribute__((artificial));
     201static inline $thread * unlock( fast_lock & this ) {
    210202        $thread * thrd = active_thread();
    211203        /* paranoid */ verify(thrd == this.owner);
    212         $thread * next = V(this.sem, false); // implicit fence
    213         // open 'owner' only after fence
     204
     205        // open 'owner' before unlocking anyone
     206        // so new and unlocked threads don't park incorrectly.
    214207        this.owner = 0p;
    215208
    216         // Unpark the next person (can be 0p, unpark handles it)
    217         unpark(next);
    218 }
    219 
    220 static inline void on_wait( fast_lock & this ) {
    221         unlock(this);
    222         #warning this is broken
    223 }
    224 
    225 static inline void on_notify( fast_lock & this, struct $thread * t ) {
    226         $lock(this, t);
    227         #warning this is broken
    228 }
    229 
    230 static inline void   set_recursion_count( fast_lock & this, size_t recursion ) {}
    231 static inline size_t get_recursion_count( fast_lock & this ) { return 0; }
     209        return V(this.sem,true);
     210}
     211
     212static inline size_t on_wait( fast_lock & this ) __attribute__((artificial));
     213static inline void on_wakeup( fast_lock & this, size_t ) __attribute__((artificial));
     214static inline void on_notify( fast_lock &, struct $thread * t ) __attribute__((artificial));
     215
     216static inline size_t on_wait( fast_lock & this ) { unlock(this); return 0; }
     217static inline void on_wakeup( fast_lock & this, size_t ) { lock(this); }
     218static inline void on_notify( fast_lock &, struct $thread * t ) { unpark(t); }
    232219
    233220struct mcs_node {
     
    263250
    264251        // For synchronization locks to use when releasing
    265         void on_wait( L & );
    266 
    267         // to get recursion count for cond lock to reset after waking
    268         size_t get_recursion_count( L & );
     252        size_t on_wait( L & );
    269253
    270254        // to set recursion count after getting signalled;
    271         void set_recursion_count( L &, size_t recursion );
     255        void on_wakeup( L &, size_t recursion );
    272256};
    273257
  • tests/unified_locking/.expect/locks.txt

    rf621e43f r22b7579  
    1111Start Test 6: owner lock and condition variable 3 wait/notify all
    1212Done Test 6
    13 Start Test 7: multi acquisiton lock and condition variable multiple acquire and wait/notify
     13Start Test 7: fast lock and condition variable single wait/notify
    1414Done Test 7
    15 Start Test 8: owner lock and condition variable multiple acquire and wait/notify
     15Start Test 8: fast lock and condition variable 3 wait/notify all
    1616Done Test 8
    17 Start Test 9: no lock condition variable wait/notify
     17Start Test 9: multi acquisiton lock and condition variable multiple acquire and wait/notify
    1818Done Test 9
    19 Start Test 10: locked condition variable wait/notify with front()
     19Start Test 10: owner lock and condition variable multiple acquire and wait/notify
    2020Done Test 10
     21Start Test 11: no lock condition variable wait/notify
     22Done Test 11
     23Start Test 12: locked condition variable wait/notify with front()
     24Done Test 12
  • tests/unified_locking/locks.cfa

    rf621e43f r22b7579  
    1515condition_variable( owner_lock ) c_o;
    1616
     17fast_lock f;
     18condition_variable( fast_lock ) c_f;
     19
    1720thread T_C_M_WS1 {};
    1821
     
    6871                }
    6972                unlock(s);
     73        }
     74}
     75
     76thread T_C_F_WS1 {};
     77
     78void main( T_C_F_WS1 & this ) {
     79        for (unsigned int i = 0; i < num_times; i++) {
     80                lock(f);
     81                if(empty(c_f) && i != num_times - 1) {
     82                        wait(c_f,f);
     83                }else{
     84                        notify_one(c_f);
     85                }
     86                unlock(f);
     87        }
     88}
     89
     90thread T_C_F_WB1 {};
     91
     92void main( T_C_F_WB1 & this ) {
     93        for (unsigned int i = 0; i < num_times; i++) {
     94                lock(f);
     95                if(counter(c_f) == 3 || i == num_times - 1) {
     96                        notify_all(c_f);
     97                }else{
     98                        wait(c_f,f);
     99                }
     100                unlock(f);
    70101        }
    71102}
     
    255286        printf("Done Test 6\n");
    256287
    257         printf("Start Test 7: multi acquisiton lock and condition variable multiple acquire and wait/notify\n");
     288        printf("Start Test 7: fast lock and condition variable single wait/notify\n");
     289        {
     290                T_C_F_WS1 t1[2];
     291        }
     292        printf("Done Test 7\n");
     293
     294        printf("Start Test 8: fast lock and condition variable 3 wait/notify all\n");
     295        {
     296                T_C_F_WB1 t1[4];
     297        }
     298        printf("Done Test 8\n");
     299
     300        printf("Start Test 9: multi acquisiton lock and condition variable multiple acquire and wait/notify\n");
    258301        {
    259302                T_C_M_WS2 t1[2];
    260303        }
    261         printf("Done Test 7\n");
    262 
    263         printf("Start Test 8: owner lock and condition variable multiple acquire and wait/notify\n");
     304        printf("Done Test 9\n");
     305
     306        printf("Start Test 10: owner lock and condition variable multiple acquire and wait/notify\n");
    264307        {
    265308                T_C_O_WS2 t1[2];
    266309        }
    267         printf("Done Test 8\n");
    268 
    269         printf("Start Test 9: no lock condition variable wait/notify\n");
     310        printf("Done Test 10\n");
     311
     312        printf("Start Test 11: no lock condition variable wait/notify\n");
    270313        {
    271314                T_C_NLW t1;
    272315                T_C_NLS t2;
    273316        }
    274         printf("Done Test 9\n");
    275 
    276         printf("Start Test 10: locked condition variable wait/notify with front()\n");
     317        printf("Done Test 11\n");
     318
     319        printf("Start Test 12: locked condition variable wait/notify with front()\n");
    277320        {
    278321                T_C_S_WNF t1[2];
    279322        }
    280         printf("Done Test 10\n");
     323        printf("Done Test 12\n");
    281324
    282325        // removed to limit test duration. Full test is in long run tests
Note: See TracChangeset for help on using the changeset viewer.