Changeset 22f94a4
- Timestamp:
- Aug 11, 2020, 4:40:15 PM (5 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:
- 0d070ca
- Parents:
- 07d867b (diff), 129674b (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:
-
- 91 added
- 42 deleted
- 125 edited
- 6 moved
-
.gitignore (modified) (2 diffs)
-
Jenkinsfile_disabled (modified) (1 diff)
-
Makefile.in (deleted)
-
aclocal.m4 (deleted)
-
autogen.sh (added)
-
automake/compile (deleted)
-
automake/config.guess (deleted)
-
automake/config.sub (deleted)
-
automake/depcomp (deleted)
-
automake/install-sh (deleted)
-
automake/libtool.m4 (deleted)
-
automake/ltmain.sh (deleted)
-
automake/ltoptions.m4 (deleted)
-
automake/ltsugar.m4 (deleted)
-
automake/ltversion.m4 (deleted)
-
automake/lt~obsolete.m4 (deleted)
-
automake/missing (deleted)
-
automake/test-driver (deleted)
-
automake/ylwrap (deleted)
-
benchmark/Makefile.am (modified) (1 diff)
-
benchmark/Makefile.in (deleted)
-
benchmark/benchcltr.hfa (added)
-
benchmark/creation/node_cor.js (modified) (1 diff)
-
benchmark/creation/rust_tokio_thrd.rs (added)
-
benchmark/ctxswitch/node_cor.js (modified) (1 diff)
-
benchmark/ctxswitch/rust_await.rs (added)
-
benchmark/ctxswitch/rust_tokio_thrd.rs (added)
-
benchmark/exclude (modified) (1 diff)
-
benchmark/io/batch-readv.c (added)
-
benchmark/io/http/channel.cfa (added)
-
benchmark/io/http/channel.hfa (added)
-
benchmark/io/http/filecache.cfa (added)
-
benchmark/io/http/filecache.hfa (added)
-
benchmark/io/http/main.cfa (added)
-
benchmark/io/http/options.cfa (added)
-
benchmark/io/http/options.hfa (added)
-
benchmark/io/http/protocol.cfa (added)
-
benchmark/io/http/protocol.hfa (added)
-
benchmark/io/http/worker.cfa (added)
-
benchmark/io/http/worker.hfa (added)
-
benchmark/io/io_uring.h (added)
-
benchmark/io/readv.cfa (modified) (7 diffs)
-
benchmark/readyQ/yield.cfa (added)
-
benchmark/readyQ/yield.cpp (added)
-
configure (deleted)
-
configure.ac (modified) (2 diffs)
-
doc/bibliography/pl.bib (modified) (2 diffs)
-
doc/papers/AMA/AMA-stix/ama/WileyNJD-v2.cls (modified) (1 diff)
-
doc/papers/concurrency/Paper.tex (modified) (88 diffs)
-
doc/papers/concurrency/figures/RunTimeStructure.fig (modified) (1 diff)
-
doc/papers/concurrency/mail2 (modified) (1 diff)
-
doc/papers/concurrency/response2 (added)
-
doc/proposals/vtable.md (modified) (2 diffs)
-
doc/theses/thierry_delisle_PhD/code/bitbench/select.cpp (added)
-
doc/theses/thierry_delisle_PhD/code/links.hpp (added)
-
doc/theses/thierry_delisle_PhD/code/process.sh (added)
-
doc/theses/thierry_delisle_PhD/code/relaxed_list.cpp (modified) (25 diffs)
-
doc/theses/thierry_delisle_PhD/code/relaxed_list.hpp (modified) (18 diffs)
-
doc/theses/thierry_delisle_PhD/code/runperf.sh (added)
-
doc/theses/thierry_delisle_PhD/code/snzi-packed.hpp (added)
-
doc/theses/thierry_delisle_PhD/code/snzi.hpp (added)
-
doc/theses/thierry_delisle_PhD/code/snzm.hpp (added)
-
doc/theses/thierry_delisle_PhD/code/utils.hpp (modified) (3 diffs)
-
doc/theses/thierry_delisle_PhD/code/work_stealing.hpp (added)
-
driver/Makefile.in (deleted)
-
driver/cc1.cc (modified) (6 diffs)
-
driver/cfa.cc (modified) (5 diffs)
-
examples/hashtable.cfa (added)
-
examples/hashtable2.cfa (added)
-
examples/io/cat.c (moved) (moved from examples/io_uring.c ) (6 diffs)
-
examples/io/filereader.c (modified) (6 diffs)
-
examples/io/simple/server.c (modified) (2 diffs)
-
examples/io/simple/server_epoll.c (added)
-
libcfa/Makefile.in (deleted)
-
libcfa/aclocal.m4 (deleted)
-
libcfa/automake/compile (deleted)
-
libcfa/automake/config.guess (deleted)
-
libcfa/automake/config.sub (deleted)
-
libcfa/automake/depcomp (deleted)
-
libcfa/automake/install-sh (deleted)
-
libcfa/automake/libtool.m4 (deleted)
-
libcfa/automake/ltmain.sh (deleted)
-
libcfa/automake/ltoptions.m4 (deleted)
-
libcfa/automake/ltsugar.m4 (deleted)
-
libcfa/automake/ltversion.m4 (deleted)
-
libcfa/automake/lt~obsolete.m4 (deleted)
-
libcfa/automake/missing (deleted)
-
libcfa/configure (deleted)
-
libcfa/configure.ac (modified) (5 diffs)
-
libcfa/prelude/Makefile.am (modified) (1 diff)
-
libcfa/prelude/Makefile.in (deleted)
-
libcfa/prelude/builtins.c (modified) (2 diffs)
-
libcfa/prelude/defines.hfa.in (modified) (1 diff)
-
libcfa/src/Makefile.am (modified) (4 diffs)
-
libcfa/src/Makefile.in (deleted)
-
libcfa/src/bitmanip.hfa (modified) (5 diffs)
-
libcfa/src/bits/containers.hfa (modified) (1 diff)
-
libcfa/src/bits/debug.cfa (modified) (2 diffs)
-
libcfa/src/bits/debug.hfa (modified) (2 diffs)
-
libcfa/src/bits/defs.hfa (modified) (1 diff)
-
libcfa/src/bits/locks.hfa (modified) (2 diffs)
-
libcfa/src/bits/random.hfa (added)
-
libcfa/src/bits/signal.hfa (modified) (2 diffs)
-
libcfa/src/concurrency/alarm.cfa (modified) (2 diffs)
-
libcfa/src/concurrency/alarm.hfa (modified) (1 diff)
-
libcfa/src/concurrency/coroutine.cfa (modified) (3 diffs)
-
libcfa/src/concurrency/invoke.c (modified) (1 diff)
-
libcfa/src/concurrency/invoke.h (modified) (9 diffs)
-
libcfa/src/concurrency/io.cfa (modified) (5 diffs)
-
libcfa/src/concurrency/io/setup.cfa (added)
-
libcfa/src/concurrency/io/types.hfa (added)
-
libcfa/src/concurrency/iocall.cfa (added)
-
libcfa/src/concurrency/iofwd.hfa (modified) (1 diff)
-
libcfa/src/concurrency/kernel.cfa (modified) (27 diffs)
-
libcfa/src/concurrency/kernel.hfa (modified) (10 diffs)
-
libcfa/src/concurrency/kernel/fwd.hfa (added)
-
libcfa/src/concurrency/kernel/startup.cfa (added)
-
libcfa/src/concurrency/kernel_private.hfa (modified) (4 diffs)
-
libcfa/src/concurrency/monitor.cfa (modified) (5 diffs)
-
libcfa/src/concurrency/mutex.cfa (modified) (1 diff)
-
libcfa/src/concurrency/preemption.cfa (modified) (15 diffs)
-
libcfa/src/concurrency/preemption.hfa (modified) (1 diff)
-
libcfa/src/concurrency/ready_queue.cfa (added)
-
libcfa/src/concurrency/ready_subqueue.hfa (added)
-
libcfa/src/concurrency/snzi.hfa (added)
-
libcfa/src/concurrency/stats.cfa (added)
-
libcfa/src/concurrency/stats.hfa (added)
-
libcfa/src/concurrency/thread.cfa (modified) (3 diffs)
-
libcfa/src/concurrency/thread.hfa (modified) (2 diffs)
-
libcfa/src/containers/list.hfa (modified) (8 diffs)
-
libcfa/src/containers/stackLockFree.hfa (added)
-
libcfa/src/containers/vector.hfa (modified) (1 diff)
-
libcfa/src/exception.c (modified) (8 diffs)
-
libcfa/src/exception.h (modified) (3 diffs)
-
libcfa/src/exception.hfa (modified) (7 diffs)
-
libcfa/src/executor.cfa (modified) (1 diff)
-
libcfa/src/fstream.cfa (modified) (8 diffs)
-
libcfa/src/fstream.hfa (modified) (4 diffs)
-
libcfa/src/heap.cfa (modified) (58 diffs)
-
libcfa/src/heap.hfa (added)
-
libcfa/src/iostream.cfa (modified) (16 diffs)
-
libcfa/src/iostream.hfa (modified) (14 diffs)
-
libcfa/src/memory.cfa (added)
-
libcfa/src/memory.hfa (added)
-
libcfa/src/parseargs.cfa (added)
-
libcfa/src/parseargs.hfa (added)
-
libcfa/src/stdhdr/assert.h (modified) (1 diff)
-
libcfa/src/stdhdr/malloc.h (modified) (1 diff)
-
libcfa/src/stdhdr/sys/mman.h (added)
-
libcfa/src/stdhdr/sys/time.h (added)
-
libcfa/src/stdhdr/sys/ucontext.h (deleted)
-
libcfa/src/stdlib.cfa (modified) (5 diffs)
-
libcfa/src/stdlib.hfa (modified) (12 diffs)
-
libcfa/src/time.hfa (modified) (3 diffs)
-
longrun_tests/Makefile.am (modified) (1 diff)
-
longrun_tests/Makefile.in (deleted)
-
src/Common/PassVisitor.proto.h (modified) (1 diff)
-
src/Common/ScopedMap.h (modified) (1 diff)
-
src/Concurrency/Keywords.cc (modified) (5 diffs)
-
src/Concurrency/Waitfor.cc (modified) (3 diffs)
-
src/ControlStruct/ExceptTranslate.cc (modified) (19 diffs)
-
src/ControlStruct/ExceptTranslate.h (modified) (2 diffs)
-
src/GenPoly/InstantiateGeneric.cc (modified) (4 diffs)
-
src/GenPoly/Specialize.cc (modified) (4 diffs)
-
src/Makefile.in (deleted)
-
src/Parser/DeclarationNode.cc (modified) (2 diffs)
-
src/Parser/ExpressionNode.cc (modified) (7 diffs)
-
src/Parser/ParseNode.h (modified) (2 diffs)
-
src/Parser/module.mk (modified) (1 diff)
-
src/Parser/parser.yy (modified) (13 diffs)
-
src/ResolvExpr/AlternativeFinder.cc (modified) (2 diffs)
-
src/ResolvExpr/ConversionCost.cc (modified) (3 diffs)
-
src/ResolvExpr/ConversionCost.h (modified) (3 diffs)
-
src/SynTree/Expression.h (modified) (1 diff)
-
src/Virtual/ExpandCasts.cc (modified) (10 diffs)
-
src/main.cc (modified) (3 diffs)
-
tests/.expect/alloc.txt (modified) (1 diff)
-
tests/.expect/bitmanip3.x64.txt (modified) (21 diffs)
-
tests/.expect/bitmanip3.x86.txt (modified) (21 diffs)
-
tests/.expect/castError.txt (modified) (3 diffs)
-
tests/.expect/copyfile.txt (modified) (1 diff)
-
tests/.expect/functions.x64.txt (modified) (4 diffs)
-
tests/.expect/functions.x86.txt (modified) (4 diffs)
-
tests/.expect/global-monomorph.txt (added)
-
tests/.expect/init1.txt (added)
-
tests/.expect/manipulatorsInput.x64.txt (added)
-
tests/.expect/manipulatorsInput.x86.txt (moved) (moved from tests/.expect/manipulatorsInput.txt )
-
tests/.expect/manipulatorsOutput3.x64.txt (added)
-
tests/.expect/poly-cycle.txt (added)
-
tests/.expect/smart-pointers.txt (added)
-
tests/.expect/time.txt (modified) (1 diff)
-
tests/.in/copyfile.txt (modified) (1 diff)
-
tests/.in/manipulatorsInput.txt (modified) (1 diff)
-
tests/Makefile.am (modified) (1 diff)
-
tests/Makefile.in (deleted)
-
tests/avltree/avl1.cfa (modified) (1 diff)
-
tests/bitmanip3.cfa (modified) (21 diffs)
-
tests/bugs/10.cfa (added)
-
tests/bugs/104.cfa (added)
-
tests/bugs/140.cfa (added)
-
tests/bugs/194.cfa (added)
-
tests/bugs/20.cfa (added)
-
tests/bugs/203-2.cfa (added)
-
tests/bugs/203-7.cfa (added)
-
tests/bugs/203-9.cfa (added)
-
tests/bugs/44.cfa (added)
-
tests/bugs/46.cfa (added)
-
tests/bugs/5.cfa (added)
-
tests/bugs/66.cfa (added)
-
tests/bugs/7.cfa (added)
-
tests/bugs/91.cfa (added)
-
tests/bugs/92.cfa (added)
-
tests/bugs/95.cfa (added)
-
tests/castError.cfa (modified) (2 diffs)
-
tests/concurrent/examples/datingService.cfa (modified) (2 diffs)
-
tests/concurrent/park/.expect/start_parked.txt (added)
-
tests/concurrent/park/start_parked.cfa (added)
-
tests/concurrent/signal/block.cfa (modified) (1 diff)
-
tests/concurrent/signal/disjoint.cfa (modified) (6 diffs)
-
tests/concurrent/waitfor/when.cfa (modified) (1 diff)
-
tests/copyfile.cfa (modified) (1 diff)
-
tests/errors/.expect/completeType.x64.txt (moved) (moved from tests/errors/.expect/completeType.txt ) (1 diff)
-
tests/errors/.expect/completeType.x86.txt (added)
-
tests/exceptions/.expect/defaults.txt (added)
-
tests/exceptions/.expect/polymorphic.txt (added)
-
tests/exceptions/.expect/resume.txt (modified) (2 diffs)
-
tests/exceptions/.expect/terminate.txt (modified) (2 diffs)
-
tests/exceptions/.expect/type-check.txt (added)
-
tests/exceptions/.expect/virtual-cast.txt (added)
-
tests/exceptions/.expect/virtual-poly.txt (added)
-
tests/exceptions/conditional.cfa (modified) (3 diffs)
-
tests/exceptions/data-except.cfa (modified) (2 diffs)
-
tests/exceptions/defaults.cfa (added)
-
tests/exceptions/finally.cfa (modified) (2 diffs)
-
tests/exceptions/interact.cfa (modified) (10 diffs)
-
tests/exceptions/polymorphic.cfa (added)
-
tests/exceptions/resume.cfa (modified) (8 diffs)
-
tests/exceptions/terminate.cfa (modified) (8 diffs)
-
tests/exceptions/type-check.cfa (added)
-
tests/exceptions/virtual-cast.cfa (moved) (moved from tests/zombies/virtualCast.cfa )
-
tests/exceptions/virtual-poly.cfa (added)
-
tests/global-monomorph.cfa (added)
-
tests/heap.cfa (modified) (26 diffs)
-
tests/init1.cfa (added)
-
tests/io2.cfa (modified) (1 diff)
-
tests/list/.expect/dlist-insert-remove.txt (modified) (1 diff)
-
tests/list/dlist-insert-remove.cfa (modified) (2 diffs)
-
tests/manipulatorsInput.cfa (modified) (2 diffs)
-
tests/manipulatorsOutput3.cfa (modified) (1 diff)
-
tests/poly-cycle.cfa (added)
-
tests/pybin/test_run.py (modified) (1 diff)
-
tests/pybin/tools.py (modified) (1 diff)
-
tests/searchsort.cfa (modified) (1 diff)
-
tests/smart-pointers.cfa (added)
-
tests/test.py (modified) (1 diff)
-
tests/time.cfa (modified) (2 diffs)
-
tools/Makefile.in (deleted)
-
tools/build/cfa.m4 (moved) (moved from automake/cfa.m4 )
-
tools/build/cfa.make (moved) (moved from src/cfa.make ) (1 diff)
-
tools/build/push2dist.sh (modified) (2 diffs)
-
tools/gdb/utils-gdb.py (modified) (1 diff)
-
tools/perf/process_halts.sh (added)
-
tools/perf/view_halts.py (added)
-
tools/prettyprinter/Makefile.in (deleted)
Legend:
- Unmodified
- Added
- Removed
-
.gitignore
r07d867b r22f94a4 4 4 5 5 # generated by configure 6 aclocal.m4 7 automake 6 8 autom4te.cache 7 9 config.h … … 9 11 config.log 10 12 config.py 13 configure 14 libtool 11 15 stamp-h1 12 libtool13 16 /Makefile 17 /Makefile.in 14 18 **/Makefile 19 **/Makefile.in 15 20 /version 16 21 -
Jenkinsfile_disabled
r07d867b r22f94a4 114 114 release = Settings.RunAllTests || Settings.RunBenchmark 115 115 build_stage('Build : configure', true) { 116 // Configure must be run inside the tree 117 dir (SrcDir) { 118 // Generate the necessary build files 119 sh './autogen.sh' 120 } 121 116 122 // Build outside of the src tree to ease cleaning 117 123 dir (BuildDir) { -
benchmark/Makefile.am
r07d867b r22f94a4 19 19 20 20 # applies to both programs 21 include $(top_srcdir)/ src/cfa.make21 include $(top_srcdir)/tools/build/cfa.make 22 22 23 23 AM_CFLAGS = -O2 -Wall -Wextra -I$(srcdir) -lrt -pthread # -Werror -
benchmark/creation/node_cor.js
r07d867b r22f94a4 5 5 6 6 function * coroutine() { yield } 7 8 for ( var i = 0; i < times; i += 1 ) { // warm jit 9 cor = coroutine() 10 } 11 7 12 var hrstart = process.hrtime() 8 13 for ( var i = 0; i < times; i += 1 ) { -
benchmark/ctxswitch/node_cor.js
r07d867b r22f94a4 10 10 } 11 11 cor = coroutine() 12 13 for ( var i = 0; i < times; i += 1 ) { // warm git 14 cor.next(); 15 } 12 16 13 17 var hrstart = process.hrtime() -
benchmark/exclude
r07d867b r22f94a4 10 10 interrupt_linux.c 11 11 exclude 12 io 12 13 Monitor.c -
benchmark/io/readv.cfa
r07d867b r22f94a4 1 #define _GNU_SOURCE 2 1 3 #include <stdlib.h> 2 4 #include <stdio.h> … … 10 12 } 11 13 14 #include <errno.h> 12 15 #include <unistd.h> 13 16 14 17 #include <clock.hfa> 18 #include <iofwd.hfa> 15 19 #include <kernel.hfa> 16 20 #include <thread.hfa> 17 21 #include <time.hfa> 22 #include <stats.hfa> 23 24 #include "../benchcltr.hfa" 18 25 19 26 extern bool traceHeapOn(); 20 extern ssize_t cfa_preadv2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags);21 27 22 28 int fd; … … 24 30 volatile size_t count = 0; 25 31 26 unsigned long int buflen = 50; 32 unsigned long int buflen = 512; 33 bool fixed_file = false; 27 34 28 cluster * the_cluster; 29 30 thread Reader {}; 35 thread __attribute__((aligned(128))) Reader {}; 31 36 void ?{}( Reader & this ) { 32 ((thread&)this){ "Reader Thread", *the_ cluster };37 ((thread&)this){ "Reader Thread", *the_benchmark_cluster }; 33 38 } 34 39 35 struct my_processor { 36 processor p; 37 }; 38 39 void ?{}( my_processor & this ) { 40 (this.p){ "I/O Processor", *the_cluster }; 40 int do_read(int fd, struct iovec * iov) { 41 // extern ssize_t cfa_preadv2(int, const struct iovec *, int, off_t, int, int = 0, Duration = -1`s, io_cancellation * = 0p, io_context * = 0p); 42 int sflags = 0; 43 if(fixed_file) { 44 sflags |= CFA_IO_FIXED_FD1; 45 } 46 return cfa_preadv2(fd, iov, 1, 0, 0, sflags, -1`s, 0p, 0p); 41 47 } 42 48 43 49 void main( Reader & ) { 44 while(!__atomic_load_n(&run, __ATOMIC_RELAXED)) yield(); 50 park( __cfaabi_dbg_ctx ); 51 /* paranoid */ assert( true == __atomic_load_n(&run, __ATOMIC_RELAXED) ); 45 52 46 char data[buflen];53 __attribute__((aligned(512))) char data[buflen]; 47 54 struct iovec iov = { data, buflen }; 48 55 49 56 while(__atomic_load_n(&run, __ATOMIC_RELAXED)) { 50 int r = cfa_preadv2(fd, &iov, 1, 0, 0);51 if(r < 0) abort("%s\n", strerror( -r));57 int r = do_read(fd, &iov); 58 if(r < 0) abort("%s\n", strerror(errno)); 52 59 53 60 __atomic_fetch_add( &count, 1, __ATOMIC_SEQ_CST ); … … 56 63 57 64 int main(int argc, char * argv[]) { 58 double duration = 5.0; 59 unsigned long int nthreads = 2; 60 unsigned long int nprocs = 1; 61 int flags = 0; 65 BENCH_DECL 66 unsigned num_io = 1; 67 io_context_params params; 68 int file_flags = 0; 69 unsigned sublen = 16; 62 70 63 71 arg_loop: 64 72 for(;;) { 65 73 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'}, 74 BENCH_OPT_LONG 75 {"bufsize", required_argument, 0, 'b'}, 76 {"submitthread", no_argument , 0, 's'}, 77 {"eagersubmit", no_argument , 0, 'e'}, 78 {"kpollsubmit", no_argument , 0, 'k'}, 79 {"kpollcomplete", no_argument , 0, 'i'}, 80 {"fixed-files", no_argument , 0, 'f'}, 81 {"open-direct", no_argument , 0, 'o'}, 82 {"submitlength", required_argument, 0, 'l'}, 71 83 {0, 0, 0, 0} 72 84 }; 73 85 74 86 int idx = 0; 75 int opt = getopt_long(argc, argv, "d:t:p:b:u", options, &idx);87 int opt = getopt_long(argc, argv, BENCH_OPT_SHORT "b:sekil:", options, &idx); 76 88 77 89 const char * arg = optarg ? optarg : ""; … … 81 93 case -1: 82 94 break arg_loop; 83 // Numeric Arguments 84 case 'd': 85 duration = strtod(arg, &end); 86 if(*end != '\0') { 87 fprintf(stderr, "Duration must be a valid double, was %s\n", arg); 88 goto usage; 89 } 90 break; 91 case 't': 92 nthreads = strtoul(arg, &end, 10); 93 if(*end != '\0' || nthreads < 1) { 94 fprintf(stderr, "Number of threads must be a positive integer, was %s\n", arg); 95 goto usage; 96 } 97 break; 98 case 'p': 99 nprocs = strtoul(arg, &end, 10); 100 if(*end != '\0' || nprocs < 1) { 101 fprintf(stderr, "Number of processors must be a positive integer, was %s\n", arg); 102 goto usage; 103 } 104 break; 95 BENCH_OPT_CASE 105 96 case 'b': 106 97 buflen = strtoul(arg, &end, 10); … … 110 101 } 111 102 break; 112 case ' u':113 flags |= CFA_CLUSTER_IO_POLLER_USER_THREAD;103 case 's': 104 params.poller_submits = true; 114 105 break; 115 // Other cases 106 case 'e': 107 params.eager_submits = true; 108 break; 109 case 'k': 110 params.poll_submit = true; 111 case 'f': 112 fixed_file = true; 113 break; 114 case 'i': 115 params.poll_complete = true; 116 case 'o': 117 file_flags |= O_DIRECT; 118 break; 119 case 'l': 120 sublen = strtoul(arg, &end, 10); 121 if(*end != '\0' && sublen < 16) { 122 fprintf(stderr, "Submit length must be at least 16, was %s\n", arg); 123 goto usage; 124 } 125 // flags |= (sublen << CFA_CLUSTER_IO_BUFFLEN_OFFSET); 126 break; 116 127 default: /* ? */ 117 128 fprintf(stderr, "%d\n", opt); 118 129 usage: 119 fprintf(stderr, "Usage: %s : [options]\n", argv[0]); 120 fprintf(stderr, "\n"); 121 fprintf(stderr, " -d, --duration=DURATION Duration of the experiment, in seconds\n"); 122 fprintf(stderr, " -t, --nthreads=NTHREADS Number of user threads\n"); 123 fprintf(stderr, " -p, --nprocs=NPROCS Number of kernel threads\n"); 124 fprintf(stderr, " -b, --buflen=SIZE Number of bytes to read per request\n"); 130 bench_usage( argv ); 131 fprintf( stderr, " -b, --buflen=SIZE Number of bytes to read per request\n" ); 132 fprintf( stderr, " -u, --userthread If set, cluster uses user-thread to poll I/O\n" ); 133 fprintf( stderr, " -s, --submitthread If set, cluster uses polling thread to submit I/O\n" ); 134 fprintf( stderr, " -e, --eagersubmit If set, cluster submits I/O eagerly but still aggregates submits\n" ); 135 fprintf( stderr, " -k, --kpollsubmit If set, cluster uses IORING_SETUP_SQPOLL\n" ); 136 fprintf( stderr, " -i, --kpollcomplete If set, cluster uses IORING_SETUP_IOPOLL\n" ); 137 fprintf( stderr, " -l, --submitlength=LEN Max number of submitions that can be submitted together\n" ); 125 138 exit(EXIT_FAILURE); 126 139 } 127 140 } 128 141 129 fd = open(__FILE__, 0);130 if( fd < 0) {142 int lfd = open(__FILE__, file_flags); 143 if(lfd < 0) { 131 144 fprintf(stderr, "Could not open source file\n"); 132 145 exit(EXIT_FAILURE); 133 146 } 134 147 135 printf("Running % lu threads, reading %lu bytes each, over %lu processors for %lf seconds\n", nthreads, buflen, nprocs, duration);148 printf("Running %d threads, reading %lu bytes each, over %d processors for %f seconds\n", nthreads, buflen, nprocs, duration); 136 149 137 150 { 138 151 Time start, end; 139 cluster cl = { "IO Cluster", flags }; 140 the_cluster = &cl; 141 #if !defined(__CFA_NO_STATISTICS__) 142 print_stats_at_exit( cl ); 143 #endif 152 BenchCluster cl = { num_io, params, CFA_STATS_READY_Q | CFA_STATS_IO }; 153 154 if(fixed_file) { 155 fd = 0; 156 register_fixed_files( cl.self, &lfd, 1 ); 157 } 158 else { 159 fd = lfd; 160 } 161 144 162 { 145 my_processorprocs[nprocs];163 BenchProc procs[nprocs]; 146 164 { 147 165 Reader threads[nthreads]; 148 166 149 167 printf("Starting\n"); 150 start = getTime(); 168 bool is_tty = isatty(STDOUT_FILENO); 169 start = getTimeNsec(); 151 170 run = true; 152 do { 153 sleep(500`ms); 154 end = getTime(); 155 } while( (end - start) < duration`s ); 171 172 for(i; nthreads) { 173 unpark( threads[i] __cfaabi_dbg_ctx2 ); 174 } 175 wait(duration, start, end, is_tty); 176 156 177 run = false; 157 end = getTime ();158 printf(" Done\n");178 end = getTimeNsec(); 179 printf("\nDone\n"); 159 180 } 181 printf("Readers closed\n"); 160 182 } 161 183 printf("Took %'ld ms\n", (end - start)`ms); … … 166 188 } 167 189 168 close( fd);190 close(lfd); 169 191 } -
configure.ac
r07d867b r22f94a4 6 6 AC_CONFIG_AUX_DIR([automake]) 7 7 AC_CONFIG_MACRO_DIRS([automake]) 8 #AC_CONFIG_SRCDIR([src/main.cc])9 8 AC_CONFIG_HEADERS([config.h:src/config.h.in]) 10 9 AM_SILENT_RULES([yes]) 11 10 12 m4_include([ automake/cfa.m4])11 m4_include([tools/build/cfa.m4]) 13 12 14 13 # don't use the default CFLAGS as they unconditonnaly add -O2 … … 64 63 [ --enable-distcc whether or not to enable distributed compilation], 65 64 enable_distcc=$enableval, enable_distcc=no) 65 66 AC_ARG_WITH(bwlimit, 67 [ --with-bwlimit=RATE RATE the maximum rate at which rsync will be limited when using distributed builds], 68 [], []) 66 69 67 70 AM_CONDITIONAL([ENABLE_DISTCC], [test x$enable_distcc = xyes]) -
doc/bibliography/pl.bib
r07d867b r22f94a4 1001 1001 } 1002 1002 1003 @misc{Cforall BenchMarks,1003 @misc{CforallConcurrentBenchmarks, 1004 1004 contributer = {pabuhr@plg}, 1005 1005 key = {Cforall Benchmarks}, 1006 1006 author = {{\textsf{C}{$\mathbf{\forall}$} Benchmarks}}, 1007 howpublished= {\href{https://plg.uwaterloo.ca/~cforall/ benchmark.tar}{https://\-plg.uwaterloo.ca/\-$\sim$cforall/\-benchmark.tar}},1007 howpublished= {\href{https://plg.uwaterloo.ca/~cforall/doc/CforallConcurrentBenchmarks.tar}{https://\-plg.uwaterloo.ca/\-$\sim$cforall/\-doc/\-CforallConcurrentBenchmarks.tar}}, 1008 1008 } 1009 1009 … … 1982 1982 author = {Adya, Atul and Howell, Jon and Theimer, Marvin and Bolosky, William J. and Douceur, John R.}, 1983 1983 title = {Cooperative Task Management Without Manual Stack Management}, 1984 booktitle = {Proc eedings of the General Track of the Annual Conference on USENIX Annual Technical Conference},1984 booktitle = {Proc. of the General Track USENIX Tech. Conf.}, 1985 1985 series = {ATEC '02}, 1986 1986 year = {2002}, -
doc/papers/AMA/AMA-stix/ama/WileyNJD-v2.cls
r07d867b r22f94a4 2444 2444 \@afterheading} 2445 2445 2446 \renewcommand\section{\@startsection{section}{1}{\z@}{-2 5pt \@plus -2pt \@minus -2pt}{12\p@}{\sectionfont}}%2447 \renewcommand\subsection{\@startsection{subsection}{2}{\z@}{- 22pt \@plus -2pt \@minus -2pt}{5\p@}{\subsectionfont}}%2448 \renewcommand\subsubsection{\@startsection{subsubsection}{3}{\z@}{- 20pt \@plus -2pt \@minus -2pt}{2\p@}{\subsubsectionfont}}%2446 \renewcommand\section{\@startsection{section}{1}{\z@}{-20pt \@plus -2pt \@minus -2pt}{7\p@}{\sectionfont}}% 2447 \renewcommand\subsection{\@startsection{subsection}{2}{\z@}{-18pt \@plus -2pt \@minus -2pt}{5\p@}{\subsectionfont}}% 2448 \renewcommand\subsubsection{\@startsection{subsubsection}{3}{\z@}{-16pt \@plus -2pt \@minus -2pt}{2\p@}{\subsubsectionfont}}% 2449 2449 % 2450 2450 \newskip\secruleskip\secruleskip8.5\p@% -
doc/papers/concurrency/Paper.tex
r07d867b r22f94a4 99 99 \newcommand{\CRT}{\global\columnposn=\gcolumnposn} 100 100 101 % Denote newterms in particular font and index them without particular font and in lowercase, e.g.,\newterm{abc}.102 % The option parameter provides an index term different from the new term, e.g.,\newterm[\texttt{abc}]{abc}101 % Denote newterms in particular font and index them without particular font and in lowercase, \eg \newterm{abc}. 102 % The option parameter provides an index term different from the new term, \eg \newterm[\texttt{abc}]{abc} 103 103 % The star version does not lowercase the index information, e.g., \newterm*{IBM}. 104 104 \newcommand{\newtermFontInline}{\emph} … … 235 235 {\lstset{language=python,moredelim=**[is][\protect\color{red}]{`}{`},#1}\lstset{#1}} 236 236 {} 237 \lstnewenvironment{java}[1][] 238 {\lstset{language=java,moredelim=**[is][\protect\color{red}]{`}{`},#1}\lstset{#1}} 239 {} 237 240 238 241 % inline code @...@ … … 266 269 267 270 \abstract[Summary]{ 268 \CFA is a polymorphic, non-object-oriented, concurrent, backwards -compatible extension of the C programming language.271 \CFA is a polymorphic, non-object-oriented, concurrent, backwards compatible extension of the C programming language. 269 272 This paper discusses the design philosophy and implementation of its advanced control-flow and concurrent/parallel features, along with the supporting runtime written in \CFA. 270 273 These features are created from scratch as ISO C has only low-level and/or unimplemented concurrency, so C programmers continue to rely on library approaches like pthreads. … … 272 275 % Library extension for executors, futures, and actors are built on these basic mechanisms. 273 276 The runtime provides significant programmer simplification and safety by eliminating spurious wakeup and monitor barging. 274 The runtime also ensures multiple monitors can be safely acquired \emph{simultaneously} (deadlock free), and this feature is fully integrated with all monitor synchronization mechanisms.277 The runtime also ensures multiple monitors can be safely acquired in a deadlock-free way, and this feature is fully integrated with all monitor synchronization mechanisms. 275 278 All control-flow features integrate with the \CFA polymorphic type-system and exception handling, while respecting the expectations and style of C programmers. 276 279 Experimental results show comparable performance of the new features with similar mechanisms in other concurrent programming languages. … … 289 292 290 293 \CFA~\cite{Moss18,Cforall} is a modern, polymorphic, non-object-oriented\footnote{ 291 \CFA has object-oriented features, such as constructors, destructors, virtualsand simple trait/interface inheritance.294 \CFA has object-oriented features, such as constructors, destructors, and simple trait/interface inheritance. 292 295 % Go interfaces, Rust traits, Swift Protocols, Haskell Type Classes and Java Interfaces. 293 296 % "Trait inheritance" works for me. "Interface inheritance" might also be a good choice, and distinguish clearly from implementation inheritance. 294 % You'll want to be a little bit careful with terms like "structural" and "nominal" inheritance as well. CFA has structural inheritance (I think Go as well) -- it's inferred based on the structure of the code. Java, Rust, and Haskell (not sure about Swift) have nominal inheritance, where there needs to be a specific statement that "this type inherits from this type". 295 However, functions \emph{cannot} be nested in structures, so there is no lexical binding between a structure and set of functions (member/method) implemented by an implicit \lstinline@this@ (receiver) parameter.}, 297 % You'll want to be a little bit careful with terms like "structural" and "nominal" inheritance as well. CFA has structural inheritance (I think Go as well) -- it's inferred based on the structure of the code. 298 % Java, Rust, and Haskell (not sure about Swift) have nominal inheritance, where there needs to be a specific statement that "this type inherits from this type". 299 However, functions \emph{cannot} be nested in structures and there is no mechanism to designate a function parameter as a receiver, \lstinline@this@, parameter.}, 296 300 backwards-compatible extension of the C programming language. 297 In many ways, \CFA is to C as Scala~\cite{Scala} is to Java, providing a \emph{research vehicle}for new typing and control-flow capabilities on top of a highly popular programming language\footnote{298 The TIOBE index~\cite{TIOBE} for December 2019 ranks the top five \emph{popular} programming languages as Java 17\%, C 16\%, Python 10\%, and \CC 6\%, \Csharp 5\% = 54\%, and over the past 30 years, C has always ranked either first or second in popularity.}301 In many ways, \CFA is to C as Scala~\cite{Scala} is to Java, providing a vehicle for new typing and control-flow capabilities on top of a highly popular programming language\footnote{ 302 The TIOBE index~\cite{TIOBE} for May 2020 ranks the top five \emph{popular} programming languages as C 17\%, Java 16\%, Python 9\%, \CC 6\%, and \Csharp 4\% = 52\%, and over the past 30 years, C has always ranked either first or second in popularity.} 299 303 allowing immediate dissemination. 300 This paper discusses the design philosophy and implementation of advanced language-level control-flow and concurrent/parallel features in \CFA and its runtime, which is written entirely in \CFA. 301 The \CFA control-flow framework extends ISO \Celeven~\cite{C11} with new call/return and concurrent/parallel control-flow. 304 This paper discusses the design philosophy and implementation of \CFA's advanced control-flow and concurrent/parallel features, along with the supporting runtime written in \CFA. 302 305 303 306 % The call/return extensions retain state between callee and caller versus losing the callee's state on return; 304 307 % the concurrency extensions allow high-level management of threads. 305 308 306 Call/return control-flow with argument/parameter passing appeared in the first programming languages. 307 Over the past 50 years, call/return has been augmented with features like static/dynamic call, exceptions (multi-level return) and generators/coroutines (retain state between calls). 308 While \CFA has mechanisms for dynamic call (algebraic effects) and exceptions\footnote{ 309 The \CFA control-flow framework extends ISO \Celeven~\cite{C11} with new call/return and concurrent/parallel control-flow. 310 Call/return control-flow with argument and parameter passing appeared in the first programming languages. 311 Over the past 50 years, call/return has been augmented with features like static and dynamic call, exceptions (multi-level return) and generators/coroutines (see Section~\ref{s:StatefulFunction}). 312 While \CFA has mechanisms for dynamic call (algebraic effects~\cite{Zhang19}) and exceptions\footnote{ 309 313 \CFA exception handling will be presented in a separate paper. 310 The key feature that dovetails with this paper is nonlocal exceptions allowing exceptions to be raised across stacks, with synchronous exceptions raised among coroutines and asynchronous exceptions raised among threads, similar to that in \uC~\cite[\S~5]{uC++}}, this work only discusses retaining state between calls via generators /coroutines.314 The key feature that dovetails with this paper is nonlocal exceptions allowing exceptions to be raised across stacks, with synchronous exceptions raised among coroutines and asynchronous exceptions raised among threads, similar to that in \uC~\cite[\S~5]{uC++}}, this work only discusses retaining state between calls via generators and coroutines. 311 315 \newterm{Coroutining} was introduced by Conway~\cite{Conway63} (1963), discussed by Knuth~\cite[\S~1.4.2]{Knuth73V1}, implemented in Simula67~\cite{Simula67}, formalized by Marlin~\cite{Marlin80}, and is now popular and appears in old and new programming languages: CLU~\cite{CLU}, \Csharp~\cite{Csharp}, Ruby~\cite{Ruby}, Python~\cite{Python}, JavaScript~\cite{JavaScript}, Lua~\cite{Lua}, \CCtwenty~\cite{C++20Coroutine19}. 312 316 Coroutining is sequential execution requiring direct handoff among coroutines, \ie only the programmer is controlling execution order. 313 If coroutines transfer to an internal event-engine for scheduling the next coroutines , the program transitions into the realm of concurrency~\cite[\S~3]{Buhr05a}.317 If coroutines transfer to an internal event-engine for scheduling the next coroutines (as in async-await), the program transitions into the realm of concurrency~\cite[\S~3]{Buhr05a}. 314 318 Coroutines are only a stepping stone towards concurrency where the commonality is that coroutines and threads retain state between calls. 315 319 316 \Celeven /\CCeleven define concurrency~\cite[\S~7.26]{C11}, but it is largely wrappers for a subset of the pthreads library~\cite{Pthreads}.\footnote{Pthreads concurrency is based on simple thread fork/join in a function and mutex/condition locks, which is low-level and error-prone}317 Interestingly, almost a decade after the \Celeven standard, neither gcc-9, clang-9 nor msvc-19 (most recent versions)support the \Celeven include @threads.h@, indicating no interest in the C11 concurrency approach (possibly because of the recent effort to add concurrency to \CC).320 \Celeven and \CCeleven define concurrency~\cite[\S~7.26]{C11}, but it is largely wrappers for a subset of the pthreads library~\cite{Pthreads}.\footnote{Pthreads concurrency is based on simple thread fork and join in a function and mutex or condition locks, which is low-level and error-prone} 321 Interestingly, almost a decade after the \Celeven standard, the most recent versions of gcc, clang, and msvc do not support the \Celeven include @threads.h@, indicating no interest in the C11 concurrency approach (possibly because of the recent effort to add concurrency to \CC). 318 322 While the \Celeven standard does not state a threading model, the historical association with pthreads suggests implementations would adopt kernel-level threading (1:1)~\cite{ThreadModel}, as for \CC. 319 323 In contrast, there has been a renewed interest during the past decade in user-level (M:N, green) threading in old and new programming languages. … … 321 325 Kernel threading was chosen, largely because of its simplicity and fit with the simpler operating systems and hardware architectures at the time, which gave it a performance advantage~\cite{Drepper03}. 322 326 Libraries like pthreads were developed for C, and the Solaris operating-system switched from user (JDK 1.1~\cite{JDK1.1}) to kernel threads. 323 As a result, many current languages implementations adopt the 1:1 kernel-threading model, like Java (Scala), Objective-C~\cite{obj-c-book}, \CCeleven~\cite{C11}, C\#~\cite{Csharp} and Rust~\cite{Rust}, with a variety of presentation mechanisms.327 As a result, many languages adopt the 1:1 kernel-threading model, like Java (Scala), Objective-C~\cite{obj-c-book}, \CCeleven~\cite{C11}, C\#~\cite{Csharp} and Rust~\cite{Rust}, with a variety of presentation mechanisms. 324 328 From 2000 onwards, several language implementations have championed the M:N user-threading model, like Go~\cite{Go}, Erlang~\cite{Erlang}, Haskell~\cite{Haskell}, D~\cite{D}, and \uC~\cite{uC++,uC++book}, including putting green threads back into Java~\cite{Quasar}, and many user-threading libraries have appeared~\cite{Qthreads,MPC,Marcel}. 325 The main argument for user-level threading is that it is lighter weight than kernel threading (locking and context switching do not cross the kernel boundary), so there is less restriction on programming styles that encourages large numbers of threads performing medium-sized work to facilitate load balancing by the runtime~\cite{Verch12}.329 The main argument for user-level threading is that it is lighter weight than kernel threading because locking and context switching do not cross the kernel boundary, so there is less restriction on programming styles that encourages large numbers of threads performing medium-sized work to facilitate load balancing by the runtime~\cite{Verch12}. 326 330 As well, user-threading facilitates a simpler concurrency approach using thread objects that leverage sequential patterns versus events with call-backs~\cite{Adya02,vonBehren03}. 327 Finally, performant user-threading implementations (both time and space)meet or exceed direct kernel-threading implementations, while achieving the programming advantages of high concurrency levels and safety.331 Finally, performant user-threading implementations, both in time and space, meet or exceed direct kernel-threading implementations, while achieving the programming advantages of high concurrency levels and safety. 328 332 329 333 A further effort over the past two decades is the development of language memory models to deal with the conflict between language features and compiler/hardware optimizations, \eg some language features are unsafe in the presence of aggressive sequential optimizations~\cite{Buhr95a,Boehm05}. 330 The consequence is that a language must provide sufficient tools to program around safety issues, as inline and library code is all sequential to the compiler.331 One solution is low-level qualifiers and functions (\eg @volatile@ and atomics) allowing \emph{programmers} to explicitly write safe (race-free~\cite{Boehm12})programs.332 A safer solution is high-level language constructs so the \emph{compiler} knows the concurrency boundaries (where mutual exclusion and synchronization are acquired/released)and provide implicit safety at and across these boundaries.334 The consequence is that a language must provide sufficient tools to program around safety issues, as inline and library code is compiled as sequential without any explicit concurrent directive. 335 One solution is low-level qualifiers and functions, \eg @volatile@ and atomics, allowing \emph{programmers} to explicitly write safe, race-free~\cite{Boehm12} programs. 336 A safer solution is high-level language constructs so the \emph{compiler} knows the concurrency boundaries, \ie where mutual exclusion and synchronization are acquired and released, and provide implicit safety at and across these boundaries. 333 337 While the optimization problem is best known with respect to concurrency, it applies to other complex control-flow, like exceptions and coroutines. 334 338 As well, language solutions allow matching the language paradigm with the approach, \eg matching the functional paradigm with data-flow programming or the imperative paradigm with thread programming. 335 339 336 Finally, it is important for a language to provide safety over performance \emph{as the default}, allowing careful reduction of safety (unsafe code)for performance when necessary.337 Two concurrency violations of this philosophy are \emph{spurious wakeup} (random wakeup~\cite[\S~9]{Buhr05a})and \emph{barging}\footnote{340 Finally, it is important for a language to provide safety over performance \emph{as the default}, allowing careful reduction of safety for performance when necessary. 341 Two concurrency violations of this philosophy are \emph{spurious} or \emph{random wakeup}~\cite[\S~9]{Buhr05a}, and \emph{barging}\footnote{ 338 342 Barging is competitive succession instead of direct handoff, \ie after a lock is released both arriving and preexisting waiter threads compete to acquire the lock. 339 343 Hence, an arriving thread can temporally \emph{barge} ahead of threads already waiting for an event, which can repeat indefinitely leading to starvation of waiter threads. 340 } (signals-as-hints~\cite[\S~8]{Buhr05a}), where one is a consequence of the other, \ie once there is spurious wakeup, signals-as-hints follow.344 } or signals-as-hints~\cite[\S~8]{Buhr05a}, where one is a consequence of the other, \ie once there is spurious wakeup, barging follows. 341 345 (Author experience teaching concurrency is that students are confused by these semantics.) 342 346 However, spurious wakeup is \emph{not} a foundational concurrency property~\cite[\S~9]{Buhr05a}; … … 356 360 357 361 \item 358 monitor synchronization without barging, and the ability to safely acquiring multiple monitors \emph{simultaneously} (deadlock free), while seamlessly integrating these capabilities with all monitor synchronization mechanisms,362 monitor synchronization without barging, and the ability to safely acquiring multiple monitors in a deadlock-free way, while seamlessly integrating these capabilities with all monitor synchronization mechanisms, 359 363 360 364 \item … … 368 372 369 373 \item 370 a dynamic partitioning mechanism to segregate groups of executing user and kernel threads performing specialized work (\eg web-server or compute engine) or requiring different scheduling (\eg NUMA or real-time).374 a dynamic partitioning mechanism to segregate groups of executing user and kernel threads performing specialized work, \eg web-server or compute engine, or requiring different scheduling, \eg NUMA or real-time. 371 375 372 376 % \item … … 380 384 Section~\ref{s:StatefulFunction} begins advanced control by introducing sequential functions that retain data and execution state between calls producing constructs @generator@ and @coroutine@. 381 385 Section~\ref{s:Concurrency} begins concurrency, or how to create (fork) and destroy (join) a thread producing the @thread@ construct. 382 Section~\ref{s:MutualExclusionSynchronization} discusses the two mechanisms to restricted nondeterminism when controlling shared access to resources (mutual exclusion) and timing relationships among threads (synchronization).386 Section~\ref{s:MutualExclusionSynchronization} discusses the two mechanisms to restricted nondeterminism when controlling shared access to resources, called mutual exclusion, and timing relationships among threads, called synchronization. 383 387 Section~\ref{s:Monitor} shows how both mutual exclusion and synchronization are safely embedded in the @monitor@ and @thread@ constructs. 384 Section~\ref{s:CFARuntimeStructure} describes the large-scale mechanism to structure (cluster)threads and virtual processors (kernel threads).385 Section~\ref{s:Performance} uses a series of microbenchmarks to compare \CFA threading with pthreads, Java 11.0.6, Go 1.12.6, Rust 1.37.0, Python 3.7.6, Node.js 12.14.1, and \uC 7.0.0.388 Section~\ref{s:CFARuntimeStructure} describes the large-scale mechanism to structure threads and virtual processors (kernel threads). 389 Section~\ref{s:Performance} uses microbenchmarks to compare \CFA threading with pthreads, Java 11.0.6, Go 1.12.6, Rust 1.37.0, Python 3.7.6, Node.js v12.18.0, and \uC 7.0.0. 386 390 387 391 … … 389 393 \label{s:FundamentalExecutionProperties} 390 394 391 The features in a programming language should be composed froma set of fundamental properties rather than an ad hoc collection chosen by the designers.395 The features in a programming language should be composed of a set of fundamental properties rather than an ad hoc collection chosen by the designers. 392 396 To this end, the control-flow features created for \CFA are based on the fundamental properties of any language with function-stack control-flow (see also \uC~\cite[pp.~140-142]{uC++}). 393 The fundamental properties are execution state, thread, and mutual-exclusion/synchronization (MES).394 These independent properties can be used alone, in pairs, or in triplets to compose different language features, forming a compositional hierarchy where the most advanced feature has all the properties (state/thread/MES).395 While it is possible for a language to only support the most advanced feature~\cite{Hermes90}, this unnecessarily complicates and makes inefficient solutions to certain classes of problems.396 As is shown, each of the (non-rejected) composedfeatures solves a particular set of problems, and hence, has a defensible position in a programming language.397 If a compositional feature is missing, a programmer has too few /many fundamental properties resulting in a complex and/or isinefficient solution.397 The fundamental properties are execution state, thread, and mutual-exclusion/synchronization. 398 These independent properties can be used to compose different language features, forming a compositional hierarchy, where the combination of all three is the most advanced feature, called a thread. 399 While it is possible for a language to only provide threads for composing programs~\cite{Hermes90}, this unnecessarily complicates and makes inefficient solutions to certain classes of problems. 400 As is shown, each of the non-rejected composed language features solves a particular set of problems, and hence, has a defensible position in a programming language. 401 If a compositional feature is missing, a programmer has too few fundamental properties resulting in a complex and/or inefficient solution. 398 402 399 403 In detail, the fundamental properties are: 400 404 \begin{description}[leftmargin=\parindent,topsep=3pt,parsep=0pt] 401 405 \item[\newterm{execution state}:] 402 is the state information needed by a control-flow feature to initialize, manage compute data and execution location(s), and de-initialize. 403 State is retained in fixed-sized aggregate structures and dynamic-sized stack(s), often allocated in the heap(s) managed by the runtime system. 404 The lifetime of the state varies with the control-flow feature, where longer life-time and dynamic size provide greater power but also increase usage complexity and cost. 405 Control-flow transfers among execution states occurs in multiple ways, such as function call, context switch, asynchronous await, etc. 406 is the state information needed by a control-flow feature to initialize and manage both compute data and execution location(s), and de-initialize. 407 For example, calling a function initializes a stack frame including contained objects with constructors, manages local data in blocks and return locations during calls, and de-initializes the frame by running any object destructors and management operations. 408 State is retained in fixed-sized aggregate structures (objects) and dynamic-sized stack(s), often allocated in the heap(s) managed by the runtime system. 409 The lifetime of state varies with the control-flow feature, where longer life-time and dynamic size provide greater power but also increase usage complexity and cost. 410 Control-flow transfers among execution states in multiple ways, such as function call, context switch, asynchronous await, etc. 406 411 Because the programming language determines what constitutes an execution state, implicitly manages this state, and defines movement mechanisms among states, execution state is an elementary property of the semantics of a programming language. 407 412 % An execution-state is related to the notion of a process continuation \cite{Hieb90}. 408 413 409 414 \item[\newterm{threading}:] 410 is execution of code that occurs independently of other execution, \ie the execution resulting from a threadis sequential.415 is execution of code that occurs independently of other execution, where an individual thread's execution is sequential. 411 416 Multiple threads provide \emph{concurrent execution}; 412 concurrent execution becomes parallel when run on multiple processing units (hyper-threading, cores, sockets).413 There must be language mechanisms to create, block/unblock, and join with a thread.414 415 \item[\newterm{ MES}:]416 is the concurrency mechanism sto perform an action without interruption and establish timing relationships among multiple threads.417 These two properties are independent, \ie mutual exclusion cannot provide synchronization and vice versa without introducing additional threads~\cite[\S~4]{Buhr05a}.418 Limiting MES , \eg no access to shared data,results in contrived solutions and inefficiency on multi-core von Neumann computers where shared memory is a foundational aspect of its design.417 concurrent execution becomes parallel when run on multiple processing units, \eg hyper-threading, cores, or sockets. 418 A programmer needs mechanisms to create, block and unblock, and join with a thread, even if these basic mechanisms are supplied indirectly through high-level features. 419 420 \item[\newterm{mutual-exclusion / synchronization (MES)}:] 421 is the concurrency mechanism to perform an action without interruption and establish timing relationships among multiple threads. 422 We contented these two properties are independent, \ie mutual exclusion cannot provide synchronization and vice versa without introducing additional threads~\cite[\S~4]{Buhr05a}. 423 Limiting MES functionality results in contrived solutions and inefficiency on multi-core von Neumann computers where shared memory is a foundational aspect of its design. 419 424 \end{description} 420 These properties are fundamental because they cannot be built from existing language features, \eg a basic programming language like C99~\cite{C99} cannot create new control-flow features, concurrency, or provide MES using atomic hardware mechanisms. 421 422 423 \subsection{Execution Properties} 424 425 Table~\ref{t:ExecutionPropertyComposition} shows how the three fundamental execution properties: state, thread, and mutual exclusion compose a hierarchy of control-flow features needed in a programming language. 426 (When doing case analysis, not all combinations are meaningful.) 427 Note, basic von Neumann execution requires at least one thread and an execution state providing some form of call stack. 425 These properties are fundamental as they cannot be built from existing language features, \eg a basic programming language like C99~\cite{C99} cannot create new control-flow features, concurrency, or provide MES without (atomic) hardware mechanisms. 426 427 428 \subsection{Structuring Execution Properties} 429 430 Programming languages seldom present the fundamental execution properties directly to programmers. 431 Instead, the properties are packaged into higher-level constructs that encapsulate details and provide safety to these low-level mechanisms. 432 Interestingly, language designers often pick and choose among these execution properties proving a varying subset of constructs. 433 434 Table~\ref{t:ExecutionPropertyComposition} shows all combinations of the three fundamental execution properties available to language designers. 435 (When doing combination case-analysis, not all combinations are meaningful.) 436 The combinations of state, thread, and MES compose a hierarchy of control-flow features all of which have appeared in prior programming languages, where each of these languages have found the feature useful. 437 To understand the table, it is important to review the basic von Neumann execution requirement of at least one thread and execution state providing some form of call stack. 428 438 For table entries missing these minimal components, the property is borrowed from the invoker (caller). 429 430 Case 1 is a function that borrows storage for its state (stack frame/activation) and a thread from its invoker and retains this state across \emph{callees}, \ie function local-variables are retained on the stack across calls. 431 Case 2 is case 1 with access to shared state so callers are restricted during update (mutual exclusion) and scheduling for other threads (synchronization). 432 Case 3 is a stateful function supporting resume/suspend along with call/return to retain state across \emph{callers}, but has some restrictions because the function's state is stackless. 433 Note, stackless functions still borrow the caller's stack and thread, where the stack is used to preserve state across its callees. 434 Case 4 is cases 2 and 3 with protection to shared state for stackless functions. 435 Cases 5 and 6 are the same as 3 and 4 but only the thread is borrowed as the function state is stackful, so resume/suspend is a context switch from the caller's to the function's stack. 436 Cases 7 and 8 are rejected because a function that is given a new thread must have its own stack where the thread begins and stack frames are stored for calls, \ie there is no stack to borrow. 437 Cases 9 and 10 are rejected because a thread with a fixed state (no stack) cannot accept calls, make calls, block, or be preempted, all of which require an unknown amount of additional dynamic state. 438 Hence, once started, this kind of thread must execute to completion, \ie computation only, which severely restricts runtime management. 439 Cases 11 and 12 have a stackful thread with and without safe access to shared state. 440 Execution properties increase the cost of creation and execution along with complexity of usage. 439 Each entry in the table, numbered \textbf{1}--\textbf{12}, is discussed with respect to how the execution properties combine to generate a high-level language construct. 441 440 442 441 \begin{table} … … 446 445 \renewcommand{\arraystretch}{1.25} 447 446 %\setlength{\tabcolsep}{5pt} 447 \vspace*{-5pt} 448 448 \begin{tabular}{c|c||l|l} 449 449 \multicolumn{2}{c||}{execution properties} & \multicolumn{2}{c}{mutual exclusion / synchronization} \\ … … 452 452 \hline 453 453 \hline 454 No & No & \textbf{1}\ \ \ function & \textbf{2}\ \ \ @monitor@ function\\454 No & No & \textbf{1}\ \ \ @struct@ & \textbf{2}\ \ \ @mutex@ @struct@ \\ 455 455 \hline 456 Yes (stackless) & No & \textbf{3}\ \ \ @generator@ & \textbf{4}\ \ \ @m onitor@ @generator@ \\456 Yes (stackless) & No & \textbf{3}\ \ \ @generator@ & \textbf{4}\ \ \ @mutex@ @generator@ \\ 457 457 \hline 458 Yes (stackful) & No & \textbf{5}\ \ \ @coroutine@ & \textbf{6}\ \ \ @m onitor@ @coroutine@ \\458 Yes (stackful) & No & \textbf{5}\ \ \ @coroutine@ & \textbf{6}\ \ \ @mutex@ @coroutine@ \\ 459 459 \hline 460 460 No & Yes & \textbf{7}\ \ \ {\color{red}rejected} & \textbf{8}\ \ \ {\color{red}rejected} \\ … … 462 462 Yes (stackless) & Yes & \textbf{9}\ \ \ {\color{red}rejected} & \textbf{10}\ \ \ {\color{red}rejected} \\ 463 463 \hline 464 Yes (stackful) & Yes & \textbf{11}\ \ \ @thread@ & \textbf{12}\ \ @m onitor@ @thread@ \\464 Yes (stackful) & Yes & \textbf{11}\ \ \ @thread@ & \textbf{12}\ \ @mutex@ @thread@ \\ 465 465 \end{tabular} 466 \vspace*{-8pt} 466 467 \end{table} 467 468 468 Given the execution-properties taxonomy, programmers can now answer three basic questions: is state necessary across calls and how much, is a separate thread necessary, is access to shared state necessary. 469 The answers define the optimal language feature need for implementing a programming problem. 470 The next sections discusses how \CFA fills in the table with language features, while other programming languages may only provide a subset of the table. 469 Case 1 is a structure where access functions borrow local state (stack frame/activation) and thread from the invoker and retain this state across \emph{callees}, \ie function local-variables are retained on the borrowed stack during calls. 470 Structures are a foundational mechanism for data organization, and access functions provide interface abstraction and code sharing in all programming languages. 471 Case 2 is case 1 with thread safety to a structure's state where access functions provide serialization (mutual exclusion) and scheduling among calling threads (synchronization). 472 A @mutex@ structure, often called a \newterm{monitor}, provides a high-level interface for race-free access of shared data in concurrent programming-languages. 473 Case 3 is case 1 where the structure can implicitly retain execution state and access functions use this execution state to resume/suspend across \emph{callers}, but resume/suspend does not retain a function's local state. 474 A stackless structure, often called a \newterm{generator} or \emph{iterator}, is \newterm{stackless} because it still borrows the caller's stack and thread, but the stack is used only to preserve state across its callees not callers. 475 Generators provide the first step toward directly solving problems like finite-state machines that retain data and execution state between calls, whereas normal functions restart on each call. 476 Case 4 is cases 2 and 3 with thread safety during execution of the generator's access functions. 477 A @mutex@ generator extends generators into the concurrent domain. 478 Cases 5 and 6 are like cases 3 and 4 where the structure is extended with an implicit separate stack, so only the thread is borrowed by access functions. 479 A stackful generator, often called a \newterm{coroutine}, is \newterm{stackful} because resume/suspend now context switch to/from the caller's and coroutine's stack. 480 A coroutine extends the state retained between calls beyond the generator's structure to arbitrary call depth in the access functions. 481 Cases 7, 8, 9 and 10 are rejected because a new thread must have its own stack, where the thread begins and stack frames are stored for calls, \ie it is unrealistic for a thread to borrow a stack. 482 For cases 9 and 10, the stackless frame is not growable, precluding accepting nested calls, making calls, blocking as it requires calls, or preemption as it requires pushing an interrupt frame, all of which compound to require an unknown amount of execution state. 483 Hence, if this kind of uninterruptable thread exists, it must execute to completion, \ie computation only, which severely restricts runtime management. 484 Cases 11 and 12 are a stackful thread with and without safe access to shared state. 485 A thread is the language mechanism to start another thread of control in a program with growable execution state for call/return execution. 486 In general, language constructs with more execution properties increase the cost of creation and execution along with complexity of usage. 487 488 Given the execution-properties taxonomy, programmers now ask three basic questions: is state necessary across callers and how much, is a separate thread necessary, is thread safety necessary. 489 Table~\ref{t:ExecutionPropertyComposition} then suggests the optimal language feature needed for implementing a programming problem. 490 The following sections describe how \CFA fills in \emph{all} the non-rejected table entries with language features, while other programming languages may only provide a subset of the table. 471 491 472 492 … … 481 501 \item 482 502 Direct interaction among language features must be possible allowing any feature to be selected without restricting comm\-unication. 483 For example, many concurrent languages do not provide direct communication (calls)among threads, \ie threads only communicate indirectly through monitors, channels, messages, and/or futures.484 Indirect communication increases the number of objects, consuming more resources, and require additional synchronization and possibly data transfer.503 For example, many concurrent languages do not provide direct communication calls among threads, \ie threads only communicate indirectly through monitors, channels, messages, and/or futures. 504 Indirect communication increases the number of objects, consuming more resources, and requires additional synchronization and possibly data transfer. 485 505 486 506 \item … … 493 513 494 514 \item 495 MES must be available implicitly in language constructs as well as explicitly for specialized requirements, because requiring programmers to build MES using low-level locks often leads to incorrect programs.515 MES must be available implicitly in language constructs, \eg Java built-in monitors, as well as explicitly for specialized requirements, \eg @java.util.concurrent@, because requiring programmers to build MES using low-level locks often leads to incorrect programs. 496 516 Furthermore, reducing synchronization scope by encapsulating it within language constructs further reduces errors in concurrent programs. 497 517 … … 502 522 \item 503 523 Synchronization must be able to control the service order of requests including prioritizing selection from different kinds of outstanding requests, and postponing a request for an unspecified time while continuing to accept new requests. 504 Otherwise, certain concurrency problems are difficult, e.g.\web server, disk scheduling, and the amount of concurrency is inhibited~\cite{Gentleman81}.524 Otherwise, certain concurrency problems are difficult, \eg web server, disk scheduling, and the amount of concurrency is inhibited~\cite{Gentleman81}. 505 525 \end{itemize} 506 526 We have satisfied these requirements in \CFA while maintaining backwards compatibility with the huge body of legacy C programs. … … 511 531 512 532 Asynchronous await/call is a caller mechanism for structuring programs and/or increasing concurrency, where the caller (client) postpones an action into the future, which is subsequently executed by a callee (server). 513 The caller detects the action's completion through a \newterm{future} /\newterm{promise}.533 The caller detects the action's completion through a \newterm{future} or \newterm{promise}. 514 534 The benefit is asynchronous caller execution with respect to the callee until future resolution. 515 535 For single-threaded languages like JavaScript, an asynchronous call passes a callee action, which is queued in the event-engine, and continues execution with a promise. … … 517 537 A promise-completion call-back can be part of the callee action or the caller is rescheduled; 518 538 in either case, the call back is executed after the promise is fulfilled. 519 While asynchronous calls generate new callee (server) events, we conten t this mechanism is insufficient for advanced control-flow mechanisms like generators or coroutines (which are discussed next).539 While asynchronous calls generate new callee (server) events, we contend this mechanism is insufficient for advanced control-flow mechanisms like generators or coroutines, which are discussed next. 520 540 Specifically, control between caller and callee occurs indirectly through the event-engine precluding direct handoff and cycling among events, and requires complex resolution of a control promise and data. 521 541 Note, @async-await@ is just syntactic-sugar over the event engine so it does not solve these deficiencies. 522 542 For multi-threaded languages like Java, the asynchronous call queues a callee action with an executor (server), which subsequently executes the work by a thread in the executor thread-pool. 523 The problem is when concurrent work-units need to interact and/or block as this effects the executor , \eg stopsthreads.543 The problem is when concurrent work-units need to interact and/or block as this effects the executor by stopping threads. 524 544 While it is possible to extend this approach to support the necessary mechanisms, \eg message passing in Actors, we show monitors and threads provide an equally competitive approach that does not deviate from normal call communication and can be used to build asynchronous call, as is done in Java. 525 545 … … 540 560 There are two styles of activating a stateful function, \emph{asymmetric} or \emph{symmetric}, identified by resume/suspend (no cycles) and resume/resume (cycles). 541 561 These styles \emph{do not} cause incremental stack growth, \eg a million resume/suspend or resume/resume cycles do not remember each cycle just the last resumer for each cycle. 542 Selecting between stackless/stackful semantics and asymmetric/symmetric style is a tradeoff between programming requirements, performance, and design, where stackless is faster and smaller (modified call/return between closures), stackful is more general but slower and larger (context switching between distinct stacks), and asymmetric is simpler control-flow than symmetric.543 Additionally, storage management for the closure/stack (especially in unmanaged languages, \ie no garbage collection) must be factored into design and performance.562 Selecting between stackless/stackful semantics and asymmetric/symmetric style is a tradeoff between programming requirements, performance, and design, where stackless is faster and smaller using modified call/return between closures, stackful is more general but slower and larger using context switching between distinct stacks, and asymmetric is simpler control-flow than symmetric. 563 Additionally, storage management for the closure/stack must be factored into design and performance, especially in unmanaged languages without garbage collection. 544 564 Note, creation cost (closure/stack) is amortized across usage, so activation cost (resume/suspend) is usually the dominant factor. 545 565 … … 578 598 & 579 599 \begin{cfa} 580 void * rtn( void * arg ) { ... }600 void * `rtn`( void * arg ) { ... } 581 601 int i = 3, rc; 582 602 pthread_t t; $\C{// thread id}$ … … 690 710 \hspace{3pt} 691 711 \subfloat[C generated code for \CFA version]{\label{f:CFibonacciSim}\usebox\myboxC} 692 \caption{Fibonacci (output)asymmetric generator}712 \caption{Fibonacci output asymmetric generator} 693 713 \label{f:FibonacciAsymmetricGenerator} 694 714 … … 765 785 \subfloat[C generated code for \CFA version]{\label{f:CFormatGenImpl}\usebox\myboxB} 766 786 \hspace{3pt} 767 \caption{Formatter (input)asymmetric generator}787 \caption{Formatter input asymmetric generator} 768 788 \label{f:FormatterAsymmetricGenerator} 769 789 \end{figure} 770 790 771 Figure~\ref{f:FibonacciAsymmetricGenerator} shows an unbounded asymmetric generator for an infinite sequence of Fibonacci numbers written (left to right)in C, \CFA, and showing the underlying C implementation for the \CFA version.791 Figure~\ref{f:FibonacciAsymmetricGenerator} shows an unbounded asymmetric generator for an infinite sequence of Fibonacci numbers written left to right in C, \CFA, and showing the underlying C implementation for the \CFA version. 772 792 This generator is an \emph{output generator}, producing a new result on each resumption. 773 793 To compute Fibonacci, the previous two values in the sequence are retained to generate the next value, \ie @fn1@ and @fn@, plus the execution location where control restarts when the generator is resumed, \ie top or middle. 774 An additional requirement is the ability to create an arbitrary number of generators (of any kind), \ie retaining one state in global variables is insufficient;794 An additional requirement is the ability to create an arbitrary number of generators of any kind, \ie retaining one state in global variables is insufficient; 775 795 hence, state is retained in a closure between calls. 776 796 Figure~\ref{f:CFibonacci} shows the C approach of manually creating the closure in structure @Fib@, and multiple instances of this closure provide multiple Fibonacci generators. … … 794 814 Figure~\ref{f:CFibonacciSim} shows the C implementation of the \CFA asymmetric generator. 795 815 Only one execution-state field, @restart@, is needed to subscript the suspension points in the generator. 796 At the start of the generator main, the @static@ declaration, @states@, is initialized to the N suspend points in the generator (where operator @&&@ dereferences/references a label~\cite{gccValueLabels}).816 At the start of the generator main, the @static@ declaration, @states@, is initialized to the N suspend points in the generator, where operator @&&@ dereferences or references a label~\cite{gccValueLabels}. 797 817 Next, the computed @goto@ selects the last suspend point and branches to it. 798 The cost of setting @restart@ and branching via the computed @goto@ adds very little cost to the suspend /resume calls.818 The cost of setting @restart@ and branching via the computed @goto@ adds very little cost to the suspend and resume calls. 799 819 800 820 An advantage of the \CFA explicit generator type is the ability to allow multiple type-safe interface functions taking and returning arbitrary types. … … 877 897 With respect to safety, we believe static analysis can discriminate persistent generator state from temporary generator-main state and raise a compile-time error for temporary usage spanning suspend points. 878 898 Our experience using generators is that the problems have simple data state, including local state, but complex execution state, so the burden of creating the generator type is small. 879 As well, C programmers are not afraid of this kind of semantic programming requirement, if it results in very small ,fast generators.899 As well, C programmers are not afraid of this kind of semantic programming requirement, if it results in very small and fast generators. 880 900 881 901 Figure~\ref{f:CFAFormatGen} shows an asymmetric \newterm{input generator}, @Fmt@, for restructuring text into groups of characters of fixed-size blocks, \ie the input on the left is reformatted into the output on the right, where newlines are ignored. … … 899 919 The destructor provides a newline, if formatted text ends with a full line. 900 920 Figure~\ref{f:CFormatGenImpl} shows the C implementation of the \CFA input generator with one additional field and the computed @goto@. 901 For contrast, Figure~\ref{f:PythonFormatter} shows the equivalent Python format generator with the same properties as the format generator.921 For contrast, Figure~\ref{f:PythonFormatter} shows the equivalent Python format generator with the same properties as the \CFA format generator. 902 922 903 923 % https://dl-acm-org.proxy.lib.uwaterloo.ca/ 904 924 905 Figure~\ref{f:DeviceDriverGen} shows an important application for an asymmetric generator,a device-driver, because device drivers are a significant source of operating-system errors: 85\% in Windows XP~\cite[p.~78]{Swift05} and 51.6\% in Linux~\cite[p.~1358,]{Xiao19}. %\cite{Palix11}925 An important application for the asymmetric generator is a device-driver, because device drivers are a significant source of operating-system errors: 85\% in Windows XP~\cite[p.~78]{Swift05} and 51.6\% in Linux~\cite[p.~1358,]{Xiao19}. %\cite{Palix11} 906 926 Swift \etal~\cite[p.~86]{Swift05} restructure device drivers using the Extension Procedure Call (XPC) within the kernel via functions @nooks_driver_call@ and @nooks_kernel_call@, which have coroutine properties context switching to separate stacks with explicit hand-off calls; 907 927 however, the calls do not retain execution state, and hence always start from the top. … … 909 929 However, Adya \etal~\cite{Adya02} argue against stack ripping in Section 3.2 and suggest a hybrid approach in Section 4 using cooperatively scheduled \emph{fibers}, which is coroutining. 910 930 911 As an example,the following protocol:931 Figure~\ref{f:DeviceDriverGen} shows the generator advantages in implementing a simple network device-driver with the following protocol: 912 932 \begin{center} 913 933 \ldots\, STX \ldots\, message \ldots\, ESC ETX \ldots\, message \ldots\, ETX 2-byte crc \ldots 914 934 \end{center} 915 is for a simple network message beginning with the control character STX, ending with an ETX, andfollowed by a 2-byte cyclic-redundancy check.935 where the network message begins with the control character STX, ends with an ETX, and is followed by a 2-byte cyclic-redundancy check. 916 936 Control characters may appear in a message if preceded by an ESC. 917 937 When a message byte arrives, it triggers an interrupt, and the operating system services the interrupt by calling the device driver with the byte read from a hardware register. 918 The device driver returns a status code of its current state, and when a complete message is obtained, the operating system read the message accumulated in the supplied buffer.919 Hence, the device driver is an input/output generator, where the cost of resuming the device-driver generator is the same as call /return, so performance in an operating-system kernel is excellent.938 The device driver returns a status code of its current state, and when a complete message is obtained, the operating system reads the message accumulated in the supplied buffer. 939 Hence, the device driver is an input/output generator, where the cost of resuming the device-driver generator is the same as call and return, so performance in an operating-system kernel is excellent. 920 940 The key benefits of using a generator are correctness, safety, and maintenance because the execution states are transcribed directly into the programming language rather than table lookup or stack ripping. 921 The conclusion is that FSMs are complex and occur in important domains, so direct generator support is important in a system programming language.941 % The conclusion is that FSMs are complex and occur in important domains, so direct generator support is important in a system programming language. 922 942 923 943 \begin{figure} … … 976 996 \end{figure} 977 997 978 Figure~\ref{f:CFAPingPongGen} shows a symmetric generator, where the generator resumes another generator, forming a resume/resume cycle.998 Generators can also have symmetric activation using resume/resume to create control-flow cycles among generators. 979 999 (The trivial cycle is a generator resuming itself.) 980 1000 This control flow is similar to recursion for functions but without stack growth. 981 Figure~\ref{f:PingPongFullCoroutineSteps} shows the steps for symmetric control-flow are creating, executing, and terminating the cycle. 1001 Figure~\ref{f:PingPongFullCoroutineSteps} shows the steps for symmetric control-flow using for the ping/pong program in Figure~\ref{f:CFAPingPongGen}. 1002 The program starts by creating the generators, @ping@ and @pong@, and then assigns the partners that form the cycle. 982 1003 Constructing the cycle must deal with definition-before-use to close the cycle, \ie, the first generator must know about the last generator, which is not within scope. 983 1004 (This issue occurs for any cyclic data structure.) 984 The example creates the generators, @ping@/@pong@, and then assigns the partners that form the cycle.985 1005 % (Alternatively, the constructor can assign the partners as they are declared, except the first, and the first-generator partner is set after the last generator declaration to close the cycle.) 986 Once the cycle is formed, the program main resumes one of the generators, @ping@, and the generators can then traverse an arbitrary cycleusing @resume@ to activate partner generator(s).1006 Once the cycle is formed, the program main resumes one of the generators, @ping@, and the generators can then traverse an arbitrary number of cycles using @resume@ to activate partner generator(s). 987 1007 Terminating the cycle is accomplished by @suspend@ or @return@, both of which go back to the stack frame that started the cycle (program main in the example). 988 1008 Note, the creator and starter may be different, \eg if the creator calls another function that starts the cycle. … … 990 1010 Also, since local variables are not retained in the generator function, there are no objects with destructors to be called, so the cost is the same as a function return. 991 1011 Destructor cost occurs when the generator instance is deallocated by the creator. 1012 1013 \begin{figure} 1014 \centering 1015 \input{FullCoroutinePhases.pstex_t} 1016 \vspace*{-10pt} 1017 \caption{Symmetric coroutine steps: Ping / Pong} 1018 \label{f:PingPongFullCoroutineSteps} 1019 \end{figure} 992 1020 993 1021 \begin{figure} … … 1053 1081 \end{figure} 1054 1082 1055 \begin{figure}1056 \centering1057 \input{FullCoroutinePhases.pstex_t}1058 \vspace*{-10pt}1059 \caption{Symmetric coroutine steps: Ping / Pong}1060 \label{f:PingPongFullCoroutineSteps}1061 \end{figure}1062 1063 1083 Figure~\ref{f:CPingPongSim} shows the C implementation of the \CFA symmetric generator, where there is still only one additional field, @restart@, but @resume@ is more complex because it does a forward rather than backward jump. 1064 1084 Before the jump, the parameter for the next call @partner@ is placed into the register used for the first parameter, @rdi@, and the remaining registers are reset for a return. … … 1066 1086 While the semantics of call forward is a tail-call optimization, which compilers perform, the generator state is different on each call rather a common state for a tail-recursive function (i.e., the parameter to the function never changes during the forward calls. 1067 1087 However, this assembler code depends on what entry code is generated, specifically if there are local variables and the level of optimization. 1068 Hence, internal compiler support is necessary for any forward call (or backwards return), \eg LLVM has various coroutine support~\cite{CoroutineTS}, and \CFA can leverage this support should it eventually fork @clang@.1069 For this reason, \CFA does not support general symmetric generators at this time, but, it is possible to hand generate any symmetric generators (as in Figure~\ref{f:CPingPongSim})for proof of concept and performance testing.1088 Hence, internal compiler support is necessary for any forward call or backwards return, \eg LLVM has various coroutine support~\cite{CoroutineTS}, and \CFA can leverage this support should it eventually fork @clang@. 1089 For this reason, \CFA does not support general symmetric generators at this time, but, it is possible to hand generate any symmetric generators, as in Figure~\ref{f:CPingPongSim}, for proof of concept and performance testing. 1070 1090 1071 1091 Finally, part of this generator work was inspired by the recent \CCtwenty coroutine proposal~\cite{C++20Coroutine19}, which uses the general term coroutine to mean generator. … … 1084 1104 \label{s:Coroutine} 1085 1105 1086 Stackful coroutines (Table~\ref{t:ExecutionPropertyComposition} case 5) extend generator semantics, \ie there is an implicit closure and @suspend@ may appear in a helper function called from the coroutine main. 1087 A coroutine is specified by replacing @generator@ with @coroutine@ for the type. 1106 Stackful coroutines (Table~\ref{t:ExecutionPropertyComposition} case 5) extend generator semantics with an implicit closure and @suspend@ may appear in a helper function called from the coroutine main because of the separate stack. 1107 Note, simulating coroutines with stacks of generators, \eg Python with @yield from@ cannot handle symmetric control-flow. 1108 Furthermore, all stack components must be of generators, so it is impossible to call a library function passing a generator that yields. 1109 Creating a generator copy of the library function maybe impossible because the library function is opaque. 1110 1111 A \CFA coroutine is specified by replacing @generator@ with @coroutine@ for the type. 1088 1112 Coroutine generality results in higher cost for creation, due to dynamic stack allocation, for execution, due to context switching among stacks, and for terminating, due to possible stack unwinding and dynamic stack deallocation. 1089 1113 A series of different kinds of coroutines and their implementations demonstrate how coroutines extend generators. 1090 1114 1091 1115 First, the previous generator examples are converted to their coroutine counterparts, allowing local-state variables to be moved from the generator type into the coroutine main. 1116 Now the coroutine type only contains communication variables between interface functions and the coroutine main. 1092 1117 \begin{center} 1093 1118 \begin{tabular}{@{}l|l|l|l@{}} … … 1126 1151 \begin{cfa} 1127 1152 int Crc() { 1128 `suspend;` 1129 short int crc = byte << 8; 1130 `suspend;` 1131 status = (crc | byte) == sum ? MSG : ECRC; 1153 `suspend;` short int crc = byte << 8; 1154 `suspend;` status = (crc | byte) == sum ? MSG : ECRC; 1132 1155 return crc; 1133 1156 } 1134 1157 \end{cfa} 1135 A call to this function is placed at the end of the d river's coroutine-main.1158 A call to this function is placed at the end of the device driver's coroutine-main. 1136 1159 For complex finite-state machines, refactoring is part of normal program abstraction, especially when code is used in multiple places. 1137 1160 Again, this complexity is usually associated with execution state rather than data state. … … 1139 1162 \begin{comment} 1140 1163 Figure~\ref{f:Coroutine3States} creates a @coroutine@ type, @`coroutine` Fib { int fn; }@, which provides communication, @fn@, for the \newterm{coroutine main}, @main@, which runs on the coroutine stack, and possibly multiple interface functions, \eg @restart@. 1141 Like the structure in Figure~\ref{f:ExternalState}, the coroutine type allows multiple instances, where instances of this type are passed to the (overloaded)coroutine main.1164 Like the structure in Figure~\ref{f:ExternalState}, the coroutine type allows multiple instances, where instances of this type are passed to the overloaded coroutine main. 1142 1165 The coroutine main's stack holds the state for the next generation, @f1@ and @f2@, and the code represents the three states in the Fibonacci formula via the three suspend points, to context switch back to the caller's @resume@. 1143 1166 The interface function @restart@, takes a Fibonacci instance and context switches to it using @resume@; … … 1373 1396 1374 1397 Figure~\ref{f:ProdCons} shows the ping-pong example in Figure~\ref{f:CFAPingPongGen} extended into a producer/consumer symmetric-coroutine performing bidirectional communication. 1375 This example is illustrative because both producer /consumer have two interface functions with @resume@s that suspend execution in these interface (helper)functions.1398 This example is illustrative because both producer and consumer have two interface functions with @resume@s that suspend execution in these interface functions. 1376 1399 The program main creates the producer coroutine, passes it to the consumer coroutine in its initialization, and closes the cycle at the call to @start@ along with the number of items to be produced. 1377 1400 The call to @start@ is the first @resume@ of @prod@, which remembers the program main as the starter and creates @prod@'s stack with a frame for @prod@'s coroutine main at the top, and context switches to it. 1378 1401 @prod@'s coroutine main starts, creates local-state variables that are retained between coroutine activations, and executes $N$ iterations, each generating two random values, calling the consumer's @deliver@ function to transfer the values, and printing the status returned from the consumer. 1379 The producer call to @delivery@ transfers values into the consumer's communication variables, resumes the consumer, and returns the consumer status.1402 The producer's call to @delivery@ transfers values into the consumer's communication variables, resumes the consumer, and returns the consumer status. 1380 1403 Similarly on the first resume, @cons@'s stack is created and initialized, holding local-state variables retained between subsequent activations of the coroutine. 1381 1404 The symmetric coroutine cycle forms when the consumer calls the producer's @payment@ function, which resumes the producer in the consumer's delivery function. 1382 1405 When the producer calls @delivery@ again, it resumes the consumer in the @payment@ function. 1383 Both interface function than return to thetheir corresponding coroutine-main functions for the next cycle.1406 Both interface functions then return to their corresponding coroutine-main functions for the next cycle. 1384 1407 Figure~\ref{f:ProdConsRuntimeStacks} shows the runtime stacks of the program main, and the coroutine mains for @prod@ and @cons@ during the cycling. 1385 1408 As a consequence of a coroutine retaining its last resumer for suspending back, these reverse pointers allow @suspend@ to cycle \emph{backwards} around a symmetric coroutine cycle. … … 1395 1418 1396 1419 Terminating a coroutine cycle is more complex than a generator cycle, because it requires context switching to the program main's \emph{stack} to shutdown the program, whereas generators started by the program main run on its stack. 1397 Furthermore, each deallocated coroutine must execute all destructors for object allocated in the coroutine type \emph{and} allocated on the coroutine's stack at the point of suspension, which can be arbitrarily deep.1420 Furthermore, each deallocated coroutine must execute all destructors for objects allocated in the coroutine type \emph{and} allocated on the coroutine's stack at the point of suspension, which can be arbitrarily deep. 1398 1421 In the example, termination begins with the producer's loop stopping after N iterations and calling the consumer's @stop@ function, which sets the @done@ flag, resumes the consumer in function @payment@, terminating the call, and the consumer's loop in its coroutine main. 1399 1422 % (Not shown is having @prod@ raise a nonlocal @stop@ exception at @cons@ after it finishes generating values and suspend back to @cons@, which catches the @stop@ exception to terminate its loop.) … … 1401 1424 The question now is where does control continue? 1402 1425 1403 The na\"{i}ve semantics for coroutine-cycle termination is to context switch to the last resumer, like executing a @suspend@ /@return@ in a generator.1426 The na\"{i}ve semantics for coroutine-cycle termination is to context switch to the last resumer, like executing a @suspend@ or @return@ in a generator. 1404 1427 However, for coroutines, the last resumer is \emph{not} implicitly below the current stack frame, as for generators, because each coroutine's stack is independent. 1405 1428 Unfortunately, it is impossible to determine statically if a coroutine is in a cycle and unrealistic to check dynamically (graph-cycle problem). … … 1410 1433 For asymmetric coroutines, it is common for the first resumer (starter) coroutine to be the only resumer; 1411 1434 for symmetric coroutines, it is common for the cycle creator to persist for the lifetime of the cycle. 1412 For other scenarios, it is always possible to devise a solution with additional programming effort, such as forcing the cycle forward (backward)to a safe point before starting termination.1435 For other scenarios, it is always possible to devise a solution with additional programming effort, such as forcing the cycle forward or backward to a safe point before starting termination. 1413 1436 1414 1437 Note, the producer/consumer example does not illustrate the full power of the starter semantics because @cons@ always ends first. 1415 1438 Assume generator @PingPong@ in Figure~\ref{f:PingPongSymmetricGenerator} is converted to a coroutine. 1416 1439 Unlike generators, coroutines have a starter structure with multiple levels, where the program main starts @ping@ and @ping@ starts @pong@. 1417 By adjusting $N$ for either @ping@ /@pong@, it is possible to have either finish first.1440 By adjusting $N$ for either @ping@ or @pong@, it is possible to have either finish first. 1418 1441 If @pong@ ends first, it resumes its starter @ping@ in its coroutine main, then @ping@ ends and resumes its starter the program main on return; 1419 1442 if @ping@ ends first, it resumes its starter the program main on return. 1420 1443 Regardless of the cycle complexity, the starter structure always leads back to the program main, but the path can be entered at an arbitrary point. 1421 Once back at the program main (creator), coroutines @ping@ and @pong@ are deallocated, runn ning any destructors for objects within the coroutine and possibly deallocating any coroutine stacks for non-terminated coroutines, where stack deallocation implies stack unwinding to find destructors for allocated objects on the stack.1422 Hence, the \CFA termination semantics for the generator and coroutine ensure correct deallocation sem natics, regardless of the coroutine's state (terminated or active), like any other aggregate object.1444 Once back at the program main (creator), coroutines @ping@ and @pong@ are deallocated, running any destructors for objects within the coroutine and possibly deallocating any coroutine stacks for non-terminated coroutines, where stack deallocation implies stack unwinding to find destructors for allocated objects on the stack. 1445 Hence, the \CFA termination semantics for the generator and coroutine ensure correct deallocation semantics, regardless of the coroutine's state (terminated or active), like any other aggregate object. 1423 1446 1424 1447 1425 1448 \subsection{Generator / Coroutine Implementation} 1426 1449 1427 A significant implementation challenge for generators /coroutines (and threads in Section~\ref{s:threads}) is adding extra fields to the custom types and related functions, \eg inserting code after/before the coroutine constructor/destructor and @main@ to create/initialize/de-initialize/destroy any extra fields, \egstack.1428 There are several solutions to th eseproblem, which follow from the object-oriented flavour of adopting custom types.1450 A significant implementation challenge for generators and coroutines (and threads in Section~\ref{s:threads}) is adding extra fields to the custom types and related functions, \eg inserting code after/before the coroutine constructor/destructor and @main@ to create/initialize/de-initialize/destroy any extra fields, \eg the coroutine stack. 1451 There are several solutions to this problem, which follow from the object-oriented flavour of adopting custom types. 1429 1452 1430 1453 For object-oriented languages, inheritance is used to provide extra fields and code via explicit inheritance: … … 1433 1456 \end{cfa} 1434 1457 % The problem is that the programming language and its tool chain, \eg debugger, @valgrind@, need to understand @baseCoroutine@ because it infers special property, so type @baseCoroutine@ becomes a de facto keyword and all types inheriting from it are implicitly custom types. 1435 The problem is that some special properties are not handled by existing language semantics, \eg the execution of constructors /destructors is in the wrong order to implicitly start threads because the thread must start \emph{after} all constructors as it relies on a completely initialized object, but the inherited constructor runs \emph{before} the derived.1458 The problem is that some special properties are not handled by existing language semantics, \eg the execution of constructors and destructors is in the wrong order to implicitly start threads because the thread must start \emph{after} all constructors as it relies on a completely initialized object, but the inherited constructor runs \emph{before} the derived. 1436 1459 Alternatives, such as explicitly starting threads as in Java, are repetitive and forgetting to call start is a common source of errors. 1437 1460 An alternative is composition: … … 1461 1484 forall( `dtype` T | is_coroutine(T) ) void $suspend$( T & ), resume( T & ); 1462 1485 \end{cfa} 1463 Note, copying generators /coroutines/threads is undefined because muliple objects cannot execute on a shared stack and stack copying does not work in unmanaged languages (no garbage collection), like C, because the stack may contain pointers to objects within it that require updating for the copy.1464 The \CFA @dtype@ property provides no \emph{implicit} copying operations and the @is_coroutine@ trait provides no \emph{explicit} copying operations, so all coroutines must be passed by reference (pointer).1465 The function definitions ensure there is a statically typed @main@ function that is the starting point (first stack frame) of a coroutine, and a mechanism to get (read)the coroutine descriptor from its handle.1466 The @main@ function has no return value or additional parameters because the coroutine type allows an arbitrary number of interface functions with corresponding arbitrary typed input/output values versus fixed ones.1486 Note, copying generators, coroutines, and threads is undefined because multiple objects cannot execute on a shared stack and stack copying does not work in unmanaged languages (no garbage collection), like C, because the stack may contain pointers to objects within it that require updating for the copy. 1487 The \CFA @dtype@ property provides no \emph{implicit} copying operations and the @is_coroutine@ trait provides no \emph{explicit} copying operations, so all coroutines must be passed by reference or pointer. 1488 The function definitions ensure there is a statically typed @main@ function that is the starting point (first stack frame) of a coroutine, and a mechanism to read the coroutine descriptor from its handle. 1489 The @main@ function has no return value or additional parameters because the coroutine type allows an arbitrary number of interface functions with arbitrary typed input and output values versus fixed ones. 1467 1490 The advantage of this approach is that users can easily create different types of coroutines, \eg changing the memory layout of a coroutine is trivial when implementing the @get_coroutine@ function, and possibly redefining \textsf{suspend} and @resume@. 1468 1491 … … 1506 1529 1507 1530 Figure~\ref{f:CoroutineMemoryLayout} shows different memory-layout options for a coroutine (where a thread is similar). 1508 The coroutine handle is the @coroutine@ instance containing programmer specified type global /communication variables across interface functions.1531 The coroutine handle is the @coroutine@ instance containing programmer specified type global and communication variables across interface functions. 1509 1532 The coroutine descriptor contains all implicit declarations needed by the runtime, \eg @suspend@/@resume@, and can be part of the coroutine handle or separate. 1510 1533 The coroutine stack can appear in a number of locations and be fixed or variable sized. 1511 Hence, the coroutine's stack could be a variable-length structure (VLS)\footnote{ 1512 We are examining VLSs, where fields can be variable-sized structures or arrays. 1513 Once allocated, a VLS is fixed sized.} 1534 Hence, the coroutine's stack could be a variable-length structure (VLS) 1535 % \footnote{ 1536 % We are examining VLSs, where fields can be variable-sized structures or arrays. 1537 % Once allocated, a VLS is fixed sized.} 1514 1538 on the allocating stack, provided the allocating stack is large enough. 1515 For a VLS stack allocation /deallocation is an inexpensive adjustment of the stack pointer, modulo any stack constructor costs (\eg initial frame setup).1516 For stack allocation in the heap, allocation /deallocation is an expensive allocation, where the heap can be a shared resource, modulo any stack constructor costs.1517 It is also possible to use a split (segmented)stack calling convention, available with gcc and clang, allowing a variable-sized stack via a set of connected blocks in the heap.1518 Currently, \CFA supports stack /heap allocated descriptors but only fixed-sized heap allocated stacks.1539 For a VLS stack allocation and deallocation is an inexpensive adjustment of the stack pointer, modulo any stack constructor costs to initial frame setup. 1540 For stack allocation in the heap, allocation and deallocation is an expensive allocation, where the heap can be a shared resource, modulo any stack constructor costs. 1541 It is also possible to use a split or segmented stack calling convention, available with gcc and clang, allowing a variable-sized stack via a set of connected blocks in the heap. 1542 Currently, \CFA supports stack and heap allocated descriptors but only fixed-sized heap allocated stacks. 1519 1543 In \CFA debug-mode, the fixed-sized stack is terminated with a write-only page, which catches most stack overflows. 1520 1544 Experience teaching concurrency with \uC~\cite{CS343} shows fixed-sized stacks are rarely an issue for students. … … 1539 1563 The transition to concurrency, even for a single thread with multiple stacks, occurs when coroutines context switch to a \newterm{scheduling coroutine}, introducing non-determinism from the coroutine perspective~\cite[\S~3]{Buhr05a}. 1540 1564 Therefore, a minimal concurrency system requires coroutines \emph{in conjunction with a nondeterministic scheduler}. 1541 The resulting execution system now follows a cooperative threading-model~\cite{Adya02,libdill} because context-switching points to the scheduler (blocking)are known, but the next unblocking point is unknown due to the scheduler.1565 The resulting execution system now follows a cooperative threading-model~\cite{Adya02,libdill} because context-switching points to the scheduler are known, but the next unblocking point is unknown due to the scheduler. 1542 1566 Adding \newterm{preemption} introduces \newterm{non-cooperative} or \newterm{preemptive} scheduling, where context switching points to the scheduler are unknown as they can occur randomly between any two instructions often based on a timer interrupt. 1543 1567 Uncertainty gives the illusion of parallelism on a single processor and provides a mechanism to access and increase performance on multiple processors. 1544 The reason is that the scheduler /runtime have complete knowledge about resources and how to best utilized them.1568 The reason is that the scheduler and runtime have complete knowledge about resources and how to best utilized them. 1545 1569 However, the introduction of unrestricted nondeterminism results in the need for \newterm{mutual exclusion} and \newterm{synchronization}~\cite[\S~4]{Buhr05a}, which restrict nondeterminism for correctness; 1546 1570 otherwise, it is impossible to write meaningful concurrent programs. … … 1556 1580 \label{s:threads} 1557 1581 1558 Threading (Table~\ref{t:ExecutionPropertyComposition} case 11) needs the ability to start a thread and wait for its completion. 1559 A common API for this ability is @fork@ and @join@. 1582 Threading (Table~\ref{t:ExecutionPropertyComposition} case 11) needs the ability to start a thread and wait for its completion, where a common API is @fork@ and @join@. 1560 1583 \vspace{4pt} 1561 1584 \par\noindent … … 1589 1612 \vspace{1pt} 1590 1613 \par\noindent 1591 \CFA has a simpler approach using a custom @thread@ type and leveraging declaration semantics (allocation/deallocation), where threads implicitly @fork@ after construction and @join@ before destruction.1614 \CFA has a simpler approach using a custom @thread@ type and leveraging declaration semantics, allocation and deallocation, where threads implicitly @fork@ after construction and @join@ before destruction. 1592 1615 \begin{cfa} 1593 1616 thread MyThread {}; … … 1598 1621 } $\C{// deallocate stack-based threads, implicit joins before destruction}$ 1599 1622 \end{cfa} 1600 This semantic ensures a thread is started and stopped exactly once, eliminating some programming error, and scales to multiple threads for basic (termination)synchronization.1601 For block allocation to arbitrary depth, including recursion, threads are created /destroyed in a lattice structure (tree with top and bottom).1623 This semantic ensures a thread is started and stopped exactly once, eliminating some programming error, and scales to multiple threads for basic termination synchronization. 1624 For block allocation to arbitrary depth, including recursion, threads are created and destroyed in a lattice structure (tree with top and bottom). 1602 1625 Arbitrary topologies are possible using dynamic allocation, allowing threads to outlive their declaration scope, identical to normal dynamic allocation. 1603 1626 \begin{cfa} … … 1606 1629 MyThread * team = factory( 10 ); 1607 1630 // concurrency 1608 ` delete( team );` $\C{// deallocate heap-based threads, implicit joins before destruction}\CRT$1631 `adelete( team );` $\C{// deallocate heap-based threads, implicit joins before destruction}\CRT$ 1609 1632 } 1610 1633 \end{cfa} … … 1670 1693 \end{tabular} 1671 1694 \end{cquote} 1672 Like coroutines, the @dtype@ property prevents \emph{implicit} copy operations and the @is_thread@ trait provides no \emph{explicit} copy operations, so threads must be passed by reference (pointer).1673 Similarly, the function definitions ensure there is a statically typed @main@ function that is the thread starting point (first stack frame), a mechanism to get (read)the thread descriptor from its handle, and a special destructor to prevent deallocation while the thread is executing.1695 Like coroutines, the @dtype@ property prevents \emph{implicit} copy operations and the @is_thread@ trait provides no \emph{explicit} copy operations, so threads must be passed by reference or pointer. 1696 Similarly, the function definitions ensure there is a statically typed @main@ function that is the thread starting point (first stack frame), a mechanism to read the thread descriptor from its handle, and a special destructor to prevent deallocation while the thread is executing. 1674 1697 (The qualifier @mutex@ for the destructor parameter is discussed in Section~\ref{s:Monitor}.) 1675 1698 The difference between the coroutine and thread is that a coroutine borrows a thread from its caller, so the first thread resuming a coroutine creates the coroutine's stack and starts running the coroutine main on the stack; 1676 1699 whereas, a thread is scheduling for execution in @main@ immediately after its constructor is run. 1677 No return value or additional parameters are necessary for this function because the @thread@ type allows an arbitrary number of interface functions with corresponding arbitrary typed input /output values.1700 No return value or additional parameters are necessary for this function because the @thread@ type allows an arbitrary number of interface functions with corresponding arbitrary typed input and output values. 1678 1701 1679 1702 … … 1683 1706 Unrestricted nondeterminism is meaningless as there is no way to know when a result is completed and safe to access. 1684 1707 To produce meaningful execution requires clawing back some determinism using mutual exclusion and synchronization, where mutual exclusion provides access control for threads using shared data, and synchronization is a timing relationship among threads~\cite[\S~4]{Buhr05a}. 1685 The shared data protected by mutual ex lusion is called a \newterm{critical section}~\cite{Dijkstra65}, and the protection can be simple (only 1 thread) or complex (only N kinds of threads, \eg group~\cite{Joung00} or readers/writer~\cite{Courtois71}).1686 Without synchronization control in a critical section, an arriving thread can barge ahead of preexisting waiter threads resulting in short/long-term starvation, staleness /freshness problems, and/orincorrect transfer of data.1708 The shared data protected by mutual exclusion is called a \newterm{critical section}~\cite{Dijkstra65}, and the protection can be simple, only 1 thread, or complex, only N kinds of threads, \eg group~\cite{Joung00} or readers/writer~\cite{Courtois71} problems. 1709 Without synchronization control in a critical section, an arriving thread can barge ahead of preexisting waiter threads resulting in short/long-term starvation, staleness and freshness problems, and incorrect transfer of data. 1687 1710 Preventing or detecting barging is a challenge with low-level locks, but made easier through higher-level constructs. 1688 1711 This challenge is often split into two different approaches: barging \emph{avoidance} and \emph{prevention}. … … 1696 1719 Some concurrent systems eliminate mutable shared-state by switching to non-shared communication like message passing~\cite{Thoth,Harmony,V-Kernel,MPI} (Erlang, MPI), channels~\cite{CSP} (CSP,Go), actors~\cite{Akka} (Akka, Scala), or functional techniques (Haskell). 1697 1720 However, these approaches introduce a new communication mechanism for concurrency different from the standard communication using function call/return. 1698 Hence, a programmer must learn and manipulate two sets of design /programming patterns.1721 Hence, a programmer must learn and manipulate two sets of design and programming patterns. 1699 1722 While this distinction can be hidden away in library code, effective use of the library still has to take both paradigms into account. 1700 In contrast, approaches based on shared-state models more closely resemble the standard call /return programming model, resulting in a single programming paradigm.1723 In contrast, approaches based on shared-state models more closely resemble the standard call and return programming model, resulting in a single programming paradigm. 1701 1724 Finally, a newer approach for restricting non-determinism is transactional memory~\cite{Herlihy93}. 1702 1725 While this approach is pursued in hardware~\cite{Nakaike15} and system languages, like \CC~\cite{Cpp-Transactions}, the performance and feature set is still too restrictive~\cite{Cascaval08,Boehm09} to be the main concurrency paradigm for system languages. … … 1711 1734 For these reasons, \CFA selected monitors as the core high-level concurrency construct, upon which higher-level approaches can be easily constructed. 1712 1735 1713 Specifically, a \textbf{monitor} is a set of functions that ensure mutual exclusion when accessing shared state. 1714 More precisely, a monitor is a programming technique that implicitly binds mutual exclusion to static function scope by call/return, as opposed to locks, where mutual-exclusion is defined by acquire/release calls, independent of lexical context (analogous to block and heap storage allocation). 1715 Restricting acquire/release points eases programming, comprehension, and maintenance, at a slight cost in flexibility and efficiency. 1716 \CFA uses a custom @monitor@ type and leverages declaration semantics (deallocation) to protect active or waiting threads in a monitor. 1717 1718 The following is a \CFA monitor implementation of an atomic counter. 1719 \begin{cfa} 1720 `monitor` Aint { int cnt; }; $\C[4.25in]{// atomic integer counter}$ 1721 int ++?( Aint & `mutex` this ) with( this ) { return ++cnt; } $\C{// increment}$ 1722 int ?=?( Aint & `mutex` lhs, int rhs ) with( lhs ) { cnt = rhs; } $\C{// conversions with int, mutex optional}\CRT$ 1723 int ?=?( int & lhs, Aint & `mutex` rhs ) with( rhs ) { lhs = cnt; } 1724 \end{cfa} 1725 The operators use the parameter-only declaration type-qualifier @mutex@ to mark which parameters require locking during function execution to protect from race conditions. 1726 The assignment operators provide bidirectional conversion between an atomic and normal integer without accessing field @cnt@. 1727 (These operations only need @mutex@, if reading/writing the implementation type is not atomic.) 1728 The atomic counter is used without any explicit mutual-exclusion and provides thread-safe semantics. 1729 \begin{cfa} 1736 Figure~\ref{f:AtomicCounter} compares a \CFA and Java monitor implementing an atomic counter. 1737 (Like other concurrent programming languages, \CFA and Java have performant specializations for the basic types using atomic instructions.) 1738 A \newterm{monitor} is a set of functions that ensure mutual exclusion when accessing shared state. 1739 (Note, in \CFA, @monitor@ is short-hand for @mutex struct@.) 1740 More precisely, a monitor is a programming technique that implicitly binds mutual exclusion to static function scope by call and return, as opposed to locks, where mutual exclusion is defined by acquire/release calls, independent of lexical context (analogous to block and heap storage allocation). 1741 Restricting acquire and release points eases programming, comprehension, and maintenance, at a slight cost in flexibility and efficiency. 1742 As for other special types, \CFA has a custom @monitor@ type. 1743 1744 \begin{figure} 1745 \centering 1746 1747 \begin{lrbox}{\myboxA} 1748 \begin{cfa}[aboveskip=0pt,belowskip=0pt] 1749 `monitor` Aint { // atomic integer counter 1750 int cnt; 1751 }; 1752 int ++?( Aint & `mutex` this ) with(this) { return ++cnt; } 1753 int ?=?( Aint & `mutex` lhs, int rhs ) with(lhs) { cnt = rhs; } 1754 int ?=?(int & lhs, Aint & rhs) with(rhs) { lhs = cnt; } 1755 1730 1756 int i = 0, j = 0, k = 5; 1731 Aint x = { 0 }, y = { 0 }, z = { 5 }; $\C{// no mutex required}$ 1732 ++x; ++y; ++z; $\C{// safe increment by multiple threads}$ 1733 x = 2; y = i; z = k; $\C{// conversions}$ 1734 i = x; j = y; k = z; 1735 \end{cfa} 1736 Note, like other concurrent programming languages, \CFA has specializations for the basic types using atomic instructions for performance and a general trait similar to the \CC template @std::atomic@. 1737 1738 \CFA monitors have \newterm{multi-acquire} semantics so the thread in the monitor may acquire it multiple times without deadlock, allowing recursion and calling other interface functions. 1739 \newpage 1740 \begin{cfa} 1741 monitor M { ... } m; 1742 void foo( M & mutex m ) { ... } $\C{// acquire mutual exclusion}$ 1743 void bar( M & mutex m ) { $\C{// acquire mutual exclusion}$ 1744 ... `bar( m );` ... `foo( m );` ... $\C{// reacquire mutual exclusion}$ 1745 } 1746 \end{cfa} 1747 \CFA monitors also ensure the monitor lock is released regardless of how an acquiring function ends (normal or exceptional), and returning a shared variable is safe via copying before the lock is released. 1757 Aint x = { 0 }, y = { 0 }, z = { 5 }; // no mutex 1758 ++x; ++y; ++z; // mutex 1759 x = 2; y = i; z = k; // mutex 1760 i = x; j = y; k = z; // no mutex 1761 \end{cfa} 1762 \end{lrbox} 1763 1764 \begin{lrbox}{\myboxB} 1765 \begin{java}[aboveskip=0pt,belowskip=0pt] 1766 class Aint { 1767 private int cnt; 1768 public Aint( int init ) { cnt = init; } 1769 `synchronized` public int inc() { return ++cnt; } 1770 `synchronized` public void set( int rhs ) {cnt=rhs;} 1771 public int get() { return cnt; } 1772 } 1773 int i = 0, j = 0, k = 5; 1774 Aint x=new Aint(0), y=new Aint(0), z=new Aint(5); 1775 x.inc(); y.inc(); z.inc(); 1776 x.set( 2 ); y.set( i ); z.set( k ); 1777 i = x.get(); j = y.get(); k = z.get(); 1778 \end{java} 1779 \end{lrbox} 1780 1781 \subfloat[\CFA]{\label{f:AtomicCounterCFA}\usebox\myboxA} 1782 \hspace{3pt} 1783 \vrule 1784 \hspace{3pt} 1785 \subfloat[Java]{\label{f:AtomicCounterJava}\usebox\myboxB} 1786 \caption{Atomic counter} 1787 \label{f:AtomicCounter} 1788 \end{figure} 1789 1790 Like Java, \CFA monitors have \newterm{multi-acquire} semantics so the thread in the monitor may acquire it multiple times without deadlock, allowing recursion and calling other interface functions. 1791 % \begin{cfa} 1792 % monitor M { ... } m; 1793 % void foo( M & mutex m ) { ... } $\C{// acquire mutual exclusion}$ 1794 % void bar( M & mutex m ) { $\C{// acquire mutual exclusion}$ 1795 % ... `bar( m );` ... `foo( m );` ... $\C{// reacquire mutual exclusion}$ 1796 % } 1797 % \end{cfa} 1798 \CFA monitors also ensure the monitor lock is released regardless of how an acquiring function ends, normal or exceptional, and returning a shared variable is safe via copying before the lock is released. 1748 1799 Similar safety is offered by \emph{explicit} opt-in disciplines like \CC RAII versus the monitor \emph{implicit} language-enforced safety guarantee ensuring no programmer usage errors. 1749 Furthermore, RAII mechanisms cannot handle complex synchronization within a monitor, where the monitor lock may not be released on function exit because it is passed to an unblocking thread;1800 However, RAII mechanisms cannot handle complex synchronization within a monitor, where the monitor lock may not be released on function exit because it is passed to an unblocking thread; 1750 1801 RAII is purely a mutual-exclusion mechanism (see Section~\ref{s:Scheduling}). 1802 1803 Both Java and \CFA use a keyword @mutex@/\lstinline[language=java]|synchronized| to designate functions that implicitly acquire/release the monitor lock on call/return providing mutual exclusion to the stared data. 1804 Non-designated functions provide no mutual exclusion for read-only access or as an interface to a multi-step protocol requiring several steps of acquiring and releasing the monitor. 1805 Monitor objects can be passed through multiple helper functions without acquiring mutual exclusion, until a designated function associated with the object is called. 1806 \CFA designated functions are marked by an explicitly parameter-only pointer/reference qualifier @mutex@ (discussed further in Section\ref{s:MutexAcquisition}). 1807 Whereas, Java designated members are marked with \lstinline[language=java]|synchronized| that applies to the implicit reference parameter @this@. 1808 In the example, the increment and setter operations need mutual exclusion while the read-only getter operation can be non-mutex if reading the implementation is atomic. 1751 1809 1752 1810 … … 1771 1829 \end{tabular} 1772 1830 \end{cquote} 1773 The @dtype@ property prevents \emph{implicit} copy operations and the @is_monitor@ trait provides no \emph{explicit} copy operations, so monitors must be passed by reference (pointer).1774 Similarly, the function definitions ensure s there is a mechanism to get (read) the monitor descriptor from its handle, and a special destructor to prevent deallocation if a threadusing the shared data.1831 The @dtype@ property prevents \emph{implicit} copy operations and the @is_monitor@ trait provides no \emph{explicit} copy operations, so monitors must be passed by reference or pointer. 1832 Similarly, the function definitions ensure there is a mechanism to read the monitor descriptor from its handle, and a special destructor to prevent deallocation if a thread is using the shared data. 1775 1833 The custom monitor type also inserts any locks needed to implement the mutual exclusion semantics. 1834 \CFA relies heavily on traits as an abstraction mechanism, so the @mutex@ qualifier prevents coincidentally matching of a monitor trait with a type that is not a monitor, similar to coincidental inheritance where a shape and playing card can both be drawable. 1776 1835 1777 1836 … … 1779 1838 \label{s:MutexAcquisition} 1780 1839 1781 While the monitor lock provides mutual exclusion for shared data, there are implementation options for when and where the locking/unlocking occurs. 1782 (Much of this discussion also applies to basic locks.) 1783 For example, a monitor may be passed through multiple helper functions before it is necessary to acquire the monitor's mutual exclusion. 1784 1785 \CFA requires programmers to identify the kind of parameter with the @mutex@ keyword and uses no keyword to mean \lstinline[morekeywords=nomutex]@nomutex@, because @mutex@ parameters are rare and no keyword is the \emph{normal} parameter semantics. 1786 Hence, @mutex@ parameters are documentation, at the function and its prototype, to both programmer and compiler, without other redundant keywords. 1787 Furthermore, \CFA relies heavily on traits as an abstraction mechanism, so the @mutex@ qualifier prevents coincidentally matching of a monitor trait with a type that is not a monitor, similar to coincidental inheritance where a shape and playing card can both be drawable. 1788 1789 The next semantic decision is establishing which parameter \emph{types} may be qualified with @mutex@. 1790 The following has monitor parameter types that are composed of multiple objects. 1791 \begin{cfa} 1792 monitor M { ... } 1840 For object-oriented programming languages, the mutex property applies to one object, the implicit pointer/reference to the monitor type. 1841 Because \CFA uses a pointer qualifier, other possibilities exist, \eg: 1842 \begin{cfa} 1843 monitor M { ... }; 1793 1844 int f1( M & mutex m ); $\C{// single parameter object}$ 1794 1845 int f2( M * mutex m ); $\C{// single or multiple parameter object}$ … … 1796 1847 int f4( stack( M * ) & mutex m ); $\C{// multiple parameters object}$ 1797 1848 \end{cfa} 1798 Function @f1@ has a single parameter object, while @f2@'s indirection could be a single or multi-element array, where static array size is often unknown in C. 1799 Function @f3@ has a multiple object matrix, and @f4@ a multiple object data structure. 1800 While shown shortly, multiple object acquisition is possible, but the number of objects must be statically known. 1801 Therefore, \CFA only acquires one monitor per parameter with exactly one level of indirection, and exclude pointer types to unknown sized arrays. 1802 1803 For object-oriented monitors, \eg Java, calling a mutex member \emph{implicitly} acquires mutual exclusion of the receiver object, @`rec`.foo(...)@. 1804 \CFA has no receiver, and hence, the explicit @mutex@ qualifier is used to specify which objects acquire mutual exclusion. 1805 A positive consequence of this design decision is the ability to support multi-monitor functions,\footnote{ 1849 Function @f1@ has a single object parameter, while functions @f2@ to @f4@ can be a single or multi-element parameter with statically unknown size. 1850 Because of the statically unknown size, \CFA only supports a single reference @mutex@ parameter, @f1@. 1851 1852 The \CFA @mutex@ qualifier does allow the ability to support multi-monitor functions,\footnote{ 1806 1853 While object-oriented monitors can be extended with a mutex qualifier for multiple-monitor members, no prior example of this feature could be found.} 1807 called \newterm{bulk acquire}.1854 where the number of acquisitions is statically known, called \newterm{bulk acquire}. 1808 1855 \CFA guarantees bulk acquisition order is consistent across calls to @mutex@ functions using the same monitors as arguments, so acquiring multiple monitors in a bulk acquire is safe from deadlock. 1809 1856 Figure~\ref{f:BankTransfer} shows a trivial solution to the bank transfer problem~\cite{BankTransfer}, where two resources must be locked simultaneously, using \CFA monitors with implicit locking and \CC with explicit locking. … … 1933 1980 % There are many aspects of scheduling in a concurrency system, all related to resource utilization by waiting threads, \ie which thread gets the resource next. 1934 1981 % Different forms of scheduling include access to processors by threads (see Section~\ref{s:RuntimeStructureCluster}), another is access to a shared resource by a lock or monitor. 1935 This section discusses scheduling for waiting threads eligible for monitor entry , \ie which user thread gets the shared resource next. (See Section~\ref{s:RuntimeStructureCluster} for scheduling kernel threads on virtual processors.)1982 This section discusses scheduling for waiting threads eligible for monitor entry~\cite{Buhr95b}, \ie which user thread gets the shared resource next. (See Section~\ref{s:RuntimeStructureCluster} for scheduling kernel threads on virtual processors.) 1936 1983 While monitor mutual-exclusion provides safe access to its shared data, the data may indicate a thread cannot proceed, \eg a bounded buffer may be full/\-empty so produce/consumer threads must block. 1937 1984 Leaving the monitor and retrying (busy waiting) is impractical for high-level programming. … … 1939 1986 Monitors eliminate busy waiting by providing synchronization within the monitor critical-section to schedule threads needing access to the shared data, where threads block versus spin. 1940 1987 Synchronization is generally achieved with internal~\cite{Hoare74} or external~\cite[\S~2.9.2]{uC++} scheduling. 1941 \newterm{Internal} (largely)schedules threads located \emph{inside} the monitor and is accomplished using condition variables with signal and wait.1942 \newterm{External} (largely)schedules threads located \emph{outside} the monitor and is accomplished with the @waitfor@ statement.1943 Note, internal scheduling has a small amount of external scheduling and vice vers us, so the naming denotes where the majority of the block threads reside (inside or outside) for scheduling.1944 For complex scheduling, the approaches can be combined, so there can be an equal number ofthreads waiting inside and outside.1945 1946 \CFA monitors do not allow calling threads to barge ahead of signalled threads (via barging prevention), which simplifies synchronization among threads in the monitor and increases correctness.1988 \newterm{Internal} largely schedules threads located \emph{inside} the monitor and is accomplished using condition variables with signal and wait. 1989 \newterm{External} largely schedules threads located \emph{outside} the monitor and is accomplished with the @waitfor@ statement. 1990 Note, internal scheduling has a small amount of external scheduling and vice versa, so the naming denotes where the majority of the block threads reside (inside or outside) for scheduling. 1991 For complex scheduling, the approaches can be combined, so there are threads waiting inside and outside. 1992 1993 \CFA monitors do not allow calling threads to barge ahead of signalled threads via barging prevention, which simplifies synchronization among threads in the monitor and increases correctness. 1947 1994 A direct consequence of this semantics is that unblocked waiting threads are not required to recheck the waiting condition, \ie waits are not in a starvation-prone busy-loop as required by the signals-as-hints style with barging. 1948 1995 Preventing barging comes directly from Hoare's semantics in the seminal paper on monitors~\cite[p.~550]{Hoare74}. … … 1953 2000 Furthermore, \CFA concurrency has no spurious wakeup~\cite[\S~9]{Buhr05a}, which eliminates an implicit self barging. 1954 2001 1955 Monitor mutual-exclusion means signalling cannot have the signaller and signalled thread in the monitor simultaneously, so only the signaller or signallee can proceed .1956 Figure~\ref{f:MonitorScheduling} shows internal /external scheduling for the bounded-buffer examples in Figure~\ref{f:GenericBoundedBuffer}.1957 For internal scheduling in Figure~\ref{f:BBInt}, the @signal@ moves the signallee (front thread of the specified condition queue) to urgentand the signaller continues (solid line).2002 Monitor mutual-exclusion means signalling cannot have the signaller and signalled thread in the monitor simultaneously, so only the signaller or signallee can proceed and the other waits on an implicit urgent list~\cite[p.~551]{Hoare74}. 2003 Figure~\ref{f:MonitorScheduling} shows internal and external scheduling for the bounded-buffer examples in Figure~\ref{f:GenericBoundedBuffer}. 2004 For internal scheduling in Figure~\ref{f:BBInt}, the @signal@ moves the signallee, front thread of the specified condition queue, to the urgent list (see Figure~\ref{f:MonitorScheduling}) and the signaller continues (solid line). 1958 2005 Multiple signals move multiple signallees to urgent until the condition queue is empty. 1959 When the signaller exits or waits, a thread is implicitly unblocked from urgent (if available)before unblocking a calling thread to prevent barging.2006 When the signaller exits or waits, a thread is implicitly unblocked from urgent, if available, before unblocking a calling thread to prevent barging. 1960 2007 (Java conceptually moves the signalled thread to the calling queue, and hence, allows barging.) 1961 Signal is used when the signaller is providing the cooperation needed by the signallee (\eg creating an empty slot in a buffer for a producer) and the signaller immediately exits the monitor to run concurrently (consume the buffer element)and passes control of the monitor to the signalled thread, which can immediately take advantage of the state change.2008 Signal is used when the signaller is providing the cooperation needed by the signallee, \eg creating an empty slot in a buffer for a producer, and the signaller immediately exits the monitor to run concurrently consuming the buffer element, and passes control of the monitor to the signalled thread, which can immediately take advantage of the state change. 1962 2009 Specifically, the @wait@ function atomically blocks the calling thread and implicitly releases the monitor lock(s) for all monitors in the function's parameter list. 1963 2010 Signalling is unconditional because signalling an empty condition queue does nothing. 1964 2011 It is common to declare condition queues as monitor fields to prevent shared access, hence no locking is required for access as the queues are protected by the monitor lock. 1965 In \CFA, a condition queue can be created /stored independently.2012 In \CFA, a condition queue can be created and stored independently. 1966 2013 1967 2014 \begin{figure} … … 2049 2096 \end{figure} 2050 2097 2051 The @signal_block@ provides the opposite unblocking order, where the signaller is moved to urgent and the signallee continues and a thread is implicitly unblocked from urgent when the signallee exits or waits (dashed line) .2052 Signal block is used when the signallee is providing the cooperation needed by the signaller (\eg if the buffer is removed and a producer hands off an item to a consumer, as in Figure~\ref{f:DatingSignalBlock})so the signaller must wait until the signallee unblocks, provides the cooperation, exits the monitor to run concurrently, and passes control of the monitor to the signaller, which can immediately take advantage of the state change.2098 The @signal_block@ provides the opposite unblocking order, where the signaller is moved to urgent and the signallee continues and a thread is implicitly unblocked from urgent when the signallee exits or waits (dashed line)~\cite[p.~551]{Hoare74}. 2099 Signal block is used when the signallee is providing the cooperation needed by the signaller, \eg if the buffer is removed and a producer hands off an item to a consumer as in Figure~\ref{f:DatingSignalBlock}, so the signaller must wait until the signallee unblocks, provides the cooperation, exits the monitor to run concurrently, and passes control of the monitor to the signaller, which can immediately take advantage of the state change. 2053 2100 Using @signal@ or @signal_block@ can be a dynamic decision based on whether the thread providing the cooperation arrives before or after the thread needing the cooperation. 2054 2101 2055 External scheduling in Figure~\ref{f:BBExt} simplifies internal scheduling byeliminating condition queues and @signal@/@wait@ (cases where it cannot are discussed shortly), and has existed in the programming language Ada for almost 40 years with variants in other languages~\cite{SR,ConcurrentC++,uC++}.2102 For external scheduling in Figure~\ref{f:BBExt}, the internal scheduling is replaced, eliminating condition queues and @signal@/@wait@ (cases where it cannot are discussed shortly), and has existed in the programming language Ada for almost 40 years with variants in other languages~\cite{SR,ConcurrentC++,uC++}. 2056 2103 While prior languages use external scheduling solely for thread interaction, \CFA generalizes it to both monitors and threads. 2057 2104 External scheduling allows waiting for events from other threads while restricting unrelated events, that would otherwise have to wait on condition queues in the monitor. … … 2062 2109 Now when a producer/consumer detects a full/empty buffer, the necessary cooperation for continuation is specified by indicating the next function call that can occur. 2063 2110 For example, a producer detecting a full buffer must have cooperation from a consumer to remove an item so function @remove@ is accepted, which prevents producers from entering the monitor, and after a consumer calls @remove@, the producer waiting on urgent is \emph{implicitly} unblocked because it can now continue its insert operation. 2064 Hence, this mechanism is done in terms of control flow, next call, versus in terms of data, channels, as in Go /Rust @select@.2111 Hence, this mechanism is done in terms of control flow, next call, versus in terms of data, channels, as in Go and Rust @select@. 2065 2112 While both mechanisms have strengths and weaknesses, \CFA uses the control-flow mechanism to be consistent with other language features. 2066 2113 2067 Figure~\ref{f:ReadersWriterLock} shows internal /external scheduling for a readers/writer lock with no barging and threads are serviced in FIFO order to eliminate staleness/freshness among the reader/writer threads.2114 Figure~\ref{f:ReadersWriterLock} shows internal and external scheduling for a readers/writer lock with no barging and threads are serviced in FIFO order to eliminate staleness and freshness among the reader/writer threads. 2068 2115 For internal scheduling in Figure~\ref{f:RWInt}, the readers and writers wait on the same condition queue in FIFO order, making it impossible to tell if a waiting thread is a reader or writer. 2069 2116 To clawback the kind of thread, a \CFA condition can store user data in the node for a blocking thread at the @wait@, \ie whether the thread is a @READER@ or @WRITER@. … … 2229 2276 For signal scheduling, the @exchange@ condition is necessary to block the thread finding the match, while the matcher unblocks to take the opposite number, post its phone number, and unblock the partner. 2230 2277 For signal-block scheduling, the implicit urgent-queue replaces the explicit @exchange@-condition and @signal_block@ puts the finding thread on the urgent stack and unblocks the matcher. 2231 2232 The dating service is an important example of a monitor that cannot be written using external scheduling. 2233 First, because scheduling requires knowledge of calling parameters to make matching decisions, and parameters of calling threads are unavailable within the monitor. 2234 For example, a girl thread within the monitor cannot examine the @ccode@ of boy threads waiting on the calling queue to determine if there is a matching partner. 2235 Second, because a scheduling decision may be delayed when there is no immediate match, which requires a condition queue for waiting, and condition queues imply internal scheduling. 2236 For example, if a girl thread could determine there is no calling boy with the same @ccode@, it must wait until a matching boy arrives. 2237 Finally, barging corrupts the dating service during an exchange because a barger may also match and change the phone numbers, invalidating the previous exchange phone number. 2278 Note, barging corrupts the dating service during an exchange because a barger may also match and change the phone numbers, invalidating the previous exchange phone number. 2238 2279 This situation shows rechecking the waiting condition and waiting again (signals-as-hints) fails, requiring significant restructured to account for barging. 2239 2280 2240 Both internal and external scheduling extend to multiple monitors in a natural way. 2281 Given external and internal scheduling, what guidelines can a programmer use to select between them? 2282 In general, external scheduling is easier to understand and code because only the next logical action (mutex function(s)) is stated, and the monitor implicitly handles all the details. 2283 Therefore, there are no condition variables, and hence, no wait and signal, which reduces coding complexity and synchronization errors. 2284 If external scheduling is simpler than internal, why not use it all the time? 2285 Unfortunately, external scheduling cannot be used if: scheduling depends on parameter value(s) or scheduling must block across an unknown series of calls on a condition variable, \ie internal scheduling. 2286 For example, the dating service cannot be written using external scheduling. 2287 First, scheduling requires knowledge of calling parameters to make matching decisions and parameters of calling threads are unavailable within the monitor. 2288 Specifically, a thread within the monitor cannot examine the @ccode@ of threads waiting on the calling queue to determine if there is a matching partner. 2289 (Similarly, if the bounded buffer or readers/writer are restructured with a single interface function with a parameter denoting producer/consumer or reader/write, they cannot be solved with external scheduling.) 2290 Second, a scheduling decision may be delayed across an unknown number of calls when there is no immediate match so the thread in the monitor must block on a condition. 2291 Specifically, if a thread determines there is no opposite calling thread with the same @ccode@, it must wait an unknown period until a matching thread arrives. 2292 For complex synchronization, both external and internal scheduling can be used to take advantage of best of properties of each. 2293 2294 Finally, both internal and external scheduling extend to multiple monitors in a natural way. 2241 2295 \begin{cquote} 2242 2296 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}} … … 2274 2328 Similarly, for @waitfor( rtn )@, the default semantics is to atomically block the acceptor and release all acquired mutex parameters, \ie @waitfor( rtn : m1, m2 )@. 2275 2329 To override the implicit multi-monitor wait, specific mutex parameter(s) can be specified, \eg @waitfor( rtn : m1 )@. 2276 @waitfor@ does statically verify the monitor types passed are the same as the acquired mutex-parameters of the given function or function pointer, hence the function (pointer)prototype must be accessible.2330 @waitfor@ does statically verify the monitor types passed are the same as the acquired mutex-parameters of the given function or function pointer, hence the prototype must be accessible. 2277 2331 % When an overloaded function appears in an @waitfor@ statement, calls to any function with that name are accepted. 2278 % The rationale is that members with the same name should perform a similar function, and therefore, all should be eligible to accept a call.2332 % The rationale is that functions with the same name should perform a similar actions, and therefore, all should be eligible to accept a call. 2279 2333 Overloaded functions can be disambiguated using a cast 2280 2334 \begin{cfa} … … 2285 2339 2286 2340 The ability to release a subset of acquired monitors can result in a \newterm{nested monitor}~\cite{Lister77} deadlock (see Section~\ref{s:MutexAcquisition}). 2287 \newpage2288 2341 \begin{cfa} 2289 2342 void foo( M & mutex m1, M & mutex m2 ) { … … 2300 2353 2301 2354 Figure~\ref{f:ExtendedWaitfor} shows the extended form of the @waitfor@ statement to conditionally accept one of a group of mutex functions, with an optional statement to be performed \emph{after} the mutex function finishes. 2302 For a @waitfor@ clause to be executed, its @when@ must be true and an outstanding call to its corresponding member(s) must exist.2355 For a @waitfor@ clause to be executed, its @when@ must be true and an outstanding call to its corresponding function(s) must exist. 2303 2356 The \emph{conditional-expression} of a @when@ may call a function, but the function must not block or context switch. 2304 If there are multiple acceptable mutex calls, selection occurs top-to-bottom (prioritized)among the @waitfor@ clauses, whereas some programming languages with similar mechanisms accept nondeterministically for this case, \eg Go \lstinline[morekeywords=select]@select@.2305 If some accept guards are true and there are no outstanding calls to these members, the acceptor is blocked until a call to one of these members is made.2357 If there are multiple acceptable mutex calls, selection is prioritized top-to-bottom among the @waitfor@ clauses, whereas some programming languages with similar mechanisms accept nondeterministically for this case, \eg Go \lstinline[morekeywords=select]@select@. 2358 If some accept guards are true and there are no outstanding calls to these functions, the acceptor is blocked until a call to one of these functions is made. 2306 2359 If there is a @timeout@ clause, it provides an upper bound on waiting. 2307 2360 If all the accept guards are false, the statement does nothing, unless there is a terminating @else@ clause with a true guard, which is executed instead. 2308 2361 Hence, the terminating @else@ clause allows a conditional attempt to accept a call without blocking. 2309 2362 If both @timeout@ and @else@ clause are present, the @else@ must be conditional, or the @timeout@ is never triggered. 2310 There is also a traditional future wait queue (not shown) (\eg Microsoft @WaitForMultipleObjects@), to wait for a specified number of future elements in the queue.2363 % There is also a traditional future wait queue (not shown) (\eg Microsoft @WaitForMultipleObjects@), to wait for a specified number of future elements in the queue. 2311 2364 Finally, there is a shorthand for specifying multiple functions using the same set of monitors: @waitfor( f, g, h : m1, m2, m3 )@. 2312 2365 … … 2315 2368 \begin{cfa} 2316 2369 `when` ( $\emph{conditional-expression}$ ) $\C{// optional guard}$ 2317 waitfor( $\emph{mutex- member-name}$ ) $\emph{statement}$ $\C{// action after call}$2370 waitfor( $\emph{mutex-function-name}$ ) $\emph{statement}$ $\C{// action after call}$ 2318 2371 `or` `when` ( $\emph{conditional-expression}$ ) $\C{// any number of functions}$ 2319 waitfor( $\emph{mutex- member-name}$ ) $\emph{statement}$2372 waitfor( $\emph{mutex-function-name}$ ) $\emph{statement}$ 2320 2373 `or` ... 2321 2374 `when` ( $\emph{conditional-expression}$ ) $\C{// optional guard}$ … … 2335 2388 The left example only accepts @mem1@ if @C1@ is true or only @mem2@ if @C2@ is true. 2336 2389 The right example accepts either @mem1@ or @mem2@ if @C1@ and @C2@ are true. 2390 Hence, the @waitfor@ has parallel semantics, accepting any true @when@ clause. 2337 2391 2338 2392 An interesting use of @waitfor@ is accepting the @mutex@ destructor to know when an object is deallocated, \eg assume the bounded buffer is restructured from a monitor to a thread with the following @main@. … … 2429 2483 2430 2484 One scheduling solution is for the signaller S to keep ownership of all locks until the last lock is ready to be transferred, because this semantics fits most closely to the behaviour of single-monitor scheduling. 2431 However, this solution is inefficient if W2 waited first and can beimmediate passed @m2@ when released, while S retains @m1@ until completion of the outer mutex statement.2485 However, this solution is inefficient if W2 waited first and immediate passed @m2@ when released, while S retains @m1@ until completion of the outer mutex statement. 2432 2486 If W1 waited first, the signaller must retain @m1@ amd @m2@ until completion of the outer mutex statement and then pass both to W1. 2433 2487 % Furthermore, there is an execution sequence where the signaller always finds waiter W2, and hence, waiter W1 starves. 2434 To support th is efficient semantics (and prevent barging), the implementation maintains a list of monitors acquired for each blocked thread.2435 When a signaller exits or waits in a m onitor function/statement, the front waiter on urgent is unblocked if all its monitors are released.2436 Implementing a fast subset check for the necessar y released monitors is important and discussed in the following sections.2488 To support these efficient semantics and prevent barging, the implementation maintains a list of monitors acquired for each blocked thread. 2489 When a signaller exits or waits in a mutex function or statement, the front waiter on urgent is unblocked if all its monitors are released. 2490 Implementing a fast subset check for the necessarily released monitors is important and discussed in the following sections. 2437 2491 % The benefit is encapsulating complexity into only two actions: passing monitors to the next owner when they should be released and conditionally waking threads if all conditions are met. 2438 2492 … … 2442 2496 2443 2497 In a statically-typed object-oriented programming language, a class has an exhaustive list of members, even when members are added via static inheritance (see Figure~\ref{f:uCinheritance}). 2444 Knowing all members at compilation (even separate compilation) allows uniquely numbered them so the accept-statement implementation can use a fast/compact bit mask with $O(1)$ compare.2498 Knowing all members at compilation, even separate compilation, allows uniquely numbered them so the accept-statement implementation can use a fast and compact bit mask with $O(1)$ compare. 2445 2499 2446 2500 \begin{figure} … … 2493 2547 Hence, function pointers are used to identify the functions listed in the @waitfor@ statement, stored in a variable-sized array. 2494 2548 Then, the same implementation approach used for the urgent stack (see Section~\ref{s:Scheduling}) is used for the calling queue. 2495 Each caller has a list of monitors acquired, and the @waitfor@ statement performs a (short) linear search matching functions in the @waitfor@ list with called functions, and then verifying the associated mutex locks can be transfers.2549 Each caller has a list of monitors acquired, and the @waitfor@ statement performs a short linear search matching functions in the @waitfor@ list with called functions, and then verifying the associated mutex locks can be transferred. 2496 2550 2497 2551 … … 2571 2625 2572 2626 struct Msg { int i, j; }; 2573 m onitorthread GoRtn { int i; float f; Msg m; };2627 mutex thread GoRtn { int i; float f; Msg m; }; 2574 2628 void mem1( GoRtn & mutex gortn, int i ) { gortn.i = i; } 2575 2629 void mem2( GoRtn & mutex gortn, float f ) { gortn.f = f; } … … 2577 2631 void ^?{}( GoRtn & mutex ) {} 2578 2632 2579 void main( GoRtn & gortn ) with( gortn ) {// thread starts2633 void main( GoRtn & mutex gortn ) with(gortn) { // thread starts 2580 2634 2581 2635 for () { … … 2644 2698 2645 2699 \begin{cfa} 2646 m onitorthread DatingService {2700 mutex thread DatingService { 2647 2701 condition Girls[CompCodes], Boys[CompCodes]; 2648 2702 int girlPhoneNo, boyPhoneNo, ccode; … … 2708 2762 % \label{f:pingpong} 2709 2763 % \end{figure} 2710 Note, the ping/pong threads are globally declared, @pi@/@po@, and hence, start (and possibly complete)before the program main starts.2764 Note, the ping/pong threads are globally declared, @pi@/@po@, and hence, start and possibly complete before the program main starts. 2711 2765 \end{comment} 2712 2766 2713 2767 2714 \subsection{\texorpdfstring{\protect\lstinline@m onitor@ Generators / Coroutines / Threads}{monitor Generators / Coroutines / Threads}}2715 2716 \CFA generators, coroutines, and threads can also be monitors(Table~\ref{t:ExecutionPropertyComposition} cases 4, 6, 12) allowing safe \emph{direct communication} with threads, \ie the custom types can have mutex functions that are called by other threads.2768 \subsection{\texorpdfstring{\protect\lstinline@mutex@ Generators / Coroutines / Threads}{monitor Generators / Coroutines / Threads}} 2769 2770 \CFA generators, coroutines, and threads can also be @mutex@ (Table~\ref{t:ExecutionPropertyComposition} cases 4, 6, 12) allowing safe \emph{direct communication} with threads, \ie the custom types can have mutex functions that are called by other threads. 2717 2771 All monitor features are available within these mutex functions. 2718 For example, if the formatter generator (or coroutine equivalent)in Figure~\ref{f:CFAFormatGen} is extended with the monitor property and this interface function is used to communicate with the formatter:2772 For example, if the formatter generator or coroutine equivalent in Figure~\ref{f:CFAFormatGen} is extended with the monitor property and this interface function is used to communicate with the formatter: 2719 2773 \begin{cfa} 2720 2774 void fmt( Fmt & mutex fmt, char ch ) { fmt.ch = ch; resume( fmt ) } … … 2724 2778 Figure~\ref{f:DirectCommunicationComparison} shows a comparison of direct call-communication in \CFA versus indirect channel-communication in Go. 2725 2779 (Ada has a similar mechanism to \CFA direct communication.) 2726 The program thread in \CFA @main@ uses the call/return paradigm to directly communicate with the @GoRtn main@, whereas Go switches to the channel paradigm to indirectly communicate with the goroutine. 2780 % The thread main function is by default @mutex@, so the @mutex@ qualifier for the thread parameter is optional. 2781 % The reason is that the thread logically starts instantaneously in the thread main acquiring its mutual exclusion, so it starts before any calls to prepare for synchronizing these calls. 2782 The \CFA program @main@ uses the call/return paradigm to directly communicate with the @GoRtn main@, whereas Go switches to the unbuffered channel paradigm to indirectly communicate with the goroutine. 2727 2783 Communication by multiple threads is safe for the @gortn@ thread via mutex calls in \CFA or channel assignment in Go. 2784 The difference between call and channel send occurs for buffered channels making the send asynchronous. 2785 In \CFA, asynchronous call and multiple buffers are provided using an administrator and worker threads~\cite{Gentleman81} and/or futures (not discussed). 2728 2786 2729 2787 Figure~\ref{f:DirectCommunicationDatingService} shows the dating-service problem in Figure~\ref{f:DatingServiceMonitor} extended from indirect monitor communication to direct thread communication. 2730 When converting a monitor to a thread (server), the coding pattern is to move as much code as possible from the accepted members into the thread main so it does anmuch work as possible.2788 When converting a monitor to a thread (server), the coding pattern is to move as much code as possible from the accepted functions into the thread main so it does as much work as possible. 2731 2789 Notice, the dating server is postponing requests for an unspecified time while continuing to accept new requests. 2732 For complex servers (web-servers), there can be hundreds of lines of code in the thread main and safe interaction with clients can be complex.2790 For complex servers, \eg web-servers, there can be hundreds of lines of code in the thread main and safe interaction with clients can be complex. 2733 2791 2734 2792 … … 2736 2794 2737 2795 For completeness and efficiency, \CFA provides a standard set of low-level locks: recursive mutex, condition, semaphore, barrier, \etc, and atomic instructions: @fetchAssign@, @fetchAdd@, @testSet@, @compareSet@, \etc. 2738 Some of these low-level mechanism are used to build the \CFA runtime, but we always advocate using high-level mechanisms whenever possible.2796 Some of these low-level mechanisms are used to build the \CFA runtime, but we always advocate using high-level mechanisms whenever possible. 2739 2797 2740 2798 … … 2768 2826 2769 2827 In contrast to direct threading is indirect \newterm{thread pools}, \eg Java @executor@, where small jobs (work units) are inserted into a work pool for execution. 2770 If the jobs are dependent, \ie interact, there is an implicit /explicitdependency graph that ties them together.2828 If the jobs are dependent, \ie interact, there is an implicit dependency graph that ties them together. 2771 2829 While removing direct concurrency, and hence the amount of context switching, thread pools significantly limit the interaction that can occur among jobs. 2772 2830 Indeed, jobs should not block because that also blocks the underlying thread, which effectively means the CPU utilization, and therefore throughput, suffers. … … 2857 2915 \label{s:RuntimeStructureProcessor} 2858 2916 2859 A virtual processor is implemented by a kernel thread (\eg UNIX process), which are scheduled for execution on a hardware processor by the underlying operating system.2917 A virtual processor is implemented by a kernel thread, \eg UNIX process, which are scheduled for execution on a hardware processor by the underlying operating system. 2860 2918 Programs may use more virtual processors than hardware processors. 2861 2919 On a multiprocessor, kernel threads are distributed across the hardware processors resulting in virtual processors executing in parallel. … … 2872 2930 \label{s:Implementation} 2873 2931 2874 A primary implementation challenge is avoiding contention from dynamically allocating memory because of bulk acquire, \eg the internal-scheduling design is (almost)free of allocations.2932 A primary implementation challenge is avoiding contention from dynamically allocating memory because of bulk acquire, \eg the internal-scheduling design is almost free of allocations. 2875 2933 All blocking operations are made by parking threads onto queues, therefore all queues are designed with intrusive nodes, where each node has preallocated link fields for chaining. 2876 2934 Furthermore, several bulk-acquire operations need a variable amount of memory. … … 2918 2976 2919 2977 There are two versions of the \CFA runtime kernel: debug and non-debug. 2920 The debugging version has many runtime checks and internal assertions, \eg stack (non-writable)guard page, and checks for stack overflow whenever context switches occur among coroutines and threads, which catches most stack overflows.2978 The debugging version has many runtime checks and internal assertions, \eg stack non-writable guard page, and checks for stack overflow whenever context switches occur among coroutines and threads, which catches most stack overflows. 2921 2979 After a program is debugged, the non-debugging version can be used to significantly decrease space and increase performance. 2922 2980 … … 2926 2984 2927 2985 To test the performance of the \CFA runtime, a series of microbenchmarks are used to compare \CFA with pthreads, Java 11.0.6, Go 1.12.6, Rust 1.37.0, Python 3.7.6, Node.js 12.14.1, and \uC 7.0.0. 2928 For comparison, the package must be multi-processor (M:N), which excludes libdil l/libmil~\cite{libdill} (M:1)), and use a shared-memory programming model, \eg not message passing.2986 For comparison, the package must be multi-processor (M:N), which excludes libdil and libmil~\cite{libdill} (M:1)), and use a shared-memory programming model, \eg not message passing. 2929 2987 The benchmark computer is an AMD Opteron\texttrademark\ 6380 NUMA 64-core, 8 socket, 2.5 GHz processor, running Ubuntu 16.04.6 LTS, and pthreads/\CFA/\uC are compiled with gcc 9.2.1. 2930 2988 … … 2937 2995 The total time is divided by @N@ to obtain the average time for a benchmark. 2938 2996 Each benchmark experiment is run 13 times and the average appears in the table. 2939 All omitted tests for other languages are functionally identical to the \CFA tests and available online~\cite{Cforall BenchMarks}.2997 All omitted tests for other languages are functionally identical to the \CFA tests and available online~\cite{CforallConcurrentBenchmarks}. 2940 2998 % tar --exclude-ignore=exclude -cvhf benchmark.tar benchmark 2941 2942 \paragraph{Context Switching} 2943 2944 In procedural programming, the cost of a function call is important as modularization (refactoring) increases. 2945 (In many cases, a compiler inlines function calls to increase the size and number of basic blocks for optimizing.) 2946 Similarly, when modularization extends to coroutines/threads, the time for a context switch becomes a relevant factor. 2947 The coroutine test is from resumer to suspender and from suspender to resumer, which is two context switches. 2948 %For async-await systems, the test is scheduling and fulfilling @N@ empty promises, where all promises are allocated before versus interleaved with fulfillment to avoid garbage collection. 2949 For async-await systems, the test measures the cost of the @await@ expression entering the event engine by awaiting @N@ promises, where each created promise is resolved by an immediate event in the engine (using Node.js @setImmediate@). 2950 The thread test is using yield to enter and return from the runtime kernel, which is two context switches. 2951 The difference in performance between coroutine and thread context-switch is the cost of scheduling for threads, whereas coroutines are self-scheduling. 2952 Figure~\ref{f:ctx-switch} shows the \CFA code for a coroutine/thread with results in Table~\ref{t:ctx-switch}. 2953 2954 % From: Gregor Richards <gregor.richards@uwaterloo.ca> 2955 % To: "Peter A. Buhr" <pabuhr@plg2.cs.uwaterloo.ca> 2956 % Date: Fri, 24 Jan 2020 13:49:18 -0500 2957 % 2958 % I can also verify that the previous version, which just tied a bunch of promises together, *does not* go back to the 2959 % event loop at all in the current version of Node. Presumably they're taking advantage of the fact that the ordering of 2960 % events is intentionally undefined to just jump right to the next 'then' in the chain, bypassing event queueing 2961 % entirely. That's perfectly correct behavior insofar as its difference from the specified behavior isn't observable, but 2962 % it isn't typical or representative of much anything useful, because most programs wouldn't have whole chains of eager 2963 % promises. Also, it's not representative of *anything* you can do with async/await, as there's no way to encode such an 2964 % eager chain that way. 2999 % cp -p benchmark.tar /u/cforall/public_html/doc/concurrent_benchmark.tar 3000 3001 \paragraph{Creation} 3002 3003 Creation is measured by creating and deleting a specific kind of control-flow object. 3004 Figure~\ref{f:creation} shows the code for \CFA with results in Table~\ref{t:creation}. 3005 Note, the call stacks of \CFA coroutines are lazily created on the first resume, therefore the cost of creation with and without a stack are presented. 2965 3006 2966 3007 \begin{multicols}{2} 2967 3008 \lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}} 2968 \begin{cfa}[aboveskip=0pt,belowskip=0pt] 2969 @coroutine@ C {}; 2970 void main( C & ) { for () { @suspend;@ } } 2971 int main() { // coroutine test 2972 C c; 2973 BENCH( for ( N ) { @resume( c );@ } ) 3009 \begin{cfa} 3010 @coroutine@ MyCoroutine {}; 3011 void ?{}( MyCoroutine & this ) { 3012 #ifdef EAGER 3013 resume( this ); 3014 #endif 3015 } 3016 void main( MyCoroutine & ) {} 3017 int main() { 3018 BENCH( for ( N ) { @MyCoroutine c;@ } ) 2974 3019 sout | result; 2975 3020 } 2976 int main() { // thread test 2977 BENCH( for ( N ) { @yield();@ } ) 2978 sout | result; 2979 } 2980 \end{cfa} 2981 \captionof{figure}{\CFA context-switch benchmark} 2982 \label{f:ctx-switch} 3021 \end{cfa} 3022 \captionof{figure}{\CFA creation benchmark} 3023 \label{f:creation} 2983 3024 2984 3025 \columnbreak 2985 3026 2986 3027 \vspace*{-16pt} 2987 \captionof{table}{Context switch comparison (nanoseconds)} 2988 \label{t:ctx-switch} 2989 \begin{tabular}{@{}r*{3}{D{.}{.}{3.2}}@{}} 2990 \multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\ 2991 C function & 1.8 & 1.8 & 0.0 \\ 2992 \CFA generator & 1.8 & 2.0 & 0.3 \\ 2993 \CFA coroutine & 32.5 & 32.9 & 0.8 \\ 2994 \CFA thread & 93.8 & 93.6 & 2.2 \\ 2995 \uC coroutine & 50.3 & 50.3 & 0.2 \\ 2996 \uC thread & 97.3 & 97.4 & 1.0 \\ 2997 Python generator & 40.9 & 41.3 & 1.5 \\ 2998 Node.js generator & 32.6 & 32.2 & 1.0 \\ 2999 Node.js await & 1852.2 & 1854.7 & 16.4 \\ 3000 Goroutine thread & 143.0 & 143.3 & 1.1 \\ 3001 Rust thread & 332.0 & 331.4 & 2.4 \\ 3002 Java thread & 405.0 & 415.0 & 17.6 \\ 3003 Pthreads thread & 334.3 & 335.2 & 3.9 3028 \captionof{table}{Creation comparison (nanoseconds)} 3029 \label{t:creation} 3030 3031 \begin{tabular}[t]{@{}r*{3}{D{.}{.}{5.2}}@{}} 3032 \multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} & \multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\ 3033 \CFA generator & 0.6 & 0.6 & 0.0 \\ 3034 \CFA coroutine lazy & 13.4 & 13.1 & 0.5 \\ 3035 \CFA coroutine eager & 144.7 & 143.9 & 1.5 \\ 3036 \CFA thread & 466.4 & 468.0 & 11.3 \\ 3037 \uC coroutine & 155.6 & 155.7 & 1.7 \\ 3038 \uC thread & 523.4 & 523.9 & 7.7 \\ 3039 Python generator & 123.2 & 124.3 & 4.1 \\ 3040 Node.js generator & 33.4 & 33.5 & 0.3 \\ 3041 Goroutine thread & 751.0 & 750.5 & 3.1 \\ 3042 Rust tokio thread & 1860.0 & 1881.1 & 37.6 \\ 3043 Rust thread & 53801.0 & 53896.8 & 274.9 \\ 3044 Java thread & 120274.0 & 120722.9 & 2356.7 \\ 3045 Pthreads thread & 31465.5 & 31419.5 & 140.4 3004 3046 \end{tabular} 3005 3047 \end{multicols} 3006 3048 3049 \vspace*{-10pt} 3007 3050 \paragraph{Internal Scheduling} 3008 3051 … … 3010 3053 Figure~\ref{f:schedint} shows the code for \CFA, with results in Table~\ref{t:schedint}. 3011 3054 Note, the incremental cost of bulk acquire for \CFA, which is largely a fixed cost for small numbers of mutex objects. 3012 Java scheduling is significantly greater because the benchmark explicitly creates multiple thread in order to prevent the JIT from making the program sequential, \ie removing all locking.3055 Java scheduling is significantly greater because the benchmark explicitly creates multiple threads in order to prevent the JIT from making the program sequential, \ie removing all locking. 3013 3056 3014 3057 \begin{multicols}{2} … … 3036 3079 } 3037 3080 \end{cfa} 3081 \vspace*{-8pt} 3038 3082 \captionof{figure}{\CFA Internal-scheduling benchmark} 3039 3083 \label{f:schedint} … … 3104 3148 \paragraph{Mutual-Exclusion} 3105 3149 3106 Uncontented mutual exclusion, which frequently occurs, is measured by entering /leaving a critical section.3107 For monitors, entering and leaving a m onitorfunction is measured, otherwise the language-appropriate mutex-lock is measured.3150 Uncontented mutual exclusion, which frequently occurs, is measured by entering and leaving a critical section. 3151 For monitors, entering and leaving a mutex function is measured, otherwise the language-appropriate mutex-lock is measured. 3108 3152 For comparison, a spinning (versus blocking) test-and-test-set lock is presented. 3109 3153 Figure~\ref{f:mutex} shows the code for \CFA with results in Table~\ref{t:mutex}. … … 3142 3186 \end{multicols} 3143 3187 3144 \paragraph{Creation} 3145 3146 Creation is measured by creating/deleting a specific kind of control-flow object. 3147 Figure~\ref{f:creation} shows the code for \CFA with results in Table~\ref{t:creation}. 3148 Note, the call stacks of \CFA coroutines are lazily created on the first resume, therefore the cost of creation with and without a stack are presented. 3188 \paragraph{Context Switching} 3189 3190 In procedural programming, the cost of a function call is important as modularization (refactoring) increases. 3191 (In many cases, a compiler inlines function calls to increase the size and number of basic blocks for optimizing.) 3192 Similarly, when modularization extends to coroutines and threads, the time for a context switch becomes a relevant factor. 3193 The coroutine test is from resumer to suspender and from suspender to resumer, which is two context switches. 3194 %For async-await systems, the test is scheduling and fulfilling @N@ empty promises, where all promises are allocated before versus interleaved with fulfillment to avoid garbage collection. 3195 For async-await systems, the test measures the cost of the @await@ expression entering the event engine by awaiting @N@ promises, where each created promise is resolved by an immediate event in the engine (using Node.js @setImmediate@). 3196 The thread test is using yield to enter and return from the runtime kernel, which is two context switches. 3197 The difference in performance between coroutine and thread context-switch is the cost of scheduling for threads, whereas coroutines are self-scheduling. 3198 Figure~\ref{f:ctx-switch} shows the \CFA code for a coroutine and thread with results in Table~\ref{t:ctx-switch}. 3199 3200 % From: Gregor Richards <gregor.richards@uwaterloo.ca> 3201 % To: "Peter A. Buhr" <pabuhr@plg2.cs.uwaterloo.ca> 3202 % Date: Fri, 24 Jan 2020 13:49:18 -0500 3203 % 3204 % I can also verify that the previous version, which just tied a bunch of promises together, *does not* go back to the 3205 % event loop at all in the current version of Node. Presumably they're taking advantage of the fact that the ordering of 3206 % events is intentionally undefined to just jump right to the next 'then' in the chain, bypassing event queueing 3207 % entirely. That's perfectly correct behavior insofar as its difference from the specified behavior isn't observable, but 3208 % it isn't typical or representative of much anything useful, because most programs wouldn't have whole chains of eager 3209 % promises. Also, it's not representative of *anything* you can do with async/await, as there's no way to encode such an 3210 % eager chain that way. 3149 3211 3150 3212 \begin{multicols}{2} 3151 3213 \lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}} 3152 \begin{cfa} 3153 @coroutine@ MyCoroutine {}; 3154 void ?{}( MyCoroutine & this ) { 3155 #ifdef EAGER 3156 resume( this ); 3157 #endif 3158 } 3159 void main( MyCoroutine & ) {} 3160 int main() { 3161 BENCH( for ( N ) { @MyCoroutine c;@ } ) 3214 \begin{cfa}[aboveskip=0pt,belowskip=0pt] 3215 @coroutine@ C {}; 3216 void main( C & ) { for () { @suspend;@ } } 3217 int main() { // coroutine test 3218 C c; 3219 BENCH( for ( N ) { @resume( c );@ } ) 3162 3220 sout | result; 3163 3221 } 3164 \end{cfa} 3165 \captionof{figure}{\CFA creation benchmark} 3166 \label{f:creation} 3222 int main() { // thread test 3223 BENCH( for ( N ) { @yield();@ } ) 3224 sout | result; 3225 } 3226 \end{cfa} 3227 \captionof{figure}{\CFA context-switch benchmark} 3228 \label{f:ctx-switch} 3167 3229 3168 3230 \columnbreak 3169 3231 3170 3232 \vspace*{-16pt} 3171 \captionof{table}{Creation comparison (nanoseconds)} 3172 \label{t:creation} 3173 3174 \begin{tabular}[t]{@{}r*{3}{D{.}{.}{5.2}}@{}} 3175 \multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} & \multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\ 3176 \CFA generator & 0.6 & 0.6 & 0.0 \\ 3177 \CFA coroutine lazy & 13.4 & 13.1 & 0.5 \\ 3178 \CFA coroutine eager & 144.7 & 143.9 & 1.5 \\ 3179 \CFA thread & 466.4 & 468.0 & 11.3 \\ 3180 \uC coroutine & 155.6 & 155.7 & 1.7 \\ 3181 \uC thread & 523.4 & 523.9 & 7.7 \\ 3182 Python generator & 123.2 & 124.3 & 4.1 \\ 3183 Node.js generator & 32.3 & 32.2 & 0.3 \\ 3184 Goroutine thread & 751.0 & 750.5 & 3.1 \\ 3185 Rust thread & 53801.0 & 53896.8 & 274.9 \\ 3186 Java thread & 120274.0 & 120722.9 & 2356.7 \\ 3187 Pthreads thread & 31465.5 & 31419.5 & 140.4 3233 \captionof{table}{Context switch comparison (nanoseconds)} 3234 \label{t:ctx-switch} 3235 \begin{tabular}{@{}r*{3}{D{.}{.}{3.2}}@{}} 3236 \multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\ 3237 C function & 1.8 & 1.8 & 0.0 \\ 3238 \CFA generator & 1.8 & 2.0 & 0.3 \\ 3239 \CFA coroutine & 32.5 & 32.9 & 0.8 \\ 3240 \CFA thread & 93.8 & 93.6 & 2.2 \\ 3241 \uC coroutine & 50.3 & 50.3 & 0.2 \\ 3242 \uC thread & 97.3 & 97.4 & 1.0 \\ 3243 Python generator & 40.9 & 41.3 & 1.5 \\ 3244 Node.js await & 1852.2 & 1854.7 & 16.4 \\ 3245 Node.js generator & 33.3 & 33.4 & 0.3 \\ 3246 Goroutine thread & 143.0 & 143.3 & 1.1 \\ 3247 Rust async await & 32.0 & 32.0 & 0.0 \\ 3248 Rust tokio thread & 143.0 & 143.0 & 1.7 \\ 3249 Rust thread & 332.0 & 331.4 & 2.4 \\ 3250 Java thread & 405.0 & 415.0 & 17.6 \\ 3251 Pthreads thread & 334.3 & 335.2 & 3.9 3188 3252 \end{tabular} 3189 3253 \end{multicols} … … 3192 3256 \subsection{Discussion} 3193 3257 3194 Languages using 1:1 threading based on pthreads can at best meet or exceed (due to language overhead)the pthread results.3258 Languages using 1:1 threading based on pthreads can at best meet or exceed, due to language overhead, the pthread results. 3195 3259 Note, pthreads has a fast zero-contention mutex lock checked in user space. 3196 3260 Languages with M:N threading have better performance than 1:1 because there is no operating-system interactions. … … 3200 3264 3201 3265 3202 \section{Conclusion }3266 \section{Conclusions and Future Work} 3203 3267 3204 3268 Advanced control-flow will always be difficult, especially when there is temporal ordering and nondeterminism. … … 3207 3271 Combining these properties creates a number of high-level, efficient, and maintainable control-flow types: generator, coroutine, thread, each of which can be a monitor. 3208 3272 Eliminated from \CFA are barging and spurious wakeup, which are nonintuitive and lead to errors, and having to work with a bewildering set of low-level locks and acquisition techniques. 3209 \CFA high-level race-free monitors and threads provide the core mechanisms for mutual exclusion and synchronization, without having to resort to magic qualifiers like @volatile@/@atomic@.3273 \CFA high-level race-free monitors and threads, when used with mutex access function, provide the core mechanisms for mutual exclusion and synchronization, without having to resort to magic qualifiers like @volatile@ or @atomic@. 3210 3274 Extending these mechanisms to handle high-level deadlock-free bulk acquire across both mutual exclusion and synchronization is a unique contribution. 3211 3275 The \CFA runtime provides concurrency based on a preemptive M:N user-level threading-system, executing in clusters, which encapsulate scheduling of work on multiple kernel threads providing parallelism. 3212 3276 The M:N model is judged to be efficient and provide greater flexibility than a 1:1 threading model. 3213 3277 These concepts and the \CFA runtime-system are written in the \CFA language, extensively leveraging the \CFA type-system, which demonstrates the expressiveness of the \CFA language. 3214 Performance comparisons with other concurrent systems /languages show the \CFA approach is competitive across all basic operations, which translates directly into good performance in well-written applications with advanced control-flow.3278 Performance comparisons with other concurrent systems and languages show the \CFA approach is competitive across all basic operations, which translates directly into good performance in well-written applications with advanced control-flow. 3215 3279 C programmers should feel comfortable using these mechanisms for developing complex control-flow in applications, with the ability to obtain maximum available performance by selecting mechanisms at the appropriate level of need using only calling communication. 3216 3280 3217 3218 \section{Future Work}3219 3220 3281 While control flow in \CFA has a strong start, development is still underway to complete a number of missing features. 3221 3282 3222 \paragraph{Flexible Scheduling} 3223 \label{futur:sched} 3224 3283 \medskip 3284 \textbf{Flexible Scheduling:} 3225 3285 An important part of concurrency is scheduling. 3226 Different scheduling algorithms can affect performance (both in terms of average and variation).3286 Different scheduling algorithms can affect performance, both in terms of average and variation. 3227 3287 However, no single scheduler is optimal for all workloads and therefore there is value in being able to change the scheduler for given programs. 3228 3288 One solution is to offer various tuning options, allowing the scheduler to be adjusted to the requirements of the workload. … … 3230 3290 Currently, the \CFA pluggable scheduler is too simple to handle complex scheduling, \eg quality of service and real-time, where the scheduler must interact with mutex objects to deal with issues like priority inversion~\cite{Buhr00b}. 3231 3291 3232 \paragraph{Non-Blocking I/O} 3233 \label{futur:nbio} 3234 3292 \smallskip 3293 \textbf{Non-Blocking I/O:} 3235 3294 Many modern workloads are not bound by computation but IO operations, common cases being web servers and XaaS~\cite{XaaS} (anything as a service). 3236 3295 These types of workloads require significant engineering to amortizing costs of blocking IO-operations. … … 3241 3300 A non-blocking I/O library is currently under development for \CFA. 3242 3301 3243 \paragraph{Other Concurrency Tools} 3244 \label{futur:tools} 3245 3302 \smallskip 3303 \textbf{Other Concurrency Tools:} 3246 3304 While monitors offer flexible and powerful concurrency for \CFA, other concurrency tools are also necessary for a complete multi-paradigm concurrency package. 3247 3305 Examples of such tools can include futures and promises~\cite{promises}, executors and actors. … … 3249 3307 As well, new \CFA extensions should make it possible to create a uniform interface for virtually all mutual exclusion, including monitors and low-level locks. 3250 3308 3251 \paragraph{Implicit Threading} 3252 \label{futur:implcit} 3253 3254 Basic concurrent (embarrassingly parallel) applications can benefit greatly from implicit concurrency, where sequential programs are converted to concurrent, possibly with some help from pragmas to guide the conversion. 3309 \smallskip 3310 \textbf{Implicit Threading:} 3311 Basic \emph{embarrassingly parallel} applications can benefit greatly from implicit concurrency, where sequential programs are converted to concurrent, with some help from pragmas to guide the conversion. 3255 3312 This type of concurrency can be achieved both at the language level and at the library level. 3256 3313 The canonical example of implicit concurrency is concurrent nested @for@ loops, which are amenable to divide and conquer algorithms~\cite{uC++book}. 3257 The \CFA language features should make it possible to develop a reasonable number of implicit concurrency mechanism to solve basic HPC data-concurrency problems.3314 The \CFA language features should make it possible to develop a reasonable number of implicit concurrency mechanisms to solve basic HPC data-concurrency problems. 3258 3315 However, implicit concurrency is a restrictive solution with significant limitations, so it can never replace explicit concurrent programming. 3259 3316 -
doc/papers/concurrency/figures/RunTimeStructure.fig
r07d867b r22f94a4 8 8 -2 9 9 1200 2 10 6 3 855 2775 4155 292511 1 3 0 1 0 0 0 0 0 0.000 1 0.0000 3 930 2850 30 30 3930 2850 3960 288012 1 3 0 1 0 0 0 0 0 0.000 1 0.0000 4035 2850 30 30 4035 2850 4065 288010 6 3255 2475 3555 2625 11 1 3 0 1 0 0 0 0 0 0.000 1 0.0000 3330 2550 30 30 3330 2550 3360 2580 12 1 3 0 1 0 0 0 0 0 0.000 1 0.0000 3435 2550 30 30 3435 2550 3465 2580 13 13 -6 14 6 4 755 3525 5055 367515 1 3 0 1 0 0 0 0 0 0.000 1 0.0000 4 830 3600 30 30 4830 3600 4860 363016 1 3 0 1 0 0 0 0 0 0.000 1 0.0000 4 935 3600 30 30 4935 3600 4965 363014 6 4155 3225 4455 3375 15 1 3 0 1 0 0 0 0 0 0.000 1 0.0000 4230 3300 30 30 4230 3300 4260 3330 16 1 3 0 1 0 0 0 0 0 0.000 1 0.0000 4335 3300 30 30 4335 3300 4365 3330 17 17 -6 18 6 4 650 2775 4950 292519 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 4 725 2850 15 15 4725 2850 4740 286520 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 4 800 2850 15 15 4800 2850 4815 286521 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 4 875 2850 15 15 4875 2850 4890 286518 6 4050 2475 4350 2625 19 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 4125 2550 15 15 4125 2550 4140 2565 20 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 4200 2550 15 15 4200 2550 4215 2565 21 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 4275 2550 15 15 4275 2550 4290 2565 22 22 -6 23 6 3225 2400 3525 255024 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 3300 2475 15 15 3300 2475 3315 249025 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 3375 2475 15 15 3375 2475 3390 249026 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 3450 2475 15 15 3450 2475 3465 249023 6 2625 2100 2925 2250 24 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 2700 2175 15 15 2700 2175 2715 2190 25 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 2775 2175 15 15 2775 2175 2790 2190 26 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 2850 2175 15 15 2850 2175 2865 2190 27 27 -6 28 6 5475 3450 5625 375029 1 3 0 1 -1 -1 0 0 20 0.000 1 4.7120 5550 3525 15 15 5550 3525 5535 354030 1 3 0 1 -1 -1 0 0 20 0.000 1 4.7120 5550 3600 15 15 5550 3600 5535 361531 1 3 0 1 -1 -1 0 0 20 0.000 1 4.7120 5550 3675 15 15 5550 3675 5535 369028 6 4875 3150 5025 3450 29 1 3 0 1 -1 -1 0 0 20 0.000 1 4.7120 4950 3225 15 15 4950 3225 4935 3240 30 1 3 0 1 -1 -1 0 0 20 0.000 1 4.7120 4950 3300 15 15 4950 3300 4935 3315 31 1 3 0 1 -1 -1 0 0 20 0.000 1 4.7120 4950 3375 15 15 4950 3375 4935 3390 32 32 -6 33 6 4275 3525 4575 367534 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 4350 3600 15 15 4350 3600 4365 361535 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 4425 3600 15 15 4425 3600 4440 361536 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 4500 3600 15 15 4500 3600 4515 361533 6 3675 3225 3975 3375 34 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 3750 3300 15 15 3750 3300 3765 3315 35 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 3825 3300 15 15 3825 3300 3840 3315 36 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 3900 3300 15 15 3900 3300 3915 3315 37 37 -6 38 6 3225 4125 4650 442539 6 4350 4200 4650 435040 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 4425 4275 15 15 4425 4275 4440 429041 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 4500 4275 15 15 4500 4275 4515 429042 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 4575 4275 15 15 4575 4275 4590 429038 6 2625 3825 4050 4125 39 6 3750 3900 4050 4050 40 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 3825 3975 15 15 3825 3975 3840 3990 41 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 3900 3975 15 15 3900 3975 3915 3990 42 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 3975 3975 15 15 3975 3975 3990 3990 43 43 -6 44 1 1 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3450 4275 225 150 3450 4275 3675 442545 1 1 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4050 4275 225 150 4050 4275 4275 442544 1 1 0 1 -1 -1 0 0 -1 0.000 1 0.0000 2850 3975 225 150 2850 3975 3075 4125 45 1 1 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3450 3975 225 150 3450 3975 3675 4125 46 46 -6 47 6 6 675 4125 7500 442548 6 7200 4200 7500 435049 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 7275 4275 15 15 7275 4275 7290 429050 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 7350 4275 15 15 7350 4275 7365 429051 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 7425 4275 15 15 7425 4275 7440 429047 6 6075 3825 6900 4125 48 6 6600 3900 6900 4050 49 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 6675 3975 15 15 6675 3975 6690 3990 50 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 6750 3975 15 15 6750 3975 6765 3990 51 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 6825 3975 15 15 6825 3975 6840 3990 52 52 -6 53 1 1 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6 900 4275 225 150 6900 4275 7125 442553 1 1 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6300 3975 225 150 6300 3975 6525 4125 54 54 -6 55 6 6 675 3525 8025 397555 6 6075 3225 7425 3675 56 56 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2 57 57 1 1 1.00 45.00 90.00 58 6 675 3750 6975 375058 6075 3450 6375 3450 59 59 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2 60 60 1 1 1.00 45.00 90.00 61 7125 3750 7350 375061 6525 3450 6750 3450 62 62 2 2 0 1 -1 -1 0 0 -1 0.000 0 0 0 0 0 5 63 7 800 3975 7800 3525 7350 3525 7350 3975 7800 397563 7200 3675 7200 3225 6750 3225 6750 3675 7200 3675 64 64 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2 65 65 1 1 1.00 45.00 90.00 66 7 800 3750 8025 375066 7200 3450 7425 3450 67 67 -6 68 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 5550 2625 150 150 5550 2625 5700 262569 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 5550 3225 150 150 5550 3225 5700 322570 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 5550 3975 150 150 5550 3975 5700 397571 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3525 2850 150 150 3525 2850 3675 285072 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4200 2475 150 150 4200 2475 4350 247573 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4425 2850 150 150 4425 2850 4575 285074 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4 650 2475 150 150 4650 2475 4800 247575 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3 975 3600 150 150 3975 3600 4125 360076 1 3 0 1 0 0 0 0 0 0.000 1 0.0000 3525 3600 30 30 3525 3600 3555 363077 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3 750 2475 150 150 3750 2475 3900 262578 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4 875 3600 150 150 4875 3600 5025 375079 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3 975 2850 150 150 3975 2850 4125 285080 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 7200 2775 150 150 7200 2775 7350 277581 1 3 0 1 0 0 0 0 0 0.000 1 0.0000 2250 4830 30 30 2250 4830 2280 486082 1 3 0 1 0 0 0 0 0 0.000 1 0.0000 7200 2775 30 30 7200 2775 7230 280583 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3525 3600 150 150 3525 3600 3675 360084 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3 875 4800 100 100 3875 4800 3975 480085 1 1 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4 650 4800 150 75 4650 4800 4800 487568 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4950 2325 150 150 4950 2325 5100 2325 69 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4950 2925 150 150 4950 2925 5100 2925 70 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4950 3675 150 150 4950 3675 5100 3675 71 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 2925 2550 150 150 2925 2550 3075 2550 72 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3600 2175 150 150 3600 2175 3750 2175 73 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3825 2550 150 150 3825 2550 3975 2550 74 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4050 2175 150 150 4050 2175 4200 2175 75 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3375 3300 150 150 3375 3300 3525 3300 76 1 3 0 1 0 0 0 0 0 0.000 1 0.0000 2925 3300 30 30 2925 3300 2955 3330 77 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3150 2175 150 150 3150 2175 3300 2325 78 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4275 3300 150 150 4275 3300 4425 3450 79 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3375 2550 150 150 3375 2550 3525 2550 80 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6600 2475 150 150 6600 2475 6750 2475 81 1 3 0 1 0 0 0 0 0 0.000 1 0.0000 1650 4530 30 30 1650 4530 1680 4560 82 1 3 0 1 0 0 0 0 0 0.000 1 0.0000 6600 2475 30 30 6600 2475 6630 2505 83 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 2925 3300 150 150 2925 3300 3075 3300 84 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3275 4500 100 100 3275 4500 3375 4500 85 1 1 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4050 4500 150 75 4050 4500 4200 4575 86 86 2 2 0 1 -1 -1 0 0 -1 0.000 0 0 0 0 0 5 87 2400 4200 2400 3750 1950 3750 1950 4200 2400 420087 1800 3900 1800 3450 1350 3450 1350 3900 1800 3900 88 88 2 2 1 1 -1 -1 0 0 -1 4.000 0 0 0 0 0 5 89 6300 4500 6300 1800 3000 1800 3000 4500 6300 450089 5700 4200 5700 1500 2400 1500 2400 4200 5700 4200 90 90 2 2 0 1 -1 -1 0 0 -1 0.000 0 0 0 0 0 5 91 5 775 2850 5775 2400 5325 2400 5325 2850 5775 285091 5175 2550 5175 2100 4725 2100 4725 2550 5175 2550 92 92 2 2 0 1 -1 -1 0 0 -1 0.000 0 0 0 0 0 5 93 5 775 4200 5775 3750 5325 3750 5325 4200 5775 420093 5175 3900 5175 3450 4725 3450 4725 3900 5175 3900 94 94 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2 95 95 1 1 1.00 45.00 90.00 96 5175 3975 5325 397596 4575 3675 4725 3675 97 97 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2 98 98 1 1 1.00 45.00 90.00 99 5175 3225 5325 322599 4575 2925 4725 2925 100 100 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2 101 101 1 1 1.00 45.00 90.00 102 5175 2625 5325 2625102 4575 2325 4725 2325 103 103 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2 104 104 1 1 1.00 45.00 90.00 105 5 775 3975 5925 3975105 5175 3675 5325 3675 106 106 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2 107 107 1 1 1.00 45.00 90.00 108 5 775 3225 5925 3225108 5175 2925 5325 2925 109 109 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2 110 110 1 1 1.00 45.00 90.00 111 5 775 2625 5925 2625111 5175 2325 5325 2325 112 112 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2 113 5175 3975 5175 2625113 4575 3675 4575 2325 114 114 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2 115 115 1 1 1.00 45.00 90.00 116 5 925 3975 5925 2025116 5325 3675 5325 1725 117 117 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2 118 118 1 1 1.00 45.00 90.00 119 5 925 3750 6225 3750119 5325 3450 5625 3450 120 120 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2 121 121 1 1 1.00 45.00 90.00 122 3450 2625 3225 2625122 2850 2325 2625 2325 123 123 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 3 124 124 1 1 1.00 45.00 90.00 125 5 925 2025 4200 2025 4200 2250125 5325 1725 3600 1725 3600 1950 126 126 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2 127 3225 2625 3225 3600127 2625 2325 2625 3300 128 128 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2 129 129 1 1 1.00 45.00 90.00 130 3075 3600 3375 3600130 2475 3300 2775 3300 131 131 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2 132 132 1 1 1.00 45.00 90.00 133 3 675 3600 3825 3600133 3075 3300 3225 3300 134 134 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2 135 135 1 1 1.00 45.00 90.00 136 4125 3600 4275 3600136 3525 3300 3675 3300 137 137 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2 138 138 1 1 1.00 45.00 90.00 139 4575 3600 4725 3600139 3975 3300 4125 3300 140 140 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2 141 141 1 1 1.00 45.00 90.00 142 5025 3600 5175 3600142 4425 3300 4575 3300 143 143 2 2 0 1 -1 -1 0 0 -1 0.000 0 0 0 0 0 5 144 5 775 3450 5775 3000 5325 3000 5325 3450 5775 3450144 5175 3150 5175 2700 4725 2700 4725 3150 5175 3150 145 145 2 2 1 1 -1 -1 0 0 -1 4.000 0 0 0 0 0 5 146 8100 4500 8100 1800 6600 1800 6600 4500 8100 4500146 7500 4200 7500 1500 6000 1500 6000 4200 7500 4200 147 147 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2 148 148 1 1 1.00 45.00 90.00 149 7050 2775 6825 2775149 6450 2475 6225 2475 150 150 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2 151 6 825 2775 6825 3750151 6225 2475 6225 3450 152 152 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 4 153 153 1 1 1.00 45.00 90.00 154 7 875 3750 7875 2325 7200 2325 7200 2550154 7275 3450 7275 2025 6600 2025 6600 2250 155 155 2 2 0 1 -1 -1 0 0 -1 0.000 0 0 0 0 0 5 156 5 850 4950 5850 4725 5625 4725 5625 4950 5850 4950156 5250 4650 5250 4425 5025 4425 5025 4650 5250 4650 157 157 2 2 1 1 -1 -1 0 0 -1 3.000 0 0 0 0 0 5 158 6 975 4950 6750 4950 6750 4725 6975 4725 6975 4950159 4 1 -1 0 0 0 10 0.0000 2 105 720 5550 4425 Processors\001160 4 1 -1 0 0 0 10 0.0000 2 120 1005 4200 3225 Blocked Tasks\001161 4 1 -1 0 0 0 10 0.0000 2 150 870 4200 3975 Ready Tasks\001162 4 1 -1 0 0 0 10 0.0000 2 135 1095 7350 1725 Other Cluster(s)\001163 4 1 -1 0 0 0 10 0.0000 2 105 840 4 650 1725 User Cluster\001164 4 1 -1 0 0 0 10 0.0000 2 150 615 2175 3675 Manager\001165 4 1 -1 0 0 0 10 0.0000 2 105 990 2175 3525 Discrete-event\001166 4 1 -1 0 0 0 10 0.0000 2 135 795 2175 4350 preemption\001167 4 0 -1 0 0 0 10 0.0000 2 150 1 290 2325 4875 genrator/coroutine\001168 4 0 -1 0 0 0 10 0.0000 2 120 270 4050 4875 task\001169 4 0 -1 0 0 0 10 0.0000 2 105 450 7050 4875 cluster\001170 4 0 -1 0 0 0 10 0.0000 2 105 660 5 925 4875 processor\001171 4 0 -1 0 0 0 10 0.0000 2 105 555 4 875 4875 monitor\001158 6375 4650 6150 4650 6150 4425 6375 4425 6375 4650 159 4 1 -1 0 0 0 10 0.0000 2 105 720 4950 4125 Processors\001 160 4 1 -1 0 0 0 10 0.0000 2 120 1005 3600 2925 Blocked Tasks\001 161 4 1 -1 0 0 0 10 0.0000 2 150 870 3600 3675 Ready Tasks\001 162 4 1 -1 0 0 0 10 0.0000 2 135 1095 6750 1425 Other Cluster(s)\001 163 4 1 -1 0 0 0 10 0.0000 2 105 840 4050 1425 User Cluster\001 164 4 1 -1 0 0 0 10 0.0000 2 150 615 1575 3375 Manager\001 165 4 1 -1 0 0 0 10 0.0000 2 105 990 1575 3225 Discrete-event\001 166 4 1 -1 0 0 0 10 0.0000 2 135 795 1575 4050 preemption\001 167 4 0 -1 0 0 0 10 0.0000 2 150 1365 1725 4575 generator/coroutine\001 168 4 0 -1 0 0 0 10 0.0000 2 120 270 3450 4575 task\001 169 4 0 -1 0 0 0 10 0.0000 2 105 450 6450 4575 cluster\001 170 4 0 -1 0 0 0 10 0.0000 2 105 660 5325 4575 processor\001 171 4 0 -1 0 0 0 10 0.0000 2 105 555 4275 4575 monitor\001 -
doc/papers/concurrency/mail2
r07d867b r22f94a4 512 512 Software: Practice and Experience Editorial Office 513 513 514 515 516 Date: Sat, 18 Apr 2020 10:42:13 +0000 517 From: Richard Jones <onbehalfof@manuscriptcentral.com> 518 Reply-To: R.E.Jones@kent.ac.uk 519 To: tdelisle@uwaterloo.ca, pabuhr@uwaterloo.ca 520 Subject: Software: Practice and Experience - Decision on Manuscript ID 521 SPE-19-0219.R1 522 523 18-Apr-2020 524 525 Dear Dr Buhr, 526 527 Many thanks for submitting SPE-19-0219.R1 entitled "Advanced Control-flow and Concurrency in Cforall" to Software: Practice and Experience. The paper has now been reviewed and the comments of the referees are included at the bottom of this letter. 528 529 I believe that we are making progress here towards a paper that can be published in Software: Practice and Experience. However the referees still have significant concerns about the paper. The journal's focus is on practice and experience, and one of the the reviewers' concerns remains that your submission should focus the narrative more on the perspective of the programmer than the language designer. I agree that this would strengthen your submission, and I ask you to address this as well as the referees' other comments. 530 531 A revised version of your manuscript that takes into account the comments of the referee(s) will be reconsidered for publication. 532 533 Please note that submitting a revision of your manuscript does not guarantee eventual acceptance, and that your revision may be subject to re-review by the referees before a decision is rendered. 534 535 You have 90 days from the date of this email to submit your revision. If you are unable to complete the revision within this time, please contact me to request a short extension. 536 537 You can upload your revised manuscript and submit it through your Author Center. Log into https://mc.manuscriptcentral.com/spe and enter your Author Center, where you will find your manuscript title listed under "Manuscripts with Decisions". 538 539 When submitting your revised manuscript, you will be able to respond to the comments made by the referee(s) in the space provided. You can use this space to document any changes you make to the original manuscript. 540 541 If you would like help with English language editing, or other article preparation support, Wiley Editing Services offers expert help with English Language Editing, as well as translation, manuscript formatting, and figure formatting at www.wileyauthors.com/eeo/preparation. You can also check out our resources for Preparing Your Article for general guidance about writing and preparing your manuscript at www.wileyauthors.com/eeo/prepresources. 542 543 Once again, thank you for submitting your manuscript to Software: Practice and Experience and I look forward to receiving your revision. 544 545 Sincerely, 546 Richard 547 548 Prof. Richard Jones 549 Software: Practice and Experience 550 R.E.Jones@kent.ac.uk 551 552 553 Referee(s)' Comments to Author: 554 555 Reviewing: 1 556 557 Comments to the Author 558 (A relatively short second review) 559 560 I thank the authors for their revisions and comprehensive response to 561 reviewers' comments --- many of my comments have been successfully 562 addressed by the revisions. Here I'll structure my comments around 563 the main salient points in that response which I consider would 564 benefit from further explanation. 565 566 > Table 1 is moved to the start and explained in detail. 567 568 I consider this change makes a significant improvement to the paper, 569 laying out the landscape of language features at the start, and thus 570 addresses my main concerns about the paper. 571 572 I still have a couple of issues --- perhaps the largest is that it's 573 still not clear at this point in the paper what some of these options 574 are, or crucially how they would be used. I don't know if it's 575 possbile to give high-level examples or use cases to be clear about 576 these up front - or if that would duplicate too much information from 577 later in the paper - either way expanding out the discussion - even if 578 just two a couple of sentences for each row - would help me more. The 579 point is not just to define these categories but to ensure the 580 readers' understanding of these definitons agrees with that used in 581 the paper. 582 583 in a little more detail: 584 585 * 1st para section 2 begs the question: why not support each 586 dimension independently, and let the programmer or library designer 587 combiine features? 588 589 * "execution state" seems a relatively low-level description here. 590 I don't think of e.g. the lambda calculus that way. Perhaps it's as 591 good a term as any. 592 593 * Why must there "be language mechanisms to create, block/unblock, 594 and join with a thread"? There aren't in Smalltalk (although there 595 are in the runtime). Especially given in Cforall those mechanisms 596 are *implicit* on thread creation and destruction? 597 598 * "Case 1 is a function that borrows storage for its state (stack 599 frame/activation) and a thread from its invoker" 600 601 this much makes perfect sense to me, but I don't understand how a 602 non-stateful, non-theaded function can then retain 603 604 "this state across callees, ie, function local-variables are 605 retained on the stack across calls." 606 607 how can it retain function-local values *across calls* when it 608 doesn't have any functional-local state? 609 610 I'm not sure if I see two separate cases here - rougly equivalent 611 to C functions without static storage, and then C functions *with* 612 static storage. I assumed that was the distinction between cases 1 613 & 3; but perhpas the actual distinction is that 3 has a 614 suspend/resume point, and so the "state" in figure 1 is this 615 component of execution state (viz figs 1 & 2), not the state 616 representing the cross-call variables? 617 618 > but such evaluation isn't appropriate for garbage-collected or JITTed 619 languages like Java or Go. 620 621 For JITTed languages in particular, reporting peak performance needs 622 to "warm up" the JIT with a number of iterators before beginning 623 measurement. Actually for JIT's its even worse: see Edd Barrett et al 624 OOPSLA 2017. 625 626 627 628 minor issues: 629 630 * footnote A - I've looked at various other papers & the website to 631 try to understand how "object-oriented" Cforall is - I'm still not 632 sure. This footnote says Cforall has "virtuals" - presumably 633 virtual functions, i.e. dynamic dispatch - and inheritance: that 634 really is OO as far as I (and most OO people) are concerned. For 635 example Haskell doesn't have inheritance, so it's not OO; while 636 CLOS (the Common Lisp *Object* System) or things like Cecil and 637 Dylan are considered OO even though they have "multiple function 638 parameters as receivers", lack "lexical binding between a structure 639 and set of functions", and don't have explicit receiver invocation 640 syntax. Python has receiver syntax, but unlike Java or Smalltalk 641 or C++, method declarations still need to have an explicit "self" 642 receiver parameter. Seems to me that Go, for example, is 643 more-or-less OO with interfaces, methods, and dynamic dispatch (yes 644 also and an explicit receiver syntax but that's not 645 determiniative); while Rust lacks dynamic dispatch built-in. C is 646 not OO as a language, but as you say given it supports function 647 pointers with structures, it does support an OO programm style. 648 649 This is why I again recommend just not buying into this fight: not 650 making any claims about whether Cforall is OO or is not - because 651 as I see it, the rest of the paper doesn't depend on whether 652 Cforall is OO or not. That said: this is just a recommendation, 653 and I won't quibble over this any further. 654 655 * is a "monitor function" the same as a "mutex function"? 656 if so the paper should pick one term; if not, make the distinction clear. 657 658 659 * "As stated on line 1 because state declarations from the generator 660 type can be moved out of the coroutine type into the coroutine main" 661 662 OK sure, but again: *why* would a programmer want to do that? 663 (Other than, I guess, to show the difference between coroutines & 664 generators?) Perhaps another way to put this is that the first 665 para of 3.2 gives the disadvantages of coroutines vs-a-vs 666 generators, briefly describes the extended semantics, but never 667 actualy says why a programmer may want those extended semantics, 668 or how they would benefit. I don't mean to belabour the point, 669 but (generalist?) readers like me would generally benefit from 670 those kinds of discussions about each feature throughout the 671 paper: why might a programmer want to use them? 672 673 674 > p17 if the multiple-monitor entry procedure really is novel, write a paper 675 > about that, and only about that. 676 677 > We do not believe this is a practical suggestion. 678 679 * I'm honestly not trying to be snide here: I'm not an expert on 680 monitor or concurrent implementations. Brinch Hansen's original 681 monitors were single acquire; this draft does not cite any other 682 previous work that I could see. I'm not suggesting that the brief 683 mention of this mechanism necessarily be removed from this paper, 684 but if this is novel (and a clear advance over a classical OO 685 monitor a-la Java which only acquires the distinguished reciever) 686 then that would be worth another paper in itself. 687 688 > * conclusion should conclude the paper, not the related. 689 > We do not understand this comment.if ithis 690 691 My typo: the paper's conclusion should come at the end, after the 692 future work section. 693 694 695 696 697 To encourage accountability, I'm signing my reviews in 2020. 698 For the record, I am James Noble, kjx@ecs.vuw.ac.nz. 699 700 701 Reviewing: 2 702 703 Comments to the Author 704 I thank the authors for their detailed response. To respond to a couple of points raised in response to my review (number 2): 705 706 - on the Boehm paper and whether code is "all sequential to the compiler": I now understand the authors' position better and suspect we are in violent agreement, except for whether it's appropriate to use the rather breezy phrase "all sequential to the compiler". It would be straightforward to clarify that code not using the atomics features is optimized *as if* it were sequential, i.e. on the assumption of a lack of data races. 707 708 - on the distinction between "mutual exclusion" and "synchronization": the added citation does help, in that it makes a coherent case for the definition the authors prefer. However, the text could usefully clarify that this is a matter of definition not of fact, given especially that in my assessment the authors' preferred definition is not the most common one. (Although the mention of Hoare's apparent use of this definition is one data point, countervailing ones are found in many contemporaneous or later papers, e.g. Habermann's 1972 "Synchronization of Communicating Processes" (CACM 15(3)), Reed & Kanodia's 1979 "Synchronization with eventcounts and sequencers" (CACM (22(2)) and so on.) 709 710 I am glad to see that the authors have taken on board most of the straightforward improvements I suggested. 711 712 However, a recurring problem of unclear writing still remains through many parts of the paper, including much of sections 2, 3 and 6. To highlight a couple of problem patches (by no means exhaustive): 713 714 - section 2 (an expanded version of what was previously section 5.9) lacks examples and is generally obscure and allusory ("the most advanced feature" -- name it! "in triplets" -- there is only one triplet!; what are "execution locations"? "initialize" and "de-initialize" what? "borrowed from the invoker" is a concept in need of explaining or at least a fully explained example -- in what sense does a plain function borrow" its stack frame? "computation only" as opposed to what? in 2.2, in what way is a "request" fundamental to "synchronization"? and the "implicitly" versus "explicitly" point needs stating as elsewhere, with a concrete example e.g. Java built-in mutexes versus java.util.concurrent). 715 716 - section 6: 6.2 omits the most important facts in preference for otherwise inscrutable detail: "identify the kind of parameter" (first say *that there are* kinds of parameter, and what "kinds" means!); "mutex parameters are documentation" is misleading (they are also semantically significant!) and fails to say *what* they mean; the most important thing is surely that 'mutex' is a language feature for performing lock/unlock operations at function entry/exit. So say it! The meanings of examples f3 and f4 remain unclear. Meanwhile in 6.3, "urgent" is not introduced (we are supposed to infer its meaning from Figure 12, but that Figure is incomprehensible to me), and we are told of "external scheduling"'s long history in Ada but not clearly what it actually means; 6.4's description of "waitfor" tells us it is different from an if-else chain but tries to use two *different* inputs to tell us that the behavior is different; tell us an instance where *the same* values of C1 and C2 give different behavior (I even wrote out a truth table and still don't see the semantic difference) 717 718 The authors frequently use bracketed phrases, and sometimes slashes "/", in ways that are confusing and/or detrimental to readability. Page 13 line 2's "forward (backward)" is one particularly egregious example. In general I would recommend the the authors try to limit their use of parentheses and slashes as a means of forcing a clearer wording to emerge. Also, the use of "eg." is often cursory and does not explain the examples given, which are frequently a one- or two-word phrase of unclear referent. 719 720 Considering the revision more broadly, none of the more extensive or creative rewrites I suggested in my previous review have been attempted, nor any equivalent efforts to improve its readability. The hoisting of the former section 5.9 is a good idea, but the newly added material accompanying it (around Table 1) suffers fresh deficiencies in clarity. Overall the paper is longer than before, even though (as my previous review stated), I believe a shorter paper is required in order to serve the likely purpose of publication. (Indeed, the authors' letter implies that a key goal of publication is to build community and gain external users.) 721 722 Given this trajectory, I no longer see a path to an acceptable revision of the present submission. Instead I suggest the authors consider splitting the paper in two: one half about coroutines and stack management, the other about mutexes, monitors and the runtime. (A briefer presentation of the runtime may be helpful in the first paper also, and a brief recap of the generator and coroutine support is obviously needed in the second too.) Both of these new papers would need to be written with a strong emphasis on clarity, paying great care to issues of structure, wording, choices of example, and restraint (saying what's important, not everything that could be said). I am confident the authors could benefit from getting early feedback from others at their institution. For the performance experiments, of course these do not split evenly -- most (but not all) belong in the second of these two hypothetical papers. But the first of them would still have plenty of meat to it; for me, a clear and thorough study of the design space around coroutines is the most interesting and tantalizing prospect. 723 724 I do not buy the authors' defense of the limited practical experience or "non-micro" benchmarking presented. Yes, gaining external users is hard and I am sympathetic on that point. But building something at least *somewhat* substantial with your own system should be within reach, and without it the "practice and experience" aspects of the work have not been explored. Clearly C\/ is the product of a lot of work over an extended period, so it is a surprise that no such experience is readily available for inclusion. 725 726 Some smaller points: 727 728 It does not seem right to state that a stack is essential to Von Neumann architectures -- since the earliest Von Neumann machines (and indeed early Fortran) did not use one. 729 730 To elaborate on something another reviewer commented on: it is a surprise to find a "Future work" section *after* the "Conclusion" section. A "Conclusions and future work" section often works well. 731 732 733 Reviewing: 3 734 735 Comments to the Author 736 This is the second round of reviewing. 737 738 As in the first review, I found that the paper (and Cforall) contains 739 a lot of really interesting ideas, but it remains really difficult to 740 have a good sense of which idea I should use and when. This applies in 741 different ways to different features from the language: 742 743 * coroutines/generators/threads: here there is 744 some discussion, but it can be improved. 745 * interal/external scheduling: I didn't find any direct comparison 746 between these features, except by way of example. 747 748 I requested similar things in my previous review and I see that 749 content was added in response to those requests. Unfortunately, I'm 750 not sure that I can say it improved the paper's overall read. I think 751 in some sense the additions were "too much" -- I would have preferred 752 something more like a table or a few paragraphs highlighting the key 753 reasons one would pick one construct or the other. 754 755 In general, I do wonder if the paper is just trying to do too much. 756 The discussion of clusters and pre-emption in particular feels quite 757 rushed. 758 759 ## Summary 760 761 I make a number of suggestions below but the two most important 762 I think are: 763 764 * Recommend to shorten the comparison on coroutine/generator/threads 765 in Section 2 to a paragraph with a few examples, or possibly a table 766 explaining the trade-offs between the constructs 767 * Recommend to clarify the relationship between internal/external 768 scheduling -- is one more general but more error-prone or low-level? 769 770 ## Coroutines/generators/threads 771 772 There is obviously a lot of overlap between these features, and in 773 particular between coroutines and generators. As noted in the previous 774 review, many languages have chosen to offer *only* generators, and to 775 build coroutines by stacks of generators invoking one another. 776 777 I believe the newly introduced Section 2 of the paper is trying to 778 motivate why each of these constructs exist, but I did not find it 779 effective. It was dense and difficult to understand. I think the 780 problem is that Section 2 seems to be trying to derive "from first 781 principles" why each construct exists, but I think that a more "top 782 down" approach would be easier to understand. 783 784 In fact, the end of Section 2.1 (on page 5) contains a particular 785 paragraph that embodies this "top down" approach. It starts, 786 "programmers can now answer three basic questions", and thus gives 787 some practical advice for which construct you should use and when. I 788 think giving some examples of specific applications that this 789 paragraph, combined with some examples of cases where each construct 790 was needed, would be a better approach. 791 792 I don't think this compariosn needs to be very long. It seems clear 793 enough that one would 794 795 * prefer generators for simple computations that yield up many values, 796 * prefer coroutines for more complex processes that have significant 797 internal structure, 798 * prefer threads for cases where parallel execution is desired or 799 needed. 800 801 I did appreciate the comparison in Section 2.3 between async-await in 802 JS/Java and generators/coroutines. I agree with its premise that those 803 mechanisms are a poor replacement for generators (and, indeed, JS has 804 a distinct generator mechanism, for example, in part for this reason). 805 I believe I may have asked for this in a previous review, but having 806 read it, I wonder if it is really necessary, since those mechanisms 807 are so different in purpose. 808 809 ## Internal vs external scheduling 810 811 I find the motivation for supporting both internal and external 812 scheduling to be fairly implicit. After several reads through the 813 section, I came to the conclusion that internal scheduling is more 814 expressive than external scheduling, but sometimes less convenient or 815 clear. Is this correct? If not, it'd be useful to clarify where 816 external scheduling is more expressive. 817 818 The same is true, I think, of the `signal_block` function, which I 819 have not encountered before; it seems like its behavior can be modeled 820 with multiple condition variables, but that's clearly more complex. 821 822 One question I had about `signal_block`: what happens if one signals 823 but no other thread is waiting? Does it block until some other thread 824 waits? Or is that user error? 825 826 I would find it very interesting to try and capture some of the 827 properties that make internal vs external scheduling the better 828 choice. 829 830 For example, it seems to me that external scheduling works well if 831 there are only a few "key" operations, but that internal scheduling 832 might be better otherwise, simply because it would be useful to have 833 the ability to name a signal that can be referenced by many 834 methods. Consider the bounded buffer from Figure 13: if it had 835 multiple methods for removing elements, and not just `remove`, then 836 the `waitfor(remove)` call in `insert` might not be sufficient. 837 838 ## Comparison of external scheduling to messaging 839 840 I did enjoy the section comparing external scheduling to Go's 841 messaging mechanism, which I believe is a new addition. 842 843 I believe that one difference between the Go program and the Cforall 844 equivalent is that the Goroutine has an associated queue, so that 845 multiple messages could be enqueued, whereas the Cforall equivalent is 846 effectively a "bounded buffer" of length 1. Is that correct? I think 847 this should be stated explicitly. (Presumably, one could modify the 848 Cforall program to include an explicit vector of queued messages if 849 desired, but you would also be reimplementing the channel 850 abstraction.) 851 852 Also, in Figure 20, I believe that there is a missing `mutex` keyword. 853 The fiugre states: 854 855 ``` 856 void main(GoRtn & gortn) with(gortn) { 857 ``` 858 859 but I think it should probably be as follows: 860 861 ``` 862 void main(GoRtn & mutex gortn) with(gortn) { 863 ``` 864 865 Unless there is some implicit `mutex` associated with being a main 866 function for a `monitor thread`. 867 868 ## Atomic operations and race freedom 869 870 I was glad to see that the paper acknowledged that Cforall still had 871 low-level atomic operations, even if their use is discouraged in favor 872 of higher-level alternatives. 873 874 However, I still feel that the conclusion overstates the value of the 875 contribution here when it says that "Cforall high-level race-free 876 monitors and threads provide the core mechanisms for mutual exclusion 877 and synchronization, without the need for volatile and atomics". I 878 feel confident that Java programmers, for example, would be advised to 879 stick with synchronized methods whenever possible, and it seems to me 880 that they offer similar advantages -- but they sometimes wind up using 881 volatiles for performance reasons. 882 883 I was also confused by the term "race-free" in that sentence. In 884 particular, I don't think that Cforall has any mechanisms for 885 preventing *data races*, and it clearly doesn't prevent "race 886 conditions" (which would bar all sorts of useful programs). I suppose 887 that "race free" here might be referring to the improvements such as 888 removing barging behavior. 889 890 ## Performance comparisons 891 892 In my previous review, I requested comparisons against Rust and 893 node.js, and I see that the new version of the paper includes both, 894 which is a good addition. 895 896 One note on the Rust results: I believe that the results are comparing 897 against the threads found in Rust's standard library, which are 898 essentially a shallow wrapper around pthreads, and hence the 899 performance is quite close to pthread performance (as one would 900 expect). It would perhaps be more interesting to see a comparison 901 built using [tokio] or [async-std], two of the more prominent 902 user-space threading libraries that build on Rust's async-await 903 feature (which operates quite differently than Javascript's 904 async-await, in that it doesn't cause every aync function call to 905 schedule a distinct task). 906 907 [tokio]: https://tokio.rs/ 908 [async-std]: https://async.rs/ 909 910 That said, I am satisfied with the performance results as they are in 911 the current revision. 912 913 ## Minor notes and typos 914 915 Several figures used the `with` keyword. I deduced that `with(foo)` 916 permits one to write `bar` instead of `foo.bar`. It seems worth 917 introducing. Apologies if this is stated in the paper, if so I missed 918 it. 919 920 On page 20, section 6.3, "external scheduling and vice versus" should be 921 "external scheduling and vice versa". 922 923 On page 5, section 2.3, the paper states "we content" but it should be 924 "we contend". 925 926 Reviewing: Editor 927 928 A few small comments in addition to those of the referees. 929 930 Page 1. I don't believe that it s fair to imply that Scala is "research vehicle" as it is used by major players, Twitter being the most prominent example. 931 932 Page 15. Must Cforall threads start after construction (e.g. see your example on page 15, line 21)? I can think of examples where it is not desirable that threads start immediately after construction, e.g. a game with N players, each of whom is expensive to create, but all of whom should be started at the same time. 933 934 Page 18, line 17: is using 935 936 937 938 Date: Tue, 16 Jun 2020 13:45:03 +0000 939 From: Aaron Thomas <onbehalfof@manuscriptcentral.com> 940 Reply-To: speoffice@wiley.com 941 To: tdelisle@uwaterloo.ca, pabuhr@uwaterloo.ca 942 Subject: SPE-19-0219.R2 successfully submitted 943 944 16-Jun-2020 945 946 Dear Dr Buhr, 947 948 Your manuscript entitled "Advanced Control-flow and Concurrency in Cforall" has been successfully submitted online and is presently being given full consideration for publication in Software: Practice and Experience. 949 950 Your manuscript number is SPE-19-0219.R2. Please mention this number in all future correspondence regarding this submission. 951 952 You can view the status of your manuscript at any time by checking your Author Center after logging into https://mc.manuscriptcentral.com/spe. If you have difficulty using this site, please click the 'Get Help Now' link at the top right corner of the site. 953 954 955 Thank you for submitting your manuscript to Software: Practice and Experience. 956 957 Sincerely, 958 959 Software: Practice and Experience Editorial Office 960 -
doc/proposals/vtable.md
r07d867b r22f94a4 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 -
doc/theses/thierry_delisle_PhD/code/relaxed_list.cpp
r07d867b r22f94a4 1 #include "relaxed_list.hpp" 1 #if !defined(LIST_VARIANT_HPP) 2 #define LIST_VARIANT_HPP "relaxed_list.hpp" 3 #endif 4 5 #include LIST_VARIANT_HPP 6 #if !defined(LIST_VARIANT) 7 #error not variant selected 8 #endif 2 9 3 10 #include <array> … … 35 42 36 43 template<> 37 thread_local relaxed_list<Node>::TLS relaxed_list<Node>::tls = {};44 thread_local LIST_VARIANT<Node>::TLS LIST_VARIANT<Node>::tls = {}; 38 45 39 46 template<> 40 relaxed_list<Node> * relaxed_list<Node>::head = nullptr;47 std::atomic_uint32_t LIST_VARIANT<Node>::ticket = { 0 }; 41 48 42 49 #ifndef NO_STATS 43 50 template<> 44 relaxed_list<Node>::GlobalStats relaxed_list<Node>::global_stats = {};51 LIST_VARIANT<Node>::GlobalStats LIST_VARIANT<Node>::global_stats = {}; 45 52 #endif 46 53 … … 57 64 size_t valmax = 0; 58 65 size_t valmin = 100000000ul; 66 struct { 67 size_t val = 0; 68 size_t cnt = 0; 69 } comp; 70 struct { 71 size_t val = 0; 72 size_t cnt = 0; 73 } subm; 59 74 }; 60 75 … … 67 82 std::atomic_size_t valmax = { 0 }; 68 83 std::atomic_size_t valmin = { 100000000ul }; 84 struct { 85 std::atomic_size_t val = { 0 }; 86 std::atomic_size_t cnt = { 0 }; 87 } comp; 88 struct { 89 std::atomic_size_t val = { 0 }; 90 std::atomic_size_t cnt = { 0 }; 91 } subm; 69 92 }; 70 93 … … 96 119 global.crc_out += local.crc_out; 97 120 121 global.comp.val += local.comp.val; 122 global.comp.cnt += local.comp.cnt; 123 global.subm.val += local.subm.val; 124 global.subm.cnt += local.subm.cnt; 125 98 126 atomic_max(global.valmax, local.valmax); 99 127 atomic_min(global.valmin, local.valmin); 100 128 101 relaxed_list<Node>::stats_tls_tally();129 LIST_VARIANT<Node>::stats_tls_tally(); 102 130 } 103 131 … … 106 134 auto before = Clock::now(); 107 135 barrier.wait(0); 136 bool is_tty = isatty(STDOUT_FILENO); 108 137 109 138 while(true) { … … 115 144 break; 116 145 } 117 std::cout << "\r" << std::setprecision(4) << durr.count(); 118 std::cout.flush(); 146 if(is_tty) { 147 std::cout << "\r" << std::setprecision(4) << durr.count(); 148 std::cout.flush(); 149 } 119 150 } 120 151 … … 159 190 auto dur_nano = duration_cast<std::nano>(1.0); 160 191 192 if(global.valmax != 0) { 193 std::cout << "Max runs : " << global.valmax << "\n"; 194 std::cout << "Min runs : " << global.valmin << "\n"; 195 } 196 if(global.comp.cnt != 0) { 197 std::cout << "Submit count : " << global.subm.cnt << "\n"; 198 std::cout << "Submit average: " << ((double(global.subm.val)) / global.subm.cnt) << "\n"; 199 std::cout << "Complete count: " << global.comp.cnt << "\n"; 200 std::cout << "Complete avg : " << ((double(global.comp.val)) / global.comp.cnt) << "\n"; 201 } 161 202 std::cout << "Duration : " << duration << "s\n"; 162 203 std::cout << "ns/Op : " << ( dur_nano / ops_thread )<< "\n"; … … 164 205 std::cout << "Ops/sec : " << ops_sec << "\n"; 165 206 std::cout << "Total ops : " << ops << "(" << global.in << "i, " << global.out << "o, " << global.empty << "e)\n"; 166 if(global.valmax != 0) {167 std::cout << "Max runs : " << global.valmax << "\n";168 std::cout << "Min runs : " << global.valmin << "\n";169 }170 207 #ifndef NO_STATS 171 relaxed_list<Node>::stats_print(std::cout);208 LIST_VARIANT<Node>::stats_print(std::cout); 172 209 #endif 173 210 } … … 186 223 unsigned nslots, 187 224 local_stat_t & local, 188 relaxed_list<Node> & list225 LIST_VARIANT<Node> & list 189 226 ) { 190 227 while(__builtin_expect(!done.load(std::memory_order_relaxed), true)) { … … 224 261 std::cout << "Initializing "; 225 262 size_t npushed = 0; 226 relaxed_list<Node> list = { nthread *nqueues };263 LIST_VARIANT<Node> list = { nthread, nqueues }; 227 264 { 228 265 Node** all_nodes[nthread]; … … 310 347 unsigned nnodes, 311 348 local_stat_t & local, 312 relaxed_list<Node> & list349 LIST_VARIANT<Node> & list 313 350 ) { 314 351 Node * nodes[nnodes]; … … 354 391 std::cout << "Initializing "; 355 392 // List being tested 356 relaxed_list<Node> list = { nthread *nqueues };393 LIST_VARIANT<Node> list = { nthread, nqueues }; 357 394 { 358 395 enable_stats = true; … … 395 432 396 433 enable_stats = false; 434 } 435 436 print_stats(duration, nthread, global); 437 } 438 439 // ================================================================================================ 440 struct __attribute__((aligned(64))) Slot { 441 Node * volatile node; 442 }; 443 444 __attribute__((noinline)) void runProducer_body( 445 std::atomic<bool>& done, 446 Random & rand, 447 Slot * slots, 448 int nslots, 449 local_stat_t & local, 450 LIST_VARIANT<Node> & list 451 ) { 452 while(__builtin_expect(!done.load(std::memory_order_relaxed), true)) { 453 454 Node * node = list.pop(); 455 if(!node) { 456 local.empty ++; 457 continue; 458 } 459 460 local.crc_out += node->value; 461 local.out++; 462 463 if(node->id == 0) { 464 unsigned cnt = 0; 465 for(int i = 0; i < nslots; i++) { 466 Node * found = __atomic_exchange_n( &slots[i].node, nullptr, __ATOMIC_SEQ_CST ); 467 if( found ) { 468 local.crc_in += found->value; 469 local.in++; 470 cnt++; 471 list.push( found ); 472 } 473 } 474 475 local.crc_in += node->value; 476 local.in++; 477 list.push( node ); 478 479 local.comp.cnt++; 480 local.comp.val += cnt; 481 } 482 else { 483 unsigned len = 0; 484 while(true) { 485 auto off = rand.next(); 486 for(int i = 0; i < nslots; i++) { 487 Node * expected = nullptr; 488 int idx = (i + off) % nslots; 489 Slot & slot = slots[ idx ]; 490 if( 491 slot.node == nullptr && 492 __atomic_compare_exchange_n( &slot.node, &expected, node, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST ) 493 ) { 494 local.subm.cnt++; 495 local.subm.val += len; 496 goto LOOP; 497 } 498 assert( expected != node ); 499 len++; 500 } 501 } 502 } 503 504 LOOP:; 505 } 506 } 507 508 void runProducer(unsigned nthread, unsigned nqueues, double duration, unsigned nnodes) { 509 std::cout << "Producer Benchmark" << std::endl; 510 511 // Barrier for synchronization 512 barrier_t barrier(nthread + 1); 513 514 // Data to check everything is OK 515 global_stat_t global; 516 517 // Flag to signal termination 518 std::atomic_bool done = { false }; 519 520 std::cout << "Initializing "; 521 522 int nslots = nnodes * 4; 523 Slot * slots = new Slot[nslots]; 524 std::cout << nnodes << " nodes (" << nslots << " slots)" << std::endl; 525 526 // List being tested 527 LIST_VARIANT<Node> list = { nthread, nqueues }; 528 { 529 Random rand(rdtscl()); 530 for(unsigned i = 0; i < nnodes; i++) { 531 Node * node = new Node(rand.next() % 100); 532 node->id = i; 533 global.crc_in += node->value; 534 list.push(node); 535 } 536 537 for(int i = 0; i < nslots; i++) { 538 slots[i].node = nullptr; 539 } 540 } 541 542 { 543 enable_stats = true; 544 545 std::thread * threads[nthread]; 546 unsigned i = 1; 547 for(auto & t : threads) { 548 t = new std::thread([&done, &list, &barrier, &global, slots, nslots](unsigned tid) { 549 Random rand(tid + rdtscl()); 550 551 local_stat_t local; 552 barrier.wait(tid); 553 554 // EXPERIMENT START 555 556 runProducer_body(done, rand, slots, nslots, local, list); 557 558 // EXPERIMENT END 559 560 barrier.wait(tid); 561 562 tally_stats(global, local); 563 }, i++); 564 } 565 566 waitfor(duration, barrier, done); 567 568 for(auto t : threads) { 569 t->join(); 570 delete t; 571 } 572 573 enable_stats = false; 574 } 575 576 { 577 while(Node * node = list.pop()) { 578 global.crc_out += node->value; 579 delete node; 580 } 581 582 for(int i = 0; i < nslots; i++) { 583 delete slots[i].node; 584 } 585 586 delete [] slots; 397 587 } 398 588 … … 410 600 unsigned nnodes, 411 601 local_stat_t & local, 412 relaxed_list<Node> & list602 LIST_VARIANT<Node> & list 413 603 ) { 414 604 Node * nodes[nnodes]; … … 470 660 471 661 // List being tested 472 relaxed_list<Node> list = { nthread *nqueues };662 LIST_VARIANT<Node> list = { nthread, nqueues }; 473 663 { 474 664 enable_stats = true; … … 521 711 print_stats(duration, nthread, global); 522 712 523 save_fairness(data_out.get(), 100, nthread, width, length, output);713 // save_fairness(data_out.get(), 100, nthread, width, length, output); 524 714 } 525 715 … … 547 737 Churn, 548 738 PingPong, 739 Producer, 549 740 Fairness, 550 741 NONE … … 577 768 case PingPong: 578 769 nnodes = 1; 579 nslots = 1;580 770 switch(argc - optind) { 581 771 case 0: break; … … 591 781 break; 592 782 default: 593 std::cerr << "'PingPong' benchmark doesn't accept more than 2 extra arguments" << std::endl; 783 std::cerr << "'PingPong' benchmark doesn't accept more than 1 extra arguments" << std::endl; 784 goto usage; 785 } 786 break; 787 case Producer: 788 nnodes = 32; 789 switch(argc - optind) { 790 case 0: break; 791 case 1: 792 try { 793 arg = optarg = argv[optind]; 794 nnodes = stoul(optarg, &len); 795 if(len != arg.size()) { throw std::invalid_argument(""); } 796 } catch(std::invalid_argument &) { 797 std::cerr << "Number of nodes must be a positive integer, was " << arg << std::endl; 798 goto usage; 799 } 800 break; 801 default: 802 std::cerr << "'Producer' benchmark doesn't accept more than 1 extra arguments" << std::endl; 594 803 goto usage; 595 804 } … … 662 871 break; 663 872 } 873 if(iequals(arg, "producer")) { 874 benchmark = Producer; 875 break; 876 } 664 877 if(iequals(arg, "fairness")) { 665 878 benchmark = Fairness; … … 702 915 std::cerr << "Usage: " << argv[0] << ": [options] -b churn [NNODES] [NSLOTS = NNODES]" << std::endl; 703 916 std::cerr << " or: " << argv[0] << ": [options] -b pingpong [NNODES]" << std::endl; 917 std::cerr << " or: " << argv[0] << ": [options] -b producer [NNODES]" << std::endl; 704 918 std::cerr << std::endl; 705 919 std::cerr << " -d, --duration=DURATION Duration of the experiment, in seconds" << std::endl; … … 714 928 715 929 std::cout << "Running " << nthreads << " threads (" << (nthreads * nqueues) << " queues) for " << duration << " seconds" << std::endl; 930 std::cout << "Relaxed list variant: " << LIST_VARIANT<Node>::name() << std::endl; 716 931 switch(benchmark) { 717 932 case Churn: … … 720 935 case PingPong: 721 936 runPingPong(nthreads, nqueues, duration, nnodes); 937 break; 938 case Producer: 939 runProducer(nthreads, nqueues, duration, nnodes); 722 940 break; 723 941 case Fairness: … … 801 1019 } 802 1020 803 void save_fairness(const int data[], int factor, unsigned nthreads, size_t columns, size_t rows, const std::string & output) {804 std::ofstream os(output);805 os << "<html>\n";806 os << "<head>\n";807 os << "<style>\n";808 os << "</style>\n";809 os << "</head>\n";810 os << "<body>\n";811 os << "<table style=\"width=100%\">\n";812 813 size_t idx = 0;814 for(size_t r = 0ul; r < rows; r++) {815 os << "<tr>\n";816 for(size_t c = 0ul; c < columns; c++) {817 os << "<td class=\"custom custom" << data[idx] << "\"></td>\n";818 idx++;819 }820 os << "</tr>\n";821 }822 823 os << "</table>\n";824 os << "</body>\n";825 os << "</html>\n";826 os << std::endl;827 }828 829 #include <png.h>830 #include <setjmp.h>1021 // void save_fairness(const int data[], int factor, unsigned nthreads, size_t columns, size_t rows, const std::string & output) { 1022 // std::ofstream os(output); 1023 // os << "<html>\n"; 1024 // os << "<head>\n"; 1025 // os << "<style>\n"; 1026 // os << "</style>\n"; 1027 // os << "</head>\n"; 1028 // os << "<body>\n"; 1029 // os << "<table style=\"width=100%\">\n"; 1030 1031 // size_t idx = 0; 1032 // for(size_t r = 0ul; r < rows; r++) { 1033 // os << "<tr>\n"; 1034 // for(size_t c = 0ul; c < columns; c++) { 1035 // os << "<td class=\"custom custom" << data[idx] << "\"></td>\n"; 1036 // idx++; 1037 // } 1038 // os << "</tr>\n"; 1039 // } 1040 1041 // os << "</table>\n"; 1042 // os << "</body>\n"; 1043 // os << "</html>\n"; 1044 // os << std::endl; 1045 // } 1046 1047 // #include <png.h> 1048 // #include <setjmp.h> 831 1049 832 1050 /* -
doc/theses/thierry_delisle_PhD/code/relaxed_list.hpp
r07d867b r22f94a4 1 1 #pragma once 2 #define LIST_VARIANT relaxed_list 3 4 #define VANILLA 0 5 #define SNZI 1 6 #define BITMASK 2 7 #define DISCOVER 3 8 #define SNZM 4 9 #define BIAS 5 10 #define BACK 6 11 #define BACKBIAS 7 12 13 #ifndef VARIANT 14 #define VARIANT VANILLA 15 #endif 2 16 3 17 #ifndef NO_STATS … … 5 19 #endif 6 20 21 #include <cmath> 22 #include <functional> 7 23 #include <memory> 8 24 #include <mutex> 25 #include <thread> 9 26 #include <type_traits> 10 27 11 28 #include "assert.hpp" 12 29 #include "utils.hpp" 30 #include "links.hpp" 31 #include "snzi.hpp" 32 #include "snzi-packed.hpp" 33 #include "snzm.hpp" 13 34 14 35 using namespace std; 15 16 struct spinlock_t {17 std::atomic_bool ll = { false };18 19 inline void lock() {20 while( __builtin_expect(ll.exchange(true),false) ) {21 while(ll.load(std::memory_order_relaxed))22 asm volatile("pause");23 }24 }25 26 inline bool try_lock() {27 return false == ll.exchange(true);28 }29 30 inline void unlock() {31 ll.store(false, std::memory_order_release);32 }33 34 inline explicit operator bool() {35 return ll.load(std::memory_order_relaxed);36 }37 };38 39 static inline bool bts(std::atomic_size_t & target, size_t bit ) {40 //*41 int result = 0;42 asm volatile(43 "LOCK btsq %[bit], %[target]\n\t"44 :"=@ccc" (result)45 : [target] "m" (target), [bit] "r" (bit)46 );47 return result != 0;48 /*/49 size_t mask = 1ul << bit;50 size_t ret = target.fetch_or(mask, std::memory_order_relaxed);51 return (ret & mask) != 0;52 //*/53 }54 55 static inline bool btr(std::atomic_size_t & target, size_t bit ) {56 //*57 int result = 0;58 asm volatile(59 "LOCK btrq %[bit], %[target]\n\t"60 :"=@ccc" (result)61 : [target] "m" (target), [bit] "r" (bit)62 );63 return result != 0;64 /*/65 size_t mask = 1ul << bit;66 size_t ret = target.fetch_and(~mask, std::memory_order_relaxed);67 return (ret & mask) != 0;68 //*/69 }70 71 extern bool enable_stats;72 36 73 37 struct pick_stat { … … 75 39 size_t attempt = 0; 76 40 size_t success = 0; 41 size_t local = 0; 77 42 } push; 78 43 struct { … … 80 45 size_t success = 0; 81 46 size_t mask_attempt = 0; 47 size_t mask_reset = 0; 48 size_t local = 0; 82 49 } pop; 83 50 }; … … 95 62 96 63 template<typename node_t> 97 struct _LinksFields_t {98 node_t * prev = nullptr;99 node_t * next = nullptr;100 unsigned long long ts = 0;101 };102 103 template<typename node_t>104 64 class __attribute__((aligned(128))) relaxed_list { 105 65 static_assert(std::is_same<decltype(node_t::_links), _LinksFields_t<node_t>>::value, "Node must have a links field"); 106 66 107 67 public: 108 relaxed_list(unsigned numLists) 109 : lists(new intrusive_queue_t[numLists]) 110 , numLists(numLists) 68 static const char * name() { 69 const char * names[] = { 70 "RELAXED: VANILLA", 71 "RELAXED: SNZI", 72 "RELAXED: BITMASK", 73 "RELAXED: SNZI + DISCOVERED MASK", 74 "RELAXED: SNZI + MASK", 75 "RELAXED: SNZI + LOCAL BIAS", 76 "RELAXED: SNZI + REVERSE RNG", 77 "RELAXED: SNZI + LOCAL BIAS + REVERSE RNG" 78 }; 79 return names[VARIANT]; 80 } 81 82 relaxed_list(unsigned numThreads, unsigned numQueues) 83 : numLists(numThreads * numQueues) 84 , lists(new intrusive_queue_t<node_t>[numLists]) 85 #if VARIANT == SNZI || VARIANT == BACK 86 , snzi( std::log2( numLists / (2 * numQueues) ), 2 ) 87 #elif VARIANT == BIAS || VARIANT == BACKBIAS 88 #ifdef SNZI_PACKED 89 , snzi( std::ceil( std::log2(numLists) ) ) 90 #else 91 , snzi( std::log2( numLists / (2 * numQueues) ), 2 ) 92 #endif 93 #elif VARIANT == SNZM || VARIANT == DISCOVER 94 , snzm( numLists ) 95 #endif 111 96 { 112 97 assertf(7 * 8 * 8 >= numLists, "List currently only supports 448 sublists"); 113 // assert(sizeof(*this) == 128);114 98 std::cout << "Constructing Relaxed List with " << numLists << std::endl; 115 116 #ifndef NO_STATS117 if(head) this->next = head;118 head = this;119 #endif120 99 } 121 100 … … 130 109 while(true) { 131 110 // Pick a random list 132 unsigned i = tls.rng.next() % numLists;111 unsigned i = idx_from_r(tls.rng1.next(), VARIANT == BIAS || VARIANT == BACKBIAS); 133 112 134 113 #ifndef NO_STATS … … 139 118 if( !lists[i].lock.try_lock() ) continue; 140 119 141 __attribute__((unused)) int num = numNonEmpty; 120 #if VARIANT == VANILLA || VARIANT == BITMASK 121 __attribute__((unused)) int num = numNonEmpty; 122 #endif 142 123 143 124 // Actually push it 144 125 if(lists[i].push(node)) { 145 numNonEmpty++; 146 size_t qword = i >> 6ull; 147 size_t bit = i & 63ull; 148 assertf((list_mask[qword] & (1ul << bit)) == 0, "Before set %zu:%zu (%u), %zx & %zx", qword, bit, i, list_mask[qword].load(), (1ul << bit)); 149 __attribute__((unused)) bool ret = bts(list_mask[qword], bit); 150 assert(!ret); 151 assertf((list_mask[qword] & (1ul << bit)) != 0, "After set %zu:%zu (%u), %zx & %zx", qword, bit, i, list_mask[qword].load(), (1ul << bit)); 152 } 153 assert(numNonEmpty <= (int)numLists); 126 #if VARIANT == DISCOVER 127 size_t qword = i >> 6ull; 128 size_t bit = i & 63ull; 129 assert(qword == 0); 130 bts(tls.mask, bit); 131 snzm.arrive(i); 132 #elif VARIANT == SNZI || VARIANT == BIAS 133 snzi.arrive(i); 134 #elif VARIANT == BACK || VARIANT == BACKBIAS 135 snzi.arrive(i); 136 tls.rng2.set_raw_state( tls.rng1.get_raw_state()); 137 #elif VARIANT == SNZM 138 snzm.arrive(i); 139 #elif VARIANT == BITMASK 140 numNonEmpty++; 141 size_t qword = i >> 6ull; 142 size_t bit = i & 63ull; 143 assertf((list_mask[qword] & (1ul << bit)) == 0, "Before set %zu:%zu (%u), %zx & %zx", qword, bit, i, list_mask[qword].load(), (1ul << bit)); 144 __attribute__((unused)) bool ret = bts(list_mask[qword], bit); 145 assert(!ret); 146 assertf((list_mask[qword] & (1ul << bit)) != 0, "After set %zu:%zu (%u), %zx & %zx", qword, bit, i, list_mask[qword].load(), (1ul << bit)); 147 #else 148 numNonEmpty++; 149 #endif 150 } 151 #if VARIANT == VANILLA || VARIANT == BITMASK 152 assert(numNonEmpty <= (int)numLists); 153 #endif 154 154 155 155 // Unlock and return … … 158 158 #ifndef NO_STATS 159 159 tls.pick.push.success++; 160 tls.empty.push.value += num; 161 tls.empty.push.count += 1; 160 #if VARIANT == VANILLA || VARIANT == BITMASK 161 tls.empty.push.value += num; 162 tls.empty.push.count += 1; 163 #endif 162 164 #endif 163 165 return; … … 166 168 167 169 __attribute__((noinline, hot)) node_t * pop() { 168 #if !defined(NO_BITMASK) 169 // for(int r = 0; r < 10 && numNonEmpty != 0; r++) { 170 // // Pick two lists at random 171 // unsigned i = tls.rng.next() % numLists; 172 // unsigned j = tls.rng.next() % numLists; 173 174 // if(auto node = try_pop(i, j)) return node; 175 // } 170 #if VARIANT == DISCOVER 171 assert(numLists <= 64); 172 while(snzm.query()) { 173 tls.pick.pop.mask_attempt++; 174 unsigned i, j; 175 { 176 // Pick first list totally randomly 177 i = tls.rng1.next() % numLists; 178 179 // Pick the other according to the bitmask 180 unsigned r = tls.rng1.next(); 181 182 size_t mask = tls.mask.load(std::memory_order_relaxed); 183 if(mask == 0) { 184 tls.pick.pop.mask_reset++; 185 mask = (1U << numLists) - 1; 186 tls.mask.store(mask, std::memory_order_relaxed); 187 } 188 189 unsigned b = rand_bit(r, mask); 190 191 assertf(b < 64, "%zu %u", mask, b); 192 193 j = b; 194 195 assert(j < numLists); 196 } 197 198 if(auto node = try_pop(i, j)) return node; 199 } 200 #elif VARIANT == SNZI 201 while(snzi.query()) { 202 // Pick two lists at random 203 int i = tls.rng1.next() % numLists; 204 int j = tls.rng1.next() % numLists; 205 206 if(auto node = try_pop(i, j)) return node; 207 } 208 209 #elif VARIANT == BACK 210 while(snzi.query()) { 211 // Pick two lists at random 212 int i = tls.rng2.prev() % numLists; 213 int j = tls.rng2.prev() % numLists; 214 215 if(auto node = try_pop(i, j)) return node; 216 } 217 218 #elif VARIANT == BACKBIAS 219 while(snzi.query()) { 220 // Pick two lists at random 221 int i = idx_from_r(tls.rng2.prev(), true); 222 int j = idx_from_r(tls.rng2.prev(), true); 223 224 if(auto node = try_pop(i, j)) return node; 225 } 226 227 #elif VARIANT == BIAS 228 while(snzi.query()) { 229 // Pick two lists at random 230 unsigned ri = tls.rng1.next(); 231 unsigned i; 232 unsigned j = tls.rng1.next(); 233 if(0 == (ri & 0xF)) { 234 i = (ri >> 4) % numLists; 235 } else { 236 i = tls.my_queue + ((ri >> 4) % 4); 237 j = tls.my_queue + ((j >> 4) % 4); 238 tls.pick.pop.local++; 239 } 240 i %= numLists; 241 j %= numLists; 242 243 if(auto node = try_pop(i, j)) return node; 244 } 245 #elif VARIANT == SNZM 246 //* 247 while(snzm.query()) { 248 tls.pick.pop.mask_attempt++; 249 unsigned i, j; 250 { 251 // Pick two random number 252 unsigned ri = tls.rng1.next(); 253 unsigned rj = tls.rng1.next(); 254 255 // Pick two nodes from it 256 unsigned wdxi = ri & snzm.mask; 257 // unsigned wdxj = rj & snzm.mask; 258 259 // Get the masks from the nodes 260 // size_t maski = snzm.masks(wdxi); 261 size_t maskj = snzm.masks(wdxj); 262 263 if(maski == 0 && maskj == 0) continue; 264 265 #if defined(__BMI2__) 266 uint64_t idxsi = _pext_u64(snzm.indexes, maski); 267 // uint64_t idxsj = _pext_u64(snzm.indexes, maskj); 268 269 auto pi = __builtin_popcountll(maski); 270 // auto pj = __builtin_popcountll(maskj); 271 272 ri = pi ? ri & ((pi >> 3) - 1) : 0; 273 rj = pj ? rj & ((pj >> 3) - 1) : 0; 274 275 unsigned bi = (idxsi >> (ri << 3)) & 0xff; 276 unsigned bj = (idxsj >> (rj << 3)) & 0xff; 277 #else 278 unsigned bi = rand_bit(ri >> snzm.depth, maski); 279 unsigned bj = rand_bit(rj >> snzm.depth, maskj); 280 #endif 281 282 i = (bi << snzm.depth) | wdxi; 283 j = (bj << snzm.depth) | wdxj; 284 285 /* paranoid */ assertf(i < numLists, "%u %u", bj, wdxi); 286 /* paranoid */ assertf(j < numLists, "%u %u", bj, wdxj); 287 } 288 289 if(auto node = try_pop(i, j)) return node; 290 } 291 /*/ 292 while(snzm.query()) { 293 // Pick two lists at random 294 int i = tls.rng1.next() % numLists; 295 int j = tls.rng1.next() % numLists; 296 297 if(auto node = try_pop(i, j)) return node; 298 } 299 //*/ 300 #elif VARIANT == BITMASK 176 301 int nnempty; 177 302 while(0 != (nnempty = numNonEmpty)) { 178 303 tls.pick.pop.mask_attempt++; 179 304 unsigned i, j; 180 // if( numLists < 4 || (numLists / nnempty) < 4 ) {181 // // Pick two lists at random182 // i = tls.rng.next() % numLists;183 // j = tls.rng.next() % numLists;184 // } else185 305 { 186 #ifndef NO_STATS187 // tls.pick.push.mask_attempt++;188 #endif189 190 306 // Pick two lists at random 191 307 unsigned num = ((numLists - 1) >> 6) + 1; 192 308 193 unsigned ri = tls.rng .next();194 unsigned rj = tls.rng .next();309 unsigned ri = tls.rng1.next(); 310 unsigned rj = tls.rng1.next(); 195 311 196 312 unsigned wdxi = (ri >> 6u) % num; … … 220 336 while(numNonEmpty != 0) { 221 337 // Pick two lists at random 222 int i = tls.rng .next() % numLists;223 int j = tls.rng .next() % numLists;338 int i = tls.rng1.next() % numLists; 339 int j = tls.rng1.next() % numLists; 224 340 225 341 if(auto node = try_pop(i, j)) return node; … … 234 350 #ifndef NO_STATS 235 351 tls.pick.pop.attempt++; 352 #endif 353 354 #if VARIANT == DISCOVER 355 if(lists[i].ts() > 0) bts(tls.mask, i); else btr(tls.mask, i); 356 if(lists[j].ts() > 0) bts(tls.mask, j); else btr(tls.mask, j); 236 357 #endif 237 358 … … 249 370 if( !list.lock.try_lock() ) return nullptr; 250 371 251 __attribute__((unused)) int num = numNonEmpty; 372 #if VARIANT == VANILLA || VARIANT == BITMASK 373 __attribute__((unused)) int num = numNonEmpty; 374 #endif 252 375 253 376 // If list is empty, unlock and retry … … 264 387 265 388 if(emptied) { 266 numNonEmpty--; 267 size_t qword = w >> 6ull; 268 size_t bit = w & 63ull; 269 assert((list_mask[qword] & (1ul << bit)) != 0); 270 __attribute__((unused)) bool ret = btr(list_mask[qword], bit); 271 assert(ret); 272 assert((list_mask[qword] & (1ul << bit)) == 0); 389 #if VARIANT == DISCOVER 390 size_t qword = w >> 6ull; 391 size_t bit = w & 63ull; 392 assert(qword == 0); 393 __attribute__((unused)) bool ret = btr(tls.mask, bit); 394 snzm.depart(w); 395 #elif VARIANT == SNZI || VARIANT == BIAS || VARIANT == BACK || VARIANT == BACKBIAS 396 snzi.depart(w); 397 #elif VARIANT == SNZM 398 snzm.depart(w); 399 #elif VARIANT == BITMASK 400 numNonEmpty--; 401 size_t qword = w >> 6ull; 402 size_t bit = w & 63ull; 403 assert((list_mask[qword] & (1ul << bit)) != 0); 404 __attribute__((unused)) bool ret = btr(list_mask[qword], bit); 405 assert(ret); 406 assert((list_mask[qword] & (1ul << bit)) == 0); 407 #else 408 numNonEmpty--; 409 #endif 273 410 } 274 411 275 412 // Unlock and return 276 413 list.lock.unlock(); 277 assert(numNonEmpty >= 0); 414 #if VARIANT == VANILLA || VARIANT == BITMASK 415 assert(numNonEmpty >= 0); 416 #endif 278 417 #ifndef NO_STATS 279 418 tls.pick.pop.success++; 280 tls.empty.pop.value += num; 281 tls.empty.pop.count += 1; 419 #if VARIANT == VANILLA || VARIANT == BITMASK 420 tls.empty.pop.value += num; 421 tls.empty.pop.count += 1; 422 #endif 282 423 #endif 283 424 return node; 284 425 } 285 426 286 private: 287 288 class __attribute__((aligned(128))) intrusive_queue_t { 289 public: 290 typedef spinlock_t lock_t; 291 292 friend class relaxed_list<node_t>; 293 294 struct stat { 295 ssize_t diff = 0; 296 size_t push = 0; 297 size_t pop = 0; 298 // size_t value = 0; 299 // size_t count = 0; 300 }; 301 302 private: 303 struct sentinel_t { 304 _LinksFields_t<node_t> _links; 305 }; 306 307 lock_t lock; 308 sentinel_t before; 309 sentinel_t after; 310 #ifndef NO_STATS 311 stat s; 312 #endif 313 314 #pragma GCC diagnostic push 315 #pragma GCC diagnostic ignored "-Winvalid-offsetof" 316 static constexpr auto fields_offset = offsetof( node_t, _links ); 317 #pragma GCC diagnostic pop 318 public: 319 intrusive_queue_t() 320 : before{{ nullptr, tail() }} 321 , after {{ head(), nullptr }} 322 { 323 /* paranoid */ assert((reinterpret_cast<uintptr_t>( head() ) + fields_offset) == reinterpret_cast<uintptr_t>(&before)); 324 /* paranoid */ assert((reinterpret_cast<uintptr_t>( tail() ) + fields_offset) == reinterpret_cast<uintptr_t>(&after )); 325 /* paranoid */ assert(head()->_links.prev == nullptr); 326 /* paranoid */ assert(head()->_links.next == tail() ); 327 /* paranoid */ assert(tail()->_links.next == nullptr); 328 /* paranoid */ assert(tail()->_links.prev == head() ); 329 /* paranoid */ assert(sizeof(*this) == 128); 330 /* paranoid */ assert((intptr_t(this) % 128) == 0); 427 inline unsigned idx_from_r(unsigned r, bool bias) { 428 unsigned i; 429 if(bias) { 430 if(0 == (r & 0x3F)) { 431 i = r >> 6; 432 } else { 433 i = tls.my_queue + ((r >> 6) % 4); 434 tls.pick.push.local++; 435 } 436 } else { 437 i = r; 331 438 } 332 333 ~intrusive_queue_t() = default; 334 335 inline node_t * head() const { 336 node_t * rhead = reinterpret_cast<node_t *>( 337 reinterpret_cast<uintptr_t>( &before ) - fields_offset 338 ); 339 assert(rhead); 340 return rhead; 341 } 342 343 inline node_t * tail() const { 344 node_t * rtail = reinterpret_cast<node_t *>( 345 reinterpret_cast<uintptr_t>( &after ) - fields_offset 346 ); 347 assert(rtail); 348 return rtail; 349 } 350 351 inline bool push(node_t * node) { 352 assert(lock); 353 assert(node->_links.ts != 0); 354 node_t * tail = this->tail(); 355 356 node_t * prev = tail->_links.prev; 357 // assertf(node->_links.ts >= prev->_links.ts, 358 // "New node has smaller timestamp: %llu < %llu", node->_links.ts, prev->_links.ts); 359 node->_links.next = tail; 360 node->_links.prev = prev; 361 prev->_links.next = node; 362 tail->_links.prev = node; 363 #ifndef NO_STATS 364 if(enable_stats) { 365 s.diff++; 366 s.push++; 367 } 368 #endif 369 if(before._links.ts == 0l) { 370 before._links.ts = node->_links.ts; 371 assert(node->_links.prev == this->head()); 372 return true; 373 } 374 return false; 375 } 376 377 inline std::pair<node_t *, bool> pop() { 378 assert(lock); 379 node_t * head = this->head(); 380 node_t * tail = this->tail(); 381 382 node_t * node = head->_links.next; 383 node_t * next = node->_links.next; 384 if(node == tail) return {nullptr, false}; 385 386 head->_links.next = next; 387 next->_links.prev = head; 388 389 #ifndef NO_STATS 390 if(enable_stats) { 391 s.diff--; 392 s.pop ++; 393 } 394 #endif 395 if(next == tail) { 396 before._links.ts = 0l; 397 return {node, true}; 398 } 399 else { 400 assert(next->_links.ts != 0); 401 before._links.ts = next->_links.ts; 402 assert(before._links.ts != 0); 403 return {node, false}; 404 } 405 } 406 407 long long ts() const { 408 return before._links.ts; 409 } 410 }; 411 439 return i % numLists; 440 } 412 441 413 442 public: 414 443 415 444 static __attribute__((aligned(128))) thread_local struct TLS { 416 Random rng = { int(rdtscl()) }; 445 Random rng1 = { unsigned(std::hash<std::thread::id>{}(std::this_thread::get_id()) ^ rdtscl()) }; 446 Random rng2 = { unsigned(std::hash<std::thread::id>{}(std::this_thread::get_id()) ^ rdtscl()) }; 447 unsigned my_queue = (ticket++) * 4; 417 448 pick_stat pick; 418 449 empty_stat empty; 450 __attribute__((aligned(64))) std::atomic_size_t mask = { 0 }; 419 451 } tls; 420 452 453 private: 454 const unsigned numLists; 455 __attribute__((aligned(64))) std::unique_ptr<intrusive_queue_t<node_t> []> lists; 456 private: 457 #if VARIANT == SNZI || VARIANT == BACK 458 snzi_t snzi; 459 #elif VARIANT == BIAS || VARIANT == BACKBIAS 460 #ifdef SNZI_PACKED 461 snzip_t snzi; 462 #else 463 snzi_t snzi; 464 #endif 465 #elif VARIANT == SNZM || VARIANT == DISCOVER 466 snzm_t snzm; 467 #else 468 std::atomic_int numNonEmpty = { 0 }; // number of non-empty lists 469 #endif 470 #if VARIANT == BITMASK 471 std::atomic_size_t list_mask[7] = { {0}, {0}, {0}, {0}, {0}, {0}, {0} }; // which queues are empty 472 #endif 473 421 474 public: 422 std::atomic_int numNonEmpty = { 0 }; // number of non-empty lists 423 std::atomic_size_t list_mask[7] = { {0}, {0}, {0}, {0}, {0}, {0}, {0} }; // which queues are empty 424 private: 425 __attribute__((aligned(64))) std::unique_ptr<intrusive_queue_t []> lists; 426 const unsigned numLists; 427 428 public: 429 static const constexpr size_t sizeof_queue = sizeof(intrusive_queue_t); 475 static const constexpr size_t sizeof_queue = sizeof(intrusive_queue_t<node_t>); 476 static std::atomic_uint32_t ticket; 430 477 431 478 #ifndef NO_STATS 432 static void stats_print(std::ostream & os) {433 auto it = head;434 while(it) {435 it->stats_print_local(os);436 it = it->next;437 }438 }439 440 479 static void stats_tls_tally() { 441 480 global_stats.pick.push.attempt += tls.pick.push.attempt; 442 481 global_stats.pick.push.success += tls.pick.push.success; 482 global_stats.pick.push.local += tls.pick.push.local; 443 483 global_stats.pick.pop .attempt += tls.pick.pop.attempt; 444 484 global_stats.pick.pop .success += tls.pick.pop.success; 445 485 global_stats.pick.pop .mask_attempt += tls.pick.pop.mask_attempt; 486 global_stats.pick.pop .mask_reset += tls.pick.pop.mask_reset; 487 global_stats.pick.pop .local += tls.pick.pop.local; 446 488 447 489 global_stats.qstat.push.value += tls.empty.push.value; … … 457 499 std::atomic_size_t attempt = { 0 }; 458 500 std::atomic_size_t success = { 0 }; 501 std::atomic_size_t local = { 0 }; 459 502 } push; 460 503 struct { … … 462 505 std::atomic_size_t success = { 0 }; 463 506 std::atomic_size_t mask_attempt = { 0 }; 507 std::atomic_size_t mask_reset = { 0 }; 508 std::atomic_size_t local = { 0 }; 464 509 } pop; 465 510 } pick; … … 476 521 } global_stats; 477 522 478 // Link list of all lists for stats 479 __attribute__((aligned(64))) relaxed_list<node_t> * next = nullptr; 480 481 static relaxed_list<node_t> * head; 482 483 void stats_print_local(std::ostream & os ) { 523 public: 524 static void stats_print(std::ostream & os ) { 484 525 std::cout << "----- Relaxed List Stats -----" << std::endl; 485 {486 ssize_t diff = 0;487 size_t num = 0;488 ssize_t max = 0;489 490 for(size_t i = 0; i < numLists; i++) {491 const auto & list = lists[i];492 diff+= list.s.diff;493 num ++;494 max = std::abs(max) > std::abs(list.s.diff) ? max : list.s.diff;495 os << "Local Q ops : " << (list.s.push + list.s.pop) << "(" << list.s.push << "i, " << list.s.pop << "o)\n";496 }497 498 os << "Difference : " << ssize_t(double(diff) / num ) << " avg\t" << max << "max" << std::endl;499 }500 526 501 527 const auto & global = global_stats; … … 504 530 double pop_sur = (100.0 * double(global.pick.pop .success) / global.pick.pop .attempt); 505 531 double mpop_sur = (100.0 * double(global.pick.pop .success) / global.pick.pop .mask_attempt); 506 507 os << "Push Pick % : " << push_sur << "(" << global.pick.push.success << " / " << global.pick.push.attempt << ")\n"; 508 os << "Pop Pick % : " << pop_sur << "(" << global.pick.pop .success << " / " << global.pick.pop .attempt << ")\n"; 509 os << "TryPop Pick % : " << mpop_sur << "(" << global.pick.pop .success << " / " << global.pick.pop .mask_attempt << ")\n"; 532 double rpop_sur = (100.0 * double(global.pick.pop .success) / global.pick.pop .mask_reset); 533 534 double push_len = double(global.pick.push.attempt ) / global.pick.push.success; 535 double pop_len = double(global.pick.pop .attempt ) / global.pick.pop .success; 536 double mpop_len = double(global.pick.pop .mask_attempt) / global.pick.pop .success; 537 double rpop_len = double(global.pick.pop .mask_reset ) / global.pick.pop .success; 538 539 os << "Push Pick : " << push_sur << " %, len " << push_len << " (" << global.pick.push.attempt << " / " << global.pick.push.success << ")\n"; 540 os << "Pop Pick : " << pop_sur << " %, len " << pop_len << " (" << global.pick.pop .attempt << " / " << global.pick.pop .success << ")\n"; 541 os << "TryPop Pick : " << mpop_sur << " %, len " << mpop_len << " (" << global.pick.pop .mask_attempt << " / " << global.pick.pop .success << ")\n"; 542 os << "Pop M Reset : " << rpop_sur << " %, len " << rpop_len << " (" << global.pick.pop .mask_reset << " / " << global.pick.pop .success << ")\n"; 510 543 511 544 double avgQ_push = double(global.qstat.push.value) / global.qstat.push.count; … … 515 548 os << "Pop Avg Qs : " << avgQ_pop << " (" << global.qstat.pop .count << "ops)\n"; 516 549 os << "Global Avg Qs : " << avgQ << " (" << (global.qstat.push.count + global.qstat.pop .count) << "ops)\n"; 550 551 os << "Local Push : " << global.pick.push.local << "\n"; 552 os << "Local Pop : " << global.pick.pop .local << "\n"; 517 553 } 518 554 #endif -
doc/theses/thierry_delisle_PhD/code/utils.hpp
r07d867b r22f94a4 35 35 }; 36 36 37 // class Random { 38 // private: 39 // unsigned int seed; 40 // public: 41 // Random(int seed) { 42 // this->seed = seed; 43 // } 44 45 // /** returns pseudorandom x satisfying 0 <= x < n. **/ 46 // unsigned int next() { 47 // seed ^= seed << 6; 48 // seed ^= seed >> 21; 49 // seed ^= seed << 7; 50 // return seed; 51 // } 52 // }; 53 54 constexpr uint64_t extendedEuclidY(uint64_t a, uint64_t b); 55 constexpr uint64_t extendedEuclidX(uint64_t a, uint64_t b){ 56 return (b==0) ? 1 : extendedEuclidY(b, a - b * (a / b)); 57 } 58 constexpr uint64_t extendedEuclidY(uint64_t a, uint64_t b){ 59 return (b==0) ? 0 : extendedEuclidX(b, a - b * (a / b)) - (a / b) * extendedEuclidY(b, a - b * (a / b)); 60 } 61 37 62 class Random { 38 63 private: 39 unsigned int seed; 64 uint64_t x; 65 66 static constexpr const uint64_t M = 1ul << 48ul; 67 static constexpr const uint64_t A = 25214903917; 68 static constexpr const uint64_t C = 11; 69 static constexpr const uint64_t D = 16; 70 40 71 public: 41 Random(int seed) { 42 this->seed = seed; 72 static constexpr const uint64_t m = M; 73 static constexpr const uint64_t a = A; 74 static constexpr const uint64_t c = C; 75 static constexpr const uint64_t d = D; 76 static constexpr const uint64_t ai = extendedEuclidX(A, M); 77 public: 78 Random(unsigned int seed) { 79 this->x = seed * a; 43 80 } 44 81 45 82 /** returns pseudorandom x satisfying 0 <= x < n. **/ 46 83 unsigned int next() { 47 seed ^= seed << 6; 48 seed ^= seed >> 21; 49 seed ^= seed << 7; 50 return seed; 51 } 84 //nextx = (a * x + c) % m; 85 x = (A * x + C) & (M - 1); 86 return x >> D; 87 } 88 unsigned int prev() { 89 //prevx = (ainverse * (x - c)) mod m 90 unsigned int r = x >> D; 91 x = ai * (x - C) & (M - 1); 92 return r; 93 } 94 95 void set_raw_state(uint64_t _x) { 96 this->x = _x; 97 } 98 99 uint64_t get_raw_state() { 100 return this->x; 101 } 52 102 }; 53 103 … … 106 156 } 107 157 158 static inline unsigned rand_bit(unsigned rnum, size_t mask) __attribute__((artificial)); 108 159 static inline unsigned rand_bit(unsigned rnum, size_t mask) { 109 160 unsigned bit = mask ? rnum % __builtin_popcountl(mask) : 0; … … 143 194 #endif 144 195 } 196 197 struct spinlock_t { 198 std::atomic_bool ll = { false }; 199 200 inline void lock() { 201 while( __builtin_expect(ll.exchange(true),false) ) { 202 while(ll.load(std::memory_order_relaxed)) 203 asm volatile("pause"); 204 } 205 } 206 207 inline bool try_lock() { 208 return false == ll.exchange(true); 209 } 210 211 inline void unlock() { 212 ll.store(false, std::memory_order_release); 213 } 214 215 inline explicit operator bool() { 216 return ll.load(std::memory_order_relaxed); 217 } 218 }; 219 220 static inline bool bts(std::atomic_size_t & target, size_t bit ) { 221 //* 222 int result = 0; 223 asm volatile( 224 "LOCK btsq %[bit], %[target]\n\t" 225 :"=@ccc" (result) 226 : [target] "m" (target), [bit] "r" (bit) 227 ); 228 return result != 0; 229 /*/ 230 size_t mask = 1ul << bit; 231 size_t ret = target.fetch_or(mask, std::memory_order_relaxed); 232 return (ret & mask) != 0; 233 //*/ 234 } 235 236 static inline bool btr(std::atomic_size_t & target, size_t bit ) { 237 //* 238 int result = 0; 239 asm volatile( 240 "LOCK btrq %[bit], %[target]\n\t" 241 :"=@ccc" (result) 242 : [target] "m" (target), [bit] "r" (bit) 243 ); 244 return result != 0; 245 /*/ 246 size_t mask = 1ul << bit; 247 size_t ret = target.fetch_and(~mask, std::memory_order_relaxed); 248 return (ret & mask) != 0; 249 //*/ 250 } -
driver/cc1.cc
r07d867b r22f94a4 10 10 // Created On : Fri Aug 26 14:23:51 2005 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : S un Oct 20 08:14:33 201913 // Update Count : 38512 // Last Modified On : Sat May 30 18:09:05 2020 13 // Update Count : 404 14 14 // 15 15 … … 38 38 static string o_file; 39 39 static string bprefix; 40 static string lang; // -x flag 40 41 41 42 … … 73 74 if ( prefix( val, "-compiler=" ) ) { 74 75 compiler_path = val.substr( 10 ); 76 } else if ( prefix( val, "-x=" ) ) { 77 lang = val.substr( 3 ); 75 78 } // if 76 79 } // if … … 100 103 } else if ( prefix( val, "-B=" ) ) { // location of cfa-cpp 101 104 bprefix = val.substr( 3 ); 105 } else if ( prefix( val, "-x=" ) ) { // ignore 102 106 } else { // normal flag for cfa-cpp 103 107 args[nargs++] = ( *new string( arg.substr( arg.find_first_of( "=" ) + 1 ) ) ).c_str(); … … 247 251 248 252 args[0] = compiler_path.c_str(); 249 suffix( cpp_in, args, nargs ); // check suffix 253 if ( lang.size() == 0 ) { 254 suffix( cpp_in, args, nargs ); // check suffix 255 } else { 256 args[nargs++] = "-x"; 257 args[nargs++] = ( *new string( lang.c_str() ) ).c_str(); 258 } // if 250 259 args[nargs++] = cpp_in; 251 260 if ( o_flag ) { // location for output … … 280 289 281 290 args[0] = compiler_path.c_str(); 282 suffix( cpp_in, args, nargs ); // check suffix 291 if ( lang.size() == 0 ) { 292 suffix( cpp_in, args, nargs ); // check suffix 293 } else { 294 args[nargs++] = "-x"; 295 args[nargs++] = ( *new string( lang.c_str() ) ).c_str(); 296 } // if 283 297 args[nargs++] = cpp_in; // input to cpp 284 298 args[nargs] = nullptr; // terminate argument list -
driver/cfa.cc
r07d867b r22f94a4 10 10 // Created On : Tue Aug 20 13:44:49 2002 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Jan 31 16:48:03 202013 // Update Count : 4 2112 // Last Modified On : Sat May 30 18:28:23 2020 13 // Update Count : 433 14 14 // 15 15 … … 185 185 args[nargs++] = argv[i]; // pass argument along 186 186 if ( arg == "-o" ) o_file = i; // remember file 187 } else if ( arg == "-XCFA" ) { // CFA pass through 188 i += 1; 189 if ( i == argc ) continue; // next argument available ? 190 Putenv( argv, argv[i] ); 191 192 // CFA specific arguments 187 } else if ( strncmp(arg.c_str(), "-XCFA", 5) == 0 ) { // CFA pass through 188 if(arg.size() == 5) { 189 i += 1; 190 if ( i == argc ) continue; // next argument available ? 191 Putenv( argv, argv[i] ); 192 193 // CFA specific arguments 194 } 195 else if(arg[5] == ',') { 196 Putenv( argv, argv[i] + 6 ); 197 198 // CFA specific arguments 199 } 200 else { 201 args[nargs++] = argv[i]; 202 } 193 203 194 204 } else if ( arg == "-CFA" ) { … … 243 253 lang = arg.substr( 2 ); 244 254 } // if 245 x_flag = lang != "none"; 255 if ( x_flag ) { 256 cerr << argv[0] << " warning, only one -x flag per compile, ignoring subsequent flag." << endl; 257 } else { 258 x_flag = true; 259 Putenv( argv, string( "-x=" ) + lang ); 260 } // if 246 261 } else if ( prefix( arg, "-std=" ) || prefix( arg, "--std=" ) ) { 247 262 std_flag = true; // -std=XX provided … … 302 317 303 318 #ifdef __x86_64__ 304 args[nargs++] = "-mcx16"; // allow double-wide CA A319 args[nargs++] = "-mcx16"; // allow double-wide CAS 305 320 #endif // __x86_64__ 306 321 … … 420 435 args[nargs++] = "-Wl,--pop-state"; 421 436 args[nargs++] = "-pthread"; 437 #ifdef __x86_64__ 438 args[nargs++] = "-latomic"; // allow double-wide CAS 439 #endif // __x86_64__ 422 440 args[nargs++] = "-ldl"; 423 441 args[nargs++] = "-lrt"; -
examples/io/cat.c
r07d867b r22f94a4 1 /* 2 This is a simple "cat" example that uses io_uring in IORING_SETUP_IOPOLL mode. 3 It demonstrates the bare minimum needed to use io_uring in polling mode. 4 It uses liburing for simplicity. 5 */ 6 7 8 #ifndef _GNU_SOURCE 9 #define _GNU_SOURCE 10 #endif 11 1 12 #include <fcntl.h> 2 13 #include <liburing.h> 3 14 #include <stdio.h> 15 #include <string.h> 4 16 #include <unistd.h> 5 17 6 18 struct io_uring ring; 19 20 __attribute__((aligned(1024))) char data[1024]; 7 21 8 22 int main(int argc, char * argv[]) { … … 12 26 } 13 27 14 int fd = open(argv[1], 0);28 int fd = open(argv[1], O_DIRECT); 15 29 if(fd < 0) { 16 30 printf("Could not open file %s.\n", argv[1]); … … 19 33 20 34 /* prep the array */ 21 char data[512]; 22 struct iovec iov = { data, 512 }; 35 struct iovec iov = { data, 1024 }; 23 36 24 37 /* init liburing */ 25 io_uring_queue_init(256, &ring, 0);38 io_uring_queue_init(256, &ring, IORING_SETUP_IOPOLL); 26 39 27 40 /* declare required structs */ … … 32 45 sqe = io_uring_get_sqe(&ring); 33 46 io_uring_prep_readv(sqe, fd, &iov, 1, 0); 47 // io_uring_prep_read(sqe, fd, data, 1024, 0); 34 48 35 sqe->user_data = data;49 sqe->user_data = (uint64_t)(uintptr_t)data; 36 50 37 51 /* tell the kernel we have an sqe ready for consumption */ … … 40 54 /* wait for the sqe to complete */ 41 55 int ret = io_uring_wait_cqe(&ring, &cqe); 42 56 43 57 /* read and process cqe event */ 44 58 if(ret == 0) { 45 char * out = cqe->user_data;59 char * out = (char *)(uintptr_t)cqe->user_data; 46 60 signed int len = cqe->res; 47 61 io_uring_cqe_seen(&ring, cqe); … … 49 63 if(len > 0) { 50 64 printf("%.*s", len, out); 65 } 66 else if( len < 0 ) { 67 fprintf(stderr, "readv/read returned error : %s\n", strerror(-len)); 51 68 } 52 69 } -
examples/io/filereader.c
r07d867b r22f94a4 1 /* 2 This is a file reading example that users io_uring in non-blocking mode. 3 It demonstrates the bare minimum needed to use io_uring. 4 It also optionally pre-registers the file descriptors (and a pipe, just to show it works). 5 It uses liburing for simplicity. 6 */ 7 8 1 9 #include <errno.h> 2 10 #include <fcntl.h> … … 9 17 10 18 int main(int argc, char * argv[]) { 11 if ( argc != 3 ) { 12 printf( "usage\n" ); 13 exit( EXIT_FAILURE ); 14 } 15 16 if(argc != 3) { 17 printf("usage: %s FILE TIMES - read FILE from disk TIMES times\n", argv[0]); 19 if(argc != 3 && argc != 4) { 20 printf("usage: %s FILE TIMES [fixed] - read FILE from disk TIMES times\n", argv[0]); 18 21 return EXIT_FAILURE; 19 22 } 20 23 24 bool fixed = false; 25 if(argc == 4) { 26 fixed = 0 == strcmp(argv[3], "fixed"); 27 } 21 28 22 29 int times = atoi( argv[2] ); … … 32 39 } 33 40 41 int rfd = fd; 42 34 43 /* prep the array */ 35 44 char data[100]; … … 40 49 io_uring_queue_init(256, &ring, 0); 41 50 51 int pipefds[2]; 52 if(fixed) { 53 int ret = pipe(pipefds); 54 if( ret < 0 ) { 55 printf("Pipe Error : %s\n", strerror( errno )); 56 return EXIT_FAILURE; 57 } 58 rfd = 0; 59 int fds[] = { 60 fd, pipefds[0], pipefds[1] 61 }; 62 int cnt = sizeof(fds) / sizeof(fds[0]); 63 printf("Registering %d files as fixed\n", cnt); 64 ret = io_uring_register_files(&ring, fds, cnt); 65 if( ret < 0 ) { 66 printf("Register Error : %s\n", strerror( -ret )); 67 return EXIT_FAILURE; 68 } 69 } 70 42 71 /* declare required structs */ 43 72 printf("Reading %s(%d) %d times\n", argv[1], fd, times); … … 46 75 /* get an sqe and fill in a READV operation */ 47 76 struct io_uring_sqe * sqe = io_uring_get_sqe(&ring); 48 io_uring_prep_readv(sqe, fd, &iov, 1, 0); 77 io_uring_prep_readv(sqe, rfd, &iov, 1, 0); 78 if(fixed) { 79 sqe->flags = IOSQE_FIXED_FILE; 80 } 49 81 50 82 /* tell the kernel we have an sqe ready for consumption */ … … 83 115 84 116 close(fd); 117 118 if(fixed) { 119 close(pipefds[0]); 120 close(pipefds[1]); 121 } 85 122 } -
examples/io/simple/server.c
r07d867b r22f94a4 1 /* 2 This is a simple server that users io_uring in blocking mode. 3 It demonstrates the bare minimum needed to use io_uring. 4 It uses liburing for simplicity. 5 */ 6 7 1 8 #include <assert.h> 2 9 #include <stdio.h> … … 16 23 char data[256]; 17 24 struct iovec iov = { data, 256 }; 18 struct msghdr msg = { "", 0, &iov, 1, NULL, 0, 0 };25 struct msghdr msg = { (void *)"", 0, &iov, 1, NULL, 0, 0 }; 19 26 static void async_read(int sock) { 20 27 /* get an sqe and fill in a READ operation */ -
libcfa/configure.ac
r07d867b r22f94a4 8 8 AM_SILENT_RULES([yes]) 9 9 10 m4_include([../ automake/cfa.m4])10 m4_include([../tools/build/cfa.m4]) 11 11 12 12 AM_INIT_AUTOMAKE([subdir-objects]) … … 30 30 [ --enable-distcc whether or not to enable distributed compilation], 31 31 enable_distcc=$enableval, enable_distcc=no) 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) 32 36 33 37 echo -n "checking for distributated build... " … … 55 59 AC_SUBST(CFADIR_HASH) 56 60 AC_SUBST(CFA_VERSION) 61 AC_SUBST(DIST_BWLIMIT) 57 62 58 63 #============================================================================== … … 100 105 AM_CONDITIONAL([BUILDLIB], [test "x${CONFIG_BUILDLIB}" = "xyes"]) 101 106 107 AM_T='$(T)' 108 AC_SUBST(AM_T) 109 102 110 #============================================================================== 103 111 #Trasforming cc1 will break compilation … … 118 126 AC_PROG_MAKE_SET 119 127 120 AC_CHECK_HEADERS([linux/io_uring.h]) 128 129 130 #io_uring 5.4 and earlier uses defines 131 #io_uring 5.5 uses enum values 132 #io_uring 5.6 and later uses probes 133 134 AH_TEMPLATE([CFA_HAVE_LINUX_IO_URING_H],[Defined if io_uring support is present when compiling libcfathread.]) 135 AH_TEMPLATE([CFA_HAVE_IORING_OP_NOP],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_NOP.]) 136 AH_TEMPLATE([CFA_HAVE_IORING_OP_READV],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_READV.]) 137 AH_TEMPLATE([CFA_HAVE_IORING_OP_WRITEV],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_WRITEV.]) 138 AH_TEMPLATE([CFA_HAVE_IORING_OP_FSYNC],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_FSYNC.]) 139 AH_TEMPLATE([CFA_HAVE_IORING_OP_READ_FIXED],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_READ_FIXED.]) 140 AH_TEMPLATE([CFA_HAVE_IORING_OP_WRITE_FIXED],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_WRITE_FIXED.]) 141 AH_TEMPLATE([CFA_HAVE_IORING_OP_POLL_ADD],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_POLL_ADD.]) 142 AH_TEMPLATE([CFA_HAVE_IORING_OP_POLL_REMOVE],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_POLL_REMOVE.]) 143 AH_TEMPLATE([CFA_HAVE_IORING_OP_SYNC_FILE_RANGE],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_SYNC_FILE_RANGE.]) 144 AH_TEMPLATE([CFA_HAVE_IORING_OP_SENDMSG],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_SENDMSG.]) 145 AH_TEMPLATE([CFA_HAVE_IORING_OP_RECVMSG],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_RECVMSG.]) 146 AH_TEMPLATE([CFA_HAVE_IORING_OP_TIMEOUT],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_TIMEOUT.]) 147 AH_TEMPLATE([CFA_HAVE_IORING_OP_TIMEOUT_REMOVE],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_TIMEOUT_REMOVE.]) 148 AH_TEMPLATE([CFA_HAVE_IORING_OP_ACCEPT],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_ACCEPT.]) 149 AH_TEMPLATE([CFA_HAVE_IORING_OP_ASYNC_CANCEL],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_ASYNC_CANCEL.]) 150 AH_TEMPLATE([CFA_HAVE_IORING_OP_LINK_TIMEOUT],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_LINK_TIMEOUT.]) 151 AH_TEMPLATE([CFA_HAVE_IORING_OP_CONNECT],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_CONNECT.]) 152 AH_TEMPLATE([CFA_HAVE_IORING_OP_FALLOCATE],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_FALLOCATE.]) 153 AH_TEMPLATE([CFA_HAVE_IORING_OP_OPENAT],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_OPENAT.]) 154 AH_TEMPLATE([CFA_HAVE_IORING_OP_CLOSE],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_CLOSE.]) 155 AH_TEMPLATE([CFA_HAVE_IORING_OP_FILES_UPDATE],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_FILES_UPDATE.]) 156 AH_TEMPLATE([CFA_HAVE_IORING_OP_STATX],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_STATX.]) 157 AH_TEMPLATE([CFA_HAVE_IORING_OP_READ],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_READ.]) 158 AH_TEMPLATE([CFA_HAVE_IORING_OP_WRITE],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_WRITE.]) 159 AH_TEMPLATE([CFA_HAVE_IORING_OP_FADVISE],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_FADVISE.]) 160 AH_TEMPLATE([CFA_HAVE_IORING_OP_MADVISE],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_MADVISE.]) 161 AH_TEMPLATE([CFA_HAVE_IORING_OP_SEND],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_SEND.]) 162 AH_TEMPLATE([CFA_HAVE_IORING_OP_RECV],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_RECV.]) 163 AH_TEMPLATE([CFA_HAVE_IORING_OP_OPENAT2],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_OPENAT2.]) 164 AH_TEMPLATE([CFA_HAVE_IORING_OP_EPOLL_CTL],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_EPOLL_CTL.]) 165 AH_TEMPLATE([CFA_HAVE_IORING_OP_SPLICE],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_SPLICE.]) 166 AH_TEMPLATE([CFA_HAVE_IORING_OP_PROVIDE_BUFFERS],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_PROVIDE_BUFFERS.]) 167 AH_TEMPLATE([CFA_HAVE_IORING_OP_REMOVE_BUFFER],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_REMOVE_BUFFER.]) 168 AH_TEMPLATE([CFA_HAVE_IOSQE_FIXED_FILE],[Defined if io_uring support is present when compiling libcfathread and supports the flag FIXED_FILE.]) 169 AH_TEMPLATE([CFA_HAVE_IOSQE_IO_DRAIN],[Defined if io_uring support is present when compiling libcfathread and supports the flag IO_DRAIN.]) 170 AH_TEMPLATE([CFA_HAVE_IOSQE_ASYNC],[Defined if io_uring support is present when compiling libcfathread and supports the flag ASYNC.]) 171 AH_TEMPLATE([CFA_HAVE_IOSQE_IO_LINK],[Defined if io_uring support is present when compiling libcfathread and supports the flag IO_LINK.]) 172 AH_TEMPLATE([CFA_HAVE_IOSQE_IO_HARDLINK],[Defined if io_uring support is present when compiling libcfathread and supports the flag IO_HARDLINK.]) 173 AH_TEMPLATE([CFA_HAVE_SPLICE_F_FD_IN_FIXED],[Defined if io_uring support is present when compiling libcfathread and supports the flag SPLICE_F_FD_IN_FIXED.]) 174 AH_TEMPLATE([CFA_HAVE_IORING_SETUP_ATTACH_WQ],[Defined if io_uring support is present when compiling libcfathread and supports the flag IORING_SETUP_ATTACH_WQ.]) 175 AH_TEMPLATE([HAVE_PREADV2],[Defined if preadv2 support is present when compiling libcfathread.]) 176 AH_TEMPLATE([HAVE_PWRITEV2],[Defined if pwritev2 support is present when compiling libcfathread.]) 177 AH_TEMPLATE([__CFA_NO_STATISTICS__],[Defined if libcfathread was compiled without support for statistics.]) 178 179 define(ioring_ops, [IORING_OP_NOP,IORING_OP_READV,IORING_OP_WRITEV,IORING_OP_FSYNC,IORING_OP_READ_FIXED,IORING_OP_WRITE_FIXED,IORING_OP_POLL_ADD,IORING_OP_POLL_REMOVE,IORING_OP_SYNC_FILE_RANGE,IORING_OP_SENDMSG,IORING_OP_RECVMSG,IORING_OP_TIMEOUT,IORING_OP_TIMEOUT_REMOVE,IORING_OP_ACCEPT,IORING_OP_ASYNC_CANCEL,IORING_OP_LINK_TIMEOUT,IORING_OP_CONNECT,IORING_OP_FALLOCATE,IORING_OP_OPENAT,IORING_OP_CLOSE,IORING_OP_FILES_UPDATE,IORING_OP_STATX,IORING_OP_READ,IORING_OP_WRITE,IORING_OP_FADVISE,IORING_OP_MADVISE,IORING_OP_SEND,IORING_OP_RECV,IORING_OP_OPENAT2,IORING_OP_EPOLL_CTL,IORING_OP_SPLICE,IORING_OP_PROVIDE_BUFFERS,IORING_OP_REMOVE_BUFFER]) 180 define(ioring_flags, [IOSQE_FIXED_FILE,IOSQE_IO_DRAIN,IOSQE_ASYNC,IOSQE_IO_LINK,IOSQE_IO_HARDLINK,SPLICE_F_FD_IN_FIXED,IORING_SETUP_ATTACH_WQ]) 181 182 define(ioring_from_decls, [ 183 m4_foreach([op], [ioring_ops], [ 184 AC_CHECK_DECL(op, [AC_DEFINE([CFA_HAVE_]op)], [], [[#include <linux/io_uring.h>]]) 185 ]) 186 ]) 187 188 AC_CHECK_HEADERS([linux/io_uring.h], [ 189 AC_DEFINE(CFA_HAVE_LINUX_IO_URING_H) 190 AC_CHECK_HEADER([liburing.h], [ 191 AC_CHECK_LIB([uring], [io_uring_get_probe], [ 192 m4_foreach([op], [ioring_ops], [ 193 AC_CHECK_DECL(op, [ 194 AC_RUN_IFELSE([ 195 AC_LANG_PROGRAM( 196 [[#include <liburing.h>]], 197 [[int main() {]] 198 [[ struct io_uring_probe *probe = io_uring_get_probe();]] 199 [[ if(io_uring_opcode_supported(probe, ]]op[[))]] 200 [[ return 0;]] 201 [[ else]] 202 [[ return 1;]] 203 [[}]] 204 ) 205 ],[ 206 AC_DEFINE([CFA_HAVE_]op) 207 ],[ 208 AC_MSG_FAILURE([Check support for] op [ with liburing failed]) 209 ]) 210 ], [], [[#include <linux/io_uring.h>]]) 211 ]) 212 ], [ 213 ioring_from_decls 214 ]) 215 ], [ 216 ioring_from_decls 217 ]) 218 219 # check support for various io_uring flags 220 m4_foreach([op], [ioring_flags], [ 221 AC_CHECK_DECL(op, [AC_DEFINE([CFA_HAVE_]op)], [], [[#include <linux/io_uring.h>]]) 222 ]) 223 ]) 121 224 AC_CHECK_FUNCS([preadv2 pwritev2]) 122 225 -
libcfa/prelude/Makefile.am
r07d867b r22f94a4 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/builtins.c
r07d867b r22f94a4 10 10 // Created On : Fri Jul 21 16:21:03 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Nov 21 16:31:39 201913 // Update Count : 10 112 // Last Modified On : Mon Jul 13 21:10:02 2020 13 // Update Count : 109 14 14 // 15 15 … … 95 95 static inline forall( dtype DT ) DT * intptr( uintptr_t addr ) { return (DT *)addr; } 96 96 97 #if defined(__SIZEOF_INT128__) 98 // constructor for 128-bit numbers (all constants are unsigned as +/- are operators) 99 static inline void ?{}( unsigned int128 & this, unsigned long int h, unsigned long int l ) { 100 this = (unsigned int128)h << 64 | (unsigned int128)l; 101 } // ?{} 102 #endif // __SIZEOF_INT128__ 103 97 104 // exponentiation operator implementation 98 105 -
libcfa/prelude/defines.hfa.in
r07d867b r22f94a4 1 // 2 // Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo 3 // 4 // The contents of this file are covered under the licence agreement in the 5 // file "LICENCE" distributed with Cforall. 6 // 7 // defines.hfa.in -- 8 // 9 // Author : Thierry Delisle 10 // Created On : Thu Apr 30 15:23:00 2020 11 // Last Modified By : 12 // Last Modified On : 13 // Update Count : 14 // 15 1 /* prelude/defines.hfa.in. Generated from configure.ac by autoheader. */ 2 3 /* Location of cfa command. */ 4 #undef CFA_BINDIR 5 6 /* Defined if io_uring support is present when compiling libcfathread and 7 supports the operation IORING_OP_ACCEPT. */ 8 #undef CFA_HAVE_IORING_OP_ACCEPT 9 10 /* Defined if io_uring support is present when compiling libcfathread and 11 supports the operation IORING_OP_ASYNC_CANCEL. */ 12 #undef CFA_HAVE_IORING_OP_ASYNC_CANCEL 13 14 /* Defined if io_uring support is present when compiling libcfathread and 15 supports the operation IORING_OP_CLOSE. */ 16 #undef CFA_HAVE_IORING_OP_CLOSE 17 18 /* Defined if io_uring support is present when compiling libcfathread and 19 supports the operation IORING_OP_CONNECT. */ 20 #undef CFA_HAVE_IORING_OP_CONNECT 21 22 /* Defined if io_uring support is present when compiling libcfathread and 23 supports the operation IORING_OP_EPOLL_CTL. */ 24 #undef CFA_HAVE_IORING_OP_EPOLL_CTL 25 26 /* Defined if io_uring support is present when compiling libcfathread and 27 supports the operation IORING_OP_FADVISE. */ 28 #undef CFA_HAVE_IORING_OP_FADVISE 29 30 /* Defined if io_uring support is present when compiling libcfathread and 31 supports the operation IORING_OP_FALLOCATE. */ 32 #undef CFA_HAVE_IORING_OP_FALLOCATE 33 34 /* Defined if io_uring support is present when compiling libcfathread and 35 supports the operation IORING_OP_FILES_UPDATE. */ 36 #undef CFA_HAVE_IORING_OP_FILES_UPDATE 37 38 /* Defined if io_uring support is present when compiling libcfathread and 39 supports the operation IORING_OP_FSYNC. */ 40 #undef CFA_HAVE_IORING_OP_FSYNC 41 42 /* Defined if io_uring support is present when compiling libcfathread and 43 supports the operation IORING_OP_LINK_TIMEOUT. */ 44 #undef CFA_HAVE_IORING_OP_LINK_TIMEOUT 45 46 /* Defined if io_uring support is present when compiling libcfathread and 47 supports the operation IORING_OP_MADVISE. */ 48 #undef CFA_HAVE_IORING_OP_MADVISE 49 50 /* Defined if io_uring support is present when compiling libcfathread and 51 supports the operation IORING_OP_NOP. */ 52 #undef CFA_HAVE_IORING_OP_NOP 53 54 /* Defined if io_uring support is present when compiling libcfathread and 55 supports the operation IORING_OP_OPENAT. */ 56 #undef CFA_HAVE_IORING_OP_OPENAT 57 58 /* Defined if io_uring support is present when compiling libcfathread and 59 supports the operation IORING_OP_OPENAT2. */ 60 #undef CFA_HAVE_IORING_OP_OPENAT2 61 62 /* Defined if io_uring support is present when compiling libcfathread and 63 supports the operation IORING_OP_POLL_ADD. */ 64 #undef CFA_HAVE_IORING_OP_POLL_ADD 65 66 /* Defined if io_uring support is present when compiling libcfathread and 67 supports the operation IORING_OP_POLL_REMOVE. */ 68 #undef CFA_HAVE_IORING_OP_POLL_REMOVE 69 70 /* Defined if io_uring support is present when compiling libcfathread and 71 supports the operation IORING_OP_PROVIDE_BUFFERS. */ 72 #undef CFA_HAVE_IORING_OP_PROVIDE_BUFFERS 73 74 /* Defined if io_uring support is present when compiling libcfathread and 75 supports the operation IORING_OP_READ. */ 76 #undef CFA_HAVE_IORING_OP_READ 77 78 /* Defined if io_uring support is present when compiling libcfathread and 79 supports the operation IORING_OP_READV. */ 80 #undef CFA_HAVE_IORING_OP_READV 81 82 /* Defined if io_uring support is present when compiling libcfathread and 83 supports the operation IORING_OP_READ_FIXED. */ 84 #undef CFA_HAVE_IORING_OP_READ_FIXED 85 86 /* Defined if io_uring support is present when compiling libcfathread and 87 supports the operation IORING_OP_RECV. */ 88 #undef CFA_HAVE_IORING_OP_RECV 89 90 /* Defined if io_uring support is present when compiling libcfathread and 91 supports the operation IORING_OP_RECVMSG. */ 92 #undef CFA_HAVE_IORING_OP_RECVMSG 93 94 /* Defined if io_uring support is present when compiling libcfathread and 95 supports the operation IORING_OP_REMOVE_BUFFER. */ 96 #undef CFA_HAVE_IORING_OP_REMOVE_BUFFER 97 98 /* Defined if io_uring support is present when compiling libcfathread and 99 supports the operation IORING_OP_SEND. */ 100 #undef CFA_HAVE_IORING_OP_SEND 101 102 /* Defined if io_uring support is present when compiling libcfathread and 103 supports the operation IORING_OP_SENDMSG. */ 104 #undef CFA_HAVE_IORING_OP_SENDMSG 105 106 /* Defined if io_uring support is present when compiling libcfathread and 107 supports the operation IORING_OP_SPLICE. */ 108 #undef CFA_HAVE_IORING_OP_SPLICE 109 110 /* Defined if io_uring support is present when compiling libcfathread and 111 supports the operation IORING_OP_STATX. */ 112 #undef CFA_HAVE_IORING_OP_STATX 113 114 /* Defined if io_uring support is present when compiling libcfathread and 115 supports the operation IORING_OP_SYNC_FILE_RANGE. */ 116 #undef CFA_HAVE_IORING_OP_SYNC_FILE_RANGE 117 118 /* Defined if io_uring support is present when compiling libcfathread and 119 supports the operation IORING_OP_TIMEOUT. */ 120 #undef CFA_HAVE_IORING_OP_TIMEOUT 121 122 /* Defined if io_uring support is present when compiling libcfathread and 123 supports the operation IORING_OP_TIMEOUT_REMOVE. */ 124 #undef CFA_HAVE_IORING_OP_TIMEOUT_REMOVE 125 126 /* Defined if io_uring support is present when compiling libcfathread and 127 supports the operation IORING_OP_WRITE. */ 128 #undef CFA_HAVE_IORING_OP_WRITE 129 130 /* Defined if io_uring support is present when compiling libcfathread and 131 supports the operation IORING_OP_WRITEV. */ 132 #undef CFA_HAVE_IORING_OP_WRITEV 133 134 /* Defined if io_uring support is present when compiling libcfathread and 135 supports the operation IORING_OP_WRITE_FIXED. */ 136 #undef CFA_HAVE_IORING_OP_WRITE_FIXED 137 138 /* Defined if io_uring support is present when compiling libcfathread and 139 supports the flag IORING_SETUP_ATTACH_WQ. */ 140 #undef CFA_HAVE_IORING_SETUP_ATTACH_WQ 141 142 /* Defined if io_uring support is present when compiling libcfathread and 143 supports the flag ASYNC. */ 144 #undef CFA_HAVE_IOSQE_ASYNC 145 146 /* Defined if io_uring support is present when compiling libcfathread and 147 supports the flag FIXED_FILE. */ 148 #undef CFA_HAVE_IOSQE_FIXED_FILE 149 150 /* Defined if io_uring support is present when compiling libcfathread and 151 supports the flag IO_DRAIN. */ 152 #undef CFA_HAVE_IOSQE_IO_DRAIN 153 154 /* Defined if io_uring support is present when compiling libcfathread and 155 supports the flag IO_HARDLINK. */ 156 #undef CFA_HAVE_IOSQE_IO_HARDLINK 157 158 /* Defined if io_uring support is present when compiling libcfathread and 159 supports the flag IO_LINK. */ 160 #undef CFA_HAVE_IOSQE_IO_LINK 161 162 /* Defined if io_uring support is present when compiling libcfathread. */ 163 #undef CFA_HAVE_LINUX_IO_URING_H 164 165 /* Defined if io_uring support is present when compiling libcfathread and 166 supports the flag SPLICE_F_FD_IN_FIXED. */ 167 #undef CFA_HAVE_SPLICE_F_FD_IN_FIXED 168 169 /* Location of include files. */ 170 #undef CFA_INCDIR 171 172 /* Location of cc1 and cfa-cpp commands. */ 173 #undef CFA_LIBDIR 174 175 /* Location of cfa install. */ 176 #undef CFA_PREFIX 177 178 /* Define to 1 if you have the <dlfcn.h> header file. */ 179 #undef HAVE_DLFCN_H 180 181 /* Define to 1 if you have the <inttypes.h> header file. */ 182 #undef HAVE_INTTYPES_H 183 184 /* Define to 1 if you have the <linux/io_uring.h> header file. */ 16 185 #undef HAVE_LINUX_IO_URING_H 17 186 187 /* Define to 1 if you have the <memory.h> header file. */ 188 #undef HAVE_MEMORY_H 189 190 /* Define to 1 if you have the `preadv2' function. */ 18 191 #undef HAVE_PREADV2 192 193 /* Define to 1 if you have the `pwritev2' function. */ 19 194 #undef HAVE_PWRITEV2 20 195 196 /* Define to 1 if you have the <stdint.h> header file. */ 197 #undef HAVE_STDINT_H 198 199 /* Define to 1 if you have the <stdlib.h> header file. */ 200 #undef HAVE_STDLIB_H 201 202 /* Define to 1 if you have the <strings.h> header file. */ 203 #undef HAVE_STRINGS_H 204 205 /* Define to 1 if you have the <string.h> header file. */ 206 #undef HAVE_STRING_H 207 208 /* Define to 1 if you have the <sys/stat.h> header file. */ 209 #undef HAVE_SYS_STAT_H 210 211 /* Define to 1 if you have the <sys/types.h> header file. */ 212 #undef HAVE_SYS_TYPES_H 213 214 /* Define to 1 if you have the <unistd.h> header file. */ 215 #undef HAVE_UNISTD_H 216 217 /* Define to the sub-directory where libtool stores uninstalled libraries. */ 218 #undef LT_OBJDIR 219 220 /* Name of package */ 221 #undef PACKAGE 222 223 /* Define to the address where bug reports for this package should be sent. */ 224 #undef PACKAGE_BUGREPORT 225 226 /* Define to the full name of this package. */ 227 #undef PACKAGE_NAME 228 229 /* Define to the full name and version of this package. */ 230 #undef PACKAGE_STRING 231 232 /* Define to the one symbol short name of this package. */ 233 #undef PACKAGE_TARNAME 234 235 /* Define to the home page for this package. */ 236 #undef PACKAGE_URL 237 238 /* Define to the version of this package. */ 239 #undef PACKAGE_VERSION 240 241 /* Define to 1 if you have the ANSI C header files. */ 242 #undef STDC_HEADERS 243 244 /* Version number of package */ 245 #undef VERSION 246 247 /* Defined if libcfathread was compiled without support for statistics. */ 21 248 #undef __CFA_NO_STATISTICS__ -
libcfa/src/Makefile.am
r07d867b r22f94a4 11 11 ## Created On : Sun May 31 08:54:01 2015 12 12 ## Last Modified By : Peter A. Buhr 13 ## Last Modified On : Mon Mar 16 18:07:59202014 ## Update Count : 24 213 ## Last Modified On : Mon Jun 1 13:35:33 2020 14 ## Update Count : 248 15 15 ############################################################################### 16 16 … … 19 19 ACLOCAL_AMFLAGS = -I automake 20 20 21 include $( srcdir)/../../src/cfa.make21 include $(top_srcdir)/../tools/build/cfa.make 22 22 23 23 libdir = ${CFA_LIBDIR} … … 39 39 #---------------------------------------------------------------------------------------------------------------- 40 40 if BUILDLIB 41 headers_nosrc = bitmanip.hfa math.hfa gmp.hfa time_t.hfa bits/align.hfa bits/containers.hfa bits/defs.hfa bits/debug.hfa bits/locks.hfa containers/list.hfa42 headers = fstream.hfa iostream.hfa iterator.hfa limits.hfa rational.hfa time.hfa stdlib.hfa common.hfa \43 containers/maybe.hfa containers/pair.hfa containers/result.hfa containers/vector.hfa41 headers_nosrc = bitmanip.hfa exception.hfa math.hfa gmp.hfa time_t.hfa clock.hfa \ 42 bits/align.hfa bits/containers.hfa bits/defs.hfa bits/debug.hfa bits/locks.hfa \ 43 containers/list.hfa containers/stackLockFree.hfa concurrency/iofwd.hfa 44 44 45 libsrc = startup.cfa interpose.cfa bits/debug.cfa assert.cfa exception.c virtual.c heap.cfa ${headers:.hfa=.cfa} 45 headers = common.hfa fstream.hfa heap.hfa iostream.hfa iterator.hfa limits.hfa rational.hfa \ 46 time.hfa stdlib.hfa memory.hfa parseargs.hfa \ 47 containers/maybe.hfa containers/pair.hfa containers/result.hfa containers/vector.hfa 48 49 libsrc = startup.cfa interpose.cfa bits/debug.cfa assert.cfa exception.c virtual.c ${headers:.hfa=.cfa} 46 50 47 51 # not all platforms support concurrency, add option do disable it 48 thread_headers_nosrc = concurrency/invoke.h 49 thread_headers = concurrency/coroutine.hfa concurrency/thread.hfa concurrency/kernel.hfa concurrency/monitor.hfa concurrency/mutex.hfa 50 thread_libsrc = concurrency/CtxSwitch-@ARCHITECTURE@.S concurrency/alarm.cfa concurrency/invoke.c concurrency/io.cfa concurrency/preemption.cfa ${thread_headers:.hfa=.cfa} 52 thread_headers_nosrc = bits/random.hfa concurrency/invoke.h concurrency/kernel/fwd.hfa 53 54 thread_headers = concurrency/coroutine.hfa concurrency/thread.hfa concurrency/kernel.hfa \ 55 concurrency/monitor.hfa concurrency/mutex.hfa 56 57 thread_libsrc = concurrency/CtxSwitch-@ARCHITECTURE@.S concurrency/alarm.cfa \ 58 concurrency/invoke.c concurrency/io.cfa concurrency/iocall.cfa \ 59 concurrency/io/setup.cfa \ 60 concurrency/kernel/startup.cfa concurrency/preemption.cfa \ 61 concurrency/ready_queue.cfa concurrency/stats.cfa \ 62 ${thread_headers:.hfa=.cfa} 51 63 else 52 64 headers = … … 96 108 97 109 prelude.o : prelude.cfa extras.cf gcc-builtins.cf builtins.cf @LOCAL_CFACC@ @CFACPP@ 98 ${AM_V_GEN}$(CFACOMPILE) -quiet -XCFA -l ${<} -c -o ${@}110 ${AM_V_GEN}$(CFACOMPILE) -quiet -XCFA,-l ${<} -c -o ${@} 99 111 100 112 prelude.lo: prelude.cfa extras.cf gcc-builtins.cf builtins.cf @LOCAL_CFACC@ @CFACPP@ 101 113 ${AM_V_GEN}$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile \ 102 $(CFACOMPILE) -quiet -XCFA -l ${<} -c -o ${@}114 $(CFACOMPILE) -quiet -XCFA,-l ${<} -c -o ${@} 103 115 104 116 #---------------------------------------------------------------------------------------------------------------- -
libcfa/src/bitmanip.hfa
r07d867b r22f94a4 11 11 // Created On : Sat Mar 14 18:12:27 2020 12 12 // Last Modified By : Peter A. Buhr 13 // Last Modified On : Sun Apr 19 22:29:58202014 // Update Count : 1 2113 // Last Modified On : Mon Aug 10 09:21:02 2020 14 // Update Count : 139 15 15 // 16 16 … … 21 21 // Bits are numbered 1-N. 22 22 23 //#include <assert.h>23 #include <assert.h> 24 24 25 25 #define __bitsizeof( n ) (sizeof(n) * __CHAR_BIT__) … … 48 48 49 49 // Count all 0 bits. 50 unsigned int all0s( unsigned char n ) { return __b itsizeof(n) - __builtin_popcount(n ); }51 unsigned int all0s( unsigned short int n ) { return __b itsizeof(n) - __builtin_popcount(n ); }52 unsigned int all0s( unsigned int n ) { return __b itsizeof(n) - __builtin_popcount(n ); }53 unsigned int all0s( unsigned long int n ) { return __b itsizeof(n) - __builtin_popcountl(n ); }54 unsigned int all0s( unsigned long long int n ) { return __b itsizeof(n) - __builtin_popcountll(n ); }50 unsigned int all0s( unsigned char n ) { return __builtin_popcount( (typeof(n))~n ); } 51 unsigned int all0s( unsigned short int n ) { return __builtin_popcount( (typeof(n))~n ); } 52 unsigned int all0s( unsigned int n ) { return __builtin_popcount( ~n ); } 53 unsigned int all0s( unsigned long int n ) { return __builtin_popcountl( ~n ); } 54 unsigned int all0s( unsigned long long int n ) { return __builtin_popcountll( ~n ); } 55 55 56 56 // Find least significiant zero bit. (ffs) … … 89 89 90 90 // Returns n aligned at the floor of align, clear bits above or equal to align, giving n % align. 91 signed char floor2( signed char n, char align ) { /*assert( is_pow2( align ) );*/return n & -align; }92 unsigned char floor2( unsigned char n, unsigned char align ) { /*assert( is_pow2( align ) );*/return n & -align; }93 short int floor2( short int n, short int align ) { /*assert( is_pow2( align ) );*/return n & -align; }94 unsigned short int floor2( unsigned short int n, unsigned short int align ) { /*assert( is_pow2( align ) );*/return n & -align; }95 int floor2( int n, int align ) { /*assert( is_pow2( align ) );*/return n & -align; }96 unsigned int floor2( unsigned int n, unsigned int align ) { /*assert( is_pow2( align ) );*/return n & -align; }97 long int floor2( long int n, long int align ) { /*assert( is_pow2( align ) );*/return n & -align; }98 unsigned long int floor2( unsigned long int n, unsigned long int align ) { /*assert( is_pow2( align ) );*/return n & -align; }99 long long int floor2( long long int n, long long int align ) { /*assert( is_pow2( align ) );*/return n & -align; }100 unsigned long long int floor2( unsigned long long int n, unsigned long long int align ) { /*assert( is_pow2( align ) );*/return n & -align; }91 signed char floor2( signed char n, signed char align ) { verify( is_pow2( align ) ); return n & -align; } 92 unsigned char floor2( unsigned char n, unsigned char align ) { verify( is_pow2( align ) ); return n & -align; } 93 short int floor2( short int n, short int align ) { verify( is_pow2( align ) ); return n & -align; } 94 unsigned short int floor2( unsigned short int n, unsigned short int align ) { verify( is_pow2( align ) ); return n & -align; } 95 int floor2( int n, int align ) { verify( is_pow2( align ) ); return n & -align; } 96 unsigned int floor2( unsigned int n, unsigned int align ) { verify( is_pow2( align ) ); return n & -align; } 97 long int floor2( long int n, long int align ) { verify( is_pow2( align ) ); return n & -align; } 98 unsigned long int floor2( unsigned long int n, unsigned long int align ) { verify( is_pow2( align ) ); return n & -align; } 99 long long int floor2( long long int n, long long int align ) { verify( is_pow2( align ) ); return n & -align; } 100 unsigned long long int floor2( unsigned long long int n, unsigned long long int align ) { verify( is_pow2( align ) ); return n & -align; } 101 101 102 102 // forall( otype T | { T ?&?( T, T ); T -?( T ); } ) 103 // T floor2( T n, T align ) { /* assert( is_pow2( align ) ); */return n & -align; }103 // T floor2( T n, T align ) { verify( is_pow2( align ) ); return n & -align; } 104 104 105 signed char floor( signed char n, char align ) { return n / align * align; }105 signed char floor( signed char n, signed char align ) { return n / align * align; } 106 106 unsigned char floor( unsigned char n, unsigned char align ) { return n / align * align; } 107 107 short int floor( short int n, short int align ) { return n / align * align; } … … 118 118 119 119 // Returns n aligned at the ceiling of align, negate, round down, negate is the same as round up. 120 signed char ceiling2( signed char n, char align ) { /*assert( is_pow2( align ) );*/return -floor2( -n, align ); }121 unsigned char ceiling2( unsigned char n, unsigned char align ) { /*assert( is_pow2( align ) );*/return -floor2( -n, align ); }122 short int ceiling2( short int n, short int align ) { /*assert( is_pow2( align ) );*/return -floor2( -n, align ); }123 unsigned short int ceiling2( unsigned short int n, unsigned short int align ) { /*assert( is_pow2( align ) );*/return -floor2( -n, align ); }124 int ceiling2( int n, int align ) { /*assert( is_pow2( align ) );*/return -floor2( -n, align ); }125 unsigned int ceiling2( unsigned int n, unsigned int align ) { /*assert( is_pow2( align ) );*/return -floor2( -n, align ); }126 long int ceiling2( long int n, long int align ) { /*assert( is_pow2( align ) );*/return -floor2( -n, align ); }127 unsigned long int ceiling2( unsigned long int n, unsigned long int align ) { /*assert( is_pow2( align ) );*/return -floor2( -n, align ); }128 long long int ceiling2( long long int n, long long int align ) { /*assert( is_pow2( align ) );*/return -floor2( -n, align ); }129 unsigned long long int ceiling2( unsigned long long int n, unsigned long long int align ) { /*assert( is_pow2( align ) );*/return -floor2( -n, align ); }120 signed char ceiling2( signed char n, signed char align ) { verify( is_pow2( align ) ); return -floor2( -n, align ); } 121 unsigned char ceiling2( unsigned char n, unsigned char align ) { verify( is_pow2( align ) ); return -floor2( -n, align ); } 122 short int ceiling2( short int n, short int align ) { verify( is_pow2( align ) ); return -floor2( -n, align ); } 123 unsigned short int ceiling2( unsigned short int n, unsigned short int align ) { verify( is_pow2( align ) ); return -floor2( -n, align ); } 124 int ceiling2( int n, int align ) { verify( is_pow2( align ) ); return -floor2( -n, align ); } 125 unsigned int ceiling2( unsigned int n, unsigned int align ) { verify( is_pow2( align ) ); return -floor2( -n, align ); } 126 long int ceiling2( long int n, long int align ) { verify( is_pow2( align ) ); return -floor2( -n, align ); } 127 unsigned long int ceiling2( unsigned long int n, unsigned long int align ) { verify( is_pow2( align ) ); return -floor2( -n, align ); } 128 long long int ceiling2( long long int n, long long int align ) { verify( is_pow2( align ) ); return -floor2( -n, align ); } 129 unsigned long long int ceiling2( unsigned long long int n, unsigned long long int align ) { verify( is_pow2( align ) ); return -floor2( -n, align ); } 130 130 131 131 // forall( otype T | { T floor2( T, T ); T -?( T ); } ) 132 // T ceiling2( T n, T align ) { /* assert( is_pow2( align ) ); */return -floor2( -n, align ); }132 // T ceiling2( T n, T align ) { verify( is_pow2( align ) ); return -floor2( -n, align ); } 133 133 134 signed char ceiling( signed char n, char align ) { return (n + (align - 1)) / align; } 135 unsigned char ceiling( unsigned char n, unsigned char align ) { return (n + (align - 1)) / align; } 136 short int ceiling( short int n, short int align ) { return (n + (align - 1)) / align; } 137 unsigned short int ceiling( unsigned short int n, unsigned short int align ) { return (n + (align - 1)) / align; } 138 int ceiling( int n, int align ) { return (n + (align - 1)) / align; } 139 unsigned int ceiling( unsigned int n, unsigned int align ) { return (n + (align - 1)) / align; } 140 long int ceiling( long int n, long int align ) { return (n + (align - 1)) / align; } 141 unsigned long int ceiling( unsigned long int n, unsigned long int align ) { return (n + (align - 1)) / align; } 142 long long int ceiling( long long int n, long long int align ) { return (n + (align - 1)) / align; } 143 unsigned long long int ceiling( unsigned long long int n, unsigned long long int align ) { return (n + (align - 1)) / align; } 134 signed char ceiling_div( signed char n, char align ) { return (n + (align - 1)) / align; } 135 unsigned char ceiling_div( unsigned char n, unsigned char align ) { return (n + (align - 1)) / align; } 136 short int ceiling_div( short int n, short int align ) { return (n + (align - 1)) / align; } 137 unsigned short int ceiling_div( unsigned short int n, unsigned short int align ) { return (n + (align - 1)) / align; } 138 int ceiling_div( int n, int align ) { return (n + (align - 1)) / align; } 139 unsigned int ceiling_div( unsigned int n, unsigned int align ) { return (n + (align - 1)) / align; } 140 long int ceiling_div( long int n, long int align ) { return (n + (align - 1)) / align; } 141 unsigned long int ceiling_div( unsigned long int n, unsigned long int align ) { return (n + (align - 1)) / align; } 142 long long int ceiling_div( long long int n, long long int align ) { return (n + (align - 1)) / align; } 143 unsigned long long int ceiling_div( unsigned long long int n, unsigned long long int align ) { return (n + (align - 1)) / align; } 144 145 // forall( otype T | { T ?+?( T, T ); T ?-?( T, T ); T ?%?( T, T ); } ) 146 // T ceiling_div( T n, T align ) { verify( is_pow2( align ) );return (n + (align - 1)) / align; } 147 148 // gcc notices the div/mod pair and saves both so only one div. 149 signed char ceiling( signed char n, signed char align ) { return floor( n + (n % align != 0 ? align - 1 : 0), align ); } 150 unsigned char ceiling( unsigned char n, unsigned char align ) { return floor( n + (n % align != 0 ? align - 1 : 0), align ); } 151 short int ceiling( short int n, short int align ) { return floor( n + (n % align != 0 ? align - 1 : 0), align ); } 152 unsigned short int ceiling( unsigned short int n, unsigned short int align ) { return floor( n + (n % align != 0 ? align - 1 : 0), align ); } 153 int ceiling( int n, int align ) { return floor( n + (n % align != 0 ? align - 1 : 0), align ); } 154 unsigned int ceiling( unsigned int n, unsigned int align ) { return floor( n + (n % align != 0 ? align - 1 : 0), align ); } 155 long int ceiling( long int n, long int align ) { return floor( n + (n % align != 0 ? align - 1 : 0), align ); } 156 unsigned long int ceiling( unsigned long int n, unsigned long int align ) { return floor( n + (n % align != 0 ? align - 1 : 0) , align); } 157 long long int ceiling( long long int n, long long int align ) { return floor( n + (n % align != 0 ? align - 1 : 0), align ); } 158 unsigned long long int ceiling( unsigned long long int n, unsigned long long int align ) { return floor( n + (n % align != 0 ? align - 1 : 0), align ); } 144 159 145 160 // forall( otype T | { void ?{}( T &, one_t ); T ?+?( T, T ); T ?-?( T, T ); T ?/?( T, T ); } ) 146 // T ceiling( T n, T align ) { return (n + (align - (T){1})) / align;}161 // T ceiling( T n, T align ) { return return floor( n + (n % align != 0 ? align - 1 : 0), align ); *} 147 162 } // distribution 148 163 -
libcfa/src/bits/containers.hfa
r07d867b r22f94a4 194 194 195 195 int ?!=?( const __queue(T) & this, __attribute__((unused)) zero_t zero ) { 196 return this.head != 0;196 return this.head != 1p; 197 197 } 198 198 } -
libcfa/src/bits/debug.cfa
r07d867b r22f94a4 10 10 // Created On : Thu Mar 30 12:30:01 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Feb 4 13:03:16202013 // Update Count : 1 112 // Last Modified On : Wed Jun 17 11:07:13 2020 13 // Update Count : 12 14 14 // 15 15 16 extern "C" {17 16 #include <stdio.h> 18 17 #include <stdlib.h> … … 21 20 #include <stdarg.h> 22 21 #include <unistd.h> 23 }24 22 25 23 enum { buffer_size = 4096 }; -
libcfa/src/bits/debug.hfa
r07d867b r22f94a4 15 15 16 16 #pragma once 17 18 #include <assert.h> 17 19 18 20 #ifdef __CFA_DEBUG__ … … 52 54 || defined(__CFA_DEBUG_PRINT_IO__) || defined(__CFA_DEBUG_PRINT_IO_CORE__) \ 53 55 || defined(__CFA_DEBUG_PRINT_MONITOR__) || defined(__CFA_DEBUG_PRINT_PREEMPTION__) \ 54 || defined(__CFA_DEBUG_PRINT_RUNTIME_CORE__) || defined(__CFA_DEBUG_PRINT_EXCEPTION__) 56 || defined(__CFA_DEBUG_PRINT_RUNTIME_CORE__) || defined(__CFA_DEBUG_PRINT_EXCEPTION__) \ 57 || defined(__CFA_DEBUG_PRINT_READY_QUEUE__) 55 58 #include <stdio.h> 56 59 #include <unistd.h> -
libcfa/src/bits/defs.hfa
r07d867b r22f94a4 16 16 #pragma once 17 17 18 #include <stdbool.h>19 #include <stddef.h>20 18 #include <stdint.h> 21 19 -
libcfa/src/bits/locks.hfa
r07d867b r22f94a4 130 130 pthread_mutex_init(&lock, &mattr); 131 131 132 pthread_cond_init (&cond, 0p);132 pthread_cond_init (&cond, (const pthread_condattr_t *)0p); // workaround trac#208: cast should not be required 133 133 val = 0; 134 134 } … … 164 164 165 165 #undef CHECKED 166 167 struct $thread; 168 extern void park( __cfaabi_dbg_ctx_param ); 169 extern void unpark( struct $thread * this __cfaabi_dbg_ctx_param2 ); 170 static inline struct $thread * active_thread (); 171 172 // Semaphore which only supports a single thread 173 struct single_sem { 174 struct $thread * volatile ptr; 175 }; 176 177 static inline { 178 void ?{}(single_sem & this) { 179 this.ptr = 0p; 180 } 181 182 void ^?{}(single_sem & this) {} 183 184 bool wait(single_sem & this) { 185 for() { 186 struct $thread * expected = this.ptr; 187 if(expected == 1p) { 188 if(__atomic_compare_exchange_n(&this.ptr, &expected, 0p, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) { 189 return false; 190 } 191 } 192 else { 193 /* paranoid */ verify( expected == 0p ); 194 if(__atomic_compare_exchange_n(&this.ptr, &expected, active_thread(), false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) { 195 park( __cfaabi_dbg_ctx ); 196 return true; 197 } 198 } 199 200 } 201 } 202 203 bool post(single_sem & this) { 204 for() { 205 struct $thread * expected = this.ptr; 206 if(expected == 1p) return false; 207 if(expected == 0p) { 208 if(__atomic_compare_exchange_n(&this.ptr, &expected, 1p, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) { 209 return false; 210 } 211 } 212 else { 213 if(__atomic_compare_exchange_n(&this.ptr, &expected, 0p, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) { 214 unpark( expected __cfaabi_dbg_ctx2 ); 215 return true; 216 } 217 } 218 } 219 } 220 } 166 221 #endif -
libcfa/src/bits/signal.hfa
r07d867b r22f94a4 19 19 #include "bits/defs.hfa" 20 20 21 extern "C" {22 21 #include <errno.h> 23 22 #define __USE_GNU … … 26 25 #include <stdlib.h> 27 26 #include <string.h> 28 }29 27 30 28 // Short hands for signal context information -
libcfa/src/concurrency/alarm.cfa
r07d867b r22f94a4 10 10 // Created On : Fri Jun 2 11:31:25 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Jan 5 08:41:36202013 // Update Count : 6912 // Last Modified On : Wed Jun 17 16:11:35 2020 13 // Update Count : 75 14 14 // 15 15 16 16 #define __cforall_thread__ 17 17 18 extern "C" {19 18 #include <errno.h> 20 19 #include <stdio.h> 20 #include <unistd.h> 21 21 #include <string.h> 22 #include <unistd.h>23 22 #include <sys/time.h> 24 }25 23 26 24 #include "alarm.hfa" 27 #include "kernel _private.hfa"25 #include "kernel/fwd.hfa" 28 26 #include "preemption.hfa" 29 27 … … 55 53 } 56 54 57 void ?{}( alarm_node_t & this, processor * proc, Time alarm, Duration period ) with( this ) {55 void ?{}( alarm_node_t & this, processor * proc, Time alarm, Duration period ) with( this ) { 58 56 this.proc = proc; 59 57 this.alarm = alarm; -
libcfa/src/concurrency/alarm.hfa
r07d867b r22f94a4 23 23 #include "time.hfa" 24 24 25 #include <containers/list.hfa>25 #include "containers/list.hfa" 26 26 27 27 struct $thread; -
libcfa/src/concurrency/coroutine.cfa
r07d867b r22f94a4 10 10 // Created On : Mon Nov 28 12:27:26 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Feb 4 12:29:25202013 // Update Count : 1612 // Last Modified On : Tue May 26 22:06:09 2020 13 // Update Count : 21 14 14 // 15 15 … … 18 18 #include "coroutine.hfa" 19 19 20 extern "C" {21 20 #include <stddef.h> 22 21 #include <malloc.h> … … 24 23 #include <string.h> 25 24 #include <unistd.h> 26 // use this define to make unwind.h play nice, definetely a hack 25 #include <sys/mman.h> // mprotect 26 extern "C" { 27 // use this define to make unwind.h play nice, definitely a hack 27 28 #define HIDE_EXPORTS 28 29 #include <unwind.h> 29 30 #undef HIDE_EXPORTS 30 #include <sys/mman.h>31 31 } 32 32 -
libcfa/src/concurrency/invoke.c
r07d867b r22f94a4 146 146 147 147 #elif defined( __ARM_ARCH ) 148 #error ARM needs to be upgrade to use to parameters like X86/X64 (A.K.A. : I broke this and do not know how to fix it) 148 #error ARM needs to be upgrade to use two parameters like X86/X64 (A.K.A. : I broke this and do not know how to fix it) 149 // More details about the error: 150 // To avoid the thunk problem, I changed the invoke routine to pass the main explicitly 151 // instead of relying on an assertion. This effectively hoists any required thunk one level 152 // which was enough to get to global scope in most cases. 153 // This means that __cfactx_invoke_... now takes two parameters and the FakeStack needs 154 // to be adjusted as a consequence of that. 155 // I don't know how to do that for ARM, hence the #error 156 149 157 struct FakeStack { 150 158 float fpRegs[16]; // floating point registers -
libcfa/src/concurrency/invoke.h
r07d867b r22f94a4 17 17 #include "bits/defs.hfa" 18 18 #include "bits/locks.hfa" 19 #include "kernel/fwd.hfa" 19 20 20 21 #ifdef __cforall … … 25 26 #ifndef _INVOKE_H_ 26 27 #define _INVOKE_H_ 27 28 #ifdef __ARM_ARCH29 // function prototypes are only really used by these macros on ARM30 void disable_global_interrupts();31 void enable_global_interrupts();32 33 #define TL_GET( member ) ( { __typeof__( kernelTLS.member ) target; \34 disable_global_interrupts(); \35 target = kernelTLS.member; \36 enable_global_interrupts(); \37 target; } )38 #define TL_SET( member, value ) disable_global_interrupts(); \39 kernelTLS.member = value; \40 enable_global_interrupts();41 #else42 #define TL_GET( member ) kernelTLS.member43 #define TL_SET( member, value ) kernelTLS.member = value;44 #endif45 46 #ifdef __cforall47 extern "Cforall" {48 extern __attribute__((aligned(128))) thread_local struct KernelThreadData {49 struct $thread * volatile this_thread;50 struct processor * volatile this_processor;51 52 struct {53 volatile unsigned short disable_count;54 volatile bool enabled;55 volatile bool in_progress;56 } preemption_state;57 58 uint32_t rand_seed;59 } kernelTLS __attribute__ ((tls_model ( "initial-exec" )));60 }61 #endif62 28 63 29 struct __stack_context_t { … … 92 58 }; 93 59 94 enum coroutine_state { Halted, Start, Primed, Blocked, Ready, Active, Rerun }; 95 enum __Preemption_Reason { __NO_PREEMPTION, __ALARM_PREEMPTION, __POLL_PREEMPTION, __MANUAL_PREEMPTION }; 60 enum __Coroutine_State { Halted, Start, Primed, Blocked, Ready, Active }; 96 61 97 62 struct $coroutine { … … 106 71 107 72 // current execution status for coroutine 108 enum coroutine_state state;73 enum __Coroutine_State state; 109 74 110 75 // first coroutine to resume this one … … 161 126 }; 162 127 128 // Link lists fields 129 // instrusive link field for threads 130 struct __thread_desc_link { 131 struct $thread * next; 132 struct $thread * prev; 133 volatile unsigned long long ts; 134 int preferred; 135 }; 136 163 137 struct $thread { 164 138 // Core threading fields … … 167 141 168 142 // current execution status for coroutine 169 volatile int state; 170 enum __Preemption_Reason preempted; 143 volatile int ticket; 144 enum __Coroutine_State state:8; 145 enum __Preemption_Reason preempted:8; 171 146 172 147 //SKULLDUGGERY errno is not save in the thread data structure because returnToKernel appears to be the only function to require saving and restoring it 148 149 // pointer to the cluster on which the thread is running 150 struct cluster * curr_cluster; 151 152 // Link lists fields 153 // instrusive link field for threads 154 struct __thread_desc_link link; 173 155 174 156 // coroutine body used to store context … … 184 166 struct $monitor * self_mon_p; 185 167 186 // pointer to the cluster on which the thread is running187 struct cluster * curr_cluster;188 189 168 // monitors currently held by this thread 190 169 struct __monitor_group_t monitors; 191 192 // Link lists fields193 // instrusive link field for threads194 struct $thread * next;195 170 196 171 struct { … … 202 177 // previous function to park/unpark the thread 203 178 const char * park_caller; 204 enum coroutine_state park_result; 179 int park_result; 180 enum __Coroutine_State park_state; 205 181 bool park_stale; 206 182 const char * unpark_caller; 207 enum coroutine_state unpark_result; 183 int unpark_result; 184 enum __Coroutine_State unpark_state; 208 185 bool unpark_stale; 209 186 #endif … … 218 195 #ifdef __cforall 219 196 extern "Cforall" { 197 220 198 static inline $thread *& get_next( $thread & this ) __attribute__((const)) { 221 return this. next;199 return this.link.next; 222 200 } 223 201 -
libcfa/src/concurrency/io.cfa
r07d867b r22f94a4 14 14 // 15 15 16 // #define __CFA_DEBUG_PRINT_IO__ 17 // #define __CFA_DEBUG_PRINT_IO_CORE__ 18 19 #include "kernel.hfa" 20 21 #if !defined(HAVE_LINUX_IO_URING_H) 22 void __kernel_io_startup( cluster &, int, bool ) { 23 // Nothing to do without io_uring 24 } 25 26 void __kernel_io_finish_start( cluster & ) { 27 // Nothing to do without io_uring 28 } 29 30 void __kernel_io_prepare_stop( cluster & ) { 31 // Nothing to do without io_uring 32 } 33 34 void __kernel_io_shutdown( cluster &, bool ) { 35 // Nothing to do without io_uring 36 } 37 38 #else 16 #define __cforall_thread__ 17 18 #if defined(__CFA_DEBUG__) 19 // #define __CFA_DEBUG_PRINT_IO__ 20 // #define __CFA_DEBUG_PRINT_IO_CORE__ 21 #endif 22 23 24 #if defined(CFA_HAVE_LINUX_IO_URING_H) 25 #define _GNU_SOURCE /* See feature_test_macros(7) */ 26 #include <errno.h> 27 #include <signal.h> 28 #include <stdint.h> 29 #include <string.h> 30 #include <unistd.h> 31 39 32 extern "C" { 40 #define _GNU_SOURCE /* See feature_test_macros(7) */ 41 #include <errno.h> 42 #include <stdint.h> 43 #include <string.h> 44 #include <unistd.h> 45 #include <sys/mman.h> 33 #include <sys/epoll.h> 46 34 #include <sys/syscall.h> 47 35 … … 49 37 } 50 38 51 #include "bits/signal.hfa" 52 #include "kernel_private.hfa" 53 #include "thread.hfa" 54 55 uint32_t entries_per_cluster() { 56 return 256; 57 } 58 59 static void * __io_poller_slow( void * arg ); 60 61 // Weirdly, some systems that do support io_uring don't actually define these 62 #ifdef __alpha__ 63 /* 64 * alpha is the only exception, all other architectures 65 * have common numbers for new system calls. 66 */ 67 #ifndef __NR_io_uring_setup 68 #define __NR_io_uring_setup 535 69 #endif 70 #ifndef __NR_io_uring_enter 71 #define __NR_io_uring_enter 536 72 #endif 73 #ifndef __NR_io_uring_register 74 #define __NR_io_uring_register 537 75 #endif 76 #else /* !__alpha__ */ 77 #ifndef __NR_io_uring_setup 78 #define __NR_io_uring_setup 425 79 #endif 80 #ifndef __NR_io_uring_enter 81 #define __NR_io_uring_enter 426 82 #endif 83 #ifndef __NR_io_uring_register 84 #define __NR_io_uring_register 427 85 #endif 86 #endif 87 88 // Fast poller user-thread 89 // Not using the "thread" keyword because we want to control 90 // more carefully when to start/stop it 91 struct __io_poller_fast { 92 struct __io_data * ring; 93 bool waiting; 94 $thread thrd; 95 }; 96 97 void ?{}( __io_poller_fast & this, struct cluster & cltr ) { 98 this.ring = cltr.io; 99 this.waiting = true; 100 (this.thrd){ "Fast I/O Poller", cltr }; 101 } 102 void ^?{}( __io_poller_fast & mutex this ); 103 void main( __io_poller_fast & this ); 104 static inline $thread * get_thread( __io_poller_fast & this ) { return &this.thrd; } 105 void ^?{}( __io_poller_fast & mutex this ) {} 106 107 struct __submition_data { 108 // Head and tail of the ring (associated with array) 109 volatile uint32_t * head; 110 volatile uint32_t * tail; 111 112 // The actual kernel ring which uses head/tail 113 // indexes into the sqes arrays 114 uint32_t * array; 115 116 // number of entries and mask to go with it 117 const uint32_t * num; 118 const uint32_t * mask; 119 120 // Submission flags (Not sure what for) 121 uint32_t * flags; 122 123 // number of sqes not submitted (whatever that means) 124 uint32_t * dropped; 125 126 // Like head/tail but not seen by the kernel 127 volatile uint32_t alloc; 128 volatile uint32_t ready; 129 130 __spinlock_t lock; 131 132 // A buffer of sqes (not the actual ring) 133 struct io_uring_sqe * sqes; 134 135 // The location and size of the mmaped area 136 void * ring_ptr; 137 size_t ring_sz; 138 139 // Statistics 140 #if !defined(__CFA_NO_STATISTICS__) 141 struct { 142 struct { 143 volatile unsigned long long int val; 144 volatile unsigned long long int cnt; 145 volatile unsigned long long int block; 146 } submit_avg; 147 } stats; 148 #endif 149 }; 150 151 struct __completion_data { 152 // Head and tail of the ring 153 volatile uint32_t * head; 154 volatile uint32_t * tail; 155 156 // number of entries and mask to go with it 157 const uint32_t * mask; 158 const uint32_t * num; 159 160 // number of cqes not submitted (whatever that means) 161 uint32_t * overflow; 162 163 // the kernel ring 164 struct io_uring_cqe * cqes; 165 166 // The location and size of the mmaped area 167 void * ring_ptr; 168 size_t ring_sz; 169 170 // Statistics 171 #if !defined(__CFA_NO_STATISTICS__) 172 struct { 173 struct { 174 unsigned long long int val; 175 unsigned long long int slow_cnt; 176 unsigned long long int fast_cnt; 177 } completed_avg; 178 } stats; 179 #endif 180 }; 181 182 struct __io_data { 183 struct __submition_data submit_q; 184 struct __completion_data completion_q; 185 uint32_t ring_flags; 186 int cltr_flags; 187 int fd; 188 semaphore submit; 189 volatile bool done; 190 struct { 191 struct { 192 void * stack; 193 pthread_t kthrd; 194 } slow; 195 __io_poller_fast fast; 196 __bin_sem_t sem; 197 } poller; 198 }; 199 200 //============================================================================================= 201 // I/O Startup / Shutdown logic 202 //============================================================================================= 203 void __kernel_io_startup( cluster & this, int io_flags, bool main_cluster ) { 204 this.io = malloc(); 205 206 // Step 1 : call to setup 207 struct io_uring_params params; 208 memset(¶ms, 0, sizeof(params)); 209 210 uint32_t nentries = entries_per_cluster(); 211 212 int fd = syscall(__NR_io_uring_setup, nentries, ¶ms ); 213 if(fd < 0) { 214 abort("KERNEL ERROR: IO_URING SETUP - %s\n", strerror(errno)); 215 } 216 217 // Step 2 : mmap result 218 memset( this.io, 0, sizeof(struct __io_data) ); 219 struct __submition_data & sq = this.io->submit_q; 220 struct __completion_data & cq = this.io->completion_q; 221 222 // calculate the right ring size 223 sq.ring_sz = params.sq_off.array + (params.sq_entries * sizeof(unsigned) ); 224 cq.ring_sz = params.cq_off.cqes + (params.cq_entries * sizeof(struct io_uring_cqe)); 225 226 // Requires features 227 #if defined(IORING_FEAT_SINGLE_MMAP) 228 // adjust the size according to the parameters 229 if ((params.features & IORING_FEAT_SINGLE_MMAP) != 0) { 230 cq->ring_sz = sq->ring_sz = max(cq->ring_sz, sq->ring_sz); 231 } 232 #endif 233 234 // mmap the Submit Queue into existence 235 sq.ring_ptr = mmap(0, sq.ring_sz, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, fd, IORING_OFF_SQ_RING); 236 if (sq.ring_ptr == (void*)MAP_FAILED) { 237 abort("KERNEL ERROR: IO_URING MMAP1 - %s\n", strerror(errno)); 238 } 239 240 // Requires features 241 #if defined(IORING_FEAT_SINGLE_MMAP) 242 // mmap the Completion Queue into existence (may or may not be needed) 243 if ((params.features & IORING_FEAT_SINGLE_MMAP) != 0) { 244 cq->ring_ptr = sq->ring_ptr; 245 } 246 else 247 #endif 248 { 249 // We need multiple call to MMAP 250 cq.ring_ptr = mmap(0, cq.ring_sz, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, fd, IORING_OFF_CQ_RING); 251 if (cq.ring_ptr == (void*)MAP_FAILED) { 252 munmap(sq.ring_ptr, sq.ring_sz); 253 abort("KERNEL ERROR: IO_URING MMAP2 - %s\n", strerror(errno)); 254 } 255 } 256 257 // mmap the submit queue entries 258 size_t size = params.sq_entries * sizeof(struct io_uring_sqe); 259 sq.sqes = (struct io_uring_sqe *)mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, fd, IORING_OFF_SQES); 260 if (sq.sqes == (struct io_uring_sqe *)MAP_FAILED) { 261 munmap(sq.ring_ptr, sq.ring_sz); 262 if (cq.ring_ptr != sq.ring_ptr) munmap(cq.ring_ptr, cq.ring_sz); 263 abort("KERNEL ERROR: IO_URING MMAP3 - %s\n", strerror(errno)); 264 } 265 266 // Get the pointers from the kernel to fill the structure 267 // submit queue 268 sq.head = (volatile uint32_t *)(((intptr_t)sq.ring_ptr) + params.sq_off.head); 269 sq.tail = (volatile uint32_t *)(((intptr_t)sq.ring_ptr) + params.sq_off.tail); 270 sq.mask = ( const uint32_t *)(((intptr_t)sq.ring_ptr) + params.sq_off.ring_mask); 271 sq.num = ( const uint32_t *)(((intptr_t)sq.ring_ptr) + params.sq_off.ring_entries); 272 sq.flags = ( uint32_t *)(((intptr_t)sq.ring_ptr) + params.sq_off.flags); 273 sq.dropped = ( uint32_t *)(((intptr_t)sq.ring_ptr) + params.sq_off.dropped); 274 sq.array = ( uint32_t *)(((intptr_t)sq.ring_ptr) + params.sq_off.array); 275 sq.alloc = *sq.tail; 276 sq.ready = *sq.tail; 277 278 // completion queue 279 cq.head = (volatile uint32_t *)(((intptr_t)cq.ring_ptr) + params.cq_off.head); 280 cq.tail = (volatile uint32_t *)(((intptr_t)cq.ring_ptr) + params.cq_off.tail); 281 cq.mask = ( const uint32_t *)(((intptr_t)cq.ring_ptr) + params.cq_off.ring_mask); 282 cq.num = ( const uint32_t *)(((intptr_t)cq.ring_ptr) + params.cq_off.ring_entries); 283 cq.overflow = ( uint32_t *)(((intptr_t)cq.ring_ptr) + params.cq_off.overflow); 284 cq.cqes = (struct io_uring_cqe *)(((intptr_t)cq.ring_ptr) + params.cq_off.cqes); 285 286 // some paranoid checks 287 /* paranoid */ verifyf( (*cq.mask) == ((*cq.num) - 1ul32), "IO_URING Expected mask to be %u (%u entries), was %u", (*cq.num) - 1ul32, *cq.num, *cq.mask ); 288 /* paranoid */ verifyf( (*cq.num) >= nentries, "IO_URING Expected %u entries, got %u", nentries, *cq.num ); 289 /* paranoid */ verifyf( (*cq.head) == 0, "IO_URING Expected head to be 0, got %u", *cq.head ); 290 /* paranoid */ verifyf( (*cq.tail) == 0, "IO_URING Expected tail to be 0, got %u", *cq.tail ); 291 292 /* paranoid */ verifyf( (*sq.mask) == ((*sq.num) - 1ul32), "IO_URING Expected mask to be %u (%u entries), was %u", (*sq.num) - 1ul32, *sq.num, *sq.mask ); 293 /* paranoid */ verifyf( (*sq.num) >= nentries, "IO_URING Expected %u entries, got %u", nentries, *sq.num ); 294 /* paranoid */ verifyf( (*sq.head) == 0, "IO_URING Expected head to be 0, got %u", *sq.head ); 295 /* paranoid */ verifyf( (*sq.tail) == 0, "IO_URING Expected tail to be 0, got %u", *sq.tail ); 296 297 // Update the global ring info 298 this.io->ring_flags = params.flags; 299 this.io->cltr_flags = io_flags; 300 this.io->fd = fd; 301 this.io->done = false; 302 (this.io->submit){ min(*sq.num, *cq.num) }; 303 304 // Initialize statistics 305 #if !defined(__CFA_NO_STATISTICS__) 306 this.io->submit_q.stats.submit_avg.val = 0; 307 this.io->submit_q.stats.submit_avg.cnt = 0; 308 this.io->submit_q.stats.submit_avg.block = 0; 309 this.io->completion_q.stats.completed_avg.val = 0; 310 this.io->completion_q.stats.completed_avg.slow_cnt = 0; 311 this.io->completion_q.stats.completed_avg.fast_cnt = 0; 312 #endif 313 314 if(!main_cluster) { 315 __kernel_io_finish_start( this ); 316 } 317 } 318 319 void __kernel_io_finish_start( cluster & this ) { 320 if( this.io->cltr_flags & CFA_CLUSTER_IO_POLLER_USER_THREAD ) { 321 __cfadbg_print_safe(io_core, "Kernel I/O : Creating fast poller for cluter %p\n", &this); 322 (this.io->poller.fast){ this }; 323 __thrd_start( this.io->poller.fast, main ); 324 } 325 326 // Create the poller thread 327 __cfadbg_print_safe(io_core, "Kernel I/O : Creating slow poller for cluter %p\n", &this); 328 this.io->poller.slow.stack = __create_pthread( &this.io->poller.slow.kthrd, __io_poller_slow, &this ); 329 } 330 331 void __kernel_io_prepare_stop( cluster & this ) { 332 __cfadbg_print_safe(io_core, "Kernel I/O : Stopping pollers for cluster\n", &this); 333 // Notify the poller thread of the shutdown 334 __atomic_store_n(&this.io->done, true, __ATOMIC_SEQ_CST); 335 336 // Stop the IO Poller 337 sigval val = { 1 }; 338 pthread_sigqueue( this.io->poller.slow.kthrd, SIGUSR1, val ); 339 post( this.io->poller.sem ); 340 341 // Wait for the poller thread to finish 342 pthread_join( this.io->poller.slow.kthrd, 0p ); 343 free( this.io->poller.slow.stack ); 344 345 __cfadbg_print_safe(io_core, "Kernel I/O : Slow poller stopped for cluster\n", &this); 346 347 if( this.io->cltr_flags & CFA_CLUSTER_IO_POLLER_USER_THREAD ) { 348 with( this.io->poller.fast ) { 349 /* paranoid */ verify( waiting ); // The thread shouldn't be in a system call 350 /* paranoid */ verify( this.procs.head == 0p || &this == mainCluster ); 351 /* paranoid */ verify( this.idles.head == 0p || &this == mainCluster ); 352 353 // We need to adjust the clean-up based on where the thread is 354 if( thrd.preempted != __NO_PREEMPTION ) { 355 356 // This is the tricky case 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 359 /* paranoid */ verify( thrd.next == 1p ); // The thread should be the last on the list 360 /* paranoid */ verify( this.ready_queue.head == &thrd ); // The thread should be the only thing on the list 361 362 // Remove the thread from the ready queue of this cluster 363 this.ready_queue.head = 1p; 364 thrd.next = 0p; 365 366 // Fixup the thread state 367 thrd.state = Blocked; 368 thrd.preempted = __NO_PREEMPTION; 369 370 // Pretend like the thread was blocked all along 371 } 372 // !!! This is not an else if !!! 373 if( thrd.state == Blocked ) { 374 375 // This is the "easy case" 376 // The thread is parked and can easily be moved to active cluster 377 verify( thrd.curr_cluster != active_cluster() || thrd.curr_cluster == mainCluster ); 378 thrd.curr_cluster = active_cluster(); 379 380 // unpark the fast io_poller 381 unpark( &thrd __cfaabi_dbg_ctx2 ); 382 } 383 else { 384 385 // The thread is in a weird state 386 // I don't know what to do here 387 abort("Fast poller thread is in unexpected state, cannot clean-up correctly\n"); 388 } 389 390 } 391 392 ^(this.io->poller.fast){}; 393 394 __cfadbg_print_safe(io_core, "Kernel I/O : Fast poller stopped for cluster\n", &this); 395 } 396 } 397 398 void __kernel_io_shutdown( cluster & this, bool main_cluster ) { 399 if(!main_cluster) { 400 __kernel_io_prepare_stop( this ); 401 } 402 403 // print statistics 404 #if !defined(__CFA_NO_STATISTICS__) 405 if(this.print_stats) { 406 with(this.io->submit_q.stats, this.io->completion_q.stats) { 407 __cfaabi_bits_print_safe( STDERR_FILENO, 408 "----- 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", 414 submit_avg.cnt, 415 ((double)submit_avg.val) / submit_avg.cnt, 416 (100.0 * submit_avg.block) / submit_avg.cnt, 417 completed_avg.slow_cnt + completed_avg.fast_cnt, 418 completed_avg.slow_cnt, completed_avg.fast_cnt, 419 ((double)completed_avg.val) / (completed_avg.slow_cnt + completed_avg.fast_cnt) 420 ); 421 } 422 } 423 #endif 424 425 // Shutdown the io rings 426 struct __submition_data & sq = this.io->submit_q; 427 struct __completion_data & cq = this.io->completion_q; 428 429 // unmap the submit queue entries 430 munmap(sq.sqes, (*sq.num) * sizeof(struct io_uring_sqe)); 431 432 // unmap the Submit Queue ring 433 munmap(sq.ring_ptr, sq.ring_sz); 434 435 // unmap the Completion Queue ring, if it is different 436 if (cq.ring_ptr != sq.ring_ptr) { 437 munmap(cq.ring_ptr, cq.ring_sz); 438 } 439 440 // close the file descriptor 441 close(this.io->fd); 442 443 free( this.io ); 39 #include "stats.hfa" 40 #include "kernel.hfa" 41 #include "kernel/fwd.hfa" 42 #include "io/types.hfa" 43 44 //============================================================================================= 45 // I/O Syscall 46 //============================================================================================= 47 static int __io_uring_enter( struct __io_data & ring, unsigned to_submit, bool get ) { 48 bool need_sys_to_submit = false; 49 bool need_sys_to_complete = false; 50 unsigned flags = 0; 51 52 TO_SUBMIT: 53 if( to_submit > 0 ) { 54 if( !(ring.ring_flags & IORING_SETUP_SQPOLL) ) { 55 need_sys_to_submit = true; 56 break TO_SUBMIT; 57 } 58 if( (*ring.submit_q.flags) & IORING_SQ_NEED_WAKEUP ) { 59 need_sys_to_submit = true; 60 flags |= IORING_ENTER_SQ_WAKEUP; 61 } 62 } 63 64 if( get && !(ring.ring_flags & IORING_SETUP_SQPOLL) ) { 65 flags |= IORING_ENTER_GETEVENTS; 66 if( (ring.ring_flags & IORING_SETUP_IOPOLL) ) { 67 need_sys_to_complete = true; 68 } 69 } 70 71 int ret = 0; 72 if( need_sys_to_submit || need_sys_to_complete ) { 73 ret = syscall( __NR_io_uring_enter, ring.fd, to_submit, 0, flags, 0p, _NSIG / 8); 74 if( ret < 0 ) { 75 switch((int)errno) { 76 case EAGAIN: 77 case EINTR: 78 ret = -1; 79 break; 80 default: 81 abort( "KERNEL ERROR: IO_URING SYSCALL - (%d) %s\n", (int)errno, strerror(errno) ); 82 } 83 } 84 } 85 86 // Memory barrier 87 __atomic_thread_fence( __ATOMIC_SEQ_CST ); 88 return ret; 444 89 } 445 90 … … 447 92 // I/O Polling 448 93 //============================================================================================= 449 struct io_user_data { 450 int32_t result; 451 $thread * thrd; 452 }; 94 static unsigned __collect_submitions( struct __io_data & ring ); 95 static uint32_t __release_consumed_submission( struct __io_data & ring ); 96 97 static inline void process(struct io_uring_cqe & cqe ) { 98 struct __io_user_data_t * data = (struct __io_user_data_t *)(uintptr_t)cqe.user_data; 99 __cfadbg_print_safe( io, "Kernel I/O : Syscall completed : cqe %p, result %d for %p\n", data, cqe.res, data->thrd ); 100 101 data->result = cqe.res; 102 unpark( data->thrd __cfaabi_dbg_ctx2 ); 103 } 453 104 454 105 // Process a single completion message from the io_uring 455 106 // 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); 107 static [int, bool] __drain_io( & struct __io_data ring ) { 108 /* paranoid */ verify( !kernelTLS.preemption_state.enabled ); 109 110 unsigned to_submit = 0; 111 if( ring.poller_submits ) { 112 // If the poller thread also submits, then we need to aggregate the submissions which are ready 113 to_submit = __collect_submitions( ring ); 114 } 115 116 int ret = __io_uring_enter(ring, to_submit, true); 458 117 if( ret < 0 ) { 459 switch((int)errno) { 460 case EAGAIN: 461 case EINTR: 462 return -EAGAIN; 463 default: 464 abort( "KERNEL ERROR: IO_URING WAIT - %s\n", strerror(errno) ); 465 } 466 } 118 return [0, true]; 119 } 120 121 // update statistics 122 if (to_submit > 0) { 123 __STATS__( true, 124 if( to_submit > 0 ) { 125 io.submit_q.submit_avg.rdy += to_submit; 126 io.submit_q.submit_avg.csm += ret; 127 io.submit_q.submit_avg.cnt += 1; 128 } 129 ) 130 } 131 132 // Release the consumed SQEs 133 __release_consumed_submission( ring ); 467 134 468 135 // Drain the queue 469 136 unsigned head = *ring.completion_q.head; 470 unsigned tail = __atomic_load_n(ring.completion_q.tail, __ATOMIC_ACQUIRE); 137 unsigned tail = *ring.completion_q.tail; 138 const uint32_t mask = *ring.completion_q.mask; 471 139 472 140 // Nothing was new return 0 473 141 if (head == tail) { 474 return 0;142 return [0, to_submit > 0]; 475 143 } 476 144 477 145 uint32_t count = tail - head; 146 /* paranoid */ verify( count != 0 ); 478 147 for(i; count) { 479 unsigned idx = (head + i) & (*ring.completion_q.mask);148 unsigned idx = (head + i) & mask; 480 149 struct io_uring_cqe & cqe = ring.completion_q.cqes[idx]; 481 150 482 151 /* paranoid */ verify(&cqe); 483 152 484 struct io_user_data * data = (struct io_user_data *)cqe.user_data; 485 __cfadbg_print_safe( io, "Kernel I/O : Performed reading io cqe %p, result %d for %p\n", data, cqe.res, data->thrd ); 486 487 data->result = cqe.res; 488 if(!in_kernel) { unpark( data->thrd __cfaabi_dbg_ctx2 ); } 489 else { __unpark( data->thrd __cfaabi_dbg_ctx2 ); } 490 } 491 492 // Allow new submissions to happen 493 V(ring.submit, count); 153 process( cqe ); 154 } 494 155 495 156 // Mark to the kernel that the cqe has been seen 496 157 // Ensure that the kernel only sees the new value of the head index after the CQEs have been read. 158 __atomic_thread_fence( __ATOMIC_SEQ_CST ); 497 159 __atomic_fetch_add( ring.completion_q.head, count, __ATOMIC_RELAXED ); 498 160 499 return count; 500 } 501 502 static void * __io_poller_slow( void * arg ) { 503 cluster * cltr = (cluster *)arg; 504 struct __io_data & ring = *cltr->io; 505 506 sigset_t mask; 507 sigfillset(&mask); 508 if ( pthread_sigmask( SIG_BLOCK, &mask, 0p ) == -1 ) { 509 abort( "KERNEL ERROR: IO_URING - pthread_sigmask" ); 510 } 511 512 sigdelset( &mask, SIGUSR1 ); 513 514 verify( (*ring.submit_q.head) == (*ring.submit_q.tail) ); 515 verify( (*ring.completion_q.head) == (*ring.completion_q.tail) ); 516 517 __cfadbg_print_safe(io_core, "Kernel I/O : Slow poller for ring %p ready\n", &ring); 518 519 if( ring.cltr_flags & CFA_CLUSTER_IO_POLLER_USER_THREAD ) { 520 while(!__atomic_load_n(&ring.done, __ATOMIC_SEQ_CST)) { 521 // In the user-thread approach drain and if anything was drained, 522 // batton pass to the user-thread 523 int count = __drain_io( ring, &mask, 1, true ); 161 return [count, count > 0 || to_submit > 0]; 162 } 163 164 void main( $io_ctx_thread & this ) { 165 epoll_event ev; 166 __ioctx_register( this, ev ); 167 168 __cfadbg_print_safe(io_core, "Kernel I/O : IO poller %p for ring %p ready\n", &this, &this.ring); 169 170 int reset = 0; 171 // Then loop until we need to start 172 while(!__atomic_load_n(&this.done, __ATOMIC_SEQ_CST)) { 173 // Drain the io 174 int count; 175 bool again; 176 disable_interrupts(); 177 [count, again] = __drain_io( *this.ring ); 178 179 if(!again) reset++; 524 180 525 181 // Update statistics 526 #if !defined(__CFA_NO_STATISTICS__) 527 ring.completion_q.stats.completed_avg.val += count; 528 ring.completion_q.stats.completed_avg.slow_cnt += 1; 529 #endif 530 531 if(count > 0) { 532 __cfadbg_print_safe(io_core, "Kernel I/O : Moving to ring %p to fast poller\n", &ring); 533 __unpark( &ring.poller.fast.thrd __cfaabi_dbg_ctx2 ); 534 wait( ring.poller.sem ); 535 } 536 } 537 } 538 else { 539 while(!__atomic_load_n(&ring.done, __ATOMIC_SEQ_CST)) { 540 //In the naive approach, just poll the io completion queue directly 541 int count = __drain_io( ring, &mask, 1, true ); 542 543 // Update statistics 544 #if !defined(__CFA_NO_STATISTICS__) 545 ring.completion_q.stats.completed_avg.val += count; 546 ring.completion_q.stats.completed_avg.slow_cnt += 1; 547 #endif 548 } 549 } 550 551 __cfadbg_print_safe(io_core, "Kernel I/O : Slow poller for ring %p stopping\n", &ring); 552 553 return 0p; 554 } 555 556 void main( __io_poller_fast & this ) { 557 verify( this.ring->cltr_flags & CFA_CLUSTER_IO_POLLER_USER_THREAD ); 558 559 // Start parked 560 park( __cfaabi_dbg_ctx ); 561 562 __cfadbg_print_safe(io_core, "Kernel I/O : Fast poller for ring %p ready\n", &this.ring); 563 564 int reset = 0; 565 566 // Then loop until we need to start 567 while(!__atomic_load_n(&this.ring->done, __ATOMIC_SEQ_CST)) { 568 // Drain the io 569 this.waiting = false; 570 int count = __drain_io( *this.ring, 0p, 0, false ); 571 reset += count > 0 ? 1 : 0; 572 573 // Update statistics 574 #if !defined(__CFA_NO_STATISTICS__) 575 this.ring->completion_q.stats.completed_avg.val += count; 576 this.ring->completion_q.stats.completed_avg.fast_cnt += 1; 577 #endif 578 579 this.waiting = true; 182 __STATS__( true, 183 io.complete_q.completed_avg.val += count; 184 io.complete_q.completed_avg.fast_cnt += 1; 185 ) 186 enable_interrupts( __cfaabi_dbg_ctx ); 187 188 // If we got something, just yield and check again 580 189 if(reset < 5) { 581 // If we got something, just yield and check again582 190 yield(); 583 191 } 192 // We didn't get anything baton pass to the slow poller 584 193 else { 585 // We didn't get anything baton pass to the slow poller 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 ); 194 __cfadbg_print_safe(io_core, "Kernel I/O : Parking io poller %p\n", &this.self); 589 195 reset = 0; 196 197 // block this thread 198 __ioctx_prepare_block( this, ev ); 199 wait( this.sem ); 590 200 } 591 201 } … … 599 209 600 210 // Submition steps : 601 // 1 - We need to make sure we don't overflow any of the buffer, P(ring.submit) to make sure 602 // entries are available. The semaphore make sure that there is no more operations in 603 // progress then the number of entries in the buffer. This probably limits concurrency 604 // more than necessary since submitted but not completed operations don't need any 605 // entries in user space. However, I don't know what happens if we overflow the buffers 606 // because too many requests completed at once. This is a safe approach in all cases. 607 // Furthermore, with hundreds of entries, this may be okay. 608 // 609 // 2 - Allocate a queue entry. The ring already has memory for all entries but only the ones 211 // 1 - Allocate a queue entry. The ring already has memory for all entries but only the ones 610 212 // listed in sq.array are visible by the kernel. For those not listed, the kernel does not 611 213 // offer any assurance that an entry is not being filled by multiple flags. Therefore, we 612 214 // need to write an allocator that allows allocating concurrently. 613 215 // 614 // 3- Actually fill the submit entry, this is the only simple and straightforward step.615 // 616 // 4- Append the entry index to the array and adjust the tail accordingly. This operation216 // 2 - Actually fill the submit entry, this is the only simple and straightforward step. 217 // 218 // 3 - Append the entry index to the array and adjust the tail accordingly. This operation 617 219 // needs to arrive to two concensus at the same time: 618 220 // A - The order in which entries are listed in the array: no two threads must pick the … … 622 224 // 623 225 624 static inline [* struct io_uring_sqe, uint32_t] __submit_alloc( struct __io_data & ring ) { 625 // Wait for a spot to be available 626 __attribute__((unused)) bool blocked = P(ring.submit); 627 #if !defined(__CFA_NO_STATISTICS__) 628 __atomic_fetch_add( &ring.submit_q.stats.submit_avg.block, blocked ? 1ul64 : 0ul64, __ATOMIC_RELAXED ); 629 #endif 630 631 // Allocate the sqe 632 uint32_t idx = __atomic_fetch_add(&ring.submit_q.alloc, 1ul32, __ATOMIC_SEQ_CST); 633 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 ); 640 641 // Return the sqe 642 return [&ring.submit_q.sqes[ idx & (*ring.submit_q.mask)], idx]; 643 } 644 645 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; 226 [* struct io_uring_sqe, uint32_t] __submit_alloc( struct __io_data & ring, uint64_t data ) { 227 /* paranoid */ verify( data != 0 ); 228 229 // Prepare the data we need 230 __attribute((unused)) int len = 0; 231 __attribute((unused)) int block = 0; 232 uint32_t cnt = *ring.submit_q.num; 233 uint32_t mask = *ring.submit_q.mask; 234 235 disable_interrupts(); 236 uint32_t off = __tls_rand(); 237 enable_interrupts( __cfaabi_dbg_ctx ); 238 239 // Loop around looking for an available spot 240 for() { 241 // Look through the list starting at some offset 242 for(i; cnt) { 243 uint64_t expected = 0; 244 uint32_t idx = (i + off) & mask; 245 struct io_uring_sqe * sqe = &ring.submit_q.sqes[idx]; 246 volatile uint64_t * udata = (volatile uint64_t *)&sqe->user_data; 247 248 if( *udata == expected && 249 __atomic_compare_exchange_n( udata, &expected, data, true, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED ) ) 250 { 251 // update statistics 252 __STATS__( false, 253 io.submit_q.alloc_avg.val += len; 254 io.submit_q.alloc_avg.block += block; 255 io.submit_q.alloc_avg.cnt += 1; 256 ) 257 258 259 // Success return the data 260 return [sqe, idx]; 261 } 262 verify(expected != data); 263 264 len ++; 265 } 266 267 block++; 268 yield(); 269 } 270 } 271 272 static inline uint32_t __submit_to_ready_array( struct __io_data & ring, uint32_t idx, const uint32_t mask ) { 273 /* paranoid */ verify( idx <= mask ); 274 /* paranoid */ verify( idx != -1ul32 ); 275 276 // We need to find a spot in the ready array 277 __attribute((unused)) int len = 0; 278 __attribute((unused)) int block = 0; 279 uint32_t ready_mask = ring.submit_q.ready_cnt - 1; 280 281 disable_interrupts(); 282 uint32_t off = __tls_rand(); 283 enable_interrupts( __cfaabi_dbg_ctx ); 284 285 uint32_t picked; 286 LOOKING: for() { 287 for(i; ring.submit_q.ready_cnt) { 288 picked = (i + off) & ready_mask; 289 uint32_t expected = -1ul32; 290 if( __atomic_compare_exchange_n( &ring.submit_q.ready[picked], &expected, idx, true, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED ) ) { 291 break LOOKING; 292 } 293 verify(expected != idx); 294 295 len ++; 296 } 297 298 block++; 299 if( try_lock(ring.submit_q.lock __cfaabi_dbg_ctx2) ) { 300 __release_consumed_submission( ring ); 301 unlock( ring.submit_q.lock ); 302 } 303 else { 304 yield(); 305 } 306 } 307 308 // update statistics 309 __STATS__( false, 310 io.submit_q.look_avg.val += len; 311 io.submit_q.look_avg.block += block; 312 io.submit_q.look_avg.cnt += 1; 313 ) 314 315 return picked; 316 } 317 318 void __submit( struct io_context * ctx, uint32_t idx ) __attribute__((nonnull (1))) { 319 __io_data & ring = *ctx->thrd.ring; 320 // Get now the data we definetely need 321 volatile uint32_t * const tail = ring.submit_q.tail; 322 const uint32_t mask = *ring.submit_q.mask; 323 324 // There are 2 submission schemes, check which one we are using 325 if( ring.poller_submits ) { 326 // If the poller thread submits, then we just need to add this to the ready array 327 __submit_to_ready_array( ring, idx, mask ); 328 329 post( ctx->thrd.sem ); 330 331 __cfadbg_print_safe( io, "Kernel I/O : Added %u to ready for %p\n", idx, active_thread() ); 332 } 333 else if( ring.eager_submits ) { 334 uint32_t picked = __submit_to_ready_array( ring, idx, mask ); 335 336 for() { 337 yield(); 338 339 // If some one else collected our index, we are done 340 #warning ABA problem 341 if( ring.submit_q.ready[picked] != idx ) { 342 __STATS__( false, 343 io.submit_q.helped += 1; 344 ) 345 return; 346 } 347 348 if( try_lock(ring.submit_q.lock __cfaabi_dbg_ctx2) ) { 349 __STATS__( false, 350 io.submit_q.leader += 1; 351 ) 352 break; 353 } 354 355 __STATS__( false, 356 io.submit_q.busy += 1; 357 ) 358 } 359 360 // We got the lock 361 unsigned to_submit = __collect_submitions( ring ); 362 int ret = __io_uring_enter( ring, to_submit, false ); 363 if( ret < 0 ) { 364 unlock(ring.submit_q.lock); 365 return; 366 } 367 368 /* paranoid */ verify( ret > 0 || to_submit == 0 || (ring.ring_flags & IORING_SETUP_SQPOLL) ); 369 370 // Release the consumed SQEs 371 __release_consumed_submission( ring ); 372 373 // update statistics 374 __STATS__( true, 375 io.submit_q.submit_avg.rdy += to_submit; 376 io.submit_q.submit_avg.csm += ret; 377 io.submit_q.submit_avg.cnt += 1; 378 ) 379 380 unlock(ring.submit_q.lock); 381 } 382 else { 383 // get mutual exclusion 384 lock(ring.submit_q.lock __cfaabi_dbg_ctx2); 385 386 /* paranoid */ verifyf( ring.submit_q.sqes[ idx ].user_data != 0, 387 /* paranoid */ "index %u already reclaimed\n" 388 /* paranoid */ "head %u, prev %u, tail %u\n" 389 /* paranoid */ "[-0: %u,-1: %u,-2: %u,-3: %u]\n", 390 /* paranoid */ idx, 391 /* paranoid */ *ring.submit_q.head, ring.submit_q.prev_head, *tail 392 /* paranoid */ ,ring.submit_q.array[ ((*ring.submit_q.head) - 0) & (*ring.submit_q.mask) ] 393 /* paranoid */ ,ring.submit_q.array[ ((*ring.submit_q.head) - 1) & (*ring.submit_q.mask) ] 394 /* paranoid */ ,ring.submit_q.array[ ((*ring.submit_q.head) - 2) & (*ring.submit_q.mask) ] 395 /* paranoid */ ,ring.submit_q.array[ ((*ring.submit_q.head) - 3) & (*ring.submit_q.mask) ] 396 /* paranoid */ ); 397 398 // Append to the list of ready entries 399 400 /* paranoid */ verify( idx <= mask ); 401 ring.submit_q.array[ (*tail) & mask ] = idx; 402 __atomic_fetch_add(tail, 1ul32, __ATOMIC_SEQ_CST); 403 404 // Submit however, many entries need to be submitted 405 int ret = __io_uring_enter( ring, 1, false ); 406 if( ret < 0 ) { 407 switch((int)errno) { 408 default: 409 abort( "KERNEL ERROR: IO_URING SUBMIT - %s\n", strerror(errno) ); 410 } 411 } 412 413 // update statistics 414 __STATS__( false, 415 io.submit_q.submit_avg.csm += 1; 416 io.submit_q.submit_avg.cnt += 1; 417 ) 418 419 // Release the consumed SQEs 420 __release_consumed_submission( ring ); 421 422 unlock(ring.submit_q.lock); 423 424 __cfadbg_print_safe( io, "Kernel I/O : Performed io_submit for %p, returned %d\n", active_thread(), ret ); 425 } 426 } 427 428 static unsigned __collect_submitions( struct __io_data & ring ) { 429 /* paranoid */ verify( ring.submit_q.ready != 0p ); 430 /* paranoid */ verify( ring.submit_q.ready_cnt > 0 ); 431 432 unsigned to_submit = 0; 433 uint32_t tail = *ring.submit_q.tail; 651 434 const uint32_t mask = *ring.submit_q.mask; 652 435 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 ); 675 } 676 677 static inline void ?{}(struct io_uring_sqe & this, uint8_t opcode, int fd) { 678 this.opcode = opcode; 679 #if !defined(IOSQE_ASYNC) 680 this.flags = 0; 681 #else 682 this.flags = IOSQE_ASYNC; 683 #endif 684 this.ioprio = 0; 685 this.fd = fd; 686 this.off = 0; 687 this.addr = 0; 688 this.len = 0; 689 this.rw_flags = 0; 690 this.__pad2[0] = this.__pad2[1] = this.__pad2[2] = 0; 691 } 692 693 static inline void ?{}(struct io_uring_sqe & this, uint8_t opcode, int fd, void * addr, uint32_t len, uint64_t off ) { 694 (this){ opcode, fd }; 695 this.off = off; 696 this.addr = (uint64_t)addr; 697 this.len = len; 698 } 699 700 701 //============================================================================================= 702 // I/O Interface 703 //============================================================================================= 704 705 #define __submit_prelude \ 706 struct __io_data & ring = *active_cluster()->io; \ 707 struct io_uring_sqe * sqe; \ 708 uint32_t idx; \ 709 [sqe, idx] = __submit_alloc( ring ); 710 711 #define __submit_wait \ 712 io_user_data data = { 0, active_thread() }; \ 713 /*__cfaabi_bits_print_safe( STDERR_FILENO, "Preparing user data %p for %p\n", &data, data.thrd );*/ \ 714 sqe->user_data = (uint64_t)&data; \ 715 __submit( ring, idx ); \ 716 park( __cfaabi_dbg_ctx ); \ 717 return data.result; 436 // Go through the list of ready submissions 437 for( i; ring.submit_q.ready_cnt ) { 438 // replace any submission with the sentinel, to consume it. 439 uint32_t idx = __atomic_exchange_n( &ring.submit_q.ready[i], -1ul32, __ATOMIC_RELAXED); 440 441 // If it was already the sentinel, then we are done 442 if( idx == -1ul32 ) continue; 443 444 // If we got a real submission, append it to the list 445 ring.submit_q.array[ (tail + to_submit) & mask ] = idx & mask; 446 to_submit++; 447 } 448 449 // Increment the tail based on how many we are ready to submit 450 __atomic_fetch_add(ring.submit_q.tail, to_submit, __ATOMIC_SEQ_CST); 451 452 return to_submit; 453 } 454 455 static uint32_t __release_consumed_submission( struct __io_data & ring ) { 456 const uint32_t smask = *ring.submit_q.mask; 457 458 if( !try_lock(ring.submit_q.release_lock __cfaabi_dbg_ctx2) ) return 0; 459 uint32_t chead = *ring.submit_q.head; 460 uint32_t phead = ring.submit_q.prev_head; 461 ring.submit_q.prev_head = chead; 462 unlock(ring.submit_q.release_lock); 463 464 uint32_t count = chead - phead; 465 for( i; count ) { 466 uint32_t idx = ring.submit_q.array[ (phead + i) & smask ]; 467 ring.submit_q.sqes[ idx ].user_data = 0; 468 } 469 return count; 470 } 718 471 #endif 719 720 // Some forward declarations721 extern "C" {722 #include <unistd.h>723 #include <sys/types.h>724 #include <sys/socket.h>725 #include <sys/syscall.h>726 727 #if defined(HAVE_PREADV2)728 struct iovec;729 extern ssize_t preadv2 (int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags);730 #endif731 #if defined(HAVE_PWRITEV2)732 struct iovec;733 extern ssize_t pwritev2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags);734 #endif735 736 extern int fsync(int fd);737 extern int sync_file_range(int fd, int64_t offset, int64_t nbytes, unsigned int flags);738 739 struct msghdr;740 struct sockaddr;741 extern ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);742 extern ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);743 extern ssize_t send(int sockfd, const void *buf, size_t len, int flags);744 extern ssize_t recv(int sockfd, void *buf, size_t len, int flags);745 extern int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);746 extern int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);747 748 extern int fallocate(int fd, int mode, uint64_t offset, uint64_t len);749 extern int posix_fadvise(int fd, uint64_t offset, uint64_t len, int advice);750 extern int madvise(void *addr, size_t length, int advice);751 752 extern int openat(int dirfd, const char *pathname, int flags, mode_t mode);753 extern int close(int fd);754 755 extern ssize_t read (int fd, void *buf, size_t count);756 }757 758 //-----------------------------------------------------------------------------759 // Asynchronous operations760 #if defined(HAVE_PREADV2)761 ssize_t cfa_preadv2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags) {762 #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_READV)763 return preadv2(fd, iov, iovcnt, offset, flags);764 #else765 __submit_prelude766 767 (*sqe){ IORING_OP_READV, fd, iov, iovcnt, offset };768 769 __submit_wait770 #endif771 }772 #endif773 774 #if defined(HAVE_PWRITEV2)775 ssize_t cfa_pwritev2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags) {776 #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_WRITEV)777 return pwritev2(fd, iov, iovcnt, offset, flags);778 #else779 __submit_prelude780 781 (*sqe){ IORING_OP_WRITEV, fd, iov, iovcnt, offset };782 783 __submit_wait784 #endif785 }786 #endif787 788 int cfa_fsync(int fd) {789 #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_FSYNC)790 return fsync(fd);791 #else792 __submit_prelude793 794 (*sqe){ IORING_OP_FSYNC, fd };795 796 __submit_wait797 #endif798 }799 800 int cfa_sync_file_range(int fd, int64_t offset, int64_t nbytes, unsigned int flags) {801 #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_SYNC_FILE_RANGE)802 return sync_file_range(fd, offset, nbytes, flags);803 #else804 __submit_prelude805 806 (*sqe){ IORING_OP_SYNC_FILE_RANGE, fd };807 sqe->off = offset;808 sqe->len = nbytes;809 sqe->sync_range_flags = flags;810 811 __submit_wait812 #endif813 }814 815 816 ssize_t cfa_sendmsg(int sockfd, const struct msghdr *msg, int flags) {817 #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_SENDMSG)818 return sendmsg(sockfd, msg, flags);819 #else820 __submit_prelude821 822 (*sqe){ IORING_OP_SENDMSG, sockfd, msg, 1, 0 };823 sqe->msg_flags = flags;824 825 __submit_wait826 #endif827 }828 829 ssize_t cfa_recvmsg(int sockfd, struct msghdr *msg, int flags) {830 #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_RECVMSG)831 return recvmsg(sockfd, msg, flags);832 #else833 __submit_prelude834 835 (*sqe){ IORING_OP_RECVMSG, sockfd, msg, 1, 0 };836 sqe->msg_flags = flags;837 838 __submit_wait839 #endif840 }841 842 ssize_t cfa_send(int sockfd, const void *buf, size_t len, int flags) {843 #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_SEND)844 return send( sockfd, buf, len, flags );845 #else846 __submit_prelude847 848 (*sqe){ IORING_OP_SEND, sockfd };849 sqe->addr = (uint64_t)buf;850 sqe->len = len;851 sqe->msg_flags = flags;852 853 __submit_wait854 #endif855 }856 857 ssize_t cfa_recv(int sockfd, void *buf, size_t len, int flags) {858 #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_RECV)859 return recv( sockfd, buf, len, flags );860 #else861 __submit_prelude862 863 (*sqe){ IORING_OP_RECV, sockfd };864 sqe->addr = (uint64_t)buf;865 sqe->len = len;866 sqe->msg_flags = flags;867 868 __submit_wait869 #endif870 }871 872 int cfa_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) {873 #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_ACCEPT)874 return accept4( sockfd, addr, addrlen, flags );875 #else876 __submit_prelude877 878 (*sqe){ IORING_OP_ACCEPT, sockfd };879 sqe->addr = addr;880 sqe->addr2 = addrlen;881 sqe->accept_flags = flags;882 883 __submit_wait884 #endif885 }886 887 int cfa_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {888 #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_CONNECT)889 return connect( sockfd, addr, addrlen );890 #else891 __submit_prelude892 893 (*sqe){ IORING_OP_CONNECT, sockfd };894 sqe->addr = (uint64_t)addr;895 sqe->off = addrlen;896 897 __submit_wait898 #endif899 }900 901 int cfa_fallocate(int fd, int mode, uint64_t offset, uint64_t len) {902 #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_FALLOCATE)903 return fallocate( fd, mode, offset, len );904 #else905 __submit_prelude906 907 (*sqe){ IORING_OP_FALLOCATE, fd };908 sqe->off = offset;909 sqe->len = length;910 sqe->mode = mode;911 912 __submit_wait913 #endif914 }915 916 int cfa_fadvise(int fd, uint64_t offset, uint64_t len, int advice) {917 #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_FADVISE)918 return posix_fadvise( fd, offset, len, advice );919 #else920 __submit_prelude921 922 (*sqe){ IORING_OP_FADVISE, fd };923 sqe->off = (uint64_t)offset;924 sqe->len = length;925 sqe->fadvise_advice = advice;926 927 __submit_wait928 #endif929 }930 931 int cfa_madvise(void *addr, size_t length, int advice) {932 #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_MADVISE)933 return madvise( addr, length, advice );934 #else935 __submit_prelude936 937 (*sqe){ IORING_OP_MADVISE, 0 };938 sqe->addr = (uint64_t)addr;939 sqe->len = length;940 sqe->fadvise_advice = advice;941 942 __submit_wait943 #endif944 }945 946 int cfa_openat(int dirfd, const char *pathname, int flags, mode_t mode) {947 #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_OPENAT)948 return openat( dirfd, pathname, flags, mode );949 #else950 __submit_prelude951 952 (*sqe){ IORING_OP_OPENAT, dirfd };953 sqe->addr = (uint64_t)pathname;954 sqe->open_flags = flags;955 sqe->mode = mode;956 957 __submit_wait958 #endif959 }960 961 int cfa_close(int fd) {962 #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_CLOSE)963 return close( fd );964 #else965 __submit_prelude966 967 (*sqe){ IORING_OP_CLOSE, fd };968 969 __submit_wait970 #endif971 }972 973 974 ssize_t cfa_read(int fd, void *buf, size_t count) {975 #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_READ)976 return read( fd, buf, count );977 #else978 __submit_prelude979 980 (*sqe){ IORING_OP_READ, fd, buf, count, 0 };981 982 __submit_wait983 #endif984 }985 986 ssize_t cfa_write(int fd, void *buf, size_t count) {987 #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_WRITE)988 return read( fd, buf, count );989 #else990 __submit_prelude991 992 (*sqe){ IORING_OP_WRITE, fd, buf, count, 0 };993 994 __submit_wait995 #endif996 }997 998 //-----------------------------------------------------------------------------999 // Check if a function is asynchronous1000 1001 // Macro magic to reduce the size of the following switch case1002 #define IS_DEFINED_APPLY(f, ...) f(__VA_ARGS__)1003 #define IS_DEFINED_SECOND(first, second, ...) second1004 #define IS_DEFINED_TEST(expansion) _CFA_IO_FEATURE_##expansion1005 #define IS_DEFINED(macro) IS_DEFINED_APPLY( IS_DEFINED_SECOND,IS_DEFINED_TEST(macro) false, true)1006 1007 bool has_user_level_blocking( fptr_t func ) {1008 #if defined(HAVE_LINUX_IO_URING_H)1009 #if defined(HAVE_PREADV2)1010 if( /*func == (fptr_t)preadv2 || */1011 func == (fptr_t)cfa_preadv2 )1012 #define _CFA_IO_FEATURE_IORING_OP_READV ,1013 return IS_DEFINED(IORING_OP_READV);1014 #endif1015 1016 #if defined(HAVE_PWRITEV2)1017 if( /*func == (fptr_t)pwritev2 || */1018 func == (fptr_t)cfa_pwritev2 )1019 #define _CFA_IO_FEATURE_IORING_OP_WRITEV ,1020 return IS_DEFINED(IORING_OP_WRITEV);1021 #endif1022 1023 if( /*func == (fptr_t)fsync || */1024 func == (fptr_t)cfa_fsync )1025 #define _CFA_IO_FEATURE_IORING_OP_FSYNC ,1026 return IS_DEFINED(IORING_OP_FSYNC);1027 1028 if( /*func == (fptr_t)ync_file_range || */1029 func == (fptr_t)cfa_sync_file_range )1030 #define _CFA_IO_FEATURE_IORING_OP_SYNC_FILE_RANGE ,1031 return IS_DEFINED(IORING_OP_SYNC_FILE_RANGE);1032 1033 if( /*func == (fptr_t)sendmsg || */1034 func == (fptr_t)cfa_sendmsg )1035 #define _CFA_IO_FEATURE_IORING_OP_SENDMSG ,1036 return IS_DEFINED(IORING_OP_SENDMSG);1037 1038 if( /*func == (fptr_t)recvmsg || */1039 func == (fptr_t)cfa_recvmsg )1040 #define _CFA_IO_FEATURE_IORING_OP_RECVMSG ,1041 return IS_DEFINED(IORING_OP_RECVMSG);1042 1043 if( /*func == (fptr_t)send || */1044 func == (fptr_t)cfa_send )1045 #define _CFA_IO_FEATURE_IORING_OP_SEND ,1046 return IS_DEFINED(IORING_OP_SEND);1047 1048 if( /*func == (fptr_t)recv || */1049 func == (fptr_t)cfa_recv )1050 #define _CFA_IO_FEATURE_IORING_OP_RECV ,1051 return IS_DEFINED(IORING_OP_RECV);1052 1053 if( /*func == (fptr_t)accept4 || */1054 func == (fptr_t)cfa_accept4 )1055 #define _CFA_IO_FEATURE_IORING_OP_ACCEPT ,1056 return IS_DEFINED(IORING_OP_ACCEPT);1057 1058 if( /*func == (fptr_t)connect || */1059 func == (fptr_t)cfa_connect )1060 #define _CFA_IO_FEATURE_IORING_OP_CONNECT ,1061 return IS_DEFINED(IORING_OP_CONNECT);1062 1063 if( /*func == (fptr_t)fallocate || */1064 func == (fptr_t)cfa_fallocate )1065 #define _CFA_IO_FEATURE_IORING_OP_FALLOCATE ,1066 return IS_DEFINED(IORING_OP_FALLOCATE);1067 1068 if( /*func == (fptr_t)posix_fadvise || */1069 func == (fptr_t)cfa_fadvise )1070 #define _CFA_IO_FEATURE_IORING_OP_FADVISE ,1071 return IS_DEFINED(IORING_OP_FADVISE);1072 1073 if( /*func == (fptr_t)madvise || */1074 func == (fptr_t)cfa_madvise )1075 #define _CFA_IO_FEATURE_IORING_OP_MADVISE ,1076 return IS_DEFINED(IORING_OP_MADVISE);1077 1078 if( /*func == (fptr_t)openat || */1079 func == (fptr_t)cfa_openat )1080 #define _CFA_IO_FEATURE_IORING_OP_OPENAT ,1081 return IS_DEFINED(IORING_OP_OPENAT);1082 1083 if( /*func == (fptr_t)close || */1084 func == (fptr_t)cfa_close )1085 #define _CFA_IO_FEATURE_IORING_OP_CLOSE ,1086 return IS_DEFINED(IORING_OP_CLOSE);1087 1088 if( /*func == (fptr_t)read || */1089 func == (fptr_t)cfa_read )1090 #define _CFA_IO_FEATURE_IORING_OP_READ ,1091 return IS_DEFINED(IORING_OP_READ);1092 1093 if( /*func == (fptr_t)write || */1094 func == (fptr_t)cfa_write )1095 #define _CFA_IO_FEATURE_IORING_OP_WRITE ,1096 return IS_DEFINED(IORING_OP_WRITE);1097 #endif1098 1099 return false;1100 } -
libcfa/src/concurrency/iofwd.hfa
r07d867b r22f94a4 16 16 #pragma once 17 17 18 ssize_t cfa_preadv2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags); 19 ssize_t cfa_pwritev2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags); 20 int cfa_fsync(int fd); 21 int cfa_sync_file_range(int fd, int64_t offset, int64_t nbytes, unsigned int flags); 22 ssize_t cfa_sendmsg(int sockfd, const struct msghdr *msg, int flags); 23 ssize_t cfa_recvmsg(int sockfd, struct msghdr *msg, int flags); 24 ssize_t cfa_send(int sockfd, const void *buf, size_t len, int flags); 25 ssize_t cfa_recv(int sockfd, void *buf, size_t len, int flags); 26 int cfa_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags); 27 int cfa_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 28 int cfa_fallocate(int fd, int mode, uint64_t offset, uint64_t len); 29 int cfa_fadvise(int fd, uint64_t offset, uint64_t len, int advice); 30 int cfa_madvise(void *addr, size_t length, int advice); 31 int cfa_openat(int dirfd, const char *pathname, int flags, mode_t mode); 32 int cfa_close(int fd); 33 int cfa_statx(int dirfd, const char *pathname, int flags, unsigned int mask, struct statx *statxbuf); 34 ssize_t cfa_read(int fd, void *buf, size_t count); 35 ssize_t cfa_write(int fd, void *buf, size_t count) 18 #include <unistd.h> 19 extern "C" { 20 #include <sys/types.h> 21 #if CFA_HAVE_LINUX_IO_URING_H 22 #include <linux/io_uring.h> 23 #endif 24 } 25 #include "bits/defs.hfa" 26 #include "time.hfa" 27 28 #if defined(CFA_HAVE_IOSQE_FIXED_FILE) 29 #define CFA_IO_FIXED_FD1 IOSQE_FIXED_FILE 30 #endif 31 #if defined(CFA_HAVE_SPLICE_F_FD_IN_FIXED) 32 #define CFA_IO_FIXED_FD2 SPLICE_F_FD_IN_FIXED 33 #endif 34 #if defined(CFA_HAVE_IOSQE_IO_DRAIN) 35 #define CFA_IO_DRAIN IOSQE_IO_DRAIN 36 #endif 37 #if defined(CFA_HAVE_IOSQE_ASYNC) 38 #define CFA_IO_ASYNC IOSQE_ASYNC 39 #endif 40 41 struct cluster; 42 struct io_context; 43 struct io_cancellation; 44 45 struct iovec; 46 struct msghdr; 47 struct sockaddr; 48 struct statx; 49 50 extern ssize_t cfa_preadv2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 51 extern ssize_t cfa_pwritev2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 52 extern int cfa_fsync(int fd, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 53 extern int cfa_sync_file_range(int fd, int64_t offset, int64_t nbytes, unsigned int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 54 extern ssize_t cfa_sendmsg(int sockfd, const struct msghdr *msg, int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 55 extern ssize_t cfa_recvmsg(int sockfd, struct msghdr *msg, int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 56 extern ssize_t cfa_send(int sockfd, const void *buf, size_t len, int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 57 extern ssize_t cfa_recv(int sockfd, void *buf, size_t len, int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 58 extern int cfa_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 59 extern int cfa_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 60 extern int cfa_fallocate(int fd, int mode, uint64_t offset, uint64_t len, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 61 extern int cfa_fadvise(int fd, uint64_t offset, uint64_t len, int advice, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 62 extern int cfa_madvise(void *addr, size_t length, int advice, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 63 extern int cfa_openat(int dirfd, const char *pathname, int flags, mode_t mode, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 64 extern int cfa_close(int fd, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 65 extern int cfa_statx(int dirfd, const char *pathname, int flags, unsigned int mask, struct statx *statxbuf, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 66 extern ssize_t cfa_read(int fd, void *buf, size_t count, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 67 extern ssize_t cfa_write(int fd, void *buf, size_t count, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 68 extern ssize_t cfa_splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 69 extern ssize_t cfa_tee(int fd_in, int fd_out, size_t len, unsigned int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 36 70 37 71 //----------------------------------------------------------------------------- 38 72 // Check if a function is blocks a only the user thread 39 73 bool has_user_level_blocking( fptr_t func ); 74 75 //----------------------------------------------------------------------------- 76 void register_fixed_files( io_context & ctx , int * files, unsigned count ); 77 void register_fixed_files( cluster & cltr, int * files, unsigned count ); -
libcfa/src/concurrency/kernel.cfa
r07d867b r22f94a4 10 10 // Created On : Tue Jan 17 12:27:26 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : T ue Feb 4 13:03:15202013 // Update Count : 5812 // Last Modified On : Thu Jul 9 06:22:54 2020 13 // Update Count : 66 14 14 // 15 15 … … 18 18 19 19 //C Includes 20 #include <stddef.h>21 20 #include <errno.h> 22 #include <string.h>23 extern "C" {24 21 #include <stdio.h> 25 #include <fenv.h>26 #include <sys/resource.h>27 22 #include <signal.h> 28 23 #include <unistd.h> 29 #include <limits.h> // PTHREAD_STACK_MIN30 #include <sys/mman.h> // mprotect31 }32 24 33 25 //CFA Includes 34 #include "time.hfa"35 26 #include "kernel_private.hfa" 36 27 #include "preemption.hfa" 37 #include "startup.hfa"38 28 39 29 //Private includes … … 45 35 // Some assembly required 46 36 #if defined( __i386 ) 47 #define CtxGet( ctx ) \48 __asm__ volatile ( \49 "movl %%esp,%0\n"\50 "movl %%ebp,%1\n"\51 : "=rm" (ctx.SP),\52 "=rm" (ctx.FP) \53 )54 55 37 // mxcr : SSE Status and Control bits (control bits are preserved across function calls) 56 38 // fcw : X87 FPU control word (preserved across function calls) … … 74 56 75 57 #elif defined( __x86_64 ) 76 #define CtxGet( ctx ) \77 __asm__ volatile ( \78 "movq %%rsp,%0\n"\79 "movq %%rbp,%1\n"\80 : "=rm" (ctx.SP),\81 "=rm" (ctx.FP) \82 )83 84 58 #define __x87_store \ 85 59 uint32_t __mxcr; \ … … 102 76 103 77 #elif defined( __ARM_ARCH ) 104 #define CtxGet( ctx ) __asm__ ( \105 "mov %0,%%sp\n" \106 "mov %1,%%r11\n" \107 : "=rm" (ctx.SP), "=rm" (ctx.FP) )108 78 #else 109 79 #error unknown hardware architecture 110 80 #endif 111 81 112 //----------------------------------------------------------------------------- 113 //Start and stop routine for the kernel, declared first to make sure they run first 114 static void __kernel_startup (void) __attribute__(( constructor( STARTUP_PRIORITY_KERNEL ) )); 115 static void __kernel_shutdown(void) __attribute__(( destructor ( STARTUP_PRIORITY_KERNEL ) )); 82 extern $thread * mainThread; 83 extern processor * mainProcessor; 116 84 117 85 //----------------------------------------------------------------------------- 118 86 // Kernel Scheduling logic 119 87 static $thread * __next_thread(cluster * this); 88 static $thread * __next_thread_slow(cluster * this); 120 89 static void __run_thread(processor * this, $thread * dst); 121 static $thread * __halt(processor * this); 122 static bool __wake_one(cluster * cltr, bool was_empty); 123 static bool __wake_proc(processor *); 124 125 //----------------------------------------------------------------------------- 126 // Kernel storage 127 KERNEL_STORAGE(cluster, mainCluster); 128 KERNEL_STORAGE(processor, mainProcessor); 129 KERNEL_STORAGE($thread, mainThread); 130 KERNEL_STORAGE(__stack_t, mainThreadCtx); 131 132 cluster * mainCluster; 133 processor * mainProcessor; 134 $thread * mainThread; 135 136 extern "C" { 137 struct { __dllist_t(cluster) list; __spinlock_t lock; } __cfa_dbg_global_clusters; 138 } 139 140 size_t __page_size = 0; 141 142 //----------------------------------------------------------------------------- 143 // Global state 144 thread_local struct KernelThreadData kernelTLS __attribute__ ((tls_model ( "initial-exec" ))) = { 145 NULL, // cannot use 0p 146 NULL, 147 { 1, false, false }, 148 6u //this should be seeded better but due to a bug calling rdtsc doesn't work 149 }; 150 151 //----------------------------------------------------------------------------- 152 // Struct to steal stack 153 struct current_stack_info_t { 154 __stack_t * storage; // pointer to stack object 155 void * base; // base of stack 156 void * limit; // stack grows towards stack limit 157 void * context; // address of cfa_context_t 158 }; 159 160 void ?{}( current_stack_info_t & this ) { 161 __stack_context_t ctx; 162 CtxGet( ctx ); 163 this.base = ctx.FP; 164 165 rlimit r; 166 getrlimit( RLIMIT_STACK, &r); 167 size_t size = r.rlim_cur; 168 169 this.limit = (void *)(((intptr_t)this.base) - size); 170 this.context = &storage_mainThreadCtx; 171 } 172 173 //----------------------------------------------------------------------------- 174 // Main thread construction 175 176 void ?{}( $coroutine & this, current_stack_info_t * info) with( this ) { 177 stack.storage = info->storage; 178 with(*stack.storage) { 179 limit = info->limit; 180 base = info->base; 181 } 182 __attribute__((may_alias)) intptr_t * istorage = (intptr_t*) &stack.storage; 183 *istorage |= 0x1; 184 name = "Main Thread"; 185 state = Start; 186 starter = 0p; 187 last = 0p; 188 cancellation = 0p; 189 } 190 191 void ?{}( $thread & this, current_stack_info_t * info) with( this ) { 192 state = Start; 193 self_cor{ info }; 194 curr_cor = &self_cor; 195 curr_cluster = mainCluster; 196 self_mon.owner = &this; 197 self_mon.recursion = 1; 198 self_mon_p = &self_mon; 199 next = 0p; 200 201 node.next = 0p; 202 node.prev = 0p; 203 doregister(curr_cluster, this); 204 205 monitors{ &self_mon_p, 1, (fptr_t)0 }; 206 } 207 208 //----------------------------------------------------------------------------- 209 // Processor coroutine 210 void ?{}(processorCtx_t & this) { 211 212 } 213 214 // Construct the processor context of non-main processors 215 static void ?{}(processorCtx_t & this, processor * proc, current_stack_info_t * info) { 216 (this.__cor){ info }; 217 this.proc = proc; 218 } 219 220 static void * __invoke_processor(void * arg); 221 222 void ?{}(processor & this, const char name[], cluster & cltr) with( this ) { 223 this.name = name; 224 this.cltr = &cltr; 225 terminated{ 0 }; 226 destroyer = 0p; 227 do_terminate = false; 228 preemption_alarm = 0p; 229 pending_preemption = false; 230 runner.proc = &this; 231 232 idle{}; 233 234 __cfadbg_print_safe(runtime_core, "Kernel : Starting core %p\n", &this); 235 236 this.stack = __create_pthread( &this.kernel_thread, __invoke_processor, (void *)&this ); 237 238 __cfadbg_print_safe(runtime_core, "Kernel : core %p created\n", &this); 239 } 240 241 void ^?{}(processor & this) with( this ){ 242 if( ! __atomic_load_n(&do_terminate, __ATOMIC_ACQUIRE) ) { 243 __cfadbg_print_safe(runtime_core, "Kernel : core %p signaling termination\n", &this); 244 245 __atomic_store_n(&do_terminate, true, __ATOMIC_RELAXED); 246 __wake_proc( &this ); 247 248 P( terminated ); 249 verify( kernelTLS.this_processor != &this); 250 } 251 252 int err = pthread_join( kernel_thread, 0p ); 253 if( err != 0 ) abort("KERNEL ERROR: joining processor %p caused error %s\n", &this, strerror(err)); 254 255 free( this.stack ); 256 } 257 258 void ?{}(cluster & this, const char name[], Duration preemption_rate, int io_flags) with( this ) { 259 this.name = name; 260 this.preemption_rate = preemption_rate; 261 ready_queue{}; 262 ready_queue_lock{}; 263 264 #if !defined(__CFA_NO_STATISTICS__) 265 print_stats = false; 266 #endif 267 268 procs{ __get }; 269 idles{ __get }; 270 threads{ __get }; 271 272 __kernel_io_startup( this, io_flags, &this == mainCluster ); 273 274 doregister(this); 275 } 276 277 void ^?{}(cluster & this) { 278 __kernel_io_shutdown( this, &this == mainCluster ); 279 280 unregister(this); 281 } 90 static void __wake_one(struct __processor_id_t * id, cluster * cltr); 91 92 static void push (__cluster_idles & idles, processor & proc); 93 static void remove(__cluster_idles & idles, processor & proc); 94 static [unsigned idle, unsigned total, * processor] query( & __cluster_idles idles ); 95 282 96 283 97 //============================================================================================= … … 294 108 295 109 __cfadbg_print_safe(runtime_core, "Kernel : core %p starting\n", this); 296 297 doregister(this->cltr, this); 110 #if !defined(__CFA_NO_STATISTICS__) 111 if( this->print_halts ) { 112 __cfaabi_bits_print_safe( STDOUT_FILENO, "Processor : %d - %s (%p)\n", this->id, this->name, (void*)this); 113 } 114 #endif 298 115 299 116 { … … 304 121 305 122 $thread * readyThread = 0p; 306 for( unsigned int spin_count = 0; ! __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST); spin_count++ ) { 123 MAIN_LOOP: 124 for() { 307 125 // Try to get the next thread 308 126 readyThread = __next_thread( this->cltr ); 309 127 310 // If no ready thread 311 if( readyThread == 0p ) { 312 // Block until a thread is ready 313 readyThread = __halt(this); 128 if( !readyThread ) { 129 readyThread = __next_thread_slow( this->cltr ); 314 130 } 315 131 316 // Check if we actually found a thread 317 if( readyThread ) { 318 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 319 /* paranoid */ verifyf( readyThread->state == Ready || readyThread->preempted != __NO_PREEMPTION, "state : %d, preempted %d\n", readyThread->state, readyThread->preempted); 320 /* paranoid */ verifyf( readyThread->next == 0p, "Expected null got %p", readyThread->next ); 321 322 // We found a thread run it 323 __run_thread(this, readyThread); 324 325 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 132 HALT: 133 if( !readyThread ) { 134 // Don't block if we are done 135 if( __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST) ) break MAIN_LOOP; 136 137 #if !defined(__CFA_NO_STATISTICS__) 138 __tls_stats()->ready.sleep.halts++; 139 #endif 140 141 // Push self to idle stack 142 push(this->cltr->idles, * this); 143 144 // Confirm the ready-queue is empty 145 readyThread = __next_thread_slow( this->cltr ); 146 if( readyThread ) { 147 // A thread was found, cancel the halt 148 remove(this->cltr->idles, * this); 149 150 #if !defined(__CFA_NO_STATISTICS__) 151 __tls_stats()->ready.sleep.cancels++; 152 #endif 153 154 // continue the mai loop 155 break HALT; 156 } 157 158 #if !defined(__CFA_NO_STATISTICS__) 159 if(this->print_halts) { 160 __cfaabi_bits_print_safe( STDOUT_FILENO, "PH:%d - %lld 0\n", this->id, rdtscl()); 161 } 162 #endif 163 164 wait( this->idle ); 165 166 #if !defined(__CFA_NO_STATISTICS__) 167 if(this->print_halts) { 168 __cfaabi_bits_print_safe( STDOUT_FILENO, "PH:%d - %lld 1\n", this->id, rdtscl()); 169 } 170 #endif 171 172 // We were woken up, remove self from idle 173 remove(this->cltr->idles, * this); 174 175 // DON'T just proceed, start looking again 176 continue MAIN_LOOP; 326 177 } 178 179 /* paranoid */ verify( readyThread ); 180 181 // We found a thread run it 182 __run_thread(this, readyThread); 183 184 // Are we done? 185 if( __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST) ) break MAIN_LOOP; 327 186 } 328 187 … … 330 189 } 331 190 332 unregister(this->cltr, this);333 334 191 V( this->terminated ); 335 192 193 if(this == mainProcessor) { 194 // HACK : the coroutine context switch expects this_thread to be set 195 // and it make sense for it to be set in all other cases except here 196 // fake it 197 kernelTLS.this_thread = mainThread; 198 } 199 336 200 __cfadbg_print_safe(runtime_core, "Kernel : core %p terminated\n", this); 337 338 // HACK : the coroutine context switch expects this_thread to be set339 // and it make sense for it to be set in all other cases except here340 // fake it341 if( this == mainProcessor ) kernelTLS.this_thread = mainThread;342 201 } 343 202 … … 349 208 // from the processor coroutine to the target thread 350 209 static void __run_thread(processor * this, $thread * thrd_dst) { 210 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 211 /* paranoid */ verifyf( thrd_dst->state == Ready || thrd_dst->preempted != __NO_PREEMPTION, "state : %d, preempted %d\n", thrd_dst->state, thrd_dst->preempted); 212 /* paranoid */ verifyf( thrd_dst->link.next == 0p, "Expected null got %p", thrd_dst->link.next ); 213 __builtin_prefetch( thrd_dst->context.SP ); 214 351 215 $coroutine * proc_cor = get_coroutine(this->runner); 352 216 … … 360 224 // Actually run the thread 361 225 RUNNING: while(true) { 362 if(unlikely(thrd_dst->preempted)) { 363 thrd_dst->preempted = __NO_PREEMPTION; 364 verify(thrd_dst->state == Active || thrd_dst->state == Rerun); 365 } else { 366 verify(thrd_dst->state == Blocked || thrd_dst->state == Ready); // Ready means scheduled normally, blocked means rerun 367 thrd_dst->state = Active; 368 } 226 thrd_dst->preempted = __NO_PREEMPTION; 227 thrd_dst->state = Active; 369 228 370 229 __cfaabi_dbg_debug_do( … … 374 233 375 234 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 235 /* paranoid */ verify( kernelTLS.this_thread == thrd_dst ); 376 236 /* 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 237 /* 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 244 /* 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 245 /* 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 ); 246 /* paranoid */ verify( kernelTLS.this_thread == thrd_dst ); 386 247 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 387 248 … … 396 257 if(unlikely(thrd_dst->preempted != __NO_PREEMPTION)) { 397 258 // The thread was preempted, reschedule it and reset the flag 398 __schedule_thread( thrd_dst );259 __schedule_thread( (__processor_id_t*)this, thrd_dst ); 399 260 break RUNNING; 400 261 } 401 262 263 if(unlikely(thrd_dst->state == Halted)) { 264 // The thread has halted, it should never be scheduled/run again 265 // We may need to wake someone up here since 266 unpark( this->destroyer __cfaabi_dbg_ctx2 ); 267 this->destroyer = 0p; 268 break RUNNING; 269 } 270 271 /* paranoid */ verify( thrd_dst->state == Active ); 272 thrd_dst->state = Blocked; 273 402 274 // set state of processor coroutine to active and the thread to inactive 403 static_assert(sizeof(thrd_dst->state) == sizeof(int)); 404 enum coroutine_state old_state = __atomic_exchange_n(&thrd_dst->state, Blocked, __ATOMIC_SEQ_CST); 405 __cfaabi_dbg_debug_do( thrd_dst->park_result = old_state; ) 406 switch(old_state) { 407 case Halted: 408 // The thread has halted, it should never be scheduled/run again, leave it back to Halted and move on 409 thrd_dst->state = Halted; 410 411 // We may need to wake someone up here since 412 unpark( this->destroyer __cfaabi_dbg_ctx2 ); 413 this->destroyer = 0p; 414 break RUNNING; 415 case Active: 275 int old_ticket = __atomic_fetch_sub(&thrd_dst->ticket, 1, __ATOMIC_SEQ_CST); 276 __cfaabi_dbg_debug_do( thrd_dst->park_result = old_ticket; ) 277 switch(old_ticket) { 278 case 1: 416 279 // This is case 1, the regular case, nothing more is needed 417 280 break RUNNING; 418 case Rerun:281 case 2: 419 282 // This is case 2, the racy case, someone tried to run this thread before it finished blocking 420 283 // In this case, just run it again. … … 422 285 default: 423 286 // This makes no sense, something is wrong abort 424 abort( "Finished running a thread that was Blocked/Start/Primed %d\n", old_state);287 abort(); 425 288 } 426 289 } … … 429 292 proc_cor->state = Active; 430 293 kernelTLS.this_thread = 0p; 294 295 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 431 296 } 432 297 … … 436 301 $coroutine * proc_cor = get_coroutine(kernelTLS.this_processor->runner); 437 302 $thread * thrd_src = kernelTLS.this_thread; 303 304 #if !defined(__CFA_NO_STATISTICS__) 305 struct processor * last_proc = kernelTLS.this_processor; 306 #endif 438 307 439 308 // Run the thread on this processor … … 451 320 } 452 321 322 #if !defined(__CFA_NO_STATISTICS__) 323 if(last_proc != kernelTLS.this_processor) { 324 __tls_stats()->ready.threads.migration++; 325 } 326 #endif 327 453 328 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 454 329 /* paranoid */ verifyf( ((uintptr_t)thrd_src->context.SP) < ((uintptr_t)__get_stack(thrd_src->curr_cor)->base ), "ERROR : Returning $thread %p has been corrupted.\n StackPointer too small.\n", thrd_src ); 455 330 /* paranoid */ verifyf( ((uintptr_t)thrd_src->context.SP) > ((uintptr_t)__get_stack(thrd_src->curr_cor)->limit), "ERROR : Returning $thread %p has been corrupted.\n StackPointer too large.\n", thrd_src ); 456 }457 458 // KERNEL_ONLY459 // Context invoker for processors460 // This is the entry point for processors (kernel threads)461 // It effectively constructs a coroutine by stealing the pthread stack462 static void * __invoke_processor(void * arg) {463 processor * proc = (processor *) arg;464 kernelTLS.this_processor = proc;465 kernelTLS.this_thread = 0p;466 kernelTLS.preemption_state.[enabled, disable_count] = [false, 1];467 // SKULLDUGGERY: We want to create a context for the processor coroutine468 // which is needed for the 2-step context switch. However, there is no reason469 // to waste the perfectly valid stack create by pthread.470 current_stack_info_t info;471 __stack_t ctx;472 info.storage = &ctx;473 (proc->runner){ proc, &info };474 475 __cfaabi_dbg_print_safe("Coroutine : created stack %p\n", get_coroutine(proc->runner)->stack.storage);476 477 //Set global state478 kernelTLS.this_thread = 0p;479 480 //We now have a proper context from which to schedule threads481 __cfadbg_print_safe(runtime_core, "Kernel : core %p created (%p, %p)\n", proc, &proc->runner, &ctx);482 483 // SKULLDUGGERY: Since the coroutine doesn't have its own stack, we can't484 // resume it to start it like it normally would, it will just context switch485 // back to here. Instead directly call the main since we already are on the486 // appropriate stack.487 get_coroutine(proc->runner)->state = Active;488 main( proc->runner );489 get_coroutine(proc->runner)->state = Halted;490 491 // Main routine of the core returned, the core is now fully terminated492 __cfadbg_print_safe(runtime_core, "Kernel : core %p main ended (%p)\n", proc, &proc->runner);493 494 return 0p;495 }496 497 static void Abort( int ret, const char func[] ) {498 if ( ret ) { // pthread routines return errno values499 abort( "%s : internal error, error(%d) %s.", func, ret, strerror( ret ) );500 } // if501 } // Abort502 503 void * __create_pthread( pthread_t * pthread, void * (*start)(void *), void * arg ) {504 pthread_attr_t attr;505 506 Abort( pthread_attr_init( &attr ), "pthread_attr_init" ); // initialize attribute507 508 size_t stacksize;509 // default stack size, normally defined by shell limit510 Abort( pthread_attr_getstacksize( &attr, &stacksize ), "pthread_attr_getstacksize" );511 assert( stacksize >= PTHREAD_STACK_MIN );512 513 void * stack;514 __cfaabi_dbg_debug_do(515 stack = memalign( __page_size, stacksize + __page_size );516 // pthread has no mechanism to create the guard page in user supplied stack.517 if ( mprotect( stack, __page_size, PROT_NONE ) == -1 ) {518 abort( "mprotect : internal error, mprotect failure, error(%d) %s.", errno, strerror( errno ) );519 } // if520 );521 __cfaabi_dbg_no_debug_do(522 stack = malloc( stacksize );523 );524 525 Abort( pthread_attr_setstack( &attr, stack, stacksize ), "pthread_attr_setstack" );526 527 Abort( pthread_create( pthread, &attr, start, arg ), "pthread_create" );528 return stack;529 }530 531 // KERNEL_ONLY532 static void __kernel_first_resume( processor * this ) {533 $thread * src = mainThread;534 $coroutine * dst = get_coroutine(this->runner);535 536 verify( ! kernelTLS.preemption_state.enabled );537 538 kernelTLS.this_thread->curr_cor = dst;539 __stack_prepare( &dst->stack, 65000 );540 __cfactx_start(main, dst, this->runner, __cfactx_invoke_coroutine);541 542 verify( ! kernelTLS.preemption_state.enabled );543 544 dst->last = &src->self_cor;545 dst->starter = dst->starter ? dst->starter : &src->self_cor;546 547 // make sure the current state is still correct548 /* paranoid */ verify(src->state == Ready);549 550 // context switch to specified coroutine551 verify( dst->context.SP );552 __cfactx_switch( &src->context, &dst->context );553 // when __cfactx_switch returns we are back in the src coroutine554 555 mainThread->curr_cor = &mainThread->self_cor;556 557 // make sure the current state has been update558 /* paranoid */ verify(src->state == Active);559 560 verify( ! kernelTLS.preemption_state.enabled );561 }562 563 // KERNEL_ONLY564 static void __kernel_last_resume( processor * this ) {565 $coroutine * src = &mainThread->self_cor;566 $coroutine * dst = get_coroutine(this->runner);567 568 verify( ! kernelTLS.preemption_state.enabled );569 verify( dst->starter == src );570 verify( dst->context.SP );571 572 // SKULLDUGGERY in debug the processors check that the573 // stack is still within the limit of the stack limits after running a thread.574 // that check doesn't make sense if we context switch to the processor using the575 // coroutine semantics. Since this is a special case, use the current context576 // info to populate these fields.577 __cfaabi_dbg_debug_do(578 __stack_context_t ctx;579 CtxGet( ctx );580 mainThread->context.SP = ctx.SP;581 mainThread->context.FP = ctx.FP;582 )583 584 // context switch to the processor585 __cfactx_switch( &src->context, &dst->context );586 331 } 587 332 … … 589 334 // Scheduler routines 590 335 // KERNEL ONLY 591 void __schedule_thread( $thread * thrd ) with( *thrd->curr_cluster ) { 336 void __schedule_thread( struct __processor_id_t * id, $thread * thrd ) { 337 /* paranoid */ verify( thrd ); 338 /* paranoid */ verify( thrd->state != Halted ); 592 339 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 593 340 /* paranoid */ #if defined( __CFA_WITH_VERIFY__ ) 594 /* paranoid */ if( thrd->state == Blocked || thrd->state == Start ) assertf( thrd->preempted == __NO_PREEMPTION,595 "Error inactive thread marked as preempted, state %d, preemption %d\n", thrd->state, thrd->preempted );596 /* paranoid */ if( thrd->preempted != __NO_PREEMPTION ) assertf(thrd->state == Active || thrd->state == Rerun,597 "Error preempted thread marked as not currently running, state %d, preemption %d\n", thrd->state, thrd->preempted );341 /* paranoid */ if( thrd->state == Blocked || thrd->state == Start ) assertf( thrd->preempted == __NO_PREEMPTION, 342 "Error inactive thread marked as preempted, state %d, preemption %d\n", thrd->state, thrd->preempted ); 343 /* paranoid */ if( thrd->preempted != __NO_PREEMPTION ) assertf(thrd->state == Active, 344 "Error preempted thread marked as not currently running, state %d, preemption %d\n", thrd->state, thrd->preempted ); 598 345 /* paranoid */ #endif 599 /* paranoid */ verifyf( thrd-> next == 0p, "Expected null got %p", thrd->next );346 /* paranoid */ verifyf( thrd->link.next == 0p, "Expected null got %p", thrd->link.next ); 600 347 601 348 if (thrd->preempted == __NO_PREEMPTION) thrd->state = Ready; 602 349 603 lock ( ready_queue_lock __cfaabi_dbg_ctx2 ); 604 bool was_empty = !(ready_queue != 0); 605 append( ready_queue, thrd ); 606 unlock( ready_queue_lock ); 607 608 __wake_one(thrd->curr_cluster, was_empty); 350 ready_schedule_lock ( id ); 351 push( thrd->curr_cluster, thrd ); 352 __wake_one(id, thrd->curr_cluster); 353 ready_schedule_unlock( id ); 609 354 610 355 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); … … 612 357 613 358 // KERNEL ONLY 614 static $thread * __next_thread(cluster * this) with( *this ) { 615 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 616 617 lock( ready_queue_lock __cfaabi_dbg_ctx2 ); 618 $thread * head = pop_head( ready_queue ); 619 unlock( ready_queue_lock ); 620 621 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 622 return head; 359 static inline $thread * __next_thread(cluster * this) with( *this ) { 360 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 361 362 ready_schedule_lock ( (__processor_id_t*)kernelTLS.this_processor ); 363 $thread * thrd = pop( this ); 364 ready_schedule_unlock( (__processor_id_t*)kernelTLS.this_processor ); 365 366 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 367 return thrd; 368 } 369 370 // KERNEL ONLY 371 static inline $thread * __next_thread_slow(cluster * this) with( *this ) { 372 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 373 374 ready_schedule_lock ( (__processor_id_t*)kernelTLS.this_processor ); 375 $thread * thrd = pop_slow( this ); 376 ready_schedule_unlock( (__processor_id_t*)kernelTLS.this_processor ); 377 378 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 379 return thrd; 623 380 } 624 381 625 382 // KERNEL ONLY unpark with out disabling interrupts 626 void __unpark( $thread * thrd __cfaabi_dbg_ctx_param2 ) { 627 static_assert(sizeof(thrd->state) == sizeof(int)); 628 383 void __unpark( struct __processor_id_t * id, $thread * thrd __cfaabi_dbg_ctx_param2 ) { 629 384 // record activity 630 385 __cfaabi_dbg_record_thrd( *thrd, false, caller ); 631 386 632 enum coroutine_state old_state = __atomic_exchange_n(&thrd->state, Rerun, __ATOMIC_SEQ_CST);633 __cfaabi_dbg_debug_do( thrd->unpark_result = old_ state; )634 switch(old_ state) {635 case Active:387 int old_ticket = __atomic_fetch_add(&thrd->ticket, 1, __ATOMIC_SEQ_CST); 388 __cfaabi_dbg_debug_do( thrd->unpark_result = old_ticket; thrd->unpark_state = thrd->state; ) 389 switch(old_ticket) { 390 case 1: 636 391 // Wake won the race, the thread will reschedule/rerun itself 637 392 break; 638 case Blocked:393 case 0: 639 394 /* paranoid */ verify( ! thrd->preempted != __NO_PREEMPTION ); 395 /* paranoid */ verify( thrd->state == Blocked ); 640 396 641 397 // Wake lost the race, 642 thrd->state = Blocked; 643 __schedule_thread( thrd ); 398 __schedule_thread( id, thrd ); 644 399 break; 645 case Rerun:646 abort("More than one thread attempted to schedule thread %p\n", thrd);647 break;648 case Halted:649 case Start:650 case Primed:651 400 default: 652 401 // This makes no sense, something is wrong abort … … 659 408 660 409 disable_interrupts(); 661 __unpark( thrd __cfaabi_dbg_ctx_fwd2 );410 __unpark( (__processor_id_t*)kernelTLS.this_processor, thrd __cfaabi_dbg_ctx_fwd2 ); 662 411 enable_interrupts( __cfaabi_dbg_ctx ); 663 412 } … … 694 443 695 444 $thread * thrd = kernelTLS.this_thread; 696 /* paranoid */ verify(thrd->state == Active || thrd->state == Rerun);445 /* paranoid */ verify(thrd->state == Active); 697 446 698 447 // SKULLDUGGERY: It is possible that we are preempting this thread just before … … 701 450 // If that is the case, abandon the preemption. 702 451 bool preempted = false; 703 if(thrd-> next == 0p) {452 if(thrd->link.next == 0p) { 704 453 preempted = true; 705 454 thrd->preempted = reason; … … 715 464 716 465 //============================================================================================= 717 // Kernel Setup logic718 //=============================================================================================719 //-----------------------------------------------------------------------------720 // Kernel boot procedures721 static void __kernel_startup(void) {722 verify( ! kernelTLS.preemption_state.enabled );723 __cfadbg_print_safe(runtime_core, "Kernel : Starting\n");724 725 __page_size = sysconf( _SC_PAGESIZE );726 727 __cfa_dbg_global_clusters.list{ __get };728 __cfa_dbg_global_clusters.lock{};729 730 // Initialize the main cluster731 mainCluster = (cluster *)&storage_mainCluster;732 (*mainCluster){"Main Cluster"};733 734 __cfadbg_print_safe(runtime_core, "Kernel : Main cluster ready\n");735 736 // Start by initializing the main thread737 // SKULLDUGGERY: the mainThread steals the process main thread738 // which will then be scheduled by the mainProcessor normally739 mainThread = ($thread *)&storage_mainThread;740 current_stack_info_t info;741 info.storage = (__stack_t*)&storage_mainThreadCtx;742 (*mainThread){ &info };743 744 __cfadbg_print_safe(runtime_core, "Kernel : Main thread ready\n");745 746 747 748 // Construct the processor context of the main processor749 void ?{}(processorCtx_t & this, processor * proc) {750 (this.__cor){ "Processor" };751 this.__cor.starter = 0p;752 this.proc = proc;753 }754 755 void ?{}(processor & this) with( this ) {756 name = "Main Processor";757 cltr = mainCluster;758 terminated{ 0 };759 do_terminate = false;760 preemption_alarm = 0p;761 pending_preemption = false;762 kernel_thread = pthread_self();763 764 runner{ &this };765 __cfadbg_print_safe(runtime_core, "Kernel : constructed main processor context %p\n", &runner);766 }767 768 // Initialize the main processor and the main processor ctx769 // (the coroutine that contains the processing control flow)770 mainProcessor = (processor *)&storage_mainProcessor;771 (*mainProcessor){};772 773 //initialize the global state variables774 kernelTLS.this_processor = mainProcessor;775 kernelTLS.this_thread = mainThread;776 777 // Enable preemption778 kernel_start_preemption();779 780 // Add the main thread to the ready queue781 // once resume is called on mainProcessor->runner the mainThread needs to be scheduled like any normal thread782 __schedule_thread(mainThread);783 784 // SKULLDUGGERY: Force a context switch to the main processor to set the main thread's context to the current UNIX785 // context. Hence, the main thread does not begin through __cfactx_invoke_thread, like all other threads. The trick here is that786 // mainThread is on the ready queue when this call is made.787 __kernel_first_resume( kernelTLS.this_processor );788 789 790 // THE SYSTEM IS NOW COMPLETELY RUNNING791 792 793 // Now that the system is up, finish creating systems that need threading794 __kernel_io_finish_start( *mainCluster );795 796 797 __cfadbg_print_safe(runtime_core, "Kernel : Started\n--------------------------------------------------\n\n");798 799 verify( ! kernelTLS.preemption_state.enabled );800 enable_interrupts( __cfaabi_dbg_ctx );801 verify( TL_GET( preemption_state.enabled ) );802 }803 804 static void __kernel_shutdown(void) {805 //Before we start shutting things down, wait for systems that need threading to shutdown806 __kernel_io_prepare_stop( *mainCluster );807 808 /* paranoid */ verify( TL_GET( preemption_state.enabled ) );809 disable_interrupts();810 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );811 812 __cfadbg_print_safe(runtime_core, "\n--------------------------------------------------\nKernel : Shutting down\n");813 814 // SKULLDUGGERY: Notify the mainProcessor it needs to terminates.815 // When its coroutine terminates, it return control to the mainThread816 // which is currently here817 __atomic_store_n(&mainProcessor->do_terminate, true, __ATOMIC_RELEASE);818 __kernel_last_resume( kernelTLS.this_processor );819 mainThread->self_cor.state = Halted;820 821 // THE SYSTEM IS NOW COMPLETELY STOPPED822 823 // Disable preemption824 kernel_stop_preemption();825 826 // Destroy the main processor and its context in reverse order of construction827 // These were manually constructed so we need manually destroy them828 void ^?{}(processor & this) with( this ){829 /* paranoid */ verify( this.do_terminate == true );830 }831 832 ^(*mainProcessor){};833 834 // Final step, destroy the main thread since it is no longer needed835 // Since we provided a stack to this taxk it will not destroy anything836 /* paranoid */ verify(mainThread->self_cor.stack.storage == (__stack_t*)(((uintptr_t)&storage_mainThreadCtx)| 0x1));837 ^(*mainThread){};838 839 ^(*mainCluster){};840 841 ^(__cfa_dbg_global_clusters.list){};842 ^(__cfa_dbg_global_clusters.lock){};843 844 __cfadbg_print_safe(runtime_core, "Kernel : Shutdown complete\n");845 }846 847 //=============================================================================================848 466 // Kernel Idle Sleep 849 467 //============================================================================================= 850 static $thread * __halt(processor * this) with( *this ) {851 if( do_terminate ) return 0p;852 853 // First, lock the cluster idle854 lock( cltr->idle_lock __cfaabi_dbg_ctx2 );855 856 // Check if we can find a thread857 if( $thread * found = __next_thread( cltr ) ) {858 unlock( cltr->idle_lock );859 return found;860 }861 862 // Move this processor from the active list to the idle list863 move_to_front(cltr->procs, cltr->idles, *this);864 865 // Unlock the idle lock so we don't go to sleep with a lock866 unlock (cltr->idle_lock);867 868 // We are ready to sleep869 __cfadbg_print_safe(runtime_core, "Kernel : Processor %p ready to sleep\n", this);870 wait( idle );871 872 // We have woken up873 __cfadbg_print_safe(runtime_core, "Kernel : Processor %p woke up and ready to run\n", this);874 875 // Get ourself off the idle list876 with( *cltr ) {877 lock (idle_lock __cfaabi_dbg_ctx2);878 move_to_front(idles, procs, *this);879 unlock(idle_lock);880 }881 882 // Don't check the ready queue again, we may not be in a position to run a thread883 return 0p;884 }885 886 468 // Wake a thread from the front if there are any 887 static bool __wake_one(cluster * this, __attribute__((unused)) bool force) { 888 // if we don't want to force check if we know it's false 889 // if( !this->idles.head && !force ) return false; 890 891 // First, lock the cluster idle 892 lock( this->idle_lock __cfaabi_dbg_ctx2 ); 893 894 // Check if there is someone to wake up 895 if( !this->idles.head ) { 896 // Nope unlock and return false 897 unlock( this->idle_lock ); 898 return false; 899 } 900 901 // Wake them up 902 __cfadbg_print_safe(runtime_core, "Kernel : waking Processor %p\n", this->idles.head); 903 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 904 post( this->idles.head->idle ); 905 906 // Unlock and return true 907 unlock( this->idle_lock ); 908 return true; 469 static void __wake_one(struct __processor_id_t * id, cluster * this) { 470 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 471 /* paranoid */ verify( ready_schedule_islocked( id ) ); 472 473 // Check if there is a sleeping processor 474 processor * p; 475 unsigned idle; 476 unsigned total; 477 [idle, total, p] = query(this->idles); 478 479 // If no one is sleeping, we are done 480 if( idle == 0 ) return; 481 482 // We found a processor, wake it up 483 post( p->idle ); 484 485 #if !defined(__CFA_NO_STATISTICS__) 486 __tls_stats()->ready.sleep.wakes++; 487 #endif 488 489 /* paranoid */ verify( ready_schedule_islocked( id ) ); 490 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 491 492 return; 909 493 } 910 494 911 495 // Unconditionnaly wake a thread 912 static bool__wake_proc(processor * this) {496 void __wake_proc(processor * this) { 913 497 __cfadbg_print_safe(runtime_core, "Kernel : waking Processor %p\n", this); 914 498 … … 917 501 bool ret = post( this->idle ); 918 502 enable_interrupts( __cfaabi_dbg_ctx ); 919 920 return ret; 503 } 504 505 static void push (__cluster_idles & this, processor & proc) { 506 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 507 lock( this ); 508 this.idle++; 509 /* paranoid */ verify( this.idle <= this.total ); 510 511 insert_first(this.list, proc); 512 unlock( this ); 513 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 514 } 515 516 static void remove(__cluster_idles & this, processor & proc) { 517 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 518 lock( this ); 519 this.idle--; 520 /* paranoid */ verify( this.idle >= 0 ); 521 522 remove(proc); 523 unlock( this ); 524 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 525 } 526 527 static [unsigned idle, unsigned total, * processor] query( & __cluster_idles this ) { 528 for() { 529 uint64_t l = __atomic_load_n(&this.lock, __ATOMIC_SEQ_CST); 530 if( 1 == (l % 2) ) { Pause(); continue; } 531 unsigned idle = this.idle; 532 unsigned total = this.total; 533 processor * proc = &this.list`first; 534 if(l != __atomic_load_n(&this.lock, __ATOMIC_SEQ_CST)) { Pause(); continue; } 535 return [idle, total, proc]; 536 } 921 537 } 922 538 … … 952 568 953 569 void kernel_abort_msg( void * kernel_data, char * abort_text, int abort_text_size ) { 954 $thread * thrd = kernel_data;570 $thread * thrd = ( $thread * ) kernel_data; 955 571 956 572 if(thrd) { … … 1050 666 1051 667 //----------------------------------------------------------------------------- 1052 // Global Queues1053 void doregister( cluster & cltr ) {1054 lock ( __cfa_dbg_global_clusters.lock __cfaabi_dbg_ctx2);1055 push_front( __cfa_dbg_global_clusters.list, cltr );1056 unlock ( __cfa_dbg_global_clusters.lock );1057 }1058 1059 void unregister( cluster & cltr ) {1060 lock ( __cfa_dbg_global_clusters.lock __cfaabi_dbg_ctx2);1061 remove( __cfa_dbg_global_clusters.list, cltr );1062 unlock( __cfa_dbg_global_clusters.lock );1063 }1064 1065 void doregister( cluster * cltr, $thread & thrd ) {1066 lock (cltr->thread_list_lock __cfaabi_dbg_ctx2);1067 cltr->nthreads += 1;1068 push_front(cltr->threads, thrd);1069 unlock (cltr->thread_list_lock);1070 }1071 1072 void unregister( cluster * cltr, $thread & thrd ) {1073 lock (cltr->thread_list_lock __cfaabi_dbg_ctx2);1074 remove(cltr->threads, thrd );1075 cltr->nthreads -= 1;1076 unlock(cltr->thread_list_lock);1077 }1078 1079 void doregister( cluster * cltr, processor * proc ) {1080 lock (cltr->idle_lock __cfaabi_dbg_ctx2);1081 cltr->nprocessors += 1;1082 push_front(cltr->procs, *proc);1083 unlock (cltr->idle_lock);1084 }1085 1086 void unregister( cluster * cltr, processor * proc ) {1087 lock (cltr->idle_lock __cfaabi_dbg_ctx2);1088 remove(cltr->procs, *proc );1089 cltr->nprocessors -= 1;1090 unlock(cltr->idle_lock);1091 }1092 1093 //-----------------------------------------------------------------------------1094 668 // Debug 1095 669 __cfaabi_dbg_debug_do( … … 1118 692 return true; 1119 693 } 694 695 //----------------------------------------------------------------------------- 696 // Statistics 697 #if !defined(__CFA_NO_STATISTICS__) 698 void print_halts( processor & this ) { 699 this.print_halts = true; 700 } 701 #endif 1120 702 // Local Variables: // 1121 703 // mode: c // -
libcfa/src/concurrency/kernel.hfa
r07d867b r22f94a4 16 16 #pragma once 17 17 18 #include <stdbool.h>19 #include <stdint.h>20 21 18 #include "invoke.h" 22 19 #include "time_t.hfa" 23 20 #include "coroutine.hfa" 24 21 22 #include "containers/list.hfa" 23 25 24 extern "C" { 26 #include <pthread.h> 27 #include <semaphore.h> 25 #include <bits/pthreadtypes.h> 28 26 } 29 27 … … 47 45 extern struct cluster * mainCluster; 48 46 49 // Processor 47 // Processor id, required for scheduling threads 48 struct __processor_id_t { 49 unsigned id; 50 51 #if !defined(__CFA_NO_STATISTICS__) 52 struct __stats_t * stats; 53 #endif 54 }; 55 50 56 coroutine processorCtx_t { 51 57 struct processor * proc; … … 53 59 54 60 // Wrapper around kernel threads 55 struct processor {61 struct __attribute__((aligned(128))) processor { 56 62 // Main state 63 inline __processor_id_t; 64 65 // Cluster from which to get threads 66 struct cluster * cltr; 67 68 // Set to true to notify the processor should terminate 69 volatile bool do_terminate; 70 57 71 // Coroutine ctx who does keeps the state of the processor 58 72 struct processorCtx_t runner; 59 60 // Cluster from which to get threads61 struct cluster * cltr;62 73 63 74 // Name of the processor … … 81 92 __bin_sem_t idle; 82 93 83 // Termination84 // Set to true to notify the processor should terminate85 volatile bool do_terminate;86 87 94 // Termination synchronisation (user semaphore) 88 95 semaphore terminated; … … 92 99 93 100 // Link lists fields 94 struct __dbg_node_proc { 95 struct processor * next; 96 struct processor * prev; 97 } node; 101 DLISTED_MGD_IMPL_IN(processor) 102 103 #if !defined(__CFA_NO_STATISTICS__) 104 int print_stats; 105 bool print_halts; 106 #endif 98 107 99 108 #ifdef __CFA_DEBUG__ … … 110 119 static inline void ?{}(processor & this, const char name[]) { this{name, *mainCluster }; } 111 120 112 static inline [processor *&, processor *& ] __get( processor & this ) __attribute__((const)) { return this.node.[next, prev]; } 121 DLISTED_MGD_IMPL_OUT(processor) 113 122 114 123 //----------------------------------------------------------------------------- … … 116 125 struct __io_data; 117 126 118 #define CFA_CLUSTER_IO_POLLER_USER_THREAD 1 << 0 119 // #define CFA_CLUSTER_IO_POLLER_KERNEL_SIDE 1 << 1 127 // IO poller user-thread 128 // Not using the "thread" keyword because we want to control 129 // more carefully when to start/stop it 130 struct $io_ctx_thread { 131 struct __io_data * ring; 132 single_sem sem; 133 volatile bool done; 134 $thread self; 135 }; 136 137 138 struct io_context { 139 $io_ctx_thread thrd; 140 }; 141 142 struct io_context_params { 143 int num_entries; 144 int num_ready; 145 int submit_aff; 146 bool eager_submits:1; 147 bool poller_submits:1; 148 bool poll_submit:1; 149 bool poll_complete:1; 150 }; 151 152 void ?{}(io_context_params & this); 153 154 void ?{}(io_context & this, struct cluster & cl); 155 void ?{}(io_context & this, struct cluster & cl, const io_context_params & params); 156 void ^?{}(io_context & this); 157 158 struct io_cancellation { 159 uint32_t target; 160 }; 161 162 static inline void ?{}(io_cancellation & this) { this.target = -1u; } 163 static inline void ^?{}(io_cancellation & this) {} 164 bool cancel(io_cancellation & this); 165 166 //----------------------------------------------------------------------------- 167 // Cluster Tools 168 169 // Intrusives lanes which are used by the relaxed ready queue 170 struct __attribute__((aligned(128))) __intrusive_lane_t; 171 void ?{}(__intrusive_lane_t & this); 172 void ^?{}(__intrusive_lane_t & this); 173 174 // Counter used for wether or not the lanes are all empty 175 struct __attribute__((aligned(128))) __snzi_node_t; 176 struct __snzi_t { 177 unsigned mask; 178 int root; 179 __snzi_node_t * nodes; 180 }; 181 182 void ?{}( __snzi_t & this, unsigned depth ); 183 void ^?{}( __snzi_t & this ); 184 185 //TODO adjust cache size to ARCHITECTURE 186 // Structure holding the relaxed ready queue 187 struct __ready_queue_t { 188 // Data tracking how many/which lanes are used 189 // Aligned to 128 for cache locality 190 __snzi_t snzi; 191 192 // Data tracking the actual lanes 193 // On a seperate cacheline from the used struct since 194 // used can change on each push/pop but this data 195 // only changes on shrink/grow 196 struct { 197 // Arary of lanes 198 __intrusive_lane_t * volatile data; 199 200 // Number of lanes (empty or not) 201 volatile size_t count; 202 } lanes; 203 }; 204 205 void ?{}(__ready_queue_t & this); 206 void ^?{}(__ready_queue_t & this); 207 208 // Idle Sleep 209 struct __cluster_idles { 210 // Spin lock protecting the queue 211 volatile uint64_t lock; 212 213 // Total number of processors 214 unsigned total; 215 216 // Total number of idle processors 217 unsigned idle; 218 219 // List of idle processors 220 dlist(processor, processor) list; 221 }; 120 222 121 223 //----------------------------------------------------------------------------- 122 224 // Cluster 123 struct cluster { 124 // Ready queue locks 125 __spinlock_t ready_queue_lock; 126 225 struct __attribute__((aligned(128))) cluster { 127 226 // Ready queue for threads 128 __ queue_t($thread)ready_queue;227 __ready_queue_t ready_queue; 129 228 130 229 // Name of the cluster … … 134 233 Duration preemption_rate; 135 234 136 // List of processors 137 __spinlock_t idle_lock; 138 __dllist_t(struct processor) procs; 139 __dllist_t(struct processor) idles; 140 unsigned int nprocessors; 235 // List of idle processors 236 __cluster_idles idles; 141 237 142 238 // List of threads … … 151 247 } node; 152 248 153 struct __io_data * io; 249 struct { 250 io_context * ctxs; 251 unsigned cnt; 252 } io; 154 253 155 254 #if !defined(__CFA_NO_STATISTICS__) 156 bool print_stats; 255 struct __stats_t * stats; 256 int print_stats; 157 257 #endif 158 258 }; 159 259 extern Duration default_preemption(); 160 260 161 void ?{} (cluster & this, const char name[], Duration preemption_rate, int flags);261 void ?{} (cluster & this, const char name[], Duration preemption_rate, unsigned num_io, const io_context_params & io_params); 162 262 void ^?{}(cluster & this); 163 263 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}; } 264 static inline void ?{} (cluster & this) { io_context_params default_params; this{"Anonymous Cluster", default_preemption(), 1, default_params}; } 265 static inline void ?{} (cluster & this, Duration preemption_rate) { io_context_params default_params; this{"Anonymous Cluster", preemption_rate, 1, default_params}; } 266 static inline void ?{} (cluster & this, const char name[]) { io_context_params default_params; this{name, default_preemption(), 1, default_params}; } 267 static inline void ?{} (cluster & this, unsigned num_io) { io_context_params default_params; this{"Anonymous Cluster", default_preemption(), num_io, default_params}; } 268 static inline void ?{} (cluster & this, Duration preemption_rate, unsigned num_io) { io_context_params default_params; this{"Anonymous Cluster", preemption_rate, num_io, default_params}; } 269 static inline void ?{} (cluster & this, const char name[], unsigned num_io) { io_context_params default_params; this{name, default_preemption(), num_io, default_params}; } 270 static inline void ?{} (cluster & this, const io_context_params & io_params) { this{"Anonymous Cluster", default_preemption(), 1, io_params}; } 271 static inline void ?{} (cluster & this, Duration preemption_rate, const io_context_params & io_params) { this{"Anonymous Cluster", preemption_rate, 1, io_params}; } 272 static inline void ?{} (cluster & this, const char name[], const io_context_params & io_params) { this{name, default_preemption(), 1, io_params}; } 273 static inline void ?{} (cluster & this, unsigned num_io, const io_context_params & io_params) { this{"Anonymous Cluster", default_preemption(), num_io, io_params}; } 274 static inline void ?{} (cluster & this, Duration preemption_rate, unsigned num_io, const io_context_params & io_params) { this{"Anonymous Cluster", preemption_rate, num_io, io_params}; } 275 static inline void ?{} (cluster & this, const char name[], unsigned num_io, const io_context_params & io_params) { this{name, default_preemption(), num_io, io_params}; } 170 276 171 277 static inline [cluster *&, cluster *& ] __get( cluster & this ) __attribute__((const)) { return this.node.[next, prev]; } … … 175 281 176 282 #if !defined(__CFA_NO_STATISTICS__) 177 static inline void print_stats_at_exit( cluster & this ) {178 this.print_stats = true;283 static inline void print_stats_at_exit( cluster & this, int flags ) { 284 this.print_stats |= flags; 179 285 } 286 287 static inline void print_stats_at_exit( processor & this, int flags ) { 288 this.print_stats |= flags; 289 } 290 291 void print_halts( processor & this ); 180 292 #endif 181 293 -
libcfa/src/concurrency/kernel_private.hfa
r07d867b r22f94a4 20 20 21 21 #include "alarm.hfa" 22 22 #include "stats.hfa" 23 23 24 24 //----------------------------------------------------------------------------- 25 25 // Scheduler 26 27 struct __attribute__((aligned(128))) __scheduler_lock_id_t; 26 28 27 29 extern "C" { … … 31 33 } 32 34 33 void __schedule_thread( $thread * ) __attribute__((nonnull (1))); 35 void __schedule_thread( struct __processor_id_t *, $thread * ) 36 #if defined(NDEBUG) || (!defined(__CFA_DEBUG__) && !defined(__CFA_VERIFY__)) 37 __attribute__((nonnull (2))) 38 #endif 39 ; 34 40 35 41 //Block current thread and release/wake-up the following resources … … 43 49 44 50 45 46 struct event_kernel_t {47 alarm_list_t alarms;48 __spinlock_t lock;49 };50 51 extern event_kernel_t * event_kernel;52 53 struct __cfa_kernel_preemption_state_t {54 bool enabled;55 bool in_progress;56 unsigned short disable_count;57 };58 59 extern volatile thread_local __cfa_kernel_preemption_state_t preemption_state __attribute__ ((tls_model ( "initial-exec" )));60 51 61 52 extern cluster * mainCluster; … … 73 64 74 65 // KERNEL ONLY unpark with out disabling interrupts 75 void __unpark( $thread * thrd __cfaabi_dbg_ctx_param2 ); 76 77 //----------------------------------------------------------------------------- 78 // I/O 79 void __kernel_io_startup ( cluster &, int, bool ); 80 void __kernel_io_finish_start( cluster & ); 81 void __kernel_io_prepare_stop( cluster & ); 82 void __kernel_io_shutdown ( cluster &, bool ); 66 void __unpark( struct __processor_id_t *, $thread * thrd __cfaabi_dbg_ctx_param2 ); 67 68 static inline bool __post(single_sem & this, struct __processor_id_t * id) { 69 for() { 70 struct $thread * expected = this.ptr; 71 if(expected == 1p) return false; 72 if(expected == 0p) { 73 if(__atomic_compare_exchange_n(&this.ptr, &expected, 1p, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) { 74 return false; 75 } 76 } 77 else { 78 if(__atomic_compare_exchange_n(&this.ptr, &expected, 0p, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) { 79 __unpark( id, expected __cfaabi_dbg_ctx2 ); 80 return true; 81 } 82 } 83 } 84 } 83 85 84 86 //----------------------------------------------------------------------------- 85 87 // Utils 86 #define KERNEL_STORAGE(T,X) static char storage_##X[sizeof(T)]87 88 static inline uint32_t __tls_rand() {89 kernelTLS.rand_seed ^= kernelTLS.rand_seed << 6;90 kernelTLS.rand_seed ^= kernelTLS.rand_seed >> 21;91 kernelTLS.rand_seed ^= kernelTLS.rand_seed << 7;92 return kernelTLS.rand_seed;93 }94 95 96 void doregister( struct cluster & cltr );97 void unregister( struct cluster & cltr );98 99 88 void doregister( struct cluster * cltr, struct $thread & thrd ); 100 89 void unregister( struct cluster * cltr, struct $thread & thrd ); 101 90 102 void doregister( struct cluster * cltr, struct processor * proc ); 103 void unregister( struct cluster * cltr, struct processor * proc ); 91 //----------------------------------------------------------------------------- 92 // I/O 93 void ^?{}(io_context & this, bool ); 94 95 //======================================================================= 96 // Cluster lock API 97 //======================================================================= 98 // Cells use by the reader writer lock 99 // while not generic it only relies on a opaque pointer 100 struct __attribute__((aligned(128))) __scheduler_lock_id_t { 101 // Spin lock used as the underlying lock 102 volatile bool lock; 103 104 // Handle pointing to the proc owning this cell 105 // Used for allocating cells and debugging 106 __processor_id_t * volatile handle; 107 108 #ifdef __CFA_WITH_VERIFY__ 109 // Debug, check if this is owned for reading 110 bool owned; 111 #endif 112 }; 113 114 static_assert( sizeof(struct __scheduler_lock_id_t) <= __alignof(struct __scheduler_lock_id_t)); 115 116 // Lock-Free registering/unregistering of threads 117 // Register a processor to a given cluster and get its unique id in return 118 unsigned doregister( struct __processor_id_t * proc ); 119 120 // Unregister a processor from a given cluster using its id, getting back the original pointer 121 void unregister( struct __processor_id_t * proc ); 122 123 //----------------------------------------------------------------------- 124 // Cluster idle lock/unlock 125 static inline void lock(__cluster_idles & this) { 126 for() { 127 uint64_t l = this.lock; 128 if( 129 (0 == (l % 2)) 130 && __atomic_compare_exchange_n(&this.lock, &l, l + 1, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) 131 ) return; 132 Pause(); 133 } 134 } 135 136 static inline void unlock(__cluster_idles & this) { 137 /* paranoid */ verify( 1 == (this.lock % 2) ); 138 __atomic_fetch_add( &this.lock, 1, __ATOMIC_SEQ_CST ); 139 } 140 141 //======================================================================= 142 // Reader-writer lock implementation 143 // Concurrent with doregister/unregister, 144 // i.e., threads can be added at any point during or between the entry/exit 145 146 //----------------------------------------------------------------------- 147 // simple spinlock underlying the RWLock 148 // Blocking acquire 149 static inline void __atomic_acquire(volatile bool * ll) { 150 while( __builtin_expect(__atomic_exchange_n(ll, (bool)true, __ATOMIC_SEQ_CST), false) ) { 151 while(__atomic_load_n(ll, (int)__ATOMIC_RELAXED)) 152 asm volatile("pause"); 153 } 154 /* paranoid */ verify(*ll); 155 } 156 157 // Non-Blocking acquire 158 static inline bool __atomic_try_acquire(volatile bool * ll) { 159 return !__atomic_exchange_n(ll, (bool)true, __ATOMIC_SEQ_CST); 160 } 161 162 // Release 163 static inline void __atomic_unlock(volatile bool * ll) { 164 /* paranoid */ verify(*ll); 165 __atomic_store_n(ll, (bool)false, __ATOMIC_RELEASE); 166 } 167 168 //----------------------------------------------------------------------- 169 // Reader-Writer lock protecting the ready-queues 170 // while this lock is mostly generic some aspects 171 // have been hard-coded to for the ready-queue for 172 // simplicity and performance 173 struct __scheduler_RWLock_t { 174 // total cachelines allocated 175 unsigned int max; 176 177 // cachelines currently in use 178 volatile unsigned int alloc; 179 180 // cachelines ready to itereate over 181 // (!= to alloc when thread is in second half of doregister) 182 volatile unsigned int ready; 183 184 // writer lock 185 volatile bool lock; 186 187 // data pointer 188 __scheduler_lock_id_t * data; 189 }; 190 191 void ?{}(__scheduler_RWLock_t & this); 192 void ^?{}(__scheduler_RWLock_t & this); 193 194 extern __scheduler_RWLock_t * __scheduler_lock; 195 196 //----------------------------------------------------------------------- 197 // Reader side : acquire when using the ready queue to schedule but not 198 // creating/destroying queues 199 static inline void ready_schedule_lock( struct __processor_id_t * proc) with(*__scheduler_lock) { 200 unsigned iproc = proc->id; 201 /*paranoid*/ verify(data[iproc].handle == proc); 202 /*paranoid*/ verify(iproc < ready); 203 204 // Step 1 : make sure no writer are in the middle of the critical section 205 while(__atomic_load_n(&lock, (int)__ATOMIC_RELAXED)) 206 asm volatile("pause"); 207 208 // Fence needed because we don't want to start trying to acquire the lock 209 // before we read a false. 210 // Not needed on x86 211 // std::atomic_thread_fence(std::memory_order_seq_cst); 212 213 // Step 2 : acquire our local lock 214 __atomic_acquire( &data[iproc].lock ); 215 /*paranoid*/ verify(data[iproc].lock); 216 217 #ifdef __CFA_WITH_VERIFY__ 218 // Debug, check if this is owned for reading 219 data[iproc].owned = true; 220 #endif 221 } 222 223 static inline void ready_schedule_unlock( struct __processor_id_t * proc) with(*__scheduler_lock) { 224 unsigned iproc = proc->id; 225 /*paranoid*/ verify(data[iproc].handle == proc); 226 /*paranoid*/ verify(iproc < ready); 227 /*paranoid*/ verify(data[iproc].lock); 228 /*paranoid*/ verify(data[iproc].owned); 229 #ifdef __CFA_WITH_VERIFY__ 230 // Debug, check if this is owned for reading 231 data[iproc].owned = false; 232 #endif 233 __atomic_unlock(&data[iproc].lock); 234 } 235 236 #ifdef __CFA_WITH_VERIFY__ 237 static inline bool ready_schedule_islocked( struct __processor_id_t * proc) { 238 return __scheduler_lock->data[proc->id].owned; 239 } 240 241 static inline bool ready_mutate_islocked() { 242 return __scheduler_lock->lock; 243 } 244 #endif 245 246 //----------------------------------------------------------------------- 247 // Writer side : acquire when changing the ready queue, e.g. adding more 248 // queues or removing them. 249 uint_fast32_t ready_mutate_lock( void ); 250 251 void ready_mutate_unlock( uint_fast32_t /* value returned by lock */ ); 252 253 //======================================================================= 254 // Ready-Queue API 255 //----------------------------------------------------------------------- 256 // pop thread from the ready queue of a cluster 257 // returns 0p if empty 258 __attribute__((hot)) bool query(struct cluster * cltr); 259 260 //----------------------------------------------------------------------- 261 // push thread onto a ready queue for a cluster 262 // returns true if the list was previously empty, false otherwise 263 __attribute__((hot)) bool push(struct cluster * cltr, struct $thread * thrd); 264 265 //----------------------------------------------------------------------- 266 // pop thread from the ready queue of a cluster 267 // returns 0p if empty 268 // May return 0p spuriously 269 __attribute__((hot)) struct $thread * pop(struct cluster * cltr); 270 271 //----------------------------------------------------------------------- 272 // pop thread from the ready queue of a cluster 273 // returns 0p if empty 274 // guaranteed to find any threads added before this call 275 __attribute__((hot)) struct $thread * pop_slow(struct cluster * cltr); 276 277 //----------------------------------------------------------------------- 278 // remove thread from the ready queue of a cluster 279 // returns bool if it wasn't found 280 bool remove_head(struct cluster * cltr, struct $thread * thrd); 281 282 //----------------------------------------------------------------------- 283 // Increase the width of the ready queue (number of lanes) by 4 284 void ready_queue_grow (struct cluster * cltr, int target); 285 286 //----------------------------------------------------------------------- 287 // Decrease the width of the ready queue (number of lanes) by 4 288 void ready_queue_shrink(struct cluster * cltr, int target); 289 104 290 105 291 // Local Variables: // -
libcfa/src/concurrency/monitor.cfa
r07d867b r22f94a4 114 114 115 115 // Some one else has the monitor, wait in line for it 116 /* paranoid */ verify( thrd-> next == 0p );116 /* paranoid */ verify( thrd->link.next == 0p ); 117 117 append( this->entry_queue, thrd ); 118 /* paranoid */ verify( thrd-> next == 1p );118 /* paranoid */ verify( thrd->link.next == 1p ); 119 119 120 120 unlock( this->lock ); … … 199 199 200 200 // Some one else has the monitor, wait in line for it 201 /* paranoid */ verify( thrd-> next == 0p );201 /* paranoid */ verify( thrd->link.next == 0p ); 202 202 append( this->entry_queue, thrd ); 203 /* paranoid */ verify( thrd-> next == 1p );203 /* paranoid */ verify( thrd->link.next == 1p ); 204 204 unlock( this->lock ); 205 205 … … 761 761 $thread * new_owner = pop_head( this->entry_queue ); 762 762 /* paranoid */ verifyf( !this->owner || kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this ); 763 /* paranoid */ verify( !new_owner || new_owner-> next == 0p );763 /* paranoid */ verify( !new_owner || new_owner->link.next == 0p ); 764 764 __set_owner( this, new_owner ); 765 765 … … 883 883 } 884 884 885 __cfaabi_dbg_print_safe( "Kernel : Runing %i (%p)\n", ready2run, ready2run ? node->waiting_thread :0p );885 __cfaabi_dbg_print_safe( "Kernel : Runing %i (%p)\n", ready2run, ready2run ? (thread*)node->waiting_thread : (thread*)0p ); 886 886 return ready2run ? node->waiting_thread : 0p; 887 887 } … … 907 907 // For each thread in the entry-queue 908 908 for( $thread ** thrd_it = &entry_queue.head; 909 *thrd_it!= 1p;910 thrd_it = &(*thrd_it)-> next909 (*thrd_it) != 1p; 910 thrd_it = &(*thrd_it)->link.next 911 911 ) { 912 912 // For each acceptable check if it matches -
libcfa/src/concurrency/mutex.cfa
r07d867b r22f94a4 30 30 this.lock{}; 31 31 this.blocked_threads{}; 32 this.is_locked = false; 32 33 } 33 34 -
libcfa/src/concurrency/preemption.cfa
r07d867b r22f94a4 10 10 // Created On : Mon Jun 5 14:20:42 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Dec 5 16:34:05 201913 // Update Count : 4 312 // Last Modified On : Wed Jun 17 11:36:25 2020 13 // Update Count : 46 14 14 // 15 15 … … 19 19 #include <assert.h> 20 20 21 extern "C" {22 21 #include <errno.h> 23 22 #include <stdio.h> … … 25 24 #include <unistd.h> 26 25 #include <limits.h> // PTHREAD_STACK_MIN 27 }28 26 29 27 #include "bits/signal.hfa" 28 #include "kernel_private.hfa" 30 29 31 30 #if !defined(__CFA_DEFAULT_PREEMPTION__) … … 39 38 // FwdDeclarations : timeout handlers 40 39 static void preempt( processor * this ); 41 static void timeout( $thread * this );40 static void timeout( struct __processor_id_t * id, $thread * this ); 42 41 43 42 // FwdDeclarations : Signal handlers … … 90 89 91 90 // Tick one frame of the Discrete Event Simulation for alarms 92 static void tick_preemption( ) {91 static void tick_preemption( struct __processor_id_t * id ) { 93 92 alarm_node_t * node = 0p; // Used in the while loop but cannot be declared in the while condition 94 93 alarm_list_t * alarms = &event_kernel->alarms; // Local copy for ease of reading … … 108 107 } 109 108 else { 110 timeout( node->thrd );109 timeout( id, node->thrd ); 111 110 } 112 111 … … 121 120 // If there are still alarms pending, reset the timer 122 121 if( & (*alarms)`first ) { 123 __cfa abi_dbg_print_buffer_decl(" KERNEL: @%ju(%ju) resetting alarm to %ju.\n", currtime.tv, __kernel_get_time().tv, (alarms->head->alarm - currtime).tv);122 __cfadbg_print_buffer_decl(preemption, " KERNEL: @%ju(%ju) resetting alarm to %ju.\n", currtime.tv, __kernel_get_time().tv, (alarms->head->alarm - currtime).tv); 124 123 Duration delta = (*alarms)`first.alarm - currtime; 125 124 Duration capped = max(delta, 50`us); … … 188 187 void enable_interrupts( __cfaabi_dbg_ctx_param ) { 189 188 processor * proc = kernelTLS.this_processor; // Cache the processor now since interrupts can start happening after the atomic store 189 /* paranoid */ verify( proc ); 190 190 191 191 with( kernelTLS.preemption_state ){ … … 268 268 269 269 // reserved for future use 270 static void timeout( $thread * this ) { 271 __unpark( this __cfaabi_dbg_ctx2 ); 270 static void timeout( struct __processor_id_t * id, $thread * this ) { 271 #if !defined( __CFA_NO_STATISTICS__ ) 272 kernelTLS.this_stats = this->curr_cluster->stats; 273 #endif 274 __unpark( id, this __cfaabi_dbg_ctx2 ); 272 275 } 273 276 … … 291 294 // Startup routine to activate preemption 292 295 // Called from kernel_startup 293 void kernel_start_preemption() {296 void __kernel_alarm_startup() { 294 297 __cfaabi_dbg_print_safe( "Kernel : Starting preemption\n" ); 295 298 … … 313 316 // Shutdown routine to deactivate preemption 314 317 // Called from kernel_shutdown 315 void kernel_stop_preemption() {318 void __kernel_alarm_shutdown() { 316 319 __cfaabi_dbg_print_safe( "Kernel : Preemption stopping\n" ); 317 320 … … 405 408 // Waits on SIGALRM and send SIGUSR1 to whom ever needs it 406 409 static void * alarm_loop( __attribute__((unused)) void * args ) { 410 __processor_id_t id; 411 id.id = doregister(&id); 412 407 413 // Block sigalrms to control when they arrive 408 414 sigset_t mask; … … 449 455 // __cfaabi_dbg_print_safe( "Kernel : Preemption thread tick\n" ); 450 456 lock( event_kernel->lock __cfaabi_dbg_ctx2 ); 451 tick_preemption( );457 tick_preemption( &id ); 452 458 unlock( event_kernel->lock ); 453 459 break; … … 462 468 EXIT: 463 469 __cfaabi_dbg_print_safe( "Kernel : Preemption thread stopping\n" ); 470 unregister(&id); 464 471 return 0p; 465 472 } … … 475 482 sigset_t oldset; 476 483 int ret; 477 ret = pthread_sigmask(0, 0p, &oldset);484 ret = pthread_sigmask(0, ( const sigset_t * ) 0p, &oldset); // workaround trac#208: cast should be unnecessary 478 485 if(ret != 0) { abort("ERROR sigprocmask returned %d", ret); } 479 486 -
libcfa/src/concurrency/preemption.hfa
r07d867b r22f94a4 16 16 #pragma once 17 17 18 #include "bits/locks.hfa" 18 19 #include "alarm.hfa" 19 #include "kernel_private.hfa"20 20 21 void kernel_start_preemption(); 22 void kernel_stop_preemption(); 21 struct event_kernel_t { 22 alarm_list_t alarms; 23 __spinlock_t lock; 24 }; 25 26 extern event_kernel_t * event_kernel; 27 23 28 void update_preemption( processor * this, Duration duration ); 24 29 -
libcfa/src/concurrency/thread.cfa
r07d867b r22f94a4 28 28 context{ 0p, 0p }; 29 29 self_cor{ name, storage, storageSize }; 30 ticket = 1; 30 31 state = Start; 31 32 preempted = __NO_PREEMPTION; … … 35 36 self_mon_p = &self_mon; 36 37 curr_cluster = &cl; 37 next = 0p; 38 link.next = 0p; 39 link.prev = 0p; 40 link.preferred = -1; 38 41 39 42 node.next = 0p; … … 61 64 verify( this_thrd->context.SP ); 62 65 63 __schedule_thread( this_thrd);66 __schedule_thread( (__processor_id_t *)kernelTLS.this_processor, this_thrd); 64 67 enable_interrupts( __cfaabi_dbg_ctx ); 65 68 } -
libcfa/src/concurrency/thread.hfa
r07d867b r22f94a4 84 84 85 85 //----------------------------------------------------------------------------- 86 // Thread getters87 static inline struct $thread * active_thread () { return TL_GET( this_thread ); }88 89 //-----------------------------------------------------------------------------90 86 // Scheduler API 91 87 … … 106 102 bool force_yield( enum __Preemption_Reason ); 107 103 108 static inline void yield() {109 force_yield(__MANUAL_PREEMPTION);110 }111 112 // Yield: yield N times113 static inline void yield( unsigned times ) {114 for( times ) {115 yield();116 }117 }118 119 104 //---------- 120 105 // sleep: force thread to block and be rescheduled after Duration duration -
libcfa/src/containers/list.hfa
r07d867b r22f94a4 14 14 // 15 15 16 #pragma once 17 16 18 #include <assert.h> 17 19 … … 22 24 \ 23 25 static inline NODE& $tempcv_e2n(ELEM &node) { \ 24 return node; \26 return ( NODE & ) node; \ 25 27 } \ 26 28 \ … … 118 120 Telem& $tempcv_n2e(Tnode &); 119 121 Tnode& $tempcv_e2n(Telem &); 122 123 Telem& ?`next(Tnode &); 124 Telem& ?`prev(Tnode &); 120 125 }; 121 126 … … 184 189 $next_link(singleton_to_insert) = $next_link(list_pos); 185 190 if ($next_link(list_pos).is_terminator) { 186 dlist(Tnode, Telem) *list = $next_link(list_pos).terminator;191 dlist(Tnode, Telem) *list = ( dlist(Tnode, Telem) * ) $next_link(list_pos).terminator; 187 192 $dlinks(Telem) *list_links = & list->$links; 188 193 $mgd_link(Telem) *list_last = & list_links->prev; … … 207 212 $prev_link(singleton_to_insert) = $prev_link(list_pos); 208 213 if ($prev_link(list_pos).is_terminator) { 209 dlist(Tnode, Telem) *list = $prev_link(list_pos).terminator;214 dlist(Tnode, Telem) *list = ( dlist(Tnode, Telem) * ) $prev_link(list_pos).terminator; 210 215 $dlinks(Telem) *list_links = & list->$links; 211 216 $mgd_link(Telem) *list_first = & list_links->next; … … 272 277 273 278 if ( $prev_link(list_pos).is_terminator ) { 274 dlist(Tnode, Telem) * tgt_before = $prev_link(list_pos).terminator;279 dlist(Tnode, Telem) * tgt_before = ( dlist(Tnode, Telem) * ) $prev_link(list_pos).terminator; 275 280 $dlinks(Telem) * links_before = & tgt_before->$links; 276 281 &incoming_from_prev = & links_before->next; … … 282 287 283 288 if ( $next_link(list_pos).is_terminator ) { 284 dlist(Tnode, Telem) * tgt_after = $next_link(list_pos).terminator;289 dlist(Tnode, Telem) * tgt_after = ( dlist(Tnode, Telem) * ) $next_link(list_pos).terminator; 285 290 $dlinks(Telem) * links_after = & tgt_after->$links; 286 291 &incoming_from_next = & links_after->prev; … … 301 306 $prev_link(list_pos) = (Telem*) 0p; 302 307 } 308 309 static inline bool ?`is_empty(dlist(Tnode, Telem) &list) { 310 assert( &list != 0p ); 311 $dlinks(Telem) *listLinks = & list.$links; 312 if (listLinks->next.is_terminator) { 313 assert(listLinks->prev.is_terminator); 314 assert(listLinks->next.terminator); 315 assert(listLinks->prev.terminator); 316 return true; 317 } else { 318 assert(!listLinks->prev.is_terminator); 319 assert(listLinks->next.elem); 320 assert(listLinks->prev.elem); 321 return false; 322 } 323 } 324 325 static inline Telem & pop_first(dlist(Tnode, Telem) &list) { 326 assert( &list != 0p ); 327 assert( !list`is_empty ); 328 $dlinks(Telem) *listLinks = & list.$links; 329 Telem & first = *listLinks->next.elem; 330 Tnode & list_pos_first = $tempcv_e2n( first ); 331 remove(list_pos_first); 332 return first; 333 } 334 335 static inline Telem & pop_last(dlist(Tnode, Telem) &list) { 336 assert( &list != 0p ); 337 assert( !list`is_empty ); 338 $dlinks(Telem) *listLinks = & list.$links; 339 Telem & last = *listLinks->prev.elem; 340 Tnode & list_pos_last = $tempcv_e2n( last ); 341 remove(list_pos_last); 342 return last; 343 } 344 303 345 } 304 346 -
libcfa/src/containers/vector.hfa
r07d867b r22f94a4 10 10 // Created On : Tue Jul 5 18:00:07 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Jul 22 10:01:18 201713 // Update Count : 312 // Last Modified On : Wed Jun 17 11:02:46 2020 13 // Update Count : 4 14 14 // 15 15 16 16 #pragma once 17 17 18 extern "C" {19 18 #include <stdbool.h> 20 }21 19 22 20 //------------------------------------------------------------------------------ -
libcfa/src/exception.c
r07d867b r22f94a4 10 10 // Created On : Mon Jun 26 15:13:00 2017 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : T ue Apr 14 12:01:00 202013 // Update Count : 1812 // Last Modified On : Thr May 21 12:18:00 2020 13 // Update Count : 20 14 14 // 15 15 … … 80 80 } 81 81 82 void __cfaehm_throw_resume(exception_t * except ) {82 void __cfaehm_throw_resume(exception_t * except, void (*defaultHandler)(exception_t *)) { 83 83 struct exception_context_t * context = this_exception_context(); 84 84 85 85 __cfadbg_print_safe(exception, "Throwing resumption exception\n"); 86 86 87 __attribute__((cleanup(reset_top_resume))) 88 struct __cfaehm_try_resume_node * original_head = context->top_resume; 89 struct __cfaehm_try_resume_node * current = context->top_resume; 90 91 for ( ; current ; current = current->next) { 92 context->top_resume = current->next; 93 if (current->handler(except)) { 94 return; 87 { 88 __attribute__((cleanup(reset_top_resume))) 89 struct __cfaehm_try_resume_node * original_head = context->top_resume; 90 struct __cfaehm_try_resume_node * current = context->top_resume; 91 92 for ( ; current ; current = current->next) { 93 context->top_resume = current->next; 94 if (current->handler(except)) { 95 return; 96 } 95 97 } 96 } 97 98 } // End the search and return to the top of the stack. 99 100 // No handler found, fall back to the default operation. 98 101 __cfadbg_print_safe(exception, "Unhandled exception\n"); 99 100 // Fall back to termination: 101 __cfaehm_throw_terminate(except); 102 // TODO: Default handler for resumption. 102 defaultHandler(except); 103 103 } 104 104 … … 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 241 static void __cfaehm_cleanup_default( exception_t ** except ) { 242 __cfaehm_delete_exception( *except ); 243 *except = NULL; 244 } 245 230 246 // The exception that is being thrown must already be stored. 231 static __attribute__((noreturn)) void __cfaehm_begin_unwind(void) { 232 if ( ! this_exception_context()->current_exception ) { 247 static void __cfaehm_begin_unwind(void(*defaultHandler)(exception_t *)) { 248 struct exception_context_t * context = this_exception_context(); 249 struct _Unwind_Exception * storage = &this_exception_storage; 250 if ( NULL == context->current_exception ) { 233 251 printf("UNWIND ERROR missing exception in begin unwind\n"); 234 252 abort(); … … 236 254 237 255 // Call stdlibc to raise the exception 238 _Unwind_Reason_Code ret = _Unwind_RaiseException( &this_exception_storage ); 256 __cfadbg_print_safe(exception, "Begin unwinding (storage &p, context %p)\n", storage, context); 257 _Unwind_Reason_Code ret = _Unwind_RaiseException( storage ); 239 258 240 259 // If we reach here it means something happened. For resumption to work we need to find a way … … 245 264 // the whole stack. 246 265 247 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); 266 // We did not simply reach the end of the stack without finding a handler. This is an error. 267 if ( ret != _URC_END_OF_STACK ) { 268 printf("UNWIND ERROR %d after raise exception\n", ret); 254 269 abort(); 255 270 } 256 271 257 // We did not simply reach the end of the stack without finding a handler. This is an error. 258 printf("UNWIND ERROR %d after raise exception\n", ret); 272 // No handler found, go to the default operation. 273 __cfadbg_print_safe(exception, "Uncaught exception %p\n", storage); 274 275 __attribute__((cleanup(__cfaehm_cleanup_default))) 276 exception_t * exception = context->current_exception; 277 defaultHandler( exception ); 278 } 279 280 void __cfaehm_throw_terminate( exception_t * val, void (*defaultHandler)(exception_t *) ) { 281 __cfadbg_print_safe(exception, "Throwing termination exception\n"); 282 283 __cfaehm_allocate_exception( val ); 284 __cfaehm_begin_unwind( defaultHandler ); 285 } 286 287 static __attribute__((noreturn)) void __cfaehm_rethrow_adapter( exception_t * except ) { 288 // TODO: Print some error message. 289 (void)except; 259 290 abort(); 260 }261 262 void __cfaehm_throw_terminate( exception_t * val ) {263 __cfadbg_print_safe(exception, "Throwing termination exception\n");264 265 __cfaehm_allocate_exception( val );266 __cfaehm_begin_unwind();267 291 } 268 292 … … 270 294 __cfadbg_print_safe(exception, "Rethrowing termination exception\n"); 271 295 272 __cfaehm_begin_unwind(); 296 __cfaehm_begin_unwind( __cfaehm_rethrow_adapter ); 297 abort(); 273 298 } 274 299 -
libcfa/src/exception.h
r07d867b r22f94a4 10 10 // Created On : Mon Jun 26 15:11:00 2017 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Mar 27 10:16:00 202013 // Update Count : 912 // Last Modified On : Tue May 19 14:17:00 2020 13 // Update Count : 10 14 14 // 15 15 … … 38 38 39 39 40 void __cfaehm_cancel_stack(exception_t * except) __attribute__((noreturn)); 41 40 42 // Used in throw statement translation. 41 void __cfaehm_throw_terminate(exception_t * except ) __attribute__((noreturn));43 void __cfaehm_throw_terminate(exception_t * except, void (*)(exception_t *)); 42 44 void __cfaehm_rethrow_terminate() __attribute__((noreturn)); 43 void __cfaehm_throw_resume(exception_t * except );45 void __cfaehm_throw_resume(exception_t * except, void (*)(exception_t *)); 44 46 45 47 // Function catches termination exceptions. … … 70 72 #ifdef __cforall 71 73 } 74 75 // Not all the built-ins can be expressed in C. These can't be 76 // implemented in the .c file either so they all have to be inline. 77 78 trait is_exception(dtype T) { 79 /* The first field must be a pointer to a virtual table. 80 * That virtual table must be a decendent of the base exception virtual tab$ 81 */ 82 void mark_exception(T *); 83 // This is never used and should be a no-op. 84 }; 85 86 trait is_termination_exception(dtype T | is_exception(T)) { 87 void defaultTerminationHandler(T &); 88 }; 89 90 trait is_resumption_exception(dtype T | is_exception(T)) { 91 void defaultResumptionHandler(T &); 92 }; 93 94 forall(dtype T | is_termination_exception(T)) 95 static inline void $throw(T & except) { 96 __cfaehm_throw_terminate( 97 (exception_t *)&except, 98 (void(*)(exception_t *))defaultTerminationHandler 99 ); 100 } 101 102 forall(dtype T | is_resumption_exception(T)) 103 static inline void $throwResume(T & except) { 104 __cfaehm_throw_resume( 105 (exception_t *)&except, 106 (void(*)(exception_t *))defaultResumptionHandler 107 ); 108 } 109 110 forall(dtype T | is_exception(T)) 111 static inline void cancel_stack(T & except) __attribute__((noreturn)) { 112 __cfaehm_cancel_stack( (exception_t *)&except ); 113 } 114 115 forall(dtype T | is_exception(T)) 116 static inline void defaultTerminationHandler(T & except) { 117 return cancel_stack( except ); 118 } 119 120 forall(dtype T | is_exception(T)) 121 static inline void defaultResumptionHandler(T & except) { 122 throw except; 123 } 124 72 125 #endif -
libcfa/src/exception.hfa
r07d867b r22f94a4 10 10 // Created On : Thu Apr 7 10:25:00 2020 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : T hu Apr 7 10:25:00 202013 // Update Count : 012 // Last Modified On : Tue Aug 4 16:22:00 2020 13 // Update Count : 3 14 14 // 15 15 … … 18 18 // ----------------------------------------------------------------------------------------------- 19 19 20 // All internals helper macros begin with an underscore. 21 #define _CLOSE(...) __VA_ARGS__ } 22 #define _GLUE2(left, right) left##right 23 #define _GLUE3(left, middle, right) left##middle##right 24 #define _EXC_DISPATCH(to, ...) to(__VA_ARGS__,__cfaehm_base_exception_t,) 25 26 // FWD_TRIVIAL_EXCEPTION(exception_name); 20 // TRIVIAL_EXCEPTION_DECLARATION(exception_name); 27 21 // Declare a trivial exception, one that adds no fields or features. 28 22 // This will make the exception visible and may go in a .hfa or .cfa file. 29 #define FWD_TRIVIAL_EXCEPTION(...) _EXC_DISPATCH(_FWD_TRIVIAL_EXCEPTION, __VA_ARGS__) 30 // INST_TRIVIAL_EXCEPTION(exception_name); 23 #define TRIVIAL_EXCEPTION_DECLARATION(...) \ 24 _EXC_DISPATCH(_TRIVIAL_EXCEPTION_DECLARATION, __VA_ARGS__) 25 26 // TRIVIAL_EXCEPTION_INSTANCE(exception_name); 31 27 // Create the trival exception. This must be used exactly once and should be used in a .cfa file, 32 28 // as it creates the unique instance of the virtual table. 33 #define INST_TRIVIAL_EXCEPTION(...) _EXC_DISPATCH(_INST_TRIVIAL_EXCEPTION, __VA_ARGS__) 29 #define TRIVIAL_EXCEPTION_INSTANCE(...) _EXC_DISPATCH(_TRIVIAL_EXCEPTION_INSTANCE, __VA_ARGS__) 30 34 31 // TRIVIAL_EXCEPTION(exception_name[, parent_name]); 35 32 // Does both of the above, a short hand if the exception is only used in one .cfa file. … … 37 34 // base exception. This feature may be removed or changed. 38 35 #define TRIVIAL_EXCEPTION(...) \ 39 _EXC_DISPATCH(_FWD_TRIVIAL_EXCEPTION, __VA_ARGS__); \ 40 _EXC_DISPATCH(_INST_TRIVIAL_EXCEPTION, __VA_ARGS__) 41 #define _FWD_TRIVIAL_EXCEPTION(exception_name, parent_name, ...) \ 36 _EXC_DISPATCH(_TRIVIAL_EXCEPTION_DECLARATION, __VA_ARGS__); \ 37 _EXC_DISPATCH(_TRIVIAL_EXCEPTION_INSTANCE, __VA_ARGS__) 38 39 // FORALL_TRIVIAL_EXCEPTION(exception_name, (assertions...), (parameters...)); 40 // Forward declare a polymorphic but otherwise trivial exception type. You must provide the entire 41 // assertion list (exactly what would go in the forall clause) and parameters list (only the 42 // parameter names from the assertion list, same order and comma seperated). This should be 43 // visible where ever use the exception. This just generates the polymorphic framework, see 44 // POLY_VTABLE_DECLARATION to allow instantiations. 45 #define FORALL_TRIVIAL_EXCEPTION(exception_name, assertions, parameters) \ 46 _FORALL_TRIVIAL_EXCEPTION(exception_name, __cfaehm_base_exception_t, assertions, parameters, ) 47 48 // FORALL_TRIVIAL_INSTANCE(exception_name, (assertions...), (parameters...)) 49 // Create the forall trivial exception. The assertion list and parameters must match. 50 // There must be exactly one use of this in a program for each exception type. This just 51 // generates the polymorphic framework, see POLY_VTABLE_INSTANCE to allow instantiations. 52 #define FORALL_TRIVIAL_INSTANCE(exception_name, assertions, parameters) \ 53 _FORALL_CTOR0_INSTANCE(exception_name, assertions, parameters) 54 55 // DATA_EXCEPTION(exception_name)(fields...); 56 // Forward declare an exception that adds fields but no features. The added fields go in the 57 // second argument list. The virtual table instance must be provided later (see VTABLE_INSTANCE). 58 #define DATA_EXCEPTION(...) _EXC_DISPATCH(_DATA_EXCEPTION, __VA_ARGS__) 59 60 // FORALL_DATA_EXCEPTION(exception_name, (assertions...), (parameters...))(fields...); 61 // Define a polymorphic exception that adds fields but no additional features. The assertion list 62 // and matching parameters must match. Then you can give the list of fields. This should be 63 // visible where ever you use the exception. This just generates the polymorphic framework, see 64 // POLY_VTABLE_DECLARATION to allow instantiations. 65 #define FORALL_DATA_EXCEPTION(exception_name, assertions, parameters) \ 66 _FORALL_DATA_EXCEPTION(exception_name, __cfaehm_base_exception_t, assertions, parameters, ) 67 68 // FORALL_DATA_INSTANCE(exception_name, (assertions...), (parameters...)) 69 // Create a polymorphic data exception. The assertion list and parameters must match. This should 70 // appear once in each program. This just generates the polymorphic framework, see 71 // POLY_VTABLE_INSTANCE to allow instantiations. 72 #define FORALL_DATA_INSTANCE(exception_name, assertions, parameters) \ 73 _FORALL_CTOR0_INSTANCE(exception_name, assertions, parameters) 74 75 // VTABLE_DECLARATION(exception_name)([new_features...]); 76 // Declare a virtual table type for an exception with exception_name. You may also add features 77 // (fields on the virtual table) by including them in the second list. 78 #define VTABLE_DECLARATION(...) _EXC_DISPATCH(_VTABLE_DECLARATION, __VA_ARGS__) 79 80 // VTABLE_INSTANCE(exception_name)(msg [, others...]); 81 // Create the instance of the virtual table. There must be exactly one instance of a virtual table 82 // for each exception type. This fills in most of the fields of the virtual table (uses ?=? and 83 // ^?{}) but you must provide the message function and any other fields added in the declaration. 84 #define VTABLE_INSTANCE(...) _EXC_DISPATCH(_VTABLE_INSTANCE, __VA_ARGS__) 85 86 // FORALL_VTABLE_DECLARATION(exception_name, (assertions...), (parameters...))([new_features...]); 87 // Declare a polymorphic virtual table type for an exception with exception_name, the given 88 // assertions and parameters. You may also add features (fields on the virtual table). This just 89 // generates the polymorphic framework, see POLY_VTABLE_DECLARATION to allow instantiations. 90 #define FORALL_VTABLE_DECLARATION(exception_name, assertions, parameters) \ 91 _FORALL_VTABLE_DECLARATION(exception_name, __cfaehm_base_exception_t, assertions, parameters, ) 92 93 // POLY_VTABLE_DECLARATION(exception_name, types...); 94 // Declares that an instantiation for this exception exists for the given types. This should be 95 // visible anywhere you use the instantiation of the exception is used. 96 #define POLY_VTABLE_DECLARATION(exception_name, ...) \ 97 void mark_exception(exception_name(__VA_ARGS__) *); \ 98 extern VTABLE_TYPE(exception_name)(__VA_ARGS__) VTABLE_NAME(exception_name) 99 100 // POLY_VTABLE_INSTANCE(exception_name, types...)(msg [, others...]); 101 // Creates an instantiation for the given exception for the given types. This should occur only 102 // once in the entire program. You must fill in all features, message and any others given in the 103 // initial declaration. 104 #define POLY_VTABLE_INSTANCE(exception_name, ...) \ 105 _POLY_VTABLE_INSTANCE(exception_name, __cfaehm_base_exception_t, __VA_ARGS__) 106 107 // VTABLE_TYPE(exception_name) | VTABLE_NAME(exception_name) 108 // Get the name of the vtable type or the name of the vtable instance for an exception type. 109 #define VTABLE_TYPE(exception_name) struct _GLUE2(exception_name,_vtable) 110 #define VTABLE_NAME(exception_name) _GLUE3(_,exception_name,_vtable_instance) 111 112 // VTABLE_FIELD(exception_name); 113 // FORALL_VTABLE_FIELD(exception_name, (parameters-or-types)); 114 // The declaration of the virtual table field. Should be the first declaration in a virtual type. 115 #define VTABLE_FIELD(exception_name) VTABLE_TYPE(exception_name) const * virtual_table 116 #define FORALL_VTABLE_FIELD(exception_name, parameters) \ 117 VTABLE_TYPE(exception_name) parameters const * virtual_table 118 119 // VTABLE_INIT(object_reference, exception_name); 120 // Sets a virtual table field on an object to the virtual table instance for the type. 121 #define VTABLE_INIT(this, exception_name) (this).virtual_table = &VTABLE_NAME(exception_name) 122 123 // VTABLE_ASSERTION(exception_name, (parameters...)) 124 // The assertion that there is an instantiation of the vtable for the exception and types. 125 #define VTABLE_ASSERTION(exception_name, parameters) \ 126 { VTABLE_TYPE(exception_name) parameters VTABLE_NAME(exception_name); } 127 128 // All internal helper macros begin with an underscore. 129 #define _CLOSE(...) __VA_ARGS__ } 130 #define _GLUE2(left, right) left##right 131 #define _GLUE3(left, middle, right) left##middle##right 132 #define _EXC_DISPATCH(to, ...) to(__VA_ARGS__,__cfaehm_base_exception_t,) 133 #define _UNPACK(...) __VA_ARGS__ 134 135 #define _TRIVIAL_EXCEPTION_DECLARATION(exception_name, parent_name, ...) \ 42 136 _VTABLE_DECLARATION(exception_name, parent_name)(); \ 43 137 struct exception_name { \ … … 46 140 void ?{}(exception_name & this); \ 47 141 const char * _GLUE2(exception_name,_msg)(exception_name * this) 48 #define _INST_TRIVIAL_EXCEPTION(exception_name, parent_name, ...) \ 142 143 #define _TRIVIAL_EXCEPTION_INSTANCE(exception_name, parent_name, ...) \ 49 144 void ?{}(exception_name & this) { \ 50 145 VTABLE_INIT(this, exception_name); \ … … 55 150 _VTABLE_INSTANCE(exception_name, parent_name,)(_GLUE2(exception_name,_msg)) 56 151 57 // DATA_EXCEPTION(exception_name)(fields...); 58 // Forward declare an exception that adds fields but no features. The added fields go in the 59 // second argument list. The virtual table instance must be provided later (see VTABLE_INSTANCE). 60 #define DATA_EXCEPTION(...) _EXC_DISPATCH(_DATA_EXCEPTION, __VA_ARGS__) 152 #define _FORALL_TRIVIAL_EXCEPTION(exception_name, parent_name, assertions, \ 153 parameters, parent_parameters) \ 154 _FORALL_VTABLE_DECLARATION(exception_name, parent_name, assertions, \ 155 parameters, parent_parameters)(); \ 156 forall assertions struct exception_name { \ 157 FORALL_VTABLE_FIELD(exception_name, parameters); \ 158 }; \ 159 _FORALL_CTOR0_DECLARATION(exception_name, assertions, parameters) 160 161 #define _FORALL_CTOR0_DECLARATION(exception_name, assertions, parameters) \ 162 forall(_UNPACK assertions | VTABLE_ASSERTION(exception_name, parameters) ) \ 163 void ?{}(exception_name parameters & this) 164 165 #define _FORALL_CTOR0_INSTANCE(exception_name, assertions, parameters) \ 166 _FORALL_CTOR0_DECLARATION(exception_name, assertions, parameters) { \ 167 VTABLE_INIT(this, exception_name); \ 168 } 169 61 170 #define _DATA_EXCEPTION(exception_name, parent_name, ...) \ 62 171 _VTABLE_DECLARATION(exception_name, parent_name)(); \ 63 struct exception_name { VTABLE_FIELD(exception_name); _CLOSE 64 65 // VTABLE_DECLARATION(exception_name)([new_features...]); 66 // Declare a virtual table type for an exception with exception_name. You may also add features 67 // (fields on the virtual table) by including them in the second list. 68 #define VTABLE_DECLARATION(...) _EXC_DISPATCH(_VTABLE_DECLARATION, __VA_ARGS__) 172 struct exception_name { \ 173 VTABLE_FIELD(exception_name); \ 174 _CLOSE 175 176 #define _FORALL_DATA_EXCEPTION(exception_name, parent_name, \ 177 assertions, parameters, parent_parameters) \ 178 _FORALL_VTABLE_DECLARATION(exception_name, parent_name, \ 179 assertions, parameters, parent_parameters)(); \ 180 _FORALL_CTOR0_DECLARATION(exception_name, assertions, parameters); \ 181 forall assertions struct exception_name { \ 182 FORALL_VTABLE_FIELD(exception_name, parameters); \ 183 _CLOSE 184 69 185 #define _VTABLE_DECLARATION(exception_name, parent_name, ...) \ 70 186 struct exception_name; \ 187 void mark_exception(exception_name *); \ 71 188 VTABLE_TYPE(exception_name); \ 72 189 extern VTABLE_TYPE(exception_name) VTABLE_NAME(exception_name); \ … … 79 196 _CLOSE 80 197 81 // VTABLE_INSTANCE(exception_name)(msg [, others...]);82 // Create the instance of the virtual table. There must be exactly one instance of a virtual table83 // for each exception type. This fills in most of the fields of the virtual table (uses ?=? and84 // ^?{}) but you must provide the message function and any other fields added in the declaration.85 #define VTABLE_INSTANCE(...) _EXC_DISPATCH(_VTABLE_INSTANCE, __VA_ARGS__)86 198 #define _VTABLE_INSTANCE(exception_name, parent_name, ...) \ 199 void mark_exception(exception_name *) {} \ 87 200 void _GLUE2(exception_name,_copy)(exception_name * this, exception_name * other) { \ 88 201 *this = *other; \ … … 93 206 _CLOSE 94 207 95 // VTABLE_TYPE(exception_name) | VTABLE_NAME(exception_name) 96 // Get the name of the vtable type or the name of the vtable instance for an exception type. 97 #define VTABLE_TYPE(exception_name) struct _GLUE2(exception_name,_vtable) 98 #define VTABLE_NAME(exception_name) _GLUE3(_,exception_name,_vtable_instance) 99 100 // VTABLE_FIELD(exception_name); 101 // The declaration of the virtual table field. Should be the first declaration in a virtual type. 102 #define VTABLE_FIELD(exception_name) VTABLE_TYPE(exception_name) const * virtual_table 103 104 // VTABLE_INIT(object_reference, exception_name); 105 // Sets a virtual table field on an object to the virtual table instance for the type. 106 #define VTABLE_INIT(this, exception_name) (this).virtual_table = &VTABLE_NAME(exception_name) 208 #define _FORALL_VTABLE_DECLARATION(exception_name, parent_name, assertions, \ 209 parameters, parent_parameters) \ 210 forall assertions struct exception_name; \ 211 forall assertions VTABLE_TYPE(exception_name) { \ 212 VTABLE_TYPE(parent_name) parent_parameters const * parent; \ 213 size_t size; \ 214 void (*copy)(exception_name parameters * this, exception_name parameters * other); \ 215 void (*free)(exception_name parameters & this); \ 216 const char * (*msg)(exception_name parameters * this); \ 217 _CLOSE 218 219 #define _POLY_VTABLE_INSTANCE(exception_name, parent_name, ...) \ 220 void mark_exception(exception_name(__VA_ARGS__) *) {} \ 221 void _GLUE2(exception_name,_copy)( \ 222 exception_name(__VA_ARGS__) * this, exception_name(__VA_ARGS__) * other) { \ 223 *this = *other; \ 224 } \ 225 VTABLE_TYPE(exception_name)(__VA_ARGS__) VTABLE_NAME(exception_name) @= { \ 226 &VTABLE_NAME(parent_name), sizeof(exception_name(__VA_ARGS__)), \ 227 _GLUE2(exception_name,_copy), ^?{}, \ 228 _CLOSE -
libcfa/src/executor.cfa
r07d867b r22f94a4 4 4 // buffer. 5 5 6 #include <bits/containers.hfa>7 6 #include <thread.hfa> 8 #include < stdio.h>7 #include <containers/list.hfa> 9 8 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 9 forall( dtype T | $dlistable(T, T) ) { 10 monitor Buffer { // unbounded buffer 11 dlist( T, T ) queue; // unbounded list of work requests 12 condition delay; 13 }; // Buffer 20 14 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 } // remove 25 } // distribution 15 void insert( Buffer(T) & mutex buf, T * elem ) with(buf) { 16 dlist( T, T ) * qptr = &queue; // workaround https://cforall.uwaterloo.ca/trac/ticket/166 17 insert_last( *qptr, *elem ); // insert element into buffer 18 signal( delay ); // restart 19 } // insert 26 20 27 struct WRequest { // client request, no return 28 void (* action)( void ); 29 WRequest * next; // intrusive queue field 21 T * remove( Buffer(T) & mutex buf ) with(buf) { 22 dlist( T, T ) * qptr = &queue; // workaround https://cforall.uwaterloo.ca/trac/ticket/166 23 // if ( (*qptr)`is_empty ) wait( delay ); // no request to process ? => wait 24 if ( (*qptr)`is_empty ) return 0p; // no request to process ? => wait 25 return &pop_first( *qptr ); 26 } // remove 27 } // forall 28 29 struct WRequest { // client request, no return 30 void (* action)( void ); 31 DLISTED_MGD_IMPL_IN(WRequest) 30 32 }; // WRequest 33 DLISTED_MGD_IMPL_OUT(WRequest) 31 34 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; } 35 void ?{}( WRequest & req ) with(req) { action = 0; } 36 void ?{}( WRequest & req, void (* action)( void ) ) with(req) { req.action = action; } 35 37 bool stop( WRequest & req ) { return req.action == 0; } 36 38 void doit( WRequest & req ) { req.action(); } 37 39 38 // Each worker has its own work buffer to reduce contention between client and server. Hence, work requests arrive and39 // a re distributed into buffers in a roughly round-robin order.40 // Each worker has its own set (when requests buffers > workers) of work buffers to reduce contention between client 41 // and server, where work requests arrive and are distributed into buffers in a roughly round-robin order. 40 42 41 43 thread Worker { 42 Buffer( WRequest ) * requests; 43 unsigned int start, range; 44 Buffer(WRequest) * requests; 45 WRequest * request; 46 unsigned int start, range; 44 47 }; // Worker 45 48 46 49 void main( Worker & w ) with(w) { 47 for ( int i = 0;; i = (i + 1) % range ) {48 WRequest *request = remove( requests[i + start] );49 if ( ! request ) { yield(); continue; }50 if ( stop( *request ) ) break;51 doit( *request );52 delete( request );53 } // for50 for ( int i = 0;; i = (i + 1) % range ) { 51 request = remove( requests[i + start] ); 52 if ( ! request ) { yield(); continue; } 53 if ( stop( *request ) ) break; 54 doit( *request ); 55 delete( request ); 56 } // for 54 57 } // Worker::main 55 58 56 void ?{}( Worker & worker, cluster * wc, Buffer( WRequest) * requests, unsigned int start, unsigned int range ) {57 (*get_thread(worker)){ *wc }; // create on given cluster 58 worker.[requests, start, range] = [requests, start, range];59 void ?{}( Worker & worker, cluster * wc, Buffer(WRequest) * requests, unsigned int start, unsigned int range ) { 60 ((thread &)worker){ *wc }; 61 worker.[requests, request, start, range] = [requests, 0p, start, range]; 59 62 } // ?{} 60 63 64 WRequest * current_request( Worker & worker ) { return worker.request; } 65 61 66 struct Executor { 62 cluster * cluster; // if workers execute on separate cluster 63 processor ** processors; // array of virtual processors adding parallelism for workers 64 Buffer( WRequest ) * requests; // list of work requests 65 Worker ** workers; // array of workers executing work requests 66 unsigned int nprocessors, nworkers, nmailboxes; // number of mailboxes/workers/processor tasks 67 bool sepClus; // use same or separate cluster for executor 67 cluster * cluster; // if workers execute on separate cluster 68 processor ** processors; // array of virtual processors adding parallelism for workers 69 Buffer(WRequest) * requests; // list of work requests 70 Worker ** workers; // array of workers executing work requests 71 unsigned int nprocessors, nworkers, nrqueues; // number of processors/threads/request queues 72 bool sepClus; // use same or separate cluster for executor 73 unsigned int next; // demultiplexed across worker buffers 68 74 }; // Executor 69 75 70 static thread_local unsigned int next; // demultiplexed across worker buffers71 76 unsigned int tickets( Executor & ex ) with(ex) { 72 //return uFetchAdd( next, 1 ) % nmailboxes;73 return next++ % nmailboxes;// no locking, interference randomizes77 //return uFetchAdd( next, 1 ) % nrqueues; 78 return next++ % nrqueues; // no locking, interference randomizes 74 79 } // tickets 75 80 76 void ?{}( Executor & ex, unsigned int np, unsigned int nw, unsigned int n m, bool sc = false ) with(ex) {77 [nprocessors, nworkers, nmailboxes, sepClus] = [np, nw, nm, sc];78 assert( nmailboxes >= nworkers );79 cluster = sepClus ? new( "Executor" ) : active_cluster();80 processors = (processor **)anew( nprocessors );81 requests = anew( nmailboxes );82 workers = (Worker **)anew( nworkers );81 void ?{}( Executor & ex, unsigned int np, unsigned int nw, unsigned int nr, bool sc = false ) with(ex) { 82 [nprocessors, nworkers, nrqueues, sepClus] = [np, nw, nr, sc]; 83 assert( nrqueues >= nworkers ); 84 cluster = sepClus ? new( "Executor" ) : active_cluster(); 85 processors = aalloc( nprocessors ); 86 requests = anew( nrqueues ); 87 workers = aalloc( nworkers ); 83 88 84 for ( i; nprocessors ) {85 processors[ i] = new( *cluster );86 } // for89 for ( i; nprocessors ) { 90 processors[i] = new( *cluster ); 91 } // for 87 92 88 unsigned int reqPerWorker = nmailboxes / nworkers, extras = nmailboxes % nworkers; 89 for ( unsigned int i = 0, step = 0; i < nworkers; i += 1, step += reqPerWorker + ( i < extras ? 1 : 0 ) ) { 90 workers[ i ] = new( cluster, requests, step, reqPerWorker + ( i < extras ? 1 : 0 ) ); 91 } // for 93 unsigned int reqPerWorker = nrqueues / nworkers, extras = nrqueues % nworkers; 94 // for ( unsigned int i = 0, start = 0, range; i < nworkers; i += 1, start += range ) { 95 for ( i; nworkers : start; 0u ~ @ ~ range : range; ) { 96 range = reqPerWorker + ( i < extras ? 1 : 0 ); 97 workers[i] = new( cluster, requests, start, range ); 98 } // for 92 99 } // ?{} 93 100 94 101 void ?{}( Executor & ex, unsigned int nprocessors, unsigned int nworkers, bool sepClus = false ) { 95 ex{ nprocessors, nworkers, nworkers, sepClus };102 ex{ nprocessors, nworkers, nworkers, sepClus }; 96 103 } 97 104 void ?{}( Executor & ex, unsigned int nprocessors, bool sepClus = false ) { 98 ex{ nprocessors, nprocessors, nprocessors, sepClus };105 ex{ nprocessors, nprocessors, nprocessors, sepClus }; 99 106 } 100 void ?{}( Executor & ex ) { // special for current cluster101 ex{ 0, active_cluster()->nprocessors, false };107 void ?{}( Executor & ex ) { // special for current cluster, no processors added 108 ex{ 0, active_cluster()->nprocessors, false }; 102 109 } 103 110 void ^?{}( Executor & ex ) with(ex) { 104 // Add one sentinel per worker to stop them. Since in destructor, no new work should be queued. Cannot combine next105 // two loops and only have a single sentinel because workers arrive in arbitrary order, so worker1 may take the 106 //single sentinel while waiting for worker 0 to end.111 // Add one sentinel per worker to stop them. Since in destructor, no new external work should be queued. Cannot 112 // combine next two loops and only have a single sentinel because workers arrive in arbitrary order, so worker1 may 113 // take the single sentinel while waiting for worker 0 to end. 107 114 108 WRequest sentinel[nworkers];109 unsigned int reqPerWorker = nmailboxes / nworkers;110 for ( unsigned int i = 0, step = 0; i < nworkers; i += 1, step += reqPerWorker ) {111 insert( requests[step], &sentinel[i] );// force eventually termination112 } // for113 for ( i; nworkers ) {114 delete( workers[ i] );115 } // for116 for ( i; nprocessors ) {117 delete( processors[ i] );118 } // for115 WRequest sentinel[nworkers]; 116 unsigned int reqPerWorker = nrqueues / nworkers; 117 for ( unsigned int i = 0, step = 0; i < nworkers; i += 1, step += reqPerWorker ) { 118 insert( requests[step], &sentinel[i] ); // force eventually termination 119 } // for 120 for ( i; nworkers ) { 121 delete( workers[i] ); 122 } // for 123 for ( i; nprocessors ) { 124 delete( processors[i] ); 125 } // for 119 126 120 delete( workers ); 121 delete( requests ); 122 delete( processors ); 123 if ( sepClus ) { delete( cluster ); } 127 free( workers ); 128 // adelete( nrqueues, requests ); 129 for ( i; nrqueues ) ^?{}( requests[i] ); // FIX ME: problem with resolver 130 free( requests ); 131 free( processors ); 132 if ( sepClus ) { delete( cluster ); } 124 133 } // ^?{} 125 134 126 135 void send( Executor & ex, void (* action)( void ) ) { // asynchronous call, no return value 127 WRequest * node = new( action );128 insert( ex.requests[tickets( ex )], node );136 WRequest * node = new( action ); 137 insert( ex.requests[tickets( ex )], node ); 129 138 } // send 139 130 140 131 141 int counter = 0; 132 142 133 void work ie( void ) {134 __atomic_add_fetch( &counter, 1, __ATOMIC_SEQ_CST );135 //fprintf( stderr, "workie\n" );143 void work( void ) { 144 __atomic_add_fetch( &counter, 1, __ATOMIC_SEQ_CST ); 145 // fprintf( stderr, "workie\n" ); 136 146 } 137 147 138 int main() { 139 { 140 Executor exector; 141 for ( i; 3000 ) { 142 send( exector, workie ); 143 if ( i % 100 ) yield(); 144 } // for 145 } 146 printf( "%d\n", counter ); 148 int main( int argc, char * argv[] ) { 149 int times = 1_000_000; 150 if ( argc == 2 ) times = atoi( argv[1] ); 151 processor p[7]; 152 { 153 Executor exector; 154 for ( i; times ) { 155 send( exector, work ); 156 if ( i % 100 == 0 ) yield(); 157 } // for 158 } 159 printf( "%d\n", counter ); 147 160 } 148 161 149 162 // Local Variables: // 163 // tab-width: 4" // 150 164 // compile-command: "cfa executor.cfa" // 151 165 // End: // -
libcfa/src/fstream.cfa
r07d867b r22f94a4 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Feb 7 19:01:01202013 // Update Count : 3 6312 // Last Modified On : Fri Jun 19 16:24:54 2020 13 // Update Count : 384 14 14 // 15 15 … … 26 26 27 27 28 // *********************************** ofstream ***********************************28 // *********************************** ofstream *********************************** 29 29 30 30 … … 123 123 #ifdef __CFA_DEBUG__ 124 124 if ( file == 0p ) { 125 abort | IO_MSG "open output file \"" | name | "\"" | nl | strerror( errno ); 125 throw (Open_Failure){ os }; 126 // abort | IO_MSG "open output file \"" | name | "\"" | nl | strerror( errno ); 126 127 } // if 127 128 #endif // __CFA_DEBUG__ … … 134 135 135 136 void close( ofstream & os ) { 136 if ( (FILE *)(os.$file) == stdout || (FILE *)(os.$file) == stderr ) return; 137 if ( (FILE *)(os.$file) == 0p ) return; 138 if ( (FILE *)(os.$file) == (FILE *)stdout || (FILE *)(os.$file) == (FILE *)stderr ) return; 137 139 138 140 if ( fclose( (FILE *)(os.$file) ) == EOF ) { 139 141 abort | IO_MSG "close output" | nl | strerror( errno ); 140 142 } // if 143 os.$file = 0p; 141 144 } // close 142 145 … … 179 182 180 183 181 // *********************************** ifstream ***********************************184 // *********************************** ifstream *********************************** 182 185 183 186 … … 219 222 #ifdef __CFA_DEBUG__ 220 223 if ( file == 0p ) { 221 abort | IO_MSG "open input file \"" | name | "\"" | nl | strerror( errno ); 224 throw (Open_Failure){ is }; 225 // abort | IO_MSG "open input file \"" | name | "\"" | nl | strerror( errno ); 222 226 } // if 223 227 #endif // __CFA_DEBUG__ … … 230 234 231 235 void close( ifstream & is ) { 232 if ( (FILE *)(is.$file) == stdin ) return; 236 if ( (FILE *)(is.$file) == 0p ) return; 237 if ( (FILE *)(is.$file) == (FILE *)stdin ) return; 233 238 234 239 if ( fclose( (FILE *)(is.$file) ) == EOF ) { 235 240 abort | IO_MSG "close input" | nl | strerror( errno ); 236 241 } // if 242 is.$file = 0p; 237 243 } // close 238 244 … … 276 282 ifstream & sin = sinFile, & stdin = sinFile; 277 283 284 285 // *********************************** exceptions *********************************** 286 287 288 void ?{}( Open_Failure & this, ofstream & ostream ) { 289 VTABLE_INIT(this, Open_Failure); 290 this.ostream = &ostream; 291 this.tag = 1; 292 } 293 void ?{}( Open_Failure & this, ifstream & istream ) { 294 VTABLE_INIT(this, Open_Failure); 295 this.istream = &istream; 296 this.tag = 0; 297 } 298 const char * Open_Failure_msg(Open_Failure * this) { 299 return "Open_Failure"; 300 } 301 VTABLE_INSTANCE(Open_Failure)(Open_Failure_msg); 302 void throwOpen_Failure( ofstream & ostream ) { 303 Open_Failure exc = { ostream }; 304 } 305 void throwOpen_Failure( ifstream & istream ) { 306 Open_Failure exc = { istream }; 307 } 308 278 309 // Local Variables: // 279 310 // tab-width: 4 // -
libcfa/src/fstream.hfa
r07d867b r22f94a4 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Feb 17 08:29:23202013 // Update Count : 1 7512 // Last Modified On : Fri Jun 19 16:29:17 2020 13 // Update Count : 189 14 14 // 15 15 … … 17 17 18 18 #include "iostream.hfa" 19 #include <exception.hfa> 19 20 20 21 21 // *********************************** ofstream ***********************************22 // *********************************** ofstream *********************************** 22 23 23 24 … … 78 79 79 80 80 // *********************************** ifstream ***********************************81 // *********************************** ifstream *********************************** 81 82 82 83 … … 106 107 extern ifstream & sin, & stdin; // aliases 107 108 109 110 // *********************************** exceptions *********************************** 111 112 113 DATA_EXCEPTION(Open_Failure)( 114 union { 115 ofstream * ostream; 116 ifstream * istream; 117 }; 118 // TEMPORARY: need polymorphic exceptions 119 int tag; // 1 => ostream; 0 => istream 120 ); 121 122 void ?{}( Open_Failure & this, ofstream & ostream ); 123 void ?{}( Open_Failure & this, ifstream & istream ); 124 108 125 // Local Variables: // 109 126 // mode: c // -
libcfa/src/heap.cfa
r07d867b r22f94a4 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // heap.c --7 // heap.cfa -- 8 8 // 9 9 // Author : Peter A. Buhr 10 10 // Created On : Tue Dec 19 21:58:35 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed May 6 17:29:26202013 // Update Count : 72712 // Last Modified On : Sun Aug 9 12:23:20 2020 13 // Update Count : 894 14 14 // 15 15 … … 20 20 #include <string.h> // memset, memcpy 21 21 #include <limits.h> // ULONG_MAX 22 extern "C" { 22 #include <malloc.h> // memalign, malloc_usable_size 23 23 #include <sys/mman.h> // mmap, munmap 24 } // extern "C" 25 26 #include "bits/align.hfa" // libPow2 24 25 #include "bits/align.hfa" // libAlign 27 26 #include "bits/defs.hfa" // likely, unlikely 28 27 #include "bits/locks.hfa" // __spinlock_t 29 28 #include "startup.hfa" // STARTUP_PRIORITY_MEMORY 30 29 //#include "stdlib.hfa" // bsearchl 31 #include "malloc.h"32 30 #include "bitmanip.hfa" // ceiling 33 31 … … 82 80 }; 83 81 82 size_t default_mmap_start() __attribute__(( weak )) { 83 return __CFA_DEFAULT_MMAP_START__; 84 } // default_mmap_start 85 84 86 size_t default_heap_expansion() __attribute__(( weak )) { 85 87 return __CFA_DEFAULT_HEAP_EXPANSION__; 86 88 } // default_heap_expansion 87 89 88 size_t default_mmap_start() __attribute__(( weak )) {89 return __CFA_DEFAULT_MMAP_START__;90 } // default_mmap_start91 92 90 93 91 #ifdef __CFA_DEBUG__ 94 static unsigned int allocFree;// running total of allocations minus frees92 static size_t allocUnfreed; // running total of allocations minus frees 95 93 96 94 static void prtUnfreed() { 97 if ( alloc Free!= 0 ) {95 if ( allocUnfreed != 0 ) { 98 96 // DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT. 99 97 char helpText[512]; 100 int len = snprintf( helpText, sizeof(helpText), "CFA warning (UNIX pid:%ld) : program terminating with % u(0x%x) bytes of storage allocated but not freed.\n"98 int len = snprintf( helpText, sizeof(helpText), "CFA warning (UNIX pid:%ld) : program terminating with %zu(0x%zx) bytes of storage allocated but not freed.\n" 101 99 "Possible cause is unfreed storage allocated by the program or system/library routines called from the program.\n", 102 (long int)getpid(), alloc Free, allocFree); // always print the UNIX pid100 (long int)getpid(), allocUnfreed, allocUnfreed ); // always print the UNIX pid 103 101 __cfaabi_bits_write( STDERR_FILENO, helpText, len ); // print debug/nodebug 104 102 } // if … … 107 105 extern "C" { 108 106 void heapAppStart() { // called by __cfaabi_appready_startup 109 alloc Free= 0;107 allocUnfreed = 0; 110 108 } // heapAppStart 111 109 … … 128 126 #define LOCKFREE 1 129 127 #define BUCKETLOCK SPINLOCK 130 #if BUCKETLOCK == LOCKFREE 131 #include <uStackLF.h> 128 #if BUCKETLOCK == SPINLOCK 129 #elif BUCKETLOCK == LOCKFREE 130 #include <stackLockFree.hfa> 131 #else 132 #error undefined lock type for bucket lock 132 133 #endif // LOCKFREE 133 134 … … 137 138 138 139 struct HeapManager { 139 // struct FreeHeader; // forward declaration140 141 140 struct Storage { 142 141 struct Header { // header … … 146 145 struct { // 4-byte word => 8-byte header, 8-byte word => 16-byte header 147 146 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ && __SIZEOF_POINTER__ == 4 148 uint 32_t padding; // unused, force home/blocksize to overlay alignment in fake header147 uint64_t padding; // unused, force home/blocksize to overlay alignment in fake header 149 148 #endif // __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ && __SIZEOF_POINTER__ == 4 150 149 151 150 union { 152 //FreeHeader * home; // allocated block points back to home locations (must overlay alignment)151 // FreeHeader * home; // allocated block points back to home locations (must overlay alignment) 153 152 // 2nd low-order bit => zero filled 154 153 void * home; // allocated block points back to home locations (must overlay alignment) 155 154 size_t blockSize; // size for munmap (must overlay alignment) 156 #if BUCK LOCK == SPINLOCK155 #if BUCKETLOCK == SPINLOCK 157 156 Storage * next; // freed block points next freed block of same size 158 157 #endif // SPINLOCK 159 158 }; 159 size_t size; // allocation size in bytes 160 160 161 161 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ && __SIZEOF_POINTER__ == 4 162 uint 32_t padding; // unused, force home/blocksize to overlay alignment in fake header162 uint64_t padding; // unused, force home/blocksize to overlay alignment in fake header 163 163 #endif // __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ && __SIZEOF_POINTER__ == 4 164 164 }; 165 // future code 166 #if BUCKLOCK == LOCKFREE 167 Stack<Storage>::Link next; // freed block points next freed block of same size (double-wide) 165 #if BUCKETLOCK == LOCKFREE 166 Link(Storage) next; // freed block points next freed block of same size (double-wide) 168 167 #endif // LOCKFREE 169 168 }; 170 169 } real; // RealHeader 170 171 171 struct FakeHeader { 172 172 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 173 // 1st low-order bit => fake header & alignment 174 uint32_t alignment; 173 uint32_t alignment; // 1st low-order bit => fake header & alignment 175 174 #endif // __ORDER_LITTLE_ENDIAN__ 176 175 … … 182 181 } fake; // FakeHeader 183 182 } kind; // Kind 184 size_t size; // allocation size in bytes185 183 } header; // Header 186 184 char pad[libAlign() - sizeof( Header )]; … … 191 189 192 190 struct FreeHeader { 193 #if BUCK LOCK == SPINLOCK191 #if BUCKETLOCK == SPINLOCK 194 192 __spinlock_t lock; // must be first field for alignment 195 193 Storage * freeList; 196 #elif BUCKLOCK == LOCKFREE197 // future code198 StackLF<Storage> freeList;199 194 #else 200 #error undefined lock type for bucket lock201 #endif // SPINLOCK195 StackLF(Storage) freeList; 196 #endif // BUCKETLOCK 202 197 size_t blockSize; // size of allocations on this list 203 198 }; // FreeHeader … … 212 207 }; // HeapManager 213 208 209 #if BUCKETLOCK == LOCKFREE 210 static inline { 211 Link(HeapManager.Storage) * ?`next( HeapManager.Storage * this ) { return &this->header.kind.real.next; } 212 void ?{}( HeapManager.FreeHeader & ) {} 213 void ^?{}( HeapManager.FreeHeader & ) {} 214 } // distribution 215 #endif // LOCKFREE 216 214 217 static inline size_t getKey( const HeapManager.FreeHeader & freeheader ) { return freeheader.blockSize; } 215 218 … … 218 221 #define __STATISTICS__ 219 222 220 // Bucket size must be multiple of 16. 221 // Powers of 2 are common allocation sizes, so make powers of 2 generate the minimum required size. 223 // Size of array must harmonize with NoBucketSizes and individual bucket sizes must be multiple of 16. 224 // Smaller multiples of 16 and powers of 2 are common allocation sizes, so make them generate the minimum required bucket size. 225 // malloc(0) returns 0p, so no bucket is necessary for 0 bytes returning an address that can be freed. 222 226 static const unsigned int bucketSizes[] @= { // different bucket sizes 223 16 , 32, 48, 64 + sizeof(HeapManager.Storage), // 4224 96 , 112, 128 + sizeof(HeapManager.Storage), // 3227 16 + sizeof(HeapManager.Storage), 32 + sizeof(HeapManager.Storage), 48 + sizeof(HeapManager.Storage), 64 + sizeof(HeapManager.Storage), // 4 228 96 + sizeof(HeapManager.Storage), 112 + sizeof(HeapManager.Storage), 128 + sizeof(HeapManager.Storage), // 3 225 229 160, 192, 224, 256 + sizeof(HeapManager.Storage), // 4 226 230 320, 384, 448, 512 + sizeof(HeapManager.Storage), // 4 … … 240 244 }; 241 245 242 static_assert( NoBucketSizes == sizeof(bucketSizes) / sizeof(bucketSizes[0] ), "size of bucket array wrong" );246 static_assert( NoBucketSizes == sizeof(bucketSizes) / sizeof(bucketSizes[0] ), "size of bucket array wrong" ); 243 247 244 248 #ifdef FASTLOOKUP … … 251 255 static bool heapBoot = 0; // detect recursion during boot 252 256 #endif // __CFA_DEBUG__ 257 258 // The constructor for heapManager is called explicitly in memory_startup. 253 259 static HeapManager heapManager __attribute__(( aligned (128) )) @= {}; // size of cache line to prevent false sharing 254 260 … … 256 262 #ifdef __STATISTICS__ 257 263 // Heap statistics counters. 264 static unsigned int malloc_calls; 265 static unsigned long long int malloc_storage; 266 static unsigned int aalloc_calls; 267 static unsigned long long int aalloc_storage; 268 static unsigned int calloc_calls; 269 static unsigned long long int calloc_storage; 270 static unsigned int memalign_calls; 271 static unsigned long long int memalign_storage; 272 static unsigned int amemalign_calls; 273 static unsigned long long int amemalign_storage; 274 static unsigned int cmemalign_calls; 275 static unsigned long long int cmemalign_storage; 276 static unsigned int resize_calls; 277 static unsigned long long int resize_storage; 278 static unsigned int realloc_calls; 279 static unsigned long long int realloc_storage; 280 static unsigned int free_calls; 281 static unsigned long long int free_storage; 282 static unsigned int mmap_calls; 258 283 static unsigned long long int mmap_storage; 259 static unsigned int m map_calls;284 static unsigned int munmap_calls; 260 285 static unsigned long long int munmap_storage; 261 static unsigned int munmap_calls;286 static unsigned int sbrk_calls; 262 287 static unsigned long long int sbrk_storage; 263 static unsigned int sbrk_calls;264 static unsigned long long int malloc_storage;265 static unsigned int malloc_calls;266 static unsigned long long int free_storage;267 static unsigned int free_calls;268 static unsigned long long int aalloc_storage;269 static unsigned int aalloc_calls;270 static unsigned long long int calloc_storage;271 static unsigned int calloc_calls;272 static unsigned long long int memalign_storage;273 static unsigned int memalign_calls;274 static unsigned long long int amemalign_storage;275 static unsigned int amemalign_calls;276 static unsigned long long int cmemalign_storage;277 static unsigned int cmemalign_calls;278 static unsigned long long int resize_storage;279 static unsigned int resize_calls;280 static unsigned long long int realloc_storage;281 static unsigned int realloc_calls;282 288 // Statistics file descriptor (changed by malloc_stats_fd). 283 static int stat fd = STDERR_FILENO; // default stderr289 static int stat_fd = STDERR_FILENO; // default stderr 284 290 285 291 // Use "write" because streams may be shutdown when calls are made. … … 301 307 " sbrk: calls %u / storage %llu\n", 302 308 malloc_calls, malloc_storage, 303 aalloc_calls, calloc_storage,309 aalloc_calls, aalloc_storage, 304 310 calloc_calls, calloc_storage, 305 311 memalign_calls, memalign_storage, … … 354 360 355 361 356 // static inline void noMemory() {357 // abort( "Heap memory exhausted at %zu bytes.\n"358 // "Possible cause is very large memory allocation and/or large amount of unfreed storage allocated by the program or system/library routines.",359 // ((char *)(sbrk( 0 )) - (char *)(heapManager.heapBegin)) );360 // } // noMemory361 362 363 362 // thunk problem 364 363 size_t Bsearchl( unsigned int key, const unsigned int * vals, size_t dim ) { … … 407 406 408 407 static inline void checkAlign( size_t alignment ) { 409 if ( alignment < libAlign() || ! libPow2( alignment ) ) {408 if ( alignment < libAlign() || ! is_pow2( alignment ) ) { 410 409 abort( "Alignment %zu for memory allocation is less than %d and/or not a power of 2.", alignment, libAlign() ); 411 410 } // if … … 429 428 #endif // __CFA_DEBUG__ 430 429 header = realHeader( header ); // backup from fake to real header 430 } else { 431 alignment = libAlign(); // => no fake header 431 432 } // if 432 433 } // fakeHeader 433 434 434 435 435 static inline bool headers( const char name[] __attribute__(( unused )), void * addr, HeapManager.Storage.Header *& header, HeapManager.FreeHeader *& freeElem, size_t & size, size_t & alignment ) with ( heapManager ) { 436 static inline bool headers( const char name[] __attribute__(( unused )), void * addr, HeapManager.Storage.Header *& header, HeapManager.FreeHeader *& freeElem, 437 size_t & size, size_t & alignment ) with( heapManager ) { 436 438 header = headerAddr( addr ); 437 439 438 if ( unlikely( heapEnd < addr ) ) { // mmapped ?440 if ( unlikely( heapEnd < addr ) ) { // mmapped ? 439 441 fakeHeader( header, alignment ); 440 442 size = header->kind.real.blockSize & -3; // mmap size … … 464 466 } // headers 465 467 466 467 static inline void * extend( size_t size ) with ( heapManager ) { 468 #define NO_MEMORY_MSG "insufficient heap memory available for allocating %zd new bytes." 469 470 static inline void * extend( size_t size ) with( heapManager ) { 468 471 lock( extlock __cfaabi_dbg_ctx2 ); 469 472 ptrdiff_t rem = heapRemaining - size; … … 471 474 // If the size requested is bigger than the current remaining storage, increase the size of the heap. 472 475 473 size_t increase = libCeiling( size > heapExpand ? size : heapExpand, libAlign() );474 if ( sbrk( increase ) == (void *)-1 ) { 476 size_t increase = ceiling2( size > heapExpand ? size : heapExpand, libAlign() ); 477 if ( sbrk( increase ) == (void *)-1 ) { // failed, no memory ? 475 478 unlock( extlock ); 476 errno = ENOMEM; 477 return 0p; 479 abort( NO_MEMORY_MSG, size ); // give up 478 480 } // if 479 481 #ifdef __STATISTICS__ … … 496 498 497 499 498 static inline void * doMalloc( size_t size ) with ( heapManager ) {500 static inline void * doMalloc( size_t size ) with( heapManager ) { 499 501 HeapManager.Storage * block; // pointer to new block of storage 500 502 … … 512 514 posn = Bsearchl( (unsigned int)tsize, bucketSizes, (size_t)maxBucketsUsed ); 513 515 HeapManager.FreeHeader * freeElem = &freeLists[posn]; 514 // #ifdef FASTLOOKUP 515 // if ( tsize < LookupSizes ) 516 // freeElem = &freeLists[lookup[tsize]]; 517 // else 518 // #endif // FASTLOOKUP 519 // freeElem = bsearchl( tsize, freeLists, (size_t)maxBucketsUsed ); // binary search 520 // HeapManager.FreeHeader * freeElem = 521 // #ifdef FASTLOOKUP 522 // tsize < LookupSizes ? &freeLists[lookup[tsize]] : 523 // #endif // FASTLOOKUP 524 // bsearchl( tsize, freeLists, (size_t)maxBucketsUsed ); // binary search 525 assert( freeElem <= &freeLists[maxBucketsUsed] ); // subscripting error ? 526 assert( tsize <= freeElem->blockSize ); // search failure ? 516 verify( freeElem <= &freeLists[maxBucketsUsed] ); // subscripting error ? 517 verify( tsize <= freeElem->blockSize ); // search failure ? 527 518 tsize = freeElem->blockSize; // total space needed for request 528 519 529 520 // Spin until the lock is acquired for this particular size of block. 530 521 531 #if defined( SPINLOCK )522 #if BUCKETLOCK == SPINLOCK 532 523 lock( freeElem->lock __cfaabi_dbg_ctx2 ); 533 524 block = freeElem->freeList; // remove node from stack 534 525 #else 535 block = freeElem->freeList.pop();536 #endif // SPINLOCK526 block = pop( freeElem->freeList ); 527 #endif // BUCKETLOCK 537 528 if ( unlikely( block == 0p ) ) { // no free block ? 538 #if defined( SPINLOCK )529 #if BUCKETLOCK == SPINLOCK 539 530 unlock( freeElem->lock ); 540 #endif // SPINLOCK531 #endif // BUCKETLOCK 541 532 542 533 // Freelist for that size was empty, so carve it out of the heap if there's enough left, or get some more … … 544 535 545 536 block = (HeapManager.Storage *)extend( tsize ); // mutual exclusion on call 546 if ( unlikely( block == 0p ) ) return 0p; 547 #if defined( SPINLOCK ) 537 #if BUCKETLOCK == SPINLOCK 548 538 } else { 549 539 freeElem->freeList = block->header.kind.real.next; 550 540 unlock( freeElem->lock ); 551 #endif // SPINLOCK541 #endif // BUCKETLOCK 552 542 } // if 553 543 … … 555 545 } else { // large size => mmap 556 546 if ( unlikely( size > ULONG_MAX - pageSize ) ) return 0p; 557 tsize = libCeiling( tsize, pageSize ); // must be multiple of page size547 tsize = ceiling2( tsize, pageSize ); // must be multiple of page size 558 548 #ifdef __STATISTICS__ 559 549 __atomic_add_fetch( &mmap_calls, 1, __ATOMIC_SEQ_CST ); 560 550 __atomic_add_fetch( &mmap_storage, tsize, __ATOMIC_SEQ_CST ); 561 551 #endif // __STATISTICS__ 552 562 553 block = (HeapManager.Storage *)mmap( 0, tsize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, mmapFd, 0 ); 563 if ( block == (HeapManager.Storage *)MAP_FAILED ) { 554 if ( block == (HeapManager.Storage *)MAP_FAILED ) { // failed ? 555 if ( errno == ENOMEM ) abort( NO_MEMORY_MSG, tsize ); // no memory 564 556 // Do not call strerror( errno ) as it may call malloc. 565 557 abort( "(HeapManager &)0x%p.doMalloc() : internal error, mmap failure, size:%zu error:%d.", &heapManager, tsize, errno ); 566 } // if558 } //if 567 559 #ifdef __CFA_DEBUG__ 568 560 // Set new memory to garbage so subsequent uninitialized usages might fail. … … 572 564 } // if 573 565 574 block->header. size = size;// store allocation size566 block->header.kind.real.size = size; // store allocation size 575 567 void * addr = &(block->data); // adjust off header to user bytes 568 verify( ((uintptr_t)addr & (libAlign() - 1)) == 0 ); // minimum alignment ? 576 569 577 570 #ifdef __CFA_DEBUG__ 578 assert( ((uintptr_t)addr & (libAlign() - 1)) == 0 ); // minimum alignment ? 579 __atomic_add_fetch( &allocFree, tsize, __ATOMIC_SEQ_CST ); 571 __atomic_add_fetch( &allocUnfreed, tsize, __ATOMIC_SEQ_CST ); 580 572 if ( traceHeap() ) { 581 573 enum { BufferSize = 64 }; 582 574 char helpText[BufferSize]; 583 575 int len = snprintf( helpText, BufferSize, "%p = Malloc( %zu ) (allocated %zu)\n", addr, size, tsize ); 584 // int len = snprintf( helpText, BufferSize, "Malloc %p %zu\n", addr, size );585 576 __cfaabi_bits_write( STDERR_FILENO, helpText, len ); // print debug/nodebug 586 577 } // if … … 591 582 592 583 593 static inline void doFree( void * addr ) with ( heapManager ) {584 static inline void doFree( void * addr ) with( heapManager ) { 594 585 #ifdef __CFA_DEBUG__ 595 586 if ( unlikely( heapManager.heapBegin == 0p ) ) { … … 623 614 free_storage += size; 624 615 #endif // __STATISTICS__ 625 #if defined( SPINLOCK )616 #if BUCKETLOCK == SPINLOCK 626 617 lock( freeElem->lock __cfaabi_dbg_ctx2 ); // acquire spin lock 627 618 header->kind.real.next = freeElem->freeList; // push on stack … … 629 620 unlock( freeElem->lock ); // release spin lock 630 621 #else 631 freeElem->freeList.push(*(HeapManager.Storage *)header );632 #endif // SPINLOCK622 push( freeElem->freeList, *(HeapManager.Storage *)header ); 623 #endif // BUCKETLOCK 633 624 } // if 634 625 635 626 #ifdef __CFA_DEBUG__ 636 __atomic_add_fetch( &alloc Free, -size, __ATOMIC_SEQ_CST );627 __atomic_add_fetch( &allocUnfreed, -size, __ATOMIC_SEQ_CST ); 637 628 if ( traceHeap() ) { 638 enum { BufferSize = 64 }; 639 char helpText[BufferSize]; 629 char helpText[64]; 640 630 int len = snprintf( helpText, sizeof(helpText), "Free( %p ) size:%zu\n", addr, size ); 641 631 __cfaabi_bits_write( STDERR_FILENO, helpText, len ); // print debug/nodebug … … 645 635 646 636 647 size_t prtFree( HeapManager & manager ) with ( manager ) {637 size_t prtFree( HeapManager & manager ) with( manager ) { 648 638 size_t total = 0; 649 639 #ifdef __STATISTICS__ … … 657 647 #endif // __STATISTICS__ 658 648 659 #if defined( SPINLOCK )649 #if BUCKETLOCK == SPINLOCK 660 650 for ( HeapManager.Storage * p = freeLists[i].freeList; p != 0p; p = p->header.kind.real.next ) { 661 651 #else 662 for ( HeapManager.Storage * p = freeLists[i].freeList.top(); p != 0p; p = p->header.kind.real.next.top ) {663 #endif // SPINLOCK652 for ( HeapManager.Storage * p = top( freeLists[i].freeList ); p != 0p; p = (p)`next->top ) { 653 #endif // BUCKETLOCK 664 654 total += size; 665 655 #ifdef __STATISTICS__ … … 681 671 682 672 683 static void ?{}( HeapManager & manager ) with ( manager ) {673 static void ?{}( HeapManager & manager ) with( manager ) { 684 674 pageSize = sysconf( _SC_PAGESIZE ); 685 675 … … 702 692 703 693 char * end = (char *)sbrk( 0 ); 704 heapBegin = heapEnd = sbrk( (char *) libCeiling( (long unsigned int)end, libAlign() ) - end ); // move start of heap to multiple of alignment694 heapBegin = heapEnd = sbrk( (char *)ceiling2( (long unsigned int)end, libAlign() ) - end ); // move start of heap to multiple of alignment 705 695 } // HeapManager 706 696 … … 710 700 if ( traceHeapTerm() ) { 711 701 printStats(); 712 // if ( prtfree() ) prtFree( heapManager, true );702 // prtUnfreed() called in heapAppStop() 713 703 } // if 714 704 #endif // __STATISTICS__ … … 719 709 void memory_startup( void ) { 720 710 #ifdef __CFA_DEBUG__ 721 if ( unlikely( heapBoot ) ) {// check for recursion during system boot711 if ( heapBoot ) { // check for recursion during system boot 722 712 // DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT. 723 713 abort( "boot() : internal error, recursively invoked during system boot." ); … … 726 716 #endif // __CFA_DEBUG__ 727 717 728 // assert( heapManager.heapBegin != 0 );718 //verify( heapManager.heapBegin != 0 ); 729 719 //heapManager{}; 730 720 if ( heapManager.heapBegin == 0p ) heapManager{}; // sanity check … … 738 728 739 729 static inline void * mallocNoStats( size_t size ) { // necessary for malloc statistics 740 //assert( heapManager.heapBegin != 0 ); 741 if ( unlikely( heapManager.heapBegin == 0p ) ) heapManager{}; // called before memory_startup ? 730 verify( heapManager.heapBegin != 0p ); // called before memory_startup ? 731 if ( unlikely( size ) == 0 ) return 0p; // 0 BYTE ALLOCATION RETURNS NULL POINTER 732 742 733 #if __SIZEOF_POINTER__ == 8 743 734 verify( size < ((typeof(size_t))1 << 48) ); 744 735 #endif // __SIZEOF_POINTER__ == 8 745 void * addr = doMalloc( size ); 746 if ( unlikely( addr == 0p ) ) errno = ENOMEM; // POSIX 747 return addr; 736 return doMalloc( size ); 748 737 } // mallocNoStats 749 738 … … 751 740 static inline void * callocNoStats( size_t dim, size_t elemSize ) { 752 741 size_t size = dim * elemSize; 742 if ( unlikely( size ) == 0 ) return 0p; // 0 BYTE ALLOCATION RETURNS NULL POINTER 753 743 char * addr = (char *)mallocNoStats( size ); 754 if ( unlikely( addr == 0p ) ) return 0p;755 744 756 745 HeapManager.Storage.Header * header; 757 746 HeapManager.FreeHeader * freeElem; 758 747 size_t bsize, alignment; 759 bool mapped __attribute__(( unused )) = headers( "calloc", addr, header, freeElem, bsize, alignment );760 748 #ifndef __CFA_DEBUG__ 749 bool mapped = 750 #endif // __CFA_DEBUG__ 751 headers( "calloc", addr, header, freeElem, bsize, alignment ); 752 #ifndef __CFA_DEBUG__ 753 761 754 // Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero. 762 755 if ( ! mapped ) 763 756 #endif // __CFA_DEBUG__ 764 // Zero entire data space even when > than size => realloc without a new allocation and zero fill works. 765 // <-------00000000000000000000000000000000000000000000000000000> bsize (bucket size) 757 // <-------0000000000000000000000000000UUUUUUUUUUUUUUUUUUUUUUUUU> bsize (bucket size) U => undefined 766 758 // `-header`-addr `-size 767 memset( addr, '\0', bsize - sizeof(HeapManager.Storage) );// set to zeros759 memset( addr, '\0', size ); // set to zeros 768 760 769 761 header->kind.real.blockSize |= 2; // mark as zero filled … … 772 764 773 765 774 static inline void * memalignNoStats( size_t alignment, size_t size ) { // necessary for malloc statistics 766 static inline void * memalignNoStats( size_t alignment, size_t size ) { 767 if ( unlikely( size ) == 0 ) return 0p; // 0 BYTE ALLOCATION RETURNS NULL POINTER 768 775 769 #ifdef __CFA_DEBUG__ 776 770 checkAlign( alignment ); // check alignment … … 790 784 // add sizeof(Storage) for fake header 791 785 char * addr = (char *)mallocNoStats( size + alignment - libAlign() + sizeof(HeapManager.Storage) ); 792 if ( unlikely( addr == 0p ) ) return addr;793 786 794 787 // address in the block of the "next" alignment address 795 char * user = (char *) libCeiling( (uintptr_t)(addr + sizeof(HeapManager.Storage)), alignment );788 char * user = (char *)ceiling2( (uintptr_t)(addr + sizeof(HeapManager.Storage)), alignment ); 796 789 797 790 // address of header from malloc 798 791 HeapManager.Storage.Header * realHeader = headerAddr( addr ); 792 realHeader->kind.real.size = size; // correct size to eliminate above alignment offset 799 793 // address of fake header * before* the alignment location 800 794 HeapManager.Storage.Header * fakeHeader = headerAddr( user ); … … 810 804 static inline void * cmemalignNoStats( size_t alignment, size_t dim, size_t elemSize ) { 811 805 size_t size = dim * elemSize; 806 if ( unlikely( size ) == 0 ) return 0p; // 0 BYTE ALLOCATION RETURNS NULL POINTER 812 807 char * addr = (char *)memalignNoStats( alignment, size ); 813 if ( unlikely( addr == 0p ) ) return 0p; 808 814 809 HeapManager.Storage.Header * header; 815 810 HeapManager.FreeHeader * freeElem; 816 811 size_t bsize; 817 bool mapped __attribute__(( unused )) = headers( "cmemalign", addr, header, freeElem, bsize, alignment );818 812 #ifndef __CFA_DEBUG__ 813 bool mapped = 814 #endif // __CFA_DEBUG__ 815 headers( "cmemalign", addr, header, freeElem, bsize, alignment ); 816 819 817 // Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero. 818 #ifndef __CFA_DEBUG__ 820 819 if ( ! mapped ) 821 820 #endif // __CFA_DEBUG__ 822 memset( addr, '\0', dataStorage( bsize, addr, header ) ); // set to zeros 821 // <-------0000000000000000000000000000UUUUUUUUUUUUUUUUUUUUUUUUU> bsize (bucket size) U => undefined 822 // `-header`-addr `-size 823 memset( addr, '\0', size ); // set to zeros 823 824 824 825 header->kind.real.blockSize |= 2; // mark as zero filled 825 826 return addr; 826 827 } // cmemalignNoStats 827 828 829 // supported mallopt options830 #ifndef M_MMAP_THRESHOLD831 #define M_MMAP_THRESHOLD (-1)832 #endif // M_TOP_PAD833 #ifndef M_TOP_PAD834 #define M_TOP_PAD (-2)835 #endif // M_TOP_PAD836 828 837 829 … … 851 843 // Same as malloc() except size bytes is an array of dim elements each of elemSize bytes. 852 844 void * aalloc( size_t dim, size_t elemSize ) { 845 size_t size = dim * elemSize; 853 846 #ifdef __STATISTICS__ 854 847 __atomic_add_fetch( &aalloc_calls, 1, __ATOMIC_SEQ_CST ); 855 __atomic_add_fetch( &aalloc_storage, dim * elemSize, __ATOMIC_SEQ_CST );856 #endif // __STATISTICS__ 857 858 return mallocNoStats( dim * elemSize );848 __atomic_add_fetch( &aalloc_storage, size, __ATOMIC_SEQ_CST ); 849 #endif // __STATISTICS__ 850 851 return mallocNoStats( size ); 859 852 } // aalloc 860 853 … … 869 862 return callocNoStats( dim, elemSize ); 870 863 } // calloc 864 871 865 872 866 // Change the size of the memory block pointed to by oaddr to size bytes. The contents are undefined. If oaddr is … … 877 871 #ifdef __STATISTICS__ 878 872 __atomic_add_fetch( &resize_calls, 1, __ATOMIC_SEQ_CST ); 879 __atomic_add_fetch( &resize_storage, size, __ATOMIC_SEQ_CST );880 873 #endif // __STATISTICS__ 881 874 882 875 // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned. 883 if ( unlikely( size == 0 ) ) { free( oaddr ); return mallocNoStats( size ); } // special cases 884 if ( unlikely( oaddr == 0p ) ) return mallocNoStats( size ); 876 if ( unlikely( size == 0 ) ) { free( oaddr ); return 0p; } // special cases 877 if ( unlikely( oaddr == 0p ) ) { 878 #ifdef __STATISTICS__ 879 __atomic_add_fetch( &resize_storage, size, __ATOMIC_SEQ_CST ); 880 #endif // __STATISTICS__ 881 return mallocNoStats( size ); 882 } // if 885 883 886 884 HeapManager.Storage.Header * header; 887 885 HeapManager.FreeHeader * freeElem; 888 size_t bsize, oalign = 0;886 size_t bsize, oalign; 889 887 headers( "resize", oaddr, header, freeElem, bsize, oalign ); 890 888 891 889 size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket 892 890 // same size, DO NOT preserve STICKY PROPERTIES. 893 if ( oalign == 0&& size <= odsize && odsize <= size * 2 ) { // allow 50% wasted storage for smaller size891 if ( oalign <= libAlign() && size <= odsize && odsize <= size * 2 ) { // allow 50% wasted storage for smaller size 894 892 header->kind.real.blockSize &= -2; // no alignment and turn off 0 fill 893 header->kind.real.size = size; // reset allocation size 895 894 return oaddr; 896 895 } // if 897 896 897 #ifdef __STATISTICS__ 898 __atomic_add_fetch( &resize_storage, size, __ATOMIC_SEQ_CST ); 899 #endif // __STATISTICS__ 900 898 901 // change size, DO NOT preserve STICKY PROPERTIES. 899 902 free( oaddr ); 900 void * naddr = mallocNoStats( size ); // create new area 901 return naddr; 903 return mallocNoStats( size ); // create new area 902 904 } // resize 903 905 … … 908 910 #ifdef __STATISTICS__ 909 911 __atomic_add_fetch( &realloc_calls, 1, __ATOMIC_SEQ_CST ); 910 __atomic_add_fetch( &realloc_storage, size, __ATOMIC_SEQ_CST );911 912 #endif // __STATISTICS__ 912 913 913 914 // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned. 914 if ( unlikely( size == 0 ) ) { free( oaddr ); return mallocNoStats( size ); } // special cases 915 if ( unlikely( oaddr == 0p ) ) return mallocNoStats( size ); 915 if ( unlikely( size == 0 ) ) { free( oaddr ); return 0p; } // special cases 916 if ( unlikely( oaddr == 0p ) ) { 917 #ifdef __STATISTICS__ 918 __atomic_add_fetch( &realloc_storage, size, __ATOMIC_SEQ_CST ); 919 #endif // __STATISTICS__ 920 return mallocNoStats( size ); 921 } // if 916 922 917 923 HeapManager.Storage.Header * header; 918 924 HeapManager.FreeHeader * freeElem; 919 size_t bsize, oalign = 0;925 size_t bsize, oalign; 920 926 headers( "realloc", oaddr, header, freeElem, bsize, oalign ); 921 927 922 928 size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket 923 if ( size <= odsize && odsize <= size * 2 ) { // allow up to 50% wasted storage in smaller size 924 // Do not know size of original allocation => cannot do 0 fill for any additional space because do not know 925 // where to start filling, i.e., do not overwrite existing values in space. 929 size_t osize = header->kind.real.size; // old allocation size 930 bool ozfill = (header->kind.real.blockSize & 2) != 0; // old allocation zero filled 931 if ( unlikely( size <= odsize ) && size > odsize / 2 ) { // allow up to 50% wasted storage 932 header->kind.real.size = size; // reset allocation size 933 if ( unlikely( ozfill ) && size > osize ) { // previous request zero fill and larger ? 934 memset( (char *)oaddr + osize, (int)'\0', size - osize ); // initialize added storage 935 } // if 926 936 return oaddr; 927 937 } // if 928 938 939 #ifdef __STATISTICS__ 940 __atomic_add_fetch( &realloc_storage, size, __ATOMIC_SEQ_CST ); 941 #endif // __STATISTICS__ 942 929 943 // change size and copy old content to new storage 930 944 931 945 void * naddr; 932 if ( unlikely( oalign != 0 ) ) { // previous request memalign? 933 if ( unlikely( header->kind.real.blockSize & 2 ) ) { // previous request zero fill 934 naddr = cmemalignNoStats( oalign, 1, size ); // create new aligned area 935 } else { 936 naddr = memalignNoStats( oalign, size ); // create new aligned area 946 if ( likely( oalign <= libAlign() ) ) { // previous request not aligned ? 947 naddr = mallocNoStats( size ); // create new area 948 } else { 949 naddr = memalignNoStats( oalign, size ); // create new aligned area 950 } // if 951 952 headers( "realloc", naddr, header, freeElem, bsize, oalign ); 953 memcpy( naddr, oaddr, MIN( osize, size ) ); // copy bytes 954 free( oaddr ); 955 956 if ( unlikely( ozfill ) ) { // previous request zero fill ? 957 header->kind.real.blockSize |= 2; // mark new request as zero filled 958 if ( size > osize ) { // previous request larger ? 959 memset( (char *)naddr + osize, (int)'\0', size - osize ); // initialize added storage 937 960 } // if 938 } else { 939 if ( unlikely( header->kind.real.blockSize & 2 ) ) { // previous request zero fill 940 naddr = callocNoStats( 1, size ); // create new area 941 } else { 942 naddr = mallocNoStats( size ); // create new area 943 } // if 944 } // if 945 if ( unlikely( naddr == 0p ) ) return 0p; 946 947 headers( "realloc", naddr, header, freeElem, bsize, oalign ); 948 size_t ndsize = dataStorage( bsize, naddr, header ); // data storage avilable in bucket 949 // To preserve prior fill, the entire bucket must be copied versus the size. 950 memcpy( naddr, oaddr, MIN( odsize, ndsize ) ); // copy bytes 951 free( oaddr ); 961 } // if 952 962 return naddr; 953 963 } // realloc 954 964 965 955 966 // Same as malloc() except the memory address is a multiple of alignment, which must be a power of two. (obsolete) 956 967 void * memalign( size_t alignment, size_t size ) { … … 966 977 // Same as aalloc() with memory alignment. 967 978 void * amemalign( size_t alignment, size_t dim, size_t elemSize ) { 979 size_t size = dim * elemSize; 968 980 #ifdef __STATISTICS__ 969 981 __atomic_add_fetch( &cmemalign_calls, 1, __ATOMIC_SEQ_CST ); 970 __atomic_add_fetch( &cmemalign_storage, dim * elemSize, __ATOMIC_SEQ_CST );971 #endif // __STATISTICS__ 972 973 return memalignNoStats( alignment, dim * elemSize );982 __atomic_add_fetch( &cmemalign_storage, size, __ATOMIC_SEQ_CST ); 983 #endif // __STATISTICS__ 984 985 return memalignNoStats( alignment, size ); 974 986 } // amemalign 975 987 … … 997 1009 // free(3). 998 1010 int posix_memalign( void ** memptr, size_t alignment, size_t size ) { 999 if ( alignment < sizeof(void *) || ! libPow2( alignment ) ) return EINVAL; // check alignment1011 if ( alignment < libAlign() || ! is_pow2( alignment ) ) return EINVAL; // check alignment 1000 1012 * memptr = memalign( alignment, size ); 1001 if ( unlikely( * memptr == 0p ) ) return ENOMEM;1002 1013 return 0; 1003 1014 } // posix_memalign … … 1012 1023 // Same as valloc but rounds size to multiple of page size. 1013 1024 void * pvalloc( size_t size ) { 1014 return memalign( pageSize, libCeiling( size, pageSize ) );1025 return memalign( pageSize, ceiling2( size, pageSize ) ); 1015 1026 } // pvalloc 1016 1027 … … 1050 1061 } // malloc_alignment 1051 1062 1063 1052 1064 // Set the alignment for an the allocation and return previous alignment or 0 if no alignment. 1053 1065 size_t $malloc_alignment_set( void * addr, size_t alignment ) { … … 1090 1102 // Returns original total allocation size (not bucket size) => array size is dimension * sizeif(T). 1091 1103 size_t malloc_size( void * addr ) { 1092 if ( unlikely( addr == 0p ) ) return false; // null allocation is not zero fill1104 if ( unlikely( addr == 0p ) ) return 0; // null allocation has zero size 1093 1105 HeapManager.Storage.Header * header = headerAddr( addr ); 1094 1106 if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ? 1095 1107 header = realHeader( header ); // backup from fake to real header 1096 1108 } // if 1097 return header-> size;1109 return header->kind.real.size; 1098 1110 } // malloc_size 1099 1111 1100 1112 // Set allocation size and return previous size. 1101 1113 size_t $malloc_size_set( void * addr, size_t size ) { 1102 if ( unlikely( addr == 0p ) ) return false; // null allocation is not zero fill1114 if ( unlikely( addr == 0p ) ) return 0; // null allocation has 0 size 1103 1115 HeapManager.Storage.Header * header = headerAddr( addr ); 1104 1116 if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ? 1105 1117 header = realHeader( header ); // backup from fake to real header 1106 1118 } // if 1107 size_t ret = header-> size;1108 header-> size = size;1119 size_t ret = header->kind.real.size; 1120 header->kind.real.size = size; 1109 1121 return ret; 1110 1122 } // $malloc_size_set … … 1120 1132 1121 1133 headers( "malloc_usable_size", addr, header, freeElem, bsize, alignment ); 1122 return dataStorage( bsize, addr, header ); // data storage in bucket1134 return dataStorage( bsize, addr, header ); // data storage in bucket 1123 1135 } // malloc_usable_size 1124 1136 … … 1132 1144 } // malloc_stats 1133 1145 1146 1134 1147 // Changes the file descripter where malloc_stats() writes statistics. 1135 1148 int malloc_stats_fd( int fd __attribute__(( unused )) ) { 1136 1149 #ifdef __STATISTICS__ 1137 int temp = stat fd;1138 stat fd = fd;1150 int temp = stat_fd; 1151 stat_fd = fd; 1139 1152 return temp; 1140 1153 #else … … 1157 1170 } // mallopt 1158 1171 1172 1159 1173 // Attempt to release free memory at the top of the heap (by calling sbrk with a suitable argument). 1160 1174 int malloc_trim( size_t ) { … … 1167 1181 // malloc). 1168 1182 int malloc_info( int options, FILE * stream ) { 1169 if ( options != 0 ) { errno = EINVAL; return -1; } 1183 if ( options != 0 ) { errno = EINVAL; return -1; } 1184 #ifdef __STATISTICS__ 1170 1185 return printStatsXML( stream ); 1186 #else 1187 return 0; // unsupported 1188 #endif // __STATISTICS__ 1171 1189 } // malloc_info 1172 1190 … … 1183 1201 // Restores the state of all malloc internal bookkeeping variables to the values recorded in the opaque data 1184 1202 // structure pointed to by state. 1185 int malloc_set_state( void * ptr) {1203 int malloc_set_state( void * ) { 1186 1204 return 0; // unsupported 1187 1205 } // malloc_set_state … … 1193 1211 #ifdef __STATISTICS__ 1194 1212 __atomic_add_fetch( &resize_calls, 1, __ATOMIC_SEQ_CST ); 1195 __atomic_add_fetch( &resize_storage, size, __ATOMIC_SEQ_CST );1196 1213 #endif // __STATISTICS__ 1197 1214 1198 1215 // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned. 1199 if ( unlikely( size == 0 ) ) { free( oaddr ); return memalignNoStats( nalign, size ); } // special cases 1200 if ( unlikely( oaddr == 0p ) ) return memalignNoStats( nalign, size ); 1201 1202 1203 if ( unlikely( nalign == 0 ) ) nalign = libAlign(); // reset alignment to minimum 1216 if ( unlikely( size == 0 ) ) { free( oaddr ); return 0p; } // special cases 1217 if ( unlikely( oaddr == 0p ) ) { 1218 #ifdef __STATISTICS__ 1219 __atomic_add_fetch( &resize_storage, size, __ATOMIC_SEQ_CST ); 1220 #endif // __STATISTICS__ 1221 return memalignNoStats( nalign, size ); 1222 } // if 1223 1224 if ( unlikely( nalign < libAlign() ) ) nalign = libAlign(); // reset alignment to minimum 1204 1225 #ifdef __CFA_DEBUG__ 1205 1226 else … … 1209 1230 HeapManager.Storage.Header * header; 1210 1231 HeapManager.FreeHeader * freeElem; 1211 size_t bsize, oalign = 0;1232 size_t bsize, oalign; 1212 1233 headers( "resize", oaddr, header, freeElem, bsize, oalign ); 1213 1234 size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket 1214 1235 1215 1236 if ( oalign <= nalign && (uintptr_t)oaddr % nalign == 0 ) { // <= alignment and new alignment happens to match 1216 if ( oalign > =libAlign() ) { // fake header ?1237 if ( oalign > libAlign() ) { // fake header ? 1217 1238 headerAddr( oaddr )->kind.fake.alignment = nalign | 1; // update alignment (could be the same) 1218 1239 } // if 1219 1240 if ( size <= odsize && odsize <= size * 2 ) { // allow 50% wasted storage for smaller size 1220 1241 header->kind.real.blockSize &= -2; // turn off 0 fill 1242 header->kind.real.size = size; // reset allocation size 1221 1243 return oaddr; 1222 1244 } // if 1223 1245 } // if 1224 1246 1225 // change size 1226 1227 void * naddr; 1228 if ( unlikely( header->kind.real.blockSize & 2 ) ) { // previous request zero fill 1229 naddr = cmemalignNoStats( nalign, 1, size ); // create new aligned area 1230 } else { 1231 naddr = memalignNoStats( nalign, size ); // create new aligned area 1232 } // if 1233 1247 #ifdef __STATISTICS__ 1248 __atomic_add_fetch( &resize_storage, size, __ATOMIC_SEQ_CST ); 1249 #endif // __STATISTICS__ 1250 1251 // change size, DO NOT preserve STICKY PROPERTIES. 1234 1252 free( oaddr ); 1235 return naddr;1253 return memalignNoStats( nalign, size ); // create new aligned area 1236 1254 } // resize 1237 1255 1238 1256 1239 1257 void * realloc( void * oaddr, size_t nalign, size_t size ) { 1240 if ( unlikely( nalign == 0 ) ) nalign = libAlign();// reset alignment to minimum1258 if ( unlikely( nalign < libAlign() ) ) nalign = libAlign(); // reset alignment to minimum 1241 1259 #ifdef __CFA_DEBUG__ 1242 1260 else … … 1246 1264 HeapManager.Storage.Header * header; 1247 1265 HeapManager.FreeHeader * freeElem; 1248 size_t bsize, oalign = 0;1266 size_t bsize, oalign; 1249 1267 headers( "realloc", oaddr, header, freeElem, bsize, oalign ); 1250 size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket1251 1268 1252 1269 if ( oalign <= nalign && (uintptr_t)oaddr % nalign == 0 ) { // <= alignment and new alignment happens to match 1253 if ( oalign > =libAlign() ) { // fake header ?1270 if ( oalign > libAlign() ) { // fake header ? 1254 1271 headerAddr( oaddr )->kind.fake.alignment = nalign | 1; // update alignment (could be the same) 1255 1272 } // if … … 1265 1282 1266 1283 // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned. 1267 if ( unlikely( size == 0 ) ) { free( oaddr ); return memalignNoStats( nalign, size ); } // special cases1284 if ( unlikely( size == 0 ) ) { free( oaddr ); return 0p; } // special cases 1268 1285 if ( unlikely( oaddr == 0p ) ) return memalignNoStats( nalign, size ); 1269 1286 1270 void * naddr; 1271 if ( unlikely( header->kind.real.blockSize & 2 ) ) { // previous request zero fill 1272 naddr = cmemalignNoStats( nalign, 1, size ); // create new aligned area 1273 } else { 1274 naddr = memalignNoStats( nalign, size ); // create new aligned area 1275 } // if 1287 size_t osize = header->kind.real.size; // old allocation size 1288 bool ozfill = (header->kind.real.blockSize & 2) != 0; // old allocation zero filled 1289 1290 void * naddr = memalignNoStats( nalign, size ); // create new aligned area 1276 1291 1277 1292 headers( "realloc", naddr, header, freeElem, bsize, oalign ); 1278 size_t ndsize = dataStorage( bsize, naddr, header ); // data storage available in bucket 1279 // To preserve prior fill, the entire bucket must be copied versus the size. 1280 memcpy( naddr, oaddr, MIN( odsize, ndsize ) ); // copy bytes 1293 memcpy( naddr, oaddr, MIN( osize, size ) ); // copy bytes 1281 1294 free( oaddr ); 1295 1296 if ( unlikely( ozfill ) ) { // previous request zero fill ? 1297 header->kind.real.blockSize |= 2; // mark new request as zero filled 1298 if ( size > osize ) { // previous request larger ? 1299 memset( (char *)naddr + osize, (int)'\0', size - osize ); // initialize added storage 1300 } // if 1301 } // if 1282 1302 return naddr; 1283 1303 } // realloc -
libcfa/src/iostream.cfa
r07d867b r22f94a4 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat May 2 18:30:25202013 // Update Count : 1 01712 // Last Modified On : Mon Aug 10 09:32:14 2020 13 // Update Count : 1126 14 14 // 15 15 16 16 #include "iostream.hfa" 17 17 18 extern "C" {19 18 #include <stdio.h> 20 19 #include <stdbool.h> // true/false 21 20 #include <stdint.h> // UINT64_MAX 21 #include <float.h> // DBL_DIG, LDBL_DIG 22 #include <math.h> // isfinite 23 #include <complex.h> // creal, cimag 22 24 //#include <string.h> // strlen, strcmp 25 extern "C" { 23 26 extern size_t strlen (const char *__s) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))); 24 27 extern int strcmp (const char *__s1, const char *__s2) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); 25 28 extern char *strcpy (char *__restrict __dest, const char *__restrict __src) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); 26 29 extern void *memcpy (void *__restrict __dest, const void *__restrict __src, size_t __n) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2))); 27 #include <float.h> // DBL_DIG, LDBL_DIG28 #include <math.h> // isfinite29 #include <complex.h> // creal, cimag30 30 } // extern "C" 31 31 32 #include <bitmanip.hfa> // fms33 34 35 // *********************************** ostream ***********************************32 #include <bitmanip.hfa> // high1 33 34 35 // *********************************** ostream *********************************** 36 36 37 37 … … 167 167 #define P10_UINT64 10_000_000_000_000_000_000_ULL // 19 zeroes 168 168 169 static void base10_128( ostype & os, unsigned int128 val ) { 170 if ( val > UINT64_MAX ) { 169 static inline void base10_128( ostype & os, unsigned int128 val ) { 170 #if defined(__GNUC__) && __GNUC_PREREQ(7,0) // gcc version >= 7 171 if ( val > P10_UINT64 ) { 172 #else 173 if ( (uint64_t)(val >> 64) != 0 || (uint64_t)val > P10_UINT64 ) { // patch gcc 5 & 6 -O3 bug 174 #endif // __GNUC_PREREQ(7,0) 171 175 base10_128( os, val / P10_UINT64 ); // recursive 172 176 fmt( os, "%.19lu", (uint64_t)(val % P10_UINT64) ); … … 176 180 } // base10_128 177 181 178 static void base10_128( ostype & os, int128 val ) {182 static inline void base10_128( ostype & os, int128 val ) { 179 183 if ( val < 0 ) { 180 184 fmt( os, "-" ); // leading negative sign … … 447 451 } // distribution 448 452 449 // *********************************** manipulators ***********************************450 451 // *********************************** integral ***********************************453 // *********************************** manipulators *********************************** 454 455 // *********************************** integral *********************************** 452 456 453 457 static const char * shortbin[] = { "0", "1", "10", "11", "100", "101", "110", "111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111" }; … … 455 459 456 460 // Default prefix for non-decimal prints is 0b, 0, 0x. 457 #define IntegralFMTImpl( T, CODE,IFMTNP, IFMTP ) \461 #define IntegralFMTImpl( T, IFMTNP, IFMTP ) \ 458 462 forall( dtype ostype | ostream( ostype ) ) { \ 459 463 ostype & ?|?( ostype & os, _Ostream_Manip(T) f ) { \ … … 506 510 if ( f.flags.left && spaces > 0 ) fmt( os, "%*s", spaces, " " ); \ 507 511 return os; \ 508 } /* if */ \512 } /* if */ \ 509 513 \ 510 514 char fmtstr[sizeof(IFMTP)]; /* sizeof includes '\0' */ \ … … 516 520 if ( ! f.flags.nobsdp ) { fmtstr[star] = '#'; star -= 1; } \ 517 521 if ( f.flags.left ) { fmtstr[star] = '-'; star -= 1; } \ 518 if ( f.flags.sign && f.base == CODE) { fmtstr[star] = '+'; star -= 1; } \522 if ( f.flags.sign ) { fmtstr[star] = '+'; star -= 1; } \ 519 523 if ( f.flags.pad0 && ! f.flags.pc ) { fmtstr[star] = '0'; star -= 1; } \ 520 524 fmtstr[star] = '%'; \ … … 522 526 if ( ! f.flags.pc ) { /* no precision */ \ 523 527 fmtstr[sizeof(IFMTNP)-2] = f.base; /* sizeof includes '\0' */ \ 524 /* printf( "%s %c %c\n", &fmtstr[star], f.base, CODE); */ \528 /* printf( "%s %c\n", &fmtstr[star], f.base ); */ \ 525 529 fmt( os, &fmtstr[star], f.wd, f.val ); \ 526 530 } else { /* precision */ \ 527 531 fmtstr[sizeof(IFMTP)-2] = f.base; /* sizeof includes '\0' */ \ 528 /* printf( "%s %c %c\n", &fmtstr[star], f.base, CODE); */ \532 /* printf( "%s %c\n", &fmtstr[star], f.base ); */ \ 529 533 fmt( os, &fmtstr[star], f.wd, f.pc, f.val ); \ 530 534 } /* if */ \ … … 534 538 } // distribution 535 539 536 IntegralFMTImpl( signed char, 'd',"% *hh ", "% *.*hh " )537 IntegralFMTImpl( unsigned char, 'u',"% *hh ", "% *.*hh " )538 IntegralFMTImpl( signed short int, 'd',"% *h ", "% *.*h " )539 IntegralFMTImpl( unsigned short int, 'u',"% *h ", "% *.*h " )540 IntegralFMTImpl( signed int, 'd',"% * ", "% *.* " )541 IntegralFMTImpl( unsigned int, 'u',"% * ", "% *.* " )542 IntegralFMTImpl( signed long int, 'd',"% *l ", "% *.*l " )543 IntegralFMTImpl( unsigned long int, 'u',"% *l ", "% *.*l " )544 IntegralFMTImpl( signed long long int, 'd',"% *ll ", "% *.*ll " )545 IntegralFMTImpl( unsigned long long int, 'u',"% *ll ", "% *.*ll " )546 547 540 IntegralFMTImpl( signed char, "% *hh ", "% *.*hh " ) 541 IntegralFMTImpl( unsigned char, "% *hh ", "% *.*hh " ) 542 IntegralFMTImpl( signed short int, "% *h ", "% *.*h " ) 543 IntegralFMTImpl( unsigned short int, "% *h ", "% *.*h " ) 544 IntegralFMTImpl( signed int, "% * ", "% *.* " ) 545 IntegralFMTImpl( unsigned int, "% * ", "% *.* " ) 546 IntegralFMTImpl( signed long int, "% *l ", "% *.*l " ) 547 IntegralFMTImpl( unsigned long int, "% *l ", "% *.*l " ) 548 IntegralFMTImpl( signed long long int, "% *ll ", "% *.*ll " ) 549 IntegralFMTImpl( unsigned long long int, "% *ll ", "% *.*ll " ) 550 551 #if 0 548 552 #if defined( __SIZEOF_INT128__ ) 549 553 // Default prefix for non-decimal prints is 0b, 0, 0x. … … 611 615 sepOff( os ); \ 612 616 fmt2.flags.left = true; \ 613 int msigd = ceiling ( high1( fmt.val ), 3 ); \617 int msigd = ceiling_div( high1( fmt.val ), 3 ); \ 614 618 fmt2.wd = f.wd - (fmt.pc > msigd ? fmt.pc : msigd); \ 615 619 if ( ! fmt.flags.nobsdp ) fmt2.wd -= 1; /* compensate for 0 base specifier */ \ … … 663 667 IntegralFMTImpl128( unsigned int128, unsigned, 'u', "% *ll ", "% *.*ll " ) 664 668 #endif // __SIZEOF_INT128__ 665 666 //*********************************** floating point *********************************** 669 #endif // 0 670 671 #if 1 672 #if defined( __SIZEOF_INT128__ ) 673 // Default prefix for non-decimal prints is 0b, 0, 0x. 674 forall( dtype ostype | ostream( ostype ) ) 675 static inline void base_128( ostype & os, unsigned int128 val, unsigned int128 power, _Ostream_Manip(uint64_t) & f, unsigned int maxdig, unsigned int bits, unsigned int cnt = 0 ) { 676 int wd = 1; // f.wd is never 0 because 0 implies left-pad 677 if ( val > power ) { // subdivide value into printable 64-bit values 678 base_128( os, val / power, power, f, maxdig, bits, cnt + 1 ); // recursive 679 f.val = val % power; 680 if ( cnt == 1 && f.flags.left ) { wd = f.wd; f.wd = maxdig; } // copy f.wd and reset for printing middle chunk 681 // printf( "R val:%#lx(%lu) wd:%u pc:%u base:%c neg:%d pc:%d left:%d nobsdp:%d sign:%d pad0:%d\n", 682 // f.val, f.val, f.wd, f.pc, f.base, f.flags.neg, f.flags.pc, f.flags.left, f.flags.nobsdp, f.flags.sign, f.flags.pad0 ); 683 (ostype &)(os | f); 684 if ( cnt == 1 ) { 685 if ( f.flags.left ) { wd -= maxdig; f.wd = wd < 0 ? 1 : wd; } // update and restore f.wd for printing end chunk 686 sepOff( os ); // no seperator between chunks 687 } // if 688 } else { // print start chunk 689 f.val = val; 690 // f.pc is unsigned => use wd 691 if ( f.flags.pc && f.pc > maxdig * cnt ) { wd = f.pc - maxdig * cnt; f.pc = wd < 0 ? 0 : wd; } 692 else { f.flags.pc = false; f.pc = 0; } 693 694 if ( ! f.flags.left ) { // right justify 695 wd = f.wd - maxdig * cnt; 696 f.wd = wd < 0 ? 1 : wd; 697 wd = maxdig; 698 } else { // left justify 699 if ( cnt != 0 ) { // value >= 2^64 ? 700 unsigned int dig, bs = 0; 701 // compute size of prefix digits and base 702 if ( f.base == 'd' || f.base == 'u' ) { // no base prefix 703 dig = ceil( log10( f.val ) ); // use floating-point 704 if ( f.base == 'd' && (f.flags.neg || f.flags.sign) ) bs = 1; // sign ? 705 } else { 706 dig = ceiling_div( high1( f.val ), bits ); 707 if ( ! f.flags.nobsdp ) { // base prefix ? 708 if ( f.base == 'o' ) { 709 // 0 prefix for octal is not added for precision with leading zero 710 if ( f.pc <= dig ) bs = 1; // 1 character prefix 711 } else bs = 2; // 2 character prefix 712 } // if 713 } // if 714 wd = f.wd - (f.pc > dig ? f.pc : dig) - bs; // precision > leading digits ? 715 if ( wd < 0 ) wd = 1; 716 f.wd = 1; 717 } // if 718 // all manipulators handled implicitly for value < 2^64 719 } // if 720 // prior checks ensure wd not negative 721 722 if ( f.flags.neg ) f.val = -f.val; 723 // printf( "L val:%#lx(%lu) wd:%u pc:%u base:%c neg:%d pc:%d left:%d nobsdp:%d sign:%d pad0:%d\n", 724 // f.val, f.val, f.wd, f.pc, f.base, f.flags.neg, f.flags.pc, f.flags.left, f.flags.nobsdp, f.flags.sign, f.flags.pad0 ); 725 (ostype &)(os | f); 726 727 // remaining middle and end chunks are padded with 0s on the left 728 if ( ! f.flags.left ) { f.flags.pad0 = true; f.flags.pc = false; } // left pad with 0s 729 else { f.pc = maxdig; f.flags.pc = true; } // left pad with precision 730 731 if ( cnt != 0 ) sepOff( os ); // no seperator between chunks 732 f.wd = wd; // reset f.wd for next chunk 733 f.flags.sign = false; // no leading +/- sign 734 f.flags.nobsdp = true; // no leading base prefix 735 } // if 736 } // base_128 737 738 #define IntegralFMTImpl128( T ) \ 739 forall( dtype ostype | ostream( ostype ) ) { \ 740 ostype & ?|?( ostype & os, _Ostream_Manip(T) f ) { \ 741 _Ostream_Manip(uint64_t) fmt; \ 742 fmt.[wd, pc, base, all] = f.[wd, pc, base, all]; \ 743 if ( f.base == 'b' | f.base == 'B' ) { \ 744 base_128( os, f.val, (unsigned int128)1 << 64, fmt, 64, 1 ); \ 745 } else if ( f.base == 'o' ) { \ 746 base_128( os, f.val, (unsigned int128)1 << 63, fmt, 21, 3 ); \ 747 } else if ( f.base == 'd' || f.base == 'u' ) { \ 748 if ( f.base == 'd' && f.val < 0 ) { f.val = -f.val; fmt.flags.neg = true; } \ 749 base_128( os, f.val, (unsigned int128)10_000_000_000_000_000_000UL, fmt, 19, 0 ); \ 750 } else { \ 751 base_128( os, f.val, (unsigned int128)1 << 64, fmt, 16, 4 ); \ 752 } /* if */ \ 753 return os; \ 754 } /* ?|? */ \ 755 void ?|?( ostype & os, _Ostream_Manip(T) f ) { (ostype &)(os | f); ends( os ); } \ 756 } // distribution 757 758 IntegralFMTImpl128( int128 ) 759 IntegralFMTImpl128( unsigned int128 ) 760 #endif // __SIZEOF_INT128__ 761 #endif // 0 762 763 // *********************************** floating point *********************************** 667 764 668 765 #define PrintWithDP2( os, format, val, ... ) \ … … 720 817 FloatingPointFMTImpl( long double, "% *L ", "% *.*L " ) 721 818 722 // *********************************** character ***********************************819 // *********************************** character *********************************** 723 820 724 821 forall( dtype ostype | ostream( ostype ) ) { … … 753 850 } // distribution 754 851 755 // *********************************** C string ***********************************852 // *********************************** C string *********************************** 756 853 757 854 forall( dtype ostype | ostream( ostype ) ) { … … 800 897 801 898 802 // *********************************** istream ***********************************899 // *********************************** istream *********************************** 803 900 804 901 … … 877 974 } // ?|? 878 975 976 #if defined( __SIZEOF_INT128__ ) 977 istype & ?|?( istype & is, int128 & i128 ) { 978 return (istype &)(is | (unsigned int128 &)i128); 979 } // ?|? 980 981 istype & ?|?( istype & is, unsigned int128 & ui128 ) { 982 char s[40]; 983 bool sign = false; 984 985 if ( fmt( is, " %[-]", s ) == 1 ) sign = true; // skip whitespace, negative sign ? 986 // If the input is too large, the value returned is undefined. If there is no input, no value is returned 987 if ( fmt( is, "%39[0-9]%*[0-9]", s ) == 1 ) { // take first 39 characters, ignore remaining 988 ui128 = 0; 989 for ( unsigned int i = 0; s[i] != '\0'; i += 1 ) { 990 ui128 = ui128 * 10 + s[i] - '0'; 991 } // for 992 if ( sign ) ui128 = -ui128; 993 } else if ( sign ) ungetc( is, '-' ); // return minus when no digits 994 return is; 995 } // ?|? 996 #endif // __SIZEOF_INT128__ 879 997 880 998 istype & ?|?( istype & is, float & f ) { … … 946 1064 } // distribution 947 1065 948 // *********************************** manipulators ***********************************1066 // *********************************** manipulators *********************************** 949 1067 950 1068 forall( dtype istype | istream( istype ) ) -
libcfa/src/iostream.hfa
r07d867b r22f94a4 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Feb 20 15:30:56202013 // Update Count : 3 3712 // Last Modified On : Thu Jul 16 07:43:32 2020 13 // Update Count : 348 14 14 // 15 15 … … 19 19 20 20 21 // *********************************** ostream ***********************************21 // *********************************** ostream *********************************** 22 22 23 23 … … 156 156 } // distribution 157 157 158 // *********************************** manipulators ***********************************158 // *********************************** manipulators *********************************** 159 159 160 160 forall( otype T ) … … 166 166 unsigned char all; 167 167 struct { 168 unsigned char neg:1; // val is negative 168 169 unsigned char pc:1; // precision specified 169 170 unsigned char left:1; // left justify … … 175 176 }; // _Ostream_Manip 176 177 177 // *********************************** integral ***********************************178 // *********************************** integral *********************************** 178 179 179 180 // See 6.7.9. 19) The initialization shall occur in initializer list order, each initializer provided for a particular … … 215 216 IntegralFMTDecl( int128, 'd' ) 216 217 IntegralFMTDecl( unsigned int128, 'u' ) 217 #endif 218 219 // *********************************** floating point ***********************************218 #endif // __SIZEOF_INT128__ 219 220 // *********************************** floating point *********************************** 220 221 221 222 // Default suffix for values with no fraction is "." … … 246 247 FloatingPointFMTDecl( long double ) 247 248 248 // *********************************** character ***********************************249 // *********************************** character *********************************** 249 250 250 251 static inline { … … 263 264 } // ?|? 264 265 265 // *********************************** C string ***********************************266 // *********************************** C string *********************************** 266 267 267 268 static inline { … … 282 283 283 284 284 // *********************************** istream ***********************************285 // *********************************** istream *********************************** 285 286 286 287 … … 314 315 istype & ?|?( istype &, unsigned int & ); 315 316 istype & ?|?( istype &, long int & ); 317 istype & ?|?( istype &, unsigned long int & ); 316 318 istype & ?|?( istype &, long long int & ); 317 istype & ?|?( istype &, unsigned long int & );318 319 istype & ?|?( istype &, unsigned long long int & ); 320 #if defined( __SIZEOF_INT128__ ) 321 istype & ?|?( istype &, int128 & ); 322 istype & ?|?( istype &, unsigned int128 & ); 323 #endif // __SIZEOF_INT128__ 319 324 320 325 istype & ?|?( istype &, float & ); … … 336 341 } // distribution 337 342 338 // *********************************** manipulators ***********************************343 // *********************************** manipulators *********************************** 339 344 340 345 struct _Istream_Cstr { … … 358 363 _Istream_Cstr excl( const char scanset[], char * s ) { return (_Istream_Cstr){ s, scanset, -1, { .flags.inex : true } }; } 359 364 _Istream_Cstr & excl( const char scanset[], _Istream_Cstr & fmt ) { fmt.scanset = scanset; fmt.flags.inex = true; return fmt; } 360 _Istream_Cstr ignore( c onst char s[] ) { return (_Istream_Cstr)@{ s, 0p, -1, { .flags.ignore : true } }; }365 _Istream_Cstr ignore( char s[] ) { return (_Istream_Cstr)@{ s, 0p, -1, { .flags.ignore : true } }; } 361 366 _Istream_Cstr & ignore( _Istream_Cstr & fmt ) { fmt.flags.ignore = true; return fmt; } 362 367 _Istream_Cstr wdi( unsigned int w, char s[] ) { return (_Istream_Cstr)@{ s, 0p, w, { .all : 0 } }; } … … 370 375 371 376 static inline { 372 _Istream_Char ignore( const char c) { return (_Istream_Char)@{ true }; }377 _Istream_Char ignore( const char ) { return (_Istream_Char)@{ true }; } 373 378 _Istream_Char & ignore( _Istream_Char & fmt ) { fmt.ignore = true; return fmt; } 374 379 } // distribution 375 380 forall( dtype istype | istream( istype ) ) istype & ?|?( istype & is, _Istream_Char f ); 376 381 377 forall( otype T)382 forall( dtype T | sized( T ) ) 378 383 struct _Istream_Manip { 379 384 T & val; // polymorphic base-type … … 413 418 414 419 415 // *********************************** time ***********************************420 // *********************************** time *********************************** 416 421 417 422 -
libcfa/src/stdhdr/assert.h
r07d867b r22f94a4 33 33 #define verify(x) assert(x) 34 34 #define verifyf(x, ...) assertf(x, __VA_ARGS__) 35 #define verifyfail(...) 35 36 #define __CFA_WITH_VERIFY__ 36 37 #else 37 38 #define verify(x) 38 39 #define verifyf(x, ...) 40 #define verifyfail(...) 39 41 #endif 40 42 -
libcfa/src/stdhdr/malloc.h
r07d867b r22f94a4 10 10 // Created On : Thu Jul 20 15:58:16 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Apr 16 22:44:06202013 // Update Count : 1 312 // Last Modified On : Wed May 27 14:13:14 2020 13 // Update Count : 18 14 14 // 15 16 17 size_t default_mmap_start(); // CFA extras18 size_t default_heap_expansion();19 20 bool traceHeap();21 bool traceHeapOn();22 bool traceHeapOff();23 24 bool traceHeapTerm();25 bool traceHeapTermOn();26 bool traceHeapTermOff();27 28 bool checkFree();29 bool checkFreeOn();30 bool checkFreeOff();31 32 extern "C" {33 void * aalloc( size_t noOfElems, size_t elemSize );34 void * amemalign( size_t alignment, size_t noOfElems, size_t elemSize );35 void * cmemalign( size_t alignment, size_t noOfElems, size_t elemSize );36 size_t malloc_alignment( void * );37 bool malloc_zero_fill( void * );38 size_t malloc_size( void * );39 int malloc_stats_fd( int fd );40 } // extern "C"41 15 42 16 extern "C" { 43 17 #include_next <malloc.h> // has internal check for multiple expansion 44 18 } // extern "C" 19 20 #include <heap.hfa> 45 21 46 22 // Local Variables: // -
libcfa/src/stdlib.cfa
r07d867b r22f94a4 10 10 // Created On : Thu Jan 28 17:10:29 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Apr 16 22:43:33202013 // Update Count : 49812 // Last Modified On : Sun Jul 19 15:05:28 2020 13 // Update Count : 501 14 14 // 15 15 … … 26 26 //--------------------------------------- 27 27 28 forall( dtype T | sized(T) ) {29 T * alloc_set( T ptr[], size_t dim, char fill ) { // realloc array with fill30 size_t olen = malloc_usable_size( ptr ); // current allocation31 void * nptr = (void *)realloc( (void *)ptr, dim * sizeof(T) ); // C realloc32 size_t nlen = malloc_usable_size( nptr ); // new allocation33 if ( nlen > olen ) { // larger ?34 memset( (char *)nptr + olen, (int)fill, nlen - olen ); // initialize added storage35 } // if36 return (T *)nptr;37 } // alloc_set38 39 T * alloc_set( T ptr[], size_t dim, T fill ) { // realloc array with fill40 size_t olen = malloc_usable_size( ptr ); // current allocation41 void * nptr = (void *)realloc( (void *)ptr, dim * sizeof(T) ); // C realloc42 size_t nlen = malloc_usable_size( nptr ); // new allocation43 if ( nlen > olen ) { // larger ?44 for ( i; malloc_size( ptr ) / sizeof(T) ~ dim ) {45 memcpy( &ptr[i], &fill, sizeof(T) ); // initialize with fill value46 } // for47 } // if48 return (T *)nptr;49 } // alloc_align_set50 51 T * alloc_align_set( T ptr[], size_t align, char fill ) { // aligned realloc with fill52 size_t olen = malloc_usable_size( ptr ); // current allocation53 void * nptr = (void *)realloc( (void *)ptr, align, sizeof(T) ); // CFA realloc54 // char * nptr = alloc_align( ptr, align );55 size_t nlen = malloc_usable_size( nptr ); // new allocation56 if ( nlen > olen ) { // larger ?57 memset( (char *)nptr + olen, (int)fill, nlen - olen ); // initialize added storage58 } // if59 return (T *)nptr;60 } // alloc_align_set61 62 T * alloc_align_set( T ptr[], size_t align, size_t dim, T fill ) { // aligned realloc with fill63 size_t olen = malloc_usable_size( ptr ); // current allocation64 void * nptr = (void *)realloc( (void *)ptr, align, sizeof(T) ); // CFA realloc65 // char * nptr = alloc_align( ptr, align );66 size_t nlen = malloc_usable_size( nptr ); // new allocation67 if ( nlen > olen ) { // larger ?68 for ( i; dim ) { memcpy( &ptr[i], &fill, sizeof(T) ); } // initialize with fill value69 } // if70 return (T *)nptr;71 } // alloc_align_set72 } // distribution73 74 28 // allocation/deallocation and constructor/destructor, non-array types 75 29 forall( dtype T | sized(T), ttype Params | { void ?{}( T &, Params ); } ) … … 78 32 } // new 79 33 80 forall( dtype T | sized(T) |{ void ^?{}( T & ); } )34 forall( dtype T | { void ^?{}( T & ); } ) 81 35 void delete( T * ptr ) { 82 36 if ( ptr ) { // ignore null … … 86 40 } // delete 87 41 88 forall( dtype T, ttype Params | sized(T) |{ void ^?{}( T & ); void delete( Params ); } )42 forall( dtype T, ttype Params | { void ^?{}( T & ); void delete( Params ); } ) 89 43 void delete( T * ptr, Params rest ) { 90 if ( ptr ) { // ignore null 91 ^(*ptr){}; // run destructor 92 free( ptr ); 93 } // if 44 delete( ptr ); 94 45 delete( rest ); 95 46 } // delete … … 277 228 extern "C" { // override C version 278 229 void srandom( unsigned int seed ) { srand48( (long int)seed ); } 279 long int random( void ) { return mrand48(); } 230 long int random( void ) { return mrand48(); } // GENERATES POSITIVE AND NEGATIVE VALUES 280 231 } // extern "C" 281 232 -
libcfa/src/stdlib.hfa
r07d867b r22f94a4 10 10 // Created On : Thu Jan 28 17:12:35 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Apr 16 22:44:05202013 // Update Count : 4 3212 // Last Modified On : Thu Jul 30 16:14:58 2020 13 // Update Count : 490 14 14 // 15 15 … … 20 20 21 21 #include <stdlib.h> // *alloc, strto*, ato* 22 #include <heap.hfa> 22 23 23 24 // Reduce includes by explicitly defining these routines. 24 25 extern "C" { 25 void * memalign( size_t align, size_t size ); // malloc.h 26 size_t malloc_usable_size( void * ptr ); // malloc.h 27 size_t malloc_size( void * addr ); // CFA heap 28 void * cmemalign( size_t alignment, size_t noOfElems, size_t elemSize ); // CFA heap 26 void * memalign( size_t alignment, size_t size ); // malloc.h 27 void * pvalloc( size_t size ); // malloc.h 29 28 void * memset( void * dest, int fill, size_t size ); // string.h 30 29 void * memcpy( void * dest, const void * src, size_t size ); // string.h 31 void * resize( void * oaddr, size_t size ); // CFA heap32 30 } // extern "C" 33 34 void * resize( void * oaddr, size_t nalign, size_t size ); // CFA heap35 void * realloc( void * oaddr, size_t nalign, size_t size ); // CFA heap36 31 37 32 //--------------------------------------- … … 44 39 //--------------------------------------- 45 40 41 // Macro because of returns 42 #define $VAR_ALLOC( allocation, alignment ) \ 43 if ( _Alignof(T) <= libAlign() ) return (T *)(void *)allocation( (size_t)sizeof(T) ); /* C allocation */ \ 44 else return (T *)alignment( _Alignof(T), sizeof(T) ) 45 46 #define $ARRAY_ALLOC( allocation, alignment, dim ) \ 47 if ( _Alignof(T) <= libAlign() ) return (T *)(void *)allocation( dim, (size_t)sizeof(T) ); /* C allocation */ \ 48 else return (T *)alignment( _Alignof(T), dim, sizeof(T) ) 49 50 #define $RE_SPECIALS( ptr, size, allocation, alignment ) \ 51 if ( unlikely( size == 0 ) || unlikely( ptr == 0p ) ) { \ 52 if ( unlikely( size == 0 ) ) free( ptr ); \ 53 $VAR_ALLOC( malloc, memalign ); \ 54 } /* if */ 55 46 56 static inline forall( dtype T | sized(T) ) { 47 57 // Cforall safe equivalents, i.e., implicit size specification 48 58 49 59 T * malloc( void ) { 50 if ( _Alignof(T) <= libAlign() ) return (T *)(void *)malloc( (size_t)sizeof(T) ); // C malloc 51 else return (T *)memalign( _Alignof(T), sizeof(T) ); 60 $VAR_ALLOC( malloc, memalign ); 52 61 } // malloc 53 62 63 T * aalloc( size_t dim ) { 64 $ARRAY_ALLOC( aalloc, amemalign, dim ); 65 } // aalloc 66 54 67 T * calloc( size_t dim ) { 55 if ( _Alignof(T) <= libAlign() )return (T *)(void *)calloc( dim, sizeof(T) ); // C calloc 56 else return (T *)cmemalign( _Alignof(T), dim, sizeof(T) ); 68 $ARRAY_ALLOC( calloc, cmemalign, dim ); 57 69 } // calloc 58 70 71 T * resize( T * ptr, size_t size ) { // CFA resize, eliminate return-type cast 72 $RE_SPECIALS( ptr, size, malloc, memalign ); 73 if ( _Alignof(T) <= libAlign() ) return (T *)(void *)resize( (void *)ptr, size ); // CFA resize 74 else return (T *)(void *)resize( (void *)ptr, _Alignof(T), size ); // CFA resize 75 } // resize 76 59 77 T * realloc( T * ptr, size_t size ) { // CFA realloc, eliminate return-type cast 60 return (T *)(void *)realloc( (void *)ptr, size ); // C realloc 78 $RE_SPECIALS( ptr, size, malloc, memalign ); 79 if ( _Alignof(T) <= libAlign() ) return (T *)(void *)realloc( (void *)ptr, size ); // C realloc 80 else return (T *)(void *)realloc( (void *)ptr, _Alignof(T), size ); // CFA realloc 61 81 } // realloc 62 82 … … 65 85 } // memalign 66 86 87 T * amemalign( size_t align, size_t dim ) { 88 return (T *)amemalign( align, dim, sizeof(T) ); // CFA amemalign 89 } // amemalign 90 67 91 T * cmemalign( size_t align, size_t dim ) { 68 92 return (T *)cmemalign( align, dim, sizeof(T) ); // CFA cmemalign … … 76 100 return posix_memalign( (void **)ptr, align, sizeof(T) ); // C posix_memalign 77 101 } // posix_memalign 102 103 T * valloc( void ) { 104 return (T *)valloc( sizeof(T) ); // C valloc 105 } // valloc 106 107 T * pvalloc( void ) { 108 return (T *)pvalloc( sizeof(T) ); // C pvalloc 109 } // pvalloc 78 110 } // distribution 79 111 … … 86 118 87 119 T * alloc( size_t dim ) { 88 if ( _Alignof(T) <= libAlign() ) return (T *)(void *)malloc( dim * (size_t)sizeof(T) ); 89 else return (T *)memalign( _Alignof(T), dim * sizeof(T) ); 120 return aalloc( dim ); 90 121 } // alloc 91 122 92 123 forall( dtype S | sized(S) ) 93 124 T * alloc( S ptr[], size_t dim = 1 ) { // singleton/array resize 94 size_t len = malloc_usable_size( ptr ); // current bucket size 95 if ( sizeof(T) * dim > len ) { // not enough space ? 96 T * temp = alloc( dim ); // new storage 97 free( ptr ); // free old storage 98 return temp; 125 return resize( (T *)ptr, dim * sizeof(T) ); // CFA resize 126 } // alloc 127 128 T * alloc( T ptr[], size_t dim = 1, bool copy = true ) { 129 if ( copy ) { 130 return realloc( ptr, dim * sizeof(T) ); // CFA realloc 99 131 } else { 100 return (T *)ptr; 101 } // if 102 } // alloc 103 104 T * alloc( T ptr[], size_t dim, bool copy = true ) { 105 if ( copy ) { // realloc 106 return (T *)(void *)realloc( (void *)ptr, dim * sizeof(T) ); // C realloc 107 } else { 108 struct __Unknown {}; 109 return alloc( (__Unknown *)ptr, dim ); // reuse, cheat making T/S different types 132 return resize( ptr, dim * sizeof(T) ); // CFA resize 110 133 } // if 111 134 } // alloc … … 132 155 return (T *)memcpy( (T *)alloc( dim ), fill, dim * sizeof(T) ); // initialize with fill value 133 156 } // alloc 134 } // distribution 135 136 forall( dtype T | sized(T) ) { 137 T * alloc_set( T ptr[], size_t dim, char fill ); // realloc array with fill 138 T * alloc_set( T ptr[], size_t dim, T fill ); // realloc array with fill 157 158 T * alloc_set( T ptr[], size_t dim, char fill ) { // realloc array with fill 159 size_t osize = malloc_size( ptr ); // current allocation 160 size_t nsize = dim * sizeof(T); // new allocation 161 T * nptr = realloc( ptr, nsize ); // CFA realloc 162 if ( nsize > osize ) { // larger ? 163 memset( (char *)nptr + osize, (int)fill, nsize - osize ); // initialize added storage 164 } // if 165 return nptr; 166 } // alloc_set 167 168 T * alloc_set( T ptr[], size_t dim, T & fill ) { // realloc array with fill 169 size_t odim = malloc_size( ptr ) / sizeof(T); // current dimension 170 size_t nsize = dim * sizeof(T); // new allocation 171 size_t ndim = nsize / sizeof(T); // new dimension 172 T * nptr = realloc( ptr, nsize ); // CFA realloc 173 if ( ndim > odim ) { // larger ? 174 for ( i; odim ~ ndim ) { 175 memcpy( &nptr[i], &fill, sizeof(T) ); // initialize with fill value 176 } // for 177 } // if 178 return nptr; 179 } // alloc_align_set 139 180 } // distribution 140 181 … … 148 189 } // alloc_align 149 190 150 T * alloc_align( T ptr[], size_t align ) { // aligned realloc array151 return (T *)(void *)realloc( (void *)ptr, align, sizeof(T) ); // CFA realloc191 T * alloc_align( T * ptr, size_t align ) { // aligned realloc array 192 return (T *)(void *)realloc( (void *)ptr, align, sizeof(T) ); // CFA C realloc 152 193 } // alloc_align 153 194 … … 182 223 return (T *)memcpy( (T *)alloc_align( align, dim ), fill, dim * sizeof(T) ); 183 224 } // alloc_align 184 } // distribution 185 186 forall( dtype T | sized(T) ) { 187 T * alloc_align_set( T ptr[], size_t align, char fill ); // aligned realloc with fill 188 T * alloc_align_set( T ptr[], size_t align, T fill ); // aligned realloc with fill 189 T * alloc_align_set( T ptr[], size_t align, size_t dim, char fill ); // aligned realloc array with fill 190 T * alloc_align_set( T ptr[], size_t align, size_t dim, T fill ); // aligned realloc array with fill 225 226 T * alloc_align_set( T ptr[], size_t align, size_t dim, char fill ) { 227 size_t osize = malloc_size( ptr ); // current allocation 228 size_t nsize = dim * sizeof(T); // new allocation 229 T * nptr = alloc_align( ptr, align, nsize ); 230 if ( nsize > osize ) { // larger ? 231 memset( (char *)nptr + osize, (int)fill, nsize - osize ); // initialize added storage 232 } // if 233 return nptr; 234 } // alloc_align_set 235 236 T * alloc_align_set( T ptr[], size_t align, size_t dim, T & fill ) { 237 size_t odim = malloc_size( ptr ) / sizeof(T); // current dimension 238 size_t nsize = dim * sizeof(T); // new allocation 239 size_t ndim = nsize / sizeof(T); // new dimension 240 T * nptr = alloc_align( ptr, align, nsize ); 241 if ( ndim > odim ) { // larger ? 242 for ( i; odim ~ ndim ) { 243 memcpy( &nptr[i], &fill, sizeof(T) ); // initialize with fill value 244 } // for 245 } // if 246 return nptr; 247 } // alloc_align_set 191 248 } // distribution 192 249 … … 215 272 // Cforall allocation/deallocation and constructor/destructor, non-array types 216 273 forall( dtype T | sized(T), ttype Params | { void ?{}( T &, Params ); } ) T * new( Params p ); 217 forall( dtype T | sized(T) |{ void ^?{}( T & ); } ) void delete( T * ptr );218 forall( dtype T, ttype Params | sized(T) |{ void ^?{}( T & ); void delete( Params ); } ) void delete( T * ptr, Params rest );274 forall( dtype T | { void ^?{}( T & ); } ) void delete( T * ptr ); 275 forall( dtype T, ttype Params | { void ^?{}( T & ); void delete( Params ); } ) void delete( T * ptr, Params rest ); 219 276 220 277 // Cforall allocation/deallocation and constructor/destructor, array types … … 287 344 extern "C" { // override C version 288 345 void srandom( unsigned int seed ); 289 long int random( void ); 346 long int random( void ); // GENERATES POSITIVE AND NEGATIVE VALUES 347 // For positive values, use unsigned int, e.g., unsigned int r = random() % 100U; 290 348 } // extern "C" 291 349 … … 294 352 long int random( long int u ) { if ( u < 0 ) return random( u, 0 ); else return random( 0, u ); } // [0,u) 295 353 unsigned long int random( void ) { return lrand48(); } 354 unsigned long int random( unsigned long int u ) { return lrand48() % u; } // [0,u) 296 355 unsigned long int random( unsigned long int l, unsigned long int u ) { if ( u < l ) [u, l] = [l, u]; return lrand48() % (u - l) + l; } // [l,u) 297 unsigned long int random( unsigned long int u ) { return lrand48() % u; } // [0,u)298 356 299 357 char random( void ) { return (unsigned long int)random(); } -
libcfa/src/time.hfa
r07d867b r22f94a4 10 10 // Created On : Wed Mar 14 23:18:57 2018 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Feb 4 08:24:32202013 // Update Count : 6 5412 // Last Modified On : Wed Jun 17 16:13:00 2020 13 // Update Count : 663 14 14 // 15 15 … … 20 20 21 21 #include <time.h> // timespec 22 extern "C" {23 22 #include <sys/time.h> // timeval 24 }25 23 #include <time_t.hfa> // Duration/Time types 26 24 … … 91 89 int64_t ?`w( Duration dur ) { return dur.tn / (7LL * 24LL * 60LL * 60LL * TIMEGRAN); } 92 90 91 double ?`dns( Duration dur ) { return dur.tn; } 92 double ?`dus( Duration dur ) { return dur.tn / ((double)TIMEGRAN / 1_000_000.); } 93 double ?`dms( Duration dur ) { return dur.tn / ((double)TIMEGRAN / 1_000.); } 94 double ?`ds( Duration dur ) { return dur.tn / (double)TIMEGRAN; } 95 double ?`dm( Duration dur ) { return dur.tn / (60. * TIMEGRAN); } 96 double ?`dh( Duration dur ) { return dur.tn / (60. * 60. * (double)TIMEGRAN); } 97 double ?`dd( Duration dur ) { return dur.tn / (24. * 60. * 60. * (double)TIMEGRAN); } 98 double ?`dw( Duration dur ) { return dur.tn / (7. * 24. * 60. * 60. * (double)TIMEGRAN); } 99 93 100 Duration max( Duration lhs, Duration rhs ) { return (lhs.tn < rhs.tn) ? rhs : lhs;} 94 101 Duration min( Duration lhs, Duration rhs ) { return !(rhs.tn < lhs.tn) ? lhs : rhs;} -
longrun_tests/Makefile.am
r07d867b r22f94a4 18 18 ACLOCAL_AMFLAGS = -I automake 19 19 20 include $(top_srcdir)/ src/cfa.make20 include $(top_srcdir)/tools/build/cfa.make 21 21 22 22 repeats=10 -
src/Common/PassVisitor.proto.h
r07d867b r22f94a4 38 38 }; 39 39 40 std::stack< cleanup_t, std::vector< cleanup_t> > cleanups;40 std::stack< cleanup_t, std::vector< cleanup_t > > cleanups; 41 41 }; 42 42 -
src/Common/ScopedMap.h
r07d867b r22f94a4 93 93 94 94 reference operator* () { return *it; } 95 pointer operator-> () { return it.operator->(); }95 pointer operator-> () const { return it.operator->(); } 96 96 97 97 iterator& operator++ () { -
src/Concurrency/Keywords.cc
r07d867b r22f94a4 510 510 new CastExpr( 511 511 new VariableExpr( func->get_functionType()->get_parameters().front() ), 512 func->get_functionType()->get_parameters().front()->get_type()->stripReferences()->clone() 512 func->get_functionType()->get_parameters().front()->get_type()->stripReferences()->clone(), 513 false 513 514 ) 514 515 ) … … 888 889 new SingleInit( new UntypedExpr( 889 890 new NameExpr( "get_monitor" ), 890 { new CastExpr( new VariableExpr( args.front() ), arg_type ) }891 { new CastExpr( new VariableExpr( args.front() ), arg_type, false ) } 891 892 )) 892 893 ); … … 909 910 { 910 911 new SingleInit( new AddressExpr( new VariableExpr( monitors ) ) ), 911 new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone() ) )912 new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone(), false ) ) 912 913 }, 913 914 noDesignators, … … 946 947 return new SingleInit( new UntypedExpr( 947 948 new NameExpr( "get_monitor" ), 948 { new CastExpr( new VariableExpr( var ), type ) }949 { new CastExpr( new VariableExpr( var ), type, false ) } 949 950 ) ); 950 951 }) … … 970 971 new SingleInit( new VariableExpr( monitors ) ), 971 972 new SingleInit( new ConstantExpr( Constant::from_ulong( args.size() ) ) ), 972 new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone() ) )973 new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone(), false ) ) 973 974 }, 974 975 noDesignators, -
src/Concurrency/Waitfor.cc
r07d867b r22f94a4 384 384 decl_monitor 385 385 ) 386 ) 386 ), 387 false 387 388 ); 388 389 … … 408 409 new CompoundStmt({ 409 410 makeAccStatement( acceptables, index, "is_dtor", detectIsDtor( clause.target.function ) , indexer ), 410 makeAccStatement( acceptables, index, "func" , new CastExpr( clause.target.function, fptr_t ), indexer ),411 makeAccStatement( acceptables, index, "func" , new CastExpr( clause.target.function, fptr_t, false ) , indexer ), 411 412 makeAccStatement( acceptables, index, "data" , new VariableExpr( monitors ) , indexer ), 412 413 makeAccStatement( acceptables, index, "size" , new ConstantExpr( Constant::from_ulong( clause.target.arguments.size() ) ), indexer ), … … 531 532 decl_mask 532 533 ) 533 ) 534 ), 535 false 534 536 ), 535 537 timeout -
src/ControlStruct/ExceptTranslate.cc
r07d867b r22f94a4 10 10 // Created On : Wed Jun 14 16:49:00 2017 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Mar 27 11:58:00 202013 // Update Count : 1 312 // Last Modified On : Wed Jun 24 11:18:00 2020 13 // Update Count : 17 14 14 // 15 15 … … 64 64 } 65 65 66 class ExceptionMutatorCore : public WithGuards { 67 enum Context { NoHandler, TerHandler, ResHandler }; 68 69 // Also need to handle goto, break & continue. 70 // They need to be cut off in a ResHandler, until we enter another 71 // loop, switch or the goto stays within the function. 72 73 Context cur_context; 74 75 // The current (innermost) termination handler exception declaration. 76 ObjectDecl * handler_except_decl; 77 66 class ThrowMutatorCore : public WithGuards { 67 ObjectDecl * terminate_handler_except; 68 enum Context { NoHandler, TerHandler, ResHandler } cur_context; 69 70 // The helper functions for code/syntree generation. 71 Statement * create_either_throw( 72 ThrowStmt * throwStmt, const char * throwFunc ); 73 Statement * create_terminate_rethrow( ThrowStmt * throwStmt ); 74 75 public: 76 ThrowMutatorCore() : 77 terminate_handler_except( nullptr ), 78 cur_context( NoHandler ) 79 {} 80 81 void premutate( CatchStmt *catchStmt ); 82 Statement * postmutate( ThrowStmt *throwStmt ); 83 }; 84 85 // ThrowStmt Mutation Helpers 86 87 Statement * ThrowMutatorCore::create_either_throw( 88 ThrowStmt * throwStmt, const char * throwFunc ) { 89 // `throwFunc`( `throwStmt->get_name()` ); 90 UntypedExpr * call = new UntypedExpr( new NameExpr( throwFunc ) ); 91 call->get_args().push_back( throwStmt->get_expr() ); 92 throwStmt->set_expr( nullptr ); 93 delete throwStmt; 94 return new ExprStmt( call ); 95 } 96 97 Statement * ThrowMutatorCore::create_terminate_rethrow( 98 ThrowStmt *throwStmt ) { 99 // { `terminate_handler_except` = 0p; __rethrow_terminate(); } 100 assert( nullptr == throwStmt->get_expr() ); 101 assert( terminate_handler_except ); 102 103 CompoundStmt * result = new CompoundStmt(); 104 result->labels = throwStmt->labels; 105 result->push_back( new ExprStmt( UntypedExpr::createAssign( 106 nameOf( terminate_handler_except ), 107 new ConstantExpr( Constant::null( 108 terminate_handler_except->get_type()->clone() 109 ) ) 110 ) ) ); 111 result->push_back( new ExprStmt( 112 new UntypedExpr( new NameExpr( "__cfaehm_rethrow_terminate" ) ) 113 ) ); 114 delete throwStmt; 115 return result; 116 } 117 118 // Visiting/Mutating Functions 119 120 void ThrowMutatorCore::premutate( CatchStmt *catchStmt ) { 121 // Validate the statement's form. 122 ObjectDecl * decl = dynamic_cast<ObjectDecl *>( catchStmt->get_decl() ); 123 // Also checking the type would be nice. 124 if ( !decl || !dynamic_cast<PointerType *>( decl->type ) ) { 125 std::string kind = (CatchStmt::Terminate == catchStmt->kind) ? "catch" : "catchResume"; 126 SemanticError( catchStmt->location, kind + " must have pointer to an exception type" ); 127 } 128 129 // Track the handler context. 130 GuardValue( cur_context ); 131 if ( CatchStmt::Terminate == catchStmt->get_kind() ) { 132 cur_context = TerHandler; 133 134 GuardValue( terminate_handler_except ); 135 terminate_handler_except = decl; 136 } else { 137 cur_context = ResHandler; 138 } 139 } 140 141 Statement * ThrowMutatorCore::postmutate( ThrowStmt *throwStmt ) { 142 // Ignoring throwStmt->get_target() for now. 143 if ( ThrowStmt::Terminate == throwStmt->get_kind() ) { 144 if ( throwStmt->get_expr() ) { 145 return create_either_throw( throwStmt, "$throw" ); 146 } else if ( TerHandler == cur_context ) { 147 return create_terminate_rethrow( throwStmt ); 148 } else { 149 abort("Invalid throw in %s at %i\n", 150 throwStmt->location.filename.c_str(), 151 throwStmt->location.first_line); 152 } 153 } else { 154 if ( throwStmt->get_expr() ) { 155 return create_either_throw( throwStmt, "$throwResume" ); 156 } else if ( ResHandler == cur_context ) { 157 // This has to be handled later. 158 return throwStmt; 159 } else { 160 abort("Invalid throwResume in %s at %i\n", 161 throwStmt->location.filename.c_str(), 162 throwStmt->location.first_line); 163 } 164 } 165 } 166 167 class TryMutatorCore { 78 168 // The built in types used in translation. 79 169 StructDecl * except_decl; … … 82 172 83 173 // The many helper functions for code/syntree generation. 84 Statement * create_given_throw(85 const char * throwFunc, ThrowStmt * throwStmt );86 Statement * create_terminate_throw( ThrowStmt * throwStmt );87 Statement * create_terminate_rethrow( ThrowStmt * throwStmt );88 Statement * create_resume_throw( ThrowStmt * throwStmt );89 Statement * create_resume_rethrow( ThrowStmt * throwStmt );90 174 CompoundStmt * take_try_block( TryStmt * tryStmt ); 91 175 FunctionDecl * create_try_wrapper( CompoundStmt * body ); … … 101 185 FunctionDecl * create_finally_wrapper( TryStmt * tryStmt ); 102 186 ObjectDecl * create_finally_hook( FunctionDecl * finally_wrapper ); 187 Statement * create_resume_rethrow( ThrowStmt * throwStmt ); 103 188 104 189 // Types used in translation, make sure to use clone. … … 121 206 122 207 public: 123 ExceptionMutatorCore() : 124 cur_context( NoHandler ), 125 handler_except_decl( nullptr ), 208 TryMutatorCore() : 126 209 except_decl( nullptr ), node_decl( nullptr ), hook_decl( nullptr ), 127 210 try_func_t( noQualifiers, false ), … … 132 215 {} 133 216 134 void premutate( CatchStmt *catchStmt );135 217 void premutate( StructDecl *structDecl ); 218 Statement * postmutate( TryStmt *tryStmt ); 136 219 Statement * postmutate( ThrowStmt *throwStmt ); 137 Statement * postmutate( TryStmt *tryStmt );138 220 }; 139 221 140 void ExceptionMutatorCore::init_func_types() {222 void TryMutatorCore::init_func_types() { 141 223 assert( except_decl ); 142 224 … … 196 278 } 197 279 198 // ThrowStmt Mutation Helpers199 200 Statement * ExceptionMutatorCore::create_given_throw(201 const char * throwFunc, ThrowStmt * throwStmt ) {202 // `throwFunc`( `throwStmt->get_name` );203 UntypedExpr * call = new UntypedExpr( new NameExpr( throwFunc ) );204 call->get_args().push_back( throwStmt->get_expr() );205 throwStmt->set_expr( nullptr );206 delete throwStmt;207 return new ExprStmt( call );208 }209 210 Statement * ExceptionMutatorCore::create_terminate_throw(211 ThrowStmt *throwStmt ) {212 // __throw_terminate( `throwStmt->get_name()` ); }213 return create_given_throw( "__cfaehm_throw_terminate", throwStmt );214 }215 216 Statement * ExceptionMutatorCore::create_terminate_rethrow(217 ThrowStmt *throwStmt ) {218 // { `handler_except_decl` = NULL; __rethrow_terminate(); }219 assert( nullptr == throwStmt->get_expr() );220 assert( handler_except_decl );221 222 CompoundStmt * result = new CompoundStmt();223 result->labels = throwStmt->labels;224 result->push_back( new ExprStmt( UntypedExpr::createAssign(225 nameOf( handler_except_decl ),226 new ConstantExpr( Constant::null(227 new PointerType(228 noQualifiers,229 handler_except_decl->get_type()->clone()230 )231 ) )232 ) ) );233 result->push_back( new ExprStmt(234 new UntypedExpr( new NameExpr( "__cfaehm_rethrow_terminate" ) )235 ) );236 delete throwStmt;237 return result;238 }239 240 Statement * ExceptionMutatorCore::create_resume_throw(241 ThrowStmt *throwStmt ) {242 // __throw_resume( `throwStmt->get_name` );243 return create_given_throw( "__cfaehm_throw_resume", throwStmt );244 }245 246 Statement * ExceptionMutatorCore::create_resume_rethrow(247 ThrowStmt *throwStmt ) {248 // return false;249 Statement * result = new ReturnStmt(250 new ConstantExpr( Constant::from_bool( false ) )251 );252 result->labels = throwStmt->labels;253 delete throwStmt;254 return result;255 }256 257 280 // TryStmt Mutation Helpers 258 281 259 CompoundStmt * ExceptionMutatorCore::take_try_block( TryStmt *tryStmt ) {282 CompoundStmt * TryMutatorCore::take_try_block( TryStmt *tryStmt ) { 260 283 CompoundStmt * block = tryStmt->get_block(); 261 284 tryStmt->set_block( nullptr ); … … 263 286 } 264 287 265 FunctionDecl * ExceptionMutatorCore::create_try_wrapper(288 FunctionDecl * TryMutatorCore::create_try_wrapper( 266 289 CompoundStmt *body ) { 267 290 … … 270 293 } 271 294 272 FunctionDecl * ExceptionMutatorCore::create_terminate_catch(295 FunctionDecl * TryMutatorCore::create_terminate_catch( 273 296 CatchList &handlers ) { 274 297 std::list<CaseStmt *> handler_wrappers; … … 350 373 // Create a single check from a moddified handler. 351 374 // except_obj is referenced, modded_handler will be freed. 352 CompoundStmt * ExceptionMutatorCore::create_single_matcher(375 CompoundStmt * TryMutatorCore::create_single_matcher( 353 376 DeclarationWithType * except_obj, CatchStmt * modded_handler ) { 354 377 // { … … 388 411 } 389 412 390 FunctionDecl * ExceptionMutatorCore::create_terminate_match(413 FunctionDecl * TryMutatorCore::create_terminate_match( 391 414 CatchList &handlers ) { 392 415 // int match(exception * except) { … … 425 448 } 426 449 427 CompoundStmt * ExceptionMutatorCore::create_terminate_caller(450 CompoundStmt * TryMutatorCore::create_terminate_caller( 428 451 FunctionDecl * try_wrapper, 429 452 FunctionDecl * terminate_catch, … … 443 466 } 444 467 445 FunctionDecl * ExceptionMutatorCore::create_resume_handler(468 FunctionDecl * TryMutatorCore::create_resume_handler( 446 469 CatchList &handlers ) { 447 470 // bool handle(exception * except) { … … 480 503 } 481 504 482 CompoundStmt * ExceptionMutatorCore::create_resume_wrapper(505 CompoundStmt * TryMutatorCore::create_resume_wrapper( 483 506 Statement * wraps, 484 507 FunctionDecl * resume_handler ) { … … 524 547 } 525 548 526 FunctionDecl * ExceptionMutatorCore::create_finally_wrapper(549 FunctionDecl * TryMutatorCore::create_finally_wrapper( 527 550 TryStmt * tryStmt ) { 528 // void finally() { <finally code>}551 // void finally() { `finally->block` } 529 552 FinallyStmt * finally = tryStmt->get_finally(); 530 553 CompoundStmt * body = finally->get_block(); … … 537 560 } 538 561 539 ObjectDecl * ExceptionMutatorCore::create_finally_hook(562 ObjectDecl * TryMutatorCore::create_finally_hook( 540 563 FunctionDecl * finally_wrapper ) { 541 564 // struct __cfaehm_cleanup_hook __finally_hook 542 // __attribute__((cleanup( finally_wrapper)));565 // __attribute__((cleanup( `finally_wrapper` ))); 543 566 544 567 // Make Cleanup Attribute. … … 564 587 } 565 588 589 Statement * TryMutatorCore::create_resume_rethrow( ThrowStmt *throwStmt ) { 590 // return false; 591 Statement * result = new ReturnStmt( 592 new ConstantExpr( Constant::from_bool( false ) ) 593 ); 594 result->labels = throwStmt->labels; 595 delete throwStmt; 596 return result; 597 } 598 566 599 // Visiting/Mutating Functions 567 void ExceptionMutatorCore::premutate( CatchStmt *catchStmt ) { 568 // Validate the Statement's form. 569 ObjectDecl * decl = 570 dynamic_cast<ObjectDecl *>( catchStmt->get_decl() ); 571 if ( decl && true /* check decl->get_type() */ ) { 572 // Pass. 573 } else if ( CatchStmt::Terminate == catchStmt->get_kind() ) { 574 SemanticError(catchStmt->location, "catch must have exception type"); 575 } else { 576 SemanticError(catchStmt->location, "catchResume must have exception type"); 577 } 578 579 // Track the handler context. 580 GuardValue( cur_context ); 581 if ( CatchStmt::Terminate == catchStmt->get_kind() ) { 582 cur_context = TerHandler; 583 584 GuardValue( handler_except_decl ); 585 handler_except_decl = decl; 586 } else { 587 cur_context = ResHandler; 588 } 589 } 590 591 void ExceptionMutatorCore::premutate( StructDecl *structDecl ) { 600 void TryMutatorCore::premutate( StructDecl *structDecl ) { 592 601 if ( !structDecl->has_body() ) { 593 602 // Skip children? … … 604 613 hook_decl = structDecl; 605 614 } 606 // Later we might get the exception type as well. 607 } 608 609 Statement * ExceptionMutatorCore::postmutate( ThrowStmt *throwStmt ) { 610 assert( except_decl ); 611 612 // Ignoring throwStmt->get_target() for now. 613 if ( ThrowStmt::Terminate == throwStmt->get_kind() ) { 614 if ( throwStmt->get_expr() ) { 615 return create_terminate_throw( throwStmt ); 616 } else if ( TerHandler == cur_context ) { 617 return create_terminate_rethrow( throwStmt ); 618 } else { 619 abort("Invalid throw in %s at %i\n", 620 throwStmt->location.filename.c_str(), 621 throwStmt->location.first_line); 622 } 623 } else { 624 if ( throwStmt->get_expr() ) { 625 return create_resume_throw( throwStmt ); 626 } else if ( ResHandler == cur_context ) { 627 return create_resume_rethrow( throwStmt ); 628 } else { 629 abort("Invalid throwResume in %s at %i\n", 630 throwStmt->location.filename.c_str(), 631 throwStmt->location.first_line); 632 } 633 } 634 } 635 636 Statement * ExceptionMutatorCore::postmutate( TryStmt *tryStmt ) { 615 } 616 617 Statement * TryMutatorCore::postmutate( TryStmt *tryStmt ) { 637 618 assert( except_decl ); 638 619 assert( node_decl ); … … 688 669 } 689 670 690 void translateEHM( std::list< Declaration *> & translationUnit ) { 691 PassVisitor<ExceptionMutatorCore> translator; 671 Statement * TryMutatorCore::postmutate( ThrowStmt *throwStmt ) { 672 // Only valid `throwResume;` statements should remain. (2/3 checks) 673 assert( ThrowStmt::Resume == throwStmt->kind && ! throwStmt->expr ); 674 return create_resume_rethrow( throwStmt ); 675 } 676 677 void translateThrows( std::list< Declaration *> & translationUnit ) { 678 PassVisitor<ThrowMutatorCore> translator; 692 679 mutateAll( translationUnit, translator ); 693 680 } 681 682 void translateTries( std::list< Declaration *> & translationUnit ) { 683 PassVisitor<TryMutatorCore> translator; 684 mutateAll( translationUnit, translator ); 685 } 694 686 } -
src/ControlStruct/ExceptTranslate.h
r07d867b r22f94a4 9 9 // Author : Andrew Beach 10 10 // Created On : Tus Jun 06 10:13:00 2017 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sat Jul 22 09:19:23 201713 // Update Count : 411 // Last Modified By : Andrew Beach 12 // Last Modified On : Tus May 19 11:47:00 2020 13 // Update Count : 5 14 14 // 15 15 … … 21 21 22 22 namespace ControlStruct { 23 void translateEHM( std::list< Declaration *> & translationUnit ); 24 // Converts exception handling structures into their underlying C code. Translation does use the exception 25 // handling header, make sure it is visible wherever translation occurs. 23 void translateThrows( std::list< Declaration *> & translationUnit ); 24 /* Replaces all throw & throwResume statements with function calls. 25 * These still need to be resolved, so call this before the reslover. 26 */ 27 28 void translateTries( std::list< Declaration *> & translationUnit ); 29 /* Replaces all try blocks (and their many clauses) with function definitions and calls. 30 * This uses the exception built-ins to produce typed output and should take place after 31 * the resolver. It also produces virtual casts and should happen before they are expanded. 32 */ 26 33 } 27 34 -
src/GenPoly/InstantiateGeneric.cc
r07d867b r22f94a4 9 9 // Author : Aaron B. Moss 10 10 // Created On : Thu Aug 04 18:33:00 2016 11 // Last Modified By : A aron B. Moss12 // Last Modified On : Thu Aug 04 18:33:00 201613 // Update Count : 111 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Jul 16 10:17:00 2020 13 // Update Count : 2 14 14 // 15 15 #include "InstantiateGeneric.h" … … 297 297 } 298 298 299 template< typename AggrInst > 300 static AggrInst * asForward( AggrInst * decl ) { 301 if ( !decl->body ) { 302 return nullptr; 303 } 304 decl = decl->clone(); 305 decl->body = false; 306 deleteAll( decl->members ); 307 decl->members.clear(); 308 return decl; 309 } 310 299 311 void GenericInstantiator::stripDtypeParams( AggregateDecl *base, std::list< TypeDecl* >& baseParams, const std::list< TypeExpr* >& typeSubs ) { 300 312 substituteMembers( base->get_members(), baseParams, typeSubs ); … … 373 385 concDecl->set_body( inst->get_baseStruct()->has_body() ); 374 386 substituteMembers( inst->get_baseStruct()->get_members(), *inst->get_baseParameters(), typeSubs, concDecl->get_members() ); 375 insert( inst, typeSubs, concDecl ); // must insert before recursion 387 // Forward declare before recursion. (TODO: Only when needed, #199.) 388 insert( inst, typeSubs, concDecl ); 389 if ( StructDecl *forwardDecl = asForward( concDecl ) ) { 390 declsToAddBefore.push_back( forwardDecl ); 391 } 376 392 concDecl->acceptMutator( *visitor ); // recursively instantiate members 377 393 declsToAddBefore.push_back( concDecl ); // must occur before declaration is added so that member instantiations appear first … … 423 439 concDecl->set_body( inst->get_baseUnion()->has_body() ); 424 440 substituteMembers( inst->get_baseUnion()->get_members(), *inst->get_baseParameters(), typeSubs, concDecl->get_members() ); 425 insert( inst, typeSubs, concDecl ); // must insert before recursion 441 // Forward declare before recursion. (TODO: Only when needed, #199.) 442 insert( inst, typeSubs, concDecl ); 443 if ( UnionDecl *forwardDecl = asForward( concDecl ) ) { 444 declsToAddBefore.push_back( forwardDecl ); 445 } 426 446 concDecl->acceptMutator( *visitor ); // recursively instantiate members 427 447 declsToAddBefore.push_back( concDecl ); // must occur before declaration is added so that member instantiations appear first -
src/GenPoly/Specialize.cc
r07d867b r22f94a4 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Fri Dec 13 23:40:49 201913 // Update Count : 3 211 // Last Modified By : Andrew Beach 12 // Last Modified On : Thr Jul 2 17:42:00 2020 13 // Update Count : 33 14 14 // 15 15 … … 42 42 43 43 namespace GenPoly { 44 struct Specialize final : public WithConstTypeSubstitution, public WithStmtsToAdd, public WithVisitorRef<Specialize> { 44 struct Specialize final : public WithConstTypeSubstitution, 45 public WithDeclsToAdd, public WithVisitorRef<Specialize> { 45 46 Expression * postmutate( ApplicationExpr *applicationExpr ); 46 47 Expression * postmutate( CastExpr *castExpr ); … … 248 249 } // if 249 250 250 // handle any specializations that may still be present 251 std::string oldParamPrefix = paramPrefix; 252 paramPrefix += "p"; 253 // save stmtsToAddBefore in oldStmts 254 std::list< Statement* > oldStmts; 255 oldStmts.splice( oldStmts.end(), stmtsToAddBefore ); 256 appExpr->acceptMutator( *visitor ); 257 paramPrefix = oldParamPrefix; 258 // write any statements added for recursive specializations into the thunk body 259 thunkFunc->statements->kids.splice( thunkFunc->statements->kids.end(), stmtsToAddBefore ); 260 // restore oldStmts into stmtsToAddBefore 261 stmtsToAddBefore.splice( stmtsToAddBefore.end(), oldStmts ); 251 // Handle any specializations that may still be present. 252 { 253 std::string oldParamPrefix = paramPrefix; 254 paramPrefix += "p"; 255 std::list< Declaration * > oldDecls; 256 oldDecls.splice( oldDecls.end(), declsToAddBefore ); 257 258 appExpr->acceptMutator( *visitor ); 259 // Write recursive specializations into the thunk body. 260 for ( Declaration * decl : declsToAddBefore ) { 261 thunkFunc->statements->kids.push_back( new DeclStmt( decl ) ); 262 } 263 264 declsToAddBefore = std::move( oldDecls ); 265 paramPrefix = oldParamPrefix; 266 } 262 267 263 268 // add return (or valueless expression) to the thunk … … 270 275 thunkFunc->statements->kids.push_back( appStmt ); 271 276 272 // add thunk definition to queue of statements to add273 stmtsToAddBefore.push_back( new DeclStmt( thunkFunc ));277 // Add the thunk definition (converted to DeclStmt if appproprate). 278 declsToAddBefore.push_back( thunkFunc ); 274 279 // return address of thunk function as replacement expression 275 280 return new AddressExpr( new VariableExpr( thunkFunc ) ); -
src/Parser/DeclarationNode.cc
r07d867b r22f94a4 10 10 // Created On : Sat May 16 12:34:05 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Dec 16 15:32:22 201913 // Update Count : 113 312 // Last Modified On : Tue Jun 9 20:26:55 2020 13 // Update Count : 1134 14 14 // 15 15 … … 1115 1115 // SUE's cannot have function specifiers, either 1116 1116 // 1117 // inl ne _Noreturn struct S { ... }; // disallowed1118 // inl ne _Noreturn enum E { ... }; // disallowed1117 // inline _Noreturn struct S { ... }; // disallowed 1118 // inline _Noreturn enum E { ... }; // disallowed 1119 1119 if ( funcSpecs.any() ) { 1120 1120 SemanticError( this, "invalid function specifier for " ); -
src/Parser/ExpressionNode.cc
r07d867b r22f94a4 10 10 // Created On : Sat May 16 13:17:07 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Dec 18 21:14:58 201913 // Update Count : 98112 // Last Modified On : Wed Jul 15 08:24:08 2020 13 // Update Count : 1046 14 14 // 15 15 … … 85 85 } // if 86 86 // remove "lL" for these cases because it may not imply long 87 str.erase( posn ); // remove length 87 str.erase( posn ); // remove length suffix and "uU" 88 88 } // lnthSuffix 89 89 … … 108 108 } // valueToType 109 109 110 static void scanbin( string & str, unsigned long long int & v ) { 111 v = 0; 112 size_t last = str.length() - 1; // last subscript of constant 113 for ( unsigned int i = 2;; ) { // ignore prefix 114 if ( str[i] == '1' ) v |= 1; 115 i += 1; 116 if ( i == last - 1 || (str[i] != '0' && str[i] != '1') ) break; 117 v <<= 1; 118 } // for 119 } // scanbin 120 110 121 Expression * build_constantInteger( string & str ) { 111 122 static const BasicType::Kind kind[2][6] = { 112 123 // short (h) must be before char (hh) because shorter type has the longer suffix 113 { BasicType::ShortSignedInt, BasicType::SignedChar, BasicType::SignedInt, BasicType::LongSignedInt, BasicType::LongLongSignedInt, BasicType::SignedInt128, },114 { BasicType::ShortUnsignedInt, BasicType::UnsignedChar, BasicType::UnsignedInt, BasicType::LongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::UnsignedInt128, },124 { BasicType::ShortSignedInt, BasicType::SignedChar, BasicType::SignedInt, BasicType::LongSignedInt, BasicType::LongLongSignedInt, /* BasicType::SignedInt128 */ BasicType::LongLongSignedInt, }, 125 { BasicType::ShortUnsignedInt, BasicType::UnsignedChar, BasicType::UnsignedInt, BasicType::LongUnsignedInt, BasicType::LongLongUnsignedInt, /* BasicType::UnsignedInt128 */ BasicType::LongLongUnsignedInt, }, 115 126 }; 116 127 … … 120 131 }; // lnthsInt 121 132 122 unsigned long long int v; // converted integral value 123 size_t last = str.length() - 1; // last subscript of constant 124 Expression * ret; 125 //string fred( str ); 133 string str2( "0x0" ); 134 unsigned long long int v, v2 = 0; // converted integral value 135 Expression * ret, * ret2; 126 136 127 137 int type = -1; // 0 => short, 1 => char, 2 => int, 3 => long int, 4 => long long int, 5 => int128 … … 139 149 } // if 140 150 151 string::size_type posn; 152 153 // 'u' can appear before or after length suffix 154 if ( str.find_last_of( "uU" ) != string::npos ) Unsigned = true; 155 156 if ( isdigit( str[str.length() - 1] ) ) { // no suffix ? 157 lnthSuffix( str, type, ltype ); // could have length suffix 158 if ( type == 5 && Unsigned ) str.erase( str.length() - 1 ); // L128 and terminating "uU" ? 159 } else { 160 // At least one digit in integer constant, so safe to backup while looking for suffix. 161 162 posn = str.find_last_of( "pP" ); // pointer value 163 if ( posn != string::npos ) { ltype = 5; str.erase( posn, 1 ); goto FINI; } 164 165 posn = str.find_last_of( "zZ" ); // size_t 166 if ( posn != string::npos ) { Unsigned = true; type = 2; ltype = 4; str.erase( posn, 1 ); goto FINI; } 167 168 posn = str.rfind( "hh" ); // char 169 if ( posn != string::npos ) { type = 1; str.erase( posn, 2 ); goto FINI; } 170 171 posn = str.rfind( "HH" ); // char 172 if ( posn != string::npos ) { type = 1; str.erase( posn, 2 ); goto FINI; } 173 174 posn = str.find_last_of( "hH" ); // short 175 if ( posn != string::npos ) { type = 0; str.erase( posn, 1 ); goto FINI; } 176 177 posn = str.find_last_of( "nN" ); // int (natural number) 178 if ( posn != string::npos ) { type = 2; str.erase( posn, 1 ); goto FINI; } 179 180 if ( str.rfind( "ll" ) != string::npos || str.rfind( "LL" ) != string::npos ) { type = 4; goto FINI; } 181 182 lnthSuffix( str, type, ltype ); // must be after check for "ll" 183 FINI: ; 184 } // if 185 141 186 // Cannot be just "0"/"1"; sscanf stops at the suffix, if any; value goes over the wall => always generate 142 187 188 #if ! defined(__SIZEOF_INT128__) 189 if ( type == 5 ) SemanticError( yylloc, "int128 constant is not supported on this target " + str ); 190 #endif // ! __SIZEOF_INT128__ 191 143 192 if ( str[0] == '0' ) { // radix character ? 144 193 dec = false; 145 194 if ( checkX( str[1] ) ) { // hex constant ? 146 sscanf( (char *)str.c_str(), "%llx", &v ); 195 if ( type < 5 ) { // not L128 ? 196 sscanf( (char *)str.c_str(), "%llx", &v ); 197 } else { // hex int128 constant 198 unsigned int len = str.length(); 199 if ( len > (2 + 16 + 16) ) SemanticError( yylloc, "128-bit hexadecimal constant to large " + str ); 200 if ( len <= (2 + 16) ) goto FHEX1; // hex digits < 2^64 201 str2 = "0x" + str.substr( len - 16 ); 202 sscanf( (char *)str2.c_str(), "%llx", &v2 ); 203 str = str.substr( 0, len - 16 ); 204 FHEX1: ; 205 sscanf( (char *)str.c_str(), "%llx", &v ); 206 } // if 147 207 //printf( "%llx %llu\n", v, v ); 148 208 } else if ( checkB( str[1] ) ) { // binary constant ? 149 v = 0; // compute value 150 for ( unsigned int i = 2;; ) { // ignore prefix 151 if ( str[i] == '1' ) v |= 1; 152 i += 1; 153 if ( i == last - 1 || (str[i] != '0' && str[i] != '1') ) break; 154 v <<= 1; 155 } // for 209 unsigned int len = str.length(); 210 if ( type == 5 && len > 2 + 64 ) { 211 if ( len > 2 + 64 + 64 ) SemanticError( yylloc, "128-bit binary constant to large " + str ); 212 str2 = "0b" + str.substr( len - 64 ); 213 str = str.substr( 0, len - 64 ); 214 scanbin( str2, v2 ); 215 } // if 216 scanbin( str, v ); 156 217 //printf( "%#llx %llu\n", v, v ); 157 218 } else { // octal constant 158 sscanf( (char *)str.c_str(), "%llo", &v ); 219 if ( type < 5 ) { // not L128 ? 220 sscanf( (char *)str.c_str(), "%llo", &v ); 221 #if defined(__SIZEOF_INT128__) 222 } else { // octal int128 constant 223 unsigned int len = str.length(); 224 if ( len > 1 + 43 || (len == 1 + 43 && str[0] > '3') ) SemanticError( yylloc, "128-bit octal constant to large " + str ); 225 if ( len <= 1 + 21 ) { // value < 21 octal digitis 226 sscanf( (char *)str.c_str(), "%llo", &v ); // leave value in octal 227 } else { 228 sscanf( &str[len - 21], "%llo", &v ); 229 __int128 val = v; // accumulate bits 230 str[len - 21] ='\0'; // shorten string 231 sscanf( &str[len == 43 ? 1 : 0], "%llo", &v ); 232 val |= (__int128)v << 63; // store bits 233 if ( len == 1 + 43 ) { // most significant 2 bits ? 234 str[2] = '\0'; // shorten string 235 sscanf( &str[1], "%llo", &v ); // process most significant 2 bits 236 val |= (__int128)v << 126; // store bits 237 } // if 238 v = val >> 64; v2 = (uint64_t)val; // replace octal constant with 2 hex constants 239 char buf[32]; 240 sprintf( buf, "%#llx", v2 ); 241 str2 = buf; 242 sprintf( buf, "%#llx", v ); 243 str = buf; 244 } // if 245 #endif // __SIZEOF_INT128__ 246 } // if 159 247 //printf( "%#llo %llu\n", v, v ); 160 248 } // if 161 249 } else { // decimal constant ? 162 sscanf( (char *)str.c_str(), "%llu", &v ); 250 if ( type < 5 ) { // not L128 ? 251 sscanf( (char *)str.c_str(), "%llu", &v ); 252 #if defined(__SIZEOF_INT128__) 253 } else { // decimal int128 constant 254 #define P10_UINT64 10'000'000'000'000'000'000ULL // 19 zeroes 255 unsigned int len = str.length(); 256 if ( str.length() == 39 && str > (Unsigned ? "340282366920938463463374607431768211455" : "170141183460469231731687303715884105727") ) 257 SemanticError( yylloc, "128-bit decimal constant to large " + str ); 258 if ( len <= 19 ) { // value < 19 decimal digitis 259 sscanf( (char *)str.c_str(), "%llu", &v ); // leave value in decimal 260 } else { 261 sscanf( &str[len - 19], "%llu", &v ); 262 __int128 val = v; // accumulate bits 263 str[len - 19] ='\0'; // shorten string 264 sscanf( &str[len == 39 ? 1 : 0], "%llu", &v ); 265 val += (__int128)v * (__int128)P10_UINT64; // store bits 266 if ( len == 39 ) { // most significant 2 bits ? 267 str[1] = '\0'; // shorten string 268 sscanf( &str[0], "%llu", &v ); // process most significant 2 bits 269 val += (__int128)v * (__int128)P10_UINT64 * (__int128)P10_UINT64; // store bits 270 } // if 271 v = val >> 64; v2 = (uint64_t)val; // replace decimal constant with 2 hex constants 272 char buf[32]; 273 sprintf( buf, "%#llx", v2 ); 274 str2 = buf; 275 sprintf( buf, "%#llx", v ); 276 str = buf; 277 } // if 278 #endif // __SIZEOF_INT128__ 279 } // if 163 280 //printf( "%llu\n", v ); 164 281 } // if 165 282 166 string::size_type posn; 167 168 if ( isdigit( str[last] ) ) { // no suffix ? 169 lnthSuffix( str, type, ltype ); // could have length suffix 170 if ( type == -1 ) { // no suffix 171 valueToType( v, dec, type, Unsigned ); 172 } // if 173 } else { 174 // At least one digit in integer constant, so safe to backup while looking for suffix. 175 176 posn = str.find_last_of( "pP" ); 177 if ( posn != string::npos ) { valueToType( v, dec, type, Unsigned ); ltype = 5; str.erase( posn, 1 ); goto FINI; } 178 179 posn = str.find_last_of( "zZ" ); 180 if ( posn != string::npos ) { Unsigned = true; type = 2; ltype = 4; str.erase( posn, 1 ); goto FINI; } 181 182 // 'u' can appear before or after length suffix 183 if ( str.find_last_of( "uU" ) != string::npos ) Unsigned = true; 184 185 posn = str.rfind( "hh" ); 186 if ( posn != string::npos ) { type = 1; str.erase( posn, 2 ); goto FINI; } 187 188 posn = str.rfind( "HH" ); 189 if ( posn != string::npos ) { type = 1; str.erase( posn, 2 ); goto FINI; } 190 191 posn = str.find_last_of( "hH" ); 192 if ( posn != string::npos ) { type = 0; str.erase( posn, 1 ); goto FINI; } 193 194 posn = str.find_last_of( "nN" ); 195 if ( posn != string::npos ) { type = 2; str.erase( posn, 1 ); goto FINI; } 196 197 if ( str.rfind( "ll" ) != string::npos || str.rfind( "LL" ) != string::npos ) { type = 4; goto FINI; } 198 199 lnthSuffix( str, type, ltype ); // must be after check for "ll" 200 if ( type == -1 ) { // only 'u' suffix ? 201 valueToType( v, dec, type, Unsigned ); 202 } // if 203 FINI: ; 204 } // if 283 if ( type == -1 ) { // no suffix => determine type from value size 284 valueToType( v, dec, type, Unsigned ); 285 } // if 286 /* printf( "%s %llo %s %llo\n", str.c_str(), v, str2.c_str(), v2 ); */ 205 287 206 288 //if ( !( 0 <= type && type <= 6 ) ) { printf( "%s %lu %d %s\n", fred.c_str(), fred.length(), type, str.c_str() ); } … … 214 296 } else if ( ltype != -1 ) { // explicit length ? 215 297 if ( ltype == 6 ) { // int128, (int128)constant 216 ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[Unsigned][type] ), false ); 298 // ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[Unsigned][type] ), false ); 299 ret2 = new ConstantExpr( Constant( new BasicType( noQualifiers, BasicType::LongLongSignedInt ), str2, v2 ) ); 300 ret = build_compoundLiteral( DeclarationNode::newBasicType( DeclarationNode::Int128 )->addType( DeclarationNode::newSignedNess( DeclarationNode::Unsigned ) ), 301 new InitializerNode( (InitializerNode *)(new InitializerNode( new ExpressionNode( v2 == 0 ? ret2 : ret ) ))->set_last( new InitializerNode( new ExpressionNode( v2 == 0 ? ret : ret2 ) ) ), true ) ); 217 302 } else { // explicit length, (length_type)constant 218 303 ret = new CastExpr( ret, new TypeInstType( Type::Qualifiers(), lnthsInt[Unsigned][ltype], false ), false ); … … 342 427 if ( str[1] == '8' ) goto Default; // utf-8 characters => array of char 343 428 // lookup type of associated typedef 344 strtype = new TypeInstType( Type::Qualifiers( Type::Const), "char16_t", false );429 strtype = new TypeInstType( Type::Qualifiers( ), "char16_t", false ); 345 430 break; 346 431 case 'U': 347 strtype = new TypeInstType( Type::Qualifiers( Type::Const), "char32_t", false );432 strtype = new TypeInstType( Type::Qualifiers( ), "char32_t", false ); 348 433 break; 349 434 case 'L': 350 strtype = new TypeInstType( Type::Qualifiers( Type::Const), "wchar_t", false );435 strtype = new TypeInstType( Type::Qualifiers( ), "wchar_t", false ); 351 436 break; 352 437 Default: // char default string type 353 438 default: 354 strtype = new BasicType( Type::Qualifiers( Type::Const), BasicType::Char );439 strtype = new BasicType( Type::Qualifiers( ), BasicType::Char ); 355 440 } // switch 356 441 ArrayType * at = new ArrayType( noQualifiers, strtype, -
src/Parser/ParseNode.h
r07d867b r22f94a4 10 10 // Created On : Sat May 16 13:28:16 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Feb 7 17:56:02 202013 // Update Count : 89 112 // Last Modified On : Mon Jul 6 09:33:32 2020 13 // Update Count : 892 14 14 // 15 15 … … 86 86 class InitializerNode : public ParseNode { 87 87 public: 88 InitializerNode( ExpressionNode *, bool aggrp = false, ExpressionNode * des = nullptr );88 InitializerNode( ExpressionNode *, bool aggrp = false, ExpressionNode * des = nullptr ); 89 89 InitializerNode( InitializerNode *, bool aggrp = false, ExpressionNode * des = nullptr ); 90 90 InitializerNode( bool isDelete ); -
src/Parser/module.mk
r07d867b r22f94a4 17 17 BUILT_SOURCES = Parser/parser.hh 18 18 19 AM_YFLAGS = -d -t -v 19 AM_YFLAGS = -d -t -v -Wno-yacc 20 20 21 21 SRC += \ -
src/Parser/parser.yy
r07d867b r22f94a4 10 10 // Created On : Sat Sep 1 20:22:55 2001 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Apr 27 12:25:42202013 // Update Count : 4 48312 // Last Modified On : Thu May 28 12:11:45 2020 13 // Update Count : 4500 14 14 // 15 15 … … 329 329 %type<en> conditional_expression constant_expression assignment_expression assignment_expression_opt 330 330 %type<en> comma_expression comma_expression_opt 331 %type<en> argument_expression_list argument_expression default_initialize_opt331 %type<en> argument_expression_list_opt argument_expression default_initialize_opt 332 332 %type<ifctl> if_control_expression 333 333 %type<fctl> for_control_expression for_control_expression_list … … 624 624 // equivalent to the old x[i,j]. 625 625 { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, $3 ) ); } 626 | postfix_expression '{' argument_expression_list '}' // CFA, constructor call626 | postfix_expression '{' argument_expression_list_opt '}' // CFA, constructor call 627 627 { 628 628 Token fn; … … 630 630 $$ = new ExpressionNode( new ConstructorExpr( build_func( new ExpressionNode( build_varref( fn ) ), (ExpressionNode *)( $1 )->set_last( $3 ) ) ) ); 631 631 } 632 | postfix_expression '(' argument_expression_list ')'632 | postfix_expression '(' argument_expression_list_opt ')' 633 633 { $$ = new ExpressionNode( build_func( $1, $3 ) ); } 634 634 | postfix_expression '`' identifier // CFA, postfix call … … 662 662 | '(' type_no_function ')' '@' '{' initializer_list_opt comma_opt '}' // CFA, explicit C compound-literal 663 663 { $$ = new ExpressionNode( build_compoundLiteral( $2, (new InitializerNode( $6, true ))->set_maybeConstructed( false ) ) ); } 664 | '^' primary_expression '{' argument_expression_list '}' // CFA, destructor call664 | '^' primary_expression '{' argument_expression_list_opt '}' // CFA, destructor call 665 665 { 666 666 Token fn; … … 670 670 ; 671 671 672 argument_expression_list :672 argument_expression_list_opt: 673 673 // empty 674 674 { $$ = nullptr; } 675 675 | argument_expression 676 | argument_expression_list ',' argument_expression676 | argument_expression_list_opt ',' argument_expression 677 677 { $$ = (ExpressionNode *)($1->set_last( $3 )); } 678 678 ; … … 1196 1196 { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), new ExpressionNode( build_constantInteger( *new string( "0" ) ) ), 1197 1197 OperKinds::LThan, $1->clone(), new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); } 1198 | '=' comma_expression // CFA1198 | '=' comma_expression // CFA 1199 1199 { $$ = forCtrl( $2, new string( DeclarationNode::anonymous.newName() ), new ExpressionNode( build_constantInteger( *new string( "0" ) ) ), 1200 1200 OperKinds::LEThan, $2->clone(), new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); } … … 1203 1203 | comma_expression inclexcl comma_expression '~' comma_expression // CFA 1204 1204 { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), $1->clone(), $2, $3, $5 ); } 1205 | comma_expression ';' // CFA 1206 { $$ = forCtrl( new ExpressionNode( build_constantInteger( *new string( "0u" ) ) ), $1, nullptr, OperKinds::LThan, nullptr, nullptr ); } 1205 1207 | comma_expression ';' comma_expression // CFA 1206 1208 { $$ = forCtrl( $3, $1, new ExpressionNode( build_constantInteger( *new string( "0" ) ) ), 1207 1209 OperKinds::LThan, $3->clone(), new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); } 1208 | comma_expression ';' '=' comma_expression // CFA1210 | comma_expression ';' '=' comma_expression // CFA 1209 1211 { $$ = forCtrl( $4, $1, new ExpressionNode( build_constantInteger( *new string( "0" ) ) ), 1210 1212 OperKinds::LEThan, $4->clone(), new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); } … … 1304 1306 // If MUTEX becomes a general qualifier, there are shift/reduce conflicts, so change syntax to "with mutex". 1305 1307 mutex_statement: 1306 MUTEX '(' argument_expression_list ')' statement1308 MUTEX '(' argument_expression_list_opt ')' statement 1307 1309 { SemanticError( yylloc, "Mutex statement is currently unimplemented." ); $$ = nullptr; } 1308 1310 ; … … 1321 1323 WAITFOR '(' cast_expression ')' 1322 1324 { $$ = $3; } 1323 // | WAITFOR '(' cast_expression ',' argument_expression_list ')'1325 // | WAITFOR '(' cast_expression ',' argument_expression_list_opt ')' 1324 1326 // { $$ = (ExpressionNode *)$3->set_last( $5 ); } 1325 | WAITFOR '(' cast_expression_list ':' argument_expression_list ')'1327 | WAITFOR '(' cast_expression_list ':' argument_expression_list_opt ')' 1326 1328 { $$ = (ExpressionNode *)($3->set_last( $5 )); } 1327 1329 ; … … 1330 1332 cast_expression 1331 1333 | cast_expression_list ',' cast_expression 1332 { $$ = (ExpressionNode *)($1->set_last( $3 )); } 1334 // { $$ = (ExpressionNode *)($1->set_last( $3 )); } 1335 { SemanticError( yylloc, "List of mutex member is currently unimplemented." ); $$ = nullptr; } 1333 1336 ; 1334 1337 … … 2095 2098 2096 2099 aggregate_control: // CFA 2097 GENERATOR 2100 MONITOR 2101 { yyy = true; $$ = AggregateDecl::Monitor; } 2102 | MUTEX STRUCT 2103 { yyy = true; $$ = AggregateDecl::Monitor; } 2104 | GENERATOR 2098 2105 { yyy = true; $$ = AggregateDecl::Generator; } 2099 | M ONITORGENERATOR2106 | MUTEX GENERATOR 2100 2107 { SemanticError( yylloc, "monitor generator is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; } 2101 2108 | COROUTINE 2102 2109 { yyy = true; $$ = AggregateDecl::Coroutine; } 2103 | MONITOR 2104 { yyy = true; $$ = AggregateDecl::Monitor; } 2105 | MONITOR COROUTINE 2110 | MUTEX COROUTINE 2106 2111 { SemanticError( yylloc, "monitor coroutine is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; } 2107 2112 | THREAD 2108 2113 { yyy = true; $$ = AggregateDecl::Thread; } 2109 | M ONITORTHREAD2114 | MUTEX THREAD 2110 2115 { SemanticError( yylloc, "monitor thread is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; } 2111 2116 ; … … 2774 2779 | attr_name 2775 2780 { $$ = DeclarationNode::newAttribute( $1 ); } 2776 | attr_name '(' argument_expression_list ')'2781 | attr_name '(' argument_expression_list_opt ')' 2777 2782 { $$ = DeclarationNode::newAttribute( $1, $3 ); } 2778 2783 ; -
src/ResolvExpr/AlternativeFinder.cc
r07d867b r22f94a4 1216 1216 unify( castExpr->result, alt.expr->result, alt.env, needAssertions, 1217 1217 haveAssertions, openVars, indexer ); 1218 Cost thisCost = castCost( alt.expr->result, castExpr->result, alt.expr->get_lvalue(), 1219 indexer, alt.env ); 1218 Cost thisCost = 1219 castExpr->isGenerated 1220 ? conversionCost( alt.expr->result, castExpr->result, alt.expr->get_lvalue(), indexer, alt.env ) 1221 : castCost( alt.expr->result, castExpr->result, alt.expr->get_lvalue(), indexer, alt.env ); 1220 1222 PRINT( 1221 1223 std::cerr << "working on cast with result: " << castExpr->result << std::endl; … … 1698 1700 1699 1701 // unification run for side-effects 1700 unify( toType, alt.expr->result, newEnv, need, have, openVars, indexer ); 1702 bool canUnify = unify( toType, alt.expr->result, newEnv, need, have, openVars, indexer ); 1703 (void) canUnify; 1701 1704 // xxx - do some inspecting on this line... why isn't result bound to initAlt.type? 1702 1705 1703 Cost thisCost = c astCost( alt.expr->result, toType, alt.expr->get_lvalue(),1706 Cost thisCost = computeConversionCost( alt.expr->result, toType, alt.expr->get_lvalue(), 1704 1707 indexer, newEnv ); 1708 1709 PRINT( 1710 Cost legacyCost = castCost( alt.expr->result, toType, alt.expr->get_lvalue(), 1711 indexer, newEnv ); 1712 std::cerr << "Considering initialization:"; 1713 std::cerr << std::endl << " FROM: "; alt.expr->result->print(std::cerr); 1714 std::cerr << std::endl << " TO: "; toType ->print(std::cerr); 1715 std::cerr << std::endl << " Unification " << (canUnify ? "succeeded" : "failed"); 1716 std::cerr << std::endl << " Legacy cost " << legacyCost; 1717 std::cerr << std::endl << " New cost " << thisCost; 1718 std::cerr << std::endl; 1719 ) 1720 1705 1721 if ( thisCost != Cost::infinity ) { 1706 1722 // count one safe conversion for each value that is thrown away -
src/ResolvExpr/ConversionCost.cc
r07d867b r22f94a4 10 10 // Created On : Sun May 17 07:06:19 2015 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Oct 4 14:45:00 201912 // Last Modified On : Wed Jul 29 16:11:00 2020 13 13 // Update Count : 28 14 14 // … … 392 392 void ConversionCost::postvisit( const FunctionType * ) {} 393 393 394 void ConversionCost::postvisit( const StructInstType * inst ) {395 /*396 if ( const StructInstType * destAsInst = dynamic_cast< const StructInstType * >( dest ) ) {397 if ( inst->name == destAsInst->name ) {398 cost = Cost::zero;399 } // if400 } // if401 */402 }403 404 void ConversionCost::postvisit( const UnionInstType * inst ) {405 /*406 if ( const UnionInstType * destAsInst = dynamic_cast< const UnionInstType * >( dest ) ) {407 if ( inst->name == destAsInst->name ) {408 cost = Cost::zero;409 } // if410 } // if411 */412 }413 414 394 void ConversionCost::postvisit( const EnumInstType * ) { 415 395 static Type::Qualifiers q; … … 685 665 } 686 666 687 void ConversionCost_new::postvisit( const ast::StructInstType * structInstType ) {688 /*689 if ( const ast::StructInstType * dstAsInst =690 dynamic_cast< const ast::StructInstType * >( dst ) ) {691 if ( structInstType->name == dstAsInst->name ) {692 cost = Cost::zero;693 }694 }695 */696 }697 698 void ConversionCost_new::postvisit( const ast::UnionInstType * unionInstType ) {699 /*700 if ( const ast::UnionInstType * dstAsInst =701 dynamic_cast< const ast::UnionInstType * >( dst ) ) {702 if ( unionInstType->name == dstAsInst->name ) {703 cost = Cost::zero;704 }705 }706 */707 }708 709 667 void ConversionCost_new::postvisit( const ast::EnumInstType * enumInstType ) { 710 668 (void)enumInstType; -
src/ResolvExpr/ConversionCost.h
r07d867b r22f94a4 10 10 // Created On : Sun May 17 09:37:28 2015 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Tue Oct 4 14:59:00 201912 // Last Modified On : Wed Jul 29 16:12:00 2020 13 13 // Update Count : 7 14 14 // … … 51 51 void postvisit( const ReferenceType * refType ); 52 52 void postvisit( const FunctionType * functionType ); 53 void postvisit( const StructInstType * aggregateUseType );54 void postvisit( const UnionInstType * aggregateUseType );55 53 void postvisit( const EnumInstType * aggregateUseType ); 56 54 void postvisit( const TraitInstType * aggregateUseType ); … … 105 103 void postvisit( const ast::ReferenceType * refType ); 106 104 void postvisit( const ast::FunctionType * functionType ); 107 void postvisit( const ast::StructInstType * structInstType );108 void postvisit( const ast::UnionInstType * unionInstType );109 105 void postvisit( const ast::EnumInstType * enumInstType ); 110 106 void postvisit( const ast::TraitInstType * traitInstType ); -
src/SynTree/Expression.h
r07d867b r22f94a4 206 206 public: 207 207 Expression * arg; 208 bool isGenerated = true; // cast generated implicitly by code generation or explicit in program 208 209 // Inidicates cast is introduced by the CFA type system. 210 // true for casts that the resolver introduces to force a return type 211 // false for casts from user code 212 // false for casts from desugaring advanced CFA features into simpler CFA 213 // example 214 // int * p; // declaration 215 // (float *) p; // use, with subject cast 216 // subject cast isGenerated means we are considering an interpretation with a type mismatch 217 // subject cast not isGenerated means someone in charge wants it that way 218 bool isGenerated = true; 209 219 210 220 CastExpr( Expression * arg, bool isGenerated = true ); -
src/Virtual/ExpandCasts.cc
r07d867b r22f94a4 10 10 // Created On : Mon Jul 24 13:59:00 2017 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Tus Aug 2 14:59:00 201713 // Update Count : 112 // Last Modified On : Fri Jul 31 10:29:00 2020 13 // Update Count : 4 14 14 // 15 15 … … 18 18 #include <cassert> // for assert, assertf 19 19 #include <iterator> // for back_inserter, inserter 20 #include <map> // for map, _Rb_tree_iterator, map<>::ite...21 20 #include <string> // for string, allocator, operator==, ope... 22 #include <utility> // for pair23 21 24 22 #include "Common/PassVisitor.h" // for PassVisitor 23 #include "Common/ScopedMap.h" // for ScopedMap 25 24 #include "Common/SemanticError.h" // for SemanticError 25 #include "SymTab/Mangler.h" // for mangleType 26 26 #include "SynTree/Declaration.h" // for ObjectDecl, StructDecl, FunctionDecl 27 27 #include "SynTree/Expression.h" // for VirtualCastExpr, CastExpr, Address... … … 31 31 32 32 namespace Virtual { 33 34 // Indented until the new ast code gets added. 35 36 /// Maps virtual table types the instance for that type. 37 class VirtualTableMap final { 38 ScopedMap<std::string, ObjectDecl *> vtable_instances; 39 public: 40 void enterScope() { 41 vtable_instances.beginScope(); 42 } 43 void leaveScope() { 44 vtable_instances.endScope(); 45 } 46 47 ObjectDecl * insert( ObjectDecl * vtableDecl ) { 48 std::string const & mangledName = SymTab::Mangler::mangleType( vtableDecl->type ); 49 ObjectDecl *& value = vtable_instances[ mangledName ]; 50 if ( value ) { 51 if ( vtableDecl->storageClasses.is_extern ) { 52 return nullptr; 53 } else if ( ! value->storageClasses.is_extern ) { 54 return value; 55 } 56 } 57 value = vtableDecl; 58 return nullptr; 59 } 60 61 ObjectDecl * lookup( const Type * vtableType ) { 62 std::string const & mangledName = SymTab::Mangler::mangleType( vtableType ); 63 const auto it = vtable_instances.find( mangledName ); 64 return ( vtable_instances.end() == it ) ? nullptr : it->second; 65 } 66 }; 33 67 34 68 /* Currently virtual depends on the rather brittle name matching between … … 39 73 */ 40 74 75 namespace { 76 41 77 std::string get_vtable_name( std::string const & name ) { 42 78 return name + "_vtable"; … … 53 89 std::string get_vtable_inst_name_root( std::string const & name ) { 54 90 return get_vtable_name_root( name.substr(1, name.size() - 10 ) ); 55 }56 57 bool is_vtable_name( std::string const & name ) {58 return (name.substr( name.size() - 7 ) == "_vtable" );59 91 } 60 92 … … 64 96 } 65 97 98 } // namespace 99 66 100 class VirtualCastCore { 67 std::map<std::string, ObjectDecl *> vtable_instances;68 FunctionDecl *vcast_decl;69 StructDecl *pvt_decl;70 71 101 Type * pointer_to_pvt(int level_of_indirection) { 72 102 Type * type = new StructInstType( … … 80 110 public: 81 111 VirtualCastCore() : 82 vtable_instances(), vcast_decl( nullptr ), pvt_decl( nullptr )112 indexer(), vcast_decl( nullptr ), pvt_decl( nullptr ) 83 113 {} 84 114 … … 88 118 89 119 Expression * postmutate( VirtualCastExpr * castExpr ); 120 121 VirtualTableMap indexer; 122 private: 123 FunctionDecl *vcast_decl; 124 StructDecl *pvt_decl; 90 125 }; 91 126 … … 107 142 void VirtualCastCore::premutate( ObjectDecl * objectDecl ) { 108 143 if ( is_vtable_inst_name( objectDecl->get_name() ) ) { 109 vtable_instances[objectDecl->get_name()] = objectDecl; 110 } 111 } 144 if ( ObjectDecl * existing = indexer.insert( objectDecl ) ) { 145 std::string msg = "Repeated instance of virtual table, original found at: "; 146 msg += existing->location.filename; 147 msg += ":" + toString( existing->location.first_line ); 148 SemanticError( objectDecl->location, msg ); 149 } 150 } 151 } 152 153 namespace { 154 155 /// Better error locations for generated casts. 156 CodeLocation castLocation( const VirtualCastExpr * castExpr ) { 157 if ( castExpr->location.isSet() ) { 158 return castExpr->location; 159 } else if ( castExpr->arg->location.isSet() ) { 160 return castExpr->arg->location; 161 } else if ( castExpr->result->location.isSet() ) { 162 return castExpr->result->location; 163 } else { 164 return CodeLocation(); 165 } 166 } 167 168 [[noreturn]] void castError( const VirtualCastExpr * castExpr, std::string const & message ) { 169 SemanticError( castLocation( castExpr ), message ); 170 } 171 172 /// Get the virtual table type used in a virtual cast. 173 Type * getVirtualTableType( const VirtualCastExpr * castExpr ) { 174 const Type * objectType; 175 if ( auto target = dynamic_cast<const PointerType *>( castExpr->result ) ) { 176 objectType = target->base; 177 } else if ( auto target = dynamic_cast<const ReferenceType *>( castExpr->result ) ) { 178 objectType = target->base; 179 } else { 180 castError( castExpr, "Virtual cast type must be a pointer or reference type." ); 181 } 182 assert( objectType ); 183 184 const StructInstType * structType = dynamic_cast<const StructInstType *>( objectType ); 185 if ( nullptr == structType ) { 186 castError( castExpr, "Virtual cast type must refer to a structure type." ); 187 } 188 const StructDecl * structDecl = structType->baseStruct; 189 assert( structDecl ); 190 191 const ObjectDecl * fieldDecl = nullptr; 192 if ( 0 < structDecl->members.size() ) { 193 const Declaration * memberDecl = structDecl->members.front(); 194 assert( memberDecl ); 195 fieldDecl = dynamic_cast<const ObjectDecl *>( memberDecl ); 196 if ( fieldDecl && fieldDecl->name != "virtual_table" ) { 197 fieldDecl = nullptr; 198 } 199 } 200 if ( nullptr == fieldDecl ) { 201 castError( castExpr, "Virtual cast type must have a leading virtual_table field." ); 202 } 203 const PointerType * fieldType = dynamic_cast<const PointerType *>( fieldDecl->type ); 204 if ( nullptr == fieldType ) { 205 castError( castExpr, "Virtual cast type virtual_table field is not a pointer." ); 206 } 207 assert( fieldType->base ); 208 auto virtualStructType = dynamic_cast<const StructInstType *>( fieldType->base ); 209 assert( virtualStructType ); 210 211 // Here is the type, but if it is polymorphic it will have lost information. 212 // (Always a clone so that it may always be deleted.) 213 StructInstType * virtualType = virtualStructType->clone(); 214 if ( ! structType->parameters.empty() ) { 215 deleteAll( virtualType->parameters ); 216 virtualType->parameters.clear(); 217 cloneAll( structType->parameters, virtualType->parameters ); 218 } 219 return virtualType; 220 } 221 222 } // namespace 112 223 113 224 Expression * VirtualCastCore::postmutate( VirtualCastExpr * castExpr ) { 114 assertf( castExpr-> get_result(), "Virtual Cast target not found before expansion." );225 assertf( castExpr->result, "Virtual Cast target not found before expansion." ); 115 226 116 227 assert( vcast_decl ); 117 228 assert( pvt_decl ); 118 229 119 // May only cast to a pointer or reference type. 120 // A earlier validation should give a syntax error, this is 121 // just to make sure errors don't creep during translation. 122 // Move to helper with more detailed error messages. 123 PointerType * target_type = 124 dynamic_cast<PointerType *>( castExpr->get_result() ); 125 assert( target_type ); 126 127 StructInstType * target_struct = 128 dynamic_cast<StructInstType *>( target_type->get_base() ); 129 assert( target_struct ); 130 131 StructDecl * target_decl = target_struct->get_baseStruct(); 132 133 std::map<std::string, ObjectDecl *>::iterator found = 134 vtable_instances.find( 135 get_vtable_inst_name( target_decl->get_name() ) ); 136 if ( vtable_instances.end() == found ) { 137 assertf( false, "virtual table instance not found." ); 138 } 139 ObjectDecl * table = found->second; 230 const Type * vtable_type = getVirtualTableType( castExpr ); 231 ObjectDecl * table = indexer.lookup( vtable_type ); 232 if ( nullptr == table ) { 233 SemanticError( castLocation( castExpr ), 234 "Could not find virtual table instance." ); 235 } 140 236 141 237 Expression * result = new CastExpr( 142 //new ApplicationExpr(143 //new AddressExpr( new VariableExpr( vcast_decl ) ),144 //new CastExpr( new VariableExpr( vcast_decl ),145 // new PointerType( noQualifiers,146 // vcast_decl->get_type()->clone()147 // )148 // ),149 238 new ApplicationExpr( VariableExpr::functionPointer( vcast_decl ), { 150 239 new CastExpr( … … 163 252 castExpr->set_result( nullptr ); 164 253 delete castExpr; 254 delete vtable_type; 165 255 return result; 166 256 } -
src/main.cc
r07d867b r22f94a4 9 9 // Author : Peter Buhr and Rob Schluntz 10 10 // Created On : Fri May 15 23:12:02 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sat Feb 8 08:33:50 202013 // Update Count : 63 311 // Last Modified By : Andrew Beach 12 // Last Modified On : Tue May 19 12:03:00 2020 13 // Update Count : 634 14 14 // 15 15 … … 312 312 } // if 313 313 314 PASS( "Translate Throws", ControlStruct::translateThrows( translationUnit ) ); 314 315 PASS( "Fix Labels", ControlStruct::fixLabels( translationUnit ) ); 315 316 PASS( "Fix Names", CodeGen::fixNames( translationUnit ) ); … … 360 361 PASS( "Expand Unique Expr", Tuples::expandUniqueExpr( translationUnit ) ); // xxx - is this the right place for this? want to expand ASAP so tha, sequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused 361 362 362 PASS( "Translate EHM" , ControlStruct::translateEHM( translationUnit ) );363 PASS( "Translate Tries" , ControlStruct::translateTries( translationUnit ) ); 363 364 364 365 PASS( "Gen Waitfor" , Concurrency::generateWaitFor( translationUnit ) ); -
tests/.expect/alloc.txt
r07d867b r22f94a4 30 30 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 31 31 CFA realloc array alloc, fill 32 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0x 1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x10101010xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede32 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 33 33 CFA realloc array alloc, fill 34 34 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 35 35 CFA realloc array alloc, fill 36 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0x 1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x10101010xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede36 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 37 37 38 38 C memalign 42 42.5 -
tests/.expect/bitmanip3.x64.txt
r07d867b r22f94a4 404 404 405 405 signed char 406 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(-2, 0) = 0407 406 floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(-3, 1) = -3 408 407 floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(-4, 2) = -4 … … 415 414 416 415 unsigned char 417 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(254, 0) = 0418 416 floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(253, 1) = 253 419 417 floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(252, 2) = 252 … … 426 424 427 425 short int 428 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(-2, 0) = 0429 426 floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(-3, 1) = -3 430 427 floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(-4, 2) = -4 … … 445 442 446 443 unsigned short int 447 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(65534, 0) = 0448 444 floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(65533, 1) = 65533 449 445 floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(65532, 2) = 65532 … … 464 460 465 461 int 466 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(-2, 0) = 0467 462 floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(-3, 1) = -3 468 463 floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(-4, 2) = -4 … … 499 494 500 495 unsigned int 501 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(4294967294, 0) = 0502 496 floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(4294967293, 1) = 4294967293 503 497 floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(4294967292, 2) = 4294967292 … … 534 528 535 529 long int 536 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(-2, 0) = 0537 530 floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(-3, 1) = -3 538 531 floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(-4, 2) = -4 … … 601 594 602 595 unsigned long int 603 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(18446744073709551614, 0) = 0604 596 floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(18446744073709551613, 1) = 18446744073709551613 605 597 floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(18446744073709551612, 2) = 18446744073709551612 … … 668 660 669 661 long long int 670 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(-2, 0) = 0671 662 floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(-3, 1) = -3 672 663 floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(-4, 2) = -4 … … 735 726 736 727 unsigned long long int 737 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(18446744073709551614, 0) = 0738 728 floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(18446744073709551613, 1) = 18446744073709551613 739 729 floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(18446744073709551612, 2) = 18446744073709551612 … … 1196 1186 1197 1187 signed char 1198 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(-2, 0) = 01199 1188 ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(-3, 1) = -3 1200 1189 ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(-4, 2) = -4 … … 1207 1196 1208 1197 unsigned char 1209 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(254, 0) = 01210 1198 ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(253, 1) = 253 1211 1199 ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(252, 2) = 252 … … 1218 1206 1219 1207 short int 1220 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(-2, 0) = 01221 1208 ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(-3, 1) = -3 1222 1209 ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(-4, 2) = -4 … … 1237 1224 1238 1225 unsigned short int 1239 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(65534, 0) = 01240 1226 ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(65533, 1) = 65533 1241 1227 ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(65532, 2) = 65532 … … 1256 1242 1257 1243 int 1258 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(-2, 0) = 01259 1244 ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(-3, 1) = -3 1260 1245 ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(-4, 2) = -4 … … 1291 1276 1292 1277 unsigned int 1293 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(4294967294, 0) = 01294 1278 ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(4294967293, 1) = 4294967293 1295 1279 ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(4294967292, 2) = 4294967292 … … 1326 1310 1327 1311 long int 1328 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(-2, 0) = 01329 1312 ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(-3, 1) = -3 1330 1313 ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(-4, 2) = -4 … … 1393 1376 1394 1377 unsigned long int 1395 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(18446744073709551614, 0) = 01396 1378 ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(18446744073709551613, 1) = 18446744073709551613 1397 1379 ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(18446744073709551612, 2) = 18446744073709551612 … … 1460 1442 1461 1443 long long int 1462 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(-2, 0) = 01463 1444 ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(-3, 1) = -3 1464 1445 ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(-4, 2) = -4 … … 1527 1508 1528 1509 unsigned long long int 1529 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(18446744073709551614, 0) = 01530 1510 ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(18446744073709551613, 1) = 18446744073709551613 1531 1511 ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(18446744073709551612, 2) = 18446744073709551612 … … 1594 1574 1595 1575 1576 ceiling_div 1577 1578 signed char 1579 ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(-3, 1) = -3 1580 ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(-4, 2) = -1 1581 ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(-6, 4) = 0 1582 ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(-10, 8) = 0 1583 ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(-18, 16) = 0 1584 ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(-34, 32) = 0 1585 ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(-66, 64) = 0 1586 ceiling_div(-128, -128) = 2, ceiling_div(-126, -128) = 1, ceiling_div(126, -128) = 0 1587 1588 unsigned char 1589 ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(253, 1) = 253 1590 ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(252, 2) = 126 1591 ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(250, 4) = 63 1592 ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(246, 8) = 31 1593 ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(238, 16) = 15 1594 ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(222, 32) = 7 1595 ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(190, 64) = 3 1596 ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(126, 128) = 1 1597 1598 short int 1599 ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(-3, 1) = -3 1600 ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(-4, 2) = -1 1601 ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(-6, 4) = 0 1602 ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(-10, 8) = 0 1603 ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(-18, 16) = 0 1604 ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(-34, 32) = 0 1605 ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(-66, 64) = 0 1606 ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(-130, 128) = 0 1607 ceiling_div(256, 256) = 1, ceiling_div(258, 256) = 2, ceiling_div(-258, 256) = 0 1608 ceiling_div(512, 512) = 1, ceiling_div(514, 512) = 2, ceiling_div(-514, 512) = 0 1609 ceiling_div(1024, 1024) = 1, ceiling_div(1026, 1024) = 2, ceiling_div(-1026, 1024) = 0 1610 ceiling_div(2048, 2048) = 1, ceiling_div(2050, 2048) = 2, ceiling_div(-2050, 2048) = 0 1611 ceiling_div(4096, 4096) = 1, ceiling_div(4098, 4096) = 2, ceiling_div(-4098, 4096) = 0 1612 ceiling_div(8192, 8192) = 1, ceiling_div(8194, 8192) = 2, ceiling_div(-8194, 8192) = 0 1613 ceiling_div(16384, 16384) = 1, ceiling_div(16386, 16384) = 2, ceiling_div(-16386, 16384) = 0 1614 ceiling_div(-32768, -32768) = 2, ceiling_div(-32766, -32768) = 1, ceiling_div(32766, -32768) = 0 1615 1616 unsigned short int 1617 ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(65533, 1) = 65533 1618 ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(65532, 2) = 32766 1619 ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(65530, 4) = 16383 1620 ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(65526, 8) = 8191 1621 ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(65518, 16) = 4095 1622 ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(65502, 32) = 2047 1623 ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(65470, 64) = 1023 1624 ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(65406, 128) = 511 1625 ceiling_div(256, 256) = 1, ceiling_div(258, 256) = 2, ceiling_div(65278, 256) = 255 1626 ceiling_div(512, 512) = 1, ceiling_div(514, 512) = 2, ceiling_div(65022, 512) = 127 1627 ceiling_div(1024, 1024) = 1, ceiling_div(1026, 1024) = 2, ceiling_div(64510, 1024) = 63 1628 ceiling_div(2048, 2048) = 1, ceiling_div(2050, 2048) = 2, ceiling_div(63486, 2048) = 31 1629 ceiling_div(4096, 4096) = 1, ceiling_div(4098, 4096) = 2, ceiling_div(61438, 4096) = 15 1630 ceiling_div(8192, 8192) = 1, ceiling_div(8194, 8192) = 2, ceiling_div(57342, 8192) = 7 1631 ceiling_div(16384, 16384) = 1, ceiling_div(16386, 16384) = 2, ceiling_div(49150, 16384) = 3 1632 ceiling_div(32768, 32768) = 1, ceiling_div(32770, 32768) = 2, ceiling_div(32766, 32768) = 1 1633 1634 int 1635 ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(-3, 1) = -3 1636 ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(-4, 2) = -1 1637 ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(-6, 4) = 0 1638 ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(-10, 8) = 0 1639 ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(-18, 16) = 0 1640 ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(-34, 32) = 0 1641 ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(-66, 64) = 0 1642 ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(-130, 128) = 0 1643 ceiling_div(256, 256) = 1, ceiling_div(258, 256) = 2, ceiling_div(-258, 256) = 0 1644 ceiling_div(512, 512) = 1, ceiling_div(514, 512) = 2, ceiling_div(-514, 512) = 0 1645 ceiling_div(1024, 1024) = 1, ceiling_div(1026, 1024) = 2, ceiling_div(-1026, 1024) = 0 1646 ceiling_div(2048, 2048) = 1, ceiling_div(2050, 2048) = 2, ceiling_div(-2050, 2048) = 0 1647 ceiling_div(4096, 4096) = 1, ceiling_div(4098, 4096) = 2, ceiling_div(-4098, 4096) = 0 1648 ceiling_div(8192, 8192) = 1, ceiling_div(8194, 8192) = 2, ceiling_div(-8194, 8192) = 0 1649 ceiling_div(16384, 16384) = 1, ceiling_div(16386, 16384) = 2, ceiling_div(-16386, 16384) = 0 1650 ceiling_div(32768, 32768) = 1, ceiling_div(32770, 32768) = 2, ceiling_div(-32770, 32768) = 0 1651 ceiling_div(65536, 65536) = 1, ceiling_div(65538, 65536) = 2, ceiling_div(-65538, 65536) = 0 1652 ceiling_div(131072, 131072) = 1, ceiling_div(131074, 131072) = 2, ceiling_div(-131074, 131072) = 0 1653 ceiling_div(262144, 262144) = 1, ceiling_div(262146, 262144) = 2, ceiling_div(-262146, 262144) = 0 1654 ceiling_div(524288, 524288) = 1, ceiling_div(524290, 524288) = 2, ceiling_div(-524290, 524288) = 0 1655 ceiling_div(1048576, 1048576) = 1, ceiling_div(1048578, 1048576) = 2, ceiling_div(-1048578, 1048576) = 0 1656 ceiling_div(2097152, 2097152) = 1, ceiling_div(2097154, 2097152) = 2, ceiling_div(-2097154, 2097152) = 0 1657 ceiling_div(4194304, 4194304) = 1, ceiling_div(4194306, 4194304) = 2, ceiling_div(-4194306, 4194304) = 0 1658 ceiling_div(8388608, 8388608) = 1, ceiling_div(8388610, 8388608) = 2, ceiling_div(-8388610, 8388608) = 0 1659 ceiling_div(16777216, 16777216) = 1, ceiling_div(16777218, 16777216) = 2, ceiling_div(-16777218, 16777216) = 0 1660 ceiling_div(33554432, 33554432) = 1, ceiling_div(33554434, 33554432) = 2, ceiling_div(-33554434, 33554432) = 0 1661 ceiling_div(67108864, 67108864) = 1, ceiling_div(67108866, 67108864) = 2, ceiling_div(-67108866, 67108864) = 0 1662 ceiling_div(134217728, 134217728) = 1, ceiling_div(134217730, 134217728) = 2, ceiling_div(-134217730, 134217728) = 0 1663 ceiling_div(268435456, 268435456) = 1, ceiling_div(268435458, 268435456) = 2, ceiling_div(-268435458, 268435456) = 0 1664 ceiling_div(536870912, 536870912) = 1, ceiling_div(536870914, 536870912) = 2, ceiling_div(-536870914, 536870912) = 0 1665 ceiling_div(1073741824, 1073741824) = 1, ceiling_div(1073741826, 1073741824) = -1, ceiling_div(-1073741826, 1073741824) = 0 1666 ceiling_div(-2147483648, -2147483648) = 0, ceiling_div(-2147483646, -2147483648) = 0, ceiling_div(2147483646, -2147483648) = 0 1667 1668 unsigned int 1669 ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(4294967293, 1) = 4294967293 1670 ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(4294967292, 2) = 2147483646 1671 ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(4294967290, 4) = 1073741823 1672 ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(4294967286, 8) = 536870911 1673 ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(4294967278, 16) = 268435455 1674 ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(4294967262, 32) = 134217727 1675 ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(4294967230, 64) = 67108863 1676 ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(4294967166, 128) = 33554431 1677 ceiling_div(256, 256) = 1, ceiling_div(258, 256) = 2, ceiling_div(4294967038, 256) = 16777215 1678 ceiling_div(512, 512) = 1, ceiling_div(514, 512) = 2, ceiling_div(4294966782, 512) = 8388607 1679 ceiling_div(1024, 1024) = 1, ceiling_div(1026, 1024) = 2, ceiling_div(4294966270, 1024) = 4194303 1680 ceiling_div(2048, 2048) = 1, ceiling_div(2050, 2048) = 2, ceiling_div(4294965246, 2048) = 2097151 1681 ceiling_div(4096, 4096) = 1, ceiling_div(4098, 4096) = 2, ceiling_div(4294963198, 4096) = 1048575 1682 ceiling_div(8192, 8192) = 1, ceiling_div(8194, 8192) = 2, ceiling_div(4294959102, 8192) = 524287 1683 ceiling_div(16384, 16384) = 1, ceiling_div(16386, 16384) = 2, ceiling_div(4294950910, 16384) = 262143 1684 ceiling_div(32768, 32768) = 1, ceiling_div(32770, 32768) = 2, ceiling_div(4294934526, 32768) = 131071 1685 ceiling_div(65536, 65536) = 1, ceiling_div(65538, 65536) = 2, ceiling_div(4294901758, 65536) = 65535 1686 ceiling_div(131072, 131072) = 1, ceiling_div(131074, 131072) = 2, ceiling_div(4294836222, 131072) = 32767 1687 ceiling_div(262144, 262144) = 1, ceiling_div(262146, 262144) = 2, ceiling_div(4294705150, 262144) = 16383 1688 ceiling_div(524288, 524288) = 1, ceiling_div(524290, 524288) = 2, ceiling_div(4294443006, 524288) = 8191 1689 ceiling_div(1048576, 1048576) = 1, ceiling_div(1048578, 1048576) = 2, ceiling_div(4293918718, 1048576) = 4095 1690 ceiling_div(2097152, 2097152) = 1, ceiling_div(2097154, 2097152) = 2, ceiling_div(4292870142, 2097152) = 2047 1691 ceiling_div(4194304, 4194304) = 1, ceiling_div(4194306, 4194304) = 2, ceiling_div(4290772990, 4194304) = 1023 1692 ceiling_div(8388608, 8388608) = 1, ceiling_div(8388610, 8388608) = 2, ceiling_div(4286578686, 8388608) = 511 1693 ceiling_div(16777216, 16777216) = 1, ceiling_div(16777218, 16777216) = 2, ceiling_div(4278190078, 16777216) = 255 1694 ceiling_div(33554432, 33554432) = 1, ceiling_div(33554434, 33554432) = 2, ceiling_div(4261412862, 33554432) = 127 1695 ceiling_div(67108864, 67108864) = 1, ceiling_div(67108866, 67108864) = 2, ceiling_div(4227858430, 67108864) = 63 1696 ceiling_div(134217728, 134217728) = 1, ceiling_div(134217730, 134217728) = 2, ceiling_div(4160749566, 134217728) = 31 1697 ceiling_div(268435456, 268435456) = 1, ceiling_div(268435458, 268435456) = 2, ceiling_div(4026531838, 268435456) = 15 1698 ceiling_div(536870912, 536870912) = 1, ceiling_div(536870914, 536870912) = 2, ceiling_div(3758096382, 536870912) = 7 1699 ceiling_div(1073741824, 1073741824) = 1, ceiling_div(1073741826, 1073741824) = 2, ceiling_div(3221225470, 1073741824) = 3 1700 ceiling_div(2147483648, 2147483648) = 1, ceiling_div(2147483650, 2147483648) = 0, ceiling_div(2147483646, 2147483648) = 1 1701 1702 long int 1703 ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(-3, 1) = -3 1704 ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(-4, 2) = -1 1705 ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(-6, 4) = 0 1706 ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(-10, 8) = 0 1707 ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(-18, 16) = 0 1708 ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(-34, 32) = 0 1709 ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(-66, 64) = 0 1710 ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(-130, 128) = 0 1711 ceiling_div(256, 256) = 1, ceiling_div(258, 256) = 2, ceiling_div(-258, 256) = 0 1712 ceiling_div(512, 512) = 1, ceiling_div(514, 512) = 2, ceiling_div(-514, 512) = 0 1713 ceiling_div(1024, 1024) = 1, ceiling_div(1026, 1024) = 2, ceiling_div(-1026, 1024) = 0 1714 ceiling_div(2048, 2048) = 1, ceiling_div(2050, 2048) = 2, ceiling_div(-2050, 2048) = 0 1715 ceiling_div(4096, 4096) = 1, ceiling_div(4098, 4096) = 2, ceiling_div(-4098, 4096) = 0 1716 ceiling_div(8192, 8192) = 1, ceiling_div(8194, 8192) = 2, ceiling_div(-8194, 8192) = 0 1717 ceiling_div(16384, 16384) = 1, ceiling_div(16386, 16384) = 2, ceiling_div(-16386, 16384) = 0 1718 ceiling_div(32768, 32768) = 1, ceiling_div(32770, 32768) = 2, ceiling_div(-32770, 32768) = 0 1719 ceiling_div(65536, 65536) = 1, ceiling_div(65538, 65536) = 2, ceiling_div(-65538, 65536) = 0 1720 ceiling_div(131072, 131072) = 1, ceiling_div(131074, 131072) = 2, ceiling_div(-131074, 131072) = 0 1721 ceiling_div(262144, 262144) = 1, ceiling_div(262146, 262144) = 2, ceiling_div(-262146, 262144) = 0 1722 ceiling_div(524288, 524288) = 1, ceiling_div(524290, 524288) = 2, ceiling_div(-524290, 524288) = 0 1723 ceiling_div(1048576, 1048576) = 1, ceiling_div(1048578, 1048576) = 2, ceiling_div(-1048578, 1048576) = 0 1724 ceiling_div(2097152, 2097152) = 1, ceiling_div(2097154, 2097152) = 2, ceiling_div(-2097154, 2097152) = 0 1725 ceiling_div(4194304, 4194304) = 1, ceiling_div(4194306, 4194304) = 2, ceiling_div(-4194306, 4194304) = 0 1726 ceiling_div(8388608, 8388608) = 1, ceiling_div(8388610, 8388608) = 2, ceiling_div(-8388610, 8388608) = 0 1727 ceiling_div(16777216, 16777216) = 1, ceiling_div(16777218, 16777216) = 2, ceiling_div(-16777218, 16777216) = 0 1728 ceiling_div(33554432, 33554432) = 1, ceiling_div(33554434, 33554432) = 2, ceiling_div(-33554434, 33554432) = 0 1729 ceiling_div(67108864, 67108864) = 1, ceiling_div(67108866, 67108864) = 2, ceiling_div(-67108866, 67108864) = 0 1730 ceiling_div(134217728, 134217728) = 1, ceiling_div(134217730, 134217728) = 2, ceiling_div(-134217730, 134217728) = 0 1731 ceiling_div(268435456, 268435456) = 1, ceiling_div(268435458, 268435456) = 2, ceiling_div(-268435458, 268435456) = 0 1732 ceiling_div(536870912, 536870912) = 1, ceiling_div(536870914, 536870912) = 2, ceiling_div(-536870914, 536870912) = 0 1733 ceiling_div(1073741824, 1073741824) = 1, ceiling_div(1073741826, 1073741824) = 2, ceiling_div(-1073741826, 1073741824) = 0 1734 ceiling_div(2147483648, 2147483648) = 1, ceiling_div(2147483650, 2147483648) = 2, ceiling_div(-2147483650, 2147483648) = 0 1735 ceiling_div(4294967296, 4294967296) = 1, ceiling_div(4294967298, 4294967296) = 2, ceiling_div(-4294967298, 4294967296) = 0 1736 ceiling_div(8589934592, 8589934592) = 1, ceiling_div(8589934594, 8589934592) = 2, ceiling_div(-8589934594, 8589934592) = 0 1737 ceiling_div(17179869184, 17179869184) = 1, ceiling_div(17179869186, 17179869184) = 2, ceiling_div(-17179869186, 17179869184) = 0 1738 ceiling_div(34359738368, 34359738368) = 1, ceiling_div(34359738370, 34359738368) = 2, ceiling_div(-34359738370, 34359738368) = 0 1739 ceiling_div(68719476736, 68719476736) = 1, ceiling_div(68719476738, 68719476736) = 2, ceiling_div(-68719476738, 68719476736) = 0 1740 ceiling_div(137438953472, 137438953472) = 1, ceiling_div(137438953474, 137438953472) = 2, ceiling_div(-137438953474, 137438953472) = 0 1741 ceiling_div(274877906944, 274877906944) = 1, ceiling_div(274877906946, 274877906944) = 2, ceiling_div(-274877906946, 274877906944) = 0 1742 ceiling_div(549755813888, 549755813888) = 1, ceiling_div(549755813890, 549755813888) = 2, ceiling_div(-549755813890, 549755813888) = 0 1743 ceiling_div(1099511627776, 1099511627776) = 1, ceiling_div(1099511627778, 1099511627776) = 2, ceiling_div(-1099511627778, 1099511627776) = 0 1744 ceiling_div(2199023255552, 2199023255552) = 1, ceiling_div(2199023255554, 2199023255552) = 2, ceiling_div(-2199023255554, 2199023255552) = 0 1745 ceiling_div(4398046511104, 4398046511104) = 1, ceiling_div(4398046511106, 4398046511104) = 2, ceiling_div(-4398046511106, 4398046511104) = 0 1746 ceiling_div(8796093022208, 8796093022208) = 1, ceiling_div(8796093022210, 8796093022208) = 2, ceiling_div(-8796093022210, 8796093022208) = 0 1747 ceiling_div(17592186044416, 17592186044416) = 1, ceiling_div(17592186044418, 17592186044416) = 2, ceiling_div(-17592186044418, 17592186044416) = 0 1748 ceiling_div(35184372088832, 35184372088832) = 1, ceiling_div(35184372088834, 35184372088832) = 2, ceiling_div(-35184372088834, 35184372088832) = 0 1749 ceiling_div(70368744177664, 70368744177664) = 1, ceiling_div(70368744177666, 70368744177664) = 2, ceiling_div(-70368744177666, 70368744177664) = 0 1750 ceiling_div(140737488355328, 140737488355328) = 1, ceiling_div(140737488355330, 140737488355328) = 2, ceiling_div(-140737488355330, 140737488355328) = 0 1751 ceiling_div(281474976710656, 281474976710656) = 1, ceiling_div(281474976710658, 281474976710656) = 2, ceiling_div(-281474976710658, 281474976710656) = 0 1752 ceiling_div(562949953421312, 562949953421312) = 1, ceiling_div(562949953421314, 562949953421312) = 2, ceiling_div(-562949953421314, 562949953421312) = 0 1753 ceiling_div(1125899906842624, 1125899906842624) = 1, ceiling_div(1125899906842626, 1125899906842624) = 2, ceiling_div(-1125899906842626, 1125899906842624) = 0 1754 ceiling_div(2251799813685248, 2251799813685248) = 1, ceiling_div(2251799813685250, 2251799813685248) = 2, ceiling_div(-2251799813685250, 2251799813685248) = 0 1755 ceiling_div(4503599627370496, 4503599627370496) = 1, ceiling_div(4503599627370498, 4503599627370496) = 2, ceiling_div(-4503599627370498, 4503599627370496) = 0 1756 ceiling_div(9007199254740992, 9007199254740992) = 1, ceiling_div(9007199254740994, 9007199254740992) = 2, ceiling_div(-9007199254740994, 9007199254740992) = 0 1757 ceiling_div(18014398509481984, 18014398509481984) = 1, ceiling_div(18014398509481986, 18014398509481984) = 2, ceiling_div(-18014398509481986, 18014398509481984) = 0 1758 ceiling_div(36028797018963968, 36028797018963968) = 1, ceiling_div(36028797018963970, 36028797018963968) = 2, ceiling_div(-36028797018963970, 36028797018963968) = 0 1759 ceiling_div(72057594037927936, 72057594037927936) = 1, ceiling_div(72057594037927938, 72057594037927936) = 2, ceiling_div(-72057594037927938, 72057594037927936) = 0 1760 ceiling_div(144115188075855872, 144115188075855872) = 1, ceiling_div(144115188075855874, 144115188075855872) = 2, ceiling_div(-144115188075855874, 144115188075855872) = 0 1761 ceiling_div(288230376151711744, 288230376151711744) = 1, ceiling_div(288230376151711746, 288230376151711744) = 2, ceiling_div(-288230376151711746, 288230376151711744) = 0 1762 ceiling_div(576460752303423488, 576460752303423488) = 1, ceiling_div(576460752303423490, 576460752303423488) = 2, ceiling_div(-576460752303423490, 576460752303423488) = 0 1763 ceiling_div(1152921504606846976, 1152921504606846976) = 1, ceiling_div(1152921504606846978, 1152921504606846976) = 2, ceiling_div(-1152921504606846978, 1152921504606846976) = 0 1764 ceiling_div(2305843009213693952, 2305843009213693952) = 1, ceiling_div(2305843009213693954, 2305843009213693952) = 2, ceiling_div(-2305843009213693954, 2305843009213693952) = 0 1765 ceiling_div(4611686018427387904, 4611686018427387904) = 1, ceiling_div(4611686018427387906, 4611686018427387904) = -1, ceiling_div(-4611686018427387906, 4611686018427387904) = 0 1766 ceiling_div(-9223372036854775808, -9223372036854775808) = 0, ceiling_div(-9223372036854775806, -9223372036854775808) = 0, ceiling_div(9223372036854775806, -9223372036854775808) = 0 1767 1768 unsigned long int 1769 ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(18446744073709551613, 1) = 18446744073709551613 1770 ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(18446744073709551612, 2) = 9223372036854775806 1771 ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(18446744073709551610, 4) = 4611686018427387903 1772 ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(18446744073709551606, 8) = 2305843009213693951 1773 ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(18446744073709551598, 16) = 1152921504606846975 1774 ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(18446744073709551582, 32) = 576460752303423487 1775 ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(18446744073709551550, 64) = 288230376151711743 1776 ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(18446744073709551486, 128) = 144115188075855871 1777 ceiling_div(256, 256) = 1, ceiling_div(258, 256) = 2, ceiling_div(18446744073709551358, 256) = 72057594037927935 1778 ceiling_div(512, 512) = 1, ceiling_div(514, 512) = 2, ceiling_div(18446744073709551102, 512) = 36028797018963967 1779 ceiling_div(1024, 1024) = 1, ceiling_div(1026, 1024) = 2, ceiling_div(18446744073709550590, 1024) = 18014398509481983 1780 ceiling_div(2048, 2048) = 1, ceiling_div(2050, 2048) = 2, ceiling_div(18446744073709549566, 2048) = 9007199254740991 1781 ceiling_div(4096, 4096) = 1, ceiling_div(4098, 4096) = 2, ceiling_div(18446744073709547518, 4096) = 4503599627370495 1782 ceiling_div(8192, 8192) = 1, ceiling_div(8194, 8192) = 2, ceiling_div(18446744073709543422, 8192) = 2251799813685247 1783 ceiling_div(16384, 16384) = 1, ceiling_div(16386, 16384) = 2, ceiling_div(18446744073709535230, 16384) = 1125899906842623 1784 ceiling_div(32768, 32768) = 1, ceiling_div(32770, 32768) = 2, ceiling_div(18446744073709518846, 32768) = 562949953421311 1785 ceiling_div(65536, 65536) = 1, ceiling_div(65538, 65536) = 2, ceiling_div(18446744073709486078, 65536) = 281474976710655 1786 ceiling_div(131072, 131072) = 1, ceiling_div(131074, 131072) = 2, ceiling_div(18446744073709420542, 131072) = 140737488355327 1787 ceiling_div(262144, 262144) = 1, ceiling_div(262146, 262144) = 2, ceiling_div(18446744073709289470, 262144) = 70368744177663 1788 ceiling_div(524288, 524288) = 1, ceiling_div(524290, 524288) = 2, ceiling_div(18446744073709027326, 524288) = 35184372088831 1789 ceiling_div(1048576, 1048576) = 1, ceiling_div(1048578, 1048576) = 2, ceiling_div(18446744073708503038, 1048576) = 17592186044415 1790 ceiling_div(2097152, 2097152) = 1, ceiling_div(2097154, 2097152) = 2, ceiling_div(18446744073707454462, 2097152) = 8796093022207 1791 ceiling_div(4194304, 4194304) = 1, ceiling_div(4194306, 4194304) = 2, ceiling_div(18446744073705357310, 4194304) = 4398046511103 1792 ceiling_div(8388608, 8388608) = 1, ceiling_div(8388610, 8388608) = 2, ceiling_div(18446744073701163006, 8388608) = 2199023255551 1793 ceiling_div(16777216, 16777216) = 1, ceiling_div(16777218, 16777216) = 2, ceiling_div(18446744073692774398, 16777216) = 1099511627775 1794 ceiling_div(33554432, 33554432) = 1, ceiling_div(33554434, 33554432) = 2, ceiling_div(18446744073675997182, 33554432) = 549755813887 1795 ceiling_div(67108864, 67108864) = 1, ceiling_div(67108866, 67108864) = 2, ceiling_div(18446744073642442750, 67108864) = 274877906943 1796 ceiling_div(134217728, 134217728) = 1, ceiling_div(134217730, 134217728) = 2, ceiling_div(18446744073575333886, 134217728) = 137438953471 1797 ceiling_div(268435456, 268435456) = 1, ceiling_div(268435458, 268435456) = 2, ceiling_div(18446744073441116158, 268435456) = 68719476735 1798 ceiling_div(536870912, 536870912) = 1, ceiling_div(536870914, 536870912) = 2, ceiling_div(18446744073172680702, 536870912) = 34359738367 1799 ceiling_div(1073741824, 1073741824) = 1, ceiling_div(1073741826, 1073741824) = 2, ceiling_div(18446744072635809790, 1073741824) = 17179869183 1800 ceiling_div(2147483648, 2147483648) = 1, ceiling_div(2147483650, 2147483648) = 2, ceiling_div(18446744071562067966, 2147483648) = 8589934591 1801 ceiling_div(4294967296, 4294967296) = 1, ceiling_div(4294967298, 4294967296) = 2, ceiling_div(18446744069414584318, 4294967296) = 4294967295 1802 ceiling_div(8589934592, 8589934592) = 1, ceiling_div(8589934594, 8589934592) = 2, ceiling_div(18446744065119617022, 8589934592) = 2147483647 1803 ceiling_div(17179869184, 17179869184) = 1, ceiling_div(17179869186, 17179869184) = 2, ceiling_div(18446744056529682430, 17179869184) = 1073741823 1804 ceiling_div(34359738368, 34359738368) = 1, ceiling_div(34359738370, 34359738368) = 2, ceiling_div(18446744039349813246, 34359738368) = 536870911 1805 ceiling_div(68719476736, 68719476736) = 1, ceiling_div(68719476738, 68719476736) = 2, ceiling_div(18446744004990074878, 68719476736) = 268435455 1806 ceiling_div(137438953472, 137438953472) = 1, ceiling_div(137438953474, 137438953472) = 2, ceiling_div(18446743936270598142, 137438953472) = 134217727 1807 ceiling_div(274877906944, 274877906944) = 1, ceiling_div(274877906946, 274877906944) = 2, ceiling_div(18446743798831644670, 274877906944) = 67108863 1808 ceiling_div(549755813888, 549755813888) = 1, ceiling_div(549755813890, 549755813888) = 2, ceiling_div(18446743523953737726, 549755813888) = 33554431 1809 ceiling_div(1099511627776, 1099511627776) = 1, ceiling_div(1099511627778, 1099511627776) = 2, ceiling_div(18446742974197923838, 1099511627776) = 16777215 1810 ceiling_div(2199023255552, 2199023255552) = 1, ceiling_div(2199023255554, 2199023255552) = 2, ceiling_div(18446741874686296062, 2199023255552) = 8388607 1811 ceiling_div(4398046511104, 4398046511104) = 1, ceiling_div(4398046511106, 4398046511104) = 2, ceiling_div(18446739675663040510, 4398046511104) = 4194303 1812 ceiling_div(8796093022208, 8796093022208) = 1, ceiling_div(8796093022210, 8796093022208) = 2, ceiling_div(18446735277616529406, 8796093022208) = 2097151 1813 ceiling_div(17592186044416, 17592186044416) = 1, ceiling_div(17592186044418, 17592186044416) = 2, ceiling_div(18446726481523507198, 17592186044416) = 1048575 1814 ceiling_div(35184372088832, 35184372088832) = 1, ceiling_div(35184372088834, 35184372088832) = 2, ceiling_div(18446708889337462782, 35184372088832) = 524287 1815 ceiling_div(70368744177664, 70368744177664) = 1, ceiling_div(70368744177666, 70368744177664) = 2, ceiling_div(18446673704965373950, 70368744177664) = 262143 1816 ceiling_div(140737488355328, 140737488355328) = 1, ceiling_div(140737488355330, 140737488355328) = 2, ceiling_div(18446603336221196286, 140737488355328) = 131071 1817 ceiling_div(281474976710656, 281474976710656) = 1, ceiling_div(281474976710658, 281474976710656) = 2, ceiling_div(18446462598732840958, 281474976710656) = 65535 1818 ceiling_div(562949953421312, 562949953421312) = 1, ceiling_div(562949953421314, 562949953421312) = 2, ceiling_div(18446181123756130302, 562949953421312) = 32767 1819 ceiling_div(1125899906842624, 1125899906842624) = 1, ceiling_div(1125899906842626, 1125899906842624) = 2, ceiling_div(18445618173802708990, 1125899906842624) = 16383 1820 ceiling_div(2251799813685248, 2251799813685248) = 1, ceiling_div(2251799813685250, 2251799813685248) = 2, ceiling_div(18444492273895866366, 2251799813685248) = 8191 1821 ceiling_div(4503599627370496, 4503599627370496) = 1, ceiling_div(4503599627370498, 4503599627370496) = 2, ceiling_div(18442240474082181118, 4503599627370496) = 4095 1822 ceiling_div(9007199254740992, 9007199254740992) = 1, ceiling_div(9007199254740994, 9007199254740992) = 2, ceiling_div(18437736874454810622, 9007199254740992) = 2047 1823 ceiling_div(18014398509481984, 18014398509481984) = 1, ceiling_div(18014398509481986, 18014398509481984) = 2, ceiling_div(18428729675200069630, 18014398509481984) = 1023 1824 ceiling_div(36028797018963968, 36028797018963968) = 1, ceiling_div(36028797018963970, 36028797018963968) = 2, ceiling_div(18410715276690587646, 36028797018963968) = 511 1825 ceiling_div(72057594037927936, 72057594037927936) = 1, ceiling_div(72057594037927938, 72057594037927936) = 2, ceiling_div(18374686479671623678, 72057594037927936) = 255 1826 ceiling_div(144115188075855872, 144115188075855872) = 1, ceiling_div(144115188075855874, 144115188075855872) = 2, ceiling_div(18302628885633695742, 144115188075855872) = 127 1827 ceiling_div(288230376151711744, 288230376151711744) = 1, ceiling_div(288230376151711746, 288230376151711744) = 2, ceiling_div(18158513697557839870, 288230376151711744) = 63 1828 ceiling_div(576460752303423488, 576460752303423488) = 1, ceiling_div(576460752303423490, 576460752303423488) = 2, ceiling_div(17870283321406128126, 576460752303423488) = 31 1829 ceiling_div(1152921504606846976, 1152921504606846976) = 1, ceiling_div(1152921504606846978, 1152921504606846976) = 2, ceiling_div(17293822569102704638, 1152921504606846976) = 15 1830 ceiling_div(2305843009213693952, 2305843009213693952) = 1, ceiling_div(2305843009213693954, 2305843009213693952) = 2, ceiling_div(16140901064495857662, 2305843009213693952) = 7 1831 ceiling_div(4611686018427387904, 4611686018427387904) = 1, ceiling_div(4611686018427387906, 4611686018427387904) = 2, ceiling_div(13835058055282163710, 4611686018427387904) = 3 1832 ceiling_div(9223372036854775808, 9223372036854775808) = 1, ceiling_div(9223372036854775810, 9223372036854775808) = 0, ceiling_div(9223372036854775806, 9223372036854775808) = 1 1833 1834 long long int 1835 ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(-3, 1) = -3 1836 ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(-4, 2) = -1 1837 ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(-6, 4) = 0 1838 ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(-10, 8) = 0 1839 ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(-18, 16) = 0 1840 ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(-34, 32) = 0 1841 ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(-66, 64) = 0 1842 ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(-130, 128) = 0 1843 ceiling_div(256, 256) = 1, ceiling_div(258, 256) = 2, ceiling_div(-258, 256) = 0 1844 ceiling_div(512, 512) = 1, ceiling_div(514, 512) = 2, ceiling_div(-514, 512) = 0 1845 ceiling_div(1024, 1024) = 1, ceiling_div(1026, 1024) = 2, ceiling_div(-1026, 1024) = 0 1846 ceiling_div(2048, 2048) = 1, ceiling_div(2050, 2048) = 2, ceiling_div(-2050, 2048) = 0 1847 ceiling_div(4096, 4096) = 1, ceiling_div(4098, 4096) = 2, ceiling_div(-4098, 4096) = 0 1848 ceiling_div(8192, 8192) = 1, ceiling_div(8194, 8192) = 2, ceiling_div(-8194, 8192) = 0 1849 ceiling_div(16384, 16384) = 1, ceiling_div(16386, 16384) = 2, ceiling_div(-16386, 16384) = 0 1850 ceiling_div(32768, 32768) = 1, ceiling_div(32770, 32768) = 2, ceiling_div(-32770, 32768) = 0 1851 ceiling_div(65536, 65536) = 1, ceiling_div(65538, 65536) = 2, ceiling_div(-65538, 65536) = 0 1852 ceiling_div(131072, 131072) = 1, ceiling_div(131074, 131072) = 2, ceiling_div(-131074, 131072) = 0 1853 ceiling_div(262144, 262144) = 1, ceiling_div(262146, 262144) = 2, ceiling_div(-262146, 262144) = 0 1854 ceiling_div(524288, 524288) = 1, ceiling_div(524290, 524288) = 2, ceiling_div(-524290, 524288) = 0 1855 ceiling_div(1048576, 1048576) = 1, ceiling_div(1048578, 1048576) = 2, ceiling_div(-1048578, 1048576) = 0 1856 ceiling_div(2097152, 2097152) = 1, ceiling_div(2097154, 2097152) = 2, ceiling_div(-2097154, 2097152) = 0 1857 ceiling_div(4194304, 4194304) = 1, ceiling_div(4194306, 4194304) = 2, ceiling_div(-4194306, 4194304) = 0 1858 ceiling_div(8388608, 8388608) = 1, ceiling_div(8388610, 8388608) = 2, ceiling_div(-8388610, 8388608) = 0 1859 ceiling_div(16777216, 16777216) = 1, ceiling_div(16777218, 16777216) = 2, ceiling_div(-16777218, 16777216) = 0 1860 ceiling_div(33554432, 33554432) = 1, ceiling_div(33554434, 33554432) = 2, ceiling_div(-33554434, 33554432) = 0 1861 ceiling_div(67108864, 67108864) = 1, ceiling_div(67108866, 67108864) = 2, ceiling_div(-67108866, 67108864) = 0 1862 ceiling_div(134217728, 134217728) = 1, ceiling_div(134217730, 134217728) = 2, ceiling_div(-134217730, 134217728) = 0 1863 ceiling_div(268435456, 268435456) = 1, ceiling_div(268435458, 268435456) = 2, ceiling_div(-268435458, 268435456) = 0 1864 ceiling_div(536870912, 536870912) = 1, ceiling_div(536870914, 536870912) = 2, ceiling_div(-536870914, 536870912) = 0 1865 ceiling_div(1073741824, 1073741824) = 1, ceiling_div(1073741826, 1073741824) = 2, ceiling_div(-1073741826, 1073741824) = 0 1866 ceiling_div(2147483648, 2147483648) = 1, ceiling_div(2147483650, 2147483648) = 2, ceiling_div(-2147483650, 2147483648) = 0 1867 ceiling_div(4294967296, 4294967296) = 1, ceiling_div(4294967298, 4294967296) = 2, ceiling_div(-4294967298, 4294967296) = 0 1868 ceiling_div(8589934592, 8589934592) = 1, ceiling_div(8589934594, 8589934592) = 2, ceiling_div(-8589934594, 8589934592) = 0 1869 ceiling_div(17179869184, 17179869184) = 1, ceiling_div(17179869186, 17179869184) = 2, ceiling_div(-17179869186, 17179869184) = 0 1870 ceiling_div(34359738368, 34359738368) = 1, ceiling_div(34359738370, 34359738368) = 2, ceiling_div(-34359738370, 34359738368) = 0 1871 ceiling_div(68719476736, 68719476736) = 1, ceiling_div(68719476738, 68719476736) = 2, ceiling_div(-68719476738, 68719476736) = 0 1872 ceiling_div(137438953472, 137438953472) = 1, ceiling_div(137438953474, 137438953472) = 2, ceiling_div(-137438953474, 137438953472) = 0 1873 ceiling_div(274877906944, 274877906944) = 1, ceiling_div(274877906946, 274877906944) = 2, ceiling_div(-274877906946, 274877906944) = 0 1874 ceiling_div(549755813888, 549755813888) = 1, ceiling_div(549755813890, 549755813888) = 2, ceiling_div(-549755813890, 549755813888) = 0 1875 ceiling_div(1099511627776, 1099511627776) = 1, ceiling_div(1099511627778, 1099511627776) = 2, ceiling_div(-1099511627778, 1099511627776) = 0 1876 ceiling_div(2199023255552, 2199023255552) = 1, ceiling_div(2199023255554, 2199023255552) = 2, ceiling_div(-2199023255554, 2199023255552) = 0 1877 ceiling_div(4398046511104, 4398046511104) = 1, ceiling_div(4398046511106, 4398046511104) = 2, ceiling_div(-4398046511106, 4398046511104) = 0 1878 ceiling_div(8796093022208, 8796093022208) = 1, ceiling_div(8796093022210, 8796093022208) = 2, ceiling_div(-8796093022210, 8796093022208) = 0 1879 ceiling_div(17592186044416, 17592186044416) = 1, ceiling_div(17592186044418, 17592186044416) = 2, ceiling_div(-17592186044418, 17592186044416) = 0 1880 ceiling_div(35184372088832, 35184372088832) = 1, ceiling_div(35184372088834, 35184372088832) = 2, ceiling_div(-35184372088834, 35184372088832) = 0 1881 ceiling_div(70368744177664, 70368744177664) = 1, ceiling_div(70368744177666, 70368744177664) = 2, ceiling_div(-70368744177666, 70368744177664) = 0 1882 ceiling_div(140737488355328, 140737488355328) = 1, ceiling_div(140737488355330, 140737488355328) = 2, ceiling_div(-140737488355330, 140737488355328) = 0 1883 ceiling_div(281474976710656, 281474976710656) = 1, ceiling_div(281474976710658, 281474976710656) = 2, ceiling_div(-281474976710658, 281474976710656) = 0 1884 ceiling_div(562949953421312, 562949953421312) = 1, ceiling_div(562949953421314, 562949953421312) = 2, ceiling_div(-562949953421314, 562949953421312) = 0 1885 ceiling_div(1125899906842624, 1125899906842624) = 1, ceiling_div(1125899906842626, 1125899906842624) = 2, ceiling_div(-1125899906842626, 1125899906842624) = 0 1886 ceiling_div(2251799813685248, 2251799813685248) = 1, ceiling_div(2251799813685250, 2251799813685248) = 2, ceiling_div(-2251799813685250, 2251799813685248) = 0 1887 ceiling_div(4503599627370496, 4503599627370496) = 1, ceiling_div(4503599627370498, 4503599627370496) = 2, ceiling_div(-4503599627370498, 4503599627370496) = 0 1888 ceiling_div(9007199254740992, 9007199254740992) = 1, ceiling_div(9007199254740994, 9007199254740992) = 2, ceiling_div(-9007199254740994, 9007199254740992) = 0 1889 ceiling_div(18014398509481984, 18014398509481984) = 1, ceiling_div(18014398509481986, 18014398509481984) = 2, ceiling_div(-18014398509481986, 18014398509481984) = 0 1890 ceiling_div(36028797018963968, 36028797018963968) = 1, ceiling_div(36028797018963970, 36028797018963968) = 2, ceiling_div(-36028797018963970, 36028797018963968) = 0 1891 ceiling_div(72057594037927936, 72057594037927936) = 1, ceiling_div(72057594037927938, 72057594037927936) = 2, ceiling_div(-72057594037927938, 72057594037927936) = 0 1892 ceiling_div(144115188075855872, 144115188075855872) = 1, ceiling_div(144115188075855874, 144115188075855872) = 2, ceiling_div(-144115188075855874, 144115188075855872) = 0 1893 ceiling_div(288230376151711744, 288230376151711744) = 1, ceiling_div(288230376151711746, 288230376151711744) = 2, ceiling_div(-288230376151711746, 288230376151711744) = 0 1894 ceiling_div(576460752303423488, 576460752303423488) = 1, ceiling_div(576460752303423490, 576460752303423488) = 2, ceiling_div(-576460752303423490, 576460752303423488) = 0 1895 ceiling_div(1152921504606846976, 1152921504606846976) = 1, ceiling_div(1152921504606846978, 1152921504606846976) = 2, ceiling_div(-1152921504606846978, 1152921504606846976) = 0 1896 ceiling_div(2305843009213693952, 2305843009213693952) = 1, ceiling_div(2305843009213693954, 2305843009213693952) = 2, ceiling_div(-2305843009213693954, 2305843009213693952) = 0 1897 ceiling_div(4611686018427387904, 4611686018427387904) = 1, ceiling_div(4611686018427387906, 4611686018427387904) = -1, ceiling_div(-4611686018427387906, 4611686018427387904) = 0 1898 ceiling_div(-9223372036854775808, -9223372036854775808) = 0, ceiling_div(-9223372036854775806, -9223372036854775808) = 0, ceiling_div(9223372036854775806, -9223372036854775808) = 0 1899 1900 unsigned long long int 1901 ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(18446744073709551613, 1) = 18446744073709551613 1902 ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(18446744073709551612, 2) = 9223372036854775806 1903 ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(18446744073709551610, 4) = 4611686018427387903 1904 ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(18446744073709551606, 8) = 2305843009213693951 1905 ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(18446744073709551598, 16) = 1152921504606846975 1906 ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(18446744073709551582, 32) = 576460752303423487 1907 ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(18446744073709551550, 64) = 288230376151711743 1908 ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(18446744073709551486, 128) = 144115188075855871 1909 ceiling_div(256, 256) = 1, ceiling_div(258, 256) = 2, ceiling_div(18446744073709551358, 256) = 72057594037927935 1910 ceiling_div(512, 512) = 1, ceiling_div(514, 512) = 2, ceiling_div(18446744073709551102, 512) = 36028797018963967 1911 ceiling_div(1024, 1024) = 1, ceiling_div(1026, 1024) = 2, ceiling_div(18446744073709550590, 1024) = 18014398509481983 1912 ceiling_div(2048, 2048) = 1, ceiling_div(2050, 2048) = 2, ceiling_div(18446744073709549566, 2048) = 9007199254740991 1913 ceiling_div(4096, 4096) = 1, ceiling_div(4098, 4096) = 2, ceiling_div(18446744073709547518, 4096) = 4503599627370495 1914 ceiling_div(8192, 8192) = 1, ceiling_div(8194, 8192) = 2, ceiling_div(18446744073709543422, 8192) = 2251799813685247 1915 ceiling_div(16384, 16384) = 1, ceiling_div(16386, 16384) = 2, ceiling_div(18446744073709535230, 16384) = 1125899906842623 1916 ceiling_div(32768, 32768) = 1, ceiling_div(32770, 32768) = 2, ceiling_div(18446744073709518846, 32768) = 562949953421311 1917 ceiling_div(65536, 65536) = 1, ceiling_div(65538, 65536) = 2, ceiling_div(18446744073709486078, 65536) = 281474976710655 1918 ceiling_div(131072, 131072) = 1, ceiling_div(131074, 131072) = 2, ceiling_div(18446744073709420542, 131072) = 140737488355327 1919 ceiling_div(262144, 262144) = 1, ceiling_div(262146, 262144) = 2, ceiling_div(18446744073709289470, 262144) = 70368744177663 1920 ceiling_div(524288, 524288) = 1, ceiling_div(524290, 524288) = 2, ceiling_div(18446744073709027326, 524288) = 35184372088831 1921 ceiling_div(1048576, 1048576) = 1, ceiling_div(1048578, 1048576) = 2, ceiling_div(18446744073708503038, 1048576) = 17592186044415 1922 ceiling_div(2097152, 2097152) = 1, ceiling_div(2097154, 2097152) = 2, ceiling_div(18446744073707454462, 2097152) = 8796093022207 1923 ceiling_div(4194304, 4194304) = 1, ceiling_div(4194306, 4194304) = 2, ceiling_div(18446744073705357310, 4194304) = 4398046511103 1924 ceiling_div(8388608, 8388608) = 1, ceiling_div(8388610, 8388608) = 2, ceiling_div(18446744073701163006, 8388608) = 2199023255551 1925 ceiling_div(16777216, 16777216) = 1, ceiling_div(16777218, 16777216) = 2, ceiling_div(18446744073692774398, 16777216) = 1099511627775 1926 ceiling_div(33554432, 33554432) = 1, ceiling_div(33554434, 33554432) = 2, ceiling_div(18446744073675997182, 33554432) = 549755813887 1927 ceiling_div(67108864, 67108864) = 1, ceiling_div(67108866, 67108864) = 2, ceiling_div(18446744073642442750, 67108864) = 274877906943 1928 ceiling_div(134217728, 134217728) = 1, ceiling_div(134217730, 134217728) = 2, ceiling_div(18446744073575333886, 134217728) = 137438953471 1929 ceiling_div(268435456, 268435456) = 1, ceiling_div(268435458, 268435456) = 2, ceiling_div(18446744073441116158, 268435456) = 68719476735 1930 ceiling_div(536870912, 536870912) = 1, ceiling_div(536870914, 536870912) = 2, ceiling_div(18446744073172680702, 536870912) = 34359738367 1931 ceiling_div(1073741824, 1073741824) = 1, ceiling_div(1073741826, 1073741824) = 2, ceiling_div(18446744072635809790, 1073741824) = 17179869183 1932 ceiling_div(2147483648, 2147483648) = 1, ceiling_div(2147483650, 2147483648) = 2, ceiling_div(18446744071562067966, 2147483648) = 8589934591 1933 ceiling_div(4294967296, 4294967296) = 1, ceiling_div(4294967298, 4294967296) = 2, ceiling_div(18446744069414584318, 4294967296) = 4294967295 1934 ceiling_div(8589934592, 8589934592) = 1, ceiling_div(8589934594, 8589934592) = 2, ceiling_div(18446744065119617022, 8589934592) = 2147483647 1935 ceiling_div(17179869184, 17179869184) = 1, ceiling_div(17179869186, 17179869184) = 2, ceiling_div(18446744056529682430, 17179869184) = 1073741823 1936 ceiling_div(34359738368, 34359738368) = 1, ceiling_div(34359738370, 34359738368) = 2, ceiling_div(18446744039349813246, 34359738368) = 536870911 1937 ceiling_div(68719476736, 68719476736) = 1, ceiling_div(68719476738, 68719476736) = 2, ceiling_div(18446744004990074878, 68719476736) = 268435455 1938 ceiling_div(137438953472, 137438953472) = 1, ceiling_div(137438953474, 137438953472) = 2, ceiling_div(18446743936270598142, 137438953472) = 134217727 1939 ceiling_div(274877906944, 274877906944) = 1, ceiling_div(274877906946, 274877906944) = 2, ceiling_div(18446743798831644670, 274877906944) = 67108863 1940 ceiling_div(549755813888, 549755813888) = 1, ceiling_div(549755813890, 549755813888) = 2, ceiling_div(18446743523953737726, 549755813888) = 33554431 1941 ceiling_div(1099511627776, 1099511627776) = 1, ceiling_div(1099511627778, 1099511627776) = 2, ceiling_div(18446742974197923838, 1099511627776) = 16777215 1942 ceiling_div(2199023255552, 2199023255552) = 1, ceiling_div(2199023255554, 2199023255552) = 2, ceiling_div(18446741874686296062, 2199023255552) = 8388607 1943 ceiling_div(4398046511104, 4398046511104) = 1, ceiling_div(4398046511106, 4398046511104) = 2, ceiling_div(18446739675663040510, 4398046511104) = 4194303 1944 ceiling_div(8796093022208, 8796093022208) = 1, ceiling_div(8796093022210, 8796093022208) = 2, ceiling_div(18446735277616529406, 8796093022208) = 2097151 1945 ceiling_div(17592186044416, 17592186044416) = 1, ceiling_div(17592186044418, 17592186044416) = 2, ceiling_div(18446726481523507198, 17592186044416) = 1048575 1946 ceiling_div(35184372088832, 35184372088832) = 1, ceiling_div(35184372088834, 35184372088832) = 2, ceiling_div(18446708889337462782, 35184372088832) = 524287 1947 ceiling_div(70368744177664, 70368744177664) = 1, ceiling_div(70368744177666, 70368744177664) = 2, ceiling_div(18446673704965373950, 70368744177664) = 262143 1948 ceiling_div(140737488355328, 140737488355328) = 1, ceiling_div(140737488355330, 140737488355328) = 2, ceiling_div(18446603336221196286, 140737488355328) = 131071 1949 ceiling_div(281474976710656, 281474976710656) = 1, ceiling_div(281474976710658, 281474976710656) = 2, ceiling_div(18446462598732840958, 281474976710656) = 65535 1950 ceiling_div(562949953421312, 562949953421312) = 1, ceiling_div(562949953421314, 562949953421312) = 2, ceiling_div(18446181123756130302, 562949953421312) = 32767 1951 ceiling_div(1125899906842624, 1125899906842624) = 1, ceiling_div(1125899906842626, 1125899906842624) = 2, ceiling_div(18445618173802708990, 1125899906842624) = 16383 1952 ceiling_div(2251799813685248, 2251799813685248) = 1, ceiling_div(2251799813685250, 2251799813685248) = 2, ceiling_div(18444492273895866366, 2251799813685248) = 8191 1953 ceiling_div(4503599627370496, 4503599627370496) = 1, ceiling_div(4503599627370498, 4503599627370496) = 2, ceiling_div(18442240474082181118, 4503599627370496) = 4095 1954 ceiling_div(9007199254740992, 9007199254740992) = 1, ceiling_div(9007199254740994, 9007199254740992) = 2, ceiling_div(18437736874454810622, 9007199254740992) = 2047 1955 ceiling_div(18014398509481984, 18014398509481984) = 1, ceiling_div(18014398509481986, 18014398509481984) = 2, ceiling_div(18428729675200069630, 18014398509481984) = 1023 1956 ceiling_div(36028797018963968, 36028797018963968) = 1, ceiling_div(36028797018963970, 36028797018963968) = 2, ceiling_div(18410715276690587646, 36028797018963968) = 511 1957 ceiling_div(72057594037927936, 72057594037927936) = 1, ceiling_div(72057594037927938, 72057594037927936) = 2, ceiling_div(18374686479671623678, 72057594037927936) = 255 1958 ceiling_div(144115188075855872, 144115188075855872) = 1, ceiling_div(144115188075855874, 144115188075855872) = 2, ceiling_div(18302628885633695742, 144115188075855872) = 127 1959 ceiling_div(288230376151711744, 288230376151711744) = 1, ceiling_div(288230376151711746, 288230376151711744) = 2, ceiling_div(18158513697557839870, 288230376151711744) = 63 1960 ceiling_div(576460752303423488, 576460752303423488) = 1, ceiling_div(576460752303423490, 576460752303423488) = 2, ceiling_div(17870283321406128126, 576460752303423488) = 31 1961 ceiling_div(1152921504606846976, 1152921504606846976) = 1, ceiling_div(1152921504606846978, 1152921504606846976) = 2, ceiling_div(17293822569102704638, 1152921504606846976) = 15 1962 ceiling_div(2305843009213693952, 2305843009213693952) = 1, ceiling_div(2305843009213693954, 2305843009213693952) = 2, ceiling_div(16140901064495857662, 2305843009213693952) = 7 1963 ceiling_div(4611686018427387904, 4611686018427387904) = 1, ceiling_div(4611686018427387906, 4611686018427387904) = 2, ceiling_div(13835058055282163710, 4611686018427387904) = 3 1964 ceiling_div(9223372036854775808, 9223372036854775808) = 1, ceiling_div(9223372036854775810, 9223372036854775808) = 0, ceiling_div(9223372036854775806, 9223372036854775808) = 1 1965 1966 1596 1967 ceiling 1597 1968 1598 1969 signed char 1599 1970 ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(-3, 1) = -3 1600 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(-4, 2) = -11601 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(-6, 4) = 01602 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(-10, 8) = 01603 ceiling(16, 16) = 1 , ceiling(18, 16) =2, ceiling(-18, 16) = 01604 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(-34, 32) = 01605 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(-66, 64) = 01606 ceiling(-128, -128) = 2, ceiling(-126, -128) = 1, ceiling(126, -128) = 01971 ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(-4, 2) = -4 1972 ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(-6, 4) = 0 1973 ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(-10, 8) = 0 1974 ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(-18, 16) = 0 1975 ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(-34, 32) = 0 1976 ceiling(64, 64) = 64, ceiling(66, 64) = -128, ceiling(-66, 64) = 0 1977 ceiling(-128, -128) = -128, ceiling(-126, -128) = -128, ceiling(126, -128) = 0 1607 1978 1608 1979 unsigned char 1609 1980 ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(253, 1) = 253 1610 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(252, 2) = 1261611 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(250, 4) = 631612 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(246, 8) = 311613 ceiling(16, 16) = 1 , ceiling(18, 16) = 2, ceiling(238, 16) = 151614 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(222, 32) = 71615 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(190, 64) = 31616 ceiling(128, 128) = 1 , ceiling(130, 128) = 2, ceiling(126, 128) = 11981 ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(252, 2) = 252 1982 ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(250, 4) = 252 1983 ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(246, 8) = 248 1984 ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(238, 16) = 240 1985 ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(222, 32) = 224 1986 ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(190, 64) = 192 1987 ceiling(128, 128) = 128, ceiling(130, 128) = 0, ceiling(126, 128) = 128 1617 1988 1618 1989 short int 1619 1990 ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(-3, 1) = -3 1620 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(-4, 2) = -11621 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(-6, 4) = 01622 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(-10, 8) = 01623 ceiling(16, 16) = 1 , ceiling(18, 16) =2, ceiling(-18, 16) = 01624 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(-34, 32) = 01625 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(-66, 64) = 01626 ceiling(128, 128) = 1 , ceiling(130, 128) = 2, ceiling(-130, 128) = 01627 ceiling(256, 256) = 1, ceiling(258, 256) =2, ceiling(-258, 256) = 01628 ceiling(512, 512) = 1, ceiling(514, 512) = 2, ceiling(-514, 512) = 01629 ceiling(1024, 1024) = 1 , ceiling(1026, 1024) = 2, ceiling(-1026, 1024) = 01630 ceiling(2048, 2048) = 1, ceiling(2050, 2048) = 2, ceiling(-2050, 2048) = 01631 ceiling(4096, 4096) = 1, ceiling(4098, 4096) =2, ceiling(-4098, 4096) = 01632 ceiling(8192, 8192) = 1, ceiling(8194, 8192) = 2, ceiling(-8194, 8192) = 01633 ceiling(16384, 16384) = 1 , ceiling(16386, 16384) = 2, ceiling(-16386, 16384) = 01634 ceiling(-32768, -32768) = 2, ceiling(-32766, -32768) = 1, ceiling(32766, -32768) = 01991 ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(-4, 2) = -4 1992 ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(-6, 4) = 0 1993 ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(-10, 8) = 0 1994 ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(-18, 16) = 0 1995 ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(-34, 32) = 0 1996 ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(-66, 64) = 0 1997 ceiling(128, 128) = 128, ceiling(130, 128) = 256, ceiling(-130, 128) = 0 1998 ceiling(256, 256) = 256, ceiling(258, 256) = 512, ceiling(-258, 256) = 0 1999 ceiling(512, 512) = 512, ceiling(514, 512) = 1024, ceiling(-514, 512) = 0 2000 ceiling(1024, 1024) = 1024, ceiling(1026, 1024) = 2048, ceiling(-1026, 1024) = 0 2001 ceiling(2048, 2048) = 2048, ceiling(2050, 2048) = 4096, ceiling(-2050, 2048) = 0 2002 ceiling(4096, 4096) = 4096, ceiling(4098, 4096) = 8192, ceiling(-4098, 4096) = 0 2003 ceiling(8192, 8192) = 8192, ceiling(8194, 8192) = 16384, ceiling(-8194, 8192) = 0 2004 ceiling(16384, 16384) = 16384, ceiling(16386, 16384) = -32768, ceiling(-16386, 16384) = 0 2005 ceiling(-32768, -32768) = -32768, ceiling(-32766, -32768) = -32768, ceiling(32766, -32768) = 0 1635 2006 1636 2007 unsigned short int 1637 2008 ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(65533, 1) = 65533 1638 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(65532, 2) = 327661639 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(65530, 4) = 163831640 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(65526, 8) = 81911641 ceiling(16, 16) = 1 , ceiling(18, 16) = 2, ceiling(65518, 16) = 40951642 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(65502, 32) = 20471643 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(65470, 64) = 10231644 ceiling(128, 128) = 1 , ceiling(130, 128) = 2, ceiling(65406, 128) = 5111645 ceiling(256, 256) = 1, ceiling(258, 256) = 2, ceiling(65278, 256) = 2551646 ceiling(512, 512) = 1, ceiling(514, 512) = 2, ceiling(65022, 512) = 1271647 ceiling(1024, 1024) = 1 , ceiling(1026, 1024) = 2, ceiling(64510, 1024) = 631648 ceiling(2048, 2048) = 1, ceiling(2050, 2048) = 2, ceiling(63486, 2048) = 311649 ceiling(4096, 4096) = 1, ceiling(4098, 4096) = 2, ceiling(61438, 4096) = 151650 ceiling(8192, 8192) = 1, ceiling(8194, 8192) = 2, ceiling(57342, 8192) = 71651 ceiling(16384, 16384) = 1 , ceiling(16386, 16384) = 2, ceiling(49150, 16384) = 31652 ceiling(32768, 32768) = 1, ceiling(32770, 32768) = 2, ceiling(32766, 32768) = 12009 ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(65532, 2) = 65532 2010 ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(65530, 4) = 65532 2011 ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(65526, 8) = 65528 2012 ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(65518, 16) = 65520 2013 ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(65502, 32) = 65504 2014 ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(65470, 64) = 65472 2015 ceiling(128, 128) = 128, ceiling(130, 128) = 256, ceiling(65406, 128) = 65408 2016 ceiling(256, 256) = 256, ceiling(258, 256) = 512, ceiling(65278, 256) = 65280 2017 ceiling(512, 512) = 512, ceiling(514, 512) = 1024, ceiling(65022, 512) = 65024 2018 ceiling(1024, 1024) = 1024, ceiling(1026, 1024) = 2048, ceiling(64510, 1024) = 64512 2019 ceiling(2048, 2048) = 2048, ceiling(2050, 2048) = 4096, ceiling(63486, 2048) = 63488 2020 ceiling(4096, 4096) = 4096, ceiling(4098, 4096) = 8192, ceiling(61438, 4096) = 61440 2021 ceiling(8192, 8192) = 8192, ceiling(8194, 8192) = 16384, ceiling(57342, 8192) = 57344 2022 ceiling(16384, 16384) = 16384, ceiling(16386, 16384) = 32768, ceiling(49150, 16384) = 49152 2023 ceiling(32768, 32768) = 32768, ceiling(32770, 32768) = 0, ceiling(32766, 32768) = 32768 1653 2024 1654 2025 int 1655 2026 ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(-3, 1) = -3 1656 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(-4, 2) = -11657 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(-6, 4) = 01658 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(-10, 8) = 01659 ceiling(16, 16) = 1 , ceiling(18, 16) =2, ceiling(-18, 16) = 01660 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(-34, 32) = 01661 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(-66, 64) = 01662 ceiling(128, 128) = 1 , ceiling(130, 128) = 2, ceiling(-130, 128) = 01663 ceiling(256, 256) = 1, ceiling(258, 256) =2, ceiling(-258, 256) = 01664 ceiling(512, 512) = 1, ceiling(514, 512) = 2, ceiling(-514, 512) = 01665 ceiling(1024, 1024) = 1 , ceiling(1026, 1024) = 2, ceiling(-1026, 1024) = 01666 ceiling(2048, 2048) = 1, ceiling(2050, 2048) = 2, ceiling(-2050, 2048) = 01667 ceiling(4096, 4096) = 1, ceiling(4098, 4096) =2, ceiling(-4098, 4096) = 01668 ceiling(8192, 8192) = 1, ceiling(8194, 8192) = 2, ceiling(-8194, 8192) = 01669 ceiling(16384, 16384) = 1 , ceiling(16386, 16384) = 2, ceiling(-16386, 16384) = 01670 ceiling(32768, 32768) = 1, ceiling(32770, 32768) = 2, ceiling(-32770, 32768) = 01671 ceiling(65536, 65536) = 1, ceiling(65538, 65536) =2, ceiling(-65538, 65536) = 01672 ceiling(131072, 131072) = 1 , ceiling(131074, 131072) = 2, ceiling(-131074, 131072) = 01673 ceiling(262144, 262144) = 1, ceiling(262146, 262144) = 2, ceiling(-262146, 262144) = 01674 ceiling(524288, 524288) = 1, ceiling(524290, 524288) = 2, ceiling(-524290, 524288) = 01675 ceiling(1048576, 1048576) = 1 , ceiling(1048578, 1048576) =2, ceiling(-1048578, 1048576) = 01676 ceiling(2097152, 2097152) = 1, ceiling(2097154, 2097152) = 2, ceiling(-2097154, 2097152) = 01677 ceiling(4194304, 4194304) = 1, ceiling(4194306, 4194304) = 2, ceiling(-4194306, 4194304) = 01678 ceiling(8388608, 8388608) = 1, ceiling(8388610, 8388608) = 2, ceiling(-8388610, 8388608) = 01679 ceiling(16777216, 16777216) = 1 , ceiling(16777218, 16777216) =2, ceiling(-16777218, 16777216) = 01680 ceiling(33554432, 33554432) = 1, ceiling(33554434, 33554432) = 2, ceiling(-33554434, 33554432) = 01681 ceiling(67108864, 67108864) = 1, ceiling(67108866, 67108864) = 2, ceiling(-67108866, 67108864) = 01682 ceiling(134217728, 134217728) = 1 , ceiling(134217730, 134217728) = 2, ceiling(-134217730, 134217728) = 01683 ceiling(268435456, 268435456) = 1, ceiling(268435458, 268435456) =2, ceiling(-268435458, 268435456) = 01684 ceiling(536870912, 536870912) = 1, ceiling(536870914, 536870912) = 2, ceiling(-536870914, 536870912) = 01685 ceiling(1073741824, 1073741824) = 1 , ceiling(1073741826, 1073741824) = -1, ceiling(-1073741826, 1073741824) = 01686 ceiling(-2147483648, -2147483648) = 0, ceiling(-2147483646, -2147483648) = 0, ceiling(2147483646, -2147483648) = 02027 ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(-4, 2) = -4 2028 ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(-6, 4) = 0 2029 ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(-10, 8) = 0 2030 ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(-18, 16) = 0 2031 ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(-34, 32) = 0 2032 ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(-66, 64) = 0 2033 ceiling(128, 128) = 128, ceiling(130, 128) = 256, ceiling(-130, 128) = 0 2034 ceiling(256, 256) = 256, ceiling(258, 256) = 512, ceiling(-258, 256) = 0 2035 ceiling(512, 512) = 512, ceiling(514, 512) = 1024, ceiling(-514, 512) = 0 2036 ceiling(1024, 1024) = 1024, ceiling(1026, 1024) = 2048, ceiling(-1026, 1024) = 0 2037 ceiling(2048, 2048) = 2048, ceiling(2050, 2048) = 4096, ceiling(-2050, 2048) = 0 2038 ceiling(4096, 4096) = 4096, ceiling(4098, 4096) = 8192, ceiling(-4098, 4096) = 0 2039 ceiling(8192, 8192) = 8192, ceiling(8194, 8192) = 16384, ceiling(-8194, 8192) = 0 2040 ceiling(16384, 16384) = 16384, ceiling(16386, 16384) = 32768, ceiling(-16386, 16384) = 0 2041 ceiling(32768, 32768) = 32768, ceiling(32770, 32768) = 65536, ceiling(-32770, 32768) = 0 2042 ceiling(65536, 65536) = 65536, ceiling(65538, 65536) = 131072, ceiling(-65538, 65536) = 0 2043 ceiling(131072, 131072) = 131072, ceiling(131074, 131072) = 262144, ceiling(-131074, 131072) = 0 2044 ceiling(262144, 262144) = 262144, ceiling(262146, 262144) = 524288, ceiling(-262146, 262144) = 0 2045 ceiling(524288, 524288) = 524288, ceiling(524290, 524288) = 1048576, ceiling(-524290, 524288) = 0 2046 ceiling(1048576, 1048576) = 1048576, ceiling(1048578, 1048576) = 2097152, ceiling(-1048578, 1048576) = 0 2047 ceiling(2097152, 2097152) = 2097152, ceiling(2097154, 2097152) = 4194304, ceiling(-2097154, 2097152) = 0 2048 ceiling(4194304, 4194304) = 4194304, ceiling(4194306, 4194304) = 8388608, ceiling(-4194306, 4194304) = 0 2049 ceiling(8388608, 8388608) = 8388608, ceiling(8388610, 8388608) = 16777216, ceiling(-8388610, 8388608) = 0 2050 ceiling(16777216, 16777216) = 16777216, ceiling(16777218, 16777216) = 33554432, ceiling(-16777218, 16777216) = 0 2051 ceiling(33554432, 33554432) = 33554432, ceiling(33554434, 33554432) = 67108864, ceiling(-33554434, 33554432) = 0 2052 ceiling(67108864, 67108864) = 67108864, ceiling(67108866, 67108864) = 134217728, ceiling(-67108866, 67108864) = 0 2053 ceiling(134217728, 134217728) = 134217728, ceiling(134217730, 134217728) = 268435456, ceiling(-134217730, 134217728) = 0 2054 ceiling(268435456, 268435456) = 268435456, ceiling(268435458, 268435456) = 536870912, ceiling(-268435458, 268435456) = 0 2055 ceiling(536870912, 536870912) = 536870912, ceiling(536870914, 536870912) = 1073741824, ceiling(-536870914, 536870912) = 0 2056 ceiling(1073741824, 1073741824) = 1073741824, ceiling(1073741826, 1073741824) = -1073741824, ceiling(-1073741826, 1073741824) = 0 2057 ceiling(-2147483648, -2147483648) = -2147483648, ceiling(-2147483646, -2147483648) = 0, ceiling(2147483646, -2147483648) = 0 1687 2058 1688 2059 unsigned int 1689 2060 ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(4294967293, 1) = 4294967293 1690 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(4294967292, 2) = 21474836461691 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(4294967290, 4) = 10737418231692 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(4294967286, 8) = 5368709111693 ceiling(16, 16) = 1 , ceiling(18, 16) = 2, ceiling(4294967278, 16) = 2684354551694 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(4294967262, 32) = 1342177271695 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(4294967230, 64) = 671088631696 ceiling(128, 128) = 1 , ceiling(130, 128) = 2, ceiling(4294967166, 128) = 335544311697 ceiling(256, 256) = 1, ceiling(258, 256) = 2, ceiling(4294967038, 256) = 167772151698 ceiling(512, 512) = 1, ceiling(514, 512) = 2, ceiling(4294966782, 512) = 83886071699 ceiling(1024, 1024) = 1 , ceiling(1026, 1024) = 2, ceiling(4294966270, 1024) = 41943031700 ceiling(2048, 2048) = 1, ceiling(2050, 2048) = 2, ceiling(4294965246, 2048) = 20971511701 ceiling(4096, 4096) = 1, ceiling(4098, 4096) = 2, ceiling(4294963198, 4096) = 10485751702 ceiling(8192, 8192) = 1, ceiling(8194, 8192) = 2, ceiling(4294959102, 8192) = 5242871703 ceiling(16384, 16384) = 1 , ceiling(16386, 16384) = 2, ceiling(4294950910, 16384) = 2621431704 ceiling(32768, 32768) = 1, ceiling(32770, 32768) = 2, ceiling(4294934526, 32768) = 1310711705 ceiling(65536, 65536) = 1, ceiling(65538, 65536) = 2, ceiling(4294901758, 65536) = 655351706 ceiling(131072, 131072) = 1 , ceiling(131074, 131072) = 2, ceiling(4294836222, 131072) = 327671707 ceiling(262144, 262144) = 1, ceiling(262146, 262144) = 2, ceiling(4294705150, 262144) = 163831708 ceiling(524288, 524288) = 1, ceiling(524290, 524288) = 2, ceiling(4294443006, 524288) = 81911709 ceiling(1048576, 1048576) = 1 , ceiling(1048578, 1048576) = 2, ceiling(4293918718, 1048576) = 40951710 ceiling(2097152, 2097152) = 1, ceiling(2097154, 2097152) = 2, ceiling(4292870142, 2097152) = 20471711 ceiling(4194304, 4194304) = 1, ceiling(4194306, 4194304) = 2, ceiling(4290772990, 4194304) = 10231712 ceiling(8388608, 8388608) = 1, ceiling(8388610, 8388608) = 2, ceiling(4286578686, 8388608) = 5111713 ceiling(16777216, 16777216) = 1 , ceiling(16777218, 16777216) = 2, ceiling(4278190078, 16777216) = 2551714 ceiling(33554432, 33554432) = 1, ceiling(33554434, 33554432) = 2, ceiling(4261412862, 33554432) = 1271715 ceiling(67108864, 67108864) = 1, ceiling(67108866, 67108864) = 2, ceiling(4227858430, 67108864) = 631716 ceiling(134217728, 134217728) = 1 , ceiling(134217730, 134217728) = 2, ceiling(4160749566, 134217728) = 311717 ceiling(268435456, 268435456) = 1, ceiling(268435458, 268435456) = 2, ceiling(4026531838, 268435456) = 151718 ceiling(536870912, 536870912) = 1, ceiling(536870914, 536870912) = 2, ceiling(3758096382, 536870912) = 71719 ceiling(1073741824, 1073741824) = 1 , ceiling(1073741826, 1073741824) = 2, ceiling(3221225470, 1073741824) = 31720 ceiling(2147483648, 2147483648) = 1, ceiling(2147483650, 2147483648) = 0, ceiling(2147483646, 2147483648) = 12061 ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(4294967292, 2) = 4294967292 2062 ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(4294967290, 4) = 4294967292 2063 ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(4294967286, 8) = 4294967288 2064 ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(4294967278, 16) = 4294967280 2065 ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(4294967262, 32) = 4294967264 2066 ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(4294967230, 64) = 4294967232 2067 ceiling(128, 128) = 128, ceiling(130, 128) = 256, ceiling(4294967166, 128) = 4294967168 2068 ceiling(256, 256) = 256, ceiling(258, 256) = 512, ceiling(4294967038, 256) = 4294967040 2069 ceiling(512, 512) = 512, ceiling(514, 512) = 1024, ceiling(4294966782, 512) = 4294966784 2070 ceiling(1024, 1024) = 1024, ceiling(1026, 1024) = 2048, ceiling(4294966270, 1024) = 4294966272 2071 ceiling(2048, 2048) = 2048, ceiling(2050, 2048) = 4096, ceiling(4294965246, 2048) = 4294965248 2072 ceiling(4096, 4096) = 4096, ceiling(4098, 4096) = 8192, ceiling(4294963198, 4096) = 4294963200 2073 ceiling(8192, 8192) = 8192, ceiling(8194, 8192) = 16384, ceiling(4294959102, 8192) = 4294959104 2074 ceiling(16384, 16384) = 16384, ceiling(16386, 16384) = 32768, ceiling(4294950910, 16384) = 4294950912 2075 ceiling(32768, 32768) = 32768, ceiling(32770, 32768) = 65536, ceiling(4294934526, 32768) = 4294934528 2076 ceiling(65536, 65536) = 65536, ceiling(65538, 65536) = 131072, ceiling(4294901758, 65536) = 4294901760 2077 ceiling(131072, 131072) = 131072, ceiling(131074, 131072) = 262144, ceiling(4294836222, 131072) = 4294836224 2078 ceiling(262144, 262144) = 262144, ceiling(262146, 262144) = 524288, ceiling(4294705150, 262144) = 4294705152 2079 ceiling(524288, 524288) = 524288, ceiling(524290, 524288) = 1048576, ceiling(4294443006, 524288) = 4294443008 2080 ceiling(1048576, 1048576) = 1048576, ceiling(1048578, 1048576) = 2097152, ceiling(4293918718, 1048576) = 4293918720 2081 ceiling(2097152, 2097152) = 2097152, ceiling(2097154, 2097152) = 4194304, ceiling(4292870142, 2097152) = 4292870144 2082 ceiling(4194304, 4194304) = 4194304, ceiling(4194306, 4194304) = 8388608, ceiling(4290772990, 4194304) = 4290772992 2083 ceiling(8388608, 8388608) = 8388608, ceiling(8388610, 8388608) = 16777216, ceiling(4286578686, 8388608) = 4286578688 2084 ceiling(16777216, 16777216) = 16777216, ceiling(16777218, 16777216) = 33554432, ceiling(4278190078, 16777216) = 4278190080 2085 ceiling(33554432, 33554432) = 33554432, ceiling(33554434, 33554432) = 67108864, ceiling(4261412862, 33554432) = 4261412864 2086 ceiling(67108864, 67108864) = 67108864, ceiling(67108866, 67108864) = 134217728, ceiling(4227858430, 67108864) = 4227858432 2087 ceiling(134217728, 134217728) = 134217728, ceiling(134217730, 134217728) = 268435456, ceiling(4160749566, 134217728) = 4160749568 2088 ceiling(268435456, 268435456) = 268435456, ceiling(268435458, 268435456) = 536870912, ceiling(4026531838, 268435456) = 4026531840 2089 ceiling(536870912, 536870912) = 536870912, ceiling(536870914, 536870912) = 1073741824, ceiling(3758096382, 536870912) = 3758096384 2090 ceiling(1073741824, 1073741824) = 1073741824, ceiling(1073741826, 1073741824) = 2147483648, ceiling(3221225470, 1073741824) = 3221225472 2091 ceiling(2147483648, 2147483648) = 2147483648, ceiling(2147483650, 2147483648) = 0, ceiling(2147483646, 2147483648) = 2147483648 1721 2092 1722 2093 long int 1723 2094 ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(-3, 1) = -3 1724 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(-4, 2) = -11725 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(-6, 4) = 01726 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(-10, 8) = 01727 ceiling(16, 16) = 1 , ceiling(18, 16) =2, ceiling(-18, 16) = 01728 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(-34, 32) = 01729 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(-66, 64) = 01730 ceiling(128, 128) = 1 , ceiling(130, 128) = 2, ceiling(-130, 128) = 01731 ceiling(256, 256) = 1, ceiling(258, 256) =2, ceiling(-258, 256) = 01732 ceiling(512, 512) = 1, ceiling(514, 512) = 2, ceiling(-514, 512) = 01733 ceiling(1024, 1024) = 1 , ceiling(1026, 1024) = 2, ceiling(-1026, 1024) = 01734 ceiling(2048, 2048) = 1, ceiling(2050, 2048) = 2, ceiling(-2050, 2048) = 01735 ceiling(4096, 4096) = 1, ceiling(4098, 4096) =2, ceiling(-4098, 4096) = 01736 ceiling(8192, 8192) = 1, ceiling(8194, 8192) = 2, ceiling(-8194, 8192) = 01737 ceiling(16384, 16384) = 1 , ceiling(16386, 16384) = 2, ceiling(-16386, 16384) = 01738 ceiling(32768, 32768) = 1, ceiling(32770, 32768) = 2, ceiling(-32770, 32768) = 01739 ceiling(65536, 65536) = 1, ceiling(65538, 65536) =2, ceiling(-65538, 65536) = 01740 ceiling(131072, 131072) = 1 , ceiling(131074, 131072) = 2, ceiling(-131074, 131072) = 01741 ceiling(262144, 262144) = 1, ceiling(262146, 262144) = 2, ceiling(-262146, 262144) = 01742 ceiling(524288, 524288) = 1, ceiling(524290, 524288) = 2, ceiling(-524290, 524288) = 01743 ceiling(1048576, 1048576) = 1 , ceiling(1048578, 1048576) =2, ceiling(-1048578, 1048576) = 01744 ceiling(2097152, 2097152) = 1, ceiling(2097154, 2097152) = 2, ceiling(-2097154, 2097152) = 01745 ceiling(4194304, 4194304) = 1, ceiling(4194306, 4194304) = 2, ceiling(-4194306, 4194304) = 01746 ceiling(8388608, 8388608) = 1, ceiling(8388610, 8388608) = 2, ceiling(-8388610, 8388608) = 01747 ceiling(16777216, 16777216) = 1 , ceiling(16777218, 16777216) =2, ceiling(-16777218, 16777216) = 01748 ceiling(33554432, 33554432) = 1, ceiling(33554434, 33554432) = 2, ceiling(-33554434, 33554432) = 01749 ceiling(67108864, 67108864) = 1, ceiling(67108866, 67108864) = 2, ceiling(-67108866, 67108864) = 01750 ceiling(134217728, 134217728) = 1 , ceiling(134217730, 134217728) = 2, ceiling(-134217730, 134217728) = 01751 ceiling(268435456, 268435456) = 1, ceiling(268435458, 268435456) =2, ceiling(-268435458, 268435456) = 01752 ceiling(536870912, 536870912) = 1, ceiling(536870914, 536870912) = 2, ceiling(-536870914, 536870912) = 01753 ceiling(1073741824, 1073741824) = 1 , ceiling(1073741826, 1073741824) = 2, ceiling(-1073741826, 1073741824) = 01754 ceiling(2147483648, 2147483648) = 1, ceiling(2147483650, 2147483648) = 2, ceiling(-2147483650, 2147483648) = 01755 ceiling(4294967296, 4294967296) = 1, ceiling(4294967298, 4294967296) =2, ceiling(-4294967298, 4294967296) = 01756 ceiling(8589934592, 8589934592) = 1, ceiling(8589934594, 8589934592) = 2, ceiling(-8589934594, 8589934592) = 01757 ceiling(17179869184, 17179869184) = 1 , ceiling(17179869186, 17179869184) = 2, ceiling(-17179869186, 17179869184) = 01758 ceiling(34359738368, 34359738368) = 1, ceiling(34359738370, 34359738368) = 2, ceiling(-34359738370, 34359738368) = 01759 ceiling(68719476736, 68719476736) = 1, ceiling(68719476738, 68719476736) =2, ceiling(-68719476738, 68719476736) = 01760 ceiling(137438953472, 137438953472) = 1 , ceiling(137438953474, 137438953472) = 2, ceiling(-137438953474, 137438953472) = 01761 ceiling(274877906944, 274877906944) = 1, ceiling(274877906946, 274877906944) = 2, ceiling(-274877906946, 274877906944) = 01762 ceiling(549755813888, 549755813888) = 1, ceiling(549755813890, 549755813888) = 2, ceiling(-549755813890, 549755813888) = 01763 ceiling(1099511627776, 1099511627776) = 1 , ceiling(1099511627778, 1099511627776) =2, ceiling(-1099511627778, 1099511627776) = 01764 ceiling(2199023255552, 2199023255552) = 1, ceiling(2199023255554, 2199023255552) = 2, ceiling(-2199023255554, 2199023255552) = 01765 ceiling(4398046511104, 4398046511104) = 1, ceiling(4398046511106, 4398046511104) = 2, ceiling(-4398046511106, 4398046511104) = 01766 ceiling(8796093022208, 8796093022208) = 1, ceiling(8796093022210, 8796093022208) = 2, ceiling(-8796093022210, 8796093022208) = 01767 ceiling(17592186044416, 17592186044416) = 1 , ceiling(17592186044418, 17592186044416) =2, ceiling(-17592186044418, 17592186044416) = 01768 ceiling(35184372088832, 35184372088832) = 1, ceiling(35184372088834, 35184372088832) = 2, ceiling(-35184372088834, 35184372088832) = 01769 ceiling(70368744177664, 70368744177664) = 1, ceiling(70368744177666, 70368744177664) = 2, ceiling(-70368744177666, 70368744177664) = 01770 ceiling(140737488355328, 140737488355328) = 1 , ceiling(140737488355330, 140737488355328) = 2, ceiling(-140737488355330, 140737488355328) = 01771 ceiling(281474976710656, 281474976710656) = 1, ceiling(281474976710658, 281474976710656) =2, ceiling(-281474976710658, 281474976710656) = 01772 ceiling(562949953421312, 562949953421312) = 1, ceiling(562949953421314, 562949953421312) = 2, ceiling(-562949953421314, 562949953421312) = 01773 ceiling(1125899906842624, 1125899906842624) = 1 , ceiling(1125899906842626, 1125899906842624) = 2, ceiling(-1125899906842626, 1125899906842624) = 01774 ceiling(2251799813685248, 2251799813685248) = 1, ceiling(2251799813685250, 2251799813685248) = 2, ceiling(-2251799813685250, 2251799813685248) = 01775 ceiling(4503599627370496, 4503599627370496) = 1, ceiling(4503599627370498, 4503599627370496) =2, ceiling(-4503599627370498, 4503599627370496) = 01776 ceiling(9007199254740992, 9007199254740992) = 1, ceiling(9007199254740994, 9007199254740992) = 2, ceiling(-9007199254740994, 9007199254740992) = 01777 ceiling(18014398509481984, 18014398509481984) = 1 , ceiling(18014398509481986, 18014398509481984) = 2, ceiling(-18014398509481986, 18014398509481984) = 01778 ceiling(36028797018963968, 36028797018963968) = 1, ceiling(36028797018963970, 36028797018963968) = 2, ceiling(-36028797018963970, 36028797018963968) = 01779 ceiling(72057594037927936, 72057594037927936) = 1, ceiling(72057594037927938, 72057594037927936) =2, ceiling(-72057594037927938, 72057594037927936) = 01780 ceiling(144115188075855872, 144115188075855872) = 1 , ceiling(144115188075855874, 144115188075855872) = 2, ceiling(-144115188075855874, 144115188075855872) = 01781 ceiling(288230376151711744, 288230376151711744) = 1, ceiling(288230376151711746, 288230376151711744) = 2, ceiling(-288230376151711746, 288230376151711744) = 01782 ceiling(576460752303423488, 576460752303423488) = 1, ceiling(576460752303423490, 576460752303423488) = 2, ceiling(-576460752303423490, 576460752303423488) = 01783 ceiling(1152921504606846976, 1152921504606846976) = 1 , ceiling(1152921504606846978, 1152921504606846976) =2, ceiling(-1152921504606846978, 1152921504606846976) = 01784 ceiling(2305843009213693952, 2305843009213693952) = 1, ceiling(2305843009213693954, 2305843009213693952) = 2, ceiling(-2305843009213693954, 2305843009213693952) = 01785 ceiling(4611686018427387904, 4611686018427387904) = 1, ceiling(4611686018427387906, 4611686018427387904) = -1, ceiling(-4611686018427387906, 4611686018427387904) = 01786 ceiling(-9223372036854775808, -9223372036854775808) = 0, ceiling(-9223372036854775806, -9223372036854775808) = 0, ceiling(9223372036854775806, -9223372036854775808) = 02095 ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(-4, 2) = -4 2096 ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(-6, 4) = 0 2097 ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(-10, 8) = 0 2098 ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(-18, 16) = 0 2099 ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(-34, 32) = 0 2100 ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(-66, 64) = 0 2101 ceiling(128, 128) = 128, ceiling(130, 128) = 256, ceiling(-130, 128) = 0 2102 ceiling(256, 256) = 256, ceiling(258, 256) = 512, ceiling(-258, 256) = 0 2103 ceiling(512, 512) = 512, ceiling(514, 512) = 1024, ceiling(-514, 512) = 0 2104 ceiling(1024, 1024) = 1024, ceiling(1026, 1024) = 2048, ceiling(-1026, 1024) = 0 2105 ceiling(2048, 2048) = 2048, ceiling(2050, 2048) = 4096, ceiling(-2050, 2048) = 0 2106 ceiling(4096, 4096) = 4096, ceiling(4098, 4096) = 8192, ceiling(-4098, 4096) = 0 2107 ceiling(8192, 8192) = 8192, ceiling(8194, 8192) = 16384, ceiling(-8194, 8192) = 0 2108 ceiling(16384, 16384) = 16384, ceiling(16386, 16384) = 32768, ceiling(-16386, 16384) = 0 2109 ceiling(32768, 32768) = 32768, ceiling(32770, 32768) = 65536, ceiling(-32770, 32768) = 0 2110 ceiling(65536, 65536) = 65536, ceiling(65538, 65536) = 131072, ceiling(-65538, 65536) = 0 2111 ceiling(131072, 131072) = 131072, ceiling(131074, 131072) = 262144, ceiling(-131074, 131072) = 0 2112 ceiling(262144, 262144) = 262144, ceiling(262146, 262144) = 524288, ceiling(-262146, 262144) = 0 2113 ceiling(524288, 524288) = 524288, ceiling(524290, 524288) = 1048576, ceiling(-524290, 524288) = 0 2114 ceiling(1048576, 1048576) = 1048576, ceiling(1048578, 1048576) = 2097152, ceiling(-1048578, 1048576) = 0 2115 ceiling(2097152, 2097152) = 2097152, ceiling(2097154, 2097152) = 4194304, ceiling(-2097154, 2097152) = 0 2116 ceiling(4194304, 4194304) = 4194304, ceiling(4194306, 4194304) = 8388608, ceiling(-4194306, 4194304) = 0 2117 ceiling(8388608, 8388608) = 8388608, ceiling(8388610, 8388608) = 16777216, ceiling(-8388610, 8388608) = 0 2118 ceiling(16777216, 16777216) = 16777216, ceiling(16777218, 16777216) = 33554432, ceiling(-16777218, 16777216) = 0 2119 ceiling(33554432, 33554432) = 33554432, ceiling(33554434, 33554432) = 67108864, ceiling(-33554434, 33554432) = 0 2120 ceiling(67108864, 67108864) = 67108864, ceiling(67108866, 67108864) = 134217728, ceiling(-67108866, 67108864) = 0 2121 ceiling(134217728, 134217728) = 134217728, ceiling(134217730, 134217728) = 268435456, ceiling(-134217730, 134217728) = 0 2122 ceiling(268435456, 268435456) = 268435456, ceiling(268435458, 268435456) = 536870912, ceiling(-268435458, 268435456) = 0 2123 ceiling(536870912, 536870912) = 536870912, ceiling(536870914, 536870912) = 1073741824, ceiling(-536870914, 536870912) = 0 2124 ceiling(1073741824, 1073741824) = 1073741824, ceiling(1073741826, 1073741824) = 2147483648, ceiling(-1073741826, 1073741824) = 0 2125 ceiling(2147483648, 2147483648) = 2147483648, ceiling(2147483650, 2147483648) = 4294967296, ceiling(-2147483650, 2147483648) = 0 2126 ceiling(4294967296, 4294967296) = 4294967296, ceiling(4294967298, 4294967296) = 8589934592, ceiling(-4294967298, 4294967296) = 0 2127 ceiling(8589934592, 8589934592) = 8589934592, ceiling(8589934594, 8589934592) = 17179869184, ceiling(-8589934594, 8589934592) = 0 2128 ceiling(17179869184, 17179869184) = 17179869184, ceiling(17179869186, 17179869184) = 34359738368, ceiling(-17179869186, 17179869184) = 0 2129 ceiling(34359738368, 34359738368) = 34359738368, ceiling(34359738370, 34359738368) = 68719476736, ceiling(-34359738370, 34359738368) = 0 2130 ceiling(68719476736, 68719476736) = 68719476736, ceiling(68719476738, 68719476736) = 137438953472, ceiling(-68719476738, 68719476736) = 0 2131 ceiling(137438953472, 137438953472) = 137438953472, ceiling(137438953474, 137438953472) = 274877906944, ceiling(-137438953474, 137438953472) = 0 2132 ceiling(274877906944, 274877906944) = 274877906944, ceiling(274877906946, 274877906944) = 549755813888, ceiling(-274877906946, 274877906944) = 0 2133 ceiling(549755813888, 549755813888) = 549755813888, ceiling(549755813890, 549755813888) = 1099511627776, ceiling(-549755813890, 549755813888) = 0 2134 ceiling(1099511627776, 1099511627776) = 1099511627776, ceiling(1099511627778, 1099511627776) = 2199023255552, ceiling(-1099511627778, 1099511627776) = 0 2135 ceiling(2199023255552, 2199023255552) = 2199023255552, ceiling(2199023255554, 2199023255552) = 4398046511104, ceiling(-2199023255554, 2199023255552) = 0 2136 ceiling(4398046511104, 4398046511104) = 4398046511104, ceiling(4398046511106, 4398046511104) = 8796093022208, ceiling(-4398046511106, 4398046511104) = 0 2137 ceiling(8796093022208, 8796093022208) = 8796093022208, ceiling(8796093022210, 8796093022208) = 17592186044416, ceiling(-8796093022210, 8796093022208) = 0 2138 ceiling(17592186044416, 17592186044416) = 17592186044416, ceiling(17592186044418, 17592186044416) = 35184372088832, ceiling(-17592186044418, 17592186044416) = 0 2139 ceiling(35184372088832, 35184372088832) = 35184372088832, ceiling(35184372088834, 35184372088832) = 70368744177664, ceiling(-35184372088834, 35184372088832) = 0 2140 ceiling(70368744177664, 70368744177664) = 70368744177664, ceiling(70368744177666, 70368744177664) = 140737488355328, ceiling(-70368744177666, 70368744177664) = 0 2141 ceiling(140737488355328, 140737488355328) = 140737488355328, ceiling(140737488355330, 140737488355328) = 281474976710656, ceiling(-140737488355330, 140737488355328) = 0 2142 ceiling(281474976710656, 281474976710656) = 281474976710656, ceiling(281474976710658, 281474976710656) = 562949953421312, ceiling(-281474976710658, 281474976710656) = 0 2143 ceiling(562949953421312, 562949953421312) = 562949953421312, ceiling(562949953421314, 562949953421312) = 1125899906842624, ceiling(-562949953421314, 562949953421312) = 0 2144 ceiling(1125899906842624, 1125899906842624) = 1125899906842624, ceiling(1125899906842626, 1125899906842624) = 2251799813685248, ceiling(-1125899906842626, 1125899906842624) = 0 2145 ceiling(2251799813685248, 2251799813685248) = 2251799813685248, ceiling(2251799813685250, 2251799813685248) = 4503599627370496, ceiling(-2251799813685250, 2251799813685248) = 0 2146 ceiling(4503599627370496, 4503599627370496) = 4503599627370496, ceiling(4503599627370498, 4503599627370496) = 9007199254740992, ceiling(-4503599627370498, 4503599627370496) = 0 2147 ceiling(9007199254740992, 9007199254740992) = 9007199254740992, ceiling(9007199254740994, 9007199254740992) = 18014398509481984, ceiling(-9007199254740994, 9007199254740992) = 0 2148 ceiling(18014398509481984, 18014398509481984) = 18014398509481984, ceiling(18014398509481986, 18014398509481984) = 36028797018963968, ceiling(-18014398509481986, 18014398509481984) = 0 2149 ceiling(36028797018963968, 36028797018963968) = 36028797018963968, ceiling(36028797018963970, 36028797018963968) = 72057594037927936, ceiling(-36028797018963970, 36028797018963968) = 0 2150 ceiling(72057594037927936, 72057594037927936) = 72057594037927936, ceiling(72057594037927938, 72057594037927936) = 144115188075855872, ceiling(-72057594037927938, 72057594037927936) = 0 2151 ceiling(144115188075855872, 144115188075855872) = 144115188075855872, ceiling(144115188075855874, 144115188075855872) = 288230376151711744, ceiling(-144115188075855874, 144115188075855872) = 0 2152 ceiling(288230376151711744, 288230376151711744) = 288230376151711744, ceiling(288230376151711746, 288230376151711744) = 576460752303423488, ceiling(-288230376151711746, 288230376151711744) = 0 2153 ceiling(576460752303423488, 576460752303423488) = 576460752303423488, ceiling(576460752303423490, 576460752303423488) = 1152921504606846976, ceiling(-576460752303423490, 576460752303423488) = 0 2154 ceiling(1152921504606846976, 1152921504606846976) = 1152921504606846976, ceiling(1152921504606846978, 1152921504606846976) = 2305843009213693952, ceiling(-1152921504606846978, 1152921504606846976) = 0 2155 ceiling(2305843009213693952, 2305843009213693952) = 2305843009213693952, ceiling(2305843009213693954, 2305843009213693952) = 4611686018427387904, ceiling(-2305843009213693954, 2305843009213693952) = 0 2156 ceiling(4611686018427387904, 4611686018427387904) = 4611686018427387904, ceiling(4611686018427387906, 4611686018427387904) = -4611686018427387904, ceiling(-4611686018427387906, 4611686018427387904) = 0 2157 ceiling(-9223372036854775808, -9223372036854775808) = -9223372036854775808, ceiling(-9223372036854775806, -9223372036854775808) = 0, ceiling(9223372036854775806, -9223372036854775808) = 0 1787 2158 1788 2159 unsigned long int 1789 2160 ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(18446744073709551613, 1) = 18446744073709551613 1790 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(18446744073709551612, 2) = 92233720368547758061791 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(18446744073709551610, 4) = 46116860184273879031792 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(18446744073709551606, 8) = 23058430092136939511793 ceiling(16, 16) = 1 , ceiling(18, 16) = 2, ceiling(18446744073709551598, 16) = 11529215046068469751794 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(18446744073709551582, 32) = 5764607523034234871795 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(18446744073709551550, 64) = 2882303761517117431796 ceiling(128, 128) = 1 , ceiling(130, 128) = 2, ceiling(18446744073709551486, 128) = 1441151880758558711797 ceiling(256, 256) = 1, ceiling(258, 256) = 2, ceiling(18446744073709551358, 256) = 720575940379279351798 ceiling(512, 512) = 1, ceiling(514, 512) = 2, ceiling(18446744073709551102, 512) = 360287970189639671799 ceiling(1024, 1024) = 1 , ceiling(1026, 1024) = 2, ceiling(18446744073709550590, 1024) = 180143985094819831800 ceiling(2048, 2048) = 1, ceiling(2050, 2048) = 2, ceiling(18446744073709549566, 2048) = 90071992547409911801 ceiling(4096, 4096) = 1, ceiling(4098, 4096) = 2, ceiling(18446744073709547518, 4096) = 45035996273704951802 ceiling(8192, 8192) = 1, ceiling(8194, 8192) = 2, ceiling(18446744073709543422, 8192) = 22517998136852471803 ceiling(16384, 16384) = 1 , ceiling(16386, 16384) = 2, ceiling(18446744073709535230, 16384) = 11258999068426231804 ceiling(32768, 32768) = 1, ceiling(32770, 32768) = 2, ceiling(18446744073709518846, 32768) = 5629499534213111805 ceiling(65536, 65536) = 1, ceiling(65538, 65536) = 2, ceiling(18446744073709486078, 65536) = 2814749767106551806 ceiling(131072, 131072) = 1 , ceiling(131074, 131072) = 2, ceiling(18446744073709420542, 131072) = 1407374883553271807 ceiling(262144, 262144) = 1, ceiling(262146, 262144) = 2, ceiling(18446744073709289470, 262144) = 703687441776631808 ceiling(524288, 524288) = 1, ceiling(524290, 524288) = 2, ceiling(18446744073709027326, 524288) = 351843720888311809 ceiling(1048576, 1048576) = 1 , ceiling(1048578, 1048576) = 2, ceiling(18446744073708503038, 1048576) = 175921860444151810 ceiling(2097152, 2097152) = 1, ceiling(2097154, 2097152) = 2, ceiling(18446744073707454462, 2097152) = 87960930222071811 ceiling(4194304, 4194304) = 1, ceiling(4194306, 4194304) = 2, ceiling(18446744073705357310, 4194304) = 43980465111031812 ceiling(8388608, 8388608) = 1, ceiling(8388610, 8388608) = 2, ceiling(18446744073701163006, 8388608) = 21990232555511813 ceiling(16777216, 16777216) = 1 , ceiling(16777218, 16777216) = 2, ceiling(18446744073692774398, 16777216) = 10995116277751814 ceiling(33554432, 33554432) = 1, ceiling(33554434, 33554432) = 2, ceiling(18446744073675997182, 33554432) = 5497558138871815 ceiling(67108864, 67108864) = 1, ceiling(67108866, 67108864) = 2, ceiling(18446744073642442750, 67108864) = 2748779069431816 ceiling(134217728, 134217728) = 1 , ceiling(134217730, 134217728) = 2, ceiling(18446744073575333886, 134217728) = 1374389534711817 ceiling(268435456, 268435456) = 1, ceiling(268435458, 268435456) = 2, ceiling(18446744073441116158, 268435456) = 687194767351818 ceiling(536870912, 536870912) = 1, ceiling(536870914, 536870912) = 2, ceiling(18446744073172680702, 536870912) = 343597383671819 ceiling(1073741824, 1073741824) = 1 , ceiling(1073741826, 1073741824) = 2, ceiling(18446744072635809790, 1073741824) = 171798691831820 ceiling(2147483648, 2147483648) = 1, ceiling(2147483650, 2147483648) = 2, ceiling(18446744071562067966, 2147483648) = 85899345911821 ceiling(4294967296, 4294967296) = 1, ceiling(4294967298, 4294967296) = 2, ceiling(18446744069414584318, 4294967296) = 42949672951822 ceiling(8589934592, 8589934592) = 1, ceiling(8589934594, 8589934592) = 2, ceiling(18446744065119617022, 8589934592) = 21474836471823 ceiling(17179869184, 17179869184) = 1 , ceiling(17179869186, 17179869184) = 2, ceiling(18446744056529682430, 17179869184) = 10737418231824 ceiling(34359738368, 34359738368) = 1, ceiling(34359738370, 34359738368) = 2, ceiling(18446744039349813246, 34359738368) = 5368709111825 ceiling(68719476736, 68719476736) = 1, ceiling(68719476738, 68719476736) = 2, ceiling(18446744004990074878, 68719476736) = 2684354551826 ceiling(137438953472, 137438953472) = 1 , ceiling(137438953474, 137438953472) = 2, ceiling(18446743936270598142, 137438953472) = 1342177271827 ceiling(274877906944, 274877906944) = 1, ceiling(274877906946, 274877906944) = 2, ceiling(18446743798831644670, 274877906944) = 671088631828 ceiling(549755813888, 549755813888) = 1, ceiling(549755813890, 549755813888) = 2, ceiling(18446743523953737726, 549755813888) = 335544311829 ceiling(1099511627776, 1099511627776) = 1 , ceiling(1099511627778, 1099511627776) = 2, ceiling(18446742974197923838, 1099511627776) = 167772151830 ceiling(2199023255552, 2199023255552) = 1, ceiling(2199023255554, 2199023255552) = 2, ceiling(18446741874686296062, 2199023255552) = 83886071831 ceiling(4398046511104, 4398046511104) = 1, ceiling(4398046511106, 4398046511104) = 2, ceiling(18446739675663040510, 4398046511104) = 41943031832 ceiling(8796093022208, 8796093022208) = 1, ceiling(8796093022210, 8796093022208) = 2, ceiling(18446735277616529406, 8796093022208) = 20971511833 ceiling(17592186044416, 17592186044416) = 1 , ceiling(17592186044418, 17592186044416) = 2, ceiling(18446726481523507198, 17592186044416) = 10485751834 ceiling(35184372088832, 35184372088832) = 1, ceiling(35184372088834, 35184372088832) = 2, ceiling(18446708889337462782, 35184372088832) = 5242871835 ceiling(70368744177664, 70368744177664) = 1, ceiling(70368744177666, 70368744177664) = 2, ceiling(18446673704965373950, 70368744177664) = 2621431836 ceiling(140737488355328, 140737488355328) = 1 , ceiling(140737488355330, 140737488355328) = 2, ceiling(18446603336221196286, 140737488355328) = 1310711837 ceiling(281474976710656, 281474976710656) = 1, ceiling(281474976710658, 281474976710656) = 2, ceiling(18446462598732840958, 281474976710656) = 655351838 ceiling(562949953421312, 562949953421312) = 1, ceiling(562949953421314, 562949953421312) = 2, ceiling(18446181123756130302, 562949953421312) = 327671839 ceiling(1125899906842624, 1125899906842624) = 1 , ceiling(1125899906842626, 1125899906842624) = 2, ceiling(18445618173802708990, 1125899906842624) = 163831840 ceiling(2251799813685248, 2251799813685248) = 1, ceiling(2251799813685250, 2251799813685248) = 2, ceiling(18444492273895866366, 2251799813685248) = 81911841 ceiling(4503599627370496, 4503599627370496) = 1, ceiling(4503599627370498, 4503599627370496) = 2, ceiling(18442240474082181118, 4503599627370496) = 40951842 ceiling(9007199254740992, 9007199254740992) = 1, ceiling(9007199254740994, 9007199254740992) = 2, ceiling(18437736874454810622, 9007199254740992) = 20471843 ceiling(18014398509481984, 18014398509481984) = 1 , ceiling(18014398509481986, 18014398509481984) = 2, ceiling(18428729675200069630, 18014398509481984) = 10231844 ceiling(36028797018963968, 36028797018963968) = 1, ceiling(36028797018963970, 36028797018963968) = 2, ceiling(18410715276690587646, 36028797018963968) = 5111845 ceiling(72057594037927936, 72057594037927936) = 1, ceiling(72057594037927938, 72057594037927936) = 2, ceiling(18374686479671623678, 72057594037927936) = 2551846 ceiling(144115188075855872, 144115188075855872) = 1 , ceiling(144115188075855874, 144115188075855872) = 2, ceiling(18302628885633695742, 144115188075855872) = 1271847 ceiling(288230376151711744, 288230376151711744) = 1, ceiling(288230376151711746, 288230376151711744) = 2, ceiling(18158513697557839870, 288230376151711744) = 631848 ceiling(576460752303423488, 576460752303423488) = 1, ceiling(576460752303423490, 576460752303423488) = 2, ceiling(17870283321406128126, 576460752303423488) = 311849 ceiling(1152921504606846976, 1152921504606846976) = 1 , ceiling(1152921504606846978, 1152921504606846976) = 2, ceiling(17293822569102704638, 1152921504606846976) = 151850 ceiling(2305843009213693952, 2305843009213693952) = 1, ceiling(2305843009213693954, 2305843009213693952) = 2, ceiling(16140901064495857662, 2305843009213693952) = 71851 ceiling(4611686018427387904, 4611686018427387904) = 1, ceiling(4611686018427387906, 4611686018427387904) = 2, ceiling(13835058055282163710, 4611686018427387904) = 31852 ceiling(9223372036854775808, 9223372036854775808) = 1, ceiling(9223372036854775810, 9223372036854775808) = 0, ceiling(9223372036854775806, 9223372036854775808) = 12161 ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(18446744073709551612, 2) = 18446744073709551612 2162 ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(18446744073709551610, 4) = 18446744073709551612 2163 ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(18446744073709551606, 8) = 18446744073709551608 2164 ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(18446744073709551598, 16) = 18446744073709551600 2165 ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(18446744073709551582, 32) = 18446744073709551584 2166 ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(18446744073709551550, 64) = 18446744073709551552 2167 ceiling(128, 128) = 128, ceiling(130, 128) = 256, ceiling(18446744073709551486, 128) = 18446744073709551488 2168 ceiling(256, 256) = 256, ceiling(258, 256) = 512, ceiling(18446744073709551358, 256) = 18446744073709551360 2169 ceiling(512, 512) = 512, ceiling(514, 512) = 1024, ceiling(18446744073709551102, 512) = 18446744073709551104 2170 ceiling(1024, 1024) = 1024, ceiling(1026, 1024) = 2048, ceiling(18446744073709550590, 1024) = 18446744073709550592 2171 ceiling(2048, 2048) = 2048, ceiling(2050, 2048) = 4096, ceiling(18446744073709549566, 2048) = 18446744073709549568 2172 ceiling(4096, 4096) = 4096, ceiling(4098, 4096) = 8192, ceiling(18446744073709547518, 4096) = 18446744073709547520 2173 ceiling(8192, 8192) = 8192, ceiling(8194, 8192) = 16384, ceiling(18446744073709543422, 8192) = 18446744073709543424 2174 ceiling(16384, 16384) = 16384, ceiling(16386, 16384) = 32768, ceiling(18446744073709535230, 16384) = 18446744073709535232 2175 ceiling(32768, 32768) = 32768, ceiling(32770, 32768) = 65536, ceiling(18446744073709518846, 32768) = 18446744073709518848 2176 ceiling(65536, 65536) = 65536, ceiling(65538, 65536) = 131072, ceiling(18446744073709486078, 65536) = 18446744073709486080 2177 ceiling(131072, 131072) = 131072, ceiling(131074, 131072) = 262144, ceiling(18446744073709420542, 131072) = 18446744073709420544 2178 ceiling(262144, 262144) = 262144, ceiling(262146, 262144) = 524288, ceiling(18446744073709289470, 262144) = 18446744073709289472 2179 ceiling(524288, 524288) = 524288, ceiling(524290, 524288) = 1048576, ceiling(18446744073709027326, 524288) = 18446744073709027328 2180 ceiling(1048576, 1048576) = 1048576, ceiling(1048578, 1048576) = 2097152, ceiling(18446744073708503038, 1048576) = 18446744073708503040 2181 ceiling(2097152, 2097152) = 2097152, ceiling(2097154, 2097152) = 4194304, ceiling(18446744073707454462, 2097152) = 18446744073707454464 2182 ceiling(4194304, 4194304) = 4194304, ceiling(4194306, 4194304) = 8388608, ceiling(18446744073705357310, 4194304) = 18446744073705357312 2183 ceiling(8388608, 8388608) = 8388608, ceiling(8388610, 8388608) = 16777216, ceiling(18446744073701163006, 8388608) = 18446744073701163008 2184 ceiling(16777216, 16777216) = 16777216, ceiling(16777218, 16777216) = 33554432, ceiling(18446744073692774398, 16777216) = 18446744073692774400 2185 ceiling(33554432, 33554432) = 33554432, ceiling(33554434, 33554432) = 67108864, ceiling(18446744073675997182, 33554432) = 18446744073675997184 2186 ceiling(67108864, 67108864) = 67108864, ceiling(67108866, 67108864) = 134217728, ceiling(18446744073642442750, 67108864) = 18446744073642442752 2187 ceiling(134217728, 134217728) = 134217728, ceiling(134217730, 134217728) = 268435456, ceiling(18446744073575333886, 134217728) = 18446744073575333888 2188 ceiling(268435456, 268435456) = 268435456, ceiling(268435458, 268435456) = 536870912, ceiling(18446744073441116158, 268435456) = 18446744073441116160 2189 ceiling(536870912, 536870912) = 536870912, ceiling(536870914, 536870912) = 1073741824, ceiling(18446744073172680702, 536870912) = 18446744073172680704 2190 ceiling(1073741824, 1073741824) = 1073741824, ceiling(1073741826, 1073741824) = 2147483648, ceiling(18446744072635809790, 1073741824) = 18446744072635809792 2191 ceiling(2147483648, 2147483648) = 2147483648, ceiling(2147483650, 2147483648) = 4294967296, ceiling(18446744071562067966, 2147483648) = 18446744071562067968 2192 ceiling(4294967296, 4294967296) = 4294967296, ceiling(4294967298, 4294967296) = 8589934592, ceiling(18446744069414584318, 4294967296) = 18446744069414584320 2193 ceiling(8589934592, 8589934592) = 8589934592, ceiling(8589934594, 8589934592) = 17179869184, ceiling(18446744065119617022, 8589934592) = 18446744065119617024 2194 ceiling(17179869184, 17179869184) = 17179869184, ceiling(17179869186, 17179869184) = 34359738368, ceiling(18446744056529682430, 17179869184) = 18446744056529682432 2195 ceiling(34359738368, 34359738368) = 34359738368, ceiling(34359738370, 34359738368) = 68719476736, ceiling(18446744039349813246, 34359738368) = 18446744039349813248 2196 ceiling(68719476736, 68719476736) = 68719476736, ceiling(68719476738, 68719476736) = 137438953472, ceiling(18446744004990074878, 68719476736) = 18446744004990074880 2197 ceiling(137438953472, 137438953472) = 137438953472, ceiling(137438953474, 137438953472) = 274877906944, ceiling(18446743936270598142, 137438953472) = 18446743936270598144 2198 ceiling(274877906944, 274877906944) = 274877906944, ceiling(274877906946, 274877906944) = 549755813888, ceiling(18446743798831644670, 274877906944) = 18446743798831644672 2199 ceiling(549755813888, 549755813888) = 549755813888, ceiling(549755813890, 549755813888) = 1099511627776, ceiling(18446743523953737726, 549755813888) = 18446743523953737728 2200 ceiling(1099511627776, 1099511627776) = 1099511627776, ceiling(1099511627778, 1099511627776) = 2199023255552, ceiling(18446742974197923838, 1099511627776) = 18446742974197923840 2201 ceiling(2199023255552, 2199023255552) = 2199023255552, ceiling(2199023255554, 2199023255552) = 4398046511104, ceiling(18446741874686296062, 2199023255552) = 18446741874686296064 2202 ceiling(4398046511104, 4398046511104) = 4398046511104, ceiling(4398046511106, 4398046511104) = 8796093022208, ceiling(18446739675663040510, 4398046511104) = 18446739675663040512 2203 ceiling(8796093022208, 8796093022208) = 8796093022208, ceiling(8796093022210, 8796093022208) = 17592186044416, ceiling(18446735277616529406, 8796093022208) = 18446735277616529408 2204 ceiling(17592186044416, 17592186044416) = 17592186044416, ceiling(17592186044418, 17592186044416) = 35184372088832, ceiling(18446726481523507198, 17592186044416) = 18446726481523507200 2205 ceiling(35184372088832, 35184372088832) = 35184372088832, ceiling(35184372088834, 35184372088832) = 70368744177664, ceiling(18446708889337462782, 35184372088832) = 18446708889337462784 2206 ceiling(70368744177664, 70368744177664) = 70368744177664, ceiling(70368744177666, 70368744177664) = 140737488355328, ceiling(18446673704965373950, 70368744177664) = 18446673704965373952 2207 ceiling(140737488355328, 140737488355328) = 140737488355328, ceiling(140737488355330, 140737488355328) = 281474976710656, ceiling(18446603336221196286, 140737488355328) = 18446603336221196288 2208 ceiling(281474976710656, 281474976710656) = 281474976710656, ceiling(281474976710658, 281474976710656) = 562949953421312, ceiling(18446462598732840958, 281474976710656) = 18446462598732840960 2209 ceiling(562949953421312, 562949953421312) = 562949953421312, ceiling(562949953421314, 562949953421312) = 1125899906842624, ceiling(18446181123756130302, 562949953421312) = 18446181123756130304 2210 ceiling(1125899906842624, 1125899906842624) = 1125899906842624, ceiling(1125899906842626, 1125899906842624) = 2251799813685248, ceiling(18445618173802708990, 1125899906842624) = 18445618173802708992 2211 ceiling(2251799813685248, 2251799813685248) = 2251799813685248, ceiling(2251799813685250, 2251799813685248) = 4503599627370496, ceiling(18444492273895866366, 2251799813685248) = 18444492273895866368 2212 ceiling(4503599627370496, 4503599627370496) = 4503599627370496, ceiling(4503599627370498, 4503599627370496) = 9007199254740992, ceiling(18442240474082181118, 4503599627370496) = 18442240474082181120 2213 ceiling(9007199254740992, 9007199254740992) = 9007199254740992, ceiling(9007199254740994, 9007199254740992) = 18014398509481984, ceiling(18437736874454810622, 9007199254740992) = 18437736874454810624 2214 ceiling(18014398509481984, 18014398509481984) = 18014398509481984, ceiling(18014398509481986, 18014398509481984) = 36028797018963968, ceiling(18428729675200069630, 18014398509481984) = 18428729675200069632 2215 ceiling(36028797018963968, 36028797018963968) = 36028797018963968, ceiling(36028797018963970, 36028797018963968) = 72057594037927936, ceiling(18410715276690587646, 36028797018963968) = 18410715276690587648 2216 ceiling(72057594037927936, 72057594037927936) = 72057594037927936, ceiling(72057594037927938, 72057594037927936) = 144115188075855872, ceiling(18374686479671623678, 72057594037927936) = 18374686479671623680 2217 ceiling(144115188075855872, 144115188075855872) = 144115188075855872, ceiling(144115188075855874, 144115188075855872) = 288230376151711744, ceiling(18302628885633695742, 144115188075855872) = 18302628885633695744 2218 ceiling(288230376151711744, 288230376151711744) = 288230376151711744, ceiling(288230376151711746, 288230376151711744) = 576460752303423488, ceiling(18158513697557839870, 288230376151711744) = 18158513697557839872 2219 ceiling(576460752303423488, 576460752303423488) = 576460752303423488, ceiling(576460752303423490, 576460752303423488) = 1152921504606846976, ceiling(17870283321406128126, 576460752303423488) = 17870283321406128128 2220 ceiling(1152921504606846976, 1152921504606846976) = 1152921504606846976, ceiling(1152921504606846978, 1152921504606846976) = 2305843009213693952, ceiling(17293822569102704638, 1152921504606846976) = 17293822569102704640 2221 ceiling(2305843009213693952, 2305843009213693952) = 2305843009213693952, ceiling(2305843009213693954, 2305843009213693952) = 4611686018427387904, ceiling(16140901064495857662, 2305843009213693952) = 16140901064495857664 2222 ceiling(4611686018427387904, 4611686018427387904) = 4611686018427387904, ceiling(4611686018427387906, 4611686018427387904) = 9223372036854775808, ceiling(13835058055282163710, 4611686018427387904) = 13835058055282163712 2223 ceiling(9223372036854775808, 9223372036854775808) = 9223372036854775808, ceiling(9223372036854775810, 9223372036854775808) = 0, ceiling(9223372036854775806, 9223372036854775808) = 9223372036854775808 1853 2224 1854 2225 long long int 1855 2226 ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(-3, 1) = -3 1856 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(-4, 2) = -11857 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(-6, 4) = 01858 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(-10, 8) = 01859 ceiling(16, 16) = 1 , ceiling(18, 16) =2, ceiling(-18, 16) = 01860 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(-34, 32) = 01861 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(-66, 64) = 01862 ceiling(128, 128) = 1 , ceiling(130, 128) = 2, ceiling(-130, 128) = 01863 ceiling(256, 256) = 1, ceiling(258, 256) =2, ceiling(-258, 256) = 01864 ceiling(512, 512) = 1, ceiling(514, 512) = 2, ceiling(-514, 512) = 01865 ceiling(1024, 1024) = 1 , ceiling(1026, 1024) = 2, ceiling(-1026, 1024) = 01866 ceiling(2048, 2048) = 1, ceiling(2050, 2048) = 2, ceiling(-2050, 2048) = 01867 ceiling(4096, 4096) = 1, ceiling(4098, 4096) =2, ceiling(-4098, 4096) = 01868 ceiling(8192, 8192) = 1, ceiling(8194, 8192) = 2, ceiling(-8194, 8192) = 01869 ceiling(16384, 16384) = 1 , ceiling(16386, 16384) = 2, ceiling(-16386, 16384) = 01870 ceiling(32768, 32768) = 1, ceiling(32770, 32768) = 2, ceiling(-32770, 32768) = 01871 ceiling(65536, 65536) = 1, ceiling(65538, 65536) =2, ceiling(-65538, 65536) = 01872 ceiling(131072, 131072) = 1 , ceiling(131074, 131072) = 2, ceiling(-131074, 131072) = 01873 ceiling(262144, 262144) = 1, ceiling(262146, 262144) = 2, ceiling(-262146, 262144) = 01874 ceiling(524288, 524288) = 1, ceiling(524290, 524288) = 2, ceiling(-524290, 524288) = 01875 ceiling(1048576, 1048576) = 1 , ceiling(1048578, 1048576) =2, ceiling(-1048578, 1048576) = 01876 ceiling(2097152, 2097152) = 1, ceiling(2097154, 2097152) = 2, ceiling(-2097154, 2097152) = 01877 ceiling(4194304, 4194304) = 1, ceiling(4194306, 4194304) = 2, ceiling(-4194306, 4194304) = 01878 ceiling(8388608, 8388608) = 1, ceiling(8388610, 8388608) = 2, ceiling(-8388610, 8388608) = 01879 ceiling(16777216, 16777216) = 1 , ceiling(16777218, 16777216) =2, ceiling(-16777218, 16777216) = 01880 ceiling(33554432, 33554432) = 1, ceiling(33554434, 33554432) = 2, ceiling(-33554434, 33554432) = 01881 ceiling(67108864, 67108864) = 1, ceiling(67108866, 67108864) = 2, ceiling(-67108866, 67108864) = 01882 ceiling(134217728, 134217728) = 1 , ceiling(134217730, 134217728) = 2, ceiling(-134217730, 134217728) = 01883 ceiling(268435456, 268435456) = 1, ceiling(268435458, 268435456) =2, ceiling(-268435458, 268435456) = 01884 ceiling(536870912, 536870912) = 1, ceiling(536870914, 536870912) = 2, ceiling(-536870914, 536870912) = 01885 ceiling(1073741824, 1073741824) = 1 , ceiling(1073741826, 1073741824) = 2, ceiling(-1073741826, 1073741824) = 01886 ceiling(2147483648, 2147483648) = 1, ceiling(2147483650, 2147483648) = 2, ceiling(-2147483650, 2147483648) = 01887 ceiling(4294967296, 4294967296) = 1, ceiling(4294967298, 4294967296) =2, ceiling(-4294967298, 4294967296) = 01888 ceiling(8589934592, 8589934592) = 1, ceiling(8589934594, 8589934592) = 2, ceiling(-8589934594, 8589934592) = 01889 ceiling(17179869184, 17179869184) = 1 , ceiling(17179869186, 17179869184) = 2, ceiling(-17179869186, 17179869184) = 01890 ceiling(34359738368, 34359738368) = 1, ceiling(34359738370, 34359738368) = 2, ceiling(-34359738370, 34359738368) = 01891 ceiling(68719476736, 68719476736) = 1, ceiling(68719476738, 68719476736) =2, ceiling(-68719476738, 68719476736) = 01892 ceiling(137438953472, 137438953472) = 1 , ceiling(137438953474, 137438953472) = 2, ceiling(-137438953474, 137438953472) = 01893 ceiling(274877906944, 274877906944) = 1, ceiling(274877906946, 274877906944) = 2, ceiling(-274877906946, 274877906944) = 01894 ceiling(549755813888, 549755813888) = 1, ceiling(549755813890, 549755813888) = 2, ceiling(-549755813890, 549755813888) = 01895 ceiling(1099511627776, 1099511627776) = 1 , ceiling(1099511627778, 1099511627776) =2, ceiling(-1099511627778, 1099511627776) = 01896 ceiling(2199023255552, 2199023255552) = 1, ceiling(2199023255554, 2199023255552) = 2, ceiling(-2199023255554, 2199023255552) = 01897 ceiling(4398046511104, 4398046511104) = 1, ceiling(4398046511106, 4398046511104) = 2, ceiling(-4398046511106, 4398046511104) = 01898 ceiling(8796093022208, 8796093022208) = 1, ceiling(8796093022210, 8796093022208) = 2, ceiling(-8796093022210, 8796093022208) = 01899 ceiling(17592186044416, 17592186044416) = 1 , ceiling(17592186044418, 17592186044416) =2, ceiling(-17592186044418, 17592186044416) = 01900 ceiling(35184372088832, 35184372088832) = 1, ceiling(35184372088834, 35184372088832) = 2, ceiling(-35184372088834, 35184372088832) = 01901 ceiling(70368744177664, 70368744177664) = 1, ceiling(70368744177666, 70368744177664) = 2, ceiling(-70368744177666, 70368744177664) = 01902 ceiling(140737488355328, 140737488355328) = 1 , ceiling(140737488355330, 140737488355328) = 2, ceiling(-140737488355330, 140737488355328) = 01903 ceiling(281474976710656, 281474976710656) = 1, ceiling(281474976710658, 281474976710656) =2, ceiling(-281474976710658, 281474976710656) = 01904 ceiling(562949953421312, 562949953421312) = 1, ceiling(562949953421314, 562949953421312) = 2, ceiling(-562949953421314, 562949953421312) = 01905 ceiling(1125899906842624, 1125899906842624) = 1 , ceiling(1125899906842626, 1125899906842624) = 2, ceiling(-1125899906842626, 1125899906842624) = 01906 ceiling(2251799813685248, 2251799813685248) = 1, ceiling(2251799813685250, 2251799813685248) = 2, ceiling(-2251799813685250, 2251799813685248) = 01907 ceiling(4503599627370496, 4503599627370496) = 1, ceiling(4503599627370498, 4503599627370496) =2, ceiling(-4503599627370498, 4503599627370496) = 01908 ceiling(9007199254740992, 9007199254740992) = 1, ceiling(9007199254740994, 9007199254740992) = 2, ceiling(-9007199254740994, 9007199254740992) = 01909 ceiling(18014398509481984, 18014398509481984) = 1 , ceiling(18014398509481986, 18014398509481984) = 2, ceiling(-18014398509481986, 18014398509481984) = 01910 ceiling(36028797018963968, 36028797018963968) = 1, ceiling(36028797018963970, 36028797018963968) = 2, ceiling(-36028797018963970, 36028797018963968) = 01911 ceiling(72057594037927936, 72057594037927936) = 1, ceiling(72057594037927938, 72057594037927936) =2, ceiling(-72057594037927938, 72057594037927936) = 01912 ceiling(144115188075855872, 144115188075855872) = 1 , ceiling(144115188075855874, 144115188075855872) = 2, ceiling(-144115188075855874, 144115188075855872) = 01913 ceiling(288230376151711744, 288230376151711744) = 1, ceiling(288230376151711746, 288230376151711744) = 2, ceiling(-288230376151711746, 288230376151711744) = 01914 ceiling(576460752303423488, 576460752303423488) = 1, ceiling(576460752303423490, 576460752303423488) = 2, ceiling(-576460752303423490, 576460752303423488) = 01915 ceiling(1152921504606846976, 1152921504606846976) = 1 , ceiling(1152921504606846978, 1152921504606846976) =2, ceiling(-1152921504606846978, 1152921504606846976) = 01916 ceiling(2305843009213693952, 2305843009213693952) = 1, ceiling(2305843009213693954, 2305843009213693952) = 2, ceiling(-2305843009213693954, 2305843009213693952) = 01917 ceiling(4611686018427387904, 4611686018427387904) = 1, ceiling(4611686018427387906, 4611686018427387904) = -1, ceiling(-4611686018427387906, 4611686018427387904) = 01918 ceiling(-9223372036854775808, -9223372036854775808) = 0, ceiling(-9223372036854775806, -9223372036854775808) = 0, ceiling(9223372036854775806, -9223372036854775808) = 02227 ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(-4, 2) = -4 2228 ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(-6, 4) = 0 2229 ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(-10, 8) = 0 2230 ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(-18, 16) = 0 2231 ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(-34, 32) = 0 2232 ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(-66, 64) = 0 2233 ceiling(128, 128) = 128, ceiling(130, 128) = 256, ceiling(-130, 128) = 0 2234 ceiling(256, 256) = 256, ceiling(258, 256) = 512, ceiling(-258, 256) = 0 2235 ceiling(512, 512) = 512, ceiling(514, 512) = 1024, ceiling(-514, 512) = 0 2236 ceiling(1024, 1024) = 1024, ceiling(1026, 1024) = 2048, ceiling(-1026, 1024) = 0 2237 ceiling(2048, 2048) = 2048, ceiling(2050, 2048) = 4096, ceiling(-2050, 2048) = 0 2238 ceiling(4096, 4096) = 4096, ceiling(4098, 4096) = 8192, ceiling(-4098, 4096) = 0 2239 ceiling(8192, 8192) = 8192, ceiling(8194, 8192) = 16384, ceiling(-8194, 8192) = 0 2240 ceiling(16384, 16384) = 16384, ceiling(16386, 16384) = 32768, ceiling(-16386, 16384) = 0 2241 ceiling(32768, 32768) = 32768, ceiling(32770, 32768) = 65536, ceiling(-32770, 32768) = 0 2242 ceiling(65536, 65536) = 65536, ceiling(65538, 65536) = 131072, ceiling(-65538, 65536) = 0 2243 ceiling(131072, 131072) = 131072, ceiling(131074, 131072) = 262144, ceiling(-131074, 131072) = 0 2244 ceiling(262144, 262144) = 262144, ceiling(262146, 262144) = 524288, ceiling(-262146, 262144) = 0 2245 ceiling(524288, 524288) = 524288, ceiling(524290, 524288) = 1048576, ceiling(-524290, 524288) = 0 2246 ceiling(1048576, 1048576) = 1048576, ceiling(1048578, 1048576) = 2097152, ceiling(-1048578, 1048576) = 0 2247 ceiling(2097152, 2097152) = 2097152, ceiling(2097154, 2097152) = 4194304, ceiling(-2097154, 2097152) = 0 2248 ceiling(4194304, 4194304) = 4194304, ceiling(4194306, 4194304) = 8388608, ceiling(-4194306, 4194304) = 0 2249 ceiling(8388608, 8388608) = 8388608, ceiling(8388610, 8388608) = 16777216, ceiling(-8388610, 8388608) = 0 2250 ceiling(16777216, 16777216) = 16777216, ceiling(16777218, 16777216) = 33554432, ceiling(-16777218, 16777216) = 0 2251 ceiling(33554432, 33554432) = 33554432, ceiling(33554434, 33554432) = 67108864, ceiling(-33554434, 33554432) = 0 2252 ceiling(67108864, 67108864) = 67108864, ceiling(67108866, 67108864) = 134217728, ceiling(-67108866, 67108864) = 0 2253 ceiling(134217728, 134217728) = 134217728, ceiling(134217730, 134217728) = 268435456, ceiling(-134217730, 134217728) = 0 2254 ceiling(268435456, 268435456) = 268435456, ceiling(268435458, 268435456) = 536870912, ceiling(-268435458, 268435456) = 0 2255 ceiling(536870912, 536870912) = 536870912, ceiling(536870914, 536870912) = 1073741824, ceiling(-536870914, 536870912) = 0 2256 ceiling(1073741824, 1073741824) = 1073741824, ceiling(1073741826, 1073741824) = 2147483648, ceiling(-1073741826, 1073741824) = 0 2257 ceiling(2147483648, 2147483648) = 2147483648, ceiling(2147483650, 2147483648) = 4294967296, ceiling(-2147483650, 2147483648) = 0 2258 ceiling(4294967296, 4294967296) = 4294967296, ceiling(4294967298, 4294967296) = 8589934592, ceiling(-4294967298, 4294967296) = 0 2259 ceiling(8589934592, 8589934592) = 8589934592, ceiling(8589934594, 8589934592) = 17179869184, ceiling(-8589934594, 8589934592) = 0 2260 ceiling(17179869184, 17179869184) = 17179869184, ceiling(17179869186, 17179869184) = 34359738368, ceiling(-17179869186, 17179869184) = 0 2261 ceiling(34359738368, 34359738368) = 34359738368, ceiling(34359738370, 34359738368) = 68719476736, ceiling(-34359738370, 34359738368) = 0 2262 ceiling(68719476736, 68719476736) = 68719476736, ceiling(68719476738, 68719476736) = 137438953472, ceiling(-68719476738, 68719476736) = 0 2263 ceiling(137438953472, 137438953472) = 137438953472, ceiling(137438953474, 137438953472) = 274877906944, ceiling(-137438953474, 137438953472) = 0 2264 ceiling(274877906944, 274877906944) = 274877906944, ceiling(274877906946, 274877906944) = 549755813888, ceiling(-274877906946, 274877906944) = 0 2265 ceiling(549755813888, 549755813888) = 549755813888, ceiling(549755813890, 549755813888) = 1099511627776, ceiling(-549755813890, 549755813888) = 0 2266 ceiling(1099511627776, 1099511627776) = 1099511627776, ceiling(1099511627778, 1099511627776) = 2199023255552, ceiling(-1099511627778, 1099511627776) = 0 2267 ceiling(2199023255552, 2199023255552) = 2199023255552, ceiling(2199023255554, 2199023255552) = 4398046511104, ceiling(-2199023255554, 2199023255552) = 0 2268 ceiling(4398046511104, 4398046511104) = 4398046511104, ceiling(4398046511106, 4398046511104) = 8796093022208, ceiling(-4398046511106, 4398046511104) = 0 2269 ceiling(8796093022208, 8796093022208) = 8796093022208, ceiling(8796093022210, 8796093022208) = 17592186044416, ceiling(-8796093022210, 8796093022208) = 0 2270 ceiling(17592186044416, 17592186044416) = 17592186044416, ceiling(17592186044418, 17592186044416) = 35184372088832, ceiling(-17592186044418, 17592186044416) = 0 2271 ceiling(35184372088832, 35184372088832) = 35184372088832, ceiling(35184372088834, 35184372088832) = 70368744177664, ceiling(-35184372088834, 35184372088832) = 0 2272 ceiling(70368744177664, 70368744177664) = 70368744177664, ceiling(70368744177666, 70368744177664) = 140737488355328, ceiling(-70368744177666, 70368744177664) = 0 2273 ceiling(140737488355328, 140737488355328) = 140737488355328, ceiling(140737488355330, 140737488355328) = 281474976710656, ceiling(-140737488355330, 140737488355328) = 0 2274 ceiling(281474976710656, 281474976710656) = 281474976710656, ceiling(281474976710658, 281474976710656) = 562949953421312, ceiling(-281474976710658, 281474976710656) = 0 2275 ceiling(562949953421312, 562949953421312) = 562949953421312, ceiling(562949953421314, 562949953421312) = 1125899906842624, ceiling(-562949953421314, 562949953421312) = 0 2276 ceiling(1125899906842624, 1125899906842624) = 1125899906842624, ceiling(1125899906842626, 1125899906842624) = 2251799813685248, ceiling(-1125899906842626, 1125899906842624) = 0 2277 ceiling(2251799813685248, 2251799813685248) = 2251799813685248, ceiling(2251799813685250, 2251799813685248) = 4503599627370496, ceiling(-2251799813685250, 2251799813685248) = 0 2278 ceiling(4503599627370496, 4503599627370496) = 4503599627370496, ceiling(4503599627370498, 4503599627370496) = 9007199254740992, ceiling(-4503599627370498, 4503599627370496) = 0 2279 ceiling(9007199254740992, 9007199254740992) = 9007199254740992, ceiling(9007199254740994, 9007199254740992) = 18014398509481984, ceiling(-9007199254740994, 9007199254740992) = 0 2280 ceiling(18014398509481984, 18014398509481984) = 18014398509481984, ceiling(18014398509481986, 18014398509481984) = 36028797018963968, ceiling(-18014398509481986, 18014398509481984) = 0 2281 ceiling(36028797018963968, 36028797018963968) = 36028797018963968, ceiling(36028797018963970, 36028797018963968) = 72057594037927936, ceiling(-36028797018963970, 36028797018963968) = 0 2282 ceiling(72057594037927936, 72057594037927936) = 72057594037927936, ceiling(72057594037927938, 72057594037927936) = 144115188075855872, ceiling(-72057594037927938, 72057594037927936) = 0 2283 ceiling(144115188075855872, 144115188075855872) = 144115188075855872, ceiling(144115188075855874, 144115188075855872) = 288230376151711744, ceiling(-144115188075855874, 144115188075855872) = 0 2284 ceiling(288230376151711744, 288230376151711744) = 288230376151711744, ceiling(288230376151711746, 288230376151711744) = 576460752303423488, ceiling(-288230376151711746, 288230376151711744) = 0 2285 ceiling(576460752303423488, 576460752303423488) = 576460752303423488, ceiling(576460752303423490, 576460752303423488) = 1152921504606846976, ceiling(-576460752303423490, 576460752303423488) = 0 2286 ceiling(1152921504606846976, 1152921504606846976) = 1152921504606846976, ceiling(1152921504606846978, 1152921504606846976) = 2305843009213693952, ceiling(-1152921504606846978, 1152921504606846976) = 0 2287 ceiling(2305843009213693952, 2305843009213693952) = 2305843009213693952, ceiling(2305843009213693954, 2305843009213693952) = 4611686018427387904, ceiling(-2305843009213693954, 2305843009213693952) = 0 2288 ceiling(4611686018427387904, 4611686018427387904) = 4611686018427387904, ceiling(4611686018427387906, 4611686018427387904) = -4611686018427387904, ceiling(-4611686018427387906, 4611686018427387904) = 0 2289 ceiling(-9223372036854775808, -9223372036854775808) = -9223372036854775808, ceiling(-9223372036854775806, -9223372036854775808) = 0, ceiling(9223372036854775806, -9223372036854775808) = 0 1919 2290 1920 2291 unsigned long long int 1921 2292 ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(18446744073709551613, 1) = 18446744073709551613 1922 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(18446744073709551612, 2) = 92233720368547758061923 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(18446744073709551610, 4) = 46116860184273879031924 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(18446744073709551606, 8) = 23058430092136939511925 ceiling(16, 16) = 1 , ceiling(18, 16) = 2, ceiling(18446744073709551598, 16) = 11529215046068469751926 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(18446744073709551582, 32) = 5764607523034234871927 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(18446744073709551550, 64) = 2882303761517117431928 ceiling(128, 128) = 1 , ceiling(130, 128) = 2, ceiling(18446744073709551486, 128) = 1441151880758558711929 ceiling(256, 256) = 1, ceiling(258, 256) = 2, ceiling(18446744073709551358, 256) = 720575940379279351930 ceiling(512, 512) = 1, ceiling(514, 512) = 2, ceiling(18446744073709551102, 512) = 360287970189639671931 ceiling(1024, 1024) = 1 , ceiling(1026, 1024) = 2, ceiling(18446744073709550590, 1024) = 180143985094819831932 ceiling(2048, 2048) = 1, ceiling(2050, 2048) = 2, ceiling(18446744073709549566, 2048) = 90071992547409911933 ceiling(4096, 4096) = 1, ceiling(4098, 4096) = 2, ceiling(18446744073709547518, 4096) = 45035996273704951934 ceiling(8192, 8192) = 1, ceiling(8194, 8192) = 2, ceiling(18446744073709543422, 8192) = 22517998136852471935 ceiling(16384, 16384) = 1 , ceiling(16386, 16384) = 2, ceiling(18446744073709535230, 16384) = 11258999068426231936 ceiling(32768, 32768) = 1, ceiling(32770, 32768) = 2, ceiling(18446744073709518846, 32768) = 5629499534213111937 ceiling(65536, 65536) = 1, ceiling(65538, 65536) = 2, ceiling(18446744073709486078, 65536) = 2814749767106551938 ceiling(131072, 131072) = 1 , ceiling(131074, 131072) = 2, ceiling(18446744073709420542, 131072) = 1407374883553271939 ceiling(262144, 262144) = 1, ceiling(262146, 262144) = 2, ceiling(18446744073709289470, 262144) = 703687441776631940 ceiling(524288, 524288) = 1, ceiling(524290, 524288) = 2, ceiling(18446744073709027326, 524288) = 351843720888311941 ceiling(1048576, 1048576) = 1 , ceiling(1048578, 1048576) = 2, ceiling(18446744073708503038, 1048576) = 175921860444151942 ceiling(2097152, 2097152) = 1, ceiling(2097154, 2097152) = 2, ceiling(18446744073707454462, 2097152) = 87960930222071943 ceiling(4194304, 4194304) = 1, ceiling(4194306, 4194304) = 2, ceiling(18446744073705357310, 4194304) = 43980465111031944 ceiling(8388608, 8388608) = 1, ceiling(8388610, 8388608) = 2, ceiling(18446744073701163006, 8388608) = 21990232555511945 ceiling(16777216, 16777216) = 1 , ceiling(16777218, 16777216) = 2, ceiling(18446744073692774398, 16777216) = 10995116277751946 ceiling(33554432, 33554432) = 1, ceiling(33554434, 33554432) = 2, ceiling(18446744073675997182, 33554432) = 5497558138871947 ceiling(67108864, 67108864) = 1, ceiling(67108866, 67108864) = 2, ceiling(18446744073642442750, 67108864) = 2748779069431948 ceiling(134217728, 134217728) = 1 , ceiling(134217730, 134217728) = 2, ceiling(18446744073575333886, 134217728) = 1374389534711949 ceiling(268435456, 268435456) = 1, ceiling(268435458, 268435456) = 2, ceiling(18446744073441116158, 268435456) = 687194767351950 ceiling(536870912, 536870912) = 1, ceiling(536870914, 536870912) = 2, ceiling(18446744073172680702, 536870912) = 343597383671951 ceiling(1073741824, 1073741824) = 1 , ceiling(1073741826, 1073741824) = 2, ceiling(18446744072635809790, 1073741824) = 171798691831952 ceiling(2147483648, 2147483648) = 1, ceiling(2147483650, 2147483648) = 2, ceiling(18446744071562067966, 2147483648) = 85899345911953 ceiling(4294967296, 4294967296) = 1, ceiling(4294967298, 4294967296) = 2, ceiling(18446744069414584318, 4294967296) = 42949672951954 ceiling(8589934592, 8589934592) = 1, ceiling(8589934594, 8589934592) = 2, ceiling(18446744065119617022, 8589934592) = 21474836471955 ceiling(17179869184, 17179869184) = 1 , ceiling(17179869186, 17179869184) = 2, ceiling(18446744056529682430, 17179869184) = 10737418231956 ceiling(34359738368, 34359738368) = 1, ceiling(34359738370, 34359738368) = 2, ceiling(18446744039349813246, 34359738368) = 5368709111957 ceiling(68719476736, 68719476736) = 1, ceiling(68719476738, 68719476736) = 2, ceiling(18446744004990074878, 68719476736) = 2684354551958 ceiling(137438953472, 137438953472) = 1 , ceiling(137438953474, 137438953472) = 2, ceiling(18446743936270598142, 137438953472) = 1342177271959 ceiling(274877906944, 274877906944) = 1, ceiling(274877906946, 274877906944) = 2, ceiling(18446743798831644670, 274877906944) = 671088631960 ceiling(549755813888, 549755813888) = 1, ceiling(549755813890, 549755813888) = 2, ceiling(18446743523953737726, 549755813888) = 335544311961 ceiling(1099511627776, 1099511627776) = 1 , ceiling(1099511627778, 1099511627776) = 2, ceiling(18446742974197923838, 1099511627776) = 167772151962 ceiling(2199023255552, 2199023255552) = 1, ceiling(2199023255554, 2199023255552) = 2, ceiling(18446741874686296062, 2199023255552) = 83886071963 ceiling(4398046511104, 4398046511104) = 1, ceiling(4398046511106, 4398046511104) = 2, ceiling(18446739675663040510, 4398046511104) = 41943031964 ceiling(8796093022208, 8796093022208) = 1, ceiling(8796093022210, 8796093022208) = 2, ceiling(18446735277616529406, 8796093022208) = 20971511965 ceiling(17592186044416, 17592186044416) = 1 , ceiling(17592186044418, 17592186044416) = 2, ceiling(18446726481523507198, 17592186044416) = 10485751966 ceiling(35184372088832, 35184372088832) = 1, ceiling(35184372088834, 35184372088832) = 2, ceiling(18446708889337462782, 35184372088832) = 5242871967 ceiling(70368744177664, 70368744177664) = 1, ceiling(70368744177666, 70368744177664) = 2, ceiling(18446673704965373950, 70368744177664) = 2621431968 ceiling(140737488355328, 140737488355328) = 1 , ceiling(140737488355330, 140737488355328) = 2, ceiling(18446603336221196286, 140737488355328) = 1310711969 ceiling(281474976710656, 281474976710656) = 1, ceiling(281474976710658, 281474976710656) = 2, ceiling(18446462598732840958, 281474976710656) = 655351970 ceiling(562949953421312, 562949953421312) = 1, ceiling(562949953421314, 562949953421312) = 2, ceiling(18446181123756130302, 562949953421312) = 327671971 ceiling(1125899906842624, 1125899906842624) = 1 , ceiling(1125899906842626, 1125899906842624) = 2, ceiling(18445618173802708990, 1125899906842624) = 163831972 ceiling(2251799813685248, 2251799813685248) = 1, ceiling(2251799813685250, 2251799813685248) = 2, ceiling(18444492273895866366, 2251799813685248) = 81911973 ceiling(4503599627370496, 4503599627370496) = 1, ceiling(4503599627370498, 4503599627370496) = 2, ceiling(18442240474082181118, 4503599627370496) = 40951974 ceiling(9007199254740992, 9007199254740992) = 1, ceiling(9007199254740994, 9007199254740992) = 2, ceiling(18437736874454810622, 9007199254740992) = 20471975 ceiling(18014398509481984, 18014398509481984) = 1 , ceiling(18014398509481986, 18014398509481984) = 2, ceiling(18428729675200069630, 18014398509481984) = 10231976 ceiling(36028797018963968, 36028797018963968) = 1, ceiling(36028797018963970, 36028797018963968) = 2, ceiling(18410715276690587646, 36028797018963968) = 5111977 ceiling(72057594037927936, 72057594037927936) = 1, ceiling(72057594037927938, 72057594037927936) = 2, ceiling(18374686479671623678, 72057594037927936) = 2551978 ceiling(144115188075855872, 144115188075855872) = 1 , ceiling(144115188075855874, 144115188075855872) = 2, ceiling(18302628885633695742, 144115188075855872) = 1271979 ceiling(288230376151711744, 288230376151711744) = 1, ceiling(288230376151711746, 288230376151711744) = 2, ceiling(18158513697557839870, 288230376151711744) = 631980 ceiling(576460752303423488, 576460752303423488) = 1, ceiling(576460752303423490, 576460752303423488) = 2, ceiling(17870283321406128126, 576460752303423488) = 311981 ceiling(1152921504606846976, 1152921504606846976) = 1 , ceiling(1152921504606846978, 1152921504606846976) = 2, ceiling(17293822569102704638, 1152921504606846976) = 151982 ceiling(2305843009213693952, 2305843009213693952) = 1, ceiling(2305843009213693954, 2305843009213693952) = 2, ceiling(16140901064495857662, 2305843009213693952) = 71983 ceiling(4611686018427387904, 4611686018427387904) = 1, ceiling(4611686018427387906, 4611686018427387904) = 2, ceiling(13835058055282163710, 4611686018427387904) = 31984 ceiling(9223372036854775808, 9223372036854775808) = 1, ceiling(9223372036854775810, 9223372036854775808) = 0, ceiling(9223372036854775806, 9223372036854775808) = 11985 2293 ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(18446744073709551612, 2) = 18446744073709551612 2294 ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(18446744073709551610, 4) = 18446744073709551612 2295 ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(18446744073709551606, 8) = 18446744073709551608 2296 ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(18446744073709551598, 16) = 18446744073709551600 2297 ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(18446744073709551582, 32) = 18446744073709551584 2298 ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(18446744073709551550, 64) = 18446744073709551552 2299 ceiling(128, 128) = 128, ceiling(130, 128) = 256, ceiling(18446744073709551486, 128) = 18446744073709551488 2300 ceiling(256, 256) = 256, ceiling(258, 256) = 512, ceiling(18446744073709551358, 256) = 18446744073709551360 2301 ceiling(512, 512) = 512, ceiling(514, 512) = 1024, ceiling(18446744073709551102, 512) = 18446744073709551104 2302 ceiling(1024, 1024) = 1024, ceiling(1026, 1024) = 2048, ceiling(18446744073709550590, 1024) = 18446744073709550592 2303 ceiling(2048, 2048) = 2048, ceiling(2050, 2048) = 4096, ceiling(18446744073709549566, 2048) = 18446744073709549568 2304 ceiling(4096, 4096) = 4096, ceiling(4098, 4096) = 8192, ceiling(18446744073709547518, 4096) = 18446744073709547520 2305 ceiling(8192, 8192) = 8192, ceiling(8194, 8192) = 16384, ceiling(18446744073709543422, 8192) = 18446744073709543424 2306 ceiling(16384, 16384) = 16384, ceiling(16386, 16384) = 32768, ceiling(18446744073709535230, 16384) = 18446744073709535232 2307 ceiling(32768, 32768) = 32768, ceiling(32770, 32768) = 65536, ceiling(18446744073709518846, 32768) = 18446744073709518848 2308 ceiling(65536, 65536) = 65536, ceiling(65538, 65536) = 131072, ceiling(18446744073709486078, 65536) = 18446744073709486080 2309 ceiling(131072, 131072) = 131072, ceiling(131074, 131072) = 262144, ceiling(18446744073709420542, 131072) = 18446744073709420544 2310 ceiling(262144, 262144) = 262144, ceiling(262146, 262144) = 524288, ceiling(18446744073709289470, 262144) = 18446744073709289472 2311 ceiling(524288, 524288) = 524288, ceiling(524290, 524288) = 1048576, ceiling(18446744073709027326, 524288) = 18446744073709027328 2312 ceiling(1048576, 1048576) = 1048576, ceiling(1048578, 1048576) = 2097152, ceiling(18446744073708503038, 1048576) = 18446744073708503040 2313 ceiling(2097152, 2097152) = 2097152, ceiling(2097154, 2097152) = 4194304, ceiling(18446744073707454462, 2097152) = 18446744073707454464 2314 ceiling(4194304, 4194304) = 4194304, ceiling(4194306, 4194304) = 8388608, ceiling(18446744073705357310, 4194304) = 18446744073705357312 2315 ceiling(8388608, 8388608) = 8388608, ceiling(8388610, 8388608) = 16777216, ceiling(18446744073701163006, 8388608) = 18446744073701163008 2316 ceiling(16777216, 16777216) = 16777216, ceiling(16777218, 16777216) = 33554432, ceiling(18446744073692774398, 16777216) = 18446744073692774400 2317 ceiling(33554432, 33554432) = 33554432, ceiling(33554434, 33554432) = 67108864, ceiling(18446744073675997182, 33554432) = 18446744073675997184 2318 ceiling(67108864, 67108864) = 67108864, ceiling(67108866, 67108864) = 134217728, ceiling(18446744073642442750, 67108864) = 18446744073642442752 2319 ceiling(134217728, 134217728) = 134217728, ceiling(134217730, 134217728) = 268435456, ceiling(18446744073575333886, 134217728) = 18446744073575333888 2320 ceiling(268435456, 268435456) = 268435456, ceiling(268435458, 268435456) = 536870912, ceiling(18446744073441116158, 268435456) = 18446744073441116160 2321 ceiling(536870912, 536870912) = 536870912, ceiling(536870914, 536870912) = 1073741824, ceiling(18446744073172680702, 536870912) = 18446744073172680704 2322 ceiling(1073741824, 1073741824) = 1073741824, ceiling(1073741826, 1073741824) = 2147483648, ceiling(18446744072635809790, 1073741824) = 18446744072635809792 2323 ceiling(2147483648, 2147483648) = 2147483648, ceiling(2147483650, 2147483648) = 4294967296, ceiling(18446744071562067966, 2147483648) = 18446744071562067968 2324 ceiling(4294967296, 4294967296) = 4294967296, ceiling(4294967298, 4294967296) = 8589934592, ceiling(18446744069414584318, 4294967296) = 18446744069414584320 2325 ceiling(8589934592, 8589934592) = 8589934592, ceiling(8589934594, 8589934592) = 17179869184, ceiling(18446744065119617022, 8589934592) = 18446744065119617024 2326 ceiling(17179869184, 17179869184) = 17179869184, ceiling(17179869186, 17179869184) = 34359738368, ceiling(18446744056529682430, 17179869184) = 18446744056529682432 2327 ceiling(34359738368, 34359738368) = 34359738368, ceiling(34359738370, 34359738368) = 68719476736, ceiling(18446744039349813246, 34359738368) = 18446744039349813248 2328 ceiling(68719476736, 68719476736) = 68719476736, ceiling(68719476738, 68719476736) = 137438953472, ceiling(18446744004990074878, 68719476736) = 18446744004990074880 2329 ceiling(137438953472, 137438953472) = 137438953472, ceiling(137438953474, 137438953472) = 274877906944, ceiling(18446743936270598142, 137438953472) = 18446743936270598144 2330 ceiling(274877906944, 274877906944) = 274877906944, ceiling(274877906946, 274877906944) = 549755813888, ceiling(18446743798831644670, 274877906944) = 18446743798831644672 2331 ceiling(549755813888, 549755813888) = 549755813888, ceiling(549755813890, 549755813888) = 1099511627776, ceiling(18446743523953737726, 549755813888) = 18446743523953737728 2332 ceiling(1099511627776, 1099511627776) = 1099511627776, ceiling(1099511627778, 1099511627776) = 2199023255552, ceiling(18446742974197923838, 1099511627776) = 18446742974197923840 2333 ceiling(2199023255552, 2199023255552) = 2199023255552, ceiling(2199023255554, 2199023255552) = 4398046511104, ceiling(18446741874686296062, 2199023255552) = 18446741874686296064 2334 ceiling(4398046511104, 4398046511104) = 4398046511104, ceiling(4398046511106, 4398046511104) = 8796093022208, ceiling(18446739675663040510, 4398046511104) = 18446739675663040512 2335 ceiling(8796093022208, 8796093022208) = 8796093022208, ceiling(8796093022210, 8796093022208) = 17592186044416, ceiling(18446735277616529406, 8796093022208) = 18446735277616529408 2336 ceiling(17592186044416, 17592186044416) = 17592186044416, ceiling(17592186044418, 17592186044416) = 35184372088832, ceiling(18446726481523507198, 17592186044416) = 18446726481523507200 2337 ceiling(35184372088832, 35184372088832) = 35184372088832, ceiling(35184372088834, 35184372088832) = 70368744177664, ceiling(18446708889337462782, 35184372088832) = 18446708889337462784 2338 ceiling(70368744177664, 70368744177664) = 70368744177664, ceiling(70368744177666, 70368744177664) = 140737488355328, ceiling(18446673704965373950, 70368744177664) = 18446673704965373952 2339 ceiling(140737488355328, 140737488355328) = 140737488355328, ceiling(140737488355330, 140737488355328) = 281474976710656, ceiling(18446603336221196286, 140737488355328) = 18446603336221196288 2340 ceiling(281474976710656, 281474976710656) = 281474976710656, ceiling(281474976710658, 281474976710656) = 562949953421312, ceiling(18446462598732840958, 281474976710656) = 18446462598732840960 2341 ceiling(562949953421312, 562949953421312) = 562949953421312, ceiling(562949953421314, 562949953421312) = 1125899906842624, ceiling(18446181123756130302, 562949953421312) = 18446181123756130304 2342 ceiling(1125899906842624, 1125899906842624) = 1125899906842624, ceiling(1125899906842626, 1125899906842624) = 2251799813685248, ceiling(18445618173802708990, 1125899906842624) = 18445618173802708992 2343 ceiling(2251799813685248, 2251799813685248) = 2251799813685248, ceiling(2251799813685250, 2251799813685248) = 4503599627370496, ceiling(18444492273895866366, 2251799813685248) = 18444492273895866368 2344 ceiling(4503599627370496, 4503599627370496) = 4503599627370496, ceiling(4503599627370498, 4503599627370496) = 9007199254740992, ceiling(18442240474082181118, 4503599627370496) = 18442240474082181120 2345 ceiling(9007199254740992, 9007199254740992) = 9007199254740992, ceiling(9007199254740994, 9007199254740992) = 18014398509481984, ceiling(18437736874454810622, 9007199254740992) = 18437736874454810624 2346 ceiling(18014398509481984, 18014398509481984) = 18014398509481984, ceiling(18014398509481986, 18014398509481984) = 36028797018963968, ceiling(18428729675200069630, 18014398509481984) = 18428729675200069632 2347 ceiling(36028797018963968, 36028797018963968) = 36028797018963968, ceiling(36028797018963970, 36028797018963968) = 72057594037927936, ceiling(18410715276690587646, 36028797018963968) = 18410715276690587648 2348 ceiling(72057594037927936, 72057594037927936) = 72057594037927936, ceiling(72057594037927938, 72057594037927936) = 144115188075855872, ceiling(18374686479671623678, 72057594037927936) = 18374686479671623680 2349 ceiling(144115188075855872, 144115188075855872) = 144115188075855872, ceiling(144115188075855874, 144115188075855872) = 288230376151711744, ceiling(18302628885633695742, 144115188075855872) = 18302628885633695744 2350 ceiling(288230376151711744, 288230376151711744) = 288230376151711744, ceiling(288230376151711746, 288230376151711744) = 576460752303423488, ceiling(18158513697557839870, 288230376151711744) = 18158513697557839872 2351 ceiling(576460752303423488, 576460752303423488) = 576460752303423488, ceiling(576460752303423490, 576460752303423488) = 1152921504606846976, ceiling(17870283321406128126, 576460752303423488) = 17870283321406128128 2352 ceiling(1152921504606846976, 1152921504606846976) = 1152921504606846976, ceiling(1152921504606846978, 1152921504606846976) = 2305843009213693952, ceiling(17293822569102704638, 1152921504606846976) = 17293822569102704640 2353 ceiling(2305843009213693952, 2305843009213693952) = 2305843009213693952, ceiling(2305843009213693954, 2305843009213693952) = 4611686018427387904, ceiling(16140901064495857662, 2305843009213693952) = 16140901064495857664 2354 ceiling(4611686018427387904, 4611686018427387904) = 4611686018427387904, ceiling(4611686018427387906, 4611686018427387904) = 9223372036854775808, ceiling(13835058055282163710, 4611686018427387904) = 13835058055282163712 2355 ceiling(9223372036854775808, 9223372036854775808) = 9223372036854775808, ceiling(9223372036854775810, 9223372036854775808) = 0, ceiling(9223372036854775806, 9223372036854775808) = 9223372036854775808 2356 -
tests/.expect/bitmanip3.x86.txt
r07d867b r22f94a4 340 340 341 341 signed char 342 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(-2, 0) = 0343 342 floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(-3, 1) = -3 344 343 floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(-4, 2) = -4 … … 351 350 352 351 unsigned char 353 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(254, 0) = 0354 352 floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(253, 1) = 253 355 353 floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(252, 2) = 252 … … 362 360 363 361 short int 364 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(-2, 0) = 0365 362 floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(-3, 1) = -3 366 363 floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(-4, 2) = -4 … … 381 378 382 379 unsigned short int 383 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(65534, 0) = 0384 380 floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(65533, 1) = 65533 385 381 floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(65532, 2) = 65532 … … 400 396 401 397 int 402 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(-2, 0) = 0403 398 floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(-3, 1) = -3 404 399 floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(-4, 2) = -4 … … 435 430 436 431 unsigned int 437 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(4294967294, 0) = 0438 432 floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(4294967293, 1) = 4294967293 439 433 floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(4294967292, 2) = 4294967292 … … 470 464 471 465 long int 472 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(-2, 0) = 0473 466 floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(-3, 1) = -3 474 467 floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(-4, 2) = -4 … … 505 498 506 499 unsigned long int 507 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(4294967294, 0) = 0508 500 floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(4294967293, 1) = 4294967293 509 501 floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(4294967292, 2) = 4294967292 … … 540 532 541 533 long long int 542 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(-2, 0) = 0543 534 floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(-3, 1) = -3 544 535 floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(-4, 2) = -4 … … 607 598 608 599 unsigned long long int 609 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(18446744073709551614, 0) = 0610 600 floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(18446744073709551613, 1) = 18446744073709551613 611 601 floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(18446744073709551612, 2) = 18446744073709551612 … … 1004 994 1005 995 signed char 1006 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(-2, 0) = 01007 996 ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(-3, 1) = -3 1008 997 ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(-4, 2) = -4 … … 1015 1004 1016 1005 unsigned char 1017 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(254, 0) = 01018 1006 ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(253, 1) = 253 1019 1007 ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(252, 2) = 252 … … 1026 1014 1027 1015 short int 1028 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(-2, 0) = 01029 1016 ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(-3, 1) = -3 1030 1017 ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(-4, 2) = -4 … … 1045 1032 1046 1033 unsigned short int 1047 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(65534, 0) = 01048 1034 ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(65533, 1) = 65533 1049 1035 ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(65532, 2) = 65532 … … 1064 1050 1065 1051 int 1066 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(-2, 0) = 01067 1052 ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(-3, 1) = -3 1068 1053 ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(-4, 2) = -4 … … 1099 1084 1100 1085 unsigned int 1101 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(4294967294, 0) = 01102 1086 ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(4294967293, 1) = 4294967293 1103 1087 ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(4294967292, 2) = 4294967292 … … 1134 1118 1135 1119 long int 1136 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(-2, 0) = 01137 1120 ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(-3, 1) = -3 1138 1121 ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(-4, 2) = -4 … … 1169 1152 1170 1153 unsigned long int 1171 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(4294967294, 0) = 01172 1154 ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(4294967293, 1) = 4294967293 1173 1155 ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(4294967292, 2) = 4294967292 … … 1204 1186 1205 1187 long long int 1206 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(-2, 0) = 01207 1188 ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(-3, 1) = -3 1208 1189 ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(-4, 2) = -4 … … 1271 1252 1272 1253 unsigned long long int 1273 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(18446744073709551614, 0) = 01274 1254 ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(18446744073709551613, 1) = 18446744073709551613 1275 1255 ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(18446744073709551612, 2) = 18446744073709551612 … … 1338 1318 1339 1319 1320 ceiling_div 1321 1322 signed char 1323 ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(-3, 1) = -3 1324 ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(-4, 2) = -1 1325 ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(-6, 4) = 0 1326 ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(-10, 8) = 0 1327 ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(-18, 16) = 0 1328 ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(-34, 32) = 0 1329 ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(-66, 64) = 0 1330 ceiling_div(-128, -128) = 2, ceiling_div(-126, -128) = 1, ceiling_div(126, -128) = 0 1331 1332 unsigned char 1333 ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(253, 1) = 253 1334 ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(252, 2) = 126 1335 ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(250, 4) = 63 1336 ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(246, 8) = 31 1337 ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(238, 16) = 15 1338 ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(222, 32) = 7 1339 ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(190, 64) = 3 1340 ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(126, 128) = 1 1341 1342 short int 1343 ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(-3, 1) = -3 1344 ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(-4, 2) = -1 1345 ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(-6, 4) = 0 1346 ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(-10, 8) = 0 1347 ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(-18, 16) = 0 1348 ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(-34, 32) = 0 1349 ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(-66, 64) = 0 1350 ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(-130, 128) = 0 1351 ceiling_div(256, 256) = 1, ceiling_div(258, 256) = 2, ceiling_div(-258, 256) = 0 1352 ceiling_div(512, 512) = 1, ceiling_div(514, 512) = 2, ceiling_div(-514, 512) = 0 1353 ceiling_div(1024, 1024) = 1, ceiling_div(1026, 1024) = 2, ceiling_div(-1026, 1024) = 0 1354 ceiling_div(2048, 2048) = 1, ceiling_div(2050, 2048) = 2, ceiling_div(-2050, 2048) = 0 1355 ceiling_div(4096, 4096) = 1, ceiling_div(4098, 4096) = 2, ceiling_div(-4098, 4096) = 0 1356 ceiling_div(8192, 8192) = 1, ceiling_div(8194, 8192) = 2, ceiling_div(-8194, 8192) = 0 1357 ceiling_div(16384, 16384) = 1, ceiling_div(16386, 16384) = 2, ceiling_div(-16386, 16384) = 0 1358 ceiling_div(-32768, -32768) = 2, ceiling_div(-32766, -32768) = 1, ceiling_div(32766, -32768) = 0 1359 1360 unsigned short int 1361 ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(65533, 1) = 65533 1362 ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(65532, 2) = 32766 1363 ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(65530, 4) = 16383 1364 ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(65526, 8) = 8191 1365 ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(65518, 16) = 4095 1366 ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(65502, 32) = 2047 1367 ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(65470, 64) = 1023 1368 ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(65406, 128) = 511 1369 ceiling_div(256, 256) = 1, ceiling_div(258, 256) = 2, ceiling_div(65278, 256) = 255 1370 ceiling_div(512, 512) = 1, ceiling_div(514, 512) = 2, ceiling_div(65022, 512) = 127 1371 ceiling_div(1024, 1024) = 1, ceiling_div(1026, 1024) = 2, ceiling_div(64510, 1024) = 63 1372 ceiling_div(2048, 2048) = 1, ceiling_div(2050, 2048) = 2, ceiling_div(63486, 2048) = 31 1373 ceiling_div(4096, 4096) = 1, ceiling_div(4098, 4096) = 2, ceiling_div(61438, 4096) = 15 1374 ceiling_div(8192, 8192) = 1, ceiling_div(8194, 8192) = 2, ceiling_div(57342, 8192) = 7 1375 ceiling_div(16384, 16384) = 1, ceiling_div(16386, 16384) = 2, ceiling_div(49150, 16384) = 3 1376 ceiling_div(32768, 32768) = 1, ceiling_div(32770, 32768) = 2, ceiling_div(32766, 32768) = 1 1377 1378 int 1379 ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(-3, 1) = -3 1380 ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(-4, 2) = -1 1381 ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(-6, 4) = 0 1382 ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(-10, 8) = 0 1383 ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(-18, 16) = 0 1384 ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(-34, 32) = 0 1385 ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(-66, 64) = 0 1386 ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(-130, 128) = 0 1387 ceiling_div(256, 256) = 1, ceiling_div(258, 256) = 2, ceiling_div(-258, 256) = 0 1388 ceiling_div(512, 512) = 1, ceiling_div(514, 512) = 2, ceiling_div(-514, 512) = 0 1389 ceiling_div(1024, 1024) = 1, ceiling_div(1026, 1024) = 2, ceiling_div(-1026, 1024) = 0 1390 ceiling_div(2048, 2048) = 1, ceiling_div(2050, 2048) = 2, ceiling_div(-2050, 2048) = 0 1391 ceiling_div(4096, 4096) = 1, ceiling_div(4098, 4096) = 2, ceiling_div(-4098, 4096) = 0 1392 ceiling_div(8192, 8192) = 1, ceiling_div(8194, 8192) = 2, ceiling_div(-8194, 8192) = 0 1393 ceiling_div(16384, 16384) = 1, ceiling_div(16386, 16384) = 2, ceiling_div(-16386, 16384) = 0 1394 ceiling_div(32768, 32768) = 1, ceiling_div(32770, 32768) = 2, ceiling_div(-32770, 32768) = 0 1395 ceiling_div(65536, 65536) = 1, ceiling_div(65538, 65536) = 2, ceiling_div(-65538, 65536) = 0 1396 ceiling_div(131072, 131072) = 1, ceiling_div(131074, 131072) = 2, ceiling_div(-131074, 131072) = 0 1397 ceiling_div(262144, 262144) = 1, ceiling_div(262146, 262144) = 2, ceiling_div(-262146, 262144) = 0 1398 ceiling_div(524288, 524288) = 1, ceiling_div(524290, 524288) = 2, ceiling_div(-524290, 524288) = 0 1399 ceiling_div(1048576, 1048576) = 1, ceiling_div(1048578, 1048576) = 2, ceiling_div(-1048578, 1048576) = 0 1400 ceiling_div(2097152, 2097152) = 1, ceiling_div(2097154, 2097152) = 2, ceiling_div(-2097154, 2097152) = 0 1401 ceiling_div(4194304, 4194304) = 1, ceiling_div(4194306, 4194304) = 2, ceiling_div(-4194306, 4194304) = 0 1402 ceiling_div(8388608, 8388608) = 1, ceiling_div(8388610, 8388608) = 2, ceiling_div(-8388610, 8388608) = 0 1403 ceiling_div(16777216, 16777216) = 1, ceiling_div(16777218, 16777216) = 2, ceiling_div(-16777218, 16777216) = 0 1404 ceiling_div(33554432, 33554432) = 1, ceiling_div(33554434, 33554432) = 2, ceiling_div(-33554434, 33554432) = 0 1405 ceiling_div(67108864, 67108864) = 1, ceiling_div(67108866, 67108864) = 2, ceiling_div(-67108866, 67108864) = 0 1406 ceiling_div(134217728, 134217728) = 1, ceiling_div(134217730, 134217728) = 2, ceiling_div(-134217730, 134217728) = 0 1407 ceiling_div(268435456, 268435456) = 1, ceiling_div(268435458, 268435456) = 2, ceiling_div(-268435458, 268435456) = 0 1408 ceiling_div(536870912, 536870912) = 1, ceiling_div(536870914, 536870912) = 2, ceiling_div(-536870914, 536870912) = 0 1409 ceiling_div(1073741824, 1073741824) = 1, ceiling_div(1073741826, 1073741824) = -1, ceiling_div(-1073741826, 1073741824) = 0 1410 ceiling_div(-2147483648, -2147483648) = 0, ceiling_div(-2147483646, -2147483648) = 0, ceiling_div(2147483646, -2147483648) = 0 1411 1412 unsigned int 1413 ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(4294967293, 1) = 4294967293 1414 ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(4294967292, 2) = 2147483646 1415 ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(4294967290, 4) = 1073741823 1416 ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(4294967286, 8) = 536870911 1417 ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(4294967278, 16) = 268435455 1418 ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(4294967262, 32) = 134217727 1419 ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(4294967230, 64) = 67108863 1420 ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(4294967166, 128) = 33554431 1421 ceiling_div(256, 256) = 1, ceiling_div(258, 256) = 2, ceiling_div(4294967038, 256) = 16777215 1422 ceiling_div(512, 512) = 1, ceiling_div(514, 512) = 2, ceiling_div(4294966782, 512) = 8388607 1423 ceiling_div(1024, 1024) = 1, ceiling_div(1026, 1024) = 2, ceiling_div(4294966270, 1024) = 4194303 1424 ceiling_div(2048, 2048) = 1, ceiling_div(2050, 2048) = 2, ceiling_div(4294965246, 2048) = 2097151 1425 ceiling_div(4096, 4096) = 1, ceiling_div(4098, 4096) = 2, ceiling_div(4294963198, 4096) = 1048575 1426 ceiling_div(8192, 8192) = 1, ceiling_div(8194, 8192) = 2, ceiling_div(4294959102, 8192) = 524287 1427 ceiling_div(16384, 16384) = 1, ceiling_div(16386, 16384) = 2, ceiling_div(4294950910, 16384) = 262143 1428 ceiling_div(32768, 32768) = 1, ceiling_div(32770, 32768) = 2, ceiling_div(4294934526, 32768) = 131071 1429 ceiling_div(65536, 65536) = 1, ceiling_div(65538, 65536) = 2, ceiling_div(4294901758, 65536) = 65535 1430 ceiling_div(131072, 131072) = 1, ceiling_div(131074, 131072) = 2, ceiling_div(4294836222, 131072) = 32767 1431 ceiling_div(262144, 262144) = 1, ceiling_div(262146, 262144) = 2, ceiling_div(4294705150, 262144) = 16383 1432 ceiling_div(524288, 524288) = 1, ceiling_div(524290, 524288) = 2, ceiling_div(4294443006, 524288) = 8191 1433 ceiling_div(1048576, 1048576) = 1, ceiling_div(1048578, 1048576) = 2, ceiling_div(4293918718, 1048576) = 4095 1434 ceiling_div(2097152, 2097152) = 1, ceiling_div(2097154, 2097152) = 2, ceiling_div(4292870142, 2097152) = 2047 1435 ceiling_div(4194304, 4194304) = 1, ceiling_div(4194306, 4194304) = 2, ceiling_div(4290772990, 4194304) = 1023 1436 ceiling_div(8388608, 8388608) = 1, ceiling_div(8388610, 8388608) = 2, ceiling_div(4286578686, 8388608) = 511 1437 ceiling_div(16777216, 16777216) = 1, ceiling_div(16777218, 16777216) = 2, ceiling_div(4278190078, 16777216) = 255 1438 ceiling_div(33554432, 33554432) = 1, ceiling_div(33554434, 33554432) = 2, ceiling_div(4261412862, 33554432) = 127 1439 ceiling_div(67108864, 67108864) = 1, ceiling_div(67108866, 67108864) = 2, ceiling_div(4227858430, 67108864) = 63 1440 ceiling_div(134217728, 134217728) = 1, ceiling_div(134217730, 134217728) = 2, ceiling_div(4160749566, 134217728) = 31 1441 ceiling_div(268435456, 268435456) = 1, ceiling_div(268435458, 268435456) = 2, ceiling_div(4026531838, 268435456) = 15 1442 ceiling_div(536870912, 536870912) = 1, ceiling_div(536870914, 536870912) = 2, ceiling_div(3758096382, 536870912) = 7 1443 ceiling_div(1073741824, 1073741824) = 1, ceiling_div(1073741826, 1073741824) = 2, ceiling_div(3221225470, 1073741824) = 3 1444 ceiling_div(2147483648, 2147483648) = 1, ceiling_div(2147483650, 2147483648) = 0, ceiling_div(2147483646, 2147483648) = 1 1445 1446 long int 1447 ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(-3, 1) = -3 1448 ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(-4, 2) = -1 1449 ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(-6, 4) = 0 1450 ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(-10, 8) = 0 1451 ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(-18, 16) = 0 1452 ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(-34, 32) = 0 1453 ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(-66, 64) = 0 1454 ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(-130, 128) = 0 1455 ceiling_div(256, 256) = 1, ceiling_div(258, 256) = 2, ceiling_div(-258, 256) = 0 1456 ceiling_div(512, 512) = 1, ceiling_div(514, 512) = 2, ceiling_div(-514, 512) = 0 1457 ceiling_div(1024, 1024) = 1, ceiling_div(1026, 1024) = 2, ceiling_div(-1026, 1024) = 0 1458 ceiling_div(2048, 2048) = 1, ceiling_div(2050, 2048) = 2, ceiling_div(-2050, 2048) = 0 1459 ceiling_div(4096, 4096) = 1, ceiling_div(4098, 4096) = 2, ceiling_div(-4098, 4096) = 0 1460 ceiling_div(8192, 8192) = 1, ceiling_div(8194, 8192) = 2, ceiling_div(-8194, 8192) = 0 1461 ceiling_div(16384, 16384) = 1, ceiling_div(16386, 16384) = 2, ceiling_div(-16386, 16384) = 0 1462 ceiling_div(32768, 32768) = 1, ceiling_div(32770, 32768) = 2, ceiling_div(-32770, 32768) = 0 1463 ceiling_div(65536, 65536) = 1, ceiling_div(65538, 65536) = 2, ceiling_div(-65538, 65536) = 0 1464 ceiling_div(131072, 131072) = 1, ceiling_div(131074, 131072) = 2, ceiling_div(-131074, 131072) = 0 1465 ceiling_div(262144, 262144) = 1, ceiling_div(262146, 262144) = 2, ceiling_div(-262146, 262144) = 0 1466 ceiling_div(524288, 524288) = 1, ceiling_div(524290, 524288) = 2, ceiling_div(-524290, 524288) = 0 1467 ceiling_div(1048576, 1048576) = 1, ceiling_div(1048578, 1048576) = 2, ceiling_div(-1048578, 1048576) = 0 1468 ceiling_div(2097152, 2097152) = 1, ceiling_div(2097154, 2097152) = 2, ceiling_div(-2097154, 2097152) = 0 1469 ceiling_div(4194304, 4194304) = 1, ceiling_div(4194306, 4194304) = 2, ceiling_div(-4194306, 4194304) = 0 1470 ceiling_div(8388608, 8388608) = 1, ceiling_div(8388610, 8388608) = 2, ceiling_div(-8388610, 8388608) = 0 1471 ceiling_div(16777216, 16777216) = 1, ceiling_div(16777218, 16777216) = 2, ceiling_div(-16777218, 16777216) = 0 1472 ceiling_div(33554432, 33554432) = 1, ceiling_div(33554434, 33554432) = 2, ceiling_div(-33554434, 33554432) = 0 1473 ceiling_div(67108864, 67108864) = 1, ceiling_div(67108866, 67108864) = 2, ceiling_div(-67108866, 67108864) = 0 1474 ceiling_div(134217728, 134217728) = 1, ceiling_div(134217730, 134217728) = 2, ceiling_div(-134217730, 134217728) = 0 1475 ceiling_div(268435456, 268435456) = 1, ceiling_div(268435458, 268435456) = 2, ceiling_div(-268435458, 268435456) = 0 1476 ceiling_div(536870912, 536870912) = 1, ceiling_div(536870914, 536870912) = 2, ceiling_div(-536870914, 536870912) = 0 1477 ceiling_div(1073741824, 1073741824) = 1, ceiling_div(1073741826, 1073741824) = -1, ceiling_div(-1073741826, 1073741824) = 0 1478 ceiling_div(-2147483648, -2147483648) = 0, ceiling_div(-2147483646, -2147483648) = 0, ceiling_div(2147483646, -2147483648) = 0 1479 1480 unsigned long int 1481 ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(4294967293, 1) = 4294967293 1482 ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(4294967292, 2) = 2147483646 1483 ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(4294967290, 4) = 1073741823 1484 ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(4294967286, 8) = 536870911 1485 ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(4294967278, 16) = 268435455 1486 ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(4294967262, 32) = 134217727 1487 ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(4294967230, 64) = 67108863 1488 ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(4294967166, 128) = 33554431 1489 ceiling_div(256, 256) = 1, ceiling_div(258, 256) = 2, ceiling_div(4294967038, 256) = 16777215 1490 ceiling_div(512, 512) = 1, ceiling_div(514, 512) = 2, ceiling_div(4294966782, 512) = 8388607 1491 ceiling_div(1024, 1024) = 1, ceiling_div(1026, 1024) = 2, ceiling_div(4294966270, 1024) = 4194303 1492 ceiling_div(2048, 2048) = 1, ceiling_div(2050, 2048) = 2, ceiling_div(4294965246, 2048) = 2097151 1493 ceiling_div(4096, 4096) = 1, ceiling_div(4098, 4096) = 2, ceiling_div(4294963198, 4096) = 1048575 1494 ceiling_div(8192, 8192) = 1, ceiling_div(8194, 8192) = 2, ceiling_div(4294959102, 8192) = 524287 1495 ceiling_div(16384, 16384) = 1, ceiling_div(16386, 16384) = 2, ceiling_div(4294950910, 16384) = 262143 1496 ceiling_div(32768, 32768) = 1, ceiling_div(32770, 32768) = 2, ceiling_div(4294934526, 32768) = 131071 1497 ceiling_div(65536, 65536) = 1, ceiling_div(65538, 65536) = 2, ceiling_div(4294901758, 65536) = 65535 1498 ceiling_div(131072, 131072) = 1, ceiling_div(131074, 131072) = 2, ceiling_div(4294836222, 131072) = 32767 1499 ceiling_div(262144, 262144) = 1, ceiling_div(262146, 262144) = 2, ceiling_div(4294705150, 262144) = 16383 1500 ceiling_div(524288, 524288) = 1, ceiling_div(524290, 524288) = 2, ceiling_div(4294443006, 524288) = 8191 1501 ceiling_div(1048576, 1048576) = 1, ceiling_div(1048578, 1048576) = 2, ceiling_div(4293918718, 1048576) = 4095 1502 ceiling_div(2097152, 2097152) = 1, ceiling_div(2097154, 2097152) = 2, ceiling_div(4292870142, 2097152) = 2047 1503 ceiling_div(4194304, 4194304) = 1, ceiling_div(4194306, 4194304) = 2, ceiling_div(4290772990, 4194304) = 1023 1504 ceiling_div(8388608, 8388608) = 1, ceiling_div(8388610, 8388608) = 2, ceiling_div(4286578686, 8388608) = 511 1505 ceiling_div(16777216, 16777216) = 1, ceiling_div(16777218, 16777216) = 2, ceiling_div(4278190078, 16777216) = 255 1506 ceiling_div(33554432, 33554432) = 1, ceiling_div(33554434, 33554432) = 2, ceiling_div(4261412862, 33554432) = 127 1507 ceiling_div(67108864, 67108864) = 1, ceiling_div(67108866, 67108864) = 2, ceiling_div(4227858430, 67108864) = 63 1508 ceiling_div(134217728, 134217728) = 1, ceiling_div(134217730, 134217728) = 2, ceiling_div(4160749566, 134217728) = 31 1509 ceiling_div(268435456, 268435456) = 1, ceiling_div(268435458, 268435456) = 2, ceiling_div(4026531838, 268435456) = 15 1510 ceiling_div(536870912, 536870912) = 1, ceiling_div(536870914, 536870912) = 2, ceiling_div(3758096382, 536870912) = 7 1511 ceiling_div(1073741824, 1073741824) = 1, ceiling_div(1073741826, 1073741824) = 2, ceiling_div(3221225470, 1073741824) = 3 1512 ceiling_div(2147483648, 2147483648) = 1, ceiling_div(2147483650, 2147483648) = 0, ceiling_div(2147483646, 2147483648) = 1 1513 1514 long long int 1515 ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(-3, 1) = -3 1516 ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(-4, 2) = -1 1517 ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(-6, 4) = 0 1518 ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(-10, 8) = 0 1519 ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(-18, 16) = 0 1520 ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(-34, 32) = 0 1521 ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(-66, 64) = 0 1522 ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(-130, 128) = 0 1523 ceiling_div(256, 256) = 1, ceiling_div(258, 256) = 2, ceiling_div(-258, 256) = 0 1524 ceiling_div(512, 512) = 1, ceiling_div(514, 512) = 2, ceiling_div(-514, 512) = 0 1525 ceiling_div(1024, 1024) = 1, ceiling_div(1026, 1024) = 2, ceiling_div(-1026, 1024) = 0 1526 ceiling_div(2048, 2048) = 1, ceiling_div(2050, 2048) = 2, ceiling_div(-2050, 2048) = 0 1527 ceiling_div(4096, 4096) = 1, ceiling_div(4098, 4096) = 2, ceiling_div(-4098, 4096) = 0 1528 ceiling_div(8192, 8192) = 1, ceiling_div(8194, 8192) = 2, ceiling_div(-8194, 8192) = 0 1529 ceiling_div(16384, 16384) = 1, ceiling_div(16386, 16384) = 2, ceiling_div(-16386, 16384) = 0 1530 ceiling_div(32768, 32768) = 1, ceiling_div(32770, 32768) = 2, ceiling_div(-32770, 32768) = 0 1531 ceiling_div(65536, 65536) = 1, ceiling_div(65538, 65536) = 2, ceiling_div(-65538, 65536) = 0 1532 ceiling_div(131072, 131072) = 1, ceiling_div(131074, 131072) = 2, ceiling_div(-131074, 131072) = 0 1533 ceiling_div(262144, 262144) = 1, ceiling_div(262146, 262144) = 2, ceiling_div(-262146, 262144) = 0 1534 ceiling_div(524288, 524288) = 1, ceiling_div(524290, 524288) = 2, ceiling_div(-524290, 524288) = 0 1535 ceiling_div(1048576, 1048576) = 1, ceiling_div(1048578, 1048576) = 2, ceiling_div(-1048578, 1048576) = 0 1536 ceiling_div(2097152, 2097152) = 1, ceiling_div(2097154, 2097152) = 2, ceiling_div(-2097154, 2097152) = 0 1537 ceiling_div(4194304, 4194304) = 1, ceiling_div(4194306, 4194304) = 2, ceiling_div(-4194306, 4194304) = 0 1538 ceiling_div(8388608, 8388608) = 1, ceiling_div(8388610, 8388608) = 2, ceiling_div(-8388610, 8388608) = 0 1539 ceiling_div(16777216, 16777216) = 1, ceiling_div(16777218, 16777216) = 2, ceiling_div(-16777218, 16777216) = 0 1540 ceiling_div(33554432, 33554432) = 1, ceiling_div(33554434, 33554432) = 2, ceiling_div(-33554434, 33554432) = 0 1541 ceiling_div(67108864, 67108864) = 1, ceiling_div(67108866, 67108864) = 2, ceiling_div(-67108866, 67108864) = 0 1542 ceiling_div(134217728, 134217728) = 1, ceiling_div(134217730, 134217728) = 2, ceiling_div(-134217730, 134217728) = 0 1543 ceiling_div(268435456, 268435456) = 1, ceiling_div(268435458, 268435456) = 2, ceiling_div(-268435458, 268435456) = 0 1544 ceiling_div(536870912, 536870912) = 1, ceiling_div(536870914, 536870912) = 2, ceiling_div(-536870914, 536870912) = 0 1545 ceiling_div(1073741824, 1073741824) = 1, ceiling_div(1073741826, 1073741824) = 2, ceiling_div(-1073741826, 1073741824) = 0 1546 ceiling_div(2147483648, 2147483648) = 1, ceiling_div(2147483650, 2147483648) = 2, ceiling_div(-2147483650, 2147483648) = 0 1547 ceiling_div(4294967296, 4294967296) = 1, ceiling_div(4294967298, 4294967296) = 2, ceiling_div(-4294967298, 4294967296) = 0 1548 ceiling_div(8589934592, 8589934592) = 1, ceiling_div(8589934594, 8589934592) = 2, ceiling_div(-8589934594, 8589934592) = 0 1549 ceiling_div(17179869184, 17179869184) = 1, ceiling_div(17179869186, 17179869184) = 2, ceiling_div(-17179869186, 17179869184) = 0 1550 ceiling_div(34359738368, 34359738368) = 1, ceiling_div(34359738370, 34359738368) = 2, ceiling_div(-34359738370, 34359738368) = 0 1551 ceiling_div(68719476736, 68719476736) = 1, ceiling_div(68719476738, 68719476736) = 2, ceiling_div(-68719476738, 68719476736) = 0 1552 ceiling_div(137438953472, 137438953472) = 1, ceiling_div(137438953474, 137438953472) = 2, ceiling_div(-137438953474, 137438953472) = 0 1553 ceiling_div(274877906944, 274877906944) = 1, ceiling_div(274877906946, 274877906944) = 2, ceiling_div(-274877906946, 274877906944) = 0 1554 ceiling_div(549755813888, 549755813888) = 1, ceiling_div(549755813890, 549755813888) = 2, ceiling_div(-549755813890, 549755813888) = 0 1555 ceiling_div(1099511627776, 1099511627776) = 1, ceiling_div(1099511627778, 1099511627776) = 2, ceiling_div(-1099511627778, 1099511627776) = 0 1556 ceiling_div(2199023255552, 2199023255552) = 1, ceiling_div(2199023255554, 2199023255552) = 2, ceiling_div(-2199023255554, 2199023255552) = 0 1557 ceiling_div(4398046511104, 4398046511104) = 1, ceiling_div(4398046511106, 4398046511104) = 2, ceiling_div(-4398046511106, 4398046511104) = 0 1558 ceiling_div(8796093022208, 8796093022208) = 1, ceiling_div(8796093022210, 8796093022208) = 2, ceiling_div(-8796093022210, 8796093022208) = 0 1559 ceiling_div(17592186044416, 17592186044416) = 1, ceiling_div(17592186044418, 17592186044416) = 2, ceiling_div(-17592186044418, 17592186044416) = 0 1560 ceiling_div(35184372088832, 35184372088832) = 1, ceiling_div(35184372088834, 35184372088832) = 2, ceiling_div(-35184372088834, 35184372088832) = 0 1561 ceiling_div(70368744177664, 70368744177664) = 1, ceiling_div(70368744177666, 70368744177664) = 2, ceiling_div(-70368744177666, 70368744177664) = 0 1562 ceiling_div(140737488355328, 140737488355328) = 1, ceiling_div(140737488355330, 140737488355328) = 2, ceiling_div(-140737488355330, 140737488355328) = 0 1563 ceiling_div(281474976710656, 281474976710656) = 1, ceiling_div(281474976710658, 281474976710656) = 2, ceiling_div(-281474976710658, 281474976710656) = 0 1564 ceiling_div(562949953421312, 562949953421312) = 1, ceiling_div(562949953421314, 562949953421312) = 2, ceiling_div(-562949953421314, 562949953421312) = 0 1565 ceiling_div(1125899906842624, 1125899906842624) = 1, ceiling_div(1125899906842626, 1125899906842624) = 2, ceiling_div(-1125899906842626, 1125899906842624) = 0 1566 ceiling_div(2251799813685248, 2251799813685248) = 1, ceiling_div(2251799813685250, 2251799813685248) = 2, ceiling_div(-2251799813685250, 2251799813685248) = 0 1567 ceiling_div(4503599627370496, 4503599627370496) = 1, ceiling_div(4503599627370498, 4503599627370496) = 2, ceiling_div(-4503599627370498, 4503599627370496) = 0 1568 ceiling_div(9007199254740992, 9007199254740992) = 1, ceiling_div(9007199254740994, 9007199254740992) = 2, ceiling_div(-9007199254740994, 9007199254740992) = 0 1569 ceiling_div(18014398509481984, 18014398509481984) = 1, ceiling_div(18014398509481986, 18014398509481984) = 2, ceiling_div(-18014398509481986, 18014398509481984) = 0 1570 ceiling_div(36028797018963968, 36028797018963968) = 1, ceiling_div(36028797018963970, 36028797018963968) = 2, ceiling_div(-36028797018963970, 36028797018963968) = 0 1571 ceiling_div(72057594037927936, 72057594037927936) = 1, ceiling_div(72057594037927938, 72057594037927936) = 2, ceiling_div(-72057594037927938, 72057594037927936) = 0 1572 ceiling_div(144115188075855872, 144115188075855872) = 1, ceiling_div(144115188075855874, 144115188075855872) = 2, ceiling_div(-144115188075855874, 144115188075855872) = 0 1573 ceiling_div(288230376151711744, 288230376151711744) = 1, ceiling_div(288230376151711746, 288230376151711744) = 2, ceiling_div(-288230376151711746, 288230376151711744) = 0 1574 ceiling_div(576460752303423488, 576460752303423488) = 1, ceiling_div(576460752303423490, 576460752303423488) = 2, ceiling_div(-576460752303423490, 576460752303423488) = 0 1575 ceiling_div(1152921504606846976, 1152921504606846976) = 1, ceiling_div(1152921504606846978, 1152921504606846976) = 2, ceiling_div(-1152921504606846978, 1152921504606846976) = 0 1576 ceiling_div(2305843009213693952, 2305843009213693952) = 1, ceiling_div(2305843009213693954, 2305843009213693952) = 2, ceiling_div(-2305843009213693954, 2305843009213693952) = 0 1577 ceiling_div(4611686018427387904, 4611686018427387904) = 1, ceiling_div(4611686018427387906, 4611686018427387904) = -1, ceiling_div(-4611686018427387906, 4611686018427387904) = 0 1578 ceiling_div(-9223372036854775808, -9223372036854775808) = 0, ceiling_div(-9223372036854775806, -9223372036854775808) = 0, ceiling_div(9223372036854775806, -9223372036854775808) = 0 1579 1580 unsigned long long int 1581 ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(18446744073709551613, 1) = 18446744073709551613 1582 ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(18446744073709551612, 2) = 9223372036854775806 1583 ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(18446744073709551610, 4) = 4611686018427387903 1584 ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(18446744073709551606, 8) = 2305843009213693951 1585 ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(18446744073709551598, 16) = 1152921504606846975 1586 ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(18446744073709551582, 32) = 576460752303423487 1587 ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(18446744073709551550, 64) = 288230376151711743 1588 ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(18446744073709551486, 128) = 144115188075855871 1589 ceiling_div(256, 256) = 1, ceiling_div(258, 256) = 2, ceiling_div(18446744073709551358, 256) = 72057594037927935 1590 ceiling_div(512, 512) = 1, ceiling_div(514, 512) = 2, ceiling_div(18446744073709551102, 512) = 36028797018963967 1591 ceiling_div(1024, 1024) = 1, ceiling_div(1026, 1024) = 2, ceiling_div(18446744073709550590, 1024) = 18014398509481983 1592 ceiling_div(2048, 2048) = 1, ceiling_div(2050, 2048) = 2, ceiling_div(18446744073709549566, 2048) = 9007199254740991 1593 ceiling_div(4096, 4096) = 1, ceiling_div(4098, 4096) = 2, ceiling_div(18446744073709547518, 4096) = 4503599627370495 1594 ceiling_div(8192, 8192) = 1, ceiling_div(8194, 8192) = 2, ceiling_div(18446744073709543422, 8192) = 2251799813685247 1595 ceiling_div(16384, 16384) = 1, ceiling_div(16386, 16384) = 2, ceiling_div(18446744073709535230, 16384) = 1125899906842623 1596 ceiling_div(32768, 32768) = 1, ceiling_div(32770, 32768) = 2, ceiling_div(18446744073709518846, 32768) = 562949953421311 1597 ceiling_div(65536, 65536) = 1, ceiling_div(65538, 65536) = 2, ceiling_div(18446744073709486078, 65536) = 281474976710655 1598 ceiling_div(131072, 131072) = 1, ceiling_div(131074, 131072) = 2, ceiling_div(18446744073709420542, 131072) = 140737488355327 1599 ceiling_div(262144, 262144) = 1, ceiling_div(262146, 262144) = 2, ceiling_div(18446744073709289470, 262144) = 70368744177663 1600 ceiling_div(524288, 524288) = 1, ceiling_div(524290, 524288) = 2, ceiling_div(18446744073709027326, 524288) = 35184372088831 1601 ceiling_div(1048576, 1048576) = 1, ceiling_div(1048578, 1048576) = 2, ceiling_div(18446744073708503038, 1048576) = 17592186044415 1602 ceiling_div(2097152, 2097152) = 1, ceiling_div(2097154, 2097152) = 2, ceiling_div(18446744073707454462, 2097152) = 8796093022207 1603 ceiling_div(4194304, 4194304) = 1, ceiling_div(4194306, 4194304) = 2, ceiling_div(18446744073705357310, 4194304) = 4398046511103 1604 ceiling_div(8388608, 8388608) = 1, ceiling_div(8388610, 8388608) = 2, ceiling_div(18446744073701163006, 8388608) = 2199023255551 1605 ceiling_div(16777216, 16777216) = 1, ceiling_div(16777218, 16777216) = 2, ceiling_div(18446744073692774398, 16777216) = 1099511627775 1606 ceiling_div(33554432, 33554432) = 1, ceiling_div(33554434, 33554432) = 2, ceiling_div(18446744073675997182, 33554432) = 549755813887 1607 ceiling_div(67108864, 67108864) = 1, ceiling_div(67108866, 67108864) = 2, ceiling_div(18446744073642442750, 67108864) = 274877906943 1608 ceiling_div(134217728, 134217728) = 1, ceiling_div(134217730, 134217728) = 2, ceiling_div(18446744073575333886, 134217728) = 137438953471 1609 ceiling_div(268435456, 268435456) = 1, ceiling_div(268435458, 268435456) = 2, ceiling_div(18446744073441116158, 268435456) = 68719476735 1610 ceiling_div(536870912, 536870912) = 1, ceiling_div(536870914, 536870912) = 2, ceiling_div(18446744073172680702, 536870912) = 34359738367 1611 ceiling_div(1073741824, 1073741824) = 1, ceiling_div(1073741826, 1073741824) = 2, ceiling_div(18446744072635809790, 1073741824) = 17179869183 1612 ceiling_div(2147483648, 2147483648) = 1, ceiling_div(2147483650, 2147483648) = 2, ceiling_div(18446744071562067966, 2147483648) = 8589934591 1613 ceiling_div(4294967296, 4294967296) = 1, ceiling_div(4294967298, 4294967296) = 2, ceiling_div(18446744069414584318, 4294967296) = 4294967295 1614 ceiling_div(8589934592, 8589934592) = 1, ceiling_div(8589934594, 8589934592) = 2, ceiling_div(18446744065119617022, 8589934592) = 2147483647 1615 ceiling_div(17179869184, 17179869184) = 1, ceiling_div(17179869186, 17179869184) = 2, ceiling_div(18446744056529682430, 17179869184) = 1073741823 1616 ceiling_div(34359738368, 34359738368) = 1, ceiling_div(34359738370, 34359738368) = 2, ceiling_div(18446744039349813246, 34359738368) = 536870911 1617 ceiling_div(68719476736, 68719476736) = 1, ceiling_div(68719476738, 68719476736) = 2, ceiling_div(18446744004990074878, 68719476736) = 268435455 1618 ceiling_div(137438953472, 137438953472) = 1, ceiling_div(137438953474, 137438953472) = 2, ceiling_div(18446743936270598142, 137438953472) = 134217727 1619 ceiling_div(274877906944, 274877906944) = 1, ceiling_div(274877906946, 274877906944) = 2, ceiling_div(18446743798831644670, 274877906944) = 67108863 1620 ceiling_div(549755813888, 549755813888) = 1, ceiling_div(549755813890, 549755813888) = 2, ceiling_div(18446743523953737726, 549755813888) = 33554431 1621 ceiling_div(1099511627776, 1099511627776) = 1, ceiling_div(1099511627778, 1099511627776) = 2, ceiling_div(18446742974197923838, 1099511627776) = 16777215 1622 ceiling_div(2199023255552, 2199023255552) = 1, ceiling_div(2199023255554, 2199023255552) = 2, ceiling_div(18446741874686296062, 2199023255552) = 8388607 1623 ceiling_div(4398046511104, 4398046511104) = 1, ceiling_div(4398046511106, 4398046511104) = 2, ceiling_div(18446739675663040510, 4398046511104) = 4194303 1624 ceiling_div(8796093022208, 8796093022208) = 1, ceiling_div(8796093022210, 8796093022208) = 2, ceiling_div(18446735277616529406, 8796093022208) = 2097151 1625 ceiling_div(17592186044416, 17592186044416) = 1, ceiling_div(17592186044418, 17592186044416) = 2, ceiling_div(18446726481523507198, 17592186044416) = 1048575 1626 ceiling_div(35184372088832, 35184372088832) = 1, ceiling_div(35184372088834, 35184372088832) = 2, ceiling_div(18446708889337462782, 35184372088832) = 524287 1627 ceiling_div(70368744177664, 70368744177664) = 1, ceiling_div(70368744177666, 70368744177664) = 2, ceiling_div(18446673704965373950, 70368744177664) = 262143 1628 ceiling_div(140737488355328, 140737488355328) = 1, ceiling_div(140737488355330, 140737488355328) = 2, ceiling_div(18446603336221196286, 140737488355328) = 131071 1629 ceiling_div(281474976710656, 281474976710656) = 1, ceiling_div(281474976710658, 281474976710656) = 2, ceiling_div(18446462598732840958, 281474976710656) = 65535 1630 ceiling_div(562949953421312, 562949953421312) = 1, ceiling_div(562949953421314, 562949953421312) = 2, ceiling_div(18446181123756130302, 562949953421312) = 32767 1631 ceiling_div(1125899906842624, 1125899906842624) = 1, ceiling_div(1125899906842626, 1125899906842624) = 2, ceiling_div(18445618173802708990, 1125899906842624) = 16383 1632 ceiling_div(2251799813685248, 2251799813685248) = 1, ceiling_div(2251799813685250, 2251799813685248) = 2, ceiling_div(18444492273895866366, 2251799813685248) = 8191 1633 ceiling_div(4503599627370496, 4503599627370496) = 1, ceiling_div(4503599627370498, 4503599627370496) = 2, ceiling_div(18442240474082181118, 4503599627370496) = 4095 1634 ceiling_div(9007199254740992, 9007199254740992) = 1, ceiling_div(9007199254740994, 9007199254740992) = 2, ceiling_div(18437736874454810622, 9007199254740992) = 2047 1635 ceiling_div(18014398509481984, 18014398509481984) = 1, ceiling_div(18014398509481986, 18014398509481984) = 2, ceiling_div(18428729675200069630, 18014398509481984) = 1023 1636 ceiling_div(36028797018963968, 36028797018963968) = 1, ceiling_div(36028797018963970, 36028797018963968) = 2, ceiling_div(18410715276690587646, 36028797018963968) = 511 1637 ceiling_div(72057594037927936, 72057594037927936) = 1, ceiling_div(72057594037927938, 72057594037927936) = 2, ceiling_div(18374686479671623678, 72057594037927936) = 255 1638 ceiling_div(144115188075855872, 144115188075855872) = 1, ceiling_div(144115188075855874, 144115188075855872) = 2, ceiling_div(18302628885633695742, 144115188075855872) = 127 1639 ceiling_div(288230376151711744, 288230376151711744) = 1, ceiling_div(288230376151711746, 288230376151711744) = 2, ceiling_div(18158513697557839870, 288230376151711744) = 63 1640 ceiling_div(576460752303423488, 576460752303423488) = 1, ceiling_div(576460752303423490, 576460752303423488) = 2, ceiling_div(17870283321406128126, 576460752303423488) = 31 1641 ceiling_div(1152921504606846976, 1152921504606846976) = 1, ceiling_div(1152921504606846978, 1152921504606846976) = 2, ceiling_div(17293822569102704638, 1152921504606846976) = 15 1642 ceiling_div(2305843009213693952, 2305843009213693952) = 1, ceiling_div(2305843009213693954, 2305843009213693952) = 2, ceiling_div(16140901064495857662, 2305843009213693952) = 7 1643 ceiling_div(4611686018427387904, 4611686018427387904) = 1, ceiling_div(4611686018427387906, 4611686018427387904) = 2, ceiling_div(13835058055282163710, 4611686018427387904) = 3 1644 ceiling_div(9223372036854775808, 9223372036854775808) = 1, ceiling_div(9223372036854775810, 9223372036854775808) = 0, ceiling_div(9223372036854775806, 9223372036854775808) = 1 1645 1646 1340 1647 ceiling 1341 1648 1342 1649 signed char 1343 1650 ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(-3, 1) = -3 1344 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(-4, 2) = -11345 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(-6, 4) = 01346 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(-10, 8) = 01347 ceiling(16, 16) = 1 , ceiling(18, 16) =2, ceiling(-18, 16) = 01348 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(-34, 32) = 01349 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(-66, 64) = 01350 ceiling(-128, -128) = 2, ceiling(-126, -128) = 1, ceiling(126, -128) = 01651 ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(-4, 2) = -4 1652 ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(-6, 4) = 0 1653 ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(-10, 8) = 0 1654 ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(-18, 16) = 0 1655 ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(-34, 32) = 0 1656 ceiling(64, 64) = 64, ceiling(66, 64) = -128, ceiling(-66, 64) = 0 1657 ceiling(-128, -128) = -128, ceiling(-126, -128) = -128, ceiling(126, -128) = 0 1351 1658 1352 1659 unsigned char 1353 1660 ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(253, 1) = 253 1354 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(252, 2) = 1261355 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(250, 4) = 631356 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(246, 8) = 311357 ceiling(16, 16) = 1 , ceiling(18, 16) = 2, ceiling(238, 16) = 151358 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(222, 32) = 71359 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(190, 64) = 31360 ceiling(128, 128) = 1 , ceiling(130, 128) = 2, ceiling(126, 128) = 11661 ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(252, 2) = 252 1662 ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(250, 4) = 252 1663 ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(246, 8) = 248 1664 ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(238, 16) = 240 1665 ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(222, 32) = 224 1666 ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(190, 64) = 192 1667 ceiling(128, 128) = 128, ceiling(130, 128) = 0, ceiling(126, 128) = 128 1361 1668 1362 1669 short int 1363 1670 ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(-3, 1) = -3 1364 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(-4, 2) = -11365 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(-6, 4) = 01366 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(-10, 8) = 01367 ceiling(16, 16) = 1 , ceiling(18, 16) =2, ceiling(-18, 16) = 01368 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(-34, 32) = 01369 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(-66, 64) = 01370 ceiling(128, 128) = 1 , ceiling(130, 128) = 2, ceiling(-130, 128) = 01371 ceiling(256, 256) = 1, ceiling(258, 256) =2, ceiling(-258, 256) = 01372 ceiling(512, 512) = 1, ceiling(514, 512) = 2, ceiling(-514, 512) = 01373 ceiling(1024, 1024) = 1 , ceiling(1026, 1024) = 2, ceiling(-1026, 1024) = 01374 ceiling(2048, 2048) = 1, ceiling(2050, 2048) = 2, ceiling(-2050, 2048) = 01375 ceiling(4096, 4096) = 1, ceiling(4098, 4096) =2, ceiling(-4098, 4096) = 01376 ceiling(8192, 8192) = 1, ceiling(8194, 8192) = 2, ceiling(-8194, 8192) = 01377 ceiling(16384, 16384) = 1 , ceiling(16386, 16384) = 2, ceiling(-16386, 16384) = 01378 ceiling(-32768, -32768) = 2, ceiling(-32766, -32768) = 1, ceiling(32766, -32768) = 01671 ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(-4, 2) = -4 1672 ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(-6, 4) = 0 1673 ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(-10, 8) = 0 1674 ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(-18, 16) = 0 1675 ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(-34, 32) = 0 1676 ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(-66, 64) = 0 1677 ceiling(128, 128) = 128, ceiling(130, 128) = 256, ceiling(-130, 128) = 0 1678 ceiling(256, 256) = 256, ceiling(258, 256) = 512, ceiling(-258, 256) = 0 1679 ceiling(512, 512) = 512, ceiling(514, 512) = 1024, ceiling(-514, 512) = 0 1680 ceiling(1024, 1024) = 1024, ceiling(1026, 1024) = 2048, ceiling(-1026, 1024) = 0 1681 ceiling(2048, 2048) = 2048, ceiling(2050, 2048) = 4096, ceiling(-2050, 2048) = 0 1682 ceiling(4096, 4096) = 4096, ceiling(4098, 4096) = 8192, ceiling(-4098, 4096) = 0 1683 ceiling(8192, 8192) = 8192, ceiling(8194, 8192) = 16384, ceiling(-8194, 8192) = 0 1684 ceiling(16384, 16384) = 16384, ceiling(16386, 16384) = -32768, ceiling(-16386, 16384) = 0 1685 ceiling(-32768, -32768) = -32768, ceiling(-32766, -32768) = -32768, ceiling(32766, -32768) = 0 1379 1686 1380 1687 unsigned short int 1381 1688 ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(65533, 1) = 65533 1382 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(65532, 2) = 327661383 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(65530, 4) = 163831384 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(65526, 8) = 81911385 ceiling(16, 16) = 1 , ceiling(18, 16) = 2, ceiling(65518, 16) = 40951386 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(65502, 32) = 20471387 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(65470, 64) = 10231388 ceiling(128, 128) = 1 , ceiling(130, 128) = 2, ceiling(65406, 128) = 5111389 ceiling(256, 256) = 1, ceiling(258, 256) = 2, ceiling(65278, 256) = 2551390 ceiling(512, 512) = 1, ceiling(514, 512) = 2, ceiling(65022, 512) = 1271391 ceiling(1024, 1024) = 1 , ceiling(1026, 1024) = 2, ceiling(64510, 1024) = 631392 ceiling(2048, 2048) = 1, ceiling(2050, 2048) = 2, ceiling(63486, 2048) = 311393 ceiling(4096, 4096) = 1, ceiling(4098, 4096) = 2, ceiling(61438, 4096) = 151394 ceiling(8192, 8192) = 1, ceiling(8194, 8192) = 2, ceiling(57342, 8192) = 71395 ceiling(16384, 16384) = 1 , ceiling(16386, 16384) = 2, ceiling(49150, 16384) = 31396 ceiling(32768, 32768) = 1, ceiling(32770, 32768) = 2, ceiling(32766, 32768) = 11689 ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(65532, 2) = 65532 1690 ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(65530, 4) = 65532 1691 ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(65526, 8) = 65528 1692 ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(65518, 16) = 65520 1693 ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(65502, 32) = 65504 1694 ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(65470, 64) = 65472 1695 ceiling(128, 128) = 128, ceiling(130, 128) = 256, ceiling(65406, 128) = 65408 1696 ceiling(256, 256) = 256, ceiling(258, 256) = 512, ceiling(65278, 256) = 65280 1697 ceiling(512, 512) = 512, ceiling(514, 512) = 1024, ceiling(65022, 512) = 65024 1698 ceiling(1024, 1024) = 1024, ceiling(1026, 1024) = 2048, ceiling(64510, 1024) = 64512 1699 ceiling(2048, 2048) = 2048, ceiling(2050, 2048) = 4096, ceiling(63486, 2048) = 63488 1700 ceiling(4096, 4096) = 4096, ceiling(4098, 4096) = 8192, ceiling(61438, 4096) = 61440 1701 ceiling(8192, 8192) = 8192, ceiling(8194, 8192) = 16384, ceiling(57342, 8192) = 57344 1702 ceiling(16384, 16384) = 16384, ceiling(16386, 16384) = 32768, ceiling(49150, 16384) = 49152 1703 ceiling(32768, 32768) = 32768, ceiling(32770, 32768) = 0, ceiling(32766, 32768) = 32768 1397 1704 1398 1705 int 1399 1706 ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(-3, 1) = -3 1400 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(-4, 2) = -11401 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(-6, 4) = 01402 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(-10, 8) = 01403 ceiling(16, 16) = 1 , ceiling(18, 16) =2, ceiling(-18, 16) = 01404 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(-34, 32) = 01405 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(-66, 64) = 01406 ceiling(128, 128) = 1 , ceiling(130, 128) = 2, ceiling(-130, 128) = 01407 ceiling(256, 256) = 1, ceiling(258, 256) =2, ceiling(-258, 256) = 01408 ceiling(512, 512) = 1, ceiling(514, 512) = 2, ceiling(-514, 512) = 01409 ceiling(1024, 1024) = 1 , ceiling(1026, 1024) = 2, ceiling(-1026, 1024) = 01410 ceiling(2048, 2048) = 1, ceiling(2050, 2048) = 2, ceiling(-2050, 2048) = 01411 ceiling(4096, 4096) = 1, ceiling(4098, 4096) =2, ceiling(-4098, 4096) = 01412 ceiling(8192, 8192) = 1, ceiling(8194, 8192) = 2, ceiling(-8194, 8192) = 01413 ceiling(16384, 16384) = 1 , ceiling(16386, 16384) = 2, ceiling(-16386, 16384) = 01414 ceiling(32768, 32768) = 1, ceiling(32770, 32768) = 2, ceiling(-32770, 32768) = 01415 ceiling(65536, 65536) = 1, ceiling(65538, 65536) =2, ceiling(-65538, 65536) = 01416 ceiling(131072, 131072) = 1 , ceiling(131074, 131072) = 2, ceiling(-131074, 131072) = 01417 ceiling(262144, 262144) = 1, ceiling(262146, 262144) = 2, ceiling(-262146, 262144) = 01418 ceiling(524288, 524288) = 1, ceiling(524290, 524288) = 2, ceiling(-524290, 524288) = 01419 ceiling(1048576, 1048576) = 1 , ceiling(1048578, 1048576) =2, ceiling(-1048578, 1048576) = 01420 ceiling(2097152, 2097152) = 1, ceiling(2097154, 2097152) = 2, ceiling(-2097154, 2097152) = 01421 ceiling(4194304, 4194304) = 1, ceiling(4194306, 4194304) = 2, ceiling(-4194306, 4194304) = 01422 ceiling(8388608, 8388608) = 1, ceiling(8388610, 8388608) = 2, ceiling(-8388610, 8388608) = 01423 ceiling(16777216, 16777216) = 1 , ceiling(16777218, 16777216) =2, ceiling(-16777218, 16777216) = 01424 ceiling(33554432, 33554432) = 1, ceiling(33554434, 33554432) = 2, ceiling(-33554434, 33554432) = 01425 ceiling(67108864, 67108864) = 1, ceiling(67108866, 67108864) = 2, ceiling(-67108866, 67108864) = 01426 ceiling(134217728, 134217728) = 1 , ceiling(134217730, 134217728) = 2, ceiling(-134217730, 134217728) = 01427 ceiling(268435456, 268435456) = 1, ceiling(268435458, 268435456) =2, ceiling(-268435458, 268435456) = 01428 ceiling(536870912, 536870912) = 1, ceiling(536870914, 536870912) = 2, ceiling(-536870914, 536870912) = 01429 ceiling(1073741824, 1073741824) = 1 , ceiling(1073741826, 1073741824) = -1, ceiling(-1073741826, 1073741824) = 01430 ceiling(-2147483648, -2147483648) = 0, ceiling(-2147483646, -2147483648) = 0, ceiling(2147483646, -2147483648) = 01707 ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(-4, 2) = -4 1708 ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(-6, 4) = 0 1709 ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(-10, 8) = 0 1710 ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(-18, 16) = 0 1711 ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(-34, 32) = 0 1712 ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(-66, 64) = 0 1713 ceiling(128, 128) = 128, ceiling(130, 128) = 256, ceiling(-130, 128) = 0 1714 ceiling(256, 256) = 256, ceiling(258, 256) = 512, ceiling(-258, 256) = 0 1715 ceiling(512, 512) = 512, ceiling(514, 512) = 1024, ceiling(-514, 512) = 0 1716 ceiling(1024, 1024) = 1024, ceiling(1026, 1024) = 2048, ceiling(-1026, 1024) = 0 1717 ceiling(2048, 2048) = 2048, ceiling(2050, 2048) = 4096, ceiling(-2050, 2048) = 0 1718 ceiling(4096, 4096) = 4096, ceiling(4098, 4096) = 8192, ceiling(-4098, 4096) = 0 1719 ceiling(8192, 8192) = 8192, ceiling(8194, 8192) = 16384, ceiling(-8194, 8192) = 0 1720 ceiling(16384, 16384) = 16384, ceiling(16386, 16384) = 32768, ceiling(-16386, 16384) = 0 1721 ceiling(32768, 32768) = 32768, ceiling(32770, 32768) = 65536, ceiling(-32770, 32768) = 0 1722 ceiling(65536, 65536) = 65536, ceiling(65538, 65536) = 131072, ceiling(-65538, 65536) = 0 1723 ceiling(131072, 131072) = 131072, ceiling(131074, 131072) = 262144, ceiling(-131074, 131072) = 0 1724 ceiling(262144, 262144) = 262144, ceiling(262146, 262144) = 524288, ceiling(-262146, 262144) = 0 1725 ceiling(524288, 524288) = 524288, ceiling(524290, 524288) = 1048576, ceiling(-524290, 524288) = 0 1726 ceiling(1048576, 1048576) = 1048576, ceiling(1048578, 1048576) = 2097152, ceiling(-1048578, 1048576) = 0 1727 ceiling(2097152, 2097152) = 2097152, ceiling(2097154, 2097152) = 4194304, ceiling(-2097154, 2097152) = 0 1728 ceiling(4194304, 4194304) = 4194304, ceiling(4194306, 4194304) = 8388608, ceiling(-4194306, 4194304) = 0 1729 ceiling(8388608, 8388608) = 8388608, ceiling(8388610, 8388608) = 16777216, ceiling(-8388610, 8388608) = 0 1730 ceiling(16777216, 16777216) = 16777216, ceiling(16777218, 16777216) = 33554432, ceiling(-16777218, 16777216) = 0 1731 ceiling(33554432, 33554432) = 33554432, ceiling(33554434, 33554432) = 67108864, ceiling(-33554434, 33554432) = 0 1732 ceiling(67108864, 67108864) = 67108864, ceiling(67108866, 67108864) = 134217728, ceiling(-67108866, 67108864) = 0 1733 ceiling(134217728, 134217728) = 134217728, ceiling(134217730, 134217728) = 268435456, ceiling(-134217730, 134217728) = 0 1734 ceiling(268435456, 268435456) = 268435456, ceiling(268435458, 268435456) = 536870912, ceiling(-268435458, 268435456) = 0 1735 ceiling(536870912, 536870912) = 536870912, ceiling(536870914, 536870912) = 1073741824, ceiling(-536870914, 536870912) = 0 1736 ceiling(1073741824, 1073741824) = 1073741824, ceiling(1073741826, 1073741824) = -1073741824, ceiling(-1073741826, 1073741824) = 0 1737 ceiling(-2147483648, -2147483648) = -2147483648, ceiling(-2147483646, -2147483648) = 0, ceiling(2147483646, -2147483648) = 0 1431 1738 1432 1739 unsigned int 1433 1740 ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(4294967293, 1) = 4294967293 1434 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(4294967292, 2) = 21474836461435 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(4294967290, 4) = 10737418231436 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(4294967286, 8) = 5368709111437 ceiling(16, 16) = 1 , ceiling(18, 16) = 2, ceiling(4294967278, 16) = 2684354551438 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(4294967262, 32) = 1342177271439 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(4294967230, 64) = 671088631440 ceiling(128, 128) = 1 , ceiling(130, 128) = 2, ceiling(4294967166, 128) = 335544311441 ceiling(256, 256) = 1, ceiling(258, 256) = 2, ceiling(4294967038, 256) = 167772151442 ceiling(512, 512) = 1, ceiling(514, 512) = 2, ceiling(4294966782, 512) = 83886071443 ceiling(1024, 1024) = 1 , ceiling(1026, 1024) = 2, ceiling(4294966270, 1024) = 41943031444 ceiling(2048, 2048) = 1, ceiling(2050, 2048) = 2, ceiling(4294965246, 2048) = 20971511445 ceiling(4096, 4096) = 1, ceiling(4098, 4096) = 2, ceiling(4294963198, 4096) = 10485751446 ceiling(8192, 8192) = 1, ceiling(8194, 8192) = 2, ceiling(4294959102, 8192) = 5242871447 ceiling(16384, 16384) = 1 , ceiling(16386, 16384) = 2, ceiling(4294950910, 16384) = 2621431448 ceiling(32768, 32768) = 1, ceiling(32770, 32768) = 2, ceiling(4294934526, 32768) = 1310711449 ceiling(65536, 65536) = 1, ceiling(65538, 65536) = 2, ceiling(4294901758, 65536) = 655351450 ceiling(131072, 131072) = 1 , ceiling(131074, 131072) = 2, ceiling(4294836222, 131072) = 327671451 ceiling(262144, 262144) = 1, ceiling(262146, 262144) = 2, ceiling(4294705150, 262144) = 163831452 ceiling(524288, 524288) = 1, ceiling(524290, 524288) = 2, ceiling(4294443006, 524288) = 81911453 ceiling(1048576, 1048576) = 1 , ceiling(1048578, 1048576) = 2, ceiling(4293918718, 1048576) = 40951454 ceiling(2097152, 2097152) = 1, ceiling(2097154, 2097152) = 2, ceiling(4292870142, 2097152) = 20471455 ceiling(4194304, 4194304) = 1, ceiling(4194306, 4194304) = 2, ceiling(4290772990, 4194304) = 10231456 ceiling(8388608, 8388608) = 1, ceiling(8388610, 8388608) = 2, ceiling(4286578686, 8388608) = 5111457 ceiling(16777216, 16777216) = 1 , ceiling(16777218, 16777216) = 2, ceiling(4278190078, 16777216) = 2551458 ceiling(33554432, 33554432) = 1, ceiling(33554434, 33554432) = 2, ceiling(4261412862, 33554432) = 1271459 ceiling(67108864, 67108864) = 1, ceiling(67108866, 67108864) = 2, ceiling(4227858430, 67108864) = 631460 ceiling(134217728, 134217728) = 1 , ceiling(134217730, 134217728) = 2, ceiling(4160749566, 134217728) = 311461 ceiling(268435456, 268435456) = 1, ceiling(268435458, 268435456) = 2, ceiling(4026531838, 268435456) = 151462 ceiling(536870912, 536870912) = 1, ceiling(536870914, 536870912) = 2, ceiling(3758096382, 536870912) = 71463 ceiling(1073741824, 1073741824) = 1 , ceiling(1073741826, 1073741824) = 2, ceiling(3221225470, 1073741824) = 31464 ceiling(2147483648, 2147483648) = 1, ceiling(2147483650, 2147483648) = 0, ceiling(2147483646, 2147483648) = 11741 ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(4294967292, 2) = 4294967292 1742 ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(4294967290, 4) = 4294967292 1743 ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(4294967286, 8) = 4294967288 1744 ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(4294967278, 16) = 4294967280 1745 ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(4294967262, 32) = 4294967264 1746 ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(4294967230, 64) = 4294967232 1747 ceiling(128, 128) = 128, ceiling(130, 128) = 256, ceiling(4294967166, 128) = 4294967168 1748 ceiling(256, 256) = 256, ceiling(258, 256) = 512, ceiling(4294967038, 256) = 4294967040 1749 ceiling(512, 512) = 512, ceiling(514, 512) = 1024, ceiling(4294966782, 512) = 4294966784 1750 ceiling(1024, 1024) = 1024, ceiling(1026, 1024) = 2048, ceiling(4294966270, 1024) = 4294966272 1751 ceiling(2048, 2048) = 2048, ceiling(2050, 2048) = 4096, ceiling(4294965246, 2048) = 4294965248 1752 ceiling(4096, 4096) = 4096, ceiling(4098, 4096) = 8192, ceiling(4294963198, 4096) = 4294963200 1753 ceiling(8192, 8192) = 8192, ceiling(8194, 8192) = 16384, ceiling(4294959102, 8192) = 4294959104 1754 ceiling(16384, 16384) = 16384, ceiling(16386, 16384) = 32768, ceiling(4294950910, 16384) = 4294950912 1755 ceiling(32768, 32768) = 32768, ceiling(32770, 32768) = 65536, ceiling(4294934526, 32768) = 4294934528 1756 ceiling(65536, 65536) = 65536, ceiling(65538, 65536) = 131072, ceiling(4294901758, 65536) = 4294901760 1757 ceiling(131072, 131072) = 131072, ceiling(131074, 131072) = 262144, ceiling(4294836222, 131072) = 4294836224 1758 ceiling(262144, 262144) = 262144, ceiling(262146, 262144) = 524288, ceiling(4294705150, 262144) = 4294705152 1759 ceiling(524288, 524288) = 524288, ceiling(524290, 524288) = 1048576, ceiling(4294443006, 524288) = 4294443008 1760 ceiling(1048576, 1048576) = 1048576, ceiling(1048578, 1048576) = 2097152, ceiling(4293918718, 1048576) = 4293918720 1761 ceiling(2097152, 2097152) = 2097152, ceiling(2097154, 2097152) = 4194304, ceiling(4292870142, 2097152) = 4292870144 1762 ceiling(4194304, 4194304) = 4194304, ceiling(4194306, 4194304) = 8388608, ceiling(4290772990, 4194304) = 4290772992 1763 ceiling(8388608, 8388608) = 8388608, ceiling(8388610, 8388608) = 16777216, ceiling(4286578686, 8388608) = 4286578688 1764 ceiling(16777216, 16777216) = 16777216, ceiling(16777218, 16777216) = 33554432, ceiling(4278190078, 16777216) = 4278190080 1765 ceiling(33554432, 33554432) = 33554432, ceiling(33554434, 33554432) = 67108864, ceiling(4261412862, 33554432) = 4261412864 1766 ceiling(67108864, 67108864) = 67108864, ceiling(67108866, 67108864) = 134217728, ceiling(4227858430, 67108864) = 4227858432 1767 ceiling(134217728, 134217728) = 134217728, ceiling(134217730, 134217728) = 268435456, ceiling(4160749566, 134217728) = 4160749568 1768 ceiling(268435456, 268435456) = 268435456, ceiling(268435458, 268435456) = 536870912, ceiling(4026531838, 268435456) = 4026531840 1769 ceiling(536870912, 536870912) = 536870912, ceiling(536870914, 536870912) = 1073741824, ceiling(3758096382, 536870912) = 3758096384 1770 ceiling(1073741824, 1073741824) = 1073741824, ceiling(1073741826, 1073741824) = 2147483648, ceiling(3221225470, 1073741824) = 3221225472 1771 ceiling(2147483648, 2147483648) = 2147483648, ceiling(2147483650, 2147483648) = 0, ceiling(2147483646, 2147483648) = 2147483648 1465 1772 1466 1773 long int 1467 1774 ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(-3, 1) = -3 1468 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(-4, 2) = -11469 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(-6, 4) = 01470 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(-10, 8) = 01471 ceiling(16, 16) = 1 , ceiling(18, 16) =2, ceiling(-18, 16) = 01472 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(-34, 32) = 01473 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(-66, 64) = 01474 ceiling(128, 128) = 1 , ceiling(130, 128) = 2, ceiling(-130, 128) = 01475 ceiling(256, 256) = 1, ceiling(258, 256) =2, ceiling(-258, 256) = 01476 ceiling(512, 512) = 1, ceiling(514, 512) = 2, ceiling(-514, 512) = 01477 ceiling(1024, 1024) = 1 , ceiling(1026, 1024) = 2, ceiling(-1026, 1024) = 01478 ceiling(2048, 2048) = 1, ceiling(2050, 2048) = 2, ceiling(-2050, 2048) = 01479 ceiling(4096, 4096) = 1, ceiling(4098, 4096) =2, ceiling(-4098, 4096) = 01480 ceiling(8192, 8192) = 1, ceiling(8194, 8192) = 2, ceiling(-8194, 8192) = 01481 ceiling(16384, 16384) = 1 , ceiling(16386, 16384) = 2, ceiling(-16386, 16384) = 01482 ceiling(32768, 32768) = 1, ceiling(32770, 32768) = 2, ceiling(-32770, 32768) = 01483 ceiling(65536, 65536) = 1, ceiling(65538, 65536) =2, ceiling(-65538, 65536) = 01484 ceiling(131072, 131072) = 1 , ceiling(131074, 131072) = 2, ceiling(-131074, 131072) = 01485 ceiling(262144, 262144) = 1, ceiling(262146, 262144) = 2, ceiling(-262146, 262144) = 01486 ceiling(524288, 524288) = 1, ceiling(524290, 524288) = 2, ceiling(-524290, 524288) = 01487 ceiling(1048576, 1048576) = 1 , ceiling(1048578, 1048576) =2, ceiling(-1048578, 1048576) = 01488 ceiling(2097152, 2097152) = 1, ceiling(2097154, 2097152) = 2, ceiling(-2097154, 2097152) = 01489 ceiling(4194304, 4194304) = 1, ceiling(4194306, 4194304) = 2, ceiling(-4194306, 4194304) = 01490 ceiling(8388608, 8388608) = 1, ceiling(8388610, 8388608) = 2, ceiling(-8388610, 8388608) = 01491 ceiling(16777216, 16777216) = 1 , ceiling(16777218, 16777216) =2, ceiling(-16777218, 16777216) = 01492 ceiling(33554432, 33554432) = 1, ceiling(33554434, 33554432) = 2, ceiling(-33554434, 33554432) = 01493 ceiling(67108864, 67108864) = 1, ceiling(67108866, 67108864) = 2, ceiling(-67108866, 67108864) = 01494 ceiling(134217728, 134217728) = 1 , ceiling(134217730, 134217728) = 2, ceiling(-134217730, 134217728) = 01495 ceiling(268435456, 268435456) = 1, ceiling(268435458, 268435456) =2, ceiling(-268435458, 268435456) = 01496 ceiling(536870912, 536870912) = 1, ceiling(536870914, 536870912) = 2, ceiling(-536870914, 536870912) = 01497 ceiling(1073741824, 1073741824) = 1 , ceiling(1073741826, 1073741824) = -1, ceiling(-1073741826, 1073741824) = 01498 ceiling(-2147483648, -2147483648) = 0, ceiling(-2147483646, -2147483648) = 0, ceiling(2147483646, -2147483648) = 01775 ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(-4, 2) = -4 1776 ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(-6, 4) = 0 1777 ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(-10, 8) = 0 1778 ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(-18, 16) = 0 1779 ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(-34, 32) = 0 1780 ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(-66, 64) = 0 1781 ceiling(128, 128) = 128, ceiling(130, 128) = 256, ceiling(-130, 128) = 0 1782 ceiling(256, 256) = 256, ceiling(258, 256) = 512, ceiling(-258, 256) = 0 1783 ceiling(512, 512) = 512, ceiling(514, 512) = 1024, ceiling(-514, 512) = 0 1784 ceiling(1024, 1024) = 1024, ceiling(1026, 1024) = 2048, ceiling(-1026, 1024) = 0 1785 ceiling(2048, 2048) = 2048, ceiling(2050, 2048) = 4096, ceiling(-2050, 2048) = 0 1786 ceiling(4096, 4096) = 4096, ceiling(4098, 4096) = 8192, ceiling(-4098, 4096) = 0 1787 ceiling(8192, 8192) = 8192, ceiling(8194, 8192) = 16384, ceiling(-8194, 8192) = 0 1788 ceiling(16384, 16384) = 16384, ceiling(16386, 16384) = 32768, ceiling(-16386, 16384) = 0 1789 ceiling(32768, 32768) = 32768, ceiling(32770, 32768) = 65536, ceiling(-32770, 32768) = 0 1790 ceiling(65536, 65536) = 65536, ceiling(65538, 65536) = 131072, ceiling(-65538, 65536) = 0 1791 ceiling(131072, 131072) = 131072, ceiling(131074, 131072) = 262144, ceiling(-131074, 131072) = 0 1792 ceiling(262144, 262144) = 262144, ceiling(262146, 262144) = 524288, ceiling(-262146, 262144) = 0 1793 ceiling(524288, 524288) = 524288, ceiling(524290, 524288) = 1048576, ceiling(-524290, 524288) = 0 1794 ceiling(1048576, 1048576) = 1048576, ceiling(1048578, 1048576) = 2097152, ceiling(-1048578, 1048576) = 0 1795 ceiling(2097152, 2097152) = 2097152, ceiling(2097154, 2097152) = 4194304, ceiling(-2097154, 2097152) = 0 1796 ceiling(4194304, 4194304) = 4194304, ceiling(4194306, 4194304) = 8388608, ceiling(-4194306, 4194304) = 0 1797 ceiling(8388608, 8388608) = 8388608, ceiling(8388610, 8388608) = 16777216, ceiling(-8388610, 8388608) = 0 1798 ceiling(16777216, 16777216) = 16777216, ceiling(16777218, 16777216) = 33554432, ceiling(-16777218, 16777216) = 0 1799 ceiling(33554432, 33554432) = 33554432, ceiling(33554434, 33554432) = 67108864, ceiling(-33554434, 33554432) = 0 1800 ceiling(67108864, 67108864) = 67108864, ceiling(67108866, 67108864) = 134217728, ceiling(-67108866, 67108864) = 0 1801 ceiling(134217728, 134217728) = 134217728, ceiling(134217730, 134217728) = 268435456, ceiling(-134217730, 134217728) = 0 1802 ceiling(268435456, 268435456) = 268435456, ceiling(268435458, 268435456) = 536870912, ceiling(-268435458, 268435456) = 0 1803 ceiling(536870912, 536870912) = 536870912, ceiling(536870914, 536870912) = 1073741824, ceiling(-536870914, 536870912) = 0 1804 ceiling(1073741824, 1073741824) = 1073741824, ceiling(1073741826, 1073741824) = -1073741824, ceiling(-1073741826, 1073741824) = 0 1805 ceiling(-2147483648, -2147483648) = -2147483648, ceiling(-2147483646, -2147483648) = 0, ceiling(2147483646, -2147483648) = 0 1499 1806 1500 1807 unsigned long int 1501 1808 ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(4294967293, 1) = 4294967293 1502 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(4294967292, 2) = 21474836461503 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(4294967290, 4) = 10737418231504 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(4294967286, 8) = 5368709111505 ceiling(16, 16) = 1 , ceiling(18, 16) = 2, ceiling(4294967278, 16) = 2684354551506 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(4294967262, 32) = 1342177271507 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(4294967230, 64) = 671088631508 ceiling(128, 128) = 1 , ceiling(130, 128) = 2, ceiling(4294967166, 128) = 335544311509 ceiling(256, 256) = 1, ceiling(258, 256) = 2, ceiling(4294967038, 256) = 167772151510 ceiling(512, 512) = 1, ceiling(514, 512) = 2, ceiling(4294966782, 512) = 83886071511 ceiling(1024, 1024) = 1 , ceiling(1026, 1024) = 2, ceiling(4294966270, 1024) = 41943031512 ceiling(2048, 2048) = 1, ceiling(2050, 2048) = 2, ceiling(4294965246, 2048) = 20971511513 ceiling(4096, 4096) = 1, ceiling(4098, 4096) = 2, ceiling(4294963198, 4096) = 10485751514 ceiling(8192, 8192) = 1, ceiling(8194, 8192) = 2, ceiling(4294959102, 8192) = 5242871515 ceiling(16384, 16384) = 1 , ceiling(16386, 16384) = 2, ceiling(4294950910, 16384) = 2621431516 ceiling(32768, 32768) = 1, ceiling(32770, 32768) = 2, ceiling(4294934526, 32768) = 1310711517 ceiling(65536, 65536) = 1, ceiling(65538, 65536) = 2, ceiling(4294901758, 65536) = 655351518 ceiling(131072, 131072) = 1 , ceiling(131074, 131072) = 2, ceiling(4294836222, 131072) = 327671519 ceiling(262144, 262144) = 1, ceiling(262146, 262144) = 2, ceiling(4294705150, 262144) = 163831520 ceiling(524288, 524288) = 1, ceiling(524290, 524288) = 2, ceiling(4294443006, 524288) = 81911521 ceiling(1048576, 1048576) = 1 , ceiling(1048578, 1048576) = 2, ceiling(4293918718, 1048576) = 40951522 ceiling(2097152, 2097152) = 1, ceiling(2097154, 2097152) = 2, ceiling(4292870142, 2097152) = 20471523 ceiling(4194304, 4194304) = 1, ceiling(4194306, 4194304) = 2, ceiling(4290772990, 4194304) = 10231524 ceiling(8388608, 8388608) = 1, ceiling(8388610, 8388608) = 2, ceiling(4286578686, 8388608) = 5111525 ceiling(16777216, 16777216) = 1 , ceiling(16777218, 16777216) = 2, ceiling(4278190078, 16777216) = 2551526 ceiling(33554432, 33554432) = 1, ceiling(33554434, 33554432) = 2, ceiling(4261412862, 33554432) = 1271527 ceiling(67108864, 67108864) = 1, ceiling(67108866, 67108864) = 2, ceiling(4227858430, 67108864) = 631528 ceiling(134217728, 134217728) = 1 , ceiling(134217730, 134217728) = 2, ceiling(4160749566, 134217728) = 311529 ceiling(268435456, 268435456) = 1, ceiling(268435458, 268435456) = 2, ceiling(4026531838, 268435456) = 151530 ceiling(536870912, 536870912) = 1, ceiling(536870914, 536870912) = 2, ceiling(3758096382, 536870912) = 71531 ceiling(1073741824, 1073741824) = 1 , ceiling(1073741826, 1073741824) = 2, ceiling(3221225470, 1073741824) = 31532 ceiling(2147483648, 2147483648) = 1, ceiling(2147483650, 2147483648) = 0, ceiling(2147483646, 2147483648) = 11809 ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(4294967292, 2) = 4294967292 1810 ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(4294967290, 4) = 4294967292 1811 ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(4294967286, 8) = 4294967288 1812 ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(4294967278, 16) = 4294967280 1813 ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(4294967262, 32) = 4294967264 1814 ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(4294967230, 64) = 4294967232 1815 ceiling(128, 128) = 128, ceiling(130, 128) = 256, ceiling(4294967166, 128) = 4294967168 1816 ceiling(256, 256) = 256, ceiling(258, 256) = 512, ceiling(4294967038, 256) = 4294967040 1817 ceiling(512, 512) = 512, ceiling(514, 512) = 1024, ceiling(4294966782, 512) = 4294966784 1818 ceiling(1024, 1024) = 1024, ceiling(1026, 1024) = 2048, ceiling(4294966270, 1024) = 4294966272 1819 ceiling(2048, 2048) = 2048, ceiling(2050, 2048) = 4096, ceiling(4294965246, 2048) = 4294965248 1820 ceiling(4096, 4096) = 4096, ceiling(4098, 4096) = 8192, ceiling(4294963198, 4096) = 4294963200 1821 ceiling(8192, 8192) = 8192, ceiling(8194, 8192) = 16384, ceiling(4294959102, 8192) = 4294959104 1822 ceiling(16384, 16384) = 16384, ceiling(16386, 16384) = 32768, ceiling(4294950910, 16384) = 4294950912 1823 ceiling(32768, 32768) = 32768, ceiling(32770, 32768) = 65536, ceiling(4294934526, 32768) = 4294934528 1824 ceiling(65536, 65536) = 65536, ceiling(65538, 65536) = 131072, ceiling(4294901758, 65536) = 4294901760 1825 ceiling(131072, 131072) = 131072, ceiling(131074, 131072) = 262144, ceiling(4294836222, 131072) = 4294836224 1826 ceiling(262144, 262144) = 262144, ceiling(262146, 262144) = 524288, ceiling(4294705150, 262144) = 4294705152 1827 ceiling(524288, 524288) = 524288, ceiling(524290, 524288) = 1048576, ceiling(4294443006, 524288) = 4294443008 1828 ceiling(1048576, 1048576) = 1048576, ceiling(1048578, 1048576) = 2097152, ceiling(4293918718, 1048576) = 4293918720 1829 ceiling(2097152, 2097152) = 2097152, ceiling(2097154, 2097152) = 4194304, ceiling(4292870142, 2097152) = 4292870144 1830 ceiling(4194304, 4194304) = 4194304, ceiling(4194306, 4194304) = 8388608, ceiling(4290772990, 4194304) = 4290772992 1831 ceiling(8388608, 8388608) = 8388608, ceiling(8388610, 8388608) = 16777216, ceiling(4286578686, 8388608) = 4286578688 1832 ceiling(16777216, 16777216) = 16777216, ceiling(16777218, 16777216) = 33554432, ceiling(4278190078, 16777216) = 4278190080 1833 ceiling(33554432, 33554432) = 33554432, ceiling(33554434, 33554432) = 67108864, ceiling(4261412862, 33554432) = 4261412864 1834 ceiling(67108864, 67108864) = 67108864, ceiling(67108866, 67108864) = 134217728, ceiling(4227858430, 67108864) = 4227858432 1835 ceiling(134217728, 134217728) = 134217728, ceiling(134217730, 134217728) = 268435456, ceiling(4160749566, 134217728) = 4160749568 1836 ceiling(268435456, 268435456) = 268435456, ceiling(268435458, 268435456) = 536870912, ceiling(4026531838, 268435456) = 4026531840 1837 ceiling(536870912, 536870912) = 536870912, ceiling(536870914, 536870912) = 1073741824, ceiling(3758096382, 536870912) = 3758096384 1838 ceiling(1073741824, 1073741824) = 1073741824, ceiling(1073741826, 1073741824) = 2147483648, ceiling(3221225470, 1073741824) = 3221225472 1839 ceiling(2147483648, 2147483648) = 2147483648, ceiling(2147483650, 2147483648) = 0, ceiling(2147483646, 2147483648) = 2147483648 1533 1840 1534 1841 long long int 1535 1842 ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(-3, 1) = -3 1536 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(-4, 2) = -11537 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(-6, 4) = 01538 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(-10, 8) = 01539 ceiling(16, 16) = 1 , ceiling(18, 16) =2, ceiling(-18, 16) = 01540 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(-34, 32) = 01541 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(-66, 64) = 01542 ceiling(128, 128) = 1 , ceiling(130, 128) = 2, ceiling(-130, 128) = 01543 ceiling(256, 256) = 1, ceiling(258, 256) =2, ceiling(-258, 256) = 01544 ceiling(512, 512) = 1, ceiling(514, 512) = 2, ceiling(-514, 512) = 01545 ceiling(1024, 1024) = 1 , ceiling(1026, 1024) = 2, ceiling(-1026, 1024) = 01546 ceiling(2048, 2048) = 1, ceiling(2050, 2048) = 2, ceiling(-2050, 2048) = 01547 ceiling(4096, 4096) = 1, ceiling(4098, 4096) =2, ceiling(-4098, 4096) = 01548 ceiling(8192, 8192) = 1, ceiling(8194, 8192) = 2, ceiling(-8194, 8192) = 01549 ceiling(16384, 16384) = 1 , ceiling(16386, 16384) = 2, ceiling(-16386, 16384) = 01550 ceiling(32768, 32768) = 1, ceiling(32770, 32768) = 2, ceiling(-32770, 32768) = 01551 ceiling(65536, 65536) = 1, ceiling(65538, 65536) =2, ceiling(-65538, 65536) = 01552 ceiling(131072, 131072) = 1 , ceiling(131074, 131072) = 2, ceiling(-131074, 131072) = 01553 ceiling(262144, 262144) = 1, ceiling(262146, 262144) = 2, ceiling(-262146, 262144) = 01554 ceiling(524288, 524288) = 1, ceiling(524290, 524288) = 2, ceiling(-524290, 524288) = 01555 ceiling(1048576, 1048576) = 1 , ceiling(1048578, 1048576) =2, ceiling(-1048578, 1048576) = 01556 ceiling(2097152, 2097152) = 1, ceiling(2097154, 2097152) = 2, ceiling(-2097154, 2097152) = 01557 ceiling(4194304, 4194304) = 1, ceiling(4194306, 4194304) = 2, ceiling(-4194306, 4194304) = 01558 ceiling(8388608, 8388608) = 1, ceiling(8388610, 8388608) = 2, ceiling(-8388610, 8388608) = 01559 ceiling(16777216, 16777216) = 1 , ceiling(16777218, 16777216) =2, ceiling(-16777218, 16777216) = 01560 ceiling(33554432, 33554432) = 1, ceiling(33554434, 33554432) = 2, ceiling(-33554434, 33554432) = 01561 ceiling(67108864, 67108864) = 1, ceiling(67108866, 67108864) = 2, ceiling(-67108866, 67108864) = 01562 ceiling(134217728, 134217728) = 1 , ceiling(134217730, 134217728) = 2, ceiling(-134217730, 134217728) = 01563 ceiling(268435456, 268435456) = 1, ceiling(268435458, 268435456) =2, ceiling(-268435458, 268435456) = 01564 ceiling(536870912, 536870912) = 1, ceiling(536870914, 536870912) = 2, ceiling(-536870914, 536870912) = 01565 ceiling(1073741824, 1073741824) = 1 , ceiling(1073741826, 1073741824) = 2, ceiling(-1073741826, 1073741824) = 01566 ceiling(2147483648, 2147483648) = 1, ceiling(2147483650, 2147483648) = 2, ceiling(-2147483650, 2147483648) = 01567 ceiling(4294967296, 4294967296) = 1, ceiling(4294967298, 4294967296) =2, ceiling(-4294967298, 4294967296) = 01568 ceiling(8589934592, 8589934592) = 1, ceiling(8589934594, 8589934592) = 2, ceiling(-8589934594, 8589934592) = 01569 ceiling(17179869184, 17179869184) = 1 , ceiling(17179869186, 17179869184) = 2, ceiling(-17179869186, 17179869184) = 01570 ceiling(34359738368, 34359738368) = 1, ceiling(34359738370, 34359738368) = 2, ceiling(-34359738370, 34359738368) = 01571 ceiling(68719476736, 68719476736) = 1, ceiling(68719476738, 68719476736) =2, ceiling(-68719476738, 68719476736) = 01572 ceiling(137438953472, 137438953472) = 1 , ceiling(137438953474, 137438953472) = 2, ceiling(-137438953474, 137438953472) = 01573 ceiling(274877906944, 274877906944) = 1, ceiling(274877906946, 274877906944) = 2, ceiling(-274877906946, 274877906944) = 01574 ceiling(549755813888, 549755813888) = 1, ceiling(549755813890, 549755813888) = 2, ceiling(-549755813890, 549755813888) = 01575 ceiling(1099511627776, 1099511627776) = 1 , ceiling(1099511627778, 1099511627776) =2, ceiling(-1099511627778, 1099511627776) = 01576 ceiling(2199023255552, 2199023255552) = 1, ceiling(2199023255554, 2199023255552) = 2, ceiling(-2199023255554, 2199023255552) = 01577 ceiling(4398046511104, 4398046511104) = 1, ceiling(4398046511106, 4398046511104) = 2, ceiling(-4398046511106, 4398046511104) = 01578 ceiling(8796093022208, 8796093022208) = 1, ceiling(8796093022210, 8796093022208) = 2, ceiling(-8796093022210, 8796093022208) = 01579 ceiling(17592186044416, 17592186044416) = 1 , ceiling(17592186044418, 17592186044416) =2, ceiling(-17592186044418, 17592186044416) = 01580 ceiling(35184372088832, 35184372088832) = 1, ceiling(35184372088834, 35184372088832) = 2, ceiling(-35184372088834, 35184372088832) = 01581 ceiling(70368744177664, 70368744177664) = 1, ceiling(70368744177666, 70368744177664) = 2, ceiling(-70368744177666, 70368744177664) = 01582 ceiling(140737488355328, 140737488355328) = 1 , ceiling(140737488355330, 140737488355328) = 2, ceiling(-140737488355330, 140737488355328) = 01583 ceiling(281474976710656, 281474976710656) = 1, ceiling(281474976710658, 281474976710656) =2, ceiling(-281474976710658, 281474976710656) = 01584 ceiling(562949953421312, 562949953421312) = 1, ceiling(562949953421314, 562949953421312) = 2, ceiling(-562949953421314, 562949953421312) = 01585 ceiling(1125899906842624, 1125899906842624) = 1 , ceiling(1125899906842626, 1125899906842624) = 2, ceiling(-1125899906842626, 1125899906842624) = 01586 ceiling(2251799813685248, 2251799813685248) = 1, ceiling(2251799813685250, 2251799813685248) = 2, ceiling(-2251799813685250, 2251799813685248) = 01587 ceiling(4503599627370496, 4503599627370496) = 1, ceiling(4503599627370498, 4503599627370496) =2, ceiling(-4503599627370498, 4503599627370496) = 01588 ceiling(9007199254740992, 9007199254740992) = 1, ceiling(9007199254740994, 9007199254740992) = 2, ceiling(-9007199254740994, 9007199254740992) = 01589 ceiling(18014398509481984, 18014398509481984) = 1 , ceiling(18014398509481986, 18014398509481984) = 2, ceiling(-18014398509481986, 18014398509481984) = 01590 ceiling(36028797018963968, 36028797018963968) = 1, ceiling(36028797018963970, 36028797018963968) = 2, ceiling(-36028797018963970, 36028797018963968) = 01591 ceiling(72057594037927936, 72057594037927936) = 1, ceiling(72057594037927938, 72057594037927936) =2, ceiling(-72057594037927938, 72057594037927936) = 01592 ceiling(144115188075855872, 144115188075855872) = 1 , ceiling(144115188075855874, 144115188075855872) = 2, ceiling(-144115188075855874, 144115188075855872) = 01593 ceiling(288230376151711744, 288230376151711744) = 1, ceiling(288230376151711746, 288230376151711744) = 2, ceiling(-288230376151711746, 288230376151711744) = 01594 ceiling(576460752303423488, 576460752303423488) = 1, ceiling(576460752303423490, 576460752303423488) = 2, ceiling(-576460752303423490, 576460752303423488) = 01595 ceiling(1152921504606846976, 1152921504606846976) = 1 , ceiling(1152921504606846978, 1152921504606846976) =2, ceiling(-1152921504606846978, 1152921504606846976) = 01596 ceiling(2305843009213693952, 2305843009213693952) = 1, ceiling(2305843009213693954, 2305843009213693952) = 2, ceiling(-2305843009213693954, 2305843009213693952) = 01597 ceiling(4611686018427387904, 4611686018427387904) = 1, ceiling(4611686018427387906, 4611686018427387904) = -1, ceiling(-4611686018427387906, 4611686018427387904) = 01598 ceiling(-9223372036854775808, -9223372036854775808) = 0, ceiling(-9223372036854775806, -9223372036854775808) = 0, ceiling(9223372036854775806, -9223372036854775808) = 01843 ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(-4, 2) = -4 1844 ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(-6, 4) = 0 1845 ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(-10, 8) = 0 1846 ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(-18, 16) = 0 1847 ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(-34, 32) = 0 1848 ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(-66, 64) = 0 1849 ceiling(128, 128) = 128, ceiling(130, 128) = 256, ceiling(-130, 128) = 0 1850 ceiling(256, 256) = 256, ceiling(258, 256) = 512, ceiling(-258, 256) = 0 1851 ceiling(512, 512) = 512, ceiling(514, 512) = 1024, ceiling(-514, 512) = 0 1852 ceiling(1024, 1024) = 1024, ceiling(1026, 1024) = 2048, ceiling(-1026, 1024) = 0 1853 ceiling(2048, 2048) = 2048, ceiling(2050, 2048) = 4096, ceiling(-2050, 2048) = 0 1854 ceiling(4096, 4096) = 4096, ceiling(4098, 4096) = 8192, ceiling(-4098, 4096) = 0 1855 ceiling(8192, 8192) = 8192, ceiling(8194, 8192) = 16384, ceiling(-8194, 8192) = 0 1856 ceiling(16384, 16384) = 16384, ceiling(16386, 16384) = 32768, ceiling(-16386, 16384) = 0 1857 ceiling(32768, 32768) = 32768, ceiling(32770, 32768) = 65536, ceiling(-32770, 32768) = 0 1858 ceiling(65536, 65536) = 65536, ceiling(65538, 65536) = 131072, ceiling(-65538, 65536) = 0 1859 ceiling(131072, 131072) = 131072, ceiling(131074, 131072) = 262144, ceiling(-131074, 131072) = 0 1860 ceiling(262144, 262144) = 262144, ceiling(262146, 262144) = 524288, ceiling(-262146, 262144) = 0 1861 ceiling(524288, 524288) = 524288, ceiling(524290, 524288) = 1048576, ceiling(-524290, 524288) = 0 1862 ceiling(1048576, 1048576) = 1048576, ceiling(1048578, 1048576) = 2097152, ceiling(-1048578, 1048576) = 0 1863 ceiling(2097152, 2097152) = 2097152, ceiling(2097154, 2097152) = 4194304, ceiling(-2097154, 2097152) = 0 1864 ceiling(4194304, 4194304) = 4194304, ceiling(4194306, 4194304) = 8388608, ceiling(-4194306, 4194304) = 0 1865 ceiling(8388608, 8388608) = 8388608, ceiling(8388610, 8388608) = 16777216, ceiling(-8388610, 8388608) = 0 1866 ceiling(16777216, 16777216) = 16777216, ceiling(16777218, 16777216) = 33554432, ceiling(-16777218, 16777216) = 0 1867 ceiling(33554432, 33554432) = 33554432, ceiling(33554434, 33554432) = 67108864, ceiling(-33554434, 33554432) = 0 1868 ceiling(67108864, 67108864) = 67108864, ceiling(67108866, 67108864) = 134217728, ceiling(-67108866, 67108864) = 0 1869 ceiling(134217728, 134217728) = 134217728, ceiling(134217730, 134217728) = 268435456, ceiling(-134217730, 134217728) = 0 1870 ceiling(268435456, 268435456) = 268435456, ceiling(268435458, 268435456) = 536870912, ceiling(-268435458, 268435456) = 0 1871 ceiling(536870912, 536870912) = 536870912, ceiling(536870914, 536870912) = 1073741824, ceiling(-536870914, 536870912) = 0 1872 ceiling(1073741824, 1073741824) = 1073741824, ceiling(1073741826, 1073741824) = 2147483648, ceiling(-1073741826, 1073741824) = 0 1873 ceiling(2147483648, 2147483648) = 2147483648, ceiling(2147483650, 2147483648) = 4294967296, ceiling(-2147483650, 2147483648) = 0 1874 ceiling(4294967296, 4294967296) = 4294967296, ceiling(4294967298, 4294967296) = 8589934592, ceiling(-4294967298, 4294967296) = 0 1875 ceiling(8589934592, 8589934592) = 8589934592, ceiling(8589934594, 8589934592) = 17179869184, ceiling(-8589934594, 8589934592) = 0 1876 ceiling(17179869184, 17179869184) = 17179869184, ceiling(17179869186, 17179869184) = 34359738368, ceiling(-17179869186, 17179869184) = 0 1877 ceiling(34359738368, 34359738368) = 34359738368, ceiling(34359738370, 34359738368) = 68719476736, ceiling(-34359738370, 34359738368) = 0 1878 ceiling(68719476736, 68719476736) = 68719476736, ceiling(68719476738, 68719476736) = 137438953472, ceiling(-68719476738, 68719476736) = 0 1879 ceiling(137438953472, 137438953472) = 137438953472, ceiling(137438953474, 137438953472) = 274877906944, ceiling(-137438953474, 137438953472) = 0 1880 ceiling(274877906944, 274877906944) = 274877906944, ceiling(274877906946, 274877906944) = 549755813888, ceiling(-274877906946, 274877906944) = 0 1881 ceiling(549755813888, 549755813888) = 549755813888, ceiling(549755813890, 549755813888) = 1099511627776, ceiling(-549755813890, 549755813888) = 0 1882 ceiling(1099511627776, 1099511627776) = 1099511627776, ceiling(1099511627778, 1099511627776) = 2199023255552, ceiling(-1099511627778, 1099511627776) = 0 1883 ceiling(2199023255552, 2199023255552) = 2199023255552, ceiling(2199023255554, 2199023255552) = 4398046511104, ceiling(-2199023255554, 2199023255552) = 0 1884 ceiling(4398046511104, 4398046511104) = 4398046511104, ceiling(4398046511106, 4398046511104) = 8796093022208, ceiling(-4398046511106, 4398046511104) = 0 1885 ceiling(8796093022208, 8796093022208) = 8796093022208, ceiling(8796093022210, 8796093022208) = 17592186044416, ceiling(-8796093022210, 8796093022208) = 0 1886 ceiling(17592186044416, 17592186044416) = 17592186044416, ceiling(17592186044418, 17592186044416) = 35184372088832, ceiling(-17592186044418, 17592186044416) = 0 1887 ceiling(35184372088832, 35184372088832) = 35184372088832, ceiling(35184372088834, 35184372088832) = 70368744177664, ceiling(-35184372088834, 35184372088832) = 0 1888 ceiling(70368744177664, 70368744177664) = 70368744177664, ceiling(70368744177666, 70368744177664) = 140737488355328, ceiling(-70368744177666, 70368744177664) = 0 1889 ceiling(140737488355328, 140737488355328) = 140737488355328, ceiling(140737488355330, 140737488355328) = 281474976710656, ceiling(-140737488355330, 140737488355328) = 0 1890 ceiling(281474976710656, 281474976710656) = 281474976710656, ceiling(281474976710658, 281474976710656) = 562949953421312, ceiling(-281474976710658, 281474976710656) = 0 1891 ceiling(562949953421312, 562949953421312) = 562949953421312, ceiling(562949953421314, 562949953421312) = 1125899906842624, ceiling(-562949953421314, 562949953421312) = 0 1892 ceiling(1125899906842624, 1125899906842624) = 1125899906842624, ceiling(1125899906842626, 1125899906842624) = 2251799813685248, ceiling(-1125899906842626, 1125899906842624) = 0 1893 ceiling(2251799813685248, 2251799813685248) = 2251799813685248, ceiling(2251799813685250, 2251799813685248) = 4503599627370496, ceiling(-2251799813685250, 2251799813685248) = 0 1894 ceiling(4503599627370496, 4503599627370496) = 4503599627370496, ceiling(4503599627370498, 4503599627370496) = 9007199254740992, ceiling(-4503599627370498, 4503599627370496) = 0 1895 ceiling(9007199254740992, 9007199254740992) = 9007199254740992, ceiling(9007199254740994, 9007199254740992) = 18014398509481984, ceiling(-9007199254740994, 9007199254740992) = 0 1896 ceiling(18014398509481984, 18014398509481984) = 18014398509481984, ceiling(18014398509481986, 18014398509481984) = 36028797018963968, ceiling(-18014398509481986, 18014398509481984) = 0 1897 ceiling(36028797018963968, 36028797018963968) = 36028797018963968, ceiling(36028797018963970, 36028797018963968) = 72057594037927936, ceiling(-36028797018963970, 36028797018963968) = 0 1898 ceiling(72057594037927936, 72057594037927936) = 72057594037927936, ceiling(72057594037927938, 72057594037927936) = 144115188075855872, ceiling(-72057594037927938, 72057594037927936) = 0 1899 ceiling(144115188075855872, 144115188075855872) = 144115188075855872, ceiling(144115188075855874, 144115188075855872) = 288230376151711744, ceiling(-144115188075855874, 144115188075855872) = 0 1900 ceiling(288230376151711744, 288230376151711744) = 288230376151711744, ceiling(288230376151711746, 288230376151711744) = 576460752303423488, ceiling(-288230376151711746, 288230376151711744) = 0 1901 ceiling(576460752303423488, 576460752303423488) = 576460752303423488, ceiling(576460752303423490, 576460752303423488) = 1152921504606846976, ceiling(-576460752303423490, 576460752303423488) = 0 1902 ceiling(1152921504606846976, 1152921504606846976) = 1152921504606846976, ceiling(1152921504606846978, 1152921504606846976) = 2305843009213693952, ceiling(-1152921504606846978, 1152921504606846976) = 0 1903 ceiling(2305843009213693952, 2305843009213693952) = 2305843009213693952, ceiling(2305843009213693954, 2305843009213693952) = 4611686018427387904, ceiling(-2305843009213693954, 2305843009213693952) = 0 1904 ceiling(4611686018427387904, 4611686018427387904) = 4611686018427387904, ceiling(4611686018427387906, 4611686018427387904) = -4611686018427387904, ceiling(-4611686018427387906, 4611686018427387904) = 0 1905 ceiling(-9223372036854775808, -9223372036854775808) = -9223372036854775808, ceiling(-9223372036854775806, -9223372036854775808) = 0, ceiling(9223372036854775806, -9223372036854775808) = 0 1599 1906 1600 1907 unsigned long long int 1601 1908 ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(18446744073709551613, 1) = 18446744073709551613 1602 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(18446744073709551612, 2) = 92233720368547758061603 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(18446744073709551610, 4) = 46116860184273879031604 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(18446744073709551606, 8) = 23058430092136939511605 ceiling(16, 16) = 1 , ceiling(18, 16) = 2, ceiling(18446744073709551598, 16) = 11529215046068469751606 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(18446744073709551582, 32) = 5764607523034234871607 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(18446744073709551550, 64) = 2882303761517117431608 ceiling(128, 128) = 1 , ceiling(130, 128) = 2, ceiling(18446744073709551486, 128) = 1441151880758558711609 ceiling(256, 256) = 1, ceiling(258, 256) = 2, ceiling(18446744073709551358, 256) = 720575940379279351610 ceiling(512, 512) = 1, ceiling(514, 512) = 2, ceiling(18446744073709551102, 512) = 360287970189639671611 ceiling(1024, 1024) = 1 , ceiling(1026, 1024) = 2, ceiling(18446744073709550590, 1024) = 180143985094819831612 ceiling(2048, 2048) = 1, ceiling(2050, 2048) = 2, ceiling(18446744073709549566, 2048) = 90071992547409911613 ceiling(4096, 4096) = 1, ceiling(4098, 4096) = 2, ceiling(18446744073709547518, 4096) = 45035996273704951614 ceiling(8192, 8192) = 1, ceiling(8194, 8192) = 2, ceiling(18446744073709543422, 8192) = 22517998136852471615 ceiling(16384, 16384) = 1 , ceiling(16386, 16384) = 2, ceiling(18446744073709535230, 16384) = 11258999068426231616 ceiling(32768, 32768) = 1, ceiling(32770, 32768) = 2, ceiling(18446744073709518846, 32768) = 5629499534213111617 ceiling(65536, 65536) = 1, ceiling(65538, 65536) = 2, ceiling(18446744073709486078, 65536) = 2814749767106551618 ceiling(131072, 131072) = 1 , ceiling(131074, 131072) = 2, ceiling(18446744073709420542, 131072) = 1407374883553271619 ceiling(262144, 262144) = 1, ceiling(262146, 262144) = 2, ceiling(18446744073709289470, 262144) = 703687441776631620 ceiling(524288, 524288) = 1, ceiling(524290, 524288) = 2, ceiling(18446744073709027326, 524288) = 351843720888311621 ceiling(1048576, 1048576) = 1 , ceiling(1048578, 1048576) = 2, ceiling(18446744073708503038, 1048576) = 175921860444151622 ceiling(2097152, 2097152) = 1, ceiling(2097154, 2097152) = 2, ceiling(18446744073707454462, 2097152) = 87960930222071623 ceiling(4194304, 4194304) = 1, ceiling(4194306, 4194304) = 2, ceiling(18446744073705357310, 4194304) = 43980465111031624 ceiling(8388608, 8388608) = 1, ceiling(8388610, 8388608) = 2, ceiling(18446744073701163006, 8388608) = 21990232555511625 ceiling(16777216, 16777216) = 1 , ceiling(16777218, 16777216) = 2, ceiling(18446744073692774398, 16777216) = 10995116277751626 ceiling(33554432, 33554432) = 1, ceiling(33554434, 33554432) = 2, ceiling(18446744073675997182, 33554432) = 5497558138871627 ceiling(67108864, 67108864) = 1, ceiling(67108866, 67108864) = 2, ceiling(18446744073642442750, 67108864) = 2748779069431628 ceiling(134217728, 134217728) = 1 , ceiling(134217730, 134217728) = 2, ceiling(18446744073575333886, 134217728) = 1374389534711629 ceiling(268435456, 268435456) = 1, ceiling(268435458, 268435456) = 2, ceiling(18446744073441116158, 268435456) = 687194767351630 ceiling(536870912, 536870912) = 1, ceiling(536870914, 536870912) = 2, ceiling(18446744073172680702, 536870912) = 343597383671631 ceiling(1073741824, 1073741824) = 1 , ceiling(1073741826, 1073741824) = 2, ceiling(18446744072635809790, 1073741824) = 171798691831632 ceiling(2147483648, 2147483648) = 1, ceiling(2147483650, 2147483648) = 2, ceiling(18446744071562067966, 2147483648) = 85899345911633 ceiling(4294967296, 4294967296) = 1, ceiling(4294967298, 4294967296) = 2, ceiling(18446744069414584318, 4294967296) = 42949672951634 ceiling(8589934592, 8589934592) = 1, ceiling(8589934594, 8589934592) = 2, ceiling(18446744065119617022, 8589934592) = 21474836471635 ceiling(17179869184, 17179869184) = 1 , ceiling(17179869186, 17179869184) = 2, ceiling(18446744056529682430, 17179869184) = 10737418231636 ceiling(34359738368, 34359738368) = 1, ceiling(34359738370, 34359738368) = 2, ceiling(18446744039349813246, 34359738368) = 5368709111637 ceiling(68719476736, 68719476736) = 1, ceiling(68719476738, 68719476736) = 2, ceiling(18446744004990074878, 68719476736) = 2684354551638 ceiling(137438953472, 137438953472) = 1 , ceiling(137438953474, 137438953472) = 2, ceiling(18446743936270598142, 137438953472) = 1342177271639 ceiling(274877906944, 274877906944) = 1, ceiling(274877906946, 274877906944) = 2, ceiling(18446743798831644670, 274877906944) = 671088631640 ceiling(549755813888, 549755813888) = 1, ceiling(549755813890, 549755813888) = 2, ceiling(18446743523953737726, 549755813888) = 335544311641 ceiling(1099511627776, 1099511627776) = 1 , ceiling(1099511627778, 1099511627776) = 2, ceiling(18446742974197923838, 1099511627776) = 167772151642 ceiling(2199023255552, 2199023255552) = 1, ceiling(2199023255554, 2199023255552) = 2, ceiling(18446741874686296062, 2199023255552) = 83886071643 ceiling(4398046511104, 4398046511104) = 1, ceiling(4398046511106, 4398046511104) = 2, ceiling(18446739675663040510, 4398046511104) = 41943031644 ceiling(8796093022208, 8796093022208) = 1, ceiling(8796093022210, 8796093022208) = 2, ceiling(18446735277616529406, 8796093022208) = 20971511645 ceiling(17592186044416, 17592186044416) = 1 , ceiling(17592186044418, 17592186044416) = 2, ceiling(18446726481523507198, 17592186044416) = 10485751646 ceiling(35184372088832, 35184372088832) = 1, ceiling(35184372088834, 35184372088832) = 2, ceiling(18446708889337462782, 35184372088832) = 5242871647 ceiling(70368744177664, 70368744177664) = 1, ceiling(70368744177666, 70368744177664) = 2, ceiling(18446673704965373950, 70368744177664) = 2621431648 ceiling(140737488355328, 140737488355328) = 1 , ceiling(140737488355330, 140737488355328) = 2, ceiling(18446603336221196286, 140737488355328) = 1310711649 ceiling(281474976710656, 281474976710656) = 1, ceiling(281474976710658, 281474976710656) = 2, ceiling(18446462598732840958, 281474976710656) = 655351650 ceiling(562949953421312, 562949953421312) = 1, ceiling(562949953421314, 562949953421312) = 2, ceiling(18446181123756130302, 562949953421312) = 327671651 ceiling(1125899906842624, 1125899906842624) = 1 , ceiling(1125899906842626, 1125899906842624) = 2, ceiling(18445618173802708990, 1125899906842624) = 163831652 ceiling(2251799813685248, 2251799813685248) = 1, ceiling(2251799813685250, 2251799813685248) = 2, ceiling(18444492273895866366, 2251799813685248) = 81911653 ceiling(4503599627370496, 4503599627370496) = 1, ceiling(4503599627370498, 4503599627370496) = 2, ceiling(18442240474082181118, 4503599627370496) = 40951654 ceiling(9007199254740992, 9007199254740992) = 1, ceiling(9007199254740994, 9007199254740992) = 2, ceiling(18437736874454810622, 9007199254740992) = 20471655 ceiling(18014398509481984, 18014398509481984) = 1 , ceiling(18014398509481986, 18014398509481984) = 2, ceiling(18428729675200069630, 18014398509481984) = 10231656 ceiling(36028797018963968, 36028797018963968) = 1, ceiling(36028797018963970, 36028797018963968) = 2, ceiling(18410715276690587646, 36028797018963968) = 5111657 ceiling(72057594037927936, 72057594037927936) = 1, ceiling(72057594037927938, 72057594037927936) = 2, ceiling(18374686479671623678, 72057594037927936) = 2551658 ceiling(144115188075855872, 144115188075855872) = 1 , ceiling(144115188075855874, 144115188075855872) = 2, ceiling(18302628885633695742, 144115188075855872) = 1271659 ceiling(288230376151711744, 288230376151711744) = 1, ceiling(288230376151711746, 288230376151711744) = 2, ceiling(18158513697557839870, 288230376151711744) = 631660 ceiling(576460752303423488, 576460752303423488) = 1, ceiling(576460752303423490, 576460752303423488) = 2, ceiling(17870283321406128126, 576460752303423488) = 311661 ceiling(1152921504606846976, 1152921504606846976) = 1 , ceiling(1152921504606846978, 1152921504606846976) = 2, ceiling(17293822569102704638, 1152921504606846976) = 151662 ceiling(2305843009213693952, 2305843009213693952) = 1, ceiling(2305843009213693954, 2305843009213693952) = 2, ceiling(16140901064495857662, 2305843009213693952) = 71663 ceiling(4611686018427387904, 4611686018427387904) = 1, ceiling(4611686018427387906, 4611686018427387904) = 2, ceiling(13835058055282163710, 4611686018427387904) = 31664 ceiling(9223372036854775808, 9223372036854775808) = 1, ceiling(9223372036854775810, 9223372036854775808) = 0, ceiling(9223372036854775806, 9223372036854775808) = 11665 1909 ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(18446744073709551612, 2) = 18446744073709551612 1910 ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(18446744073709551610, 4) = 18446744073709551612 1911 ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(18446744073709551606, 8) = 18446744073709551608 1912 ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(18446744073709551598, 16) = 18446744073709551600 1913 ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(18446744073709551582, 32) = 18446744073709551584 1914 ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(18446744073709551550, 64) = 18446744073709551552 1915 ceiling(128, 128) = 128, ceiling(130, 128) = 256, ceiling(18446744073709551486, 128) = 18446744073709551488 1916 ceiling(256, 256) = 256, ceiling(258, 256) = 512, ceiling(18446744073709551358, 256) = 18446744073709551360 1917 ceiling(512, 512) = 512, ceiling(514, 512) = 1024, ceiling(18446744073709551102, 512) = 18446744073709551104 1918 ceiling(1024, 1024) = 1024, ceiling(1026, 1024) = 2048, ceiling(18446744073709550590, 1024) = 18446744073709550592 1919 ceiling(2048, 2048) = 2048, ceiling(2050, 2048) = 4096, ceiling(18446744073709549566, 2048) = 18446744073709549568 1920 ceiling(4096, 4096) = 4096, ceiling(4098, 4096) = 8192, ceiling(18446744073709547518, 4096) = 18446744073709547520 1921 ceiling(8192, 8192) = 8192, ceiling(8194, 8192) = 16384, ceiling(18446744073709543422, 8192) = 18446744073709543424 1922 ceiling(16384, 16384) = 16384, ceiling(16386, 16384) = 32768, ceiling(18446744073709535230, 16384) = 18446744073709535232 1923 ceiling(32768, 32768) = 32768, ceiling(32770, 32768) = 65536, ceiling(18446744073709518846, 32768) = 18446744073709518848 1924 ceiling(65536, 65536) = 65536, ceiling(65538, 65536) = 131072, ceiling(18446744073709486078, 65536) = 18446744073709486080 1925 ceiling(131072, 131072) = 131072, ceiling(131074, 131072) = 262144, ceiling(18446744073709420542, 131072) = 18446744073709420544 1926 ceiling(262144, 262144) = 262144, ceiling(262146, 262144) = 524288, ceiling(18446744073709289470, 262144) = 18446744073709289472 1927 ceiling(524288, 524288) = 524288, ceiling(524290, 524288) = 1048576, ceiling(18446744073709027326, 524288) = 18446744073709027328 1928 ceiling(1048576, 1048576) = 1048576, ceiling(1048578, 1048576) = 2097152, ceiling(18446744073708503038, 1048576) = 18446744073708503040 1929 ceiling(2097152, 2097152) = 2097152, ceiling(2097154, 2097152) = 4194304, ceiling(18446744073707454462, 2097152) = 18446744073707454464 1930 ceiling(4194304, 4194304) = 4194304, ceiling(4194306, 4194304) = 8388608, ceiling(18446744073705357310, 4194304) = 18446744073705357312 1931 ceiling(8388608, 8388608) = 8388608, ceiling(8388610, 8388608) = 16777216, ceiling(18446744073701163006, 8388608) = 18446744073701163008 1932 ceiling(16777216, 16777216) = 16777216, ceiling(16777218, 16777216) = 33554432, ceiling(18446744073692774398, 16777216) = 18446744073692774400 1933 ceiling(33554432, 33554432) = 33554432, ceiling(33554434, 33554432) = 67108864, ceiling(18446744073675997182, 33554432) = 18446744073675997184 1934 ceiling(67108864, 67108864) = 67108864, ceiling(67108866, 67108864) = 134217728, ceiling(18446744073642442750, 67108864) = 18446744073642442752 1935 ceiling(134217728, 134217728) = 134217728, ceiling(134217730, 134217728) = 268435456, ceiling(18446744073575333886, 134217728) = 18446744073575333888 1936 ceiling(268435456, 268435456) = 268435456, ceiling(268435458, 268435456) = 536870912, ceiling(18446744073441116158, 268435456) = 18446744073441116160 1937 ceiling(536870912, 536870912) = 536870912, ceiling(536870914, 536870912) = 1073741824, ceiling(18446744073172680702, 536870912) = 18446744073172680704 1938 ceiling(1073741824, 1073741824) = 1073741824, ceiling(1073741826, 1073741824) = 2147483648, ceiling(18446744072635809790, 1073741824) = 18446744072635809792 1939 ceiling(2147483648, 2147483648) = 2147483648, ceiling(2147483650, 2147483648) = 4294967296, ceiling(18446744071562067966, 2147483648) = 18446744071562067968 1940 ceiling(4294967296, 4294967296) = 4294967296, ceiling(4294967298, 4294967296) = 8589934592, ceiling(18446744069414584318, 4294967296) = 18446744069414584320 1941 ceiling(8589934592, 8589934592) = 8589934592, ceiling(8589934594, 8589934592) = 17179869184, ceiling(18446744065119617022, 8589934592) = 18446744065119617024 1942 ceiling(17179869184, 17179869184) = 17179869184, ceiling(17179869186, 17179869184) = 34359738368, ceiling(18446744056529682430, 17179869184) = 18446744056529682432 1943 ceiling(34359738368, 34359738368) = 34359738368, ceiling(34359738370, 34359738368) = 68719476736, ceiling(18446744039349813246, 34359738368) = 18446744039349813248 1944 ceiling(68719476736, 68719476736) = 68719476736, ceiling(68719476738, 68719476736) = 137438953472, ceiling(18446744004990074878, 68719476736) = 18446744004990074880 1945 ceiling(137438953472, 137438953472) = 137438953472, ceiling(137438953474, 137438953472) = 274877906944, ceiling(18446743936270598142, 137438953472) = 18446743936270598144 1946 ceiling(274877906944, 274877906944) = 274877906944, ceiling(274877906946, 274877906944) = 549755813888, ceiling(18446743798831644670, 274877906944) = 18446743798831644672 1947 ceiling(549755813888, 549755813888) = 549755813888, ceiling(549755813890, 549755813888) = 1099511627776, ceiling(18446743523953737726, 549755813888) = 18446743523953737728 1948 ceiling(1099511627776, 1099511627776) = 1099511627776, ceiling(1099511627778, 1099511627776) = 2199023255552, ceiling(18446742974197923838, 1099511627776) = 18446742974197923840 1949 ceiling(2199023255552, 2199023255552) = 2199023255552, ceiling(2199023255554, 2199023255552) = 4398046511104, ceiling(18446741874686296062, 2199023255552) = 18446741874686296064 1950 ceiling(4398046511104, 4398046511104) = 4398046511104, ceiling(4398046511106, 4398046511104) = 8796093022208, ceiling(18446739675663040510, 4398046511104) = 18446739675663040512 1951 ceiling(8796093022208, 8796093022208) = 8796093022208, ceiling(8796093022210, 8796093022208) = 17592186044416, ceiling(18446735277616529406, 8796093022208) = 18446735277616529408 1952 ceiling(17592186044416, 17592186044416) = 17592186044416, ceiling(17592186044418, 17592186044416) = 35184372088832, ceiling(18446726481523507198, 17592186044416) = 18446726481523507200 1953 ceiling(35184372088832, 35184372088832) = 35184372088832, ceiling(35184372088834, 35184372088832) = 70368744177664, ceiling(18446708889337462782, 35184372088832) = 18446708889337462784 1954 ceiling(70368744177664, 70368744177664) = 70368744177664, ceiling(70368744177666, 70368744177664) = 140737488355328, ceiling(18446673704965373950, 70368744177664) = 18446673704965373952 1955 ceiling(140737488355328, 140737488355328) = 140737488355328, ceiling(140737488355330, 140737488355328) = 281474976710656, ceiling(18446603336221196286, 140737488355328) = 18446603336221196288 1956 ceiling(281474976710656, 281474976710656) = 281474976710656, ceiling(281474976710658, 281474976710656) = 562949953421312, ceiling(18446462598732840958, 281474976710656) = 18446462598732840960 1957 ceiling(562949953421312, 562949953421312) = 562949953421312, ceiling(562949953421314, 562949953421312) = 1125899906842624, ceiling(18446181123756130302, 562949953421312) = 18446181123756130304 1958 ceiling(1125899906842624, 1125899906842624) = 1125899906842624, ceiling(1125899906842626, 1125899906842624) = 2251799813685248, ceiling(18445618173802708990, 1125899906842624) = 18445618173802708992 1959 ceiling(2251799813685248, 2251799813685248) = 2251799813685248, ceiling(2251799813685250, 2251799813685248) = 4503599627370496, ceiling(18444492273895866366, 2251799813685248) = 18444492273895866368 1960 ceiling(4503599627370496, 4503599627370496) = 4503599627370496, ceiling(4503599627370498, 4503599627370496) = 9007199254740992, ceiling(18442240474082181118, 4503599627370496) = 18442240474082181120 1961 ceiling(9007199254740992, 9007199254740992) = 9007199254740992, ceiling(9007199254740994, 9007199254740992) = 18014398509481984, ceiling(18437736874454810622, 9007199254740992) = 18437736874454810624 1962 ceiling(18014398509481984, 18014398509481984) = 18014398509481984, ceiling(18014398509481986, 18014398509481984) = 36028797018963968, ceiling(18428729675200069630, 18014398509481984) = 18428729675200069632 1963 ceiling(36028797018963968, 36028797018963968) = 36028797018963968, ceiling(36028797018963970, 36028797018963968) = 72057594037927936, ceiling(18410715276690587646, 36028797018963968) = 18410715276690587648 1964 ceiling(72057594037927936, 72057594037927936) = 72057594037927936, ceiling(72057594037927938, 72057594037927936) = 144115188075855872, ceiling(18374686479671623678, 72057594037927936) = 18374686479671623680 1965 ceiling(144115188075855872, 144115188075855872) = 144115188075855872, ceiling(144115188075855874, 144115188075855872) = 288230376151711744, ceiling(18302628885633695742, 144115188075855872) = 18302628885633695744 1966 ceiling(288230376151711744, 288230376151711744) = 288230376151711744, ceiling(288230376151711746, 288230376151711744) = 576460752303423488, ceiling(18158513697557839870, 288230376151711744) = 18158513697557839872 1967 ceiling(576460752303423488, 576460752303423488) = 576460752303423488, ceiling(576460752303423490, 576460752303423488) = 1152921504606846976, ceiling(17870283321406128126, 576460752303423488) = 17870283321406128128 1968 ceiling(1152921504606846976, 1152921504606846976) = 1152921504606846976, ceiling(1152921504606846978, 1152921504606846976) = 2305843009213693952, ceiling(17293822569102704638, 1152921504606846976) = 17293822569102704640 1969 ceiling(2305843009213693952, 2305843009213693952) = 2305843009213693952, ceiling(2305843009213693954, 2305843009213693952) = 4611686018427387904, ceiling(16140901064495857662, 2305843009213693952) = 16140901064495857664 1970 ceiling(4611686018427387904, 4611686018427387904) = 4611686018427387904, ceiling(4611686018427387906, 4611686018427387904) = 9223372036854775808, ceiling(13835058055282163710, 4611686018427387904) = 13835058055282163712 1971 ceiling(9223372036854775808, 9223372036854775808) = 9223372036854775808, ceiling(9223372036854775810, 9223372036854775808) = 0, ceiling(9223372036854775806, 9223372036854775808) = 9223372036854775808 1972 -
tests/.expect/castError.txt
r07d867b r22f94a4 1 castError.cfa:2 1:1 error: Cannot choose between 3 alternatives for expression1 castError.cfa:23:1 error: Cannot choose between 3 alternatives for expression 2 2 Explicit Cast of: 3 3 Name: f … … 35 35 36 36 37 castError.cfa:2 6:1 error: Cannot choose between 2 alternatives for expression37 castError.cfa:28:1 error: Cannot choose between 2 alternatives for expression 38 38 Generated Cast of: 39 39 Comma Expression: … … 62 62 63 63 64 castError.cfa:30:1 error: No reasonable alternatives for expression Explicit Cast of: 65 Name: sint 66 ... to: 67 instance of struct S with body 1 68 ... with parameters 69 char 70 -
tests/.expect/copyfile.txt
r07d867b r22f94a4 8 8 // 9 9 // Author : Peter A. Buhr 10 // Created On : Tue Jul 16 16:47:22 201910 // Created On : Fri Jun 19 13:44:05 2020 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Jul 17 18:04:44 201913 // Update Count : 2612 // Last Modified On : Fri Jun 19 17:58:03 2020 13 // Update Count : 4 14 14 // 15 15 16 16 #include <fstream.hfa> 17 #include < stdlib.hfa> // new/delete17 #include <exception.hfa> 18 18 19 19 int main( int argc, char * argv[] ) { 20 ifstream * in = &stdin; // default files 21 ofstream * out = &stdout; 20 ifstream in = stdin; // copy default files 21 ofstream out = stdout; 22 22 23 try { 23 24 choose ( argc ) { 24 25 case 2, 3: 25 in = new( (const char *)argv[1] );// open input file first as output creates file26 if ( argc == 3 ) out = new( (const char *)argv[2] ); // only open output if input opens as output created if nonexistent27 case 1: ; // use default files26 open( in, argv[1] ); // open input file first as output creates file 27 if ( argc == 3 ) open( out, argv[2] ); // do not create output unless input opens 28 case 1: ; // use default files 28 29 default: 29 exit | "Usage[ input-file (default stdin) [ output-file (default stdout) ] ]";30 exit | "Usage" | argv[0] | "[ input-file (default stdin) [ output-file (default stdout) ] ]"; 30 31 } // choose 32 } catch( Open_Failure * ex ; ex->istream == &in ) { 33 exit | "Unable to open input file" | argv[1]; 34 } catch( Open_Failure * ex ; ex->ostream == &out ) { 35 close( in ); // optional 36 exit | "Unable to open output file" | argv[2]; 37 } // try 31 38 32 char ch; 33 *out | nlOff; // turn off auto newline 34 *in | nlOn; // turn on reading newline 39 out | nlOff; // turn off auto newline 40 in | nlOn; // turn on reading newline 35 41 36 for () { // read all characters 37 *in | ch; 38 if ( eof( *in ) ) break; // eof ? 39 *out | ch; 40 } // for 41 } finally { 42 if ( in != &stdin ) delete( in ); // close file, do not delete stdin! 43 if ( out != &stdout ) delete( out ); // close file, do not delete stdout! 44 } // try 42 char ch; 43 for () { // read all characters 44 in | ch; 45 if ( eof( in ) ) break; // eof ? 46 out | ch; 47 } //for 45 48 } // main 46 49 -
tests/.expect/functions.x64.txt
r07d867b r22f94a4 121 121 122 122 } 123 struct _conc__tuple2_0; 123 124 struct _conc__tuple2_0 { 124 125 signed int field_0; … … 157 158 158 159 } 160 struct _conc__tuple3_1; 159 161 struct _conc__tuple3_1 { 160 162 signed int field_0; … … 170 172 __attribute__ ((unused)) struct _conc__tuple3_1 _X9_retval_fT3iii_1 = { }; 171 173 } 174 struct _conc__tuple3_2; 172 175 struct _conc__tuple3_2 { 173 176 signed int field_0; … … 260 263 __attribute__ ((unused)) signed int *const _X10_retval_f3KPi_1; 261 264 } 265 struct _conc__tuple2_3; 262 266 struct _conc__tuple2_3 { 263 267 signed int *field_0; -
tests/.expect/functions.x86.txt
r07d867b r22f94a4 121 121 122 122 } 123 struct _conc__tuple2_0; 123 124 struct _conc__tuple2_0 { 124 125 signed int field_0; … … 157 158 158 159 } 160 struct _conc__tuple3_1; 159 161 struct _conc__tuple3_1 { 160 162 signed int field_0; … … 170 172 __attribute__ ((unused)) struct _conc__tuple3_1 _X9_retval_fT3iii_1 = { }; 171 173 } 174 struct _conc__tuple3_2; 172 175 struct _conc__tuple3_2 { 173 176 signed int field_0; … … 260 263 __attribute__ ((unused)) signed int *const _X10_retval_f3KPi_1; 261 264 } 265 struct _conc__tuple2_3; 262 266 struct _conc__tuple2_3 { 263 267 signed int *field_0; -
tests/.expect/time.txt
r07d867b r22f94a4 1 1 10800 2 3.375 12 1.00001 2 0.125 0.0333333333333333 3.375 12000. 1000010. 2 3 0 2 3.375 3 4 7 7 7 -
tests/.in/copyfile.txt
r07d867b r22f94a4 8 8 // 9 9 // Author : Peter A. Buhr 10 // Created On : Tue Jul 16 16:47:22 201910 // Created On : Fri Jun 19 13:44:05 2020 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Jul 17 18:04:44 201913 // Update Count : 2612 // Last Modified On : Fri Jun 19 17:58:03 2020 13 // Update Count : 4 14 14 // 15 15 16 16 #include <fstream.hfa> 17 #include < stdlib.hfa> // new/delete17 #include <exception.hfa> 18 18 19 19 int main( int argc, char * argv[] ) { 20 ifstream * in = &stdin; // default files 21 ofstream * out = &stdout; 20 ifstream in = stdin; // copy default files 21 ofstream out = stdout; 22 22 23 try { 23 24 choose ( argc ) { 24 25 case 2, 3: 25 in = new( (const char *)argv[1] );// open input file first as output creates file26 if ( argc == 3 ) out = new( (const char *)argv[2] ); // only open output if input opens as output created if nonexistent27 case 1: ; // use default files26 open( in, argv[1] ); // open input file first as output creates file 27 if ( argc == 3 ) open( out, argv[2] ); // do not create output unless input opens 28 case 1: ; // use default files 28 29 default: 29 exit | "Usage[ input-file (default stdin) [ output-file (default stdout) ] ]";30 exit | "Usage" | argv[0] | "[ input-file (default stdin) [ output-file (default stdout) ] ]"; 30 31 } // choose 32 } catch( Open_Failure * ex ; ex->istream == &in ) { 33 exit | "Unable to open input file" | argv[1]; 34 } catch( Open_Failure * ex ; ex->ostream == &out ) { 35 close( in ); // optional 36 exit | "Unable to open output file" | argv[2]; 37 } // try 31 38 32 char ch; 33 *out | nlOff; // turn off auto newline 34 *in | nlOn; // turn on reading newline 39 out | nlOff; // turn off auto newline 40 in | nlOn; // turn on reading newline 35 41 36 for () { // read all characters 37 *in | ch; 38 if ( eof( *in ) ) break; // eof ? 39 *out | ch; 40 } // for 41 } finally { 42 if ( in != &stdin ) delete( in ); // close file, do not delete stdin! 43 if ( out != &stdout ) delete( out ); // close file, do not delete stdout! 44 } // try 42 char ch; 43 for () { // read all characters 44 in | ch; 45 if ( eof( in ) ) break; // eof ? 46 out | ch; 47 } //for 45 48 } // main 46 49 -
tests/.in/manipulatorsInput.txt
r07d867b r22f94a4 27 27 3.5 3.5 3.456E+23.456E+2 -0x1.2p-3 3.5 0X1.23p3 3.5 28 28 3.5 3.5 3.456E+23.456E+2 -0x1.2p-3 3.5 0X1.23p3 3.5 29 25 -25 42798 30 1402432282 1505850196993244515 31 394749758663249135511342 32 12935154696204706112391834394 33 34 423859149128410414395372834994551 35 36 37 13889016598639747063234935497057631587 38 170141183460469231731687303715884105727 39 340282366920938463463374607431768211455 40 -340282366920938463463374607431768211455 41 340282366920938463463374607431768211455999 42 1234567890123456789 -1234567890123456789 -
tests/Makefile.am
r07d867b r22f94a4 18 18 ACLOCAL_AMFLAGS = -I automake 19 19 20 include $(top_srcdir)/src/cfa.make 20 include $(top_srcdir)/tools/build/cfa.make 21 22 DEFAULT_INCLUDES = -I${abs_srcdir} 21 23 22 24 debug=yes -
tests/avltree/avl1.cfa
r07d867b r22f94a4 24 24 tree(K, V) * create(K key, V value) { 25 25 // infinite loop trying to resolve ... t = malloc(); 26 tree(K, V) * t = malloc(sizeof(tree(K,V)));26 tree(K, V) * t = ( tree(K, V) * ) malloc(sizeof(tree(K,V))); 27 27 (*t){ key, value }; 28 28 return t; -
tests/bitmanip3.cfa
r07d867b r22f94a4 10 10 // Created On : Tue Apr 7 21:22:59 2020 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Apr 21 16:25:09202013 // Update Count : 6 112 // Last Modified On : Mon Aug 10 09:31:35 2020 13 // Update Count : 65 14 14 // 15 15 … … 134 134 135 135 printf( "signed char\n" ); 136 sc = 0;137 scr1 = floor2( sc, sc ), scr2 = floor2( sc + 2hh, sc ), scr3 = floor2( -sc - 2hh, sc );138 printf( "floor2(%hhd, %hhd) = %hhd, floor2(%hhd, %hhd) = %hhd, floor2(%hhd, %hhd) = %hhd\n", sc, sc, scr1, sc + 2hh, sc, scr2, -sc - 2hh, sc, scr3 );136 // sc = 0; 137 // scr1 = floor2( sc, sc ), scr2 = floor2( sc + 2hh, sc ), scr3 = floor2( -sc - 2hh, sc ); 138 // printf( "floor2(%hhd, %hhd) = %hhd, floor2(%hhd, %hhd) = %hhd, floor2(%hhd, %hhd) = %hhd\n", sc, sc, scr1, sc + 2hh, sc, scr2, -sc - 2hh, sc, scr3 ); 139 139 for ( sc = 1; sc != 0; sc <<= 1 ) { 140 140 scr1 = floor2( sc, sc ); scr2 = floor2( sc + 2hh, sc ); scr3 = floor2( -sc - 2hh, sc ); … … 144 144 145 145 printf( "unsigned char\n" ); 146 uc = 0;147 ucr1 = floor2( uc, uc ), ucr2 = floor2( uc + 2hh, uc ), ucr3 = floor2( -uc - 2hh, uc );148 printf( "floor2(%hhu, %hhu) = %hhu, floor2(%hhu, %hhu) = %hhu, floor2(%hhu, %hhu) = %hhu\n", uc, uc, ucr1, uc + 2uhh, uc, ucr2, -uc - 2uhh, uc, ucr3 );146 // uc = 0; 147 // ucr1 = floor2( uc, uc ), ucr2 = floor2( uc + 2hh, uc ), ucr3 = floor2( -uc - 2hh, uc ); 148 // printf( "floor2(%hhu, %hhu) = %hhu, floor2(%hhu, %hhu) = %hhu, floor2(%hhu, %hhu) = %hhu\n", uc, uc, ucr1, uc + 2uhh, uc, ucr2, -uc - 2uhh, uc, ucr3 ); 149 149 for ( uc = 1; uc != 0; uc <<= 1 ) { 150 150 ucr1 = floor2( uc, uc ); ucr2 = floor2( uc + 2hh, uc ); ucr3 = floor2( -uc - 2hh, uc ); … … 154 154 155 155 printf( "short int\n" ); 156 si = 0;157 sir1 = floor2( si, si ), sir2 = floor2( si + 2hh, si ), sir3 = floor2( -si - 2hh, si );158 printf( "floor2(%hd, %hd) = %hd, floor2(%hd, %hd) = %hd, floor2(%hd, %hd) = %hd\n", si, si, sir1, si + 2h, si, sir2, -si - 2h, si, sir3 );156 // si = 0; 157 // sir1 = floor2( si, si ), sir2 = floor2( si + 2hh, si ), sir3 = floor2( -si - 2hh, si ); 158 // printf( "floor2(%hd, %hd) = %hd, floor2(%hd, %hd) = %hd, floor2(%hd, %hd) = %hd\n", si, si, sir1, si + 2h, si, sir2, -si - 2h, si, sir3 ); 159 159 for ( si = 1; si != 0; si <<= 1 ) { 160 160 sir1 = floor2( si, si ); sir2 = floor2( si + 2hh, si ); sir3 = floor2( -si - 2hh, si ); … … 164 164 165 165 printf( "unsigned short int\n" ); 166 usi = 0;167 usir1 = floor2( usi, usi ), usir2 = floor2( usi + 2hh, usi ), usir3 = floor2( -usi - 2hh, usi );168 printf( "floor2(%hu, %hu) = %hu, floor2(%hu, %hu) = %hu, floor2(%hu, %hu) = %hu\n", usi, usi, usir1, usi + 2uh, usi, usir2, -usi - 2uh, usi, usir3 );166 // usi = 0; 167 // usir1 = floor2( usi, usi ), usir2 = floor2( usi + 2hh, usi ), usir3 = floor2( -usi - 2hh, usi ); 168 // printf( "floor2(%hu, %hu) = %hu, floor2(%hu, %hu) = %hu, floor2(%hu, %hu) = %hu\n", usi, usi, usir1, usi + 2uh, usi, usir2, -usi - 2uh, usi, usir3 ); 169 169 for ( usi = 1; usi != 0; usi <<= 1 ) { 170 170 usir1 = floor2( usi, usi ); usir2 = floor2( usi + 2hh, usi ); usir3 = floor2( -usi - 2hh, usi ); … … 174 174 175 175 printf( "int\n" ); 176 i = 0;177 ir1 = floor2( i, i ), ir2 = floor2( i + 2hh, i ), ir3 = floor2( -i - 2hh, i );178 printf( "floor2(%d, %d) = %d, floor2(%d, %d) = %d, floor2(%d, %d) = %d\n", i, i, ir1, i + 2h, i, ir2, -i - 2h, i, ir3 );176 // i = 0; 177 // ir1 = floor2( i, i ), ir2 = floor2( i + 2hh, i ), ir3 = floor2( -i - 2hh, i ); 178 // printf( "floor2(%d, %d) = %d, floor2(%d, %d) = %d, floor2(%d, %d) = %d\n", i, i, ir1, i + 2h, i, ir2, -i - 2h, i, ir3 ); 179 179 for ( i = 1; i != 0; i <<= 1 ) { 180 180 ir1 = floor2( i, i ); ir2 = floor2( i + 2hh, i ); ir3 = floor2( -i - 2hh, i ); … … 184 184 185 185 printf( "unsigned int\n" ); 186 ui = 0;187 uir1 = floor2( ui, ui ), uir2 = floor2( ui + 2hh, ui ), uir3 = floor2( -ui - 2hh, ui );188 printf( "floor2(%u, %u) = %u, floor2(%u, %u) = %u, floor2(%u, %u) = %u\n", ui, ui, uir1, ui + 2h, ui, uir2, -ui - 2h, ui, uir3 );186 // ui = 0; 187 // uir1 = floor2( ui, ui ), uir2 = floor2( ui + 2hh, ui ), uir3 = floor2( -ui - 2hh, ui ); 188 // printf( "floor2(%u, %u) = %u, floor2(%u, %u) = %u, floor2(%u, %u) = %u\n", ui, ui, uir1, ui + 2h, ui, uir2, -ui - 2h, ui, uir3 ); 189 189 for ( ui = 1; ui != 0; ui <<= 1 ) { 190 190 uir1 = floor2( ui, ui ); uir2 = floor2( ui + 2hh, ui ); uir3 = floor2( -ui - 2hh, ui ); … … 194 194 195 195 printf( "long int\n" ); 196 li = 0;197 lir1 = floor2( li, li ), lir2 = floor2( li + 2hh, li ), lir3 = floor2( -li - 2hh, li );198 printf( "floor2(%ld, %ld) = %ld, floor2(%ld, %ld) = %ld, floor2(%ld, %ld) = %ld\n", li, li, lir1, li + 2h, li, lir2, -li - 2h, li, lir3 );196 // li = 0; 197 // lir1 = floor2( li, li ), lir2 = floor2( li + 2hh, li ), lir3 = floor2( -li - 2hh, li ); 198 // printf( "floor2(%ld, %ld) = %ld, floor2(%ld, %ld) = %ld, floor2(%ld, %ld) = %ld\n", li, li, lir1, li + 2h, li, lir2, -li - 2h, li, lir3 ); 199 199 for ( li = 1; li != 0; li <<= 1 ) { 200 200 lir1 = floor2( li, li ); lir2 = floor2( li + 2hh, li ); lir3 = floor2( -li - 2hh, li ); … … 204 204 205 205 printf( "unsigned long int\n" ); 206 uli = 0;207 ulir1 = floor2( uli, uli ), ulir2 = floor2( uli + 2hh, uli ), ulir3 = floor2( -uli - 2hh, uli );208 printf( "floor2(%lu, %lu) = %lu, floor2(%lu, %lu) = %lu, floor2(%lu, %lu) = %lu\n", uli, uli, ulir1, uli + 2h, uli, ulir2, -uli - 2h, uli, ulir3 );206 // uli = 0; 207 // ulir1 = floor2( uli, uli ), ulir2 = floor2( uli + 2hh, uli ), ulir3 = floor2( -uli - 2hh, uli ); 208 // printf( "floor2(%lu, %lu) = %lu, floor2(%lu, %lu) = %lu, floor2(%lu, %lu) = %lu\n", uli, uli, ulir1, uli + 2h, uli, ulir2, -uli - 2h, uli, ulir3 ); 209 209 for ( uli = 1; uli != 0; uli <<= 1 ) { 210 210 ulir1 = floor2( uli, uli ); ulir2 = floor2( uli + 2hh, uli ); ulir3 = floor2( -uli - 2hh, uli ); … … 214 214 215 215 printf( "long long int\n" ); 216 lli = 0;217 llir1 = floor2( lli, lli ), llir2 = floor2( lli + 2hh, lli ), llir3 = floor2( -lli - 2hh, lli );218 printf( "floor2(%lld, %lld) = %lld, floor2(%lld, %lld) = %lld, floor2(%lld, %lld) = %lld\n", lli, lli, llir1, lli + 2h, lli, llir2, -lli - 2h, lli, llir3 );216 // lli = 0; 217 // llir1 = floor2( lli, lli ), llir2 = floor2( lli + 2hh, lli ), llir3 = floor2( -lli - 2hh, lli ); 218 // printf( "floor2(%lld, %lld) = %lld, floor2(%lld, %lld) = %lld, floor2(%lld, %lld) = %lld\n", lli, lli, llir1, lli + 2h, lli, llir2, -lli - 2h, lli, llir3 ); 219 219 for ( lli = 1; lli != 0; lli <<= 1 ) { 220 220 llir1 = floor2( lli, lli ); llir2 = floor2( lli + 2hh, lli ); llir3 = floor2( -lli - 2hh, lli ); … … 224 224 225 225 printf( "unsigned long long int\n" ); 226 ulli = 0;227 ullir1 = floor2( ulli, ulli ), ullir2 = floor2( ulli + 2hh, ulli ), ullir3 = floor2( -ulli - 2hh, ulli );228 printf( "floor2(%llu, %llu) = %llu, floor2(%llu, %llu) = %llu, floor2(%llu, %llu) = %llu\n", ulli, ulli, ullir1, ulli + 2h, ulli, ullir2, -ulli - 2h, ulli, ullir3 );226 // ulli = 0; 227 // ullir1 = floor2( ulli, ulli ), ullir2 = floor2( ulli + 2hh, ulli ), ullir3 = floor2( -ulli - 2hh, ulli ); 228 // printf( "floor2(%llu, %llu) = %llu, floor2(%llu, %llu) = %llu, floor2(%llu, %llu) = %llu\n", ulli, ulli, ullir1, ulli + 2h, ulli, ullir2, -ulli - 2h, ulli, ullir3 ); 229 229 for ( ulli = 1; ulli != 0; ulli <<= 1 ) { 230 230 ullir1 = floor2( ulli, ulli ); ullir2 = floor2( ulli + 2hh, ulli ); ullir3 = floor2( -ulli - 2hh, ulli ); … … 312 312 313 313 printf( "signed char\n" ); 314 sc = 0;315 scr1 = ceiling2( sc, sc ), scr2 = ceiling2( sc + 2hh, sc ), scr3 = ceiling2( -sc - 2hh, sc );316 printf( "ceiling2(%hhd, %hhd) = %hhd, ceiling2(%hhd, %hhd) = %hhd, ceiling2(%hhd, %hhd) = %hhd\n", sc, sc, scr1, sc + 2hh, sc, scr2, -sc - 2hh, sc, scr3 );314 // sc = 0; 315 // scr1 = ceiling2( sc, sc ), scr2 = ceiling2( sc + 2hh, sc ), scr3 = ceiling2( -sc - 2hh, sc ); 316 // printf( "ceiling2(%hhd, %hhd) = %hhd, ceiling2(%hhd, %hhd) = %hhd, ceiling2(%hhd, %hhd) = %hhd\n", sc, sc, scr1, sc + 2hh, sc, scr2, -sc - 2hh, sc, scr3 ); 317 317 for ( sc = 1; sc != 0; sc <<= 1 ) { 318 318 scr1 = ceiling2( sc, sc ); scr2 = ceiling2( sc + 2hh, sc ); scr3 = ceiling2( -sc - 2hh, sc ); … … 322 322 323 323 printf( "unsigned char\n" ); 324 uc = 0;325 ucr1 = ceiling2( uc, uc ), ucr2 = ceiling2( uc + 2hh, uc ), ucr3 = ceiling2( -uc - 2hh, uc );326 printf( "ceiling2(%hhu, %hhu) = %hhu, ceiling2(%hhu, %hhu) = %hhu, ceiling2(%hhu, %hhu) = %hhu\n", uc, uc, ucr1, uc + 2uhh, uc, ucr2, -uc - 2uhh, uc, ucr3 );324 // uc = 0; 325 // ucr1 = ceiling2( uc, uc ), ucr2 = ceiling2( uc + 2hh, uc ), ucr3 = ceiling2( -uc - 2hh, uc ); 326 // printf( "ceiling2(%hhu, %hhu) = %hhu, ceiling2(%hhu, %hhu) = %hhu, ceiling2(%hhu, %hhu) = %hhu\n", uc, uc, ucr1, uc + 2uhh, uc, ucr2, -uc - 2uhh, uc, ucr3 ); 327 327 for ( uc = 1; uc != 0; uc <<= 1 ) { 328 328 ucr1 = ceiling2( uc, uc ); ucr2 = ceiling2( uc + 2hh, uc ); ucr3 = ceiling2( -uc - 2hh, uc ); … … 332 332 333 333 printf( "short int\n" ); 334 si = 0;335 sir1 = ceiling2( si, si ), sir2 = ceiling2( si + 2hh, si ), sir3 = ceiling2( -si - 2hh, si );336 printf( "ceiling2(%hd, %hd) = %hd, ceiling2(%hd, %hd) = %hd, ceiling2(%hd, %hd) = %hd\n", si, si, sir1, si + 2h, si, sir2, -si - 2h, si, sir3 );334 // si = 0; 335 // sir1 = ceiling2( si, si ), sir2 = ceiling2( si + 2hh, si ), sir3 = ceiling2( -si - 2hh, si ); 336 // printf( "ceiling2(%hd, %hd) = %hd, ceiling2(%hd, %hd) = %hd, ceiling2(%hd, %hd) = %hd\n", si, si, sir1, si + 2h, si, sir2, -si - 2h, si, sir3 ); 337 337 for ( si = 1; si != 0; si <<= 1 ) { 338 338 sir1 = ceiling2( si, si ); sir2 = ceiling2( si + 2hh, si ); sir3 = ceiling2( -si - 2hh, si ); … … 342 342 343 343 printf( "unsigned short int\n" ); 344 usi = 0;345 usir1 = ceiling2( usi, usi ), usir2 = ceiling2( usi + 2hh, usi ), usir3 = ceiling2( -usi - 2hh, usi );346 printf( "ceiling2(%hu, %hu) = %hu, ceiling2(%hu, %hu) = %hu, ceiling2(%hu, %hu) = %hu\n", usi, usi, usir1, usi + 2uh, usi, usir2, -usi - 2uh, usi, usir3 );344 // usi = 0; 345 // usir1 = ceiling2( usi, usi ), usir2 = ceiling2( usi + 2hh, usi ), usir3 = ceiling2( -usi - 2hh, usi ); 346 // printf( "ceiling2(%hu, %hu) = %hu, ceiling2(%hu, %hu) = %hu, ceiling2(%hu, %hu) = %hu\n", usi, usi, usir1, usi + 2uh, usi, usir2, -usi - 2uh, usi, usir3 ); 347 347 for ( usi = 1; usi != 0; usi <<= 1 ) { 348 348 usir1 = ceiling2( usi, usi ); usir2 = ceiling2( usi + 2hh, usi ); usir3 = ceiling2( -usi - 2hh, usi ); … … 352 352 353 353 printf( "int\n" ); 354 i = 0;355 ir1 = ceiling2( i, i ), ir2 = ceiling2( i + 2hh, i ), ir3 = ceiling2( -i - 2hh, i );356 printf( "ceiling2(%d, %d) = %d, ceiling2(%d, %d) = %d, ceiling2(%d, %d) = %d\n", i, i, ir1, i + 2h, i, ir2, -i - 2h, i, ir3 );354 // i = 0; 355 // ir1 = ceiling2( i, i ), ir2 = ceiling2( i + 2hh, i ), ir3 = ceiling2( -i - 2hh, i ); 356 // printf( "ceiling2(%d, %d) = %d, ceiling2(%d, %d) = %d, ceiling2(%d, %d) = %d\n", i, i, ir1, i + 2h, i, ir2, -i - 2h, i, ir3 ); 357 357 for ( i = 1; i != 0; i <<= 1 ) { 358 358 ir1 = ceiling2( i, i ); ir2 = ceiling2( i + 2hh, i ); ir3 = ceiling2( -i - 2hh, i ); … … 362 362 363 363 printf( "unsigned int\n" ); 364 ui = 0;365 uir1 = ceiling2( ui, ui ), uir2 = ceiling2( ui + 2hh, ui ), uir3 = ceiling2( -ui - 2hh, ui );366 printf( "ceiling2(%u, %u) = %u, ceiling2(%u, %u) = %u, ceiling2(%u, %u) = %u\n", ui, ui, uir1, ui + 2h, ui, uir2, -ui - 2h, ui, uir3 );364 // ui = 0; 365 // uir1 = ceiling2( ui, ui ), uir2 = ceiling2( ui + 2hh, ui ), uir3 = ceiling2( -ui - 2hh, ui ); 366 // printf( "ceiling2(%u, %u) = %u, ceiling2(%u, %u) = %u, ceiling2(%u, %u) = %u\n", ui, ui, uir1, ui + 2h, ui, uir2, -ui - 2h, ui, uir3 ); 367 367 for ( ui = 1; ui != 0; ui <<= 1 ) { 368 368 uir1 = ceiling2( ui, ui ); uir2 = ceiling2( ui + 2hh, ui ); uir3 = ceiling2( -ui - 2hh, ui ); … … 372 372 373 373 printf( "long int\n" ); 374 li = 0;375 lir1 = ceiling2( li, li ), lir2 = ceiling2( li + 2hh, li ), lir3 = ceiling2( -li - 2hh, li );376 printf( "ceiling2(%ld, %ld) = %ld, ceiling2(%ld, %ld) = %ld, ceiling2(%ld, %ld) = %ld\n", li, li, lir1, li + 2h, li, lir2, -li - 2h, li, lir3 );374 // li = 0; 375 // lir1 = ceiling2( li, li ), lir2 = ceiling2( li + 2hh, li ), lir3 = ceiling2( -li - 2hh, li ); 376 // printf( "ceiling2(%ld, %ld) = %ld, ceiling2(%ld, %ld) = %ld, ceiling2(%ld, %ld) = %ld\n", li, li, lir1, li + 2h, li, lir2, -li - 2h, li, lir3 ); 377 377 for ( li = 1; li != 0; li <<= 1 ) { 378 378 lir1 = ceiling2( li, li ); lir2 = ceiling2( li + 2hh, li ); lir3 = ceiling2( -li - 2hh, li ); … … 382 382 383 383 printf( "unsigned long int\n" ); 384 uli = 0;385 ulir1 = ceiling2( uli, uli ), ulir2 = ceiling2( uli + 2hh, uli ), ulir3 = ceiling2( -uli - 2hh, uli );386 printf( "ceiling2(%lu, %lu) = %lu, ceiling2(%lu, %lu) = %lu, ceiling2(%lu, %lu) = %lu\n", uli, uli, ulir1, uli + 2h, uli, ulir2, -uli - 2h, uli, ulir3 );384 // uli = 0; 385 // ulir1 = ceiling2( uli, uli ), ulir2 = ceiling2( uli + 2hh, uli ), ulir3 = ceiling2( -uli - 2hh, uli ); 386 // printf( "ceiling2(%lu, %lu) = %lu, ceiling2(%lu, %lu) = %lu, ceiling2(%lu, %lu) = %lu\n", uli, uli, ulir1, uli + 2h, uli, ulir2, -uli - 2h, uli, ulir3 ); 387 387 for ( uli = 1; uli != 0; uli <<= 1 ) { 388 388 ulir1 = ceiling2( uli, uli ); ulir2 = ceiling2( uli + 2hh, uli ); ulir3 = ceiling2( -uli - 2hh, uli ); … … 392 392 393 393 printf( "long long int\n" ); 394 lli = 0;395 llir1 = ceiling2( lli, lli ), llir2 = ceiling2( lli + 2hh, lli ), llir3 = ceiling2( -lli - 2hh, lli );396 printf( "ceiling2(%lld, %lld) = %lld, ceiling2(%lld, %lld) = %lld, ceiling2(%lld, %lld) = %lld\n", lli, lli, llir1, lli + 2h, lli, llir2, -lli - 2h, lli, llir3 );394 // lli = 0; 395 // llir1 = ceiling2( lli, lli ), llir2 = ceiling2( lli + 2hh, lli ), llir3 = ceiling2( -lli - 2hh, lli ); 396 // printf( "ceiling2(%lld, %lld) = %lld, ceiling2(%lld, %lld) = %lld, ceiling2(%lld, %lld) = %lld\n", lli, lli, llir1, lli + 2h, lli, llir2, -lli - 2h, lli, llir3 ); 397 397 for ( lli = 1; lli != 0; lli <<= 1 ) { 398 398 llir1 = ceiling2( lli, lli ); llir2 = ceiling2( lli + 2hh, lli ); llir3 = ceiling2( -lli - 2hh, lli ); … … 402 402 403 403 printf( "unsigned long long int\n" ); 404 ulli = 0;405 ullir1 = ceiling2( ulli, ulli ), ullir2 = ceiling2( ulli + 2hh, ulli ), ullir3 = ceiling2( -ulli - 2hh, ulli );406 printf( "ceiling2(%llu, %llu) = %llu, ceiling2(%llu, %llu) = %llu, ceiling2(%llu, %llu) = %llu\n", ulli, ulli, ullir1, ulli + 2h, ulli, ullir2, -ulli - 2h, ulli, ullir3 );404 // ulli = 0; 405 // ullir1 = ceiling2( ulli, ulli ), ullir2 = ceiling2( ulli + 2hh, ulli ), ullir3 = ceiling2( -ulli - 2hh, ulli ); 406 // printf( "ceiling2(%llu, %llu) = %llu, ceiling2(%llu, %llu) = %llu, ceiling2(%llu, %llu) = %llu\n", ulli, ulli, ullir1, ulli + 2h, ulli, ullir2, -ulli - 2h, ulli, ullir3 ); 407 407 for ( ulli = 1; ulli != 0; ulli <<= 1 ) { 408 408 ullir1 = ceiling2( ulli, ulli ); ullir2 = ceiling2( ulli + 2hh, ulli ); ullir3 = ceiling2( -ulli - 2hh, ulli ); 409 409 printf( "ceiling2(%llu, %llu) = %llu, ceiling2(%llu, %llu) = %llu, ceiling2(%llu, %llu) = %llu\n", ulli, ulli, ullir1, ulli + 2h, ulli, ullir2, -ulli - 2h, ulli, ullir3 ); 410 } // for 411 printf( "\n" ); 412 #endif // 0 413 //============================================================ 414 #if 1 415 sout | nl | "ceiling_div" | nl | nl; 416 417 printf( "signed char\n" ); 418 for ( sc = 1; sc != 0; sc <<= 1 ) { 419 scr1 = ceiling_div( sc, sc ); scr2 = ceiling_div( sc + 2hh, sc ); scr3 = ceiling_div( -sc - 2hh, sc ); 420 printf( "ceiling_div(%hhd, %hhd) = %hhd, ceiling_div(%hhd, %hhd) = %hhd, ceiling_div(%hhd, %hhd) = %hhd\n", sc, sc, scr1, sc + 2hh, sc, scr2, -sc - 2hh, sc, scr3 ); 421 } // for 422 printf( "\n" ); 423 424 printf( "unsigned char\n" ); 425 for ( uc = 1; uc != 0; uc <<= 1 ) { 426 ucr1 = ceiling_div( uc, uc ); ucr2 = ceiling_div( uc + 2hh, uc ); ucr3 = ceiling_div( -uc - 2hh, uc ); 427 printf( "ceiling_div(%hhu, %hhu) = %hhu, ceiling_div(%hhu, %hhu) = %hhu, ceiling_div(%hhu, %hhu) = %hhu\n", uc, uc, ucr1, uc + 2uhh, uc, ucr2, -uc - 2uhh, uc, ucr3 ); 428 } // for 429 printf( "\n" ); 430 431 printf( "short int\n" ); 432 for ( si = 1; si != 0; si <<= 1 ) { 433 sir1 = ceiling_div( si, si ); sir2 = ceiling_div( si + 2hh, si ); sir3 = ceiling_div( -si - 2hh, si ); 434 printf( "ceiling_div(%hd, %hd) = %hd, ceiling_div(%hd, %hd) = %hd, ceiling_div(%hd, %hd) = %hd\n", si, si, sir1, si + 2h, si, sir2, -si - 2h, si, sir3 ); 435 } // for 436 printf( "\n" ); 437 438 printf( "unsigned short int\n" ); 439 for ( usi = 1; usi != 0; usi <<= 1 ) { 440 usir1 = ceiling_div( usi, usi ); usir2 = ceiling_div( usi + 2hh, usi ); usir3 = ceiling_div( -usi - 2hh, usi ); 441 printf( "ceiling_div(%hu, %hu) = %hu, ceiling_div(%hu, %hu) = %hu, ceiling_div(%hu, %hu) = %hu\n", usi, usi, usir1, usi + 2uh, usi, usir2, -usi - 2uh, usi, usir3 ); 442 } // for 443 printf( "\n" ); 444 445 printf( "int\n" ); 446 for ( i = 1; i != 0; i <<= 1 ) { 447 ir1 = ceiling_div( i, i ); ir2 = ceiling_div( i + 2hh, i ); ir3 = ceiling_div( -i - 2hh, i ); 448 printf( "ceiling_div(%d, %d) = %d, ceiling_div(%d, %d) = %d, ceiling_div(%d, %d) = %d\n", i, i, ir1, i + 2h, i, ir2, -i - 2h, i, ir3 ); 449 } // for 450 printf( "\n" ); 451 452 printf( "unsigned int\n" ); 453 for ( ui = 1; ui != 0; ui <<= 1 ) { 454 uir1 = ceiling_div( ui, ui ); uir2 = ceiling_div( ui + 2hh, ui ); uir3 = ceiling_div( -ui - 2hh, ui ); 455 printf( "ceiling_div(%u, %u) = %u, ceiling_div(%u, %u) = %u, ceiling_div(%u, %u) = %u\n", ui, ui, uir1, ui + 2h, ui, uir2, -ui - 2h, ui, uir3 ); 456 } // for 457 printf( "\n" ); 458 459 printf( "long int\n" ); 460 for ( li = 1; li != 0; li <<= 1 ) { 461 lir1 = ceiling_div( li, li ); lir2 = ceiling_div( li + 2hh, li ); lir3 = ceiling_div( -li - 2hh, li ); 462 printf( "ceiling_div(%ld, %ld) = %ld, ceiling_div(%ld, %ld) = %ld, ceiling_div(%ld, %ld) = %ld\n", li, li, lir1, li + 2h, li, lir2, -li - 2h, li, lir3 ); 463 } // for 464 printf( "\n" ); 465 466 printf( "unsigned long int\n" ); 467 for ( uli = 1; uli != 0; uli <<= 1 ) { 468 ulir1 = ceiling_div( uli, uli ); ulir2 = ceiling_div( uli + 2hh, uli ); ulir3 = ceiling_div( -uli - 2hh, uli ); 469 printf( "ceiling_div(%lu, %lu) = %lu, ceiling_div(%lu, %lu) = %lu, ceiling_div(%lu, %lu) = %lu\n", uli, uli, ulir1, uli + 2h, uli, ulir2, -uli - 2h, uli, ulir3 ); 470 } // for 471 printf( "\n" ); 472 473 printf( "long long int\n" ); 474 for ( lli = 1; lli != 0; lli <<= 1 ) { 475 llir1 = ceiling_div( lli, lli ); llir2 = ceiling_div( lli + 2hh, lli ); llir3 = ceiling_div( -lli - 2hh, lli ); 476 printf( "ceiling_div(%lld, %lld) = %lld, ceiling_div(%lld, %lld) = %lld, ceiling_div(%lld, %lld) = %lld\n", lli, lli, llir1, lli + 2h, lli, llir2, -lli - 2h, lli, llir3 ); 477 } // for 478 printf( "\n" ); 479 480 printf( "unsigned long long int\n" ); 481 for ( ulli = 1; ulli != 0; ulli <<= 1 ) { 482 ullir1 = ceiling_div( ulli, ulli ); ullir2 = ceiling_div( ulli + 2hh, ulli ); ullir3 = ceiling_div( -ulli - 2hh, ulli ); 483 printf( "ceiling_div(%llu, %llu) = %llu, ceiling_div(%llu, %llu) = %llu, ceiling_div(%llu, %llu) = %llu\n", ulli, ulli, ullir1, ulli + 2h, ulli, ullir2, -ulli - 2h, ulli, ullir3 ); 410 484 } // for 411 485 printf( "\n" ); -
tests/castError.cfa
r07d867b r22f94a4 14 14 // 15 15 16 forall(otype T) struct S { T p; }; 16 17 int f; 18 S(int) sint; 17 19 18 20 void f() { … … 25 27 short int v; 26 28 3, v; // implicit void cast 29 30 (S(char)) sint; 27 31 } 28 32 -
tests/concurrent/examples/datingService.cfa
r07d867b r22f94a4 35 35 signal_block( Boys[ccode] ); // restart boy to set phone number 36 36 } // if 37 // sout | "Girl:" | PhoneNo | "is dating Boy at" | BoyPhoneNo | "with ccode" | ccode;37 // sout | "Girl:" | PhoneNo | "is dating Boy at" | BoyPhoneNo | "with ccode" | ccode; 38 38 return BoyPhoneNo; 39 39 } // DatingService girl … … 47 47 signal_block( Girls[ccode] ); // restart girl to set phone number 48 48 } // if 49 // sout | " Boy:" | PhoneNo | "is dating Girl" | GirlPhoneNo | "with ccode" | ccode;49 // sout | " Boy:" | PhoneNo | "is dating Girl" | GirlPhoneNo | "with ccode" | ccode; 50 50 return GirlPhoneNo; 51 51 } // DatingService boy -
tests/concurrent/signal/block.cfa
r07d867b r22f94a4 82 82 if( !is_empty( cond ) ) { 83 83 84 $thread * next = front( cond );84 $thread * next = ( $thread * ) front( cond ); 85 85 86 86 if( ! signal_block( cond ) ) { -
tests/concurrent/signal/disjoint.cfa
r07d867b r22f94a4 21 21 #endif 22 22 23 // This tests checks what happens when someone barges in the midle of the release 24 // of a bulk of monitors. 25 23 26 enum state_t { WAIT, SIGNAL, BARGE }; 24 27 25 28 monitor global_t {}; 26 global_t mut;27 29 28 30 monitor global_data_t; … … 33 35 int counter; 34 36 state_t state; 35 } data; 37 }; 38 39 // Use a global struct because the order needs to match with Signaller thread 40 struct { 41 global_t mut; 42 global_data_t data; 43 } globals; 36 44 37 45 condition cond; … … 40 48 41 49 void ?{}( global_data_t & this ) { 42 this.counter = =0;50 this.counter = 0; 43 51 this.state = BARGE; 44 52 } … … 53 61 54 62 thread Barger {}; 63 void ?{}( Barger & this ) { 64 ((thread&)this){ "Barger Thread" }; 65 } 55 66 56 67 void main( Barger & this ) { 57 68 while( !all_done ) { 58 barge( data );69 barge( globals.data ); 59 70 yield(); 60 71 } … … 78 89 79 90 thread Waiter {}; 91 void ?{}( Waiter & this ) { 92 ((thread&)this){ "Waiter Thread" }; 93 } 80 94 81 95 void main( Waiter & this ) { 82 while( wait( mut,data ) ) { KICK_WATCHDOG; yield(); }96 while( wait( globals.mut, globals.data ) ) { KICK_WATCHDOG; yield(); } 83 97 } 84 98 … … 92 106 93 107 void logic( global_t & mutex a ) { 94 signal( cond, a, data );108 signal( cond, a, globals.data ); 95 109 96 110 yield( random( 10 ) ); 97 111 98 112 //This is technically a mutual exclusion violation but the mutex monitor protects us 99 bool running = TEST( data.counter < N) &&data.counter > 0;100 if( data.state != SIGNAL && running ) {101 sout | "ERROR Eager signal" | data.state;113 bool running = TEST(globals.data.counter < N) && globals.data.counter > 0; 114 if( globals.data.state != SIGNAL && running ) { 115 sout | "ERROR Eager signal" | globals.data.state; 102 116 } 103 117 } 104 118 105 119 thread Signaller {}; 120 void ?{}( Signaller & this ) { 121 ((thread&)this){ "Signaller Thread" }; 122 } 106 123 107 124 void main( Signaller & this ) { 108 125 while( !all_done ) { 109 logic( mut );126 logic( globals.mut ); 110 127 yield(); 111 128 } -
tests/concurrent/waitfor/when.cfa
r07d867b r22f94a4 57 57 58 58 void arbiter( global_t & mutex this ) { 59 // There is a race at start where callers can get in before the arbiter. 60 // It doesn't really matter here so just restart the loop correctly and move on 61 this.last_call = 6; 62 59 63 for( int i = 0; i < N; i++ ) { 60 64 when( this.last_call == 6 ) waitfor( call1 : this ) { if( this.last_call != 1) { serr | "Expected last_call to be 1 got" | this.last_call; } } -
tests/copyfile.cfa
r07d867b r22f94a4 8 8 // 9 9 // Author : Peter A. Buhr 10 // Created On : Tue Jul 16 16:47:22 201910 // Created On : Fri Jun 19 13:44:05 2020 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Jul 17 18:04:44 201913 // Update Count : 2612 // Last Modified On : Sun Jul 5 11:27:43 2020 13 // Update Count : 5 14 14 // 15 15 16 16 #include <fstream.hfa> 17 #include < stdlib.hfa> // new/delete17 #include <exception.hfa> 18 18 19 19 int main( int argc, char * argv[] ) { 20 ifstream * in = &stdin; // default files 21 ofstream * out = &stdout; 20 ifstream in = stdin; // copy default files 21 ofstream out = stdout; 22 22 23 try { 23 choose ( argc ) { 24 choose ( argc ) { // terminate if command-line errors 24 25 case 2, 3: 25 in = new( (const char *)argv[1] );// open input file first as output creates file26 if ( argc == 3 ) out = new( (const char *)argv[2] ); // only open output if input opens as output created if nonexistent27 case 1: ; // use default files28 default: 29 exit | "Usage[ input-file (default stdin) [ output-file (default stdout) ] ]";26 open( in, argv[1] ); // open input file first as output creates file 27 if ( argc == 3 ) open( out, argv[2] ); // do not create output unless input opens 28 case 1: ; // use default files 29 default: // wrong number of options 30 exit | "Usage" | argv[0] | "[ input-file (default stdin) [ output-file (default stdout) ] ]"; 30 31 } // choose 32 } catch( Open_Failure * ex ; ex->istream == &in ) { 33 exit | "Unable to open input file" | argv[1]; 34 } catch( Open_Failure * ex ; ex->ostream == &out ) { 35 close( in ); // optional 36 exit | "Unable to open output file" | argv[2]; 37 } // try 31 38 32 char ch; 33 *out | nlOff; // turn off auto newline 34 *in | nlOn; // turn on reading newline 39 out | nlOff; // turn off auto newline 40 in | nlOn; // turn on reading newline 35 41 36 for () { // read all characters 37 *in | ch; 38 if ( eof( *in ) ) break; // eof ? 39 *out | ch; 40 } // for 41 } finally { 42 if ( in != &stdin ) delete( in ); // close file, do not delete stdin! 43 if ( out != &stdout ) delete( out ); // close file, do not delete stdout! 44 } // try 42 char ch; 43 for () { // read all characters 44 in | ch; 45 if ( eof( in ) ) break; // eof ? 46 out | ch; 47 } //for 45 48 } // main 46 49 -
tests/errors/.expect/completeType.x64.txt
r07d867b r22f94a4 132 132 ?=?: pointer to function 133 133 ... with parameters 134 reference to instance of type _10 4_0_T (not function type)135 instance of type _10 4_0_T (not function type)134 reference to instance of type _109_0_T (not function type) 135 instance of type _109_0_T (not function type) 136 136 ... returning 137 _retval__operator_assign: instance of type _10 4_0_T (not function type)137 _retval__operator_assign: instance of type _109_0_T (not function type) 138 138 ... with attributes: 139 139 Attribute with name: unused -
tests/exceptions/.expect/resume.txt
r07d867b r22f94a4 4 4 end of try clause 5 5 Exiting: simple try clause 6 7 catch-all 6 8 7 9 throwing child exception … … 29 31 inner catch 30 32 outer catch 33 34 throw 35 rethrow 36 handle -
tests/exceptions/.expect/terminate.txt
r07d867b r22f94a4 3 3 simple catch 4 4 Exiting: simple catch clause 5 6 catch-all 5 7 6 8 throwing child exception … … 27 29 inner catch 28 30 outer catch 31 32 throw 33 rethrow 34 handle -
tests/exceptions/conditional.cfa
r07d867b r22f94a4 17 17 }; 18 18 19 voidnum_error_msg(num_error * this) {19 const char * num_error_msg(num_error * this) { 20 20 if ( ! this->msg ) { 21 21 static const char * base = "Num Error with code: X"; … … 56 56 57 57 try { 58 throw &exc;58 throw exc; 59 59 } catch (num_error * error ; 3 == error->virtual_table->code( error )) { 60 60 caught_num_error(3, error); … … 64 64 65 65 try { 66 throwResume &exc;66 throwResume exc; 67 67 } catchResume (num_error * error ; 3 == error->virtual_table->code( error )) { 68 68 caught_num_error(3, error); -
tests/exceptions/data-except.cfa
r07d867b r22f94a4 28 28 29 29 try { 30 throw &except;30 throw except; 31 31 } catch (paired * exc) { 32 32 printf("%s(%d, %d)\n", paired_msg(exc), exc->first, exc->second); … … 37 37 38 38 try { 39 throwResume &except;39 throwResume except; 40 40 } catchResume (paired * exc) { 41 41 printf("%s(%d, %d)\n", paired_msg(exc), exc->first, exc->second); -
tests/exceptions/finally.cfa
r07d867b r22f94a4 12 12 try { 13 13 printf("termination throw\n"); 14 throw &exc;14 throw exc; 15 15 } finally { 16 16 loud_exit a = "termination inner finally"; … … 28 28 try { 29 29 printf("resumption throw\n"); 30 throwResume &exc;30 throwResume exc; 31 31 } finally { 32 32 loud_exit a = "resumption inner finally"; -
tests/exceptions/interact.cfa
r07d867b r22f94a4 10 10 // Resume falls back to terminate. 11 11 try { 12 throwResume &(star){};12 throwResume (star){}; 13 13 } catch (star *) { 14 14 printf("caught as termination\n"); … … 17 17 try { 18 18 loud_region a = "try block with resume throw"; 19 throwResume &(star){};19 throwResume (star){}; 20 20 } catch (star *) { 21 21 printf("caught as termination\n"); … … 29 29 try { 30 30 try { 31 throw &(star){};31 throw (star){}; 32 32 } catchResume (star *) { 33 33 printf("resume catch on terminate\n"); … … 43 43 try { 44 44 try { 45 throwResume &(star){};45 throwResume (star){}; 46 46 } catch (star *) { 47 47 printf("terminate catch on resume\n"); … … 58 58 try { 59 59 try { 60 throw &(star){};60 throw (star){}; 61 61 } catchResume (star *) { 62 62 printf("inner resume catch (error)\n"); … … 64 64 } catch (star * error) { 65 65 printf("termination catch, will resume\n"); 66 throwResume error;66 throwResume *error; 67 67 } 68 68 } catchResume (star *) { … … 75 75 try { 76 76 try { 77 throwResume &(star){};77 throwResume (star){}; 78 78 } catch (star *) { 79 79 printf("inner termination catch\n"); … … 81 81 } catchResume (star * error) { 82 82 printf("resumption catch, will terminate\n"); 83 throw error;83 throw *error; 84 84 } 85 85 } catch (star *) { … … 94 94 try { 95 95 printf("throwing resume moon\n"); 96 throwResume &(moon){};96 throwResume (moon){}; 97 97 } catch (star *) { 98 98 printf("termination catch\n"); 99 99 } 100 100 printf("throwing resume star\n"); 101 throwResume &(star){};101 throwResume (star){}; 102 102 } catchResume (star *) { 103 103 printf("resumption star catch\n"); … … 105 105 } catchResume (moon *) { 106 106 printf("resumption moon catch, will terminate\n"); 107 throw &(star){};107 throw (star){}; 108 108 } 109 109 } catchResume (star *) { -
tests/exceptions/resume.cfa
r07d867b r22f94a4 9 9 TRIVIAL_EXCEPTION(moment_of, zen); 10 10 11 void in_void(void); 12 11 13 int main(int argc, char * argv[]) { 12 14 // The simple throw catchResume test. … … 14 16 loud_exit a = "simple try clause"; 15 17 printf("simple throw\n"); 16 throwResume &(zen){};18 throwResume (zen){}; 17 19 printf("end of try clause\n"); 18 20 } catchResume (zen * error) { … … 22 24 printf("\n"); 23 25 26 // Throw catch-all test. 27 try { 28 throwResume (zen){}; 29 } catchResume (exception_t * error) { 30 printf("catch-all\n"); 31 } 32 printf("\n"); 33 24 34 // Catch a parent of the given exception. 25 35 try { 26 36 printf("throwing child exception\n"); 27 throwResume &(moment_of){};37 throwResume (moment_of){}; 28 38 } catchResume (zen *) { 29 39 printf("inner parent match\n"); … … 36 46 try { 37 47 try { 38 throwResume &(yin){};48 throwResume (yin){}; 39 49 } catchResume (zen *) { 40 50 printf("caught yin as zen\n"); … … 52 62 loud_exit a = "rethrow inner try"; 53 63 printf("rethrow inner try\n"); 54 throwResume &(zen){};64 throwResume (zen){}; 55 65 } catchResume (zen *) { 56 66 loud_exit a = "rethrowing catch clause"; … … 67 77 try { 68 78 try { 69 throwResume &(yin){};79 throwResume (yin){}; 70 80 } catchResume (yin *) { 71 81 printf("caught yin, will throw yang\n"); 72 throwResume &(yang){};82 throwResume (yang){}; 73 83 } catchResume (yang *) { 74 84 printf("caught exception from same try\n"); … … 83 93 try { 84 94 printf("throwing first exception\n"); 85 throwResume &(yin){};95 throwResume (yin){}; 86 96 } catchResume (yin *) { 87 97 printf("caught first exception\n"); 88 98 try { 89 99 printf("throwing second exception\n"); 90 throwResume &(yang){};100 throwResume (yang){}; 91 101 } catchResume (yang *) { 92 102 printf("caught second exception\n"); … … 104 114 try { 105 115 try { 106 throwResume &(zen){};107 throwResume &(zen){};116 throwResume (zen){}; 117 throwResume (zen){}; 108 118 } catchResume (zen *) { 109 119 printf("inner catch\n"); 110 120 } 111 throwResume &(zen){};121 throwResume (zen){}; 112 122 } catchResume (zen *) { 113 123 printf("outer catch\n"); 114 124 } 125 printf("\n"); 126 127 in_void(); 115 128 } 129 130 // Do a throw and rethrow in a void function. 131 void in_void(void) { 132 try { 133 try { 134 printf("throw\n"); 135 throwResume (zen){}; 136 } catchResume (zen *) { 137 printf("rethrow\n"); 138 throwResume; 139 } 140 } catchResume (zen *) { 141 printf("handle\n"); 142 } 143 } -
tests/exceptions/terminate.cfa
r07d867b r22f94a4 9 9 TRIVIAL_EXCEPTION(moment_of, zen); 10 10 11 void in_void(void); 12 11 13 int main(int argc, char * argv[]) { 12 14 // The simple throw catch test. … … 14 16 loud_exit a = "simple try clause"; 15 17 printf("simple throw\n"); 16 throw &(zen){};18 throw (zen){}; 17 19 printf("end of try clause\n"); 18 20 } catch (zen * error) { 19 loud_exit a = "simple catch clause";21 loud_exit a = "simple catch clause"; 20 22 printf("simple catch\n"); 23 } 24 printf("\n"); 25 26 // Throw catch-all test. 27 try { 28 throw (zen){}; 29 } catch (exception_t * error) { 30 printf("catch-all\n"); 21 31 } 22 32 printf("\n"); … … 25 35 try { 26 36 printf("throwing child exception\n"); 27 throw &(moment_of){};37 throw (moment_of){}; 28 38 } catch (zen *) { 29 39 printf("inner parent match\n"); … … 36 46 try { 37 47 try { 38 throw &(yin){};48 throw (yin){}; 39 49 } catch (zen *) { 40 50 printf("caught yin as zen\n"); … … 52 62 loud_exit a = "rethrow inner try"; 53 63 printf("rethrow inner try\n"); 54 throw &(zen){};64 throw (zen){}; 55 65 } catch (zen *) { 56 66 loud_exit a = "rethrowing catch clause"; … … 67 77 try { 68 78 try { 69 throw &(yin){};79 throw (yin){}; 70 80 } catch (yin *) { 71 81 printf("caught yin, will throw yang\n"); 72 throw &(yang){};82 throw (yang){}; 73 83 } catch (yang *) { 74 84 printf("caught exception from same try\n"); … … 83 93 try { 84 94 printf("throwing first exception\n"); 85 throw &(yin){};95 throw (yin){}; 86 96 } catch (yin *) { 87 97 printf("caught first exception\n"); 88 98 try { 89 99 printf("throwing second exception\n"); 90 throw &(yang){};100 throw (yang){}; 91 101 } catch (yang *) { 92 102 printf("caught second exception\n"); … … 104 114 try { 105 115 try { 106 throw &(zen){};107 throw &(zen){};116 throw (zen){}; 117 throw (zen){}; 108 118 } catch (zen *) { 109 119 printf("inner catch\n"); 110 120 } 111 throw &(zen){};121 throw (zen){}; 112 122 } catch (zen *) { 113 123 printf("outer catch\n"); 114 124 } 125 printf("\n"); 126 127 in_void(); 115 128 } 129 130 // Do a throw and rethrow in a void function. 131 void in_void(void) { 132 try { 133 try { 134 printf("throw\n"); 135 throw (zen){}; 136 } catch (zen *) { 137 printf("rethrow\n"); 138 throw; 139 } 140 } catch (zen *) { 141 printf("handle\n"); 142 } 143 } 144 -
tests/heap.cfa
r07d867b r22f94a4 10 10 // Created On : Tue Nov 6 17:54:56 2018 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Nov 24 12:34:51 201913 // Update Count : 2812 // Last Modified On : Tue Aug 4 06:36:17 2020 13 // Update Count : 56 14 14 // 15 15 … … 75 75 size_t s = (i + 1) * 20; 76 76 char * area = (char *)malloc( s ); 77 if ( area == 0p ) abort( "malloc/free out of memory" );78 77 area[0] = '\345'; area[s - 1] = '\345'; // fill first/last 79 78 area[malloc_usable_size( area ) - 1] = '\345'; // fill ultimate byte … … 84 83 size_t s = i + 1; // +1 to make initialization simpler 85 84 locns[i] = (char *)malloc( s ); 86 if ( locns[i] == 0p ) abort( "malloc/free out of memory" );87 85 locns[i][0] = '\345'; locns[i][s - 1] = '\345'; // fill first/last 88 86 locns[i][malloc_usable_size( locns[i] ) - 1] = '\345'; // fill ultimate byte … … 100 98 size_t s = i + default_mmap_start(); // cross over point 101 99 char * area = (char *)malloc( s ); 102 if ( area == 0p ) abort( "malloc/free out of memory" );103 100 area[0] = '\345'; area[s - 1] = '\345'; // fill first/last 104 101 area[malloc_usable_size( area ) - 1] = '\345'; // fill ultimate byte … … 109 106 size_t s = i + default_mmap_start(); // cross over point 110 107 locns[i] = (char *)malloc( s ); 111 if ( locns[i] == 0p ) abort( "malloc/free out of memory" );112 108 locns[i][0] = '\345'; locns[i][s - 1] = '\345'; // fill first/last 113 109 locns[i][malloc_usable_size( locns[i] ) - 1] = '\345'; // fill ultimate byte … … 125 121 size_t s = (i + 1) * 20; 126 122 char * area = (char *)calloc( 5, s ); 127 if ( area == 0p ) abort( "calloc/free out of memory" );128 123 if ( area[0] != '\0' || area[s - 1] != '\0' || 129 area[malloc_ usable_size( area ) - 1] != '\0' ||124 area[malloc_size( area ) - 1] != '\0' || 130 125 ! malloc_zero_fill( area ) ) abort( "calloc/free corrupt storage1" ); 131 126 area[0] = '\345'; area[s - 1] = '\345'; // fill first/last … … 137 132 size_t s = i + 1; 138 133 locns[i] = (char *)calloc( 5, s ); 139 if ( locns[i] == 0p ) abort( "calloc/free out of memory" );140 134 if ( locns[i][0] != '\0' || locns[i][s - 1] != '\0' || 141 locns[i][malloc_ usable_size( locns[i] ) - 1] != '\0' ||135 locns[i][malloc_size( locns[i] ) - 1] != '\0' || 142 136 ! malloc_zero_fill( locns[i] ) ) abort( "calloc/free corrupt storage2" ); 143 137 locns[i][0] = '\345'; locns[i][s - 1] = '\345'; // fill first/last … … 156 150 size_t s = i + default_mmap_start(); // cross over point 157 151 char * area = (char *)calloc( 1, s ); 158 if ( area == 0p ) abort( "calloc/free out of memory" );159 152 if ( area[0] != '\0' || area[s - 1] != '\0' ) abort( "calloc/free corrupt storage4.1" ); 160 if ( area[malloc_ usable_size( area ) - 1] != '\0' ) abort( "calloc/free corrupt storage4.2" );153 if ( area[malloc_size( area ) - 1] != '\0' ) abort( "calloc/free corrupt storage4.2" ); 161 154 if ( ! malloc_zero_fill( area ) ) abort( "calloc/free corrupt storage4.3" ); 162 155 area[0] = '\345'; area[s - 1] = '\345'; // fill first/last … … 168 161 size_t s = i + default_mmap_start(); // cross over point 169 162 locns[i] = (char *)calloc( 1, s ); 170 if ( locns[i] == 0p ) abort( "calloc/free out of memory" );171 163 if ( locns[i][0] != '\0' || locns[i][s - 1] != '\0' || 172 locns[i][malloc_ usable_size( locns[i] ) - 1] != '\0' ||164 locns[i][malloc_size( locns[i] ) - 1] != '\0' || 173 165 ! malloc_zero_fill( locns[i] ) ) abort( "calloc/free corrupt storage5" ); 174 166 locns[i][0] = '\345'; locns[i][s - 1] = '\345'; // fill first/last … … 188 180 for ( s; 1 ~ NoOfAllocs ) { // allocation of size 0 can return null 189 181 char * area = (char *)memalign( a, s ); 190 if ( area == 0p ) abort( "memalign/free out of memory" );191 182 //sout | i | area; 192 183 if ( (size_t)area % a != 0 || malloc_alignment( area ) != a ) { // check for initial alignment … … 206 197 size_t s = i + default_mmap_start(); // cross over point 207 198 char * area = (char *)memalign( a, s ); 208 if ( area == 0p ) abort( "memalign/free out of memory" );209 199 //sout | i | area; 210 200 if ( (size_t)area % a != 0 || malloc_alignment( area ) != a ) { // check for initial alignment … … 222 212 // initial N byte allocation 223 213 char * area = (char *)calloc( 5, i ); 224 if ( area == 0p ) abort( "calloc/realloc/free out of memory" );225 214 if ( area[0] != '\0' || area[i - 1] != '\0' || 226 area[malloc_ usable_size( area ) - 1] != '\0' ||215 area[malloc_size( area ) - 1] != '\0' || 227 216 ! malloc_zero_fill( area ) ) abort( "calloc/realloc/free corrupt storage1" ); 228 217 … … 230 219 for ( s; i ~ 256 * 1024 ~ 26 ) { // start at initial memory request 231 220 area = (char *)realloc( area, s ); // attempt to reuse storage 232 if ( area == 0p ) abort( "calloc/realloc/free out of memory" );233 221 if ( area[0] != '\0' || area[s - 1] != '\0' || 234 area[malloc_ usable_size( area ) - 1] != '\0' ||222 area[malloc_size( area ) - 1] != '\0' || 235 223 ! malloc_zero_fill( area ) ) abort( "calloc/realloc/free corrupt storage2" ); 236 224 } // for … … 244 232 size_t s = i + default_mmap_start(); // cross over point 245 233 char * area = (char *)calloc( 1, s ); 246 if ( area == 0p ) abort( "calloc/realloc/free out of memory" );234 // if ( area == 0p ) abort( "calloc/realloc/free out of memory" ); 247 235 if ( area[0] != '\0' || area[s - 1] != '\0' || 248 area[malloc_usable_size( area ) - 1] != '\0' || 249 ! malloc_zero_fill( area ) ) abort( "calloc/realloc/free corrupt storage1" ); 236 area[malloc_size( area ) - 1] != '\0' || 237 ! malloc_zero_fill( area ) ) //abort( "calloc/realloc/free corrupt storage3" ); 238 printf( "C %zd %d %d %d %d\n", s, area[0] != '\0', area[s - 1] != '\0', area[malloc_size( area ) - 1] != '\0', ! malloc_zero_fill( area ) ); 250 239 251 240 // Do not start this loop index at 0 because realloc of 0 bytes frees the storage. 252 241 for ( r; i ~ 256 * 1024 ~ 26 ) { // start at initial memory request 253 242 area = (char *)realloc( area, r ); // attempt to reuse storage 254 if ( area == 0p ) abort( "calloc/realloc/free out of memory" );243 // if ( area == 0p ) abort( "calloc/realloc/free out of memory" ); 255 244 if ( area[0] != '\0' || area[r - 1] != '\0' || 256 area[malloc_ usable_size( area ) - 1] != '\0' ||257 ! malloc_zero_fill( area ) ) abort( "calloc/realloc/free corrupt storage 2" );245 area[malloc_size( area ) - 1] != '\0' || 246 ! malloc_zero_fill( area ) ) abort( "calloc/realloc/free corrupt storage4" ); 258 247 } // for 259 248 free( area ); … … 266 255 // initial N byte allocation 267 256 char * area = (char *)memalign( a, amount ); // aligned N-byte allocation 268 if ( area == 0p ) abort( "memalign/realloc/free out of memory" ); // no storage ?257 // if ( area == 0p ) abort( "memalign/realloc/free out of memory" ); // no storage ? 269 258 //sout | alignments[a] | area; 270 259 if ( (size_t)area % a != 0 || malloc_alignment( area ) != a ) { // check for initial alignment … … 277 266 if ( area[0] != '\345' || area[s - 2] != '\345' ) abort( "memalign/realloc/free corrupt storage" ); 278 267 area = (char *)realloc( area, s ); // attempt to reuse storage 279 if ( area == 0p ) abort( "memalign/realloc/free out of memory" ); // no storage ?280 268 //sout | i | area; 281 269 if ( (size_t)area % a != 0 ) { // check for initial alignment … … 293 281 for ( s; 1 ~ limit ) { // allocation of size 0 can return null 294 282 char * area = (char *)cmemalign( a, 1, s ); 295 if ( area == 0p ) abort( "cmemalign/free out of memory" );296 283 //sout | i | area; 297 284 if ( (size_t)area % a != 0 || malloc_alignment( area ) != a ) { // check for initial alignment … … 299 286 } // if 300 287 if ( area[0] != '\0' || area[s - 1] != '\0' || 301 area[malloc_ usable_size( area ) - 1] != '\0' ||288 area[malloc_size( area ) - 1] != '\0' || 302 289 ! malloc_zero_fill( area ) ) abort( "cmemalign/free corrupt storage" ); 303 290 area[0] = '\345'; area[s - 1] = '\345'; // fill first/last byte … … 312 299 // initial N byte allocation 313 300 char * area = (char *)cmemalign( a, 1, amount ); // aligned N-byte allocation 314 if ( area == 0p ) abort( "cmemalign/realloc/free out of memory" ); // no storage ?315 301 //sout | alignments[a] | area; 316 302 if ( (size_t)area % a != 0 || malloc_alignment( area ) != a ) { // check for initial alignment … … 318 304 } // if 319 305 if ( area[0] != '\0' || area[amount - 1] != '\0' || 320 area[malloc_ usable_size( area ) - 1] != '\0' ||306 area[malloc_size( area ) - 1] != '\0' || 321 307 ! malloc_zero_fill( area ) ) abort( "cmemalign/realloc/free corrupt storage1" ); 322 308 area[0] = '\345'; area[amount - 2] = '\345'; // fill first/penultimate byte … … 326 312 if ( area[0] != '\345' || area[s - 2] != '\345' ) abort( "cmemalign/realloc/free corrupt storage2" ); 327 313 area = (char *)realloc( area, s ); // attempt to reuse storage 328 if ( area == 0p ) abort( "cmemalign/realloc/free out of memory" ); // no storage ?329 314 //sout | i | area; 330 315 if ( (size_t)area % a != 0 || malloc_alignment( area ) != a ) { // check for initial alignment 331 316 abort( "cmemalign/realloc/free bad alignment %p", area ); 332 317 } // if 333 if ( area[ s - 1] != '\0' || area[s - 1] != '\0' ||334 area[malloc_ usable_size( area ) - 1] != '\0' ||318 if ( area[0] != '\345' || area[s - 1] != '\0' || 319 area[malloc_size( area ) - 1] != '\0' || 335 320 ! malloc_zero_fill( area ) ) abort( "cmemalign/realloc/free corrupt storage3" ); 336 321 area[s - 1] = '\345'; // fill last byte … … 345 330 // initial N byte allocation 346 331 char * area = (char *)memalign( a, amount ); // aligned N-byte allocation 347 if ( area == 0p ) abort( "memalign/realloc with align/free out of memory" ); // no storage ?348 332 //sout | alignments[a] | area | endl; 349 333 if ( (size_t)area % a != 0 || malloc_alignment( area ) != a ) { // check for initial alignment … … 356 340 if ( area[0] != '\345' || area[s - 2] != '\345' ) abort( "memalign/realloc/free corrupt storage" ); 357 341 area = (char *)realloc( area, a * 2, s ); // attempt to reuse storage 358 if ( area == 0p ) abort( "memalign/realloc with align/free out of memory" ); // no storage ?359 342 //sout | i | area | endl; 360 343 if ( (size_t)area % a * 2 != 0 ) { // check for initial alignment … … 371 354 for ( size_t a = libAlign() + libAlign(); a <= limit; a += a ) { // generate powers of 2 372 355 // initial N byte allocation 373 char *area = (char *)cmemalign( a, 1, amount ); // aligned N-byte allocation 374 if ( area == 0p ) abort( "cmemalign/realloc with align/free out of memory" ); // no storage ? 356 char * area = (char *)cmemalign( a, 1, amount ); // aligned N-byte allocation 375 357 //sout | alignments[a] | area | endl; 376 358 if ( (size_t)area % a != 0 || malloc_alignment( area ) != a ) { // check for initial alignment … … 378 360 } // if 379 361 if ( area[0] != '\0' || area[amount - 1] != '\0' || 380 area[malloc_ usable_size( area ) - 1] != '\0' ||362 area[malloc_size( area ) - 1] != '\0' || 381 363 ! malloc_zero_fill( area ) ) abort( "cmemalign/realloc with align/free corrupt storage1" ); 382 364 area[0] = '\345'; area[amount - 2] = '\345'; // fill first/penultimate byte … … 386 368 if ( area[0] != '\345' || area[s - 2] != '\345' ) abort( "cmemalign/realloc with align/free corrupt storage2" ); 387 369 area = (char *)realloc( area, a * 2, s ); // attempt to reuse storage 388 if ( area == 0p ) abort( "cmemalign/realloc with align/free out of memory" ); // no storage ?389 370 //sout | i | area | endl; 390 371 if ( (size_t)area % a * 2 != 0 || malloc_alignment( area ) != a * 2 ) { // check for initial alignment 391 abort( "cmemalign/realloc with align/free bad alignment %p % jd %jd", area, malloc_alignment( area ), a * 2 );372 abort( "cmemalign/realloc with align/free bad alignment %p %zd %zd", area, malloc_alignment( area ), a * 2 ); 392 373 } // if 393 374 if ( area[s - 1] != '\0' || area[s - 1] != '\0' || 394 area[malloc_ usable_size( area ) - 1] != '\0' ||375 area[malloc_size( area ) - 1] != '\0' || 395 376 ! malloc_zero_fill( area ) ) abort( "cmemalign/realloc/free corrupt storage3" ); 396 377 area[s - 1] = '\345'; // fill last byte -
tests/io2.cfa
r07d867b r22f94a4 121 121 122 122 [int, int, const char *, double] t3 = { 3, 4, "a", 7.2 }; 123 sout | [ 3, 4, "a", 7.2 ];123 sout | [ 3, 4, (const char*)"a", 7.2 ]; // workaround trac#207: the const cast should not be needed 124 124 sout | t3; 125 125 sepSetTuple( sout, " " ); -
tests/list/.expect/dlist-insert-remove.txt
r07d867b r22f94a4 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
r07d867b r22f94a4 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 } -
tests/manipulatorsInput.cfa
r07d867b r22f94a4 7 7 // Created On : Sat Jun 8 17:58:54 2019 8 8 // Last Modified By : Peter A. Buhr 9 // Last Modified On : Thu Jun 13 17:41:43 201910 // Update Count : 379 // Last Modified On : Wed Jul 15 15:56:03 2020 10 // Update Count : 47 11 11 // 12 12 … … 152 152 sin | ignore( wdi( 8, ldc ) ); sout | ldc; 153 153 } 154 #if defined( __SIZEOF_INT128__ ) 155 { 156 int128 val; 157 for ( 15 ) { 158 sin | val; 159 sout | val; 160 } 161 } 162 #endif // __SIZEOF_INT128__ 154 163 } // main 155 164 -
tests/manipulatorsOutput3.cfa
r07d867b r22f94a4 1 1 #include <fstream.hfa> 2 2 3 int main() { 3 int128 x = 0xffff, y = 0x2; 4 x <<= 64; 5 x += 0xffff; 6 y <<= 64; 7 y += 0123; 8 y |= 0x8000000000000000; 9 x = -x; 10 sout | x; 11 sout | sign(x); 12 x = -x; 13 sout | sign(x); 14 sout | nl; 15 #if 1 16 sout | bin(x); 17 sout | upcase(bin(x)); 18 sout | nobase(bin(x)); 19 sout | wd( 95, upcase(bin(x)) ); 20 sout | wd( 95,90, upcase(bin(x)) ); 21 sout | wd( 25,30, upcase(hex(x)) ); 22 sout | nl; 23 24 printf( "%#.10o\n", 0123 ); 25 sout | wd( 1,10, oct(0123) ); 26 sout | oct(x); 27 sout | nobase(oct(x)); 28 sout | wd( 45, oct(0123) ); 29 sout | wd( 45,40, oct(0123) ); 30 sout | wd( 40,45, oct(0123) ); 31 sout | wd( 45, oct(x) ); 32 sout | wd( 45,40, oct(x) ); 33 sout | wd( 40,45, oct(x) ); 34 35 sout | left(wd( 45, oct(0123) )) | 'X'; 36 sout | left(wd( 45, oct(x) )) | 'X'; 37 sout | left(wd( 45, oct(y) )) | 'X'; 38 sout | left(wd( 45,40, oct(0123) )) | 'X'; 39 sout | left(wd( 45,40, oct(x) )) | 'X'; 40 sout | left(wd( 45,40, oct(y) )) | 'X'; 41 sout | left(wd( 40,45, oct(0123) )) | 'X'; 42 sout | left(wd( 40,45, oct(x) )) | 'X'; 43 sout | left(wd( 40,45, oct(y) )) | 'X'; 44 printf( "%#-1.10oX\n", 0123 ); 45 sout | left(wd( 1,10, oct(0123) )) | 'X'; 46 printf( "%#-40.10oX\n", 0123 ); 47 sout | left(wd( 40,10, oct(0123) )) | 'X'; 48 sout | left(wd( 40,10, oct(x) )) | 'X'; 49 sout | left(wd( 40,10, oct(y) )) | 'X'; 50 sout | left(wd( 10,40, oct(0123) )) | 'X'; 51 sout | left(wd( 10,40, oct(x) )) | 'X'; 52 sout | left(wd( 10,40, oct(y) )) | 'X'; 53 54 y = 01234567; 55 sout | left(wd( 45, 49, oct(y) )) | 'X'; 56 y = -y; 57 sout | wd(0, oct(y)) | 'Y'; 58 sout | left(wd(0, oct(y))) | 'Y'; 59 sout | nl; 60 61 sout | hex(x); 62 sout | upcase(hex(x)); 63 sout | nobase(hex(x)); 64 sout | wd( 45, upcase(hex(x)) ); 65 sout | wd( 45,40, upcase(hex(x)) ); 66 sout | wd( 45,49, upcase(hex(x)) ); 67 sout | left(wd( 45, upcase(hex(x)) )) | 'X'; 68 sout | left(wd( 45,40, upcase(hex(x)) )) | 'X'; 69 sout | left(wd( 45,49, upcase(hex(x)) )) | 'X'; 70 71 sout | nl; 72 73 int128 divisor = 0x4b3b4ca85a86c47a; 74 divisor <<= 16; 75 divisor += 0x98a224000000000; 76 77 // base 2 78 sout | "base 2"; 79 sout | bin(divisor); 80 sout | upcase(bin(divisor)); 81 sout | wd(38, upcase(bin(divisor))); 82 sout | wd(40, upcase(bin(divisor))); 83 sout | wd(40, 38, upcase(bin(divisor))); 84 sout | wd(40, 30, upcase(bin(divisor))); 85 sout | pad0(sign(wd(40, 38, upcase(bin(divisor))))); 86 sout | nl; 87 88 // oct 89 sout | "base 8"; 90 sout | upcase(oct(divisor)); 91 sout | wd(38, upcase(oct(divisor))); 92 sout | wd(40, upcase(oct(divisor))); 93 sout | wd(40, 38, upcase(oct(divisor))); 94 sout | wd(40, 30, upcase(oct(divisor))); 95 sout | pad0(sign(wd(40, 38, upcase(oct(divisor))))); 96 sout | nl; 97 98 // decimal 99 sout | "base 10"; 100 sout | divisor; 101 sout | wd(2, divisor); 102 sout | wd(3, divisor); 103 sout | wd(10, divisor); 104 sout | wd(24, divisor); 105 sout | wd(38, divisor); 106 sout | wd(39, divisor); 107 sout | wd(40, divisor); 108 109 sout | wd(40, 30, divisor); 110 sout | wd(40, 38, divisor); 111 sout | wd(40, 40, divisor); 112 sout | pad0(wd(40, divisor)); 113 sout | pad0(sign(wd(40,divisor))); 114 sout | nl; 115 116 // hex 117 sout | "base 16"; 118 sout | upcase(hex(divisor)); 119 sout | wd(38, upcase(hex(divisor))); 120 sout | wd(40, upcase(hex(divisor))); 121 sout | wd(40, 38, upcase(hex(divisor))); 122 sout | wd(40, 30, upcase(hex(divisor))); 123 sout | pad0(sign(wd(40, 38, upcase(hex(divisor))))); 124 sout | nl; 125 126 127 sout | bin(divisor); 128 sout | upcase(bin(divisor)); 129 sout | oct(divisor); 130 sout | hex(divisor); 131 sout | upcase(hex(divisor)); 132 sout | nobase(bin(divisor)) | nobase(oct(divisor)) | nobase(hex(divisor)); 133 sout | sign(divisor); 134 sout | -divisor; 135 sout | sign(-divisor); 136 sout | wd(2, divisor); 137 sout | wd(3,10,divisor); 138 sout | left(wd(40,divisor)) | 'X'; 139 sout | left(sign(wd(40, divisor))) | 'X'; 140 sout | left(sign(wd(0,40, divisor))) | 'X'; 141 printf( "%-+1.40dX\n", 123456789 ); 142 #endif // 0 143 } 4 // int128 printing 5 int128 x = 0xffff, y = 0x2; 6 7 x <<= 64; 8 x += 0xffff; 9 y <<= 64; 10 y += 0123; 11 y |= 0x8000000000000000; 12 x = -x; 13 sout | x; 14 sout | sign(x); 15 x = -x; 16 sout | sign(x); 17 sout | nl; 18 19 int128 divisor = 0x4b3b4ca85a86c47a; 20 divisor <<= 16; 21 divisor += 0x98a224000000000; 22 23 // base 2 24 sout | "base 2"; 25 sout | bin(x); 26 sout | upcase(bin(x)); 27 sout | nobase(bin(x)); 28 sout | wd( 95, upcase(bin(x)) ); 29 sout | wd( 95,90, upcase(bin(x)) ); 30 sout | wd( 25,30, upcase(hex(x)) ); 31 sout | nl; 32 33 sout | bin(divisor); 34 sout | upcase(bin(divisor)); 35 sout | wd(38, upcase(bin(divisor))); 36 sout | wd(40, upcase(bin(divisor))); 37 sout | wd(40, 38, upcase(bin(divisor))); 38 sout | wd(40, 30, upcase(bin(divisor))); 39 sout | pad0(sign(wd(40, 38, upcase(bin(divisor))))); 40 sout | nl; 41 42 // oct 43 sout | "base 8"; 44 printf( "%#.10o\n", 0123 ); 45 sout | wd( 1,10, oct(0123) ); 46 sout | oct(x); 47 sout | nobase(oct(x)); 48 sout | wd( 45, oct(0123) ); 49 sout | wd( 45,40, oct(0123) ); 50 sout | wd( 40,45, oct(0123) ); 51 sout | wd( 45, oct(x) ); 52 sout | wd( 45,40, oct(x) ); 53 sout | wd( 40,45, oct(x) ); 54 55 sout | left(wd( 45, oct(0123) )) | 'X'; 56 sout | left(wd( 45, oct(x) )) | 'X'; 57 sout | left(wd( 45, oct(y) )) | 'X'; 58 sout | left(wd( 45,40, oct(0123) )) | 'X'; 59 sout | left(wd( 45,40, oct(x) )) | 'X'; 60 sout | left(wd( 45,40, oct(y) )) | 'X'; 61 sout | left(wd( 40,45, oct(0123) )) | 'X'; 62 sout | left(wd( 40,45, oct(x) )) | 'X'; 63 sout | left(wd( 40,45, oct(y) )) | 'X'; 64 printf( "%#-1.10oX\n", 0123 ); 65 sout | left(wd( 1,10, oct(0123) )) | 'X'; 66 printf( "%#-40.10oX\n", 0123 ); 67 sout | left(wd( 40,10, oct(0123) )) | 'X'; 68 sout | left(wd( 40,10, oct(x) )) | 'X'; 69 sout | left(wd( 40,10, oct(y) )) | 'X'; 70 sout | left(wd( 10,40, oct(0123) )) | 'X'; 71 sout | left(wd( 10,40, oct(x) )) | 'X'; 72 sout | left(wd( 10,40, oct(y) )) | 'X'; 73 74 y = 01234567; 75 sout | left(wd( 45, 49, oct(y) )) | 'X'; 76 y = -y; 77 sout | wd(0, oct(y)) | 'Y'; 78 sout | left(wd(0, oct(y))) | 'Y'; 79 sout | nl; 80 81 sout | upcase(oct(divisor)); 82 sout | wd(38, upcase(oct(divisor))); 83 sout | wd(40, upcase(oct(divisor))); 84 sout | wd(40, 38, upcase(oct(divisor))); 85 sout | wd(40, 30, upcase(oct(divisor))); 86 sout | pad0(sign(wd(40, 38, upcase(oct(divisor))))); 87 sout | nl; 88 89 // decimal 90 sout | "base 10"; 91 sout | divisor; 92 sout | wd(2, divisor); 93 sout | wd(3, divisor); 94 sout | wd(10, divisor); 95 sout | wd(24, divisor); 96 sout | wd(38, divisor); 97 sout | wd(39, divisor); 98 sout | wd(40, divisor); 99 100 sout | wd(40, 30, divisor); 101 sout | wd(40, 38, divisor); 102 sout | wd(40, 40, divisor); 103 sout | pad0(wd(40, divisor)); 104 sout | pad0(sign(wd(40,divisor))); 105 sout | nl; 106 107 // hex 108 sout | "base 16"; 109 110 sout | hex(x); 111 sout | upcase(hex(x)); 112 sout | nobase(hex(x)); 113 sout | wd( 45, upcase(hex(x)) ); 114 sout | wd( 45,40, upcase(hex(x)) ); 115 sout | wd( 45,49, upcase(hex(x)) ); 116 sout | left(wd( 45, upcase(hex(x)) )) | 'X'; 117 sout | left(wd( 45,40, upcase(hex(x)) )) | 'X'; 118 sout | left(wd( 45,49, upcase(hex(x)) )) | 'X'; 119 sout | nl; 120 121 sout | upcase(hex(divisor)); 122 sout | wd(38, upcase(hex(divisor))); 123 sout | wd(40, upcase(hex(divisor))); 124 sout | wd(40, 38, upcase(hex(divisor))); 125 sout | wd(40, 30, upcase(hex(divisor))); 126 sout | pad0(sign(wd(40, 38, upcase(hex(divisor))))); 127 sout | nl; 128 129 // extras 130 sout | "extras"; 131 sout | bin(divisor); 132 sout | upcase(bin(divisor)); 133 sout | oct(divisor); 134 sout | hex(divisor); 135 sout | upcase(hex(divisor)); 136 sout | nobase(bin(divisor)) | nobase(oct(divisor)) | nobase(hex(divisor)); 137 sout | sign(divisor); 138 sout | -divisor; 139 sout | sign(-divisor); 140 sout | wd(2, divisor); 141 sout | wd(3,10,divisor); 142 sout | left(wd(40,divisor)) | 'X'; 143 sout | left(sign(wd(40, divisor))) | 'X'; 144 sout | left(sign(wd(0,40, divisor))) | 'X'; 145 printf( "%-+1.40dX\n", 123456789 ); 146 147 int128 i128; 148 unsigned int128 ui128; 149 i128 = -1000; 150 for ( 10 ) { 151 sout | left( sign( wd( 2, i128 ) ) ) | left( wd( 2, hex( i128 ) ) ) | left( wd( 2, oct( i128 ) ) ); 152 sout | left( wd( 2, bin( i128 ) ) ); 153 i128 += 1; 154 } 155 sout | nl; 156 sout | nl; 157 158 ui128 = 0x7fffffffffffffff; 159 ui128 <<= 64; 160 ui128 += 0xffffffffffffffff; 161 sout | left( wd( 160, i128 ) ); 162 sout | left( sign( wd( 0, i128 ) ) ); 163 sout | left( wd( 0, hex( i128 ) ) ); 164 sout | left( wd( 0, oct( i128 ) ) ); 165 sout | left( wd( 0, bin( i128 ) ) ); 166 sout | left( sign( wd( 1, i128 ) ) ); 167 sout | left( wd( 1, hex( i128 ) ) ); 168 sout | left( wd( 1, oct( i128 ) ) ); 169 sout | left( wd( 1, bin( i128 ) ) ); 170 sout | left( sign( wd( 32, i128 ) ) ); 171 sout | left( wd( 32, hex( i128 ) ) ); 172 sout | left( wd( 32, oct( i128 ) ) ); 173 sout | left( wd( 32, bin( i128 ) ) ); 174 sout | left( sign( wd( 160, i128 ) ) ); 175 sout | left( wd( 160, hex( i128 ) ) ); 176 sout | left( wd( 160, oct( i128 ) ) ); 177 sout | left( wd( 160, bin( i128 ) ) ); 178 sout | left( sign( wd( 160, i128 ) ) ); 179 sout | left( wd( 160, upcase(hex( i128 )) ) ); 180 sout | left( wd( 160, upcase(oct( i128 ) )) ); 181 sout | left( wd( 160, upcase(bin( i128 )) ) ); 182 183 x = 1234; 184 x <<= 64; 185 x += 5678; 186 sout | x | 'X'; 187 sout | wd(45, 20, oct(x)) | 'X'; 188 sout | left(wd(45, 20, oct(x))) | 'X'; 189 sout | wd(45, 21, oct(x)) | 'X'; 190 sout | left(wd(45, 21, oct(x))) | 'X'; 191 sout | wd(45, 22, oct(x)) | 'X'; 192 sout | left(wd(45, 22, oct(x))) | 'X'; 193 sout | wd(45, 36, oct(x)) | 'X'; 194 sout | left(wd(45, 36, oct(x))) | 'X'; 195 sout | wd(45, 46, oct(x)) | 'X'; 196 sout | left(wd(45, 46, oct(x))) | 'X'; 197 sout | left(wd(45, 20, oct(x))) | 'X'; 198 sout | left(wd(45, 22, oct(x))) | 'X'; 199 sout | left(wd(45, 24, oct(x))) | 'X'; 200 sout | left(wd(45, 26, oct(x))) | 'X'; 201 sout | left(wd(45, 28, oct(x))) | 'X'; 202 203 y = -x; 204 sout | oct(y) | 'Y'; 205 sout | left(wd(0, oct(y))) | 'Y'; 206 sout | left(wd(20, oct(y))) | 'Y'; 207 sout | left(wd(26, oct(y))) | 'Y'; 208 sout | left(wd(40, oct(y))) | 'Y'; 209 sout | left(wd(41, oct(y))) | 'Y'; 210 sout | left(wd(45, oct(y))) | 'Y'; 211 sout | left(wd(45, 49, oct(y))) | 'Y'; 212 sout | left(wd(45, 4, oct(y))) | 'Y'; 213 sout | left(wd( 45, oct(0123) )) | 'X'; 214 sout | left(wd( 45, oct(x) )) | 'X'; 215 sout | left(wd( 45,40, oct(0123) )) | 'X'; 216 sout | left(wd( 45,40, oct(x) )) | 'X'; 217 sout | left(wd( 40,45, oct(0123) )) | 'X'; 218 sout | left(wd( 40,45, oct(x) )) | 'X'; 219 sout | left(wd( 40,10, oct(0123) )) | 'X'; 220 sout | left(wd( 40,10, oct(x) )) | 'X'; 221 sout | left(wd( 40,10, oct(y) )) | 'X'; 222 sout | left(wd( 10,40, oct(0123) )) | 'X'; 223 sout | left(wd( 10,40, oct(x) )) | 'X'; 224 sout | left(wd( 10,40, oct(y) )) | 'X'; 225 226 x = 0xffff, y = 0x2; 227 int128 z = 0x_ffff_ffff_ffff_ffff; 228 x <<= 64; 229 x += 0xffff; 230 y <<= 64; 231 y += 0123; 232 y |= 0x8000000000000000; 233 234 for ( int128 i = 0; i < 8; i += 1 ) { 235 sout | nobase(oct(z + 0x8000000000000000 * i)); 236 } // for 237 238 sout | bin(x); 239 sout | upcase(bin(x)); 240 sout | nobase(bin(x)); 241 242 sout | wd( 95, upcase(bin(x)) ); 243 sout | wd( 95,90, upcase(bin(x)) ); 244 sout | wd( 90,95, upcase(bin(x)) ); 245 246 sout | left(bin(x)); 247 sout | left(upcase(bin(x))); 248 sout | left(nobase(bin(x))); 249 250 sout | left(wd( 95, upcase(bin(x)) )); 251 sout | left(wd( 95,90, upcase(bin(x)) )); 252 sout | left(wd( 95,81, upcase(bin(x)) )); 253 254 sout | left(wd( 95,80, upcase(bin(x)) )); 255 sout | left(wd( 95,79, upcase(bin(x)) )); 256 sout | left(wd( 95,90, upcase(bin(0xffff)) )); 257 258 sout | left(wd( 68,64, upcase(bin(0xffff)) )); 259 sout | left(wd( 90,95, upcase(bin(x)) )); 260 261 printf( "%#30.25X\n", 0xffff ); 262 sout | wd( 30,25, upcase(hex(0xffff)) ); 263 printf( "%#25.30X\n", 0xffff ); 264 sout | wd( 25,30, upcase(hex(0xffff)) ); 265 266 sout | oct(y); 267 sout | wd( 45, oct(y) ); 268 sout | left(wd( 45, oct(y) )) | 'X'; 269 270 sout | left(wd( 40,10, oct(0123) )) | 'X'; 271 sout | left(wd( 40,10, oct(x) )) | 'X'; 272 sout | left(wd( 40,10, oct(y) )) | 'X'; 273 sout | left(wd( 10,40, oct(0123) )) | 'X'; 274 sout | left(wd( 10,40, oct(x) )) | 'X'; 275 sout | left(wd( 10,40, oct(y) )) | 'X'; 276 277 i128 = -10; 278 for ( 25 ) { 279 sout | left( sign( wd( 20, i128 ) ) ) | left( wd( 20, hex( i128 ) ) ) | left( wd( 20, oct( i128 ) ) ); 280 sout | left( wd( 20, bin( i128 ) ) ); 281 i128 += 1; 282 } // for 283 sout | nl; 284 285 i128 = 0x7fffffffffffffff; 286 i128 <<= 64; 287 i128 += 0xfffffffffffffffa; 288 289 // for ( 20 ) { 290 volatile int stop = 20; // gcc compiler bug 291 for ( int i = 0; i < stop; i += 1 ) { 292 sout | i128; 293 sout | left( sign( wd( 45, i128 ) ) ) | left( wd( 45, hex( i128 ) ) ) | left( wd( 45, oct( i128 ) ) ); 294 sout | left( wd( 45, bin( i128 ) ) ); 295 i128 += 1; 296 } // for 297 sout | nl; 298 299 ui128 = 0x7fffffffffffffff; 300 ui128 <<= 64; 301 ui128 += 0xfffffffffffffffa; 302 303 for ( 20 ) { 304 sout | ui128; 305 ui128 += 1; 306 } 307 sout | nl; 308 309 ui128 = 0xffffffffffffffff; 310 ui128 <<= 64; 311 ui128 += 0xfffffffffffffffa; 312 313 for ( 20 ) { 314 sout | ui128; 315 ui128 += 1; 316 } 317 318 319 // int128 constants (and printing) 320 int128 v = 0xffff_ffffffff_ffffffff_L128 + 0xffffffff_ffffffff_ffffffff_ffffffff_L128; 321 sout | hex(v); 322 v = 0xffff_ffffffff_ffffffff_L128 + 0xffffffff_ffffffff_ffffffff_ffffffff_L128; 323 sout | hex(v); 324 sout | nl; 325 326 sout | "binary"; 327 sout | bin(v); 328 sout | bin(0b_11111111111111111111111111111111_L128); 329 sout | bin(0b_11111111111111111111111111111111_11111111111111111111111111111111_L128); 330 sout | bin(0b_11111111111111111111111111111111_11111111111111111111111111111111_11111111111111111111111111111111_L128); 331 sout | bin(0b_11111111111111111111111111111111_11111111111111111111111111111111_11111111111111111111111111111111_11111111111111111111111111111111_L128); 332 sout | hex(0b_10100010001101000101011001111000_L128); 333 sout | hex(0b_10100010001101000101011001111000_10100111011001010100001100100001_L128); 334 sout | hex(0b_10100010001101000101011001111000_10100111011001010100001100100001_11000010001101000101011001111000_L128); 335 sout | hex(0b_10100010001101000101011001111000_10100111011001010100001100100001_11000010001101000101011001111000_11010111010101010100001100100001_L128); 336 sout | nl; 337 338 sout | "octal"; 339 sout | oct(v); 340 sout | oct(0_123456_L128u); 341 sout | oct(0_123456_65432_uL128); 342 sout | oct(0_123456_65432_34567_L128); 343 sout | oct(0_123456_65432_34567_76543_L128); 344 sout | oct(0_123456_65432_34567_76543_23456_L128); 345 sout | oct(0_123456_65432_34567_76543_23456_65432_L128); 346 sout | oct(0_123456_65432_34567_76543_23456_65432_34567_L128); 347 sout | oct(0_123456_65432_34567_76543_23456_65432_34567_76543_L128); 348 sout | oct(0_1111111111111111111L); 349 sout | oct(0_11111111111111111111L); 350 sout | oct(0_111111111111111111111L); 351 sout | nl; 352 353 sout | "decimal"; 354 sout | v; 355 sout | 42_798_L128 | oct(42_798_L128); 356 sout | 1_402_432_282_L128 | oct(1_402_432_282_L128); 357 sout | 45_954_901_031_287_L128 | oct(45_954_901_031_287_L128); 358 sout | 1_505_850_196_993_244_515_L128 | oct(1_505_850_196_993_244_515_L128); 359 sout | 394_749_758_663_249_135_511_342_L128 | oct(394_749_758_663_249_135_511_342_L128); 360 sout | 12_935_154_696_204_706_112_391_834_394_L128 | oct(12_935_154_696_204_706_112_391_834_394_L128); 361 sout | 423_859_149_128_410_414_395_372_834_994_551_L128 | oct(423_859_149_128_410_414_395_372_834_994_551_L128); 362 sout | 13_889_016_598_639_747_063_234_935_497_057_631_587_L128 | oct(13_889_016_598_639_747_063_234_935_497_057_631_587_L128); 363 sout | 1234567890123456789_uL128; 364 sout | 1234567890123456789_L128u; 365 sout | 0x_7fffffff_ffffffff_ffffffff_ffffffff_L128; 366 sout | 0x_ffffffff_ffffffff_ffffffff_ffffffff_L128; 367 sout | 0x_80000000_00000000_00000000_00000000_L128; 368 unsigned int128 vv; 369 vv = 340282366920938463463374607431768211455_L128u; 370 sout | vv; 371 vv = 170141183460469231731687303715884105727_L128; 372 sout | vv; 373 sout | nl; 374 375 sout | "hexadecimal"; 376 sout | hex(v); 377 sout | hex(0x_ffffffff_L128); 378 sout | hex(0x_ffffffff_ffffffff_L128); 379 sout | hex(0x_ffffffff_ffffffff_ffffffff_L128); 380 sout | hex(0xffffffff_ffffffff_ffffffff_ffffffff_L128); 381 sout | hex(0x_a2345678_L128); 382 sout | hex(0x_a2345678_b7654321_L128); 383 sout | hex(0x_a2345678_b7654321_c2345678_L128); 384 sout | hex(0x_a2345678_b7654321_c2345678_d7654321_L128); 385 sout | nl; 386 } // main 387 388 // Local Variables: // 389 // tab-width: 4 // 390 // compile-command: "cfa -Wall -Wextra manipulatorsOutput3.cfa" // 391 // End: // -
tests/pybin/test_run.py
r07d867b r22f94a4 69 69 else : text = "FAILED with code %d" % retcode 70 70 71 text += " C%s - R%s" % ( cls.fmtDur(duration[0]), cls.fmtDur(duration[1]))71 text += " C%s - R%s" % (fmtDur(duration[0]), fmtDur(duration[1])) 72 72 return text 73 74 @staticmethod75 def fmtDur( duration ):76 if duration :77 hours, rem = divmod(duration, 3600)78 minutes, rem = divmod(rem, 60)79 seconds, millis = divmod(rem, 1)80 return "%2d:%02d.%03d" % (minutes, seconds, millis * 1000)81 return " n/a" -
tests/pybin/tools.py
r07d867b r22f94a4 387 387 while True: 388 388 yield i.next(max(expire - time.time(), 0)) 389 390 def fmtDur( duration ): 391 if duration : 392 hours, rem = divmod(duration, 3600) 393 minutes, rem = divmod(rem, 60) 394 seconds, millis = divmod(rem, 1) 395 return "%2d:%02d.%03d" % (minutes, seconds, millis * 1000) 396 return " n/a" -
tests/searchsort.cfa
r07d867b r22f94a4 38 38 } // for 39 39 sout | nl; 40 for ( i; 0 ~ size ) { // C version 40 for ( i; 0 ~ size ) { // C version, returns void* 41 41 int key = size - i; 42 int * v = bsearch( &key, iarr, size, sizeof( iarr[0] ), comp );42 int * v = ( int * ) bsearch( &key, iarr, size, sizeof( iarr[0] ), comp ); 43 43 sout | key | ':' | *v | ", "; 44 44 } // for -
tests/test.py
r07d867b r22f94a4 361 361 362 362 # for each build configurations, run the test 363 for arch, debug, install in itertools.product(settings.all_arch, settings.all_debug, settings.all_install): 364 settings.arch = arch 365 settings.debug = debug 366 settings.install = install 367 368 # filter out the tests for a different architecture 369 # tests are the same across debug/install 370 local_tests = settings.arch.filter( tests ) 371 options.jobs, forceJobs = job_count( options, local_tests ) 372 settings.update_make_cmd(forceJobs, options.jobs) 373 374 # check the build configuration works 375 settings.validate() 376 377 # print configuration 378 print('%s %i tests on %i cores (%s:%s)' % ( 379 'Regenerating' if settings.generating else 'Running', 380 len(local_tests), 381 options.jobs, 382 settings.arch.string, 383 settings.debug.string 384 )) 385 386 # otherwise run all tests and make sure to return the correct error code 387 failed = run_tests(local_tests, options.jobs) 388 if failed: 389 result = 1 390 if not settings.continue_: 391 break 392 393 363 with Timed() as total_dur: 364 for arch, debug, install in itertools.product(settings.all_arch, settings.all_debug, settings.all_install): 365 settings.arch = arch 366 settings.debug = debug 367 settings.install = install 368 369 # filter out the tests for a different architecture 370 # tests are the same across debug/install 371 local_tests = settings.arch.filter( tests ) 372 options.jobs, forceJobs = job_count( options, local_tests ) 373 settings.update_make_cmd(forceJobs, options.jobs) 374 375 # check the build configuration works 376 settings.validate() 377 378 # print configuration 379 print('%s %i tests on %i cores (%s:%s)' % ( 380 'Regenerating' if settings.generating else 'Running', 381 len(local_tests), 382 options.jobs, 383 settings.arch.string, 384 settings.debug.string 385 )) 386 387 # otherwise run all tests and make sure to return the correct error code 388 failed = run_tests(local_tests, options.jobs) 389 if failed: 390 result = 1 391 if not settings.continue_: 392 break 393 394 print('Tests took %s' % fmtDur( total_dur.duration )) 394 395 sys.exit( failed ) -
tests/time.cfa
r07d867b r22f94a4 10 10 // Created On : Tue Mar 27 17:24:56 2018 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Jan 5 18:27:37202013 // Update Count : 3 412 // Last Modified On : Thu Jun 18 18:14:49 2020 13 // Update Count : 37 14 14 // 15 15 … … 20 20 Duration d1 = 3`h, d2 = 2`s, d3 = 3.375`s, d4 = 12`s, d5 = 1`s + 10_000`ns; 21 21 sout | d1 | d2 | d3 | d4 | d5; 22 sout | d1`dd | d2`dm | d3`ds | d4`dms | d5`dus; 22 23 d1 = 0; 23 24 sout | d1 | d2 | d3; -
tools/build/cfa.make
r07d867b r22f94a4 1 CFACOMPILE = $(CFACC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CFAFLAGS) $(CFAFLAGS) $(AM_CFLAGS) $(CFLAGS) 2 LTCFACOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ 1 AM_T_CFA = $(am__t_CFA_@AM_T@) 2 am__t_CFA_ = 3 am__t_CFA_0 = 4 am__t_CFA_1 = /usr/bin/time --quiet -f "$@ %E" # trailling space is necessary 5 6 7 CFACOMPILE = $(AM_T_CFA)$(CFACC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CFAFLAGS) $(CFAFLAGS) $(AM_CFLAGS) $(CFLAGS) 8 LTCFACOMPILE = $(AM_T_CFA)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ 3 9 $(LIBTOOLFLAGS) --mode=compile $(CFACC) $(DEFS) \ 4 10 $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CFAFLAGS) $(AM_CFLAGS) $(CFAFLAGS) $(CFLAGS) -
tools/build/push2dist.sh
r07d867b r22f94a4 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 -
tools/gdb/utils-gdb.py
r07d867b r22f94a4 59 59 thread_ptr = gdb.lookup_type('struct $thread').pointer(), 60 60 int_ptr = gdb.lookup_type('int').pointer(), 61 thread_state = gdb.lookup_type('enum coroutine_state'))61 thread_state = gdb.lookup_type('enum __Coroutine_State')) 62 62 63 63 def get_addr(addr):
Note:
See TracChangeset
for help on using the changeset viewer.