Changeset 797a193
- Timestamp:
- Dec 22, 2020, 12:50:46 PM (4 years ago)
- 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
- Location:
- libcfa/src/concurrency
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/locks.cfa
rfe97de26 r797a193 1 1 #include "locks.hfa" 2 2 #include "kernel_private.hfa" 3 #include <stdlib.h>4 #include <stdio.h>5 3 6 4 #include <kernel.hfa> 7 5 #include <stdlib.hfa> 8 #include <thread.hfa>9 6 10 7 /////////////////////////////////////////////////////////////////// … … 61 58 void lock( blocking_lock & this ) with( this ) { 62 59 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 64 61 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 66 63 addTail( blocked_threads, *active_thread() ); 67 64 wait_count++; 68 65 unlock( lock ); 69 66 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 71 68 recursion_count++; 72 69 unlock( lock ); 73 } else { 70 } else { // lock isn't held 74 71 owner = active_thread(); 75 72 recursion_count = 1; … … 81 78 bool ret = false; 82 79 lock( lock __cfaabi_dbg_ctx2 ); 83 if ( owner == 0p ) { 80 if ( owner == 0p ) { // lock isn't held 84 81 owner = active_thread(); 85 82 recursion_count = 1; 86 83 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 88 85 recursion_count++; 89 86 ret = true; … … 94 91 95 92 void unlock_error_check( blocking_lock & this ) with( this ) { 96 if ( owner == 0p ){ // no owner implieslock isn't held93 if ( owner == 0p ){ // lock isn't held 97 94 abort( "There was an attempt to release a lock that isn't held" ); 98 95 } else if ( strict_owner && owner != active_thread() ) { … … 113 110 unlock_error_check( this ); 114 111 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 116 113 pop_and_set_new_owner( this ); 117 114 } … … 131 128 } 132 129 133 void add_( blocking_lock & this, $thread * t ) with( this ) {130 void on_notify( blocking_lock & this, $thread * t ) with( this ) { 134 131 lock( lock __cfaabi_dbg_ctx2 ); 135 if ( owner != 0p ) { 132 if ( owner != 0p ) { // lock held 136 133 addTail( blocked_threads, *t ); 137 134 wait_count++; 138 135 unlock( lock ); 139 } else { 136 } else { // lock not held 140 137 owner = t; 141 138 recursion_count = 1; … … 145 142 } 146 143 147 void remove_( blocking_lock & this ) with( this ) {144 void on_wait( blocking_lock & this ) with( this ) { 148 145 lock( lock __cfaabi_dbg_ctx2 ); 149 146 unlock_error_check( this ); … … 156 153 /////////////////////////////////////////////////////////////////// 157 154 158 // Th is istemporary until an inheritance bug is fixed155 // These routines are temporary until an inheritance bug is fixed 159 156 160 157 void lock( single_acquisition_lock & this ){ lock( (blocking_lock &)this ); } 161 158 void 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 ); }159 void on_notify( single_acquisition_lock & this, struct $thread * t ){ on_notify( (blocking_lock &)this, t ); } 160 void on_wait( single_acquisition_lock & this ){ on_wait( (blocking_lock &)this ); } 164 161 void set_recursion_count( single_acquisition_lock & this, size_t recursion ){ set_recursion_count( (blocking_lock &)this, recursion ); } 165 162 size_t get_recursion_count( single_acquisition_lock & this ){ return get_recursion_count( (blocking_lock &)this ); } … … 167 164 void lock( owner_lock & this ){ lock( (blocking_lock &)this ); } 168 165 void 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 ); }166 void on_notify( owner_lock & this, struct $thread * t ){ on_notify( (blocking_lock &)this, t ); } 167 void on_wait( owner_lock & this ){ on_wait( (blocking_lock &)this ); } 171 168 void set_recursion_count( owner_lock & this, size_t recursion ){ set_recursion_count( (blocking_lock &)this, recursion ); } 172 169 size_t get_recursion_count( owner_lock & this ){ return get_recursion_count( (blocking_lock &)this ); } … … 174 171 void lock( multiple_acquisition_lock & this ){ lock( (blocking_lock &)this ); } 175 172 void 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 ); }173 void on_notify( multiple_acquisition_lock & this, struct $thread * t ){ on_notify( (blocking_lock &)this, t ); } 174 void on_wait( multiple_acquisition_lock & this ){ on_wait( (blocking_lock &)this ); } 178 175 void set_recursion_count( multiple_acquisition_lock & this, size_t recursion ){ set_recursion_count( (blocking_lock &)this, recursion ); } 179 176 size_t get_recursion_count( multiple_acquisition_lock & this ){ return get_recursion_count( (blocking_lock &)this ); } … … 188 185 // This condition_variable member is called from the kernel, and therefore, cannot block, but it can spin. 189 186 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 191 192 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) 194 194 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 197 197 } else { 198 add_(*i->lock, i->t); // call lock's add_198 unpark( i->t ); // otherwise wake thread 199 199 } 200 200 } … … 202 202 } 203 203 204 // this casts the alarm node to our wrapped type since we used type erasure 204 205 void alarm_node_wrap_cast( alarm_node_t & a ) { timeout_handler( (alarm_node_wrap(L) &)a ); } 205 206 … … 208 209 this.blocked_threads{}; 209 210 this.count = 0; 210 this.last_thread = 0p; // REMOVE AFTER DEBUG211 211 } 212 212 … … 224 224 count--; 225 225 if (popped.lock) { 226 add_(*popped.lock, popped.t);226 on_notify(*popped.lock, popped.t); // if lock passed call on_notify 227 227 } else { 228 unpark(popped.t); 228 unpark(popped.t); // otherwise wake thread 229 229 } 230 230 } … … 258 258 259 259 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 261 261 count++; 262 262 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 264 264 recursion_count = get_recursion_count(*i->lock); 265 remove_( *i->lock );265 on_wait( *i->lock ); 266 266 } 267 267 return recursion_count; … … 287 287 unlock( lock ); 288 288 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 291 291 } 292 292 -
libcfa/src/concurrency/locks.hfa
rfe97de26 r797a193 6 6 #include "bits/locks.hfa" 7 7 #include "bits/sequence.hfa" 8 #include "bits/containers.hfa"9 8 10 9 #include "invoke.h" … … 20 19 21 20 trait is_blocking_lock(dtype L | sized(L)) { 22 void add_( L &, struct $thread * );// For synchronization locks to use when acquiring23 void remove_( L & );// For synchronization locks to use when releasing24 size_t get_recursion_count( L & ); // to get recursion count for cond lock to reset after waking25 void set_recursion_count( L &, size_t recursion ); 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; 26 25 }; 27 26 … … 30 29 /////////////////////////////////////////////////////////////////// 31 30 31 // the info thread is a wrapper around a thread used 32 // to store extra data for use in the condition variable 32 33 forall(dtype L | is_blocking_lock(L)) { 33 34 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) 38 39 bool signalled; // true when signalled and false when timeout wakes thread 39 40 }; … … 44 45 void ^?{}( info_thread(L) & this ); 45 46 47 // for use by sequence 46 48 info_thread(L) *& Back( info_thread(L) * this ); 47 49 info_thread(L) *& Next( info_thread(L) * this ); … … 102 104 bool try_lock( blocking_lock & this ); 103 105 void unlock( blocking_lock & this ); 104 void add_( blocking_lock & this, struct $thread * t );105 void remove_( blocking_lock & this );106 void on_notify( blocking_lock & this, struct $thread * t ); 107 void on_wait( blocking_lock & this ); 106 108 size_t wait_count( blocking_lock & this ); 107 109 void set_recursion_count( blocking_lock & this, size_t recursion ); … … 110 112 void lock( single_acquisition_lock & this ); 111 113 void unlock( single_acquisition_lock & this ); 112 void add_( single_acquisition_lock & this, struct $thread * t );113 void remove_( single_acquisition_lock & this );114 void on_notify( single_acquisition_lock & this, struct $thread * t ); 115 void on_wait( single_acquisition_lock & this ); 114 116 void set_recursion_count( single_acquisition_lock & this, size_t recursion ); 115 117 size_t get_recursion_count( single_acquisition_lock & this ); … … 117 119 void lock( owner_lock & this ); 118 120 void unlock( owner_lock & this ); 119 void add_( owner_lock & this, struct $thread * t );120 void remove_( owner_lock & this );121 void on_notify( owner_lock & this, struct $thread * t ); 122 void on_wait( owner_lock & this ); 121 123 void set_recursion_count( owner_lock & this, size_t recursion ); 122 124 size_t get_recursion_count( owner_lock & this ); … … 124 126 void lock( multiple_acquisition_lock & this ); 125 127 void unlock( multiple_acquisition_lock & this ); 126 void add_( multiple_acquisition_lock & this, struct $thread * t );127 void remove_( multiple_acquisition_lock & this );128 void on_notify( multiple_acquisition_lock & this, struct $thread * t ); 129 void on_wait( multiple_acquisition_lock & this ); 128 130 void set_recursion_count( multiple_acquisition_lock & this, size_t recursion ); 129 131 size_t get_recursion_count( multiple_acquisition_lock & this ); … … 136 138 // Spin lock used for mutual exclusion 137 139 __spinlock_t lock; 138 139 info_thread(L) * last_thread;140 140 141 141 // List of blocked threads
Note: See TracChangeset
for help on using the changeset viewer.