Ignore:
Timestamp:
Nov 6, 2020, 4:48:52 PM (4 years ago)
Author:
m3zulfiq <m3zulfiq@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
75baaa3
Parents:
55acc3a (diff), 836c9925 (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

File:
1 edited

Legend:

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

    r55acc3a r139775e  
    1515                this.t = t;
    1616                this.lock = 0p;
     17                this.listed = false;
    1718        }
    1819
     
    2122                this.info = info;
    2223                this.lock = 0p;
     24                this.listed = false;
    2325        }
    2426
     
    7476
    7577void lock( blocking_lock & this ) with( this ) {
     78        $thread * thrd = active_thread();
    7679        lock( lock __cfaabi_dbg_ctx2 );
    77         if ( owner == kernelTLS.this_thread && !multi_acquisition) {
     80        if ( owner == thrd && !multi_acquisition) {
    7881                fprintf(stderr, "A single acquisition lock holder attempted to reacquire the lock resulting in a deadlock."); // Possibly throw instead
    79                 exit(EXIT_FAILURE);
    80         } else if ( owner != 0p && owner != kernelTLS.this_thread ) {
    81                 append( blocked_threads, kernelTLS.this_thread );
     82        exit(EXIT_FAILURE);
     83        } else if ( owner != 0p && owner != thrd ) {
     84                append( blocked_threads, thrd );
    8285                wait_count++;
    8386                unlock( lock );
    84                 park( __cfaabi_dbg_ctx );
    85         } else if ( owner == kernelTLS.this_thread && multi_acquisition ) {
     87                park( );
     88        } else if ( owner == thrd && multi_acquisition ) {
    8689                recursion_count++;
    8790                unlock( lock );
    8891        } else {
    89                 owner = kernelTLS.this_thread;
     92                owner = thrd;
    9093                recursion_count = 1;
    9194                unlock( lock );
     
    9497
    9598bool try_lock( blocking_lock & this ) with( this ) {
     99        $thread * thrd = active_thread();
    96100        bool ret = false;
    97101        lock( lock __cfaabi_dbg_ctx2 );
    98102        if ( owner == 0p ) {
    99                 owner = kernelTLS.this_thread;
     103                owner = thrd;
    100104                if ( multi_acquisition ) recursion_count = 1;
    101105                ret = true;
    102         } else if ( owner == kernelTLS.this_thread && multi_acquisition ) {
     106        } else if ( owner == thrd && multi_acquisition ) {
    103107                recursion_count++;
    104108                ret = true;
     
    113117                fprintf( stderr, "There was an attempt to release a lock that isn't held" );
    114118                return;
    115         } else if ( strict_owner && owner != kernelTLS.this_thread ) {
     119        } else if ( strict_owner && active_thread() ) {
    116120                fprintf( stderr, "A thread other than the owner attempted to release an owner lock" );
    117121                return;
     
    123127                recursion_count = ( thrd && multi_acquisition ? 1 : 0 );
    124128                wait_count--;
    125                 unpark( thrd __cfaabi_dbg_ctx2 );
     129                unpark( thrd );
    126130        }
    127131        unlock( lock );
     
    150154                owner = t;
    151155                if ( multi_acquisition ) recursion_count = 1;
    152                 unpark( t __cfaabi_dbg_ctx2 );
     156                #if !defined( __CFA_NO_STATISTICS__ )
     157                        kernelTLS.this_stats = t->curr_cluster->stats;
     158                #endif
     159                unpark( t );
    153160                unlock( lock );
    154161        }
     
    159166        if ( owner == 0p ){ // no owner implies lock isn't held
    160167                fprintf( stderr, "A lock that is not held was passed to a synchronization lock" );
    161         } else if ( strict_owner && owner != kernelTLS.this_thread ) {
     168        } else if ( strict_owner && active_thread() ) {
    162169                fprintf( stderr, "A thread other than the owner of a lock passed it to a synchronization lock" );
    163170        } else {
     
    166173                recursion_count = ( thrd && multi_acquisition ? 1 : 0 );
    167174                wait_count--;
    168                 unpark( thrd __cfaabi_dbg_ctx2 );
     175                unpark( thrd );
    169176        }
    170177        unlock( lock );
     
    175182///////////////////////////////////////////////////////////////////
    176183
    177 // In an ideal world this may not be necessary
    178 // Is it possible for nominal inheritance to inherit traits??
    179 // If that occurs we would avoid all this extra code
     184// This is temporary until an inheritance bug is fixed
    180185
    181186void lock( mutex_lock & this ){
     
    228233
    229234///////////////////////////////////////////////////////////////////
    230 //// Synchronization Locks
     235//// condition variable
    231236///////////////////////////////////////////////////////////////////
    232237
    233238forall(dtype L | is_blocking_lock(L)) {
    234         void ?{}( synchronization_lock(L) & this, bool reacquire_after_signal ){
     239
     240        void timeout_handler ( alarm_node_wrap(L) & this ) with( this ) {
     241        // This condition_variable member is called from the kernel, and therefore, cannot block, but it can spin.
     242            lock( cond->lock __cfaabi_dbg_ctx2 );
     243            if ( (*i)->listed ) {                       // is thread on queue
     244                info_thread(L) * copy = *i;
     245                        remove( cond->blocked_threads, i );              //remove this thread O(1)
     246                        cond->wait_count--;
     247                        if( !copy->lock ) {
     248                                unlock( cond->lock );
     249                                #if !defined( __CFA_NO_STATISTICS__ )
     250                                        #warning unprotected access to tls TODO discuss this
     251                                        kernelTLS.this_stats = copy->t->curr_cluster->stats;
     252                                #endif
     253                                unpark( copy->t );
     254                } else {
     255                        add_(*copy->lock, copy->t);                     // call lock's add_
     256                }
     257            }
     258            unlock( cond->lock );
     259        }
     260
     261        void alarm_node_wrap_cast( alarm_node_t & a ) {
     262                timeout_handler( (alarm_node_wrap(L) &)a );
     263        }
     264
     265        void ?{}( condition_variable(L) & this ){
    235266                this.lock{};
    236267                this.blocked_threads{};
    237268                this.count = 0;
    238                 this.reacquire_after_signal = reacquire_after_signal;
    239         }
    240 
    241         void ^?{}( synchronization_lock(L) & this ){
    242                 // default
    243         }
    244 
    245         void ?{}( condition_variable(L) & this ){
    246                 ((synchronization_lock(L) &)this){ true };
    247269        }
    248270
     
    251273        }
    252274
    253         void ?{}( thread_queue(L) & this ){
    254                 ((synchronization_lock(L) &)this){ false };
    255         }
    256 
    257         void ^?{}( thread_queue(L) & this ){
     275        void ?{}( alarm_node_wrap(L) & this, $thread * thrd, Time alarm, Duration period, Alarm_Callback callback ) {
     276                this.alarm_node{ thrd, alarm, period, callback };
     277        }
     278
     279        void ^?{}( alarm_node_wrap(L) & this ) {
    258280                // default
    259281        }
    260282
    261         bool notify_one( synchronization_lock(L) & this ) with( this ) {
     283        bool notify_one( condition_variable(L) & this ) with( this ) {
    262284                lock( lock __cfaabi_dbg_ctx2 );
    263285                bool ret = !!blocked_threads;
    264286                info_thread(L) * popped = pop_head( blocked_threads );
     287                popped->listed = false;
    265288                if(popped != 0p) {
    266                         if( reacquire_after_signal ){
     289                        count--;
     290                        if (popped->lock) {
    267291                                add_(*popped->lock, popped->t);
    268292                        } else {
    269                                 unpark(
    270                                         popped->t __cfaabi_dbg_ctx2
    271                                 );
     293                                unpark(popped->t);
    272294                        }
    273295                }
     
    276298        }
    277299
    278         bool notify_all( synchronization_lock(L) & this ) with(this) {
     300        bool notify_all( condition_variable(L) & this ) with(this) {
    279301                lock( lock __cfaabi_dbg_ctx2 );
    280302                bool ret = blocked_threads ? true : false;
    281303                while( blocked_threads ) {
    282304                        info_thread(L) * popped = pop_head( blocked_threads );
     305                        popped->listed = false;
    283306                        if(popped != 0p){
    284                                 if( reacquire_after_signal ){
     307                                count--;
     308                                if (popped->lock) {
    285309                                        add_(*popped->lock, popped->t);
    286310                                } else {
    287                                         unpark(
    288                                                 popped->t __cfaabi_dbg_ctx2
    289                                         );
     311                                        unpark(popped->t);
    290312                                }
    291313                        }
     
    295317        }
    296318
    297         uintptr_t front( synchronization_lock(L) & this ) with(this) {
    298                 return (*peek(blocked_threads)).info;
    299         }
    300 
    301         bool empty( synchronization_lock(L) & this ) with(this) {
     319        uintptr_t front( condition_variable(L) & this ) with(this) {
     320                if(!blocked_threads) return NULL;
     321                return peek(blocked_threads)->info;
     322        }
     323
     324        bool empty( condition_variable(L) & this ) with(this) {
    302325                return blocked_threads ? false : true;
    303326        }
    304327
    305         int counter( synchronization_lock(L) & this ) with(this) {
     328        int counter( condition_variable(L) & this ) with(this) {
    306329                return count;
    307330        }
    308331
    309         void queue_info_thread( synchronization_lock(L) & this, info_thread(L) & i ) with(this) {
    310                 lock( lock __cfaabi_dbg_ctx2 );
    311                 append( blocked_threads, &i );
    312                 count++;
    313                 unlock( lock );
    314                 park( __cfaabi_dbg_ctx );
    315         }
    316 
    317 
    318         void wait( synchronization_lock(L) & this ) with(this) {
    319                 info_thread( L ) i = { kernelTLS.this_thread };
    320                 queue_info_thread( this, i );
    321         }
    322 
    323         void wait( synchronization_lock(L) & this, uintptr_t info ) with(this) {
    324                 info_thread( L ) i = { kernelTLS.this_thread, info };
    325                 queue_info_thread( this, i );
    326         }
    327         // I still need to implement the time delay wait routines
    328         bool wait( synchronization_lock(L) & this, Duration duration ) with(this) {
    329                 timeval tv = { time(0) };
    330                 Time t = { tv };
    331                 return wait( this, t + duration );
    332         }
    333 
    334         bool wait( synchronization_lock(L) & this, uintptr_t info, Duration duration ) with(this) {
    335                 // TODO: ADD INFO
    336                 return wait( this, duration );
    337         }
    338 
    339         bool wait( synchronization_lock(L) & this, Time time ) with(this) {
    340                 return false; //default
    341         }
    342 
    343         bool wait( synchronization_lock(L) & this, uintptr_t info, Time time ) with(this) {
    344                 // TODO: ADD INFO
    345                 return wait( this, time );
    346         }
    347 
    348         void queue_info_thread_unlock( synchronization_lock(L) & this, L & l, info_thread(L) & i ) with(this) {
     332        // helper for wait()'s' without a timeout
     333        void queue_info_thread( condition_variable(L) & this, info_thread(L) & i ) with(this) {
    349334                lock( lock __cfaabi_dbg_ctx2 );
    350335                append( this.blocked_threads, &i );
    351336                count++;
    352                 i.lock = &l;
    353                 size_t recursion_count = get_recursion_count(l);
    354                 remove_( l );
    355                 unlock( lock );
    356                 park( __cfaabi_dbg_ctx ); // blocks here
    357 
    358                 set_recursion_count(l, recursion_count); // resets recursion count here after waking
    359         }
    360 
    361         void wait( synchronization_lock(L) & this, L & l ) with(this) {
    362                 info_thread(L) i = { kernelTLS.this_thread };
    363                 queue_info_thread_unlock( this, l, i );
    364         }
    365 
    366         void wait( synchronization_lock(L) & this, L & l, uintptr_t info ) with(this) {
    367                 info_thread(L) i = { kernelTLS.this_thread, info };
    368                 queue_info_thread_unlock( this, l, i );
    369         }
    370 
    371         bool wait( synchronization_lock(L) & this, L & l, Duration duration ) with(this) {
    372                 timeval tv = { time(0) };
    373                 Time t = { tv };
    374                 return wait( this, l, t + duration );
    375         }
    376 
    377         bool wait( synchronization_lock(L) & this, L & l, uintptr_t info, Duration duration ) with(this) {
    378                 // TODO: ADD INFO
    379                 return wait( this, l, duration );
    380         }
    381 
    382         bool wait( synchronization_lock(L) & this, L & l, Time time ) with(this) {
    383                 return false; //default
    384         }
    385 
    386         bool wait( synchronization_lock(L) & this, L & l, uintptr_t info, Time time ) with(this) {
    387                 // TODO: ADD INFO
    388                 return wait( this, l, time );
    389         }
    390 }
    391 
    392 ///////////////////////////////////////////////////////////////////
    393 //// condition lock alternative approach
    394 ///////////////////////////////////////////////////////////////////
    395 
    396 // the solution below is less efficient but does not require the lock to have a specific add/remove routine
    397 
    398 ///////////////////////////////////////////////////////////////////
    399 //// is_simple_lock
    400 ///////////////////////////////////////////////////////////////////
    401 
    402 forall(dtype L | is_simple_lock(L)) {
    403         void ?{}( condition_lock(L) & this ){
    404                 // default
    405         }
    406 
    407         void ^?{}( condition_lock(L) & this ){
    408                 // default
    409         }
    410 
    411         bool notify_one( condition_lock(L) & this ) with(this) {
    412                 return notify_one( c_var );
    413         }
    414 
    415         bool notify_all( condition_lock(L) & this ) with(this) {
    416                 return notify_all( c_var );
    417         }
    418 
    419         void wait( condition_lock(L) & this, L & l ) with(this) {
    420                 lock( m_lock );
    421                 size_t recursion = get_recursion_count( l );
    422                 unlock( l );
    423                 wait( c_var, m_lock );
    424                 lock( l );
    425                 set_recursion_count( l , recursion );
    426                 unlock( m_lock );
    427         }
    428 }
     337                i.listed = true;
     338                size_t recursion_count;
     339                if (i.lock) {
     340                        recursion_count = get_recursion_count(*i.lock);
     341                        remove_( *i.lock );
     342                }
     343
     344                unlock( lock );
     345                park( ); // blocks here
     346
     347                if (i.lock) set_recursion_count(*i.lock, recursion_count); // resets recursion count here after waking
     348        }
     349
     350        // helper for wait()'s' with a timeout
     351        void queue_info_thread_timeout( condition_variable(L) & this, info_thread(L) & info, Time t ) with(this) {
     352                lock( lock __cfaabi_dbg_ctx2 );
     353
     354                info_thread(L) * queue_ptr = &info;
     355
     356                alarm_node_wrap(L) node_wrap = { info.t, t, 0`s, alarm_node_wrap_cast };
     357                node_wrap.cond = &this;
     358                node_wrap.i = &queue_ptr;
     359
     360                register_self( &node_wrap.alarm_node );
     361
     362                append( blocked_threads, queue_ptr );
     363                info.listed = true;
     364                count++;
     365
     366                size_t recursion_count;
     367                if (info.lock) {
     368                        recursion_count = get_recursion_count(*info.lock);
     369                        remove_( *info.lock );
     370                }
     371
     372                unlock( lock );
     373                park();
     374
     375                if (info.lock) set_recursion_count(*info.lock, recursion_count);
     376        }
     377
     378        void wait( condition_variable(L) & this ) with(this) {
     379                info_thread( L ) i = { active_thread() };
     380                queue_info_thread( this, i );
     381        }
     382
     383        void wait( condition_variable(L) & this, uintptr_t info ) with(this) {
     384                info_thread( L ) i = { active_thread(), info };
     385                queue_info_thread( this, i );
     386        }
     387
     388        void wait( condition_variable(L) & this, Duration duration ) with(this) {
     389                info_thread( L ) i = { active_thread() };
     390                queue_info_thread_timeout(this, i, __kernel_get_time() + duration );
     391        }
     392
     393        void wait( condition_variable(L) & this, uintptr_t info, Duration duration ) with(this) {
     394                info_thread( L ) i = { active_thread(), info };
     395                queue_info_thread_timeout(this, i, __kernel_get_time() + duration );
     396        }
     397
     398        void wait( condition_variable(L) & this, Time time ) with(this) {
     399                info_thread( L ) i = { active_thread() };
     400                queue_info_thread_timeout(this, i, time);
     401        }
     402
     403        void wait( condition_variable(L) & this, uintptr_t info, Time time ) with(this) {
     404                info_thread( L ) i = { active_thread(), info };
     405                queue_info_thread_timeout(this, i, time);
     406        }
     407
     408        void wait( condition_variable(L) & this, L & l ) with(this) {
     409                info_thread(L) i = { active_thread() };
     410                i.lock = &l;
     411                queue_info_thread( this, i );
     412        }
     413
     414        void wait( condition_variable(L) & this, L & l, uintptr_t info ) with(this) {
     415                info_thread(L) i = { active_thread(), info };
     416                i.lock = &l;
     417                queue_info_thread( this, i );
     418        }
     419
     420        void wait( condition_variable(L) & this, L & l, Duration duration ) with(this) {
     421                info_thread(L) i = { active_thread() };
     422                i.lock = &l;
     423                queue_info_thread_timeout(this, i, __kernel_get_time() + duration );
     424        }
     425
     426        void wait( condition_variable(L) & this, L & l, uintptr_t info, Duration duration ) with(this) {
     427                info_thread(L) i = { active_thread(), info };
     428                i.lock = &l;
     429                queue_info_thread_timeout(this, i, __kernel_get_time() + duration );
     430        }
     431
     432        void wait( condition_variable(L) & this, L & l, Time time ) with(this) {
     433                info_thread(L) i = { active_thread() };
     434                i.lock = &l;
     435                queue_info_thread_timeout(this, i, time );
     436        }
     437
     438        void wait( condition_variable(L) & this, L & l, uintptr_t info, Time time ) with(this) {
     439                info_thread(L) i = { active_thread(), info };
     440                i.lock = &l;
     441                queue_info_thread_timeout(this, i, time );
     442        }
     443}
Note: See TracChangeset for help on using the changeset viewer.