Changes in / [2223c80:856fe3e]
- Files:
-
- 26 edited
-
benchmark/io/readv.cfa (modified) (3 diffs)
-
configure (modified) (3 diffs)
-
configure.ac (modified) (1 diff)
-
doc/proposals/vtable.md (modified) (2 diffs)
-
libcfa/Makefile.in (modified) (1 diff)
-
libcfa/configure (modified) (5 diffs)
-
libcfa/configure.ac (modified) (2 diffs)
-
libcfa/prelude/Makefile.am (modified) (1 diff)
-
libcfa/prelude/Makefile.in (modified) (2 diffs)
-
libcfa/src/Makefile.in (modified) (1 diff)
-
libcfa/src/concurrency/io.cfa (modified) (21 diffs)
-
libcfa/src/concurrency/kernel.cfa (modified) (3 diffs)
-
libcfa/src/concurrency/kernel.hfa (modified) (2 diffs)
-
libcfa/src/concurrency/kernel_private.hfa (modified) (1 diff)
-
libcfa/src/containers/list.hfa (modified) (1 diff)
-
libcfa/src/exception.c (modified) (4 diffs)
-
libcfa/src/exception.h (modified) (1 diff)
-
libcfa/src/exception.hfa (modified) (1 diff)
-
libcfa/src/executor.cfa (modified) (6 diffs)
-
tests/exceptions/.expect/resume.txt (modified) (1 diff)
-
tests/exceptions/.expect/terminate.txt (modified) (1 diff)
-
tests/exceptions/resume.cfa (modified) (1 diff)
-
tests/exceptions/terminate.cfa (modified) (1 diff)
-
tests/list/.expect/dlist-insert-remove.txt (modified) (1 diff)
-
tests/list/dlist-insert-remove.cfa (modified) (2 diffs)
-
tools/build/push2dist.sh (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
benchmark/io/readv.cfa
r2223c80 r856fe3e 59 59 unsigned long int nthreads = 2; 60 60 unsigned long int nprocs = 1; 61 unsigned flags = 0; 62 unsigned sublen = 16; 61 int flags = 0; 63 62 64 63 arg_loop: 65 64 for(;;) { 66 65 static struct option options[] = { 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'}, 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'}, 74 71 {0, 0, 0, 0} 75 72 }; 76 73 77 74 int idx = 0; 78 int opt = getopt_long(argc, argv, "d:t:p:b:u sl:", options, &idx);75 int opt = getopt_long(argc, argv, "d:t:p:b:u", options, &idx); 79 76 80 77 const char * arg = optarg ? optarg : ""; … … 116 113 flags |= CFA_CLUSTER_IO_POLLER_USER_THREAD; 117 114 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;129 115 // Other cases 130 116 default: /* ? */ … … 137 123 fprintf(stderr, " -p, --nprocs=NPROCS Number of kernel threads\n"); 138 124 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");141 125 exit(EXIT_FAILURE); 142 126 } -
configure
r2223c80 r856fe3e 802 802 with_cfa_name 803 803 enable_distcc 804 with_bwlimit805 804 with_target_hosts 806 805 enable_gprofiler … … 1482 1481 --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) 1483 1482 --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 builds1485 1483 --with-target-hosts=HOSTS HOSTS comma seperated list of hosts to build for, format ARCH:debug|nodebug|nolib 1486 1484 --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use … … 3200 3198 else 3201 3199 enable_distcc=no 3202 fi3203 3204 3205 3206 # Check whether --with-bwlimit was given.3207 if test "${with_bwlimit+set}" = set; then :3208 withval=$with_bwlimit;3209 3200 fi 3210 3201 -
configure.ac
r2223c80 r856fe3e 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 [], [])70 66 71 67 AM_CONDITIONAL([ENABLE_DISTCC], [test x$enable_distcc = xyes]) -
doc/proposals/vtable.md
r2223c80 r856fe3e 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 Access241 This requires that the resolution scope (see below) is at the type level or242 has explicate points with names. These are the tables and table names used243 here.244 245 The system already knows where to find the virtual table and the object. If246 the tables have particular identities, or on the user side names, then it is247 meaningful to check if a binding virtual table is the same* as another. The248 main use of this is virtual table declarations also give the type they bind249 and if a binding table matches a known table then the underlyind object in the250 trait object must be of that type.251 252 * By identity, by value would work and in some senses be more flexiable. But253 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 virtual256 tables (see below); the ability to recover the underlying object. Or a pointer257 of the approprate type it which both reflects the implementation and gives a258 convenent way to encode the boolean/conditional aspect of the operation which259 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. The262 cast is traditional and would definitely fit if a single pointer repersents263 a trait object with the virtual table as part of the object. However for a264 double pointer field access might be more approprate. By this system though265 it is not the type that is used as the identifier but the virtual table. If266 there is one table per type than it becomes equivilant again. Otherwise the267 table has to be used as the identifier and the type is just a result of that268 which seems important for syntax.269 239 270 240 Hierarchy … … 590 560 be used in only some of the declarations. 591 561 592 trait combiner fee = {summation_instance, sum};562 trait combiner fee = (summation_instance, sum); 593 563 trait combiner foe = summation_instance; 594 564 -
libcfa/Makefile.in
r2223c80 r856fe3e 253 253 DEFS = @DEFS@ 254 254 DEPDIR = @DEPDIR@ 255 DIST_BWLIMIT = @DIST_BWLIMIT@256 255 DLLTOOL = @DLLTOOL@ 257 256 DRIVER_DIR = @DRIVER_DIR@ -
libcfa/configure
r2223c80 r856fe3e 707 707 CONFIG_CFLAGS 708 708 ARCH_FLAGS 709 DIST_BWLIMIT710 709 CFADIR_HASH 711 710 LOCAL_CC1 … … 790 789 enable_silent_rules 791 790 enable_distcc 792 with_bwlimit793 791 with_cfa_name 794 792 enable_static … … 1467 1465 --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] 1468 1466 --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 builds1470 1467 --with-cfa-name=NAME NAME too which cfa will be installed 1471 1468 --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use … … 3050 3047 3051 3048 3052 3053 # Check whether --with-bwlimit was given.3054 if test "${with_bwlimit+set}" = set; then :3055 withval=$with_bwlimit; DIST_BWLIMIT=$withval3056 else3057 DIST_BWLIMIT=03058 fi3059 3060 3061 3049 echo -n "checking for distributated build... " 3062 3050 if test x$enable_distcc = xno; then … … 3082 3070 ENABLE_DISTCC_FALSE= 3083 3071 fi 3084 3085 3072 3086 3073 -
libcfa/configure.ac
r2223c80 r856fe3e 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 37 33 echo -n "checking for distributated build... " 38 34 if test x$enable_distcc = xno; then … … 59 55 AC_SUBST(CFADIR_HASH) 60 56 AC_SUBST(CFA_VERSION) 61 AC_SUBST(DIST_BWLIMIT)62 57 63 58 #============================================================================== -
libcfa/prelude/Makefile.am
r2223c80 r856fe3e 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@ @DIST_BWLIMIT@74 ${AM_V_GEN}$(srcdir)/../../tools/build/push2dist.sh @CFADIR_HASH@ 75 75 @echo "Dummy file to track distribution to remote hosts" > ${@} 76 76 -
libcfa/prelude/Makefile.in
r2223c80 r856fe3e 215 215 DEFS = @DEFS@ 216 216 DEPDIR = @DEPDIR@ 217 DIST_BWLIMIT = @DIST_BWLIMIT@218 217 DLLTOOL = @DLLTOOL@ 219 218 DRIVER_DIR = @DRIVER_DIR@ … … 656 655 657 656 @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 658 @ENABLE_DISTCC_TRUE@ ${AM_V_GEN}$(srcdir)/../../tools/build/push2dist.sh @CFADIR_HASH@ @DIST_BWLIMIT@657 @ENABLE_DISTCC_TRUE@ ${AM_V_GEN}$(srcdir)/../../tools/build/push2dist.sh @CFADIR_HASH@ 659 658 @ENABLE_DISTCC_TRUE@ @echo "Dummy file to track distribution to remote hosts" > ${@} 660 659 -
libcfa/src/Makefile.in
r2223c80 r856fe3e 307 307 DEFS = @DEFS@ 308 308 DEPDIR = @DEPDIR@ 309 DIST_BWLIMIT = @DIST_BWLIMIT@310 309 DLLTOOL = @DLLTOOL@ 311 310 DRIVER_DIR = @DRIVER_DIR@ -
libcfa/src/concurrency/io.cfa
r2223c80 r856fe3e 18 18 19 19 #include "kernel.hfa" 20 #include "bitmanip.hfa"21 20 22 21 #if !defined(HAVE_LINUX_IO_URING_H) 23 void __kernel_io_startup( cluster &, unsigned, bool ) {22 void __kernel_io_startup( cluster &, int, bool ) { 24 23 // Nothing to do without io_uring 25 24 } … … 92 91 struct __io_poller_fast { 93 92 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; 99 100 (this.thrd){ "Fast I/O Poller", cltr }; 100 101 } … … 125 126 // Like head/tail but not seen by the kernel 126 127 volatile uint32_t alloc; 127 volatile uint32_t * ready; 128 uint32_t ready_cnt; 128 volatile uint32_t ready; 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;152 147 } stats; 153 148 #endif … … 197 192 void * stack; 198 193 pthread_t kthrd; 199 volatile bool blocked;200 194 } slow; 201 195 __io_poller_fast fast; … … 207 201 // I/O Startup / Shutdown logic 208 202 //============================================================================================= 209 void __kernel_io_startup( cluster & this, unsignedio_flags, bool main_cluster ) {203 void __kernel_io_startup( cluster & this, int io_flags, bool main_cluster ) { 210 204 this.io = malloc(); 211 205 … … 280 274 sq.array = ( uint32_t *)(((intptr_t)sq.ring_ptr) + params.sq_off.array); 281 275 sq.alloc = *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 } 276 sq.ready = *sq.tail; 295 277 296 278 // completion queue … … 325 307 this.io->submit_q.stats.submit_avg.cnt = 0; 326 308 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;330 309 this.io->completion_q.stats.completed_avg.val = 0; 331 310 this.io->completion_q.stats.completed_avg.slow_cnt = 0; … … 347 326 // Create the poller thread 348 327 __cfadbg_print_safe(io_core, "Kernel I/O : Creating slow poller for cluter %p\n", &this); 349 this.io->poller.slow.blocked = false;350 328 this.io->poller.slow.stack = __create_pthread( &this.io->poller.slow.kthrd, __io_poller_slow, &this ); 351 329 } … … 369 347 if( this.io->cltr_flags & CFA_CLUSTER_IO_POLLER_USER_THREAD ) { 370 348 with( this.io->poller.fast ) { 349 /* paranoid */ verify( waiting ); // The thread shouldn't be in a system call 371 350 /* paranoid */ verify( this.procs.head == 0p || &this == mainCluster ); 372 351 /* paranoid */ verify( this.idles.head == 0p || &this == mainCluster ); 373 352 374 353 // We need to adjust the clean-up based on where the thread is 375 if( thrd. state == Ready || thrd.preempted != __NO_PREEMPTION ) {354 if( thrd.preempted != __NO_PREEMPTION ) { 376 355 377 356 // This is the tricky case 378 357 // The thread was preempted and now it is on the ready queue 358 /* paranoid */ verify( thrd.state == Active ); // The thread better be in this state 379 359 /* paranoid */ verify( thrd.next == 1p ); // The thread should be the last on the list 380 360 /* paranoid */ verify( this.ready_queue.head == &thrd ); // The thread should be the only thing on the list … … 425 405 if(this.print_stats) { 426 406 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 434 407 __cfaabi_bits_print_safe( STDERR_FILENO, 435 408 "----- I/O uRing Stats -----\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", 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", 444 414 submit_avg.cnt, 445 415 ((double)submit_avg.val) / submit_avg.cnt, 446 416 (100.0 * submit_avg.block) / submit_avg.cnt, 447 look_avg.cnt,448 lavgv,449 lavgb,450 417 completed_avg.slow_cnt + completed_avg.fast_cnt, 451 418 completed_avg.slow_cnt, completed_avg.fast_cnt, … … 474 441 close(this.io->fd); 475 442 476 free( this.io->submit_q.ready ); // Maybe null, doesn't matter477 443 free( this.io ); 478 444 } … … 488 454 // Process a single completion message from the io_uring 489 455 // This is NOT thread-safe 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); 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); 522 458 if( ret < 0 ) { 523 459 switch((int)errno) { … … 561 497 __atomic_fetch_add( ring.completion_q.head, count, __ATOMIC_RELAXED ); 562 498 563 return [count, count > 0 || to_submit > 0];499 return count; 564 500 } 565 501 … … 583 519 if( ring.cltr_flags & CFA_CLUSTER_IO_POLLER_USER_THREAD ) { 584 520 while(!__atomic_load_n(&ring.done, __ATOMIC_SEQ_CST)) { 585 586 __atomic_store_n( &ring.poller.slow.blocked, true, __ATOMIC_SEQ_CST );587 588 521 // In the user-thread approach drain and if anything was drained, 589 522 // batton pass to the user-thread 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 ); 523 int count = __drain_io( ring, &mask, 1, true ); 595 524 596 525 // Update statistics … … 600 529 #endif 601 530 602 if( again) {531 if(count > 0) { 603 532 __cfadbg_print_safe(io_core, "Kernel I/O : Moving to ring %p to fast poller\n", &ring); 604 533 __unpark( &ring.poller.fast.thrd __cfaabi_dbg_ctx2 ); … … 610 539 while(!__atomic_load_n(&ring.done, __ATOMIC_SEQ_CST)) { 611 540 //In the naive approach, just poll the io completion queue directly 612 int count; 613 bool again; 614 [count, again] = __drain_io( ring, &mask, 1, true ); 541 int count = __drain_io( ring, &mask, 1, true ); 615 542 616 543 // Update statistics … … 639 566 // Then loop until we need to start 640 567 while(!__atomic_load_n(&this.ring->done, __ATOMIC_SEQ_CST)) { 641 642 568 // Drain the io 643 int count; 644 bool again; 645 [count, again] = __drain_io( *this.ring, 0p, 0, false ); 646 647 if(!again) reset++; 569 this.waiting = false; 570 int count = __drain_io( *this.ring, 0p, 0, false ); 571 reset += count > 0 ? 1 : 0; 648 572 649 573 // Update statistics … … 653 577 #endif 654 578 655 // If we got something, just yield and check again579 this.waiting = true; 656 580 if(reset < 5) { 581 // If we got something, just yield and check again 657 582 yield(); 658 583 } 659 // We didn't get anything baton pass to the slow poller660 584 else { 585 // We didn't get anything baton pass to the slow poller 661 586 __cfadbg_print_safe(io_core, "Kernel I/O : Moving to ring %p to slow poller\n", &this.ring); 587 post( this.ring->poller.sem ); 588 park( __cfaabi_dbg_ctx ); 662 589 reset = 0; 663 664 // wake up the slow poller665 post( this.ring->poller.sem );666 667 // park this thread668 park( __cfaabi_dbg_ctx );669 590 } 670 591 } 671 592 672 593 __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 );681 594 } 682 595 … … 719 632 uint32_t idx = __atomic_fetch_add(&ring.submit_q.alloc, 1ul32, __ATOMIC_SEQ_CST); 720 633 721 // Mask the idx now to allow make everything easier to check 722 idx &= *ring.submit_q.mask; 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 ); 723 640 724 641 // Return the sqe 725 return [&ring.submit_q.sqes[ idx ], idx];642 return [&ring.submit_q.sqes[ idx & (*ring.submit_q.mask)], idx]; 726 643 } 727 644 728 645 static inline void __submit( struct __io_data & ring, uint32_t idx ) { 729 // Get now the data we definetely need 730 uint32_t * const tail = ring.submit_q.tail; 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; 731 651 const uint32_t mask = *ring.submit_q.mask; 732 652 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(); 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) ); 758 662 } 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 } 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 ); 801 675 } 802 676 -
libcfa/src/concurrency/kernel.cfa
r2223c80 r856fe3e 256 256 } 257 257 258 void ?{}(cluster & this, const char name[], Duration preemption_rate, unsignedio_flags) with( this ) {258 void ?{}(cluster & this, const char name[], Duration preemption_rate, int 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 );377 376 /* 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 378 377 /* 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 … … 385 384 /* 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 ); 386 385 /* 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 );388 386 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 389 387 -
libcfa/src/concurrency/kernel.hfa
r2223c80 r856fe3e 116 116 struct __io_data; 117 117 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 118 #define CFA_CLUSTER_IO_POLLER_USER_THREAD 1 << 0 119 // #define CFA_CLUSTER_IO_POLLER_KERNEL_SIDE 1 << 1 122 120 123 121 //----------------------------------------------------------------------------- … … 161 159 extern Duration default_preemption(); 162 160 163 void ?{} (cluster & this, const char name[], Duration preemption_rate, unsignedflags);161 void ?{} (cluster & this, const char name[], Duration preemption_rate, int flags); 164 162 void ^?{}(cluster & this); 165 163 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, unsignedflags) { this{"Anonymous Cluster", default_preemption(), flags}; }170 static inline void ?{} (cluster & this, Duration preemption_rate, unsignedflags) { this{"Anonymous Cluster", preemption_rate, flags}; }171 static inline void ?{} (cluster & this, const char name[], unsignedflags) { this{name, default_preemption(), flags}; }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, int flags) { this{"Anonymous Cluster", default_preemption(), flags}; } 168 static inline void ?{} (cluster & this, Duration preemption_rate, int flags) { this{"Anonymous Cluster", preemption_rate, flags}; } 169 static inline void ?{} (cluster & this, const char name[], int flags) { this{name, default_preemption(), flags}; } 172 170 173 171 static inline [cluster *&, cluster *& ] __get( cluster & this ) __attribute__((const)) { return this.node.[next, prev]; } -
libcfa/src/concurrency/kernel_private.hfa
r2223c80 r856fe3e 77 77 //----------------------------------------------------------------------------- 78 78 // I/O 79 void __kernel_io_startup ( cluster &, unsigned, bool );79 void __kernel_io_startup ( cluster &, int, bool ); 80 80 void __kernel_io_finish_start( cluster & ); 81 81 void __kernel_io_prepare_stop( cluster & ); -
libcfa/src/containers/list.hfa
r2223c80 r856fe3e 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 340 303 } 341 304 -
libcfa/src/exception.c
r2223c80 r856fe3e 121 121 122 122 123 // MEMORY MANAGEMENT ========================================================= 123 // TERMINATION =============================================================== 124 125 // MEMORY MANAGEMENT (still for integers) 126 // May have to move to cfa for constructors and destructors (references). 124 127 125 128 // How to clean up an exception in various situations. … … 200 203 } 201 204 202 // CANCELLATION ============================================================== 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 } 203 209 204 210 // Function needed by force unwind … … 222 228 } 223 229 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 241 230 // The exception that is being thrown must already be stored. 242 231 static __attribute__((noreturn)) void __cfaehm_begin_unwind(void) { … … 256 245 // the whole stack. 257 246 258 // No handler found, go to the default operation.259 // Currently this will always be a cancellation.260 247 if ( ret == _URC_END_OF_STACK ) { 261 __cfadbg_print_safe(exception, "Uncaught exception %p\n", &this_exception_storage); 262 263 __cfaehm_cancel_stack(this_exception_context()->current_exception); 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(); 264 255 } 265 256 -
libcfa/src/exception.h
r2223c80 r856fe3e 38 38 39 39 40 void __cfaehm_cancel_stack(exception_t * except) __attribute__((noreturn));41 42 40 // Used in throw statement translation. 43 41 void __cfaehm_throw_terminate(exception_t * except) __attribute__((noreturn)); -
libcfa/src/exception.hfa
r2223c80 r856fe3e 10 10 // Created On : Thu Apr 7 10:25:00 2020 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Apr 13 15:42:00 202013 // Update Count : 112 // Last Modified On : Thu Apr 7 10:25:00 2020 13 // Update Count : 0 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 }27 15 28 16 // Everything below this line should be considered a patch while the exception -
libcfa/src/executor.cfa
r2223c80 r856fe3e 4 4 // buffer. 5 5 6 #include < containers/list.hfa>6 #include <bits/containers.hfa> 7 7 #include <thread.hfa> 8 8 #include <stdio.h> 9 9 10 forall( dtype T ) 11 monitor Buffer { // unbounded buffer 12 __queue_t( T ) queue; // unbounded list of work requests 13 condition delay; 14 }; // Buffer 15 forall( dtype T | is_node(T) ) { 16 void insert( Buffer( T ) & mutex buf, T * elem ) with(buf) { 17 append( queue, elem ); // insert element into buffer 18 signal( delay ); // restart 19 } // insert 20 21 T * remove( Buffer( T ) & mutex buf ) with(buf) { 22 if ( queue.head != 0 ) wait( delay ); // no request to process ? => wait 23 // return pop_head( queue ); 24 } // remove 25 } // distribution 26 10 27 struct WRequest { // client request, no return 11 28 void (* action)( void ); 12 DLISTED_MGD_IMPL_IN(WRequest)29 WRequest * next; // intrusive queue field 13 30 }; // WRequest 14 DLISTED_MGD_IMPL_OUT(WRequest)15 31 16 void ?{}( WRequest & req ) with(req) { action = 0; } 17 void ?{}( WRequest & req, void (* action)( void ) ) with(req) { req.action = action; } 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; } 18 35 bool stop( WRequest & req ) { return req.action == 0; } 19 36 void doit( WRequest & req ) { req.action(); } 20 21 monitor WRBuffer { // unbounded buffer22 dlist( WRequest, WRequest ) queue; // unbounded list of work requests23 condition delay;24 }; // WRBuffer25 26 void insert( WRBuffer & mutex buf, WRequest * elem ) with(buf) {27 insert_last( queue, *elem ); // insert element into buffer28 signal( delay ); // restart29 } // insert30 31 WRequest * remove( WRBuffer & mutex buf ) with(buf) {32 if ( queue`is_empty ) wait( delay ); // no request to process ? => wait33 return & pop_first( queue );34 } // remove35 37 36 38 // Each worker has its own work buffer to reduce contention between client and server. Hence, work requests arrive and … … 38 40 39 41 thread Worker { 40 WRBuffer* requests;42 Buffer( WRequest ) * requests; 41 43 unsigned int start, range; 42 44 }; // Worker … … 52 54 } // Worker::main 53 55 54 void ?{}( Worker & worker, cluster * wc, WRBuffer* requests, unsigned int start, unsigned int range ) {56 void ?{}( Worker & worker, cluster * wc, Buffer( WRequest ) * requests, unsigned int start, unsigned int range ) { 55 57 (*get_thread(worker)){ *wc }; // create on given cluster 56 58 worker.[requests, start, range] = [requests, start, range]; … … 60 62 cluster * cluster; // if workers execute on separate cluster 61 63 processor ** processors; // array of virtual processors adding parallelism for workers 62 WRBuffer * requests;// list of work requests64 Buffer( WRequest ) * requests; // list of work requests 63 65 Worker ** workers; // array of workers executing work requests 64 66 unsigned int nprocessors, nworkers, nmailboxes; // number of mailboxes/workers/processor tasks … … 77 79 cluster = sepClus ? new( "Executor" ) : active_cluster(); 78 80 processors = (processor **)anew( nprocessors ); 79 requests = (WRBuffer *)anew( nmailboxes );81 requests = anew( nmailboxes ); 80 82 workers = (Worker **)anew( nworkers ); 81 83 … … 139 141 for ( i; 3000 ) { 140 142 send( exector, workie ); 141 if ( i % 100 == 0 ) { 142 // fprintf( stderr, "%d\n", i ); 143 yield(); 144 } 143 if ( i % 100 ) yield(); 145 144 } // for 146 145 } -
tests/exceptions/.expect/resume.txt
r2223c80 r856fe3e 4 4 end of try clause 5 5 Exiting: simple try clause 6 7 catch-all8 6 9 7 throwing child exception -
tests/exceptions/.expect/terminate.txt
r2223c80 r856fe3e 3 3 simple catch 4 4 Exiting: simple catch clause 5 6 catch-all7 5 8 6 throwing child exception -
tests/exceptions/resume.cfa
r2223c80 r856fe3e 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");29 21 } 30 22 printf("\n"); -
tests/exceptions/terminate.cfa
r2223c80 r856fe3e 17 17 printf("end of try clause\n"); 18 18 } catch (zen * error) { 19 loud_exit a = "simple catch clause";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");29 21 } 30 22 printf("\n"); -
tests/list/.expect/dlist-insert-remove.txt
r2223c80 r856fe3e 1464 1464 0.7 1465 1465 - 1466 1467 ~~~~~~~~~~ End removal tests on Headed List: First ~~~~~~~~~~1468 1469 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~1470 Test 16-i. Modifying Freds on MINE1471 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~1472 ==== fred by MINE before1473 1.71474 2.71475 3.71476 -1477 1.71478 -1479 3.71480 -1481 3.71482 2.71483 1.71484 -1485 ==== fred by YOURS before1486 1.71487 2.71488 3.71489 -1490 1.71491 -1492 3.71493 -1494 3.71495 2.71496 1.71497 -1498 ==== fred by MINE after1499 2.71500 3.71501 -1502 2.71503 -1504 3.71505 -1506 3.71507 2.71508 -1509 ==== fred by YOURS after1510 1.71511 2.71512 3.71513 -1514 1.71515 -1516 3.71517 -1518 3.71519 2.71520 1.71521 -1522 ==== fred by MINE after1523 1.71524 -1525 1.71526 -1527 -1528 -1529 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~1530 Test 16-ii. Modifying Freds on YOURS1531 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~1532 ==== fred by MINE before1533 1.71534 2.71535 3.71536 -1537 1.71538 -1539 3.71540 -1541 3.71542 2.71543 1.71544 -1545 ==== fred by YOURS before1546 1.71547 2.71548 3.71549 -1550 1.71551 -1552 3.71553 -1554 3.71555 2.71556 1.71557 -1558 ==== fred by MINE after1559 1.71560 2.71561 3.71562 -1563 1.71564 -1565 3.71566 -1567 3.71568 2.71569 1.71570 -1571 ==== fred by YOURS after1572 2.71573 3.71574 -1575 2.71576 -1577 3.71578 -1579 3.71580 2.71581 -1582 ==== fred by YOURS after1583 1.71584 -1585 1.71586 -1587 -1588 -1589 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~1590 Test 16-iii. Modifying Maries1591 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~1592 ==== mary before1593 1.71594 2.71595 3.71596 -1597 1.71598 -1599 3.71600 -1601 3.71602 2.71603 1.71604 -1605 ==== mary after1606 2.71607 3.71608 -1609 2.71610 -1611 3.71612 -1613 3.71614 2.71615 -1616 ==== mary after1617 1.71618 -1619 1.71620 -1621 -1622 -1623 1624 ~~~~~~~~~~ End removal tests on Headed List: Last ~~~~~~~~~~1625 1626 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~1627 Test 17-i. Modifying Freds on MINE1628 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~1629 ==== fred by MINE before1630 1.71631 2.71632 3.71633 -1634 1.71635 -1636 3.71637 -1638 3.71639 2.71640 1.71641 -1642 ==== fred by YOURS before1643 1.71644 2.71645 3.71646 -1647 1.71648 -1649 3.71650 -1651 3.71652 2.71653 1.71654 -1655 ==== fred by MINE after1656 1.71657 2.71658 -1659 1.71660 -1661 2.71662 -1663 2.71664 1.71665 -1666 ==== fred by YOURS after1667 1.71668 2.71669 3.71670 -1671 1.71672 -1673 3.71674 -1675 3.71676 2.71677 1.71678 -1679 ==== fred by MINE after1680 3.71681 -1682 3.71683 -1684 -1685 -1686 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~1687 Test 17-ii. Modifying Freds on YOURS1688 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~1689 ==== fred by MINE before1690 1.71691 2.71692 3.71693 -1694 1.71695 -1696 3.71697 -1698 3.71699 2.71700 1.71701 -1702 ==== fred by YOURS before1703 1.71704 2.71705 3.71706 -1707 1.71708 -1709 3.71710 -1711 3.71712 2.71713 1.71714 -1715 ==== fred by MINE after1716 1.71717 2.71718 3.71719 -1720 1.71721 -1722 3.71723 -1724 3.71725 2.71726 1.71727 -1728 ==== fred by YOURS after1729 1.71730 2.71731 -1732 1.71733 -1734 2.71735 -1736 2.71737 1.71738 -1739 ==== fred by YOURS after1740 3.71741 -1742 3.71743 -1744 -1745 -1746 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~1747 Test 17-iii. Modifying Maries1748 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~1749 ==== mary before1750 1.71751 2.71752 3.71753 -1754 1.71755 -1756 3.71757 -1758 3.71759 2.71760 1.71761 -1762 ==== mary after1763 1.71764 2.71765 -1766 1.71767 -1768 2.71769 -1770 2.71771 1.71772 -1773 ==== mary after1774 3.71775 -1776 3.71777 -1778 -1779 - -
tests/list/dlist-insert-remove.cfa
r2223c80 r856fe3e 1187 1187 //////////////////////////////////////////////////////////// 1188 1188 // 1189 // Section 4f1190 //1191 // Test cases of pop_first, pop_last1192 //1193 // Example of call-side user code1194 //1195 ////////////////////////////////////////////////////////////1196 1197 // These cases assume element removal at first-last is correct1198 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.71216 printYourFreddies(fly`first, fly`last, 1); // 1.7, 2.7, 3.7; 1.7; 3.7; 3.7, 2.7, 1.71217 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 traversed1230 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.71252 printYourFreddies(fly`first, fly`last, 1); // 1.7, 2.7, 3.7; 1.7; 3.7; 3.7, 2.7, 1.71253 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 traversed1266 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.71283 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 solo1293 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.71315 printYourFreddies(fly`first, fly`last, 1); // 1.7, 2.7, 3.7; 1.7; 3.7; 3.7, 2.7, 1.71316 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 traversed1329 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.71351 printYourFreddies(fly`first, fly`last, 1); // 1.7, 2.7, 3.7; 1.7; 3.7; 3.7, 2.7, 1.71352 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 traversed1365 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.71382 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 solo1392 printMariatheotokos(m3, *0p, 0); // 3.7; 3.7; ;1393 1394 assert( &popped == &m3 );1395 }1396 1397 ////////////////////////////////////////////////////////////1398 //1399 1189 // Section 5 1400 1190 // … … 1632 1422 test__remove_of_sole__mary(); 1633 1423 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 1672 1424 return 0; 1673 1425 } -
tools/build/push2dist.sh
r2223c80 r856fe3e 2 2 3 3 hash="$1" 4 bwlim="$2"5 4 valid=$(distcc -j 2> /dev/null) 6 5 # if test "${valid}" != 0 … … 25 24 function push() { 26 25 ssh ${host} "mkdir -p ~/.cfadistcc/${hash}/" 27 rsync - -bwlimit=${bwlim} -a ${dV} ${files} ${host}:~/.cfadistcc/${hash}/.26 rsync -a ${dV} ${files} ${host}:~/.cfadistcc/${hash}/. 28 27 } 29 28
Note:
See TracChangeset
for help on using the changeset viewer.