Changes in / [c60ef63:ca33b15]


Ignore:
Files:
4 deleted
7 edited

Legend:

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

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

    rc60ef63 rca33b15  
    5656void unlock( blocking_lock & this ) OPTIONAL_THREAD;
    5757void on_notify( blocking_lock & this, struct $thread * t ) OPTIONAL_THREAD;
    58 size_t on_wait( blocking_lock & this ) OPTIONAL_THREAD;
    59 void on_wakeup( blocking_lock & this, size_t ) OPTIONAL_THREAD;
     58void on_wait( blocking_lock & this ) OPTIONAL_THREAD;
    6059size_t wait_count( blocking_lock & this ) OPTIONAL_THREAD;
     60void set_recursion_count( blocking_lock & this, size_t recursion ) OPTIONAL_THREAD;
     61size_t get_recursion_count( blocking_lock & this ) OPTIONAL_THREAD;
    6162
    6263//----------
     
    7172static inline bool   try_lock ( multiple_acquisition_lock & this ) { return try_lock( (blocking_lock &)this ); }
    7273static inline void   unlock   ( multiple_acquisition_lock & this ) { unlock  ( (blocking_lock &)this ); }
    73 static inline size_t on_wait  ( multiple_acquisition_lock & this ) { return on_wait ( (blocking_lock &)this ); }
    74 static inline void   on_wakeup( multiple_acquisition_lock & this, size_t v ) { on_wakeup ( (blocking_lock &)this, v ); }
     74static inline void   on_wait  ( multiple_acquisition_lock & this ) { on_wait ( (blocking_lock &)this ); }
    7575static inline void   on_notify( multiple_acquisition_lock & this, struct $thread * t ){ on_notify( (blocking_lock &)this, t ); }
     76static inline void   set_recursion_count( multiple_acquisition_lock & this, size_t recursion ){ set_recursion_count( (blocking_lock &)this, recursion ); }
     77static inline size_t get_recursion_count( multiple_acquisition_lock & this ){ return get_recursion_count( (blocking_lock &)this ); }
  • libcfa/src/concurrency/locks.cfa

    rc60ef63 rca33b15  
    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 );
    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 );
     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 );
    138137
    139138        // if recursion count is zero release lock and set new owner if one is waiting
     
    147146size_t wait_count( blocking_lock & this ) with( this ) {
    148147        return wait_count;
     148}
     149
     150void set_recursion_count( blocking_lock & this, size_t recursion ) with( this ) {
     151        recursion_count = recursion;
     152}
     153
     154size_t get_recursion_count( blocking_lock & this ) with( this ) {
     155        return recursion_count;
    149156}
    150157
     
    166173}
    167174
    168 size_t on_wait( blocking_lock & this ) with( this ) {
     175void on_wait( blocking_lock & this ) with( this ) {
    169176        lock( lock __cfaabi_dbg_ctx2 );
    170177        /* paranoid */ verifyf( owner != 0p, "Attempt to release lock %p that isn't held", &this );
    171178        /* paranoid */ verifyf( owner == active_thread() || !strict_owner, "Thread %p other than the owner %p attempted to release owner lock %p", owner, active_thread(), &this );
    172179
    173         size_t ret = recursion_count;
    174 
    175180        pop_and_set_new_owner( this );
    176181        unlock( lock );
    177         return ret;
    178 }
    179 
    180 void 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) {
    277                 lock( lock __cfaabi_dbg_ctx2 );
    278                 bool ret = empty(blocked_threads);
    279                 unlock( lock );
    280                 return ret;
    281         }
     276        bool empty( condition_variable(L) & this ) with(this) { return empty(blocked_threads); }
    282277
    283278        int counter( condition_variable(L) & this ) with(this) { return count; }
     
    290285                if (i->lock) {
    291286                        // if lock was passed get recursion count to reset to after waking thread
    292                         recursion_count = on_wait( *i->lock );
     287                        recursion_count = get_recursion_count(*i->lock);
     288                        on_wait( *i->lock );
    293289                }
    294290                return recursion_count;
     
    305301
    306302                // resets recursion count here after waking
    307                 if (i.lock) on_wakeup(*i.lock, recursion_count);
     303                if (i.lock) set_recursion_count(*i.lock, recursion_count);
    308304        }
    309305
     
    327323
    328324                // resets recursion count here after waking
    329                 if (info.lock) on_wakeup(*info.lock, recursion_count);
     325                if (info.lock) set_recursion_count(*info.lock, recursion_count);
    330326        }
    331327
     
    377373}
    378374
    379 $thread * V (semaphore & this, const bool doUnpark ) with( this ) {
     375bool V(semaphore & this) with( this ) {
    380376        $thread * thrd = 0p;
    381377        lock( lock __cfaabi_dbg_ctx2 );
     
    389385
    390386        // make new owner
    391         if( doUnpark ) unpark( thrd );
    392 
    393         return thrd;
    394 }
    395 
    396 bool V(semaphore & this) with( this ) {
    397         $thread * thrd = V(this, true);
     387        unpark( thrd );
     388
    398389        return thrd != 0p;
    399390}
  • libcfa/src/concurrency/locks.hfa

    rc60ef63 rca33b15  
    3939};
    4040
     41static inline bool P(Semaphore0nary & this, $thread * thrd) __attribute__((artificial));
    4142static inline bool P(Semaphore0nary & this, $thread * thrd) {
    4243        /* paranoid */ verify(!(thrd->seqable.next));
     
    4748}
    4849
     50static inline bool P(Semaphore0nary & this) __attribute__((artificial));
    4951static inline bool P(Semaphore0nary & this) {
    5052    $thread * thrd = active_thread();
     
    5456}
    5557
     58static inline $thread * V(Semaphore0nary & this, const bool doUnpark = true) __attribute__((artificial));
    5659static inline $thread * V(Semaphore0nary & this, const bool doUnpark = true) {
    5760        $thread * next;
     
    7982
    8083        // returns true if no blocking needed
    81         bool P(BinaryBenaphore & this) {
    82                 return __atomic_fetch_sub(&this.counter, 1, __ATOMIC_SEQ_CST) > 0;
    83         }
    84 
     84        bool P(BinaryBenaphore & this) { return __atomic_fetch_sub(&this.counter, 1, __ATOMIC_SEQ_CST) > 0; }
    8585        bool tryP(BinaryBenaphore & this) {
    8686                ssize_t c = this.counter;
     
    115115static inline void ?{}(ThreadBenaphore & this, one_t ) { (this.ben){ 1 }; }
    116116
    117 static inline bool P(ThreadBenaphore & this)              { return P(this.ben) ? false : P(this.sem); }
     117static inline bool P(ThreadBenaphore & this)              { return /* P(this.ben) ? false : */ P(this.sem); }
     118static inline bool P(ThreadBenaphore & this, $thread * t) { return /* P(this.ben) ? false : */ P(this.sem, t ); }
    118119static inline bool tryP(ThreadBenaphore & this)           { return tryP(this.ben); }
    119120static inline bool P(ThreadBenaphore & this, bool wait)   { return wait ? P(this) : tryP(this); }
    120121
    121122static inline $thread * V(ThreadBenaphore & this, const bool doUnpark = true) {
    122         if (V(this.ben)) return 0p;
     123        // if (V(this.ben)) return 0p;
    123124        return V(this.sem, doUnpark);
    124125}
     
    137138bool   V (semaphore & this);
    138139bool   V (semaphore & this, unsigned count);
    139 $thread * V (semaphore & this, bool );
    140140
    141141//----------
     
    146146static inline void  ?{}( single_acquisition_lock & this ) {((blocking_lock &)this){ false, false };}
    147147static inline void ^?{}( single_acquisition_lock & this ) {}
    148 static inline void   lock     ( single_acquisition_lock & this ) { lock    ( (blocking_lock &)this ); }
    149 static inline bool   try_lock ( single_acquisition_lock & this ) { return try_lock( (blocking_lock &)this ); }
    150 static inline void   unlock   ( single_acquisition_lock & this ) { unlock  ( (blocking_lock &)this ); }
    151 static inline size_t on_wait  ( single_acquisition_lock & this ) { return on_wait ( (blocking_lock &)this ); }
    152 static inline void   on_wakeup( single_acquisition_lock & this, size_t v ) { on_wakeup ( (blocking_lock &)this, v ); }
    153 static inline void   on_notify( single_acquisition_lock & this, struct $thread * t ) { on_notify( (blocking_lock &)this, t ); }
     148static inline void   lock      ( single_acquisition_lock & this ) { lock    ( (blocking_lock &)this ); }
     149static inline bool   try_lock  ( single_acquisition_lock & this ) { return try_lock( (blocking_lock &)this ); }
     150static inline void   unlock    ( single_acquisition_lock & this ) { unlock  ( (blocking_lock &)this ); }
     151static inline void   on_wait   ( single_acquisition_lock & this ) { on_wait ( (blocking_lock &)this ); }
     152static inline void   on_notify ( single_acquisition_lock & this, struct $thread * t ) { on_notify( (blocking_lock &)this, t ); }
     153static inline void   set_recursion_count( single_acquisition_lock & this, size_t recursion ) { set_recursion_count( (blocking_lock &)this, recursion ); }
     154static inline size_t get_recursion_count( single_acquisition_lock & this ) { return get_recursion_count( (blocking_lock &)this ); }
    154155
    155156//----------
     
    163164static inline bool   try_lock ( owner_lock & this ) { return try_lock( (blocking_lock &)this ); }
    164165static inline void   unlock   ( owner_lock & this ) { unlock  ( (blocking_lock &)this ); }
    165 static inline size_t on_wait  ( owner_lock & this ) { return on_wait ( (blocking_lock &)this ); }
    166 static inline void   on_wakeup( owner_lock & this, size_t v ) { on_wakeup ( (blocking_lock &)this, v ); }
     166static inline void   on_wait  ( owner_lock & this ) { on_wait ( (blocking_lock &)this ); }
    167167static inline void   on_notify( owner_lock & this, struct $thread * t ) { on_notify( (blocking_lock &)this, t ); }
     168static inline void   set_recursion_count( owner_lock & this, size_t recursion ) { set_recursion_count( (blocking_lock &)this, recursion ); }
     169static inline size_t get_recursion_count( owner_lock & this ) { return get_recursion_count( (blocking_lock &)this ); }
    168170
    169171struct fast_lock {
     
    177179}
    178180
    179 static inline void lock( fast_lock & this ) __attribute__((artificial));
     181static inline void $lock(fast_lock & this, $thread * thrd) {
     182        /* paranoid */verify(thrd != this.owner);
     183
     184        for (;;) {
     185                if ($try_lock(this, thrd)) return;
     186                P(this.sem, thrd);
     187        }
     188}
     189
    180190static inline void lock( fast_lock & this ) {
    181191        $thread * thrd = active_thread();
     
    188198}
    189199
    190 static inline bool try_lock( fast_lock & this ) __attribute__((artificial));
    191 static inline bool try_lock ( fast_lock & this ) {
     200static inline void try_lock ( fast_lock & this ) {
    192201        $thread * thrd = active_thread();
    193202        /* paranoid */ verify(thrd != this.owner);
     
    195204}
    196205
    197 static inline $thread * unlock( fast_lock & this ) __attribute__((artificial));
    198 static inline $thread * unlock( fast_lock & this ) {
     206static inline void unlock( fast_lock & this ) {
    199207        $thread * thrd = active_thread();
    200208        /* paranoid */ verify(thrd == this.owner);
    201 
    202         // open 'owner' before unlocking anyone
    203         // so new and unlocked threads don't park incorrectly.
    204         // This may require additional fencing on ARM.
     209        $thread * next = V(this.sem, false); // implicit fence
     210        // open 'owner' only after fence
    205211        this.owner = 0p;
    206212
    207         return V(this.sem, true);
    208 }
    209 
    210 static inline size_t on_wait( fast_lock & this ) { unlock(this); return 0; }
    211 static inline void on_wakeup( fast_lock & this, size_t ) { lock(this); }
    212 static inline void on_notify( fast_lock &, struct $thread * t ) { unpark(t); }
     213        // Unpark the next person (can be 0p, unpark handles it)
     214        unpark(next);
     215}
     216
     217static inline void on_wait( fast_lock & this ) {
     218        unlock(this);
     219        #warning this is broken
     220}
     221
     222static inline void on_notify( fast_lock & this, struct $thread * t ) {
     223        $lock(this, t);
     224        #warning this is broken
     225}
     226
     227static inline void   set_recursion_count( fast_lock & this, size_t recursion ) {}
     228static inline size_t get_recursion_count( fast_lock & this ) { return 0; }
    213229
    214230struct mcs_node {
     
    244260
    245261        // For synchronization locks to use when releasing
    246         size_t on_wait( L & );
     262        void on_wait( L & );
     263
     264        // to get recursion count for cond lock to reset after waking
     265        size_t get_recursion_count( L & );
    247266
    248267        // to set recursion count after getting signalled;
    249         void on_wakeup( L &, size_t recursion );
     268        void set_recursion_count( L &, size_t recursion );
    250269};
    251270
  • tests/concurrent/spinaphore.cfa

    rc60ef63 rca33b15  
    3636        this.sum = 0;
    3737        for(num_blocks) {
     38                // sout | "b P" | me;
    3839                P(sem);
    3940                if(((thread&)this).seqable.next != 0p) sout | "Link not invalidated";
     41                // sout | "a P" | me;
    4042        }
    4143}
     
    5658                this.sum += (unsigned)b;
    5759                unpark(t);
     60                // sout | "a V" | t;
    5861                yield(random(10));
    5962        }
  • tests/unified_locking/.expect/locks.txt

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

    rc60ef63 rca33b15  
    1515condition_variable( owner_lock ) c_o;
    1616
    17 fast_lock f;
    18 condition_variable( fast_lock ) c_f;
    19 
    2017thread T_C_M_WS1 {};
    2118
     
    7168                }
    7269                unlock(s);
    73         }
    74 }
    75 
    76 thread T_C_F_WS1 {};
    77 
    78 void 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 
    90 thread T_C_F_WB1 {};
    91 
    92 void 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);
    10170        }
    10271}
     
    286255        printf("Done Test 6\n");
    287256
    288         printf("Start Test 7: fast lock and condition variable single wait/notify\n");
    289         {
    290                 T_C_F_WS1 t1[2];
     257        printf("Start Test 7: multi acquisiton lock and condition variable multiple acquire and wait/notify\n");
     258        {
     259                T_C_M_WS2 t1[2];
    291260        }
    292261        printf("Done Test 7\n");
    293262
    294         printf("Start Test 8: fast lock and condition variable 3 wait/notify all\n");
    295         {
    296                 T_C_F_WB1 t1[4];
     263        printf("Start Test 8: owner lock and condition variable multiple acquire and wait/notify\n");
     264        {
     265                T_C_O_WS2 t1[2];
    297266        }
    298267        printf("Done Test 8\n");
    299268
    300         printf("Start Test 9: multi acquisiton lock and condition variable multiple acquire and wait/notify\n");
    301         {
    302                 T_C_M_WS2 t1[2];
    303         }
    304         printf("Done Test 9\n");
    305 
    306         printf("Start Test 10: owner lock and condition variable multiple acquire and wait/notify\n");
    307         {
    308                 T_C_O_WS2 t1[2];
    309         }
    310         printf("Done Test 10\n");
    311 
    312         printf("Start Test 11: no lock condition variable wait/notify\n");
     269        printf("Start Test 9: no lock condition variable wait/notify\n");
    313270        {
    314271                T_C_NLW t1;
    315272                T_C_NLS t2;
    316273        }
    317         printf("Done Test 11\n");
    318 
    319         printf("Start Test 12: locked condition variable wait/notify with front()\n");
     274        printf("Done Test 9\n");
     275
     276        printf("Start Test 10: locked condition variable wait/notify with front()\n");
    320277        {
    321278                T_C_S_WNF t1[2];
    322279        }
    323         printf("Done Test 12\n");
     280        printf("Done Test 10\n");
    324281
    325282        // removed to limit test duration. Full test is in long run tests
Note: See TracChangeset for help on using the changeset viewer.