Changeset 884f3f67 for libcfa/src/concurrency/kernel
- Timestamp:
- Mar 14, 2022, 2:24:51 PM (3 years ago)
- Branches:
- ADT, ast-experimental, enum, master, pthread-emulation, qualifiedEnum
- Children:
- bfb9bf5
- Parents:
- c42b8a1
- Location:
- libcfa/src/concurrency/kernel
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/kernel/cluster.cfa
rc42b8a1 r884f3f67 221 221 //----------------------------------------------------------------------- 222 222 // Check that all the intrusive queues in the data structure are still consistent 223 static void check ( __ready_queue_t & q ) with (q) {223 static void check_readyQ( cluster * cltr ) with (cltr->sched) { 224 224 #if defined(__CFA_WITH_VERIFY__) 225 225 { 226 for( idx ; lanes.count ) { 227 __intrusive_lane_t & sl = lanes.data[idx]; 228 assert(!lanes.data[idx].lock); 226 const unsigned lanes_count = readyQ.count; 227 for( idx ; lanes_count ) { 228 __intrusive_lane_t & sl = readyQ.data[idx]; 229 assert(!readyQ.data[idx].lock); 229 230 230 231 if(is_empty(sl)) { … … 257 258 it->rdq.id = value; 258 259 it->rdq.target = MAX; 259 value += __ readyq_shard_factor;260 value += __shard_factor.readyq; 260 261 it = &(*it)`next; 261 262 } … … 268 269 } 269 270 270 static void fix_times( struct cluster * cltr ) with( cltr->ready_queue) {271 lanes.tscs = alloc(lanes.count, lanes.tscs`realloc);272 for(i; lanes.count) {273 lanes.tscs[i].tv = rdtscl();274 lanes.tscs[i].ma = 0;271 static void fix_times( __timestamp_t * volatile & tscs, unsigned count ) { 272 tscs = alloc(count, tscs`realloc); 273 for(i; count) { 274 tscs[i].tv = rdtscl(); 275 tscs[i].ma = 0; 275 276 } 276 277 } … … 278 279 // Grow the ready queue 279 280 void ready_queue_grow(struct cluster * cltr) { 280 size_t ncount;281 281 int target = cltr->procs.total; 282 282 … … 285 285 286 286 // Make sure that everything is consistent 287 /* paranoid */ check( cltr->ready_queue ); 288 289 // grow the ready queue 290 with( cltr->ready_queue ) { 291 // Find new count 292 // Make sure we always have atleast 1 list 293 if(target >= 2) { 294 ncount = target * __readyq_shard_factor; 295 } else { 296 ncount = __readyq_single_shard; 297 } 298 299 // Allocate new array (uses realloc and memcpies the data) 300 lanes.data = alloc( ncount, lanes.data`realloc ); 301 302 // Fix the moved data 303 for( idx; (size_t)lanes.count ) { 304 fix(lanes.data[idx]); 305 } 306 307 // Construct new data 308 for( idx; (size_t)lanes.count ~ ncount) { 309 (lanes.data[idx]){}; 310 } 311 312 // Update original 313 lanes.count = ncount; 314 315 lanes.caches = alloc( target, lanes.caches`realloc ); 316 } 317 318 fix_times(cltr); 319 287 /* paranoid */ check_readyQ( cltr ); 288 289 290 // Find new count 291 // Make sure we always have atleast 1 list 292 size_t ocount = cltr->sched.readyQ.count; 293 size_t ncount = max(target * __shard_factor.readyq, __readyq_single_shard); 294 295 // Do we have to do anything? 296 if( ocount != ncount ) { 297 298 // grow the ready queue 299 with( cltr->sched ) { 300 301 // Allocate new array (uses realloc and memcpies the data) 302 readyQ.data = alloc( ncount, readyQ.data`realloc ); 303 304 // Fix the moved data 305 for( idx; ocount ) { 306 fix(readyQ.data[idx]); 307 } 308 309 // Construct new data 310 for( idx; ocount ~ ncount) { 311 (readyQ.data[idx]){}; 312 } 313 314 // Update original count 315 readyQ.count = ncount; 316 } 317 318 319 fix_times(cltr->sched.readyQ.tscs, cltr->sched.readyQ.count); 320 } 321 322 // realloc the caches 323 cltr->sched.caches = alloc( target, cltr->sched.caches`realloc ); 324 325 // reassign the clusters. 320 326 reassign_cltr_id(cltr); 321 327 322 328 // Make sure that everything is consistent 323 /* paranoid */ check( cltr->ready_queue ); 329 /* paranoid */ check_readyQ( cltr ); 330 /* paranoid */ verify( (target == 0) == (cltr->sched.caches == 0p) ); 324 331 325 332 __cfadbg_print_safe(ready_queue, "Kernel : Growing ready queue done\n"); … … 334 341 335 342 // Make sure that everything is consistent 336 /* paranoid */ check ( cltr->ready_queue);343 /* paranoid */ check_readyQ( cltr ); 337 344 338 345 int target = cltr->procs.total; 339 346 340 with( cltr-> ready_queue) {347 with( cltr->sched ) { 341 348 // Remember old count 342 size_t ocount = lanes.count;349 size_t ocount = readyQ.count; 343 350 344 351 // Find new count 345 352 // Make sure we always have atleast 1 list 346 lanes.count = target >= 2 ? target * __readyq_shard_factor: __readyq_single_shard; 347 /* paranoid */ verify( ocount >= lanes.count ); 348 /* paranoid */ verify( lanes.count == target * __readyq_shard_factor || target < 2 ); 353 size_t ncount = max(target * __shard_factor.readyq, __readyq_single_shard); 354 /* paranoid */ verifyf( ocount >= ncount, "Error in shrinking size calculation, %zu >= %zu", ocount, ncount ); 355 /* paranoid */ verifyf( ncount == target * __shard_factor.readyq || ncount == __readyq_single_shard, 356 /* paranoid */ "Error in shrinking size calculation, expected %u or %u, got %zu", target * __shard_factor.readyq, ncount ); 357 358 readyQ.count = ncount; 349 359 350 360 // for printing count the number of displaced threads … … 354 364 355 365 // redistribute old data 356 for( idx; (size_t)lanes.count ~ ocount) {366 for( idx; ncount ~ ocount) { 357 367 // Lock is not strictly needed but makes checking invariants much easier 358 __attribute__((unused)) bool locked = __atomic_try_acquire(& lanes.data[idx].lock);368 __attribute__((unused)) bool locked = __atomic_try_acquire(&readyQ.data[idx].lock); 359 369 verify(locked); 360 370 361 371 // As long as we can pop from this lane to push the threads somewhere else in the queue 362 while(!is_empty( lanes.data[idx])) {372 while(!is_empty(readyQ.data[idx])) { 363 373 struct thread$ * thrd; 364 374 unsigned long long _; 365 [thrd, _] = pop( lanes.data[idx]);375 [thrd, _] = pop(readyQ.data[idx]); 366 376 367 377 push(cltr, thrd, true); … … 374 384 375 385 // Unlock the lane 376 __atomic_unlock(& lanes.data[idx].lock);386 __atomic_unlock(&readyQ.data[idx].lock); 377 387 378 388 // TODO print the queue statistics here 379 389 380 ^( lanes.data[idx]){};390 ^(readyQ.data[idx]){}; 381 391 } 382 392 … … 384 394 385 395 // Allocate new array (uses realloc and memcpies the data) 386 lanes.data = alloc( lanes.count, lanes.data`realloc );396 readyQ.data = alloc( ncount, readyQ.data`realloc ); 387 397 388 398 // Fix the moved data 389 for( idx; (size_t)lanes.count ) {390 fix( lanes.data[idx]);391 } 392 393 lanes.caches = alloc( target, lanes.caches`realloc);394 } 395 396 fix_times(cltr); 399 for( idx; ncount ) { 400 fix(readyQ.data[idx]); 401 } 402 403 fix_times(readyQ.tscs, ncount); 404 } 405 cltr->sched.caches = alloc( target, cltr->sched.caches`realloc ); 406 397 407 398 408 … … 400 410 401 411 // Make sure that everything is consistent 402 /* paranoid */ check( cltr->ready_queue ); 412 /* paranoid */ verify( (target == 0) == (cltr->sched.caches == 0p) ); 413 /* paranoid */ check_readyQ( cltr ); 403 414 404 415 __cfadbg_print_safe(ready_queue, "Kernel : Shrinking ready queue done\n"); 405 416 /* paranoid */ verify( ready_mutate_islocked() ); 417 } 418 419 void ready_queue_close(struct cluster * cltr) { 420 free( cltr->sched.readyQ.data ); 421 free( cltr->sched.readyQ.tscs ); 422 cltr->sched.readyQ.data = 0p; 423 cltr->sched.readyQ.tscs = 0p; 424 cltr->sched.readyQ.count = 0; 425 426 free( cltr->sched.io.tscs ); 427 free( cltr->sched.caches ); 406 428 } 407 429 -
libcfa/src/concurrency/kernel/startup.cfa
rc42b8a1 r884f3f67 515 515 this.rdq.its = 0; 516 516 this.rdq.itr = 0; 517 this.rdq.id = MAX;517 this.rdq.id = 0; 518 518 this.rdq.target = MAX; 519 519 this.rdq.last = MAX; … … 605 605 this.name = name; 606 606 this.preemption_rate = preemption_rate; 607 ready_queue{}; 607 this.sched.readyQ.data = 0p; 608 this.sched.readyQ.tscs = 0p; 609 this.sched.readyQ.count = 0; 610 this.sched.io.tscs = 0p; 611 this.sched.caches = 0p; 608 612 609 613 #if !defined(__CFA_NO_STATISTICS__) … … 644 648 // Unlock the RWlock 645 649 ready_mutate_unlock( last_size ); 650 651 ready_queue_close( &this ); 652 /* paranoid */ verify( this.sched.readyQ.data == 0p ); 653 /* paranoid */ verify( this.sched.readyQ.tscs == 0p ); 654 /* paranoid */ verify( this.sched.readyQ.count == 0 ); 655 /* paranoid */ verify( this.sched.io.tscs == 0p ); 656 /* paranoid */ verify( this.sched.caches == 0p ); 657 646 658 enable_interrupts( false ); // Don't poll, could be in main cluster 659 647 660 648 661 #if !defined(__CFA_NO_STATISTICS__)
Note: See TracChangeset
for help on using the changeset viewer.