Ignore:
File:
1 edited

Legend:

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

    r6a8882c rbe73f30  
    1515                this.t = t;
    1616                this.lock = 0p;
    17                 this.listed = false;
    1817        }
    1918
     
    2221                this.info = info;
    2322                this.lock = 0p;
    24                 this.listed = false;
    2523        }
    2624
     
    5149}
    5250
    53 void ?{}( single_acquisition_lock & this ) {
     51void ?{}( mutex_lock & this ) {
    5452        ((blocking_lock &)this){ false, false };
    5553}
    5654
    57 void ^?{}( single_acquisition_lock & this ) {
     55void ^?{}( mutex_lock & this ) {
    5856        // default
    5957}
     
    6765}
    6866
    69 void ?{}( multiple_acquisition_lock & this ) {
     67void ?{}( recursive_mutex_lock & this ) {
    7068        ((blocking_lock &)this){ true, false };
    7169}
    7270
    73 void ^?{}( multiple_acquisition_lock & this ) {
     71void ^?{}( recursive_mutex_lock & this ) {
    7472        // default
    7573}
    7674
    7775void lock( blocking_lock & this ) with( this ) {
     76        $thread * thrd = active_thread();
    7877        lock( lock __cfaabi_dbg_ctx2 );
    79         if ( owner == active_thread() && !multi_acquisition) {
     78        if ( owner == thrd && !multi_acquisition) {
    8079                fprintf(stderr, "A single acquisition lock holder attempted to reacquire the lock resulting in a deadlock."); // Possibly throw instead
    81         exit(EXIT_FAILURE);
    82         } else if ( owner != 0p && owner != active_thread() ) {
    83                 append( blocked_threads, active_thread() );
     80                exit(EXIT_FAILURE);
     81        } else if ( owner != 0p && owner != thrd ) {
     82                append( blocked_threads, thrd );
    8483                wait_count++;
    8584                unlock( lock );
    86                 park( );
    87         } else if ( owner == active_thread() && multi_acquisition ) {
     85                park( __cfaabi_dbg_ctx );
     86        } else if ( owner == thrd && multi_acquisition ) {
    8887                recursion_count++;
    8988                unlock( lock );
    9089        } else {
    91                 owner = active_thread();
     90                owner = thrd;
    9291                recursion_count = 1;
    9392                unlock( lock );
     
    9695
    9796bool 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 = active_thread();
    102                 recursion_count = 1;
     101                owner = thrd;
     102                if ( multi_acquisition ) recursion_count = 1;
    103103                ret = true;
    104         } else if ( owner == active_thread() && multi_acquisition ) {
     104        } else if ( owner == thrd && 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 ? 1 : 0 );
     125                recursion_count = ( thrd && multi_acquisition ? 1 : 0 );
    126126                wait_count--;
    127                 unpark( thrd );
     127                unpark( thrd __cfaabi_dbg_ctx2 );
    128128        }
    129129        unlock( lock );
     
    151151        } else {
    152152                owner = t;
    153                 recursion_count = 1;
    154                 #if !defined( __CFA_NO_STATISTICS__ )
    155                         //kernelTLS.this_stats = t->curr_cluster->stats;
    156                 #endif
    157                 unpark( t );
     153                if ( multi_acquisition ) recursion_count = 1;
     154                unpark( t __cfaabi_dbg_ctx2 );
    158155                unlock( lock );
    159156        }
     
    163160    lock( lock __cfaabi_dbg_ctx2 );
    164161        if ( owner == 0p ){ // no owner implies lock isn't held
    165                 fprintf( stderr, "A lock that is not held was passed to a synchronization lock" ); 
     162                fprintf( stderr, "A lock that is not held was passed to a synchronization lock" );
    166163        } else if ( strict_owner && owner != active_thread() ) {
    167                 fprintf( stderr, "A thread other than the owner of a lock passed it to a synchronization lock" ); 
     164                fprintf( stderr, "A thread other than the owner of a lock passed it to a synchronization lock" );
    168165        } else {
    169166                $thread * thrd = pop_head( blocked_threads );
    170167                owner = thrd;
    171                 recursion_count = ( thrd ? 1 : 0 );
     168                recursion_count = ( thrd && multi_acquisition ? 1 : 0 );
    172169                wait_count--;
    173                 unpark( thrd );
     170                unpark( thrd __cfaabi_dbg_ctx2 );
    174171        }
    175172        unlock( lock );
     
    180177///////////////////////////////////////////////////////////////////
    181178
    182 // This is temporary until an inheritance bug is fixed
    183 
    184 void lock( single_acquisition_lock & this ){
     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
     183void lock( mutex_lock & this ){
    185184        lock( (blocking_lock &)this );
    186185}
    187186
    188 void unlock( single_acquisition_lock & this ){
     187void unlock( mutex_lock & this ){
    189188        unlock( (blocking_lock &)this );
    190189}
    191190
    192 void add_( single_acquisition_lock & this, struct $thread * t ){
     191void add_( mutex_lock & this, struct $thread * t ){
    193192        add_( (blocking_lock &)this, t );
    194193}
    195194
    196 void remove_( single_acquisition_lock & this ){
     195void remove_( mutex_lock & this ){
    197196        remove_( (blocking_lock &)this );
    198197}
    199198
    200 void set_recursion_count( single_acquisition_lock & this, size_t recursion ){
     199void set_recursion_count( mutex_lock & this, size_t recursion ){
    201200        set_recursion_count( (blocking_lock &)this, recursion );
    202201}
    203202
    204 size_t get_recursion_count( single_acquisition_lock & this ){
    205         return get_recursion_count( (blocking_lock &)this );
    206 }
    207 
    208 void lock( owner_lock & this ){
     203size_t get_recursion_count( mutex_lock & this ){
     204        get_recursion_count( (blocking_lock &)this );
     205}
     206
     207void lock( recursive_mutex_lock & this ){
    209208        lock( (blocking_lock &)this );
    210209}
    211210
    212 void unlock( owner_lock & this ){
     211void unlock( recursive_mutex_lock & this ){
    213212        unlock( (blocking_lock &)this );
    214213}
    215214
    216 void add_( owner_lock & this, struct $thread * t ){
     215void add_( recursive_mutex_lock & this, struct $thread * t ){
    217216        add_( (blocking_lock &)this, t );
    218217}
    219218
    220 void remove_( owner_lock & this ){
     219void remove_( recursive_mutex_lock & this ){
    221220        remove_( (blocking_lock &)this );
    222221}
    223222
    224 void set_recursion_count( owner_lock & this, size_t recursion ){
     223void set_recursion_count( recursive_mutex_lock & this, size_t recursion ){
    225224        set_recursion_count( (blocking_lock &)this, recursion );
    226225}
    227226
    228 size_t get_recursion_count( owner_lock & this ){
    229         return get_recursion_count( (blocking_lock &)this );
    230 }
    231 
    232 void lock( multiple_acquisition_lock & this ){
    233         lock( (blocking_lock &)this );
    234 }
    235 
    236 void unlock( multiple_acquisition_lock & this ){
    237         unlock( (blocking_lock &)this );
    238 }
    239 
    240 void add_( multiple_acquisition_lock & this, struct $thread * t ){
    241         add_( (blocking_lock &)this, t );
    242 }
    243 
    244 void remove_( multiple_acquisition_lock & this ){
    245         remove_( (blocking_lock &)this );
    246 }
    247 
    248 void set_recursion_count( multiple_acquisition_lock & this, size_t recursion ){
    249         set_recursion_count( (blocking_lock &)this, recursion );
    250 }
    251 
    252 size_t get_recursion_count( multiple_acquisition_lock & this ){
    253         return get_recursion_count( (blocking_lock &)this );
    254 }
    255 
    256 ///////////////////////////////////////////////////////////////////
    257 //// condition variable
     227size_t get_recursion_count( recursive_mutex_lock & this ){
     228        get_recursion_count( (blocking_lock &)this );
     229}
     230
     231///////////////////////////////////////////////////////////////////
     232//// Synchronization Locks
    258233///////////////////////////////////////////////////////////////////
    259234
    260235forall(dtype L | is_blocking_lock(L)) {
    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 ){
     236        void ?{}( synchronization_lock(L) & this, bool reacquire_after_signal ){
    286237                this.lock{};
    287238                this.blocked_threads{};
    288239                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 };
    289249        }
    290250
     
    293253        }
    294254
    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 ) {
    300                 // default
    301         }
    302 
    303         bool notify_one( condition_variable(L) & this ) with( this ) {
     255        void ?{}( thread_queue(L) & this ){
     256                ((synchronization_lock(L) &)this){ false };
     257        }
     258
     259        void ^?{}( thread_queue(L) & this ){
     260                // default
     261        }
     262
     263        bool notify_one( synchronization_lock(L) & this ) with( this ) {
    304264                lock( lock __cfaabi_dbg_ctx2 );
    305265                bool ret = !!blocked_threads;
    306266                info_thread(L) * popped = pop_head( blocked_threads );
    307267                if(popped != 0p) {
    308                         popped->listed = false;
    309                         count--;
    310                         if (popped->lock) {
     268                        if( reacquire_after_signal ){
    311269                                add_(*popped->lock, popped->t);
    312270                        } else {
    313                                 unpark(popped->t);
     271                                unpark(
     272                                        popped->t __cfaabi_dbg_ctx2
     273                                );
    314274                        }
    315275                }
     
    318278        }
    319279
    320         bool notify_all( condition_variable(L) & this ) with(this) {
     280        bool notify_all( synchronization_lock(L) & this ) with(this) {
    321281                lock( lock __cfaabi_dbg_ctx2 );
    322282                bool ret = blocked_threads ? true : false;
     
    324284                        info_thread(L) * popped = pop_head( blocked_threads );
    325285                        if(popped != 0p){
    326                                 popped->listed = false;
    327                                 count--;
    328                                 if (popped->lock) {
     286                                if( reacquire_after_signal ){
    329287                                        add_(*popped->lock, popped->t);
    330288                                } else {
    331                                         unpark(popped->t);
     289                                        unpark(
     290                                                popped->t __cfaabi_dbg_ctx2
     291                                        );
    332292                                }
    333293                        }
     
    337297        }
    338298
    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) {
     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) {
    345304                return blocked_threads ? false : true;
    346305        }
    347306
    348         int counter( condition_variable(L) & this ) with(this) {
     307        int counter( synchronization_lock(L) & this ) with(this) {
    349308                return count;
    350309        }
    351310
    352         // helper for wait()'s' without a timeout
    353         void queue_info_thread( condition_variable(L) & this, info_thread(L) & i ) with(this) {
     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) {
    354351                lock( lock __cfaabi_dbg_ctx2 );
    355352                append( this.blocked_threads, &i );
    356353                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) {
     354                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) {
    429364                info_thread(L) i = { active_thread() };
    430                 i.lock = &l;
    431                 queue_info_thread( this, i );
    432         }
    433 
    434         void wait( condition_variable(L) & this, L & l, uintptr_t info ) with(this) {
     365                queue_info_thread_unlock( this, l, i );
     366        }
     367
     368        void wait( synchronization_lock(L) & this, L & l, uintptr_t info ) with(this) {
    435369                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) {
    441                 info_thread(L) i = { active_thread() };
    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) {
    447                 info_thread(L) i = { active_thread(), info };
    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 // }
     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
     404forall(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}
Note: See TracChangeset for help on using the changeset viewer.