Changeset 2223c80
- Timestamp:
- May 13, 2020, 6:34:09 PM (4 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 365cb03f, 9c438546
- Parents:
- 856fe3e (diff), 979df46 (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. - Files:
-
- 26 edited
Legend:
- Unmodified
- Added
- Removed
-
benchmark/io/readv.cfa
r856fe3e r2223c80 59 59 unsigned long int nthreads = 2; 60 60 unsigned long int nprocs = 1; 61 int flags = 0; 61 unsigned flags = 0; 62 unsigned sublen = 16; 62 63 63 64 arg_loop: 64 65 for(;;) { 65 66 static struct option options[] = { 66 {"duration", required_argument, 0, 'd'}, 67 {"nthreads", required_argument, 0, 't'}, 68 {"nprocs", required_argument, 0, 'p'}, 69 {"bufsize", required_argument, 0, 'b'}, 70 {"userthread", no_argument , 0, 'u'}, 67 {"duration", required_argument, 0, 'd'}, 68 {"nthreads", required_argument, 0, 't'}, 69 {"nprocs", required_argument, 0, 'p'}, 70 {"bufsize", required_argument, 0, 'b'}, 71 {"userthread", no_argument , 0, 'u'}, 72 {"submitthread", no_argument , 0, 's'}, 73 {"submitlength", required_argument, 0, 'l'}, 71 74 {0, 0, 0, 0} 72 75 }; 73 76 74 77 int idx = 0; 75 int opt = getopt_long(argc, argv, "d:t:p:b:u ", options, &idx);78 int opt = getopt_long(argc, argv, "d:t:p:b:usl:", options, &idx); 76 79 77 80 const char * arg = optarg ? optarg : ""; … … 113 116 flags |= CFA_CLUSTER_IO_POLLER_USER_THREAD; 114 117 break; 118 case 's': 119 flags |= CFA_CLUSTER_IO_POLLER_THREAD_SUBMITS; 120 break; 121 case 'l': 122 sublen = strtoul(arg, &end, 10); 123 if(*end != '\0' && sublen < 16) { 124 fprintf(stderr, "Submit length must be at least 16, was %s\n", arg); 125 goto usage; 126 } 127 flags |= (sublen << CFA_CLUSTER_IO_BUFFLEN_OFFSET); 128 break; 115 129 // Other cases 116 130 default: /* ? */ … … 123 137 fprintf(stderr, " -p, --nprocs=NPROCS Number of kernel threads\n"); 124 138 fprintf(stderr, " -b, --buflen=SIZE Number of bytes to read per request\n"); 139 fprintf(stderr, " -u, --userthread If set, cluster uses user-thread to poll I/O\n"); 140 fprintf(stderr, " -s, --submitthread If set, cluster uses polling thread to submit I/O\n"); 125 141 exit(EXIT_FAILURE); 126 142 } -
configure
r856fe3e r2223c80 802 802 with_cfa_name 803 803 enable_distcc 804 with_bwlimit 804 805 with_target_hosts 805 806 enable_gprofiler … … 1481 1482 --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) 1482 1483 --with-cfa-name=NAME NAME too which cfa will be installed 1484 --with-bwlimit=RATE RATE the maximum rate at which rsync will be limited when using distributed builds 1483 1485 --with-target-hosts=HOSTS HOSTS comma seperated list of hosts to build for, format ARCH:debug|nodebug|nolib 1484 1486 --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use … … 3198 3200 else 3199 3201 enable_distcc=no 3202 fi 3203 3204 3205 3206 # Check whether --with-bwlimit was given. 3207 if test "${with_bwlimit+set}" = set; then : 3208 withval=$with_bwlimit; 3200 3209 fi 3201 3210 -
configure.ac
r856fe3e r2223c80 64 64 [ --enable-distcc whether or not to enable distributed compilation], 65 65 enable_distcc=$enableval, enable_distcc=no) 66 67 AC_ARG_WITH(bwlimit, 68 [ --with-bwlimit=RATE RATE the maximum rate at which rsync will be limited when using distributed builds], 69 [], []) 66 70 67 71 AM_CONDITIONAL([ENABLE_DISTCC], [test x$enable_distcc = xyes]) -
doc/proposals/vtable.md
r856fe3e r2223c80 237 237 default is provided or not, the second syntax can be used to pick a 238 238 parameter on instantiation. 239 240 ### Extension: Object Access 241 This requires that the resolution scope (see below) is at the type level or 242 has explicate points with names. These are the tables and table names used 243 here. 244 245 The system already knows where to find the virtual table and the object. If 246 the tables have particular identities, or on the user side names, then it is 247 meaningful to check if a binding virtual table is the same* as another. The 248 main use of this is virtual table declarations also give the type they bind 249 and if a binding table matches a known table then the underlyind object in the 250 trait object must be of that type. 251 252 * By identity, by value would work and in some senses be more flexiable. But 253 it would be slower and refering to further away functions would be harder. 254 255 This gives one of the main new features of the hierarchical use of virtual 256 tables (see below); the ability to recover the underlying object. Or a pointer 257 of the approprate type it which both reflects the implementation and gives a 258 convenent way to encode the boolean/conditional aspect of the operation which 259 is that a different virtual table might be in use. 260 261 There are two general ways to reperent this; a cast or a field access. The 262 cast is traditional and would definitely fit if a single pointer repersents 263 a trait object with the virtual table as part of the object. However for a 264 double pointer field access might be more approprate. By this system though 265 it is not the type that is used as the identifier but the virtual table. If 266 there is one table per type than it becomes equivilant again. Otherwise the 267 table has to be used as the identifier and the type is just a result of that 268 which seems important for syntax. 239 269 240 270 Hierarchy … … 560 590 be used in only some of the declarations. 561 591 562 trait combiner fee = (summation_instance, sum);592 trait combiner fee = {summation_instance, sum}; 563 593 trait combiner foe = summation_instance; 564 594 -
libcfa/Makefile.in
r856fe3e r2223c80 253 253 DEFS = @DEFS@ 254 254 DEPDIR = @DEPDIR@ 255 DIST_BWLIMIT = @DIST_BWLIMIT@ 255 256 DLLTOOL = @DLLTOOL@ 256 257 DRIVER_DIR = @DRIVER_DIR@ -
libcfa/configure
r856fe3e r2223c80 707 707 CONFIG_CFLAGS 708 708 ARCH_FLAGS 709 DIST_BWLIMIT 709 710 CFADIR_HASH 710 711 LOCAL_CC1 … … 789 790 enable_silent_rules 790 791 enable_distcc 792 with_bwlimit 791 793 with_cfa_name 792 794 enable_static … … 1465 1467 --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] 1466 1468 --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) 1469 --with-bwlimit=RATE RATE the maximum rate at which rsync will be limited when using distributed builds 1467 1470 --with-cfa-name=NAME NAME too which cfa will be installed 1468 1471 --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use … … 3047 3050 3048 3051 3052 3053 # Check whether --with-bwlimit was given. 3054 if test "${with_bwlimit+set}" = set; then : 3055 withval=$with_bwlimit; DIST_BWLIMIT=$withval 3056 else 3057 DIST_BWLIMIT=0 3058 fi 3059 3060 3049 3061 echo -n "checking for distributated build... " 3050 3062 if test x$enable_distcc = xno; then … … 3070 3082 ENABLE_DISTCC_FALSE= 3071 3083 fi 3084 3072 3085 3073 3086 -
libcfa/configure.ac
r856fe3e r2223c80 31 31 enable_distcc=$enableval, enable_distcc=no) 32 32 33 AC_ARG_WITH(bwlimit, 34 [ --with-bwlimit=RATE RATE the maximum rate at which rsync will be limited when using distributed builds], 35 DIST_BWLIMIT=$withval, DIST_BWLIMIT=0) 36 33 37 echo -n "checking for distributated build... " 34 38 if test x$enable_distcc = xno; then … … 55 59 AC_SUBST(CFADIR_HASH) 56 60 AC_SUBST(CFA_VERSION) 61 AC_SUBST(DIST_BWLIMIT) 57 62 58 63 #============================================================================== -
libcfa/prelude/Makefile.am
r856fe3e r2223c80 72 72 if ENABLE_DISTCC 73 73 distribution: @LOCAL_CFACC@ @LOCAL_CC1@ @CFACPP@ gcc-builtins.cf builtins.cf extras.cf prelude.cfa bootloader.c $(srcdir)/../../tools/build/push2dist.sh 74 ${AM_V_GEN}$(srcdir)/../../tools/build/push2dist.sh @CFADIR_HASH@ 74 ${AM_V_GEN}$(srcdir)/../../tools/build/push2dist.sh @CFADIR_HASH@ @DIST_BWLIMIT@ 75 75 @echo "Dummy file to track distribution to remote hosts" > ${@} 76 76 -
libcfa/prelude/Makefile.in
r856fe3e r2223c80 215 215 DEFS = @DEFS@ 216 216 DEPDIR = @DEPDIR@ 217 DIST_BWLIMIT = @DIST_BWLIMIT@ 217 218 DLLTOOL = @DLLTOOL@ 218 219 DRIVER_DIR = @DRIVER_DIR@ … … 655 656 656 657 @ENABLE_DISTCC_TRUE@distribution: @LOCAL_CFACC@ @LOCAL_CC1@ @CFACPP@ gcc-builtins.cf builtins.cf extras.cf prelude.cfa bootloader.c $(srcdir)/../../tools/build/push2dist.sh 657 @ENABLE_DISTCC_TRUE@ ${AM_V_GEN}$(srcdir)/../../tools/build/push2dist.sh @CFADIR_HASH@ 658 @ENABLE_DISTCC_TRUE@ ${AM_V_GEN}$(srcdir)/../../tools/build/push2dist.sh @CFADIR_HASH@ @DIST_BWLIMIT@ 658 659 @ENABLE_DISTCC_TRUE@ @echo "Dummy file to track distribution to remote hosts" > ${@} 659 660 -
libcfa/src/Makefile.in
r856fe3e r2223c80 307 307 DEFS = @DEFS@ 308 308 DEPDIR = @DEPDIR@ 309 DIST_BWLIMIT = @DIST_BWLIMIT@ 309 310 DLLTOOL = @DLLTOOL@ 310 311 DRIVER_DIR = @DRIVER_DIR@ -
libcfa/src/concurrency/io.cfa
r856fe3e r2223c80 18 18 19 19 #include "kernel.hfa" 20 #include "bitmanip.hfa" 20 21 21 22 #if !defined(HAVE_LINUX_IO_URING_H) 22 void __kernel_io_startup( cluster &, int, bool ) {23 void __kernel_io_startup( cluster &, unsigned, bool ) { 23 24 // Nothing to do without io_uring 24 25 } … … 91 92 struct __io_poller_fast { 92 93 struct __io_data * ring; 93 bool waiting;94 94 $thread thrd; 95 95 }; … … 97 97 void ?{}( __io_poller_fast & this, struct cluster & cltr ) { 98 98 this.ring = cltr.io; 99 this.waiting = true;100 99 (this.thrd){ "Fast I/O Poller", cltr }; 101 100 } … … 126 125 // Like head/tail but not seen by the kernel 127 126 volatile uint32_t alloc; 128 volatile uint32_t ready; 127 volatile uint32_t * ready; 128 uint32_t ready_cnt; 129 129 130 130 __spinlock_t lock; … … 145 145 volatile unsigned long long int block; 146 146 } submit_avg; 147 struct { 148 volatile unsigned long long int val; 149 volatile unsigned long long int cnt; 150 volatile unsigned long long int block; 151 } look_avg; 147 152 } stats; 148 153 #endif … … 192 197 void * stack; 193 198 pthread_t kthrd; 199 volatile bool blocked; 194 200 } slow; 195 201 __io_poller_fast fast; … … 201 207 // I/O Startup / Shutdown logic 202 208 //============================================================================================= 203 void __kernel_io_startup( cluster & this, intio_flags, bool main_cluster ) {209 void __kernel_io_startup( cluster & this, unsigned io_flags, bool main_cluster ) { 204 210 this.io = malloc(); 205 211 … … 274 280 sq.array = ( uint32_t *)(((intptr_t)sq.ring_ptr) + params.sq_off.array); 275 281 sq.alloc = *sq.tail; 276 sq.ready = *sq.tail; 282 283 if( io_flags & CFA_CLUSTER_IO_POLLER_THREAD_SUBMITS ) { 284 /* paranoid */ verify( is_pow2( io_flags >> CFA_CLUSTER_IO_BUFFLEN_OFFSET ) || ((io_flags >> CFA_CLUSTER_IO_BUFFLEN_OFFSET) < 8) ); 285 sq.ready_cnt = max(io_flags >> CFA_CLUSTER_IO_BUFFLEN_OFFSET, 8); 286 sq.ready = alloc_align( 64, sq.ready_cnt ); 287 for(i; sq.ready_cnt) { 288 sq.ready[i] = -1ul32; 289 } 290 } 291 else { 292 sq.ready_cnt = 0; 293 sq.ready = 0p; 294 } 277 295 278 296 // completion queue … … 307 325 this.io->submit_q.stats.submit_avg.cnt = 0; 308 326 this.io->submit_q.stats.submit_avg.block = 0; 327 this.io->submit_q.stats.look_avg.val = 0; 328 this.io->submit_q.stats.look_avg.cnt = 0; 329 this.io->submit_q.stats.look_avg.block = 0; 309 330 this.io->completion_q.stats.completed_avg.val = 0; 310 331 this.io->completion_q.stats.completed_avg.slow_cnt = 0; … … 326 347 // Create the poller thread 327 348 __cfadbg_print_safe(io_core, "Kernel I/O : Creating slow poller for cluter %p\n", &this); 349 this.io->poller.slow.blocked = false; 328 350 this.io->poller.slow.stack = __create_pthread( &this.io->poller.slow.kthrd, __io_poller_slow, &this ); 329 351 } … … 347 369 if( this.io->cltr_flags & CFA_CLUSTER_IO_POLLER_USER_THREAD ) { 348 370 with( this.io->poller.fast ) { 349 /* paranoid */ verify( waiting ); // The thread shouldn't be in a system call350 371 /* paranoid */ verify( this.procs.head == 0p || &this == mainCluster ); 351 372 /* paranoid */ verify( this.idles.head == 0p || &this == mainCluster ); 352 373 353 374 // We need to adjust the clean-up based on where the thread is 354 if( thrd. preempted != __NO_PREEMPTION ) {375 if( thrd.state == Ready || thrd.preempted != __NO_PREEMPTION ) { 355 376 356 377 // This is the tricky case 357 378 // The thread was preempted and now it is on the ready queue 358 /* paranoid */ verify( thrd.state == Active ); // The thread better be in this state359 379 /* paranoid */ verify( thrd.next == 1p ); // The thread should be the last on the list 360 380 /* paranoid */ verify( this.ready_queue.head == &thrd ); // The thread should be the only thing on the list … … 405 425 if(this.print_stats) { 406 426 with(this.io->submit_q.stats, this.io->completion_q.stats) { 427 double lavgv = 0; 428 double lavgb = 0; 429 if(look_avg.cnt != 0) { 430 lavgv = ((double)look_avg.val ) / look_avg.cnt; 431 lavgb = ((double)look_avg.block) / look_avg.cnt; 432 } 433 407 434 __cfaabi_bits_print_safe( STDERR_FILENO, 408 435 "----- I/O uRing Stats -----\n" 409 "- total submit calls : %'15llu\n" 410 "- avg submit : %'18.2lf\n" 411 "- pre-submit block %% : %'18.2lf\n" 412 "- total wait calls : %'15llu (%'llu slow, %'llu fast)\n" 413 "- avg completion/wait : %'18.2lf\n", 436 "- total submit calls : %'15llu\n" 437 "- avg submit : %'18.2lf\n" 438 "- pre-submit block %% : %'18.2lf\n" 439 "- total ready search : %'15llu\n" 440 "- avg ready search len : %'18.2lf\n" 441 "- avg ready search block : %'18.2lf\n" 442 "- total wait calls : %'15llu (%'llu slow, %'llu fast)\n" 443 "- avg completion/wait : %'18.2lf\n", 414 444 submit_avg.cnt, 415 445 ((double)submit_avg.val) / submit_avg.cnt, 416 446 (100.0 * submit_avg.block) / submit_avg.cnt, 447 look_avg.cnt, 448 lavgv, 449 lavgb, 417 450 completed_avg.slow_cnt + completed_avg.fast_cnt, 418 451 completed_avg.slow_cnt, completed_avg.fast_cnt, … … 441 474 close(this.io->fd); 442 475 476 free( this.io->submit_q.ready ); // Maybe null, doesn't matter 443 477 free( this.io ); 444 478 } … … 454 488 // Process a single completion message from the io_uring 455 489 // This is NOT thread-safe 456 static int __drain_io( struct __io_data & ring, sigset_t * mask, int waitcnt, bool in_kernel ) { 457 int ret = syscall( __NR_io_uring_enter, ring.fd, 0, waitcnt, IORING_ENTER_GETEVENTS, mask, _NSIG / 8); 490 static [int, bool] __drain_io( & struct __io_data ring, * sigset_t mask, int waitcnt, bool in_kernel ) { 491 unsigned to_submit = 0; 492 if( ring.cltr_flags & CFA_CLUSTER_IO_POLLER_THREAD_SUBMITS ) { 493 494 // If the poller thread also submits, then we need to aggregate the submissions which are ready 495 uint32_t * tail = ring.submit_q.tail; 496 const uint32_t mask = *ring.submit_q.mask; 497 498 // Go through the list of ready submissions 499 for( i; ring.submit_q.ready_cnt ) { 500 // replace any submission with the sentinel, to consume it. 501 uint32_t idx = __atomic_exchange_n( &ring.submit_q.ready[i], -1ul32, __ATOMIC_RELAXED); 502 503 // If it was already the sentinel, then we are done 504 if( idx == -1ul32 ) continue; 505 506 // If we got a real submission, append it to the list 507 ring.submit_q.array[ ((*tail) + to_submit) & mask ] = idx & mask; 508 to_submit++; 509 } 510 511 // Increment the tail based on how many we are ready to submit 512 __atomic_fetch_add(tail, to_submit, __ATOMIC_SEQ_CST); 513 514 // update statistics 515 #if !defined(__CFA_NO_STATISTICS__) 516 ring.submit_q.stats.submit_avg.val += to_submit; 517 ring.submit_q.stats.submit_avg.cnt += 1; 518 #endif 519 } 520 521 int ret = syscall( __NR_io_uring_enter, ring.fd, to_submit, waitcnt, IORING_ENTER_GETEVENTS, mask, _NSIG / 8); 458 522 if( ret < 0 ) { 459 523 switch((int)errno) { … … 497 561 __atomic_fetch_add( ring.completion_q.head, count, __ATOMIC_RELAXED ); 498 562 499 return count;563 return [count, count > 0 || to_submit > 0]; 500 564 } 501 565 … … 519 583 if( ring.cltr_flags & CFA_CLUSTER_IO_POLLER_USER_THREAD ) { 520 584 while(!__atomic_load_n(&ring.done, __ATOMIC_SEQ_CST)) { 585 586 __atomic_store_n( &ring.poller.slow.blocked, true, __ATOMIC_SEQ_CST ); 587 521 588 // In the user-thread approach drain and if anything was drained, 522 589 // batton pass to the user-thread 523 int count = __drain_io( ring, &mask, 1, true ); 590 int count; 591 bool again; 592 [count, again] = __drain_io( ring, &mask, 1, true ); 593 594 __atomic_store_n( &ring.poller.slow.blocked, false, __ATOMIC_SEQ_CST ); 524 595 525 596 // Update statistics … … 529 600 #endif 530 601 531 if( count > 0) {602 if(again) { 532 603 __cfadbg_print_safe(io_core, "Kernel I/O : Moving to ring %p to fast poller\n", &ring); 533 604 __unpark( &ring.poller.fast.thrd __cfaabi_dbg_ctx2 ); … … 539 610 while(!__atomic_load_n(&ring.done, __ATOMIC_SEQ_CST)) { 540 611 //In the naive approach, just poll the io completion queue directly 541 int count = __drain_io( ring, &mask, 1, true ); 612 int count; 613 bool again; 614 [count, again] = __drain_io( ring, &mask, 1, true ); 542 615 543 616 // Update statistics … … 566 639 // Then loop until we need to start 567 640 while(!__atomic_load_n(&this.ring->done, __ATOMIC_SEQ_CST)) { 641 568 642 // Drain the io 569 this.waiting = false; 570 int count = __drain_io( *this.ring, 0p, 0, false ); 571 reset += count > 0 ? 1 : 0; 643 int count; 644 bool again; 645 [count, again] = __drain_io( *this.ring, 0p, 0, false ); 646 647 if(!again) reset++; 572 648 573 649 // Update statistics … … 577 653 #endif 578 654 579 this.waiting = true;655 // If we got something, just yield and check again 580 656 if(reset < 5) { 581 // If we got something, just yield and check again582 657 yield(); 583 658 } 659 // We didn't get anything baton pass to the slow poller 584 660 else { 585 // We didn't get anything baton pass to the slow poller586 661 __cfadbg_print_safe(io_core, "Kernel I/O : Moving to ring %p to slow poller\n", &this.ring); 662 reset = 0; 663 664 // wake up the slow poller 587 665 post( this.ring->poller.sem ); 666 667 // park this thread 588 668 park( __cfaabi_dbg_ctx ); 589 reset = 0;590 669 } 591 670 } 592 671 593 672 __cfadbg_print_safe(io_core, "Kernel I/O : Fast poller for ring %p stopping\n", &this.ring); 673 } 674 675 static inline void __wake_poller( struct __io_data & ring ) __attribute__((artificial)); 676 static inline void __wake_poller( struct __io_data & ring ) { 677 if(!__atomic_load_n( &ring.poller.slow.blocked, __ATOMIC_SEQ_CST)) return; 678 679 sigval val = { 1 }; 680 pthread_sigqueue( ring.poller.slow.kthrd, SIGUSR1, val ); 594 681 } 595 682 … … 632 719 uint32_t idx = __atomic_fetch_add(&ring.submit_q.alloc, 1ul32, __ATOMIC_SEQ_CST); 633 720 634 // Validate that we didn't overflow anything 635 // Check that nothing overflowed 636 /* paranoid */ verify( true ); 637 638 // Check that it goes head -> tail -> alloc and never head -> alloc -> tail 639 /* paranoid */ verify( true ); 721 // Mask the idx now to allow make everything easier to check 722 idx &= *ring.submit_q.mask; 640 723 641 724 // Return the sqe 642 return [&ring.submit_q.sqes[ idx & (*ring.submit_q.mask)], idx];725 return [&ring.submit_q.sqes[ idx ], idx]; 643 726 } 644 727 645 728 static inline void __submit( struct __io_data & ring, uint32_t idx ) { 646 // get mutual exclusion 647 lock(ring.submit_q.lock __cfaabi_dbg_ctx2); 648 649 // Append to the list of ready entries 650 uint32_t * tail = ring.submit_q.tail; 729 // Get now the data we definetely need 730 uint32_t * const tail = ring.submit_q.tail; 651 731 const uint32_t mask = *ring.submit_q.mask; 652 732 653 ring.submit_q.array[ (*tail) & mask ] = idx & mask; 654 __atomic_fetch_add(tail, 1ul32, __ATOMIC_SEQ_CST); 655 656 // Submit however, many entries need to be submitted 657 int ret = syscall( __NR_io_uring_enter, ring.fd, 1, 0, 0, 0p, 0); 658 if( ret < 0 ) { 659 switch((int)errno) { 660 default: 661 abort( "KERNEL ERROR: IO_URING SUBMIT - %s\n", strerror(errno) ); 662 } 663 } 664 665 // update statistics 666 #if !defined(__CFA_NO_STATISTICS__) 667 ring.submit_q.stats.submit_avg.val += 1; 668 ring.submit_q.stats.submit_avg.cnt += 1; 669 #endif 670 671 unlock(ring.submit_q.lock); 672 // Make sure that idx was submitted 673 // Be careful to not get false positive if we cycled the entire list or that someone else submitted for us 674 __cfadbg_print_safe( io, "Kernel I/O : Performed io_submit for %p, returned %d\n", active_thread(), ret ); 733 // There are 2 submission schemes, check which one we are using 734 if( ring.cltr_flags & CFA_CLUSTER_IO_POLLER_THREAD_SUBMITS ) { 735 // If the poller thread submits, then we just need to add this to the ready array 736 737 /* paranoid */ verify( idx <= mask ); 738 /* paranoid */ verify( idx != -1ul32 ); 739 740 // We need to find a spot in the ready array 741 __attribute((unused)) int len = 0; 742 __attribute((unused)) int block = 0; 743 uint32_t expected = -1ul32; 744 uint32_t ready_mask = ring.submit_q.ready_cnt - 1; 745 uint32_t off = __tls_rand(); 746 LOOKING: for() { 747 for(i; ring.submit_q.ready_cnt) { 748 uint32_t ii = (i + off) & ready_mask; 749 if( __atomic_compare_exchange_n( &ring.submit_q.ready[ii], &expected, idx, true, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED ) ) { 750 break LOOKING; 751 } 752 753 len ++; 754 } 755 756 block++; 757 yield(); 758 } 759 760 __wake_poller( ring ); 761 762 // update statistics 763 #if !defined(__CFA_NO_STATISTICS__) 764 __atomic_fetch_add( &ring.submit_q.stats.look_avg.val, len, __ATOMIC_RELAXED ); 765 __atomic_fetch_add( &ring.submit_q.stats.look_avg.block, block, __ATOMIC_RELAXED ); 766 __atomic_fetch_add( &ring.submit_q.stats.look_avg.cnt, 1, __ATOMIC_RELAXED ); 767 #endif 768 769 __cfadbg_print_safe( io, "Kernel I/O : Added %u to ready for %p\n", idx, active_thread() ); 770 } 771 else { 772 // get mutual exclusion 773 lock(ring.submit_q.lock __cfaabi_dbg_ctx2); 774 775 // Append to the list of ready entries 776 777 /* paranoid */ verify( idx <= mask ); 778 779 ring.submit_q.array[ (*tail) & mask ] = idx & mask; 780 __atomic_fetch_add(tail, 1ul32, __ATOMIC_SEQ_CST); 781 782 // Submit however, many entries need to be submitted 783 int ret = syscall( __NR_io_uring_enter, ring.fd, 1, 0, 0, 0p, 0); 784 if( ret < 0 ) { 785 switch((int)errno) { 786 default: 787 abort( "KERNEL ERROR: IO_URING SUBMIT - %s\n", strerror(errno) ); 788 } 789 } 790 791 // update statistics 792 #if !defined(__CFA_NO_STATISTICS__) 793 ring.submit_q.stats.submit_avg.val += 1; 794 ring.submit_q.stats.submit_avg.cnt += 1; 795 #endif 796 797 unlock(ring.submit_q.lock); 798 799 __cfadbg_print_safe( io, "Kernel I/O : Performed io_submit for %p, returned %d\n", active_thread(), ret ); 800 } 675 801 } 676 802 -
libcfa/src/concurrency/kernel.cfa
r856fe3e r2223c80 256 256 } 257 257 258 void ?{}(cluster & this, const char name[], Duration preemption_rate, intio_flags) with( this ) {258 void ?{}(cluster & this, const char name[], Duration preemption_rate, unsigned io_flags) with( this ) { 259 259 this.name = name; 260 260 this.preemption_rate = preemption_rate; … … 374 374 375 375 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 376 /* paranoid */ verify( kernelTLS.this_thread == thrd_dst ); 376 377 /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) < ((uintptr_t)__get_stack(thrd_dst->curr_cor)->base ) || thrd_dst->curr_cor == proc_cor, "ERROR : Destination $thread %p has been corrupted.\n StackPointer too small.\n", thrd_dst ); // add escape condition if we are setting up the processor 377 378 /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) > ((uintptr_t)__get_stack(thrd_dst->curr_cor)->limit) || thrd_dst->curr_cor == proc_cor, "ERROR : Destination $thread %p has been corrupted.\n StackPointer too large.\n", thrd_dst ); // add escape condition if we are setting up the processor … … 384 385 /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) > ((uintptr_t)__get_stack(thrd_dst->curr_cor)->limit), "ERROR : Destination $thread %p has been corrupted.\n StackPointer too large.\n", thrd_dst ); 385 386 /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) < ((uintptr_t)__get_stack(thrd_dst->curr_cor)->base ), "ERROR : Destination $thread %p has been corrupted.\n StackPointer too small.\n", thrd_dst ); 387 /* paranoid */ verify( kernelTLS.this_thread == thrd_dst ); 386 388 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 387 389 -
libcfa/src/concurrency/kernel.hfa
r856fe3e r2223c80 116 116 struct __io_data; 117 117 118 #define CFA_CLUSTER_IO_POLLER_USER_THREAD 1 << 0 119 // #define CFA_CLUSTER_IO_POLLER_KERNEL_SIDE 1 << 1 118 #define CFA_CLUSTER_IO_POLLER_USER_THREAD 1 << 0 // 0x1 119 #define CFA_CLUSTER_IO_POLLER_THREAD_SUBMITS 1 << 1 // 0x2 120 // #define CFA_CLUSTER_IO_POLLER_KERNEL_SIDE 1 << 2 // 0x4 121 #define CFA_CLUSTER_IO_BUFFLEN_OFFSET 16 120 122 121 123 //----------------------------------------------------------------------------- … … 159 161 extern Duration default_preemption(); 160 162 161 void ?{} (cluster & this, const char name[], Duration preemption_rate, intflags);163 void ?{} (cluster & this, const char name[], Duration preemption_rate, unsigned flags); 162 164 void ^?{}(cluster & this); 163 165 164 static inline void ?{} (cluster & this) { this{"Anonymous Cluster", default_preemption(), 0}; }165 static inline void ?{} (cluster & this, Duration preemption_rate) { this{"Anonymous Cluster", preemption_rate, 0}; }166 static inline void ?{} (cluster & this, const char name[]) { this{name, default_preemption(), 0}; }167 static inline void ?{} (cluster & this, intflags) { this{"Anonymous Cluster", default_preemption(), flags}; }168 static inline void ?{} (cluster & this, Duration preemption_rate, intflags) { this{"Anonymous Cluster", preemption_rate, flags}; }169 static inline void ?{} (cluster & this, const char name[], intflags) { this{name, default_preemption(), flags}; }166 static inline void ?{} (cluster & this) { this{"Anonymous Cluster", default_preemption(), 0}; } 167 static inline void ?{} (cluster & this, Duration preemption_rate) { this{"Anonymous Cluster", preemption_rate, 0}; } 168 static inline void ?{} (cluster & this, const char name[]) { this{name, default_preemption(), 0}; } 169 static inline void ?{} (cluster & this, unsigned flags) { this{"Anonymous Cluster", default_preemption(), flags}; } 170 static inline void ?{} (cluster & this, Duration preemption_rate, unsigned flags) { this{"Anonymous Cluster", preemption_rate, flags}; } 171 static inline void ?{} (cluster & this, const char name[], unsigned flags) { this{name, default_preemption(), flags}; } 170 172 171 173 static inline [cluster *&, cluster *& ] __get( cluster & this ) __attribute__((const)) { return this.node.[next, prev]; } -
libcfa/src/concurrency/kernel_private.hfa
r856fe3e r2223c80 77 77 //----------------------------------------------------------------------------- 78 78 // I/O 79 void __kernel_io_startup ( cluster &, int, bool );79 void __kernel_io_startup ( cluster &, unsigned, bool ); 80 80 void __kernel_io_finish_start( cluster & ); 81 81 void __kernel_io_prepare_stop( cluster & ); -
libcfa/src/containers/list.hfa
r856fe3e r2223c80 301 301 $prev_link(list_pos) = (Telem*) 0p; 302 302 } 303 304 static inline bool ?`is_empty(dlist(Tnode, Telem) &list) { 305 assert( &list != 0p ); 306 $dlinks(Telem) *listLinks = & list.$links; 307 if (listLinks->next.is_terminator) { 308 assert(listLinks->prev.is_terminator); 309 assert(listLinks->next.terminator); 310 assert(listLinks->prev.terminator); 311 return true; 312 } else { 313 assert(!listLinks->prev.is_terminator); 314 assert(listLinks->next.elem); 315 assert(listLinks->prev.elem); 316 return false; 317 } 318 } 319 320 static inline Telem & pop_first(dlist(Tnode, Telem) &list) { 321 assert( &list != 0p ); 322 assert( !list`is_empty ); 323 $dlinks(Telem) *listLinks = & list.$links; 324 Telem & first = *listLinks->next.elem; 325 Tnode & list_pos_first = $tempcv_e2n( first ); 326 remove(list_pos_first); 327 return first; 328 } 329 330 static inline Telem & pop_last(dlist(Tnode, Telem) &list) { 331 assert( &list != 0p ); 332 assert( !list`is_empty ); 333 $dlinks(Telem) *listLinks = & list.$links; 334 Telem & last = *listLinks->prev.elem; 335 Tnode & list_pos_last = $tempcv_e2n( last ); 336 remove(list_pos_last); 337 return last; 338 } 339 303 340 } 304 341 -
libcfa/src/exception.c
r856fe3e r2223c80 121 121 122 122 123 // TERMINATION =============================================================== 124 125 // MEMORY MANAGEMENT (still for integers) 126 // May have to move to cfa for constructors and destructors (references). 123 // MEMORY MANAGEMENT ========================================================= 127 124 128 125 // How to clean up an exception in various situations. … … 203 200 } 204 201 205 // If this isn't a rethrow (*except==0), delete the provided exception. 206 void __cfaehm_cleanup_terminate( void * except ) { 207 if ( *(void**)except ) __cfaehm_delete_exception( *(exception_t **)except ); 208 } 202 // CANCELLATION ============================================================== 209 203 210 204 // Function needed by force unwind … … 228 222 } 229 223 224 // Cancel the current stack, prefroming approprate clean-up and messaging. 225 void __cfaehm_cancel_stack( exception_t * exception ) { 226 // TODO: Detect current stack and pick a particular stop-function. 227 _Unwind_Reason_Code ret; 228 ret = _Unwind_ForcedUnwind( &this_exception_storage, _Stop_Fn, (void*)0x22 ); 229 printf("UNWIND ERROR %d after force unwind\n", ret); 230 abort(); 231 } 232 233 234 // TERMINATION =============================================================== 235 236 // If this isn't a rethrow (*except==0), delete the provided exception. 237 void __cfaehm_cleanup_terminate( void * except ) { 238 if ( *(void**)except ) __cfaehm_delete_exception( *(exception_t **)except ); 239 } 240 230 241 // The exception that is being thrown must already be stored. 231 242 static __attribute__((noreturn)) void __cfaehm_begin_unwind(void) { … … 245 256 // the whole stack. 246 257 258 // No handler found, go to the default operation. 259 // Currently this will always be a cancellation. 247 260 if ( ret == _URC_END_OF_STACK ) { 248 // No proper handler was found. This can be handled in many ways, C++ calls std::terminate. 249 // Here we force unwind the stack, basically raising a cancellation. 250 printf("Uncaught exception %p\n", &this_exception_storage); 251 252 ret = _Unwind_ForcedUnwind( &this_exception_storage, _Stop_Fn, (void*)0x22 ); 253 printf("UNWIND ERROR %d after force unwind\n", ret); 254 abort(); 261 __cfadbg_print_safe(exception, "Uncaught exception %p\n", &this_exception_storage); 262 263 __cfaehm_cancel_stack(this_exception_context()->current_exception); 255 264 } 256 265 -
libcfa/src/exception.h
r856fe3e r2223c80 38 38 39 39 40 void __cfaehm_cancel_stack(exception_t * except) __attribute__((noreturn)); 41 40 42 // Used in throw statement translation. 41 43 void __cfaehm_throw_terminate(exception_t * except) __attribute__((noreturn)); -
libcfa/src/exception.hfa
r856fe3e r2223c80 10 10 // Created On : Thu Apr 7 10:25:00 2020 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Thu Apr 7 10:25:00 202013 // Update Count : 012 // Last Modified On : Wed Apr 13 15:42:00 2020 13 // Update Count : 1 14 14 // 15 16 // WARNING: This is for documentation as it will match ANY type. 17 trait is_exception(dtype T) { 18 /* The first field must be a pointer to a virtual table. 19 * That virtual table must be a decendent of the base exception virtual table. 20 */ 21 }; 22 23 forall(dtype T | is_exception(T)) 24 inline void cancel_stack(T & except) __attribute__((noreturn)) { 25 __cfaehm_cancel_stack( (exception_t *)&except ); 26 } 15 27 16 28 // Everything below this line should be considered a patch while the exception -
libcfa/src/executor.cfa
r856fe3e r2223c80 4 4 // buffer. 5 5 6 #include < bits/containers.hfa>6 #include <containers/list.hfa> 7 7 #include <thread.hfa> 8 8 #include <stdio.h> 9 9 10 forall( dtype T )11 monitor Buffer { // unbounded buffer12 __queue_t( T ) queue; // unbounded list of work requests13 condition delay;14 }; // Buffer15 forall( dtype T | is_node(T) ) {16 void insert( Buffer( T ) & mutex buf, T * elem ) with(buf) {17 append( queue, elem ); // insert element into buffer18 signal( delay ); // restart19 } // insert20 21 T * remove( Buffer( T ) & mutex buf ) with(buf) {22 if ( queue.head != 0 ) wait( delay ); // no request to process ? => wait23 // return pop_head( queue );24 } // remove25 } // distribution26 27 10 struct WRequest { // client request, no return 28 11 void (* action)( void ); 29 WRequest * next; // intrusive queue field12 DLISTED_MGD_IMPL_IN(WRequest) 30 13 }; // WRequest 14 DLISTED_MGD_IMPL_OUT(WRequest) 31 15 32 WRequest *& get_next( WRequest & this ) { return this.next; } 33 void ?{}( WRequest & req ) with(req) { action = 0; next = 0; } 34 void ?{}( WRequest & req, void (* action)( void ) ) with(req) { req.action = action; next = 0; } 16 void ?{}( WRequest & req ) with(req) { action = 0; } 17 void ?{}( WRequest & req, void (* action)( void ) ) with(req) { req.action = action; } 35 18 bool stop( WRequest & req ) { return req.action == 0; } 36 19 void doit( WRequest & req ) { req.action(); } 20 21 monitor WRBuffer { // unbounded buffer 22 dlist( WRequest, WRequest ) queue; // unbounded list of work requests 23 condition delay; 24 }; // WRBuffer 25 26 void insert( WRBuffer & mutex buf, WRequest * elem ) with(buf) { 27 insert_last( queue, *elem ); // insert element into buffer 28 signal( delay ); // restart 29 } // insert 30 31 WRequest * remove( WRBuffer & mutex buf ) with(buf) { 32 if ( queue`is_empty ) wait( delay ); // no request to process ? => wait 33 return & pop_first( queue ); 34 } // remove 37 35 38 36 // Each worker has its own work buffer to reduce contention between client and server. Hence, work requests arrive and … … 40 38 41 39 thread Worker { 42 Buffer( WRequest )* requests;40 WRBuffer * requests; 43 41 unsigned int start, range; 44 42 }; // Worker … … 54 52 } // Worker::main 55 53 56 void ?{}( Worker & worker, cluster * wc, Buffer( WRequest )* requests, unsigned int start, unsigned int range ) {54 void ?{}( Worker & worker, cluster * wc, WRBuffer * requests, unsigned int start, unsigned int range ) { 57 55 (*get_thread(worker)){ *wc }; // create on given cluster 58 56 worker.[requests, start, range] = [requests, start, range]; … … 62 60 cluster * cluster; // if workers execute on separate cluster 63 61 processor ** processors; // array of virtual processors adding parallelism for workers 64 Buffer( WRequest ) * requests;// list of work requests62 WRBuffer * requests; // list of work requests 65 63 Worker ** workers; // array of workers executing work requests 66 64 unsigned int nprocessors, nworkers, nmailboxes; // number of mailboxes/workers/processor tasks … … 79 77 cluster = sepClus ? new( "Executor" ) : active_cluster(); 80 78 processors = (processor **)anew( nprocessors ); 81 requests = anew( nmailboxes );79 requests = (WRBuffer *)anew( nmailboxes ); 82 80 workers = (Worker **)anew( nworkers ); 83 81 … … 141 139 for ( i; 3000 ) { 142 140 send( exector, workie ); 143 if ( i % 100 ) yield(); 141 if ( i % 100 == 0 ) { 142 // fprintf( stderr, "%d\n", i ); 143 yield(); 144 } 144 145 } // for 145 146 } -
tests/exceptions/.expect/resume.txt
r856fe3e r2223c80 4 4 end of try clause 5 5 Exiting: simple try clause 6 7 catch-all 6 8 7 9 throwing child exception -
tests/exceptions/.expect/terminate.txt
r856fe3e r2223c80 3 3 simple catch 4 4 Exiting: simple catch clause 5 6 catch-all 5 7 6 8 throwing child exception -
tests/exceptions/resume.cfa
r856fe3e r2223c80 19 19 loud_exit a = "simple catch clause"; 20 20 printf("simple catch\n"); 21 } 22 printf("\n"); 23 24 // Throw catch-all test. 25 try { 26 throwResume &(zen){}; 27 } catchResume (exception_t * error) { 28 printf("catch-all\n"); 21 29 } 22 30 printf("\n"); -
tests/exceptions/terminate.cfa
r856fe3e r2223c80 17 17 printf("end of try clause\n"); 18 18 } catch (zen * error) { 19 19 loud_exit a = "simple catch clause"; 20 20 printf("simple catch\n"); 21 } 22 printf("\n"); 23 24 // Throw catch-all test. 25 try { 26 throw &(zen){}; 27 } catch (exception_t * error) { 28 printf("catch-all\n"); 21 29 } 22 30 printf("\n"); -
tests/list/.expect/dlist-insert-remove.txt
r856fe3e r2223c80 1464 1464 0.7 1465 1465 - 1466 1467 ~~~~~~~~~~ End removal tests on Headed List: First ~~~~~~~~~~ 1468 1469 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1470 Test 16-i. Modifying Freds on MINE 1471 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1472 ==== fred by MINE before 1473 1.7 1474 2.7 1475 3.7 1476 - 1477 1.7 1478 - 1479 3.7 1480 - 1481 3.7 1482 2.7 1483 1.7 1484 - 1485 ==== fred by YOURS before 1486 1.7 1487 2.7 1488 3.7 1489 - 1490 1.7 1491 - 1492 3.7 1493 - 1494 3.7 1495 2.7 1496 1.7 1497 - 1498 ==== fred by MINE after 1499 2.7 1500 3.7 1501 - 1502 2.7 1503 - 1504 3.7 1505 - 1506 3.7 1507 2.7 1508 - 1509 ==== fred by YOURS after 1510 1.7 1511 2.7 1512 3.7 1513 - 1514 1.7 1515 - 1516 3.7 1517 - 1518 3.7 1519 2.7 1520 1.7 1521 - 1522 ==== fred by MINE after 1523 1.7 1524 - 1525 1.7 1526 - 1527 - 1528 - 1529 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1530 Test 16-ii. Modifying Freds on YOURS 1531 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1532 ==== fred by MINE before 1533 1.7 1534 2.7 1535 3.7 1536 - 1537 1.7 1538 - 1539 3.7 1540 - 1541 3.7 1542 2.7 1543 1.7 1544 - 1545 ==== fred by YOURS before 1546 1.7 1547 2.7 1548 3.7 1549 - 1550 1.7 1551 - 1552 3.7 1553 - 1554 3.7 1555 2.7 1556 1.7 1557 - 1558 ==== fred by MINE after 1559 1.7 1560 2.7 1561 3.7 1562 - 1563 1.7 1564 - 1565 3.7 1566 - 1567 3.7 1568 2.7 1569 1.7 1570 - 1571 ==== fred by YOURS after 1572 2.7 1573 3.7 1574 - 1575 2.7 1576 - 1577 3.7 1578 - 1579 3.7 1580 2.7 1581 - 1582 ==== fred by YOURS after 1583 1.7 1584 - 1585 1.7 1586 - 1587 - 1588 - 1589 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1590 Test 16-iii. Modifying Maries 1591 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1592 ==== mary before 1593 1.7 1594 2.7 1595 3.7 1596 - 1597 1.7 1598 - 1599 3.7 1600 - 1601 3.7 1602 2.7 1603 1.7 1604 - 1605 ==== mary after 1606 2.7 1607 3.7 1608 - 1609 2.7 1610 - 1611 3.7 1612 - 1613 3.7 1614 2.7 1615 - 1616 ==== mary after 1617 1.7 1618 - 1619 1.7 1620 - 1621 - 1622 - 1623 1624 ~~~~~~~~~~ End removal tests on Headed List: Last ~~~~~~~~~~ 1625 1626 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1627 Test 17-i. Modifying Freds on MINE 1628 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1629 ==== fred by MINE before 1630 1.7 1631 2.7 1632 3.7 1633 - 1634 1.7 1635 - 1636 3.7 1637 - 1638 3.7 1639 2.7 1640 1.7 1641 - 1642 ==== fred by YOURS before 1643 1.7 1644 2.7 1645 3.7 1646 - 1647 1.7 1648 - 1649 3.7 1650 - 1651 3.7 1652 2.7 1653 1.7 1654 - 1655 ==== fred by MINE after 1656 1.7 1657 2.7 1658 - 1659 1.7 1660 - 1661 2.7 1662 - 1663 2.7 1664 1.7 1665 - 1666 ==== fred by YOURS after 1667 1.7 1668 2.7 1669 3.7 1670 - 1671 1.7 1672 - 1673 3.7 1674 - 1675 3.7 1676 2.7 1677 1.7 1678 - 1679 ==== fred by MINE after 1680 3.7 1681 - 1682 3.7 1683 - 1684 - 1685 - 1686 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1687 Test 17-ii. Modifying Freds on YOURS 1688 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1689 ==== fred by MINE before 1690 1.7 1691 2.7 1692 3.7 1693 - 1694 1.7 1695 - 1696 3.7 1697 - 1698 3.7 1699 2.7 1700 1.7 1701 - 1702 ==== fred by YOURS before 1703 1.7 1704 2.7 1705 3.7 1706 - 1707 1.7 1708 - 1709 3.7 1710 - 1711 3.7 1712 2.7 1713 1.7 1714 - 1715 ==== fred by MINE after 1716 1.7 1717 2.7 1718 3.7 1719 - 1720 1.7 1721 - 1722 3.7 1723 - 1724 3.7 1725 2.7 1726 1.7 1727 - 1728 ==== fred by YOURS after 1729 1.7 1730 2.7 1731 - 1732 1.7 1733 - 1734 2.7 1735 - 1736 2.7 1737 1.7 1738 - 1739 ==== fred by YOURS after 1740 3.7 1741 - 1742 3.7 1743 - 1744 - 1745 - 1746 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1747 Test 17-iii. Modifying Maries 1748 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1749 ==== mary before 1750 1.7 1751 2.7 1752 3.7 1753 - 1754 1.7 1755 - 1756 3.7 1757 - 1758 3.7 1759 2.7 1760 1.7 1761 - 1762 ==== mary after 1763 1.7 1764 2.7 1765 - 1766 1.7 1767 - 1768 2.7 1769 - 1770 2.7 1771 1.7 1772 - 1773 ==== mary after 1774 3.7 1775 - 1776 3.7 1777 - 1778 - 1779 - -
tests/list/dlist-insert-remove.cfa
r856fe3e r2223c80 1187 1187 //////////////////////////////////////////////////////////// 1188 1188 // 1189 // Section 4f 1190 // 1191 // Test cases of pop_first, pop_last 1192 // 1193 // Example of call-side user code 1194 // 1195 //////////////////////////////////////////////////////////// 1196 1197 // These cases assume element removal at first-last is correct 1198 1199 void test__pop_first__fred_mine() { 1200 1201 fred f1 = {1.7}; 1202 fred f2 = {2.7}; 1203 fred f3 = {3.7}; 1204 1205 dlist(fred_in_mine, fred) flm; 1206 insert_last(flm, f1); 1207 insert_last(flm, f2); 1208 insert_last(flm, f3); 1209 1210 dlist(fred_in_yours, fred) fly; 1211 insert_last(fly, f1); 1212 insert_last(fly, f2); 1213 insert_last(fly, f3); 1214 1215 printMyFreddies(flm`first, flm`last, 1); // 1.7, 2.7, 3.7; 1.7; 3.7; 3.7, 2.7, 1.7 1216 printYourFreddies(fly`first, fly`last, 1); // 1.7, 2.7, 3.7; 1.7; 3.7; 3.7, 2.7, 1.7 1217 1218 verify(validate(fly)); 1219 verify(validate(flm)); 1220 1221 fred & popped = pop_first(flm); 1222 1223 verify(validate(fly)); 1224 verify(validate(flm)); 1225 1226 printMyFreddies(flm`first, flm`last, 0); // 2.7, 3.7; 2.7; 3.7; 3.7, 2.7 (modified) 1227 printYourFreddies(fly`first, fly`last, 0); // 1.7, 2.7, 3.7; 1.7; 3.7; 3.7, 2.7, 1.7 (unmodified) 1228 1229 // observe f1 is now solo in mine; in yours, it was just traversed 1230 printMyFreddies(f1, *0p, 0); // 1.7; 1.7; ; 1231 1232 assert( &popped == & f1 ); 1233 } 1234 1235 void test__pop_first__fred_yours() { 1236 1237 fred f1 = {1.7}; 1238 fred f2 = {2.7}; 1239 fred f3 = {3.7}; 1240 1241 dlist(fred_in_mine, fred) flm; 1242 insert_last(flm, f1); 1243 insert_last(flm, f2); 1244 insert_last(flm, f3); 1245 1246 dlist(fred_in_yours, fred) fly; 1247 insert_last(fly, f1); 1248 insert_last(fly, f2); 1249 insert_last(fly, f3); 1250 1251 printMyFreddies(flm`first, flm`last, 1); // 1.7, 2.7, 3.7; 1.7; 3.7; 3.7, 2.7, 1.7 1252 printYourFreddies(fly`first, fly`last, 1); // 1.7, 2.7, 3.7; 1.7; 3.7; 3.7, 2.7, 1.7 1253 1254 verify(validate(fly)); 1255 verify(validate(flm)); 1256 1257 fred & popped = pop_first(fly); 1258 1259 verify(validate(fly)); 1260 verify(validate(flm)); 1261 1262 printMyFreddies(flm`first, flm`last, 0); // 1.7, 2.7, 3.7; 1.7; 3.7; 3.7, 2.7, 1.7 (unmodified) 1263 printYourFreddies(fly`first, fly`last, 0); // 2.7, 3.7; 2.7; 3.7; 3.7, 2.7 (modified) 1264 1265 // observe f1 is now solo in yours; in mine, it was just traversed 1266 printYourFreddies(f1, *0p, 0); // 1.7; 1.7; ; 1267 1268 assert( &popped == &f1 ); 1269 } 1270 1271 void test__pop_first__maries() { 1272 1273 mary m1 = {1.7}; 1274 mary m2 = {2.7}; 1275 mary m3 = {3.7}; 1276 1277 dlist(mary, mary) ml; 1278 insert_last(ml, m1); 1279 insert_last(ml, m2); 1280 insert_last(ml, m3); 1281 1282 printMariatheotokos(ml`first, ml`last, 1); // 1.7, 2.7, 3.7; 1.7; 3.7; 3.7, 2.7, 1.7 1283 1284 verify(validate(ml)); 1285 1286 mary & popped = pop_first(ml); 1287 1288 verify(validate(ml)); 1289 1290 printMariatheotokos(ml`first, ml`last, 0); // 2.7, 3.7; 2.7; 3.7; 3.7, 2.7 (modified) 1291 1292 // observe m1 is now solo 1293 printMariatheotokos(m1, *0p, 0); // 1.7; 1.7; ; 1294 1295 assert( &popped == &m1 ); 1296 } 1297 1298 void test__pop_last__fred_mine() { 1299 1300 fred f1 = {1.7}; 1301 fred f2 = {2.7}; 1302 fred f3 = {3.7}; 1303 1304 dlist(fred_in_mine, fred) flm; 1305 insert_last(flm, f1); 1306 insert_last(flm, f2); 1307 insert_last(flm, f3); 1308 1309 dlist(fred_in_yours, fred) fly; 1310 insert_last(fly, f1); 1311 insert_last(fly, f2); 1312 insert_last(fly, f3); 1313 1314 printMyFreddies(flm`first, flm`last, 1); // 1.7, 2.7, 3.7; 1.7; 3.7; 3.7, 2.7, 1.7 1315 printYourFreddies(fly`first, fly`last, 1); // 1.7, 2.7, 3.7; 1.7; 3.7; 3.7, 2.7, 1.7 1316 1317 verify(validate(fly)); 1318 verify(validate(flm)); 1319 1320 fred & popped = pop_last(flm); 1321 1322 verify(validate(fly)); 1323 verify(validate(flm)); 1324 1325 printMyFreddies(flm`first, flm`last, 0); // 1.7, 2.7; 1.7; 2.7; 2.7, 1.7 (modified) 1326 printYourFreddies(fly`first, fly`last, 0); // 1.7, 2.7, 3.7; 1.7; 3.7; 3.7, 2.7, 1.7 (unmodified) 1327 1328 // observe f3 is now solo in mine; in yours, it was just traversed 1329 printMyFreddies(f3, *0p, 0); // 3.7; 3.7; ; 1330 1331 assert( &popped == & f3 ); 1332 } 1333 1334 void test__pop_last__fred_yours() { 1335 1336 fred f1 = {1.7}; 1337 fred f2 = {2.7}; 1338 fred f3 = {3.7}; 1339 1340 dlist(fred_in_mine, fred) flm; 1341 insert_last(flm, f1); 1342 insert_last(flm, f2); 1343 insert_last(flm, f3); 1344 1345 dlist(fred_in_yours, fred) fly; 1346 insert_last(fly, f1); 1347 insert_last(fly, f2); 1348 insert_last(fly, f3); 1349 1350 printMyFreddies(flm`first, flm`last, 1); // 1.7, 2.7, 3.7; 1.7; 3.7; 3.7, 2.7, 1.7 1351 printYourFreddies(fly`first, fly`last, 1); // 1.7, 2.7, 3.7; 1.7; 3.7; 3.7, 2.7, 1.7 1352 1353 verify(validate(fly)); 1354 verify(validate(flm)); 1355 1356 fred & popped = pop_last(fly); 1357 1358 verify(validate(fly)); 1359 verify(validate(flm)); 1360 1361 printMyFreddies(flm`first, flm`last, 0); // 1.7, 2.7, 3.7; 1.7; 3.7; 3.7, 2.7, 1.7 (unmodified) 1362 printYourFreddies(fly`first, fly`last, 0); // 1.7, 2.7; 1.7; 2.7; 2.7, 1.7 (modified) 1363 1364 // observe f3 is now solo in yours; in mine, it was just traversed 1365 printYourFreddies(f3, *0p, 0); // 3.7; 3.7; ; 1366 1367 assert( &popped == & f3 ); 1368 } 1369 1370 void test__pop_last__maries() { 1371 1372 mary m1 = {1.7}; 1373 mary m2 = {2.7}; 1374 mary m3 = {3.7}; 1375 1376 dlist(mary, mary) ml; 1377 insert_last(ml, m1); 1378 insert_last(ml, m2); 1379 insert_last(ml, m3); 1380 1381 printMariatheotokos(ml`first, ml`last, 1); // 1.7, 2.7, 3.7; 1.7; 3.7; 3.7, 2.7, 1.7 1382 1383 verify(validate(ml)); 1384 1385 mary & popped = pop_last(ml); 1386 1387 verify(validate(ml)); 1388 1389 printMariatheotokos(ml`first, ml`last, 0); // 1.7, 1.7; 1.7; 2.7; 2.7, 1.7 (modified) 1390 1391 // observe m1 is now solo 1392 printMariatheotokos(m3, *0p, 0); // 3.7; 3.7; ; 1393 1394 assert( &popped == &m3 ); 1395 } 1396 1397 //////////////////////////////////////////////////////////// 1398 // 1189 1399 // Section 5 1190 1400 // … … 1422 1632 test__remove_of_sole__mary(); 1423 1633 1634 sout | ""; 1635 sout | "~~~~~~~~~~ End removal tests on Headed List: First ~~~~~~~~~~"; 1636 sout | ""; 1637 1638 sout | "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"; 1639 sout | "Test 16-i. Modifying Freds on MINE"; 1640 sout | "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"; 1641 test__pop_first__fred_mine(); 1642 1643 sout | "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"; 1644 sout | "Test 16-ii. Modifying Freds on YOURS"; 1645 sout | "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"; 1646 test__pop_first__fred_yours(); 1647 1648 sout | "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"; 1649 sout | "Test 16-iii. Modifying Maries"; 1650 sout | "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"; 1651 test__pop_first__maries(); 1652 1653 sout | ""; 1654 sout | "~~~~~~~~~~ End removal tests on Headed List: Last ~~~~~~~~~~"; 1655 sout | ""; 1656 1657 sout | "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"; 1658 sout | "Test 17-i. Modifying Freds on MINE"; 1659 sout | "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"; 1660 test__pop_last__fred_mine(); 1661 1662 sout | "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"; 1663 sout | "Test 17-ii. Modifying Freds on YOURS"; 1664 sout | "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"; 1665 test__pop_last__fred_yours(); 1666 1667 sout | "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"; 1668 sout | "Test 17-iii. Modifying Maries"; 1669 sout | "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"; 1670 test__pop_last__maries(); 1671 1424 1672 return 0; 1425 1673 } -
tools/build/push2dist.sh
r856fe3e r2223c80 2 2 3 3 hash="$1" 4 bwlim="$2" 4 5 valid=$(distcc -j 2> /dev/null) 5 6 # if test "${valid}" != 0 … … 24 25 function push() { 25 26 ssh ${host} "mkdir -p ~/.cfadistcc/${hash}/" 26 rsync - a ${dV} ${files} ${host}:~/.cfadistcc/${hash}/.27 rsync --bwlimit=${bwlim} -a ${dV} ${files} ${host}:~/.cfadistcc/${hash}/. 27 28 } 28 29
Note: See TracChangeset
for help on using the changeset viewer.