Changes in / [ca33b15:c60ef639]
- Files:
-
- 4 added
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/bits/weakso_locks.cfa
rca33b15 rc60ef639 18 18 #include "bits/weakso_locks.hfa" 19 19 20 void ?{}( blocking_lock & this, bool multi_acquisition, bool strict_owner) {}21 void ^?{}( blocking_lock & this) {}20 void ?{}( blocking_lock &, bool, bool ) {} 21 void ^?{}( blocking_lock & ) {} 22 22 23 void lock( blocking_lock & this ) {} 24 bool try_lock( blocking_lock & this ) { return false; } 25 void unlock( blocking_lock & this ) {} 26 void on_notify( blocking_lock & this, struct $thread * t ) {} 27 void on_wait( blocking_lock & this ) {} 28 size_t wait_count( blocking_lock & this ) { return 0; } 29 void set_recursion_count( blocking_lock & this, size_t recursion ) {} 30 size_t get_recursion_count( blocking_lock & this ) { return 0; } 23 void lock( blocking_lock & ) {} 24 bool try_lock( blocking_lock & ) { return false; } 25 void unlock( blocking_lock & ) {} 26 void on_notify( blocking_lock &, struct $thread * ) {} 27 size_t on_wait( blocking_lock & ) {} 28 void on_wakeup( blocking_lock &, size_t ) {} 29 size_t wait_count( blocking_lock & ) { return 0; } -
libcfa/src/bits/weakso_locks.hfa
rca33b15 rc60ef639 56 56 void unlock( blocking_lock & this ) OPTIONAL_THREAD; 57 57 void on_notify( blocking_lock & this, struct $thread * t ) OPTIONAL_THREAD; 58 void on_wait( blocking_lock & this ) OPTIONAL_THREAD; 58 size_t on_wait( blocking_lock & this ) OPTIONAL_THREAD; 59 void on_wakeup( blocking_lock & this, size_t ) OPTIONAL_THREAD; 59 60 size_t wait_count( blocking_lock & this ) OPTIONAL_THREAD; 60 void set_recursion_count( blocking_lock & this, size_t recursion ) OPTIONAL_THREAD;61 size_t get_recursion_count( blocking_lock & this ) OPTIONAL_THREAD;62 61 63 62 //---------- … … 72 71 static inline bool try_lock ( multiple_acquisition_lock & this ) { return try_lock( (blocking_lock &)this ); } 73 72 static inline void unlock ( multiple_acquisition_lock & this ) { unlock ( (blocking_lock &)this ); } 74 static inline void on_wait ( multiple_acquisition_lock & this ) { on_wait ( (blocking_lock &)this ); } 73 static inline size_t on_wait ( multiple_acquisition_lock & this ) { return on_wait ( (blocking_lock &)this ); } 74 static inline void on_wakeup( multiple_acquisition_lock & this, size_t v ) { on_wakeup ( (blocking_lock &)this, v ); } 75 75 static inline void on_notify( multiple_acquisition_lock & this, struct $thread * t ){ on_notify( (blocking_lock &)this, t ); } 76 static inline void set_recursion_count( multiple_acquisition_lock & this, size_t recursion ){ set_recursion_count( (blocking_lock &)this, recursion ); }77 static inline size_t get_recursion_count( multiple_acquisition_lock & this ){ return get_recursion_count( (blocking_lock &)this ); } -
libcfa/src/concurrency/locks.cfa
rca33b15 rc60ef639 134 134 lock( lock __cfaabi_dbg_ctx2 ); 135 135 /* paranoid */ verifyf( owner != 0p, "Attempt to release lock %p that isn't held", &this ); 136 /* paranoid */ verifyf( owner == active_thread() || !strict_owner, "Thread %p other than the owner %p attempted to release owner lock %p", owner, active_thread(), &this ); 136 /* paranoid */ verifyf( owner == active_thread() || !strict_owner , "Thread %p other than the owner %p attempted to release owner lock %p", owner, active_thread(), &this ); 137 /* paranoid */ verifyf( recursion_count == 1 || multi_acquisition, "Thread %p attempted to release owner lock %p which is not recursive but has a recursive count of %zu", active_thread(), &this, recursion_count ); 137 138 138 139 // if recursion count is zero release lock and set new owner if one is waiting … … 146 147 size_t wait_count( blocking_lock & this ) with( this ) { 147 148 return wait_count; 148 }149 150 void set_recursion_count( blocking_lock & this, size_t recursion ) with( this ) {151 recursion_count = recursion;152 }153 154 size_t get_recursion_count( blocking_lock & this ) with( this ) {155 return recursion_count;156 149 } 157 150 … … 173 166 } 174 167 175 voidon_wait( blocking_lock & this ) with( this ) {168 size_t on_wait( blocking_lock & this ) with( this ) { 176 169 lock( lock __cfaabi_dbg_ctx2 ); 177 170 /* paranoid */ verifyf( owner != 0p, "Attempt to release lock %p that isn't held", &this ); 178 171 /* paranoid */ verifyf( owner == active_thread() || !strict_owner, "Thread %p other than the owner %p attempted to release owner lock %p", owner, active_thread(), &this ); 179 172 173 size_t ret = recursion_count; 174 180 175 pop_and_set_new_owner( this ); 181 176 unlock( lock ); 177 return ret; 178 } 179 180 void on_wakeup( blocking_lock & this, size_t recursion ) with( this ) { 181 recursion_count = recursion; 182 182 } 183 183 … … 274 274 } 275 275 276 bool empty( condition_variable(L) & this ) with(this) { return empty(blocked_threads); } 276 bool empty( condition_variable(L) & this ) with(this) { 277 lock( lock __cfaabi_dbg_ctx2 ); 278 bool ret = empty(blocked_threads); 279 unlock( lock ); 280 return ret; 281 } 277 282 278 283 int counter( condition_variable(L) & this ) with(this) { return count; } … … 285 290 if (i->lock) { 286 291 // if lock was passed get recursion count to reset to after waking thread 287 recursion_count = get_recursion_count(*i->lock); 288 on_wait( *i->lock ); 292 recursion_count = on_wait( *i->lock ); 289 293 } 290 294 return recursion_count; … … 301 305 302 306 // resets recursion count here after waking 303 if (i.lock) set_recursion_count(*i.lock, recursion_count);307 if (i.lock) on_wakeup(*i.lock, recursion_count); 304 308 } 305 309 … … 323 327 324 328 // resets recursion count here after waking 325 if (info.lock) set_recursion_count(*info.lock, recursion_count);329 if (info.lock) on_wakeup(*info.lock, recursion_count); 326 330 } 327 331 … … 373 377 } 374 378 375 bool V(semaphore & this) with( this ) {379 $thread * V (semaphore & this, const bool doUnpark ) with( this ) { 376 380 $thread * thrd = 0p; 377 381 lock( lock __cfaabi_dbg_ctx2 ); … … 385 389 386 390 // make new owner 387 unpark( thrd ); 388 391 if( doUnpark ) unpark( thrd ); 392 393 return thrd; 394 } 395 396 bool V(semaphore & this) with( this ) { 397 $thread * thrd = V(this, true); 389 398 return thrd != 0p; 390 399 } -
libcfa/src/concurrency/locks.hfa
rca33b15 rc60ef639 39 39 }; 40 40 41 static inline bool P(Semaphore0nary & this, $thread * thrd) __attribute__((artificial));42 41 static inline bool P(Semaphore0nary & this, $thread * thrd) { 43 42 /* paranoid */ verify(!(thrd->seqable.next)); … … 48 47 } 49 48 50 static inline bool P(Semaphore0nary & this) __attribute__((artificial));51 49 static inline bool P(Semaphore0nary & this) { 52 50 $thread * thrd = active_thread(); … … 56 54 } 57 55 58 static inline $thread * V(Semaphore0nary & this, const bool doUnpark = true) __attribute__((artificial));59 56 static inline $thread * V(Semaphore0nary & this, const bool doUnpark = true) { 60 57 $thread * next; … … 82 79 83 80 // returns true if no blocking needed 84 bool P(BinaryBenaphore & this) { return __atomic_fetch_sub(&this.counter, 1, __ATOMIC_SEQ_CST) > 0; } 81 bool P(BinaryBenaphore & this) { 82 return __atomic_fetch_sub(&this.counter, 1, __ATOMIC_SEQ_CST) > 0; 83 } 84 85 85 bool tryP(BinaryBenaphore & this) { 86 86 ssize_t c = this.counter; … … 115 115 static inline void ?{}(ThreadBenaphore & this, one_t ) { (this.ben){ 1 }; } 116 116 117 static inline bool P(ThreadBenaphore & this) { return /* P(this.ben) ? false : */ P(this.sem); } 118 static inline bool P(ThreadBenaphore & this, $thread * t) { return /* P(this.ben) ? false : */ P(this.sem, t ); } 117 static inline bool P(ThreadBenaphore & this) { return P(this.ben) ? false : P(this.sem); } 119 118 static inline bool tryP(ThreadBenaphore & this) { return tryP(this.ben); } 120 119 static inline bool P(ThreadBenaphore & this, bool wait) { return wait ? P(this) : tryP(this); } 121 120 122 121 static inline $thread * V(ThreadBenaphore & this, const bool doUnpark = true) { 123 //if (V(this.ben)) return 0p;122 if (V(this.ben)) return 0p; 124 123 return V(this.sem, doUnpark); 125 124 } … … 138 137 bool V (semaphore & this); 139 138 bool V (semaphore & this, unsigned count); 139 $thread * V (semaphore & this, bool ); 140 140 141 141 //---------- … … 146 146 static inline void ?{}( single_acquisition_lock & this ) {((blocking_lock &)this){ false, false };} 147 147 static inline void ^?{}( single_acquisition_lock & this ) {} 148 static inline void lock ( single_acquisition_lock & this ) { lock ( (blocking_lock &)this ); } 149 static inline bool try_lock ( single_acquisition_lock & this ) { return try_lock( (blocking_lock &)this ); } 150 static inline void unlock ( single_acquisition_lock & this ) { unlock ( (blocking_lock &)this ); } 151 static inline void on_wait ( single_acquisition_lock & this ) { on_wait ( (blocking_lock &)this ); } 152 static inline void on_notify ( single_acquisition_lock & this, struct $thread * t ) { on_notify( (blocking_lock &)this, t ); } 153 static inline void set_recursion_count( single_acquisition_lock & this, size_t recursion ) { set_recursion_count( (blocking_lock &)this, recursion ); } 154 static inline size_t get_recursion_count( single_acquisition_lock & this ) { return get_recursion_count( (blocking_lock &)this ); } 148 static inline void lock ( single_acquisition_lock & this ) { lock ( (blocking_lock &)this ); } 149 static inline bool try_lock ( single_acquisition_lock & this ) { return try_lock( (blocking_lock &)this ); } 150 static inline void unlock ( single_acquisition_lock & this ) { unlock ( (blocking_lock &)this ); } 151 static inline size_t on_wait ( single_acquisition_lock & this ) { return on_wait ( (blocking_lock &)this ); } 152 static inline void on_wakeup( single_acquisition_lock & this, size_t v ) { on_wakeup ( (blocking_lock &)this, v ); } 153 static inline void on_notify( single_acquisition_lock & this, struct $thread * t ) { on_notify( (blocking_lock &)this, t ); } 155 154 156 155 //---------- … … 164 163 static inline bool try_lock ( owner_lock & this ) { return try_lock( (blocking_lock &)this ); } 165 164 static inline void unlock ( owner_lock & this ) { unlock ( (blocking_lock &)this ); } 166 static inline void on_wait ( owner_lock & this ) { on_wait ( (blocking_lock &)this ); } 165 static inline size_t on_wait ( owner_lock & this ) { return on_wait ( (blocking_lock &)this ); } 166 static inline void on_wakeup( owner_lock & this, size_t v ) { on_wakeup ( (blocking_lock &)this, v ); } 167 167 static inline void on_notify( owner_lock & this, struct $thread * t ) { on_notify( (blocking_lock &)this, t ); } 168 static inline void set_recursion_count( owner_lock & this, size_t recursion ) { set_recursion_count( (blocking_lock &)this, recursion ); }169 static inline size_t get_recursion_count( owner_lock & this ) { return get_recursion_count( (blocking_lock &)this ); }170 168 171 169 struct fast_lock { … … 179 177 } 180 178 181 static inline void $lock(fast_lock & this, $thread * thrd) { 182 /* paranoid */verify(thrd != this.owner); 183 184 for (;;) { 185 if ($try_lock(this, thrd)) return; 186 P(this.sem, thrd); 187 } 188 } 189 179 static inline void lock( fast_lock & this ) __attribute__((artificial)); 190 180 static inline void lock( fast_lock & this ) { 191 181 $thread * thrd = active_thread(); … … 198 188 } 199 189 200 static inline void try_lock ( fast_lock & this ) { 190 static inline bool try_lock( fast_lock & this ) __attribute__((artificial)); 191 static inline bool try_lock ( fast_lock & this ) { 201 192 $thread * thrd = active_thread(); 202 193 /* paranoid */ verify(thrd != this.owner); … … 204 195 } 205 196 206 static inline void unlock( fast_lock & this ) { 197 static inline $thread * unlock( fast_lock & this ) __attribute__((artificial)); 198 static inline $thread * unlock( fast_lock & this ) { 207 199 $thread * thrd = active_thread(); 208 200 /* paranoid */ verify(thrd == this.owner); 209 $thread * next = V(this.sem, false); // implicit fence 210 // open 'owner' only after fence 201 202 // open 'owner' before unlocking anyone 203 // so new and unlocked threads don't park incorrectly. 204 // This may require additional fencing on ARM. 211 205 this.owner = 0p; 212 206 213 // Unpark the next person (can be 0p, unpark handles it) 214 unpark(next); 215 } 216 217 static inline void on_wait( fast_lock & this ) { 218 unlock(this); 219 #warning this is broken 220 } 221 222 static inline void on_notify( fast_lock & this, struct $thread * t ) { 223 $lock(this, t); 224 #warning this is broken 225 } 226 227 static inline void set_recursion_count( fast_lock & this, size_t recursion ) {} 228 static inline size_t get_recursion_count( fast_lock & this ) { return 0; } 207 return V(this.sem, true); 208 } 209 210 static inline size_t on_wait( fast_lock & this ) { unlock(this); return 0; } 211 static inline void on_wakeup( fast_lock & this, size_t ) { lock(this); } 212 static inline void on_notify( fast_lock &, struct $thread * t ) { unpark(t); } 229 213 230 214 struct mcs_node { … … 260 244 261 245 // For synchronization locks to use when releasing 262 void on_wait( L & ); 263 264 // to get recursion count for cond lock to reset after waking 265 size_t get_recursion_count( L & ); 246 size_t on_wait( L & ); 266 247 267 248 // to set recursion count after getting signalled; 268 void set_recursion_count( L &, size_t recursion );249 void on_wakeup( L &, size_t recursion ); 269 250 }; 270 251 -
tests/concurrent/spinaphore.cfa
rca33b15 rc60ef639 36 36 this.sum = 0; 37 37 for(num_blocks) { 38 // sout | "b P" | me;39 38 P(sem); 40 39 if(((thread&)this).seqable.next != 0p) sout | "Link not invalidated"; 41 // sout | "a P" | me;42 40 } 43 41 } … … 58 56 this.sum += (unsigned)b; 59 57 unpark(t); 60 // sout | "a V" | t;61 58 yield(random(10)); 62 59 } -
tests/unified_locking/.expect/locks.txt
rca33b15 rc60ef639 11 11 Start Test 6: owner lock and condition variable 3 wait/notify all 12 12 Done Test 6 13 Start Test 7: multi acquisiton lock and condition variable multiple acquire andwait/notify13 Start Test 7: fast lock and condition variable single wait/notify 14 14 Done Test 7 15 Start Test 8: owner lock and condition variable multiple acquire and wait/notify15 Start Test 8: fast lock and condition variable 3 wait/notify all 16 16 Done Test 8 17 Start Test 9: no lock condition variablewait/notify17 Start Test 9: multi acquisiton lock and condition variable multiple acquire and wait/notify 18 18 Done Test 9 19 Start Test 10: locked condition variable wait/notify with front()19 Start Test 10: owner lock and condition variable multiple acquire and wait/notify 20 20 Done Test 10 21 Start Test 11: no lock condition variable wait/notify 22 Done Test 11 23 Start Test 12: locked condition variable wait/notify with front() 24 Done Test 12 -
tests/unified_locking/locks.cfa
rca33b15 rc60ef639 15 15 condition_variable( owner_lock ) c_o; 16 16 17 fast_lock f; 18 condition_variable( fast_lock ) c_f; 19 17 20 thread T_C_M_WS1 {}; 18 21 … … 68 71 } 69 72 unlock(s); 73 } 74 } 75 76 thread T_C_F_WS1 {}; 77 78 void main( T_C_F_WS1 & this ) { 79 for (unsigned int i = 0; i < num_times; i++) { 80 lock(f); 81 if(empty(c_f) && i != num_times - 1) { 82 wait(c_f,f); 83 }else{ 84 notify_one(c_f); 85 } 86 unlock(f); 87 } 88 } 89 90 thread T_C_F_WB1 {}; 91 92 void main( T_C_F_WB1 & this ) { 93 for (unsigned int i = 0; i < num_times; i++) { 94 lock(f); 95 if(counter(c_f) == 3 || i == num_times - 1) { 96 notify_all(c_f); 97 }else{ 98 wait(c_f,f); 99 } 100 unlock(f); 70 101 } 71 102 } … … 255 286 printf("Done Test 6\n"); 256 287 257 printf("Start Test 7: multi acquisiton lock and condition variable multiple acquire and wait/notify\n"); 288 printf("Start Test 7: fast lock and condition variable single wait/notify\n"); 289 { 290 T_C_F_WS1 t1[2]; 291 } 292 printf("Done Test 7\n"); 293 294 printf("Start Test 8: fast lock and condition variable 3 wait/notify all\n"); 295 { 296 T_C_F_WB1 t1[4]; 297 } 298 printf("Done Test 8\n"); 299 300 printf("Start Test 9: multi acquisiton lock and condition variable multiple acquire and wait/notify\n"); 258 301 { 259 302 T_C_M_WS2 t1[2]; 260 303 } 261 printf("Done Test 7\n");262 263 printf("Start Test 8: owner lock and condition variable multiple acquire and wait/notify\n");304 printf("Done Test 9\n"); 305 306 printf("Start Test 10: owner lock and condition variable multiple acquire and wait/notify\n"); 264 307 { 265 308 T_C_O_WS2 t1[2]; 266 309 } 267 printf("Done Test 8\n");268 269 printf("Start Test 9: no lock condition variable wait/notify\n");310 printf("Done Test 10\n"); 311 312 printf("Start Test 11: no lock condition variable wait/notify\n"); 270 313 { 271 314 T_C_NLW t1; 272 315 T_C_NLS t2; 273 316 } 274 printf("Done Test 9\n");275 276 printf("Start Test 1 0: locked condition variable wait/notify with front()\n");317 printf("Done Test 11\n"); 318 319 printf("Start Test 12: locked condition variable wait/notify with front()\n"); 277 320 { 278 321 T_C_S_WNF t1[2]; 279 322 } 280 printf("Done Test 1 0\n");323 printf("Done Test 12\n"); 281 324 282 325 // removed to limit test duration. Full test is in long run tests
Note: See TracChangeset
for help on using the changeset viewer.