Changeset b580bcc


Ignore:
Timestamp:
Apr 1, 2021, 4:20:00 PM (3 years ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
fd1f65e
Parents:
3bd2464 (diff), 198e335 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Files:
4 added
8 edited

Legend:

Unmodified
Added
Removed
  • doc/theses/andrew_beach_MMath/future.tex

    r3bd2464 rb580bcc  
    8383patterns to find the handler.
    8484
     85\section{Checked Exceptions}
     86Checked exceptions make exceptions part of a function's type by adding the
     87exception signature. An exception signature must declare all checked
     88exceptions that could propogate from the function (either because they were
     89raised inside the function or came from a sub-function). This improves safety
     90by making sure every checked exception is either handled or consciously
     91passed on.
     92
     93However checked exceptions were never seriously considered for this project
     94for two reasons. The first is due to time constraints, even copying an
     95existing checked exception system would be pushing the remaining time and
     96trying to address the second problem would take even longer. The second
     97problem is that checked exceptions have some real usability trade-offs in
     98exchange for the increased safety.
     99
     100These trade-offs are most problematic when trying to pass exceptions through
     101higher-order functions from the functions the user passed into the
     102higher-order function. There are no well known solutions to this problem
     103that were statifactory for \CFA (which carries some of C's flexability
     104over safety design) so one would have to be researched and developed.
     105
     106Follow-up work might add checked exceptions to \CFA, possibly using
     107polymorphic exception signatures, a form of tunneling\cite{Zhang19} or
     108checked and unchecked raises.
     109
    85110\section{Zero-Cost Try}
    86111\CFA does not have zero-cost try-statements because the compiler generates C
  • libcfa/src/bits/weakso_locks.cfa

    r3bd2464 rb580bcc  
    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

    r3bd2464 rb580bcc  
    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

    r3bd2464 rb580bcc  
    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

    r3bd2464 rb580bcc  
    3939};
    4040
    41 static inline bool P(Semaphore0nary & this, $thread * thrd) __attribute__((artificial));
    4241static inline bool P(Semaphore0nary & this, $thread * thrd) {
    4342        /* paranoid */ verify(!(thrd->seqable.next));
     
    4847}
    4948
    50 static inline bool P(Semaphore0nary & this) __attribute__((artificial));
    5149static inline bool P(Semaphore0nary & this) {
    5250    $thread * thrd = active_thread();
     
    5654}
    5755
    58 static inline $thread * V(Semaphore0nary & this, const bool doUnpark = true) __attribute__((artificial));
    59 static inline $thread * V(Semaphore0nary & this, const bool doUnpark = true) {
     56static inline $thread * V(Semaphore0nary & this, bool doUnpark = true) {
    6057        $thread * next;
    6158        lock(this.lock __cfaabi_dbg_ctx2);
     
    8279
    8380        // returns true if no blocking needed
    84         bool P(BinaryBenaphore & this) { return __atomic_fetch_sub(&this.counter, 1, __ATOMIC_SEQ_CST) > 0; }
     81        bool P(BinaryBenaphore & this) {
     82                return __atomic_fetch_sub(&this.counter, 1, __ATOMIC_SEQ_CST) > 0;
     83        }
     84
    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); }
    118 static inline bool P(ThreadBenaphore & this, $thread * t) { return /* P(this.ben) ? false : */ P(this.sem, t ); }
     117static inline bool P(ThreadBenaphore & this)              { return P(this.ben) ? false : P(this.sem); }
    119118static inline bool tryP(ThreadBenaphore & this)           { return tryP(this.ben); }
    120119static inline bool P(ThreadBenaphore & this, bool wait)   { return wait ? P(this) : tryP(this); }
    121120
    122 static inline $thread * V(ThreadBenaphore & this, const bool doUnpark = true) {
    123         // if (V(this.ben)) return 0p;
     121static inline $thread * V(ThreadBenaphore & this, bool doUnpark = true) {
     122        if (V(this.ben)) return 0p;
    124123        return V(this.sem, doUnpark);
    125124}
     
    138137bool   V (semaphore & this);
    139138bool   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 void   on_wait   ( single_acquisition_lock & this ) { on_wait ( (blocking_lock &)this ); }
    152 static inline void   on_notify ( single_acquisition_lock & this, struct $thread * t ) { on_notify( (blocking_lock &)this, t ); }
    153 static inline void   set_recursion_count( single_acquisition_lock & this, size_t recursion ) { set_recursion_count( (blocking_lock &)this, recursion ); }
    154 static inline size_t get_recursion_count( single_acquisition_lock & this ) { return get_recursion_count( (blocking_lock &)this ); }
     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 size_t on_wait  ( single_acquisition_lock & this ) { return on_wait ( (blocking_lock &)this ); }
     152static inline void   on_wakeup( single_acquisition_lock & this, size_t v ) { on_wakeup ( (blocking_lock &)this, v ); }
     153static inline void   on_notify( single_acquisition_lock & this, struct $thread * t ) { on_notify( (blocking_lock &)this, t ); }
    155154
    156155//----------
     
    164163static inline bool   try_lock ( owner_lock & this ) { return try_lock( (blocking_lock &)this ); }
    165164static inline void   unlock   ( owner_lock & this ) { unlock  ( (blocking_lock &)this ); }
    166 static inline void   on_wait  ( owner_lock & this ) { on_wait ( (blocking_lock &)this ); }
     165static inline size_t on_wait  ( owner_lock & this ) { return on_wait ( (blocking_lock &)this ); }
     166static inline void   on_wakeup( owner_lock & this, size_t v ) { on_wakeup ( (blocking_lock &)this, v ); }
    167167static inline void   on_notify( owner_lock & this, struct $thread * t ) { on_notify( (blocking_lock &)this, t ); }
    168 static inline void   set_recursion_count( owner_lock & this, size_t recursion ) { set_recursion_count( (blocking_lock &)this, recursion ); }
    169 static inline size_t get_recursion_count( owner_lock & this ) { return get_recursion_count( (blocking_lock &)this ); }
    170168
    171169struct fast_lock {
     
    179177}
    180178
    181 static 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 
     179static inline void lock( fast_lock & this ) __attribute__((artificial));
    190180static inline void lock( fast_lock & this ) {
    191181        $thread * thrd = active_thread();
     
    198188}
    199189
    200 static inline void try_lock ( fast_lock & this ) {
     190static inline bool try_lock( fast_lock & this ) __attribute__((artificial));
     191static inline bool try_lock ( fast_lock & this ) {
    201192        $thread * thrd = active_thread();
    202193        /* paranoid */ verify(thrd != this.owner);
     
    204195}
    205196
    206 static inline void unlock( fast_lock & this ) {
     197static inline $thread * unlock( fast_lock & this ) __attribute__((artificial));
     198static inline $thread * unlock( fast_lock & this ) {
    207199        $thread * thrd = active_thread();
    208200        /* paranoid */ verify(thrd == this.owner);
    209         $thread * next = V(this.sem, false); // implicit fence
    210         // open 'owner' only after fence
     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.
    211205        this.owner = 0p;
    212206
    213         // Unpark the next person (can be 0p, unpark handles it)
    214         unpark(next);
    215 }
    216 
    217 static inline void on_wait( fast_lock & this ) {
    218         unlock(this);
    219         #warning this is broken
    220 }
    221 
    222 static inline void on_notify( fast_lock & this, struct $thread * t ) {
    223         $lock(this, t);
    224         #warning this is broken
    225 }
    226 
    227 static inline void   set_recursion_count( fast_lock & this, size_t recursion ) {}
    228 static inline size_t get_recursion_count( fast_lock & this ) { return 0; }
     207        return V(this.sem);
     208}
     209
     210static inline size_t on_wait( fast_lock & this ) { unlock(this); return 0; }
     211static inline void on_wakeup( fast_lock & this, size_t ) { lock(this); }
     212static inline void on_notify( fast_lock &, struct $thread * t ) { unpark(t); }
    229213
    230214struct mcs_node {
     
    260244
    261245        // For synchronization locks to use when releasing
    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 & );
     246        size_t on_wait( L & );
    266247
    267248        // to set recursion count after getting signalled;
    268         void set_recursion_count( L &, size_t recursion );
     249        void on_wakeup( L &, size_t recursion );
    269250};
    270251
  • tests/concurrent/spinaphore.cfa

    r3bd2464 rb580bcc  
    3636        this.sum = 0;
    3737        for(num_blocks) {
    38                 // sout | "b P" | me;
    3938                P(sem);
    4039                if(((thread&)this).seqable.next != 0p) sout | "Link not invalidated";
    41                 // sout | "a P" | me;
    4240        }
    4341}
     
    5856                this.sum += (unsigned)b;
    5957                unpark(t);
    60                 // sout | "a V" | t;
    6158                yield(random(10));
    6259        }
  • tests/unified_locking/.expect/locks.txt

    r3bd2464 rb580bcc  
    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

    r3bd2464 rb580bcc  
    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.