Changeset b1e63ac5 for src/libcfa/concurrency/monitor.c
- Timestamp:
- Jul 4, 2017, 9:40:16 AM (8 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
- Children:
- 208e5be
- Parents:
- 9c951e3 (diff), f7cb0bc (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - File:
-
- 1 edited
-
src/libcfa/concurrency/monitor.c (modified) (13 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/libcfa/concurrency/monitor.c
r9c951e3 rb1e63ac5 56 56 else if( this->owner == thrd) { 57 57 //We already have the monitor, just not how many times we took it 58 assert( this->recursion > 0 );58 verify( this->recursion > 0 ); 59 59 this->recursion += 1; 60 60 } … … 62 62 //Some one else has the monitor, wait in line for it 63 63 append( &this->entry_queue, thrd ); 64 LIB_DEBUG_PRINT_SAFE("%p Blocking on entry\n", thrd); 64 65 ScheduleInternal( &this->lock ); 65 66 … … 77 78 lock( &this->lock ); 78 79 79 thread_desc * thrd = this_thread();80 81 80 LIB_DEBUG_PRINT_SAFE("%p Leaving %p (o: %p, r: %i)\n", thrd, this, this->owner, this->recursion); 82 assertf( thrd == this->owner, "Expected owner to be %p, got %p (r: %i)", thrd, this->owner, this->recursion );81 verifyf( this_thread() == this->owner, "Expected owner to be %p, got %p (r: %i)", this_thread(), this->owner, this->recursion ); 83 82 84 83 //Leaving a recursion level, decrement the counter … … 97 96 unlock( &this->lock ); 98 97 98 LIB_DEBUG_PRINT_SAFE("Next owner is %p\n", new_owner); 99 99 100 //We need to wake-up the thread 100 101 ScheduleThread( new_owner ); … … 134 135 } 135 136 136 void debug_break() __attribute__(( noinline )) 137 { 138 137 void ?{}(__condition_node_t * this, thread_desc * waiting_thread, unsigned short count, uintptr_t user_info ) { 138 this->waiting_thread = waiting_thread; 139 this->count = count; 140 this->next = NULL; 141 this->user_info = user_info; 142 } 143 144 void ?{}(__condition_criterion_t * this ) { 145 this->ready = false; 146 this->target = NULL; 147 this->owner = NULL; 148 this->next = NULL; 149 } 150 151 void ?{}(__condition_criterion_t * this, monitor_desc * target, __condition_node_t * owner ) { 152 this->ready = false; 153 this->target = target; 154 this->owner = owner; 155 this->next = NULL; 139 156 } 140 157 141 158 //----------------------------------------------------------------------------- 142 159 // Internal scheduling 143 void wait( condition * this ) {160 void wait( condition * this, uintptr_t user_info = 0 ) { 144 161 LIB_DEBUG_PRINT_SAFE("Waiting\n"); 145 162 … … 148 165 //Check that everything is as expected 149 166 assertf( this->monitors != NULL, "Waiting with no monitors (%p)", this->monitors ); 150 assertf( this->monitor_count != 0, "Waiting with 0 monitors (%i)", this->monitor_count ); 167 verifyf( this->monitor_count != 0, "Waiting with 0 monitors (%i)", this->monitor_count ); 168 verifyf( this->monitor_count < 32u, "Excessive monitor count (%i)", this->monitor_count ); 151 169 152 170 unsigned short count = this->monitor_count; … … 156 174 LIB_DEBUG_PRINT_SAFE("count %i\n", count); 157 175 158 __condition_node_t waiter; 159 waiter.waiting_thread = this_thread(); 160 waiter.count = count; 161 waiter.next = NULL; 176 __condition_node_t waiter = { this_thread(), count, user_info }; 162 177 163 178 __condition_criterion_t criteria[count]; 164 179 for(int i = 0; i < count; i++) { 165 criteria[i].ready = false; 166 criteria[i].target = this->monitors[i]; 167 criteria[i].owner = &waiter; 168 criteria[i].next = NULL; 180 (&criteria[i]){ this->monitors[i], &waiter }; 169 181 LIB_DEBUG_PRINT_SAFE( "Criterion %p\n", &criteria[i] ); 170 182 } … … 184 196 } 185 197 186 debug_break();187 188 198 for( int i = 0; i < count; i++) { 189 199 thread_desc * new_owner = next_thread( this->monitors[i] ); 190 200 thread_count = insert_unique( threads, thread_count, new_owner ); 191 201 } 192 193 debug_break();194 202 195 203 LIB_DEBUG_PRINT_SAFE("Will unblock: "); … … 212 220 } 213 221 214 voidsignal( condition * this ) {215 if( !this->blocked.head) {222 bool signal( condition * this ) { 223 if( is_empty( this ) ) { 216 224 LIB_DEBUG_PRINT_SAFE("Nothing to signal\n"); 217 return ;225 return false; 218 226 } 219 227 220 228 //Check that everything is as expected 221 assert( this->monitors );222 assert( this->monitor_count != 0 );229 verify( this->monitors ); 230 verify( this->monitor_count != 0 ); 223 231 224 232 unsigned short count = this->monitor_count; 225 233 234 //Some more checking in debug 226 235 LIB_DEBUG_DO( 227 236 thread_desc * this_thrd = this_thread(); … … 237 246 ); 238 247 248 //Lock all the monitors 239 249 lock_all( this->monitors, NULL, count ); 240 250 LIB_DEBUG_PRINT_SAFE("Signalling"); 241 251 252 //Pop the head of the waiting queue 242 253 __condition_node_t * node = pop_head( &this->blocked ); 254 255 //Add the thread to the proper AS stack 243 256 for(int i = 0; i < count; i++) { 244 257 __condition_criterion_t * crit = &node->criteria[i]; … … 250 263 LIB_DEBUG_PRINT_SAFE("\n"); 251 264 265 //Release 252 266 unlock_all( this->monitors, count ); 267 268 return true; 269 } 270 271 bool signal_block( condition * this ) { 272 if( !this->blocked.head ) { 273 LIB_DEBUG_PRINT_SAFE("Nothing to signal\n"); 274 return false; 275 } 276 277 //Check that everything is as expected 278 verifyf( this->monitors != NULL, "Waiting with no monitors (%p)", this->monitors ); 279 verifyf( this->monitor_count != 0, "Waiting with 0 monitors (%i)", this->monitor_count ); 280 281 unsigned short count = this->monitor_count; 282 unsigned int recursions[ count ]; //Save the current recursion levels to restore them later 283 spinlock * locks [ count ]; //We need to pass-in an array of locks to ScheduleInternal 284 285 lock_all( this->monitors, locks, count ); 286 287 //create creteria 288 __condition_node_t waiter = { this_thread(), count, 0 }; 289 290 __condition_criterion_t criteria[count]; 291 for(int i = 0; i < count; i++) { 292 (&criteria[i]){ this->monitors[i], &waiter }; 293 LIB_DEBUG_PRINT_SAFE( "Criterion %p\n", &criteria[i] ); 294 push( &criteria[i].target->signal_stack, &criteria[i] ); 295 } 296 297 waiter.criteria = criteria; 298 299 //save contexts 300 save_recursion( this->monitors, recursions, count ); 301 302 //Find the thread to run 303 thread_desc * signallee = pop_head( &this->blocked )->waiting_thread; 304 for(int i = 0; i < count; i++) { 305 set_owner( this->monitors[i], signallee ); 306 } 307 308 LIB_DEBUG_PRINT_SAFE( "Waiting on signal block\n" ); 309 310 //Everything is ready to go to sleep 311 ScheduleInternal( locks, count, &signallee, 1 ); 312 313 314 315 316 LIB_DEBUG_PRINT_SAFE( "Back from signal block\n" ); 317 318 //We are back, restore the owners and recursions 319 lock_all( locks, count ); 320 restore_recursion( this->monitors, recursions, count ); 321 unlock_all( locks, count ); 322 323 return true; 324 } 325 326 uintptr_t front( condition * this ) { 327 verifyf( !is_empty(this), 328 "Attempt to access user data on an empty condition.\n" 329 "Possible cause is not checking if the condition is empty before reading stored data." 330 ); 331 return this->blocked.head->user_info; 332 } 333 334 //----------------------------------------------------------------------------- 335 // Internal scheduling 336 void __accept_internal( unsigned short count, __acceptable_t * acceptables, void (*func)(void) ) { 337 // thread_desc * this = this_thread(); 338 339 // unsigned short count = this->current_monitor_count; 340 // unsigned int recursions[ count ]; //Save the current recursion levels to restore them later 341 // spinlock * locks [ count ]; //We need to pass-in an array of locks to ScheduleInternal 342 343 // lock_all( this->current_monitors, locks, count ); 344 345 346 347 348 349 // // // Everything is ready to go to sleep 350 // // ScheduleInternal( locks, count, threads, thread_count ); 351 352 353 // //WE WOKE UP 354 355 356 // //We are back, restore the owners and recursions 357 // lock_all( locks, count ); 358 // restore_recursion( this->monitors, recursions, count ); 359 // unlock_all( locks, count ); 253 360 } 254 361 … … 335 442 336 443 for( int i = 0; i < count; i++ ) { 444 337 445 LIB_DEBUG_PRINT_SAFE( "Checking %p for %p\n", &criteria[i], target ); 338 446 if( &criteria[i] == target ) { … … 379 487 380 488 void append( __condition_blocked_queue_t * this, __condition_node_t * c ) { 381 assert(this->tail != NULL);489 verify(this->tail != NULL); 382 490 *this->tail = c; 383 491 this->tail = &c->next;
Note:
See TracChangeset
for help on using the changeset viewer.