Changeset 797a193 for libcfa/src/concurrency/locks.cfa
- Timestamp:
- Dec 22, 2020, 12:50:46 PM (2 years ago)
- Branches:
- arm-eh, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 26a249c, 302ef2a
- Parents:
- fe97de26
- File:
-
- 1 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
Note: See TracChangeset
for help on using the changeset viewer.