Ignore:
File:
1 edited

Legend:

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

    rbe73f30 r6a8882c  
    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
     
    4951}
    5052
    51 void ?{}( mutex_lock & this ) {
     53void ?{}( single_acquisition_lock & this ) {
    5254        ((blocking_lock &)this){ false, false };
    5355}
    5456
    55 void ^?{}( mutex_lock & this ) {
     57void ^?{}( single_acquisition_lock & this ) {
    5658        // default
    5759}
     
    6567}
    6668
    67 void ?{}( recursive_mutex_lock & this ) {
     69void ?{}( multiple_acquisition_lock & this ) {
    6870        ((blocking_lock &)this){ true, false };
    6971}
    7072
    71 void ^?{}( recursive_mutex_lock & this ) {
     73void ^?{}( multiple_acquisition_lock & this ) {
    7274        // default
    7375}
    7476
    7577void lock( blocking_lock & this ) with( this ) {
    76         $thread * thrd = active_thread();
    7778        lock( lock __cfaabi_dbg_ctx2 );
    78         if ( owner == thrd && !multi_acquisition) {
     79        if ( owner == active_thread() && !multi_acquisition) {
    7980                fprintf(stderr, "A single acquisition lock holder attempted to reacquire the lock resulting in a deadlock."); // Possibly throw instead
    80                 exit(EXIT_FAILURE);
    81         } else if ( owner != 0p && owner != thrd ) {
    82                 append( blocked_threads, thrd );
     81        exit(EXIT_FAILURE);
     82        } else if ( owner != 0p && owner != active_thread() ) {
     83                append( blocked_threads, active_thread() );
    8384                wait_count++;
    8485                unlock( lock );
    85                 park( __cfaabi_dbg_ctx );
    86         } else if ( owner == thrd && multi_acquisition ) {
     86                park( );
     87        } else if ( owner == active_thread() && multi_acquisition ) {
    8788                recursion_count++;
    8889                unlock( lock );
    8990        } else {
    90                 owner = thrd;
     91                owner = active_thread();
    9192                recursion_count = 1;
    9293                unlock( lock );
     
    9596
    9697bool try_lock( blocking_lock & this ) with( this ) {
    97         $thread * thrd = active_thread();
    9898        bool ret = false;
    9999        lock( lock __cfaabi_dbg_ctx2 );
    100100        if ( owner == 0p ) {
    101                 owner = thrd;
    102                 if ( multi_acquisition ) recursion_count = 1;
     101                owner = active_thread();
     102                recursion_count = 1;
    103103                ret = true;
    104         } else if ( owner == thrd && multi_acquisition ) {
     104        } else if ( owner == active_thread() && multi_acquisition ) {
    105105                recursion_count++;
    106106                ret = true;
     
    113113        lock( lock __cfaabi_dbg_ctx2 );
    114114        if ( owner == 0p ){ // no owner implies lock isn't held
    115                 fprintf( stderr, "There was an attempt to release a lock that isn't held" );
     115                fprintf( stderr, "There was an attempt to release a lock that isn't held" ); 
    116116                return;
    117117        } else if ( strict_owner && owner != active_thread() ) {
    118                 fprintf( stderr, "A thread other than the owner attempted to release an owner lock" );
     118                fprintf( stderr, "A thread other than the owner attempted to release an owner lock" ); 
    119119                return;
    120120        }
     
    123123                $thread * thrd = pop_head( blocked_threads );
    124124                owner = thrd;
    125                 recursion_count = ( thrd && multi_acquisition ? 1 : 0 );
     125                recursion_count = ( thrd ? 1 : 0 );
    126126                wait_count--;
    127                 unpark( thrd __cfaabi_dbg_ctx2 );
     127                unpark( thrd );
    128128        }
    129129        unlock( lock );
     
    151151        } else {
    152152                owner = t;
    153                 if ( multi_acquisition ) recursion_count = 1;
    154                 unpark( t __cfaabi_dbg_ctx2 );
     153                recursion_count = 1;
     154                #if !defined( __CFA_NO_STATISTICS__ )
     155                        //kernelTLS.this_stats = t->curr_cluster->stats;
     156                #endif
     157                unpark( t );
    155158                unlock( lock );
    156159        }
     
    160163    lock( lock __cfaabi_dbg_ctx2 );
    161164        if ( owner == 0p ){ // no owner implies lock isn't held
    162                 fprintf( stderr, "A lock that is not held was passed to a synchronization lock" );
     165                fprintf( stderr, "A lock that is not held was passed to a synchronization lock" ); 
    163166        } else if ( strict_owner && owner != active_thread() ) {
    164                 fprintf( stderr, "A thread other than the owner of a lock passed it to a synchronization lock" );
     167                fprintf( stderr, "A thread other than the owner of a lock passed it to a synchronization lock" ); 
    165168        } else {
    166169                $thread * thrd = pop_head( blocked_threads );
    167170                owner = thrd;
    168                 recursion_count = ( thrd && multi_acquisition ? 1 : 0 );
     171                recursion_count = ( thrd ? 1 : 0 );
    169172                wait_count--;
    170                 unpark( thrd __cfaabi_dbg_ctx2 );
     173                unpark( thrd );
    171174        }
    172175        unlock( lock );
     
    177180///////////////////////////////////////////////////////////////////
    178181
    179 // In an ideal world this may not be necessary
    180 // Is it possible for nominal inheritance to inherit traits??
    181 // If that occurs we would avoid all this extra code
    182 
    183 void lock( mutex_lock & this ){
     182// This is temporary until an inheritance bug is fixed
     183
     184void lock( single_acquisition_lock & this ){
    184185        lock( (blocking_lock &)this );
    185186}
    186187
    187 void unlock( mutex_lock & this ){
     188void unlock( single_acquisition_lock & this ){
    188189        unlock( (blocking_lock &)this );
    189190}
    190191
    191 void add_( mutex_lock & this, struct $thread * t ){
     192void add_( single_acquisition_lock & this, struct $thread * t ){
    192193        add_( (blocking_lock &)this, t );
    193194}
    194195
    195 void remove_( mutex_lock & this ){
     196void remove_( single_acquisition_lock & this ){
    196197        remove_( (blocking_lock &)this );
    197198}
    198199
    199 void set_recursion_count( mutex_lock & this, size_t recursion ){
     200void set_recursion_count( single_acquisition_lock & this, size_t recursion ){
    200201        set_recursion_count( (blocking_lock &)this, recursion );
    201202}
    202203
    203 size_t get_recursion_count( mutex_lock & this ){
    204         get_recursion_count( (blocking_lock &)this );
    205 }
    206 
    207 void lock( recursive_mutex_lock & this ){
     204size_t get_recursion_count( single_acquisition_lock & this ){
     205        return get_recursion_count( (blocking_lock &)this );
     206}
     207
     208void lock( owner_lock & this ){
    208209        lock( (blocking_lock &)this );
    209210}
    210211
    211 void unlock( recursive_mutex_lock & this ){
     212void unlock( owner_lock & this ){
    212213        unlock( (blocking_lock &)this );
    213214}
    214215
    215 void add_( recursive_mutex_lock & this, struct $thread * t ){
     216void add_( owner_lock & this, struct $thread * t ){
    216217        add_( (blocking_lock &)this, t );
    217218}
    218219
    219 void remove_( recursive_mutex_lock & this ){
     220void remove_( owner_lock & this ){
    220221        remove_( (blocking_lock &)this );
    221222}
    222223
    223 void set_recursion_count( recursive_mutex_lock & this, size_t recursion ){
     224void set_recursion_count( owner_lock & this, size_t recursion ){
    224225        set_recursion_count( (blocking_lock &)this, recursion );
    225226}
    226227
    227 size_t get_recursion_count( recursive_mutex_lock & this ){
    228         get_recursion_count( (blocking_lock &)this );
    229 }
    230 
    231 ///////////////////////////////////////////////////////////////////
    232 //// Synchronization Locks
     228size_t get_recursion_count( owner_lock & this ){
     229        return get_recursion_count( (blocking_lock &)this );
     230}
     231
     232void lock( multiple_acquisition_lock & this ){
     233        lock( (blocking_lock &)this );
     234}
     235
     236void unlock( multiple_acquisition_lock & this ){
     237        unlock( (blocking_lock &)this );
     238}
     239
     240void add_( multiple_acquisition_lock & this, struct $thread * t ){
     241        add_( (blocking_lock &)this, t );
     242}
     243
     244void remove_( multiple_acquisition_lock & this ){
     245        remove_( (blocking_lock &)this );
     246}
     247
     248void set_recursion_count( multiple_acquisition_lock & this, size_t recursion ){
     249        set_recursion_count( (blocking_lock &)this, recursion );
     250}
     251
     252size_t get_recursion_count( multiple_acquisition_lock & this ){
     253        return get_recursion_count( (blocking_lock &)this );
     254}
     255
     256///////////////////////////////////////////////////////////////////
     257//// condition variable
    233258///////////////////////////////////////////////////////////////////
    234259
    235260forall(dtype L | is_blocking_lock(L)) {
    236         void ?{}( synchronization_lock(L) & this, bool reacquire_after_signal ){
     261
     262        void timeout_handler ( alarm_node_wrap(L) & this ) with( this ) {
     263        // This condition_variable member is called from the kernel, and therefore, cannot block, but it can spin.
     264            lock( cond->lock __cfaabi_dbg_ctx2 );
     265            if ( (*i)->listed ) {                       // is thread on queue
     266                info_thread(L) * copy = *i;
     267                        remove( cond->blocked_threads, i );              //remove this thread O(1)
     268                        cond->count--;
     269                        if( !copy->lock ) {
     270                                #if !defined( __CFA_NO_STATISTICS__ )
     271                                        //kernelTLS.this_stats = copy->t->curr_cluster->stats;
     272                                #endif
     273                                unpark( copy->t );
     274                } else {
     275                        add_(*copy->lock, copy->t);                     // call lock's add_
     276                }
     277            }
     278            unlock( cond->lock );
     279        }
     280
     281        void alarm_node_wrap_cast( alarm_node_t & a ) {
     282                timeout_handler( (alarm_node_wrap(L) &)a );
     283        }
     284
     285        void ?{}( condition_variable(L) & this ){
    237286                this.lock{};
    238287                this.blocked_threads{};
    239288                this.count = 0;
    240                 this.reacquire_after_signal = reacquire_after_signal;
    241         }
    242 
    243         void ^?{}( synchronization_lock(L) & this ){
    244                 // default
    245         }
    246 
    247         void ?{}( condition_variable(L) & this ){
    248                 ((synchronization_lock(L) &)this){ true };
    249289        }
    250290
     
    253293        }
    254294
    255         void ?{}( thread_queue(L) & this ){
    256                 ((synchronization_lock(L) &)this){ false };
    257         }
    258 
    259         void ^?{}( thread_queue(L) & this ){
     295        void ?{}( alarm_node_wrap(L) & this, $thread * thrd, Time alarm, Duration period, Alarm_Callback callback ) {
     296                this.alarm_node{ thrd, alarm, period, callback };
     297        }
     298
     299        void ^?{}( alarm_node_wrap(L) & this ) {
    260300                // default
    261301        }
    262302
    263         bool notify_one( synchronization_lock(L) & this ) with( this ) {
     303        bool notify_one( condition_variable(L) & this ) with( this ) {
    264304                lock( lock __cfaabi_dbg_ctx2 );
    265305                bool ret = !!blocked_threads;
    266306                info_thread(L) * popped = pop_head( blocked_threads );
    267307                if(popped != 0p) {
    268                         if( reacquire_after_signal ){
     308                        popped->listed = false;
     309                        count--;
     310                        if (popped->lock) {
    269311                                add_(*popped->lock, popped->t);
    270312                        } else {
    271                                 unpark(
    272                                         popped->t __cfaabi_dbg_ctx2
    273                                 );
     313                                unpark(popped->t);
    274314                        }
    275315                }
     
    278318        }
    279319
    280         bool notify_all( synchronization_lock(L) & this ) with(this) {
     320        bool notify_all( condition_variable(L) & this ) with(this) {
    281321                lock( lock __cfaabi_dbg_ctx2 );
    282322                bool ret = blocked_threads ? true : false;
     
    284324                        info_thread(L) * popped = pop_head( blocked_threads );
    285325                        if(popped != 0p){
    286                                 if( reacquire_after_signal ){
     326                                popped->listed = false;
     327                                count--;
     328                                if (popped->lock) {
    287329                                        add_(*popped->lock, popped->t);
    288330                                } else {
    289                                         unpark(
    290                                                 popped->t __cfaabi_dbg_ctx2
    291                                         );
     331                                        unpark(popped->t);
    292332                                }
    293333                        }
     
    297337        }
    298338
    299         uintptr_t front( synchronization_lock(L) & this ) with(this) {
    300                 return (*peek(blocked_threads)).info;
    301         }
    302 
    303         bool empty( synchronization_lock(L) & this ) with(this) {
     339        uintptr_t front( condition_variable(L) & this ) with(this) {
     340                if(!blocked_threads) return NULL;
     341                return peek(blocked_threads)->info;
     342        }
     343
     344        bool empty( condition_variable(L) & this ) with(this) {
    304345                return blocked_threads ? false : true;
    305346        }
    306347
    307         int counter( synchronization_lock(L) & this ) with(this) {
     348        int counter( condition_variable(L) & this ) with(this) {
    308349                return count;
    309350        }
    310351
    311         void queue_info_thread( synchronization_lock(L) & this, info_thread(L) & i ) with(this) {
    312                 lock( lock __cfaabi_dbg_ctx2 );
    313                 append( blocked_threads, &i );
    314                 count++;
    315                 unlock( lock );
    316                 park( __cfaabi_dbg_ctx );
    317         }
    318 
    319 
    320         void wait( synchronization_lock(L) & this ) with(this) {
    321                 info_thread( L ) i = { active_thread() };
    322                 queue_info_thread( this, i );
    323         }
    324 
    325         void wait( synchronization_lock(L) & this, uintptr_t info ) with(this) {
    326                 info_thread( L ) i = { active_thread(), info };
    327                 queue_info_thread( this, i );
    328         }
    329         // I still need to implement the time delay wait routines
    330         bool wait( synchronization_lock(L) & this, Duration duration ) with(this) {
    331                 timeval tv = { time(0) };
    332                 Time t = { tv };
    333                 return wait( this, t + duration );
    334         }
    335 
    336         bool wait( synchronization_lock(L) & this, uintptr_t info, Duration duration ) with(this) {
    337                 // TODO: ADD INFO
    338                 return wait( this, duration );
    339         }
    340 
    341         bool wait( synchronization_lock(L) & this, Time time ) with(this) {
    342                 return false; //default
    343         }
    344 
    345         bool wait( synchronization_lock(L) & this, uintptr_t info, Time time ) with(this) {
    346                 // TODO: ADD INFO
    347                 return wait( this, time );
    348         }
    349 
    350         void queue_info_thread_unlock( synchronization_lock(L) & this, L & l, info_thread(L) & i ) with(this) {
     352        // helper for wait()'s' without a timeout
     353        void queue_info_thread( condition_variable(L) & this, info_thread(L) & i ) with(this) {
    351354                lock( lock __cfaabi_dbg_ctx2 );
    352355                append( this.blocked_threads, &i );
    353356                count++;
     357                i.listed = true;
     358                size_t recursion_count;
     359                if (i.lock) {
     360                        recursion_count = get_recursion_count(*i.lock);
     361                        remove_( *i.lock );
     362                }
     363               
     364                unlock( lock );
     365                park( ); // blocks here
     366
     367                if (i.lock) set_recursion_count(*i.lock, recursion_count); // resets recursion count here after waking
     368        }
     369
     370        // helper for wait()'s' with a timeout
     371        void queue_info_thread_timeout( condition_variable(L) & this, info_thread(L) & info, Time t ) with(this) {
     372                lock( lock __cfaabi_dbg_ctx2 );
     373
     374                info_thread(L) * queue_ptr = &info;
     375
     376                alarm_node_wrap(L) node_wrap = { info.t, t, 0`s, alarm_node_wrap_cast };
     377                node_wrap.cond = &this;
     378                node_wrap.i = &queue_ptr;
     379
     380                register_self( &node_wrap.alarm_node );
     381
     382                append( blocked_threads, queue_ptr );
     383                info.listed = true;
     384                count++;
     385
     386                size_t recursion_count;
     387                if (info.lock) {
     388                        recursion_count = get_recursion_count(*info.lock);
     389                        remove_( *info.lock );
     390                }
     391
     392                unlock( lock );
     393                park();
     394
     395                if (info.lock) set_recursion_count(*info.lock, recursion_count);
     396        }
     397
     398        void wait( condition_variable(L) & this ) with(this) {
     399                info_thread( L ) i = { active_thread() };
     400                queue_info_thread( this, i );
     401        }
     402
     403        void wait( condition_variable(L) & this, uintptr_t info ) with(this) {
     404                info_thread( L ) i = { active_thread(), info };
     405                queue_info_thread( this, i );
     406        }
     407       
     408        void wait( condition_variable(L) & this, Duration duration ) with(this) {
     409                info_thread( L ) i = { active_thread() };
     410                queue_info_thread_timeout(this, i, __kernel_get_time() + duration );
     411        }
     412
     413        void wait( condition_variable(L) & this, uintptr_t info, Duration duration ) with(this) {
     414                info_thread( L ) i = { active_thread(), info };
     415                queue_info_thread_timeout(this, i, __kernel_get_time() + duration );
     416        }
     417
     418        void wait( condition_variable(L) & this, Time time ) with(this) {
     419                info_thread( L ) i = { active_thread() };
     420                queue_info_thread_timeout(this, i, time);
     421        }
     422
     423        void wait( condition_variable(L) & this, uintptr_t info, Time time ) with(this) {
     424                info_thread( L ) i = { active_thread(), info };
     425                queue_info_thread_timeout(this, i, time);
     426        }
     427
     428        void wait( condition_variable(L) & this, L & l ) with(this) {
     429                info_thread(L) i = { active_thread() };
    354430                i.lock = &l;
    355                 size_t recursion_count = get_recursion_count(l);
    356                 remove_( l );
    357                 unlock( lock );
    358                 park( __cfaabi_dbg_ctx ); // blocks here
    359 
    360                 set_recursion_count(l, recursion_count); // resets recursion count here after waking
    361         }
    362 
    363         void wait( synchronization_lock(L) & this, L & l ) with(this) {
     431                queue_info_thread( this, i );
     432        }
     433
     434        void wait( condition_variable(L) & this, L & l, uintptr_t info ) with(this) {
     435                info_thread(L) i = { active_thread(), info };
     436                i.lock = &l;
     437                queue_info_thread( this, i );
     438        }
     439       
     440        void wait( condition_variable(L) & this, L & l, Duration duration ) with(this) {
    364441                info_thread(L) i = { active_thread() };
    365                 queue_info_thread_unlock( this, l, i );
    366         }
    367 
    368         void wait( synchronization_lock(L) & this, L & l, uintptr_t info ) with(this) {
     442                i.lock = &l;
     443                queue_info_thread_timeout(this, i, __kernel_get_time() + duration );
     444        }
     445       
     446        void wait( condition_variable(L) & this, L & l, uintptr_t info, Duration duration ) with(this) {
    369447                info_thread(L) i = { active_thread(), info };
    370                 queue_info_thread_unlock( this, l, i );
    371         }
    372 
    373         bool wait( synchronization_lock(L) & this, L & l, Duration duration ) with(this) {
    374                 timeval tv = { time(0) };
    375                 Time t = { tv };
    376                 return wait( this, l, t + duration );
    377         }
    378 
    379         bool wait( synchronization_lock(L) & this, L & l, uintptr_t info, Duration duration ) with(this) {
    380                 // TODO: ADD INFO
    381                 return wait( this, l, duration );
    382         }
    383 
    384         bool wait( synchronization_lock(L) & this, L & l, Time time ) with(this) {
    385                 return false; //default
    386         }
    387 
    388         bool wait( synchronization_lock(L) & this, L & l, uintptr_t info, Time time ) with(this) {
    389                 // TODO: ADD INFO
    390                 return wait( this, l, time );
    391         }
    392 }
    393 
    394 ///////////////////////////////////////////////////////////////////
    395 //// condition lock alternative approach
    396 ///////////////////////////////////////////////////////////////////
    397 
    398 // the solution below is less efficient but does not require the lock to have a specific add/remove routine
    399 
    400 ///////////////////////////////////////////////////////////////////
    401 //// is_simple_lock
    402 ///////////////////////////////////////////////////////////////////
    403 
    404 forall(dtype L | is_simple_lock(L)) {
    405         void ?{}( condition_lock(L) & this ){
    406                 // default
    407         }
    408 
    409         void ^?{}( condition_lock(L) & this ){
    410                 // default
    411         }
    412 
    413         bool notify_one( condition_lock(L) & this ) with(this) {
    414                 return notify_one( c_var );
    415         }
    416 
    417         bool notify_all( condition_lock(L) & this ) with(this) {
    418                 return notify_all( c_var );
    419         }
    420 
    421         void wait( condition_lock(L) & this, L & l ) with(this) {
    422                 lock( m_lock );
    423                 size_t recursion = get_recursion_count( l );
    424                 unlock( l );
    425                 wait( c_var, m_lock );
    426                 lock( l );
    427                 set_recursion_count( l , recursion );
    428                 unlock( m_lock );
    429         }
    430 }
     448                i.lock = &l;
     449                queue_info_thread_timeout(this, i, __kernel_get_time() + duration );
     450        }
     451       
     452        void wait( condition_variable(L) & this, L & l, Time time ) with(this) {
     453                info_thread(L) i = { active_thread() };
     454                i.lock = &l;
     455                queue_info_thread_timeout(this, i, time );
     456        }
     457       
     458        void wait( condition_variable(L) & this, L & l, uintptr_t info, Time time ) with(this) {
     459                info_thread(L) i = { active_thread(), info };
     460                i.lock = &l;
     461                queue_info_thread_timeout(this, i, time );
     462        }
     463}
     464
     465// thread T1 {};
     466// thread T2 {};
     467
     468// multiple_acquisition_lock m;
     469// condition_variable( multiple_acquisition_lock ) c;
     470
     471// void main( T1 & this ) {
     472//      printf("T1 start\n");
     473//      lock(m);
     474//      printf("%d\n", counter(c));
     475//      if(empty(c)) {
     476//              printf("T1 wait\n");
     477//              wait(c,m,12);
     478//      }else{
     479//              printf("%d\n", front(c));
     480//              notify_one(c);
     481//      }
     482//      unlock(m);
     483//      printf("curr thd in main %p \n", active_thread());
     484//      printf("T1 waits for 2s\n");
     485//      lock(m);
     486//      wait( c, m, 2`s );
     487//      unlock(m);
     488//      printf("T1 wakes\n");
     489//      printf("T1 done\n");
     490// }
     491
     492// void main( T2 & this ) {
     493//      printf("T2 start\n");
     494//      lock(m);
     495//      printf("%d\n", counter(c));
     496//      if(empty(c)) {
     497//              printf("T2 wait\n");
     498//              wait(c,m,12);
     499//      }else{
     500//              printf("%d\n", front(c));
     501//              notify_one(c);
     502//      }
     503//      unlock(m);
     504//      printf("T2 done\n");
     505// }
     506
     507// int main() {
     508//      printf("start\n");
     509//      processor p[2];
     510//      {
     511//              T1 t1;
     512//              T2 t2;
     513//      }
     514//      printf("done\n");
     515// }
Note: See TracChangeset for help on using the changeset viewer.