Changeset 797a193 for libcfa


Ignore:
Timestamp:
Dec 22, 2020, 12:50:46 PM (3 years ago)
Author:
caparsons <caparson@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
26a249c, 302ef2a
Parents:
fe97de26
Message:

cleaned up locks code and added comments

Location:
libcfa/src/concurrency
Files:
2 edited

Legend:

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

    rfe97de26 r797a193  
    11#include "locks.hfa"
    22#include "kernel_private.hfa"
    3 #include <stdlib.h>
    4 #include <stdio.h>
    53
    64#include <kernel.hfa>
    75#include <stdlib.hfa>
    8 #include <thread.hfa>
    96
    107///////////////////////////////////////////////////////////////////
     
    6158void lock( blocking_lock & this ) with( this ) {
    6259        lock( lock __cfaabi_dbg_ctx2 );
    63         if ( owner == active_thread() && !multi_acquisition) {
     60        if ( owner == active_thread() && !multi_acquisition) { // single acquisition lock is held by current thread
    6461                abort("A single acquisition lock holder attempted to reacquire the lock resulting in a deadlock.");
    65         } else if ( owner != 0p && owner != active_thread() ) {
     62        } else if ( owner != 0p && owner != active_thread() ) { // lock is held by some other thread
    6663                addTail( blocked_threads, *active_thread() );
    6764                wait_count++;
    6865                unlock( lock );
    6966                park( );
    70         } else if ( owner == active_thread() && multi_acquisition ) {
     67        } else if ( owner == active_thread() && multi_acquisition ) { // multi acquisition lock is held by current thread
    7168                recursion_count++;
    7269                unlock( lock );
    73         } else {
     70        } else { // lock isn't held
    7471                owner = active_thread();
    7572                recursion_count = 1;
     
    8178        bool ret = false;
    8279        lock( lock __cfaabi_dbg_ctx2 );
    83         if ( owner == 0p ) {
     80        if ( owner == 0p ) { // lock isn't held
    8481                owner = active_thread();
    8582                recursion_count = 1;
    8683                ret = true;
    87         } else if ( owner == active_thread() && multi_acquisition ) {
     84        } else if ( owner == active_thread() && multi_acquisition ) { // multi acquisition lock is held by current thread
    8885                recursion_count++;
    8986                ret = true;
     
    9491
    9592void unlock_error_check( blocking_lock & this ) with( this ) {
    96         if ( owner == 0p ){ // no owner implies lock isn't held
     93        if ( owner == 0p ){ // lock isn't held
    9794                abort( "There was an attempt to release a lock that isn't held" );
    9895        } else if ( strict_owner && owner != active_thread() ) {
     
    113110        unlock_error_check( this );
    114111        recursion_count--;
    115         if ( recursion_count == 0 ) {
     112        if ( recursion_count == 0 ) { // if recursion count is zero release lock and set new owner if one is waiting
    116113                pop_and_set_new_owner( this );
    117114        }
     
    131128}
    132129
    133 void add_( blocking_lock & this, $thread * t ) with( this ) {
     130void on_notify( blocking_lock & this, $thread * t ) with( this ) {
    134131    lock( lock __cfaabi_dbg_ctx2 );
    135         if ( owner != 0p ) {
     132        if ( owner != 0p ) { // lock held
    136133                addTail( blocked_threads, *t );
    137134                wait_count++;
    138135                unlock( lock );
    139         } else {
     136        } else {        // lock not held
    140137                owner = t;
    141138                recursion_count = 1;
     
    145142}
    146143
    147 void remove_( blocking_lock & this ) with( this ) {
     144void on_wait( blocking_lock & this ) with( this ) {
    148145    lock( lock __cfaabi_dbg_ctx2 );
    149146        unlock_error_check( this );
     
    156153///////////////////////////////////////////////////////////////////
    157154
    158 // This is temporary until an inheritance bug is fixed
     155// These routines are temporary until an inheritance bug is fixed
    159156
    160157void lock( single_acquisition_lock & this ){ lock( (blocking_lock &)this ); }
    161158void unlock( single_acquisition_lock & this ){ unlock( (blocking_lock &)this ); }
    162 void add_( single_acquisition_lock & this, struct $thread * t ){ add_( (blocking_lock &)this, t ); }
    163 void remove_( single_acquisition_lock & this ){ remove_( (blocking_lock &)this ); }
     159void on_notify( single_acquisition_lock & this, struct $thread * t ){ on_notify( (blocking_lock &)this, t ); }
     160void on_wait( single_acquisition_lock & this ){ on_wait( (blocking_lock &)this ); }
    164161void set_recursion_count( single_acquisition_lock & this, size_t recursion ){ set_recursion_count( (blocking_lock &)this, recursion ); }
    165162size_t get_recursion_count( single_acquisition_lock & this ){ return get_recursion_count( (blocking_lock &)this ); }
     
    167164void lock( owner_lock & this ){ lock( (blocking_lock &)this ); }
    168165void unlock( owner_lock & this ){ unlock( (blocking_lock &)this ); }
    169 void add_( owner_lock & this, struct $thread * t ){ add_( (blocking_lock &)this, t ); }
    170 void remove_( owner_lock & this ){ remove_( (blocking_lock &)this ); }
     166void on_notify( owner_lock & this, struct $thread * t ){ on_notify( (blocking_lock &)this, t ); }
     167void on_wait( owner_lock & this ){ on_wait( (blocking_lock &)this ); }
    171168void set_recursion_count( owner_lock & this, size_t recursion ){ set_recursion_count( (blocking_lock &)this, recursion ); }
    172169size_t get_recursion_count( owner_lock & this ){ return get_recursion_count( (blocking_lock &)this ); }
     
    174171void lock( multiple_acquisition_lock & this ){ lock( (blocking_lock &)this ); }
    175172void unlock( multiple_acquisition_lock & this ){ unlock( (blocking_lock &)this ); }
    176 void add_( multiple_acquisition_lock & this, struct $thread * t ){ add_( (blocking_lock &)this, t ); }
    177 void remove_( multiple_acquisition_lock & this ){ remove_( (blocking_lock &)this ); }
     173void on_notify( multiple_acquisition_lock & this, struct $thread * t ){ on_notify( (blocking_lock &)this, t ); }
     174void on_wait( multiple_acquisition_lock & this ){ on_wait( (blocking_lock &)this ); }
    178175void set_recursion_count( multiple_acquisition_lock & this, size_t recursion ){ set_recursion_count( (blocking_lock &)this, recursion ); }
    179176size_t get_recursion_count( multiple_acquisition_lock & this ){ return get_recursion_count( (blocking_lock &)this ); }
     
    188185        // This condition_variable member is called from the kernel, and therefore, cannot block, but it can spin.
    189186            lock( cond->lock __cfaabi_dbg_ctx2 );
    190             if ( listed(i) ) {                  // is thread on queue
     187
     188            // this check is necessary to avoid a race condition since this timeout handler
     189            //  may still be called after a thread has been removed from the queue but
     190            //  before the alarm is unregistered
     191            if ( listed(i) ) {                                                  // is thread on queue
    191192                i->signalled = false;
    192                 cond->last_thread = i;          // REMOVE THIS AFTER DEBUG
    193                         remove( cond->blocked_threads, *i );             //remove this thread O(1)
     193                        remove( cond->blocked_threads, *i );    // remove this thread O(1)
    194194                        cond->count--;
    195                         if( !i->lock ) {
    196                                 unpark( i->t );
     195                        if( i->lock ) {
     196                                on_notify(*i->lock, i->t);                      // call lock's on_notify if a lock was passed
    197197                } else {
    198                         add_(*i->lock, i->t);                   // call lock's add_
     198                        unpark( i->t );                                         // otherwise wake thread
    199199                }
    200200            }
     
    202202        }
    203203
     204        // this casts the alarm node to our wrapped type since we used type erasure
    204205        void alarm_node_wrap_cast( alarm_node_t & a ) { timeout_handler( (alarm_node_wrap(L) &)a ); }
    205206
     
    208209                this.blocked_threads{};
    209210                this.count = 0;
    210                 this.last_thread = 0p; // REMOVE AFTER DEBUG
    211211        }
    212212
     
    224224                        count--;
    225225                        if (popped.lock) {
    226                                 add_(*popped.lock, popped.t);
     226                                on_notify(*popped.lock, popped.t); // if lock passed call on_notify
    227227                        } else {
    228                                 unpark(popped.t);
     228                                unpark(popped.t); // otherwise wake thread
    229229                        }
    230230                }
     
    258258
    259259        size_t queue_and_get_recursion( condition_variable(L) & this, info_thread(L) * i ) with(this) {
    260                 addTail( blocked_threads, *i );
     260                addTail( blocked_threads, *i ); // add info_thread to waiting queue
    261261                count++;
    262262                size_t recursion_count = 0;
    263                 if (i->lock) {
     263                if (i->lock) { // if lock was passed get recursion count to reset to after waking thread
    264264                        recursion_count = get_recursion_count(*i->lock);
    265                         remove_( *i->lock );
     265                        on_wait( *i->lock );
    266266                }
    267267                return recursion_count;
     
    287287                unlock( lock );
    288288                park();
    289                 unregister_self( &node_wrap.alarm_node );
    290                 if (info.lock) set_recursion_count(*info.lock, recursion_count);
     289                unregister_self( &node_wrap.alarm_node ); // unregisters alarm so it doesn't go off if this happens first
     290                if (info.lock) set_recursion_count(*info.lock, recursion_count); // resets recursion count here after waking
    291291        }
    292292
  • libcfa/src/concurrency/locks.hfa

    rfe97de26 r797a193  
    66#include "bits/locks.hfa"
    77#include "bits/sequence.hfa"
    8 #include "bits/containers.hfa"
    98
    109#include "invoke.h"
     
    2019
    2120trait is_blocking_lock(dtype L | sized(L)) {
    22         void add_( L &, struct $thread * );             // For synchronization locks to use when acquiring
    23         void remove_( L & );    // For synchronization locks to use when releasing
    24         size_t get_recursion_count( L & ); // to get recursion count for cond lock to reset after waking
    25         void set_recursion_count( L &, size_t recursion ); // to set recursion count after getting signalled;
     21        void on_notify( L &, struct $thread * );                        // For synchronization locks to use when acquiring
     22        void on_wait( L & );                                                            // For synchronization locks to use when releasing
     23        size_t get_recursion_count( L & );                                      // to get recursion count for cond lock to reset after waking
     24        void set_recursion_count( L &, size_t recursion );      // to set recursion count after getting signalled;
    2625};
    2726
     
    3029///////////////////////////////////////////////////////////////////
    3130
     31// the info thread is a wrapper around a thread used
     32// to store extra data for use in the condition variable
    3233forall(dtype L | is_blocking_lock(L)) {
    3334        struct info_thread {
    34                 inline Seqable;
    35                 struct $thread * t;
    36                 uintptr_t info;
    37                 L * lock;
     35                inline Seqable;                                 // used to put info_thread on a dl queue (aka sequence)
     36                struct $thread * t;                             // waiting thread
     37                uintptr_t info;                                 // shadow field
     38                L * lock;                                               // lock that is passed to wait() (if one is passed)
    3839                bool signalled;                                 // true when signalled and false when timeout wakes thread
    3940        };
     
    4445        void ^?{}( info_thread(L) & this );
    4546
     47        // for use by sequence
    4648        info_thread(L) *& Back( info_thread(L) * this );
    4749        info_thread(L) *& Next( info_thread(L) * this );
     
    102104bool try_lock( blocking_lock & this );
    103105void unlock( blocking_lock & this );
    104 void add_( blocking_lock & this, struct $thread * t );
    105 void remove_( blocking_lock & this );
     106void on_notify( blocking_lock & this, struct $thread * t );
     107void on_wait( blocking_lock & this );
    106108size_t wait_count( blocking_lock & this );
    107109void set_recursion_count( blocking_lock & this, size_t recursion );
     
    110112void lock( single_acquisition_lock & this );
    111113void unlock( single_acquisition_lock & this );
    112 void add_( single_acquisition_lock & this, struct $thread * t );
    113 void remove_( single_acquisition_lock & this );
     114void on_notify( single_acquisition_lock & this, struct $thread * t );
     115void on_wait( single_acquisition_lock & this );
    114116void set_recursion_count( single_acquisition_lock & this, size_t recursion );
    115117size_t get_recursion_count( single_acquisition_lock & this );
     
    117119void lock( owner_lock & this );
    118120void unlock( owner_lock & this );
    119 void add_( owner_lock & this, struct $thread * t );
    120 void remove_( owner_lock & this );
     121void on_notify( owner_lock & this, struct $thread * t );
     122void on_wait( owner_lock & this );
    121123void set_recursion_count( owner_lock & this, size_t recursion );
    122124size_t get_recursion_count( owner_lock & this );
     
    124126void lock( multiple_acquisition_lock & this );
    125127void unlock( multiple_acquisition_lock & this );
    126 void add_( multiple_acquisition_lock & this, struct $thread * t );
    127 void remove_( multiple_acquisition_lock & this );
     128void on_notify( multiple_acquisition_lock & this, struct $thread * t );
     129void on_wait( multiple_acquisition_lock & this );
    128130void set_recursion_count( multiple_acquisition_lock & this, size_t recursion );
    129131size_t get_recursion_count( multiple_acquisition_lock & this );
     
    136138                // Spin lock used for mutual exclusion
    137139                __spinlock_t lock;
    138 
    139                 info_thread(L) * last_thread;
    140140
    141141                // List of blocked threads
Note: See TracChangeset for help on using the changeset viewer.