Changeset 22f94a4


Ignore:
Timestamp:
Aug 11, 2020, 4:40:15 PM (5 years ago)
Author:
Thierry Delisle <tdelisle@…>
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.
Message:

Merge branch 'master' into new-ast

Files:
91 added
42 deleted
125 edited
6 moved

Legend:

Unmodified
Added
Removed
  • .gitignore

    r07d867b r22f94a4  
    44
    55# generated by configure
     6aclocal.m4
     7automake
    68autom4te.cache
    79config.h
     
    911config.log
    1012config.py
     13configure
     14libtool
    1115stamp-h1
    12 libtool
    1316/Makefile
     17/Makefile.in
    1418**/Makefile
     19**/Makefile.in
    1520/version
    1621
  • Jenkinsfile_disabled

    r07d867b r22f94a4  
    114114        release = Settings.RunAllTests || Settings.RunBenchmark
    115115        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
    116122                // Build outside of the src tree to ease cleaning
    117123                dir (BuildDir) {
  • benchmark/Makefile.am

    r07d867b r22f94a4  
    1919
    2020# applies to both programs
    21 include $(top_srcdir)/src/cfa.make
     21include $(top_srcdir)/tools/build/cfa.make
    2222
    2323AM_CFLAGS = -O2 -Wall -Wextra -I$(srcdir) -lrt -pthread # -Werror
  • benchmark/creation/node_cor.js

    r07d867b r22f94a4  
    55
    66function * coroutine() { yield }
     7
     8for ( var i = 0; i < times; i += 1 ) { // warm jit
     9        cor = coroutine()
     10}
     11
    712var hrstart = process.hrtime()
    813for ( var i = 0; i < times; i += 1 ) {
  • benchmark/ctxswitch/node_cor.js

    r07d867b r22f94a4  
    1010}
    1111cor = coroutine()
     12
     13for ( var i = 0; i < times; i += 1 ) { // warm git
     14        cor.next();
     15}
    1216
    1317var hrstart = process.hrtime()
  • benchmark/exclude

    r07d867b r22f94a4  
    1010interrupt_linux.c
    1111exclude
     12io
    1213Monitor.c
  • benchmark/io/readv.cfa

    r07d867b r22f94a4  
     1#define _GNU_SOURCE
     2
    13#include <stdlib.h>
    24#include <stdio.h>
     
    1012}
    1113
     14#include <errno.h>
    1215#include <unistd.h>
    1316
    1417#include <clock.hfa>
     18#include <iofwd.hfa>
    1519#include <kernel.hfa>
    1620#include <thread.hfa>
    1721#include <time.hfa>
     22#include <stats.hfa>
     23
     24#include "../benchcltr.hfa"
    1825
    1926extern bool traceHeapOn();
    20 extern ssize_t cfa_preadv2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags);
    2127
    2228int fd;
     
    2430volatile size_t count = 0;
    2531
    26 unsigned long int buflen = 50;
     32unsigned long int buflen = 512;
     33bool fixed_file = false;
    2734
    28 cluster * the_cluster;
    29 
    30 thread Reader {};
     35thread __attribute__((aligned(128))) Reader {};
    3136void ?{}( Reader & this ) {
    32         ((thread&)this){ "Reader Thread", *the_cluster };
     37        ((thread&)this){ "Reader Thread", *the_benchmark_cluster };
    3338}
    3439
    35 struct my_processor {
    36         processor p;
    37 };
    38 
    39 void ?{}( my_processor & this ) {
    40         (this.p){ "I/O Processor", *the_cluster };
     40int 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);
    4147}
    4248
    4349void 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) );
    4552
    46         char data[buflen];
     53        __attribute__((aligned(512)))  char data[buflen];
    4754        struct iovec iov = { data, buflen };
    4855
    4956        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));
    5259
    5360                __atomic_fetch_add( &count, 1, __ATOMIC_SEQ_CST );
     
    5663
    5764int 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;
    6270
    6371        arg_loop:
    6472        for(;;) {
    6573                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'},
    7183                        {0, 0, 0, 0}
    7284                };
    7385
    7486                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);
    7688
    7789                const char * arg = optarg ? optarg : "";
     
    8193                        case -1:
    8294                                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
    10596                        case 'b':
    10697                                buflen = strtoul(arg, &end, 10);
     
    110101                                }
    111102                                break;
    112                         case 'u':
    113                                 flags |= CFA_CLUSTER_IO_POLLER_USER_THREAD;
     103                        case 's':
     104                                params.poller_submits = true;
    114105                                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;
    116127                        default: /* ? */
    117128                                fprintf(stderr, "%d\n", opt);
    118129                        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" );
    125138                                exit(EXIT_FAILURE);
    126139                }
    127140        }
    128141
    129         fd = open(__FILE__, 0);
    130         if(fd < 0) {
     142        int lfd = open(__FILE__, file_flags);
     143        if(lfd < 0) {
    131144                fprintf(stderr, "Could not open source file\n");
    132145                exit(EXIT_FAILURE);
    133146        }
    134147
    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);
    136149
    137150        {
    138151                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
    144162                {
    145                         my_processor procs[nprocs];
     163                        BenchProc procs[nprocs];
    146164                        {
    147165                                Reader threads[nthreads];
    148166
    149167                                printf("Starting\n");
    150                                 start = getTime();
     168                                bool is_tty = isatty(STDOUT_FILENO);
     169                                start = getTimeNsec();
    151170                                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
    156177                                run = false;
    157                                 end = getTime();
    158                                 printf("Done\n");
     178                                end = getTimeNsec();
     179                                printf("\nDone\n");
    159180                        }
     181                        printf("Readers closed\n");
    160182                }
    161183                printf("Took %'ld ms\n", (end - start)`ms);
     
    166188        }
    167189
    168         close(fd);
     190        close(lfd);
    169191}
  • configure.ac

    r07d867b r22f94a4  
    66AC_CONFIG_AUX_DIR([automake])
    77AC_CONFIG_MACRO_DIRS([automake])
    8 #AC_CONFIG_SRCDIR([src/main.cc])
    98AC_CONFIG_HEADERS([config.h:src/config.h.in])
    109AM_SILENT_RULES([yes])
    1110
    12 m4_include([automake/cfa.m4])
     11m4_include([tools/build/cfa.m4])
    1312
    1413# don't use the default CFLAGS as they unconditonnaly add -O2
     
    6463        [  --enable-distcc     whether or not to enable distributed compilation],
    6564        enable_distcc=$enableval, enable_distcc=no)
     65
     66AC_ARG_WITH(bwlimit,
     67        [  --with-bwlimit=RATE     RATE the maximum rate at which rsync will be limited when using distributed builds],
     68        [], [])
    6669
    6770AM_CONDITIONAL([ENABLE_DISTCC], [test x$enable_distcc = xyes])
  • doc/bibliography/pl.bib

    r07d867b r22f94a4  
    10011001}
    10021002
    1003 @misc{CforallBenchMarks,
     1003@misc{CforallConcurrentBenchmarks,
    10041004    contributer = {pabuhr@plg},
    10051005    key         = {Cforall Benchmarks},
    10061006    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}},
    10081008}
    10091009
     
    19821982    author      = {Adya, Atul and Howell, Jon and Theimer, Marvin and Bolosky, William J. and Douceur, John R.},
    19831983    title       = {Cooperative Task Management Without Manual Stack Management},
    1984     booktitle   = {Proceedings of the General Track of the Annual Conference on USENIX Annual Technical Conference},
     1984    booktitle   = {Proc. of the General Track USENIX Tech. Conf.},
    19851985    series      = {ATEC '02},
    19861986    year        = {2002},
  • doc/papers/AMA/AMA-stix/ama/WileyNJD-v2.cls

    r07d867b r22f94a4  
    24442444     \@afterheading}
    24452445
    2446 \renewcommand\section{\@startsection{section}{1}{\z@}{-25pt \@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}}%
    24492449%
    24502450\newskip\secruleskip\secruleskip8.5\p@%
  • doc/papers/concurrency/Paper.tex

    r07d867b r22f94a4  
    9999\newcommand{\CRT}{\global\columnposn=\gcolumnposn}
    100100
    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}
    103103% The star version does not lowercase the index information, e.g., \newterm*{IBM}.
    104104\newcommand{\newtermFontInline}{\emph}
     
    235235{\lstset{language=python,moredelim=**[is][\protect\color{red}]{`}{`},#1}\lstset{#1}}
    236236{}
     237\lstnewenvironment{java}[1][]
     238{\lstset{language=java,moredelim=**[is][\protect\color{red}]{`}{`},#1}\lstset{#1}}
     239{}
    237240
    238241% inline code @...@
     
    266269
    267270\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.
    269272This paper discusses the design philosophy and implementation of its advanced control-flow and concurrent/parallel features, along with the supporting runtime written in \CFA.
    270273These 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.
     
    272275% Library extension for executors, futures, and actors are built on these basic mechanisms.
    273276The 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.
     277The 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.
    275278All control-flow features integrate with the \CFA polymorphic type-system and exception handling, while respecting the expectations and style of C programmers.
    276279Experimental results show comparable performance of the new features with similar mechanisms in other concurrent programming languages.
     
    289292
    290293\CFA~\cite{Moss18,Cforall} is a modern, polymorphic, non-object-oriented\footnote{
    291 \CFA has object-oriented features, such as constructors, destructors, virtuals and simple trait/interface inheritance.
     294\CFA has object-oriented features, such as constructors, destructors, and simple trait/interface inheritance.
    292295% Go interfaces, Rust traits, Swift Protocols, Haskell Type Classes and Java Interfaces.
    293296% "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".
     299However, functions \emph{cannot} be nested in structures and there is no mechanism to designate a function parameter as a receiver, \lstinline@this@, parameter.},
    296300backwards-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.}
     301In 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{
     302The 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.}
    299303allowing 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.
     304This 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.
    302305
    303306% The call/return extensions retain state between callee and caller versus losing the callee's state on return;
    304307% the concurrency extensions allow high-level management of threads.
    305308
    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{
     309The \CFA control-flow framework extends ISO \Celeven~\cite{C11} with new call/return and concurrent/parallel control-flow.
     310Call/return control-flow with argument and parameter passing appeared in the first programming languages.
     311Over 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}).
     312While \CFA has mechanisms for dynamic call (algebraic effects~\cite{Zhang19}) and exceptions\footnote{
    309313\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.
     314The 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.
    311315\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}.
    312316Coroutining 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}.
     317If 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}.
    314318Coroutines are only a stepping stone towards concurrency where the commonality is that coroutines and threads retain state between calls.
    315319
    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}
     321Interestingly, 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).
    318322While 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.
    319323In contrast, there has been a renewed interest during the past decade in user-level (M:N, green) threading in old and new programming languages.
     
    321325Kernel 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}.
    322326Libraries 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.
     327As 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.
    324328From 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}.
     329The 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}.
    326330As 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.
     331Finally, 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.
    328332
    329333A 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.
     334The 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.
     335One solution is low-level qualifiers and functions, \eg @volatile@ and atomics, allowing \emph{programmers} to explicitly write safe, race-free~\cite{Boehm12} programs.
     336A 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.
    333337While the optimization problem is best known with respect to concurrency, it applies to other complex control-flow, like exceptions and coroutines.
    334338As 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.
    335339
    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{
     340Finally, it is important for a language to provide safety over performance \emph{as the default}, allowing careful reduction of safety for performance when necessary.
     341Two concurrency violations of this philosophy are \emph{spurious} or \emph{random wakeup}~\cite[\S~9]{Buhr05a}, and \emph{barging}\footnote{
    338342Barging is competitive succession instead of direct handoff, \ie after a lock is released both arriving and preexisting waiter threads compete to acquire the lock.
    339343Hence, 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.
    341345(Author experience teaching concurrency is that students are confused by these semantics.)
    342346However, spurious wakeup is \emph{not} a foundational concurrency property~\cite[\S~9]{Buhr05a};
     
    356360
    357361\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,
     362monitor 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,
    359363
    360364\item
     
    368372
    369373\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).
     374a 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.
    371375
    372376% \item
     
    380384Section~\ref{s:StatefulFunction} begins advanced control by introducing sequential functions that retain data and execution state between calls producing constructs @generator@ and @coroutine@.
    381385Section~\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).
     386Section~\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.
    383387Section~\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.
     388Section~\ref{s:CFARuntimeStructure} describes the large-scale mechanism to structure threads and virtual processors (kernel threads).
     389Section~\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.
    386390
    387391
     
    389393\label{s:FundamentalExecutionProperties}
    390394
    391 The features in a programming language should be composed from a set of fundamental properties rather than an ad hoc collection chosen by the designers.
     395The features in a programming language should be composed of a set of fundamental properties rather than an ad hoc collection chosen by the designers.
    392396To 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) composed features 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 is inefficient solution.
     397The fundamental properties are execution state, thread, and mutual-exclusion/synchronization.
     398These 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.
     399While 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.
     400As 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.
     401If a compositional feature is missing, a programmer has too few fundamental properties resulting in a complex and/or inefficient solution.
    398402
    399403In detail, the fundamental properties are:
    400404\begin{description}[leftmargin=\parindent,topsep=3pt,parsep=0pt]
    401405\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.
     406is the state information needed by a control-flow feature to initialize and manage both compute data and execution location(s), and de-initialize.
     407For 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.
     408State is retained in fixed-sized aggregate structures (objects) and dynamic-sized stack(s), often allocated in the heap(s) managed by the runtime system.
     409The 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.
     410Control-flow transfers among execution states in multiple ways, such as function call, context switch, asynchronous await, etc.
    406411Because 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.
    407412% An execution-state is related to the notion of a process continuation \cite{Hieb90}.
    408413
    409414\item[\newterm{threading}:]
    410 is execution of code that occurs independently of other execution, \ie the execution resulting from a thread is sequential.
     415is execution of code that occurs independently of other execution, where an individual thread's execution is sequential.
    411416Multiple 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 mechanisms to 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.
     417concurrent execution becomes parallel when run on multiple processing units, \eg hyper-threading, cores, or sockets.
     418A 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)}:]
     421is the concurrency mechanism to perform an action without interruption and establish timing relationships among multiple threads.
     422We contented these two properties are independent, \ie mutual exclusion cannot provide synchronization and vice versa without introducing additional threads~\cite[\S~4]{Buhr05a}.
     423Limiting MES functionality results in contrived solutions and inefficiency on multi-core von Neumann computers where shared memory is a foundational aspect of its design.
    419424\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.
     425These 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
     430Programming languages seldom present the fundamental execution properties directly to programmers.
     431Instead, the properties are packaged into higher-level constructs that encapsulate details and provide safety to these low-level mechanisms.
     432Interestingly, language designers often pick and choose among these execution properties proving a varying subset of constructs.
     433
     434Table~\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.)
     436The 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.
     437To 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.
    428438For 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.
     439Each 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.
    441440
    442441\begin{table}
     
    446445\renewcommand{\arraystretch}{1.25}
    447446%\setlength{\tabcolsep}{5pt}
     447\vspace*{-5pt}
    448448\begin{tabular}{c|c||l|l}
    449449\multicolumn{2}{c||}{execution properties} & \multicolumn{2}{c}{mutual exclusion / synchronization} \\
     
    452452\hline   
    453453\hline   
    454 No                                      & No            & \textbf{1}\ \ \ function                              & \textbf{2}\ \ \ @monitor@ function    \\
     454No                                      & No            & \textbf{1}\ \ \ @struct@                              & \textbf{2}\ \ \ @mutex@ @struct@              \\
    455455\hline   
    456 Yes (stackless)         & No            & \textbf{3}\ \ \ @generator@                   & \textbf{4}\ \ \ @monitor@ @generator@ \\
     456Yes (stackless)         & No            & \textbf{3}\ \ \ @generator@                   & \textbf{4}\ \ \ @mutex@ @generator@   \\
    457457\hline   
    458 Yes (stackful)          & No            & \textbf{5}\ \ \ @coroutine@                   & \textbf{6}\ \ \ @monitor@ @coroutine@ \\
     458Yes (stackful)          & No            & \textbf{5}\ \ \ @coroutine@                   & \textbf{6}\ \ \ @mutex@ @coroutine@   \\
    459459\hline   
    460460No                                      & Yes           & \textbf{7}\ \ \ {\color{red}rejected} & \textbf{8}\ \ \ {\color{red}rejected} \\
     
    462462Yes (stackless)         & Yes           & \textbf{9}\ \ \ {\color{red}rejected} & \textbf{10}\ \ \ {\color{red}rejected} \\
    463463\hline   
    464 Yes (stackful)          & Yes           & \textbf{11}\ \ \ @thread@                             & \textbf{12}\ \ @monitor@ @thread@             \\
     464Yes (stackful)          & Yes           & \textbf{11}\ \ \ @thread@                             & \textbf{12}\ \ @mutex@ @thread@               \\
    465465\end{tabular}
     466\vspace*{-8pt}
    466467\end{table}
    467468
    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.
     469Case 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.
     470Structures are a foundational mechanism for data organization, and access functions provide interface abstraction and code sharing in all programming languages.
     471Case 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).
     472A @mutex@ structure, often called a \newterm{monitor}, provides a high-level interface for race-free access of shared data in concurrent programming-languages.
     473Case 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.
     474A 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.
     475Generators 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.
     476Case 4 is cases 2 and 3 with thread safety during execution of the generator's access functions.
     477A @mutex@ generator extends generators into the concurrent domain.
     478Cases 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.
     479A 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.
     480A coroutine extends the state retained between calls beyond the generator's structure to arbitrary call depth in the access functions.
     481Cases 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.
     482For 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.
     483Hence, if this kind of uninterruptable thread exists, it must execute to completion, \ie computation only, which severely restricts runtime management.
     484Cases 11 and 12 are a stackful thread with and without safe access to shared state.
     485A thread is the language mechanism to start another thread of control in a program with growable execution state for call/return execution.
     486In general, language constructs with more execution properties increase the cost of creation and execution along with complexity of usage.
     487
     488Given 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.
     489Table~\ref{t:ExecutionPropertyComposition} then suggests the optimal language feature needed for implementing a programming problem.
     490The 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.
    471491
    472492
     
    481501\item
    482502Direct 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.
     503For example, many concurrent languages do not provide direct communication calls among threads, \ie threads only communicate indirectly through monitors, channels, messages, and/or futures.
     504Indirect communication increases the number of objects, consuming more resources, and requires additional synchronization and possibly data transfer.
    485505
    486506\item
     
    493513
    494514\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.
     515MES 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.
    496516Furthermore, reducing synchronization scope by encapsulating it within language constructs further reduces errors in concurrent programs.
    497517
     
    502522\item
    503523Synchronization 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}.
     524Otherwise, certain concurrency problems are difficult, \eg web server, disk scheduling, and the amount of concurrency is inhibited~\cite{Gentleman81}.
    505525\end{itemize}
    506526We have satisfied these requirements in \CFA while maintaining backwards compatibility with the huge body of legacy C programs.
     
    511531
    512532Asynchronous 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}.
     533The caller detects the action's completion through a \newterm{future} or \newterm{promise}.
    514534The benefit is asynchronous caller execution with respect to the callee until future resolution.
    515535For 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.
     
    517537A promise-completion call-back can be part of the callee action or the caller is rescheduled;
    518538in either case, the call back is executed after the promise is fulfilled.
    519 While asynchronous calls generate new callee (server) events, we content this mechanism is insufficient for advanced control-flow mechanisms like generators or coroutines (which are discussed next).
     539While 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.
    520540Specifically, 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.
    521541Note, @async-await@ is just syntactic-sugar over the event engine so it does not solve these deficiencies.
    522542For 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 stops threads.
     543The problem is when concurrent work-units need to interact and/or block as this effects the executor by stopping threads.
    524544While 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.
    525545
     
    540560There are two styles of activating a stateful function, \emph{asymmetric} or \emph{symmetric}, identified by resume/suspend (no cycles) and resume/resume (cycles).
    541561These 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.
     562Selecting 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.
     563Additionally, storage management for the closure/stack must be factored into design and performance, especially in unmanaged languages without garbage collection.
    544564Note, creation cost (closure/stack) is amortized across usage, so activation cost (resume/suspend) is usually the dominant factor.
    545565
     
    578598&
    579599\begin{cfa}
    580 void * rtn( void * arg ) { ... }
     600void * `rtn`( void * arg ) { ... }
    581601int i = 3, rc;
    582602pthread_t t; $\C{// thread id}$
     
    690710\hspace{3pt}
    691711\subfloat[C generated code for \CFA version]{\label{f:CFibonacciSim}\usebox\myboxC}
    692 \caption{Fibonacci (output) asymmetric generator}
     712\caption{Fibonacci output asymmetric generator}
    693713\label{f:FibonacciAsymmetricGenerator}
    694714
     
    765785\subfloat[C generated code for \CFA version]{\label{f:CFormatGenImpl}\usebox\myboxB}
    766786\hspace{3pt}
    767 \caption{Formatter (input) asymmetric generator}
     787\caption{Formatter input asymmetric generator}
    768788\label{f:FormatterAsymmetricGenerator}
    769789\end{figure}
    770790
    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.
     791Figure~\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.
    772792This generator is an \emph{output generator}, producing a new result on each resumption.
    773793To 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;
     794An additional requirement is the ability to create an arbitrary number of generators of any kind, \ie retaining one state in global variables is insufficient;
    775795hence, state is retained in a closure between calls.
    776796Figure~\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.
     
    794814Figure~\ref{f:CFibonacciSim} shows the C implementation of the \CFA asymmetric generator.
    795815Only 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}).
     816At 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}.
    797817Next, 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.
     818The  cost of setting @restart@ and branching via the computed @goto@ adds very little cost to the suspend and resume calls.
    799819
    800820An advantage of the \CFA explicit generator type is the ability to allow multiple type-safe interface functions taking and returning arbitrary types.
     
    877897With 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.
    878898Our 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.
     899As well, C programmers are not afraid of this kind of semantic programming requirement, if it results in very small and fast generators.
    880900
    881901Figure~\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.
     
    899919The destructor provides a newline, if formatted text ends with a full line.
    900920Figure~\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.
     921For contrast, Figure~\ref{f:PythonFormatter} shows the equivalent Python format generator with the same properties as the \CFA format generator.
    902922
    903923% https://dl-acm-org.proxy.lib.uwaterloo.ca/
    904924
    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}
     925An 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}
    906926Swift \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;
    907927however, the calls do not retain execution state, and hence always start from the top.
     
    909929However, 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.
    910930
    911 As an example, the following protocol:
     931Figure~\ref{f:DeviceDriverGen} shows the generator advantages in implementing a simple network device-driver with the following protocol:
    912932\begin{center}
    913933\ldots\, STX \ldots\, message \ldots\, ESC ETX \ldots\, message \ldots\, ETX 2-byte crc \ldots
    914934\end{center}
    915 is for a simple network message beginning with the control character STX, ending with an ETX, and followed by a 2-byte cyclic-redundancy check.
     935where the network message begins with the control character STX, ends with an ETX, and is followed by a 2-byte cyclic-redundancy check.
    916936Control characters may appear in a message if preceded by an ESC.
    917937When 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.
     938The 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.
     939Hence, 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.
    920940The 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.
    922942
    923943\begin{figure}
     
    976996\end{figure}
    977997
    978 Figure~\ref{f:CFAPingPongGen} shows a symmetric generator, where the generator resumes another generator, forming a resume/resume cycle.
     998Generators can also have symmetric activation using resume/resume to create control-flow cycles among generators.
    979999(The trivial cycle is a generator resuming itself.)
    9801000This 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.
     1001Figure~\ref{f:PingPongFullCoroutineSteps} shows the steps for symmetric control-flow using for the ping/pong program in Figure~\ref{f:CFAPingPongGen}.
     1002The program starts by creating the generators, @ping@ and @pong@, and then assigns the partners that form the cycle.
    9821003Constructing 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.
    9831004(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.
    9851005% (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 cycle using @resume@ to activate partner generator(s).
     1006Once 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).
    9871007Terminating 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).
    9881008Note, the creator and starter may be different, \eg if the creator calls another function that starts the cycle.
     
    9901010Also, 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.
    9911011Destructor 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}
    9921020
    9931021\begin{figure}
     
    10531081\end{figure}
    10541082
    1055 \begin{figure}
    1056 \centering
    1057 \input{FullCoroutinePhases.pstex_t}
    1058 \vspace*{-10pt}
    1059 \caption{Symmetric coroutine steps: Ping / Pong}
    1060 \label{f:PingPongFullCoroutineSteps}
    1061 \end{figure}
    1062 
    10631083Figure~\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.
    10641084Before 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.
     
    10661086While 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.
    10671087However, 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.
     1088Hence, 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@.
     1089For 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.
    10701090
    10711091Finally, 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.
     
    10841104\label{s:Coroutine}
    10851105
    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.
     1106Stackful 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.
     1107Note, simulating coroutines with stacks of generators, \eg Python with @yield from@ cannot handle symmetric control-flow.
     1108Furthermore, all stack components must be of generators, so it is impossible to call a library function passing a generator that yields.
     1109Creating a generator copy of the library function maybe impossible because the library function is opaque.
     1110
     1111A \CFA coroutine is specified by replacing @generator@ with @coroutine@ for the type.
    10881112Coroutine 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.
    10891113A series of different kinds of coroutines and their implementations demonstrate how coroutines extend generators.
    10901114
    10911115First, 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.
     1116Now the coroutine type only contains communication variables between interface functions and the coroutine main.
    10921117\begin{center}
    10931118\begin{tabular}{@{}l|l|l|l@{}}
     
    11261151\begin{cfa}
    11271152int 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;
    11321155        return crc;
    11331156}
    11341157\end{cfa}
    1135 A call to this function is placed at the end of the driver's coroutine-main.
     1158A call to this function is placed at the end of the device driver's coroutine-main.
    11361159For complex finite-state machines, refactoring is part of normal program abstraction, especially when code is used in multiple places.
    11371160Again, this complexity is usually associated with execution state rather than data state.
     
    11391162\begin{comment}
    11401163Figure~\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.
     1164Like 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.
    11421165The 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@.
    11431166The interface function @restart@, takes a Fibonacci instance and context switches to it using @resume@;
     
    13731396
    13741397Figure~\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.
     1398This example is illustrative because both producer and consumer have two interface functions with @resume@s that suspend execution in these interface functions.
    13761399The 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.
    13771400The 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.
    13781401@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.
     1402The producer's call to @delivery@ transfers values into the consumer's communication variables, resumes the consumer, and returns the consumer status.
    13801403Similarly on the first resume, @cons@'s stack is created and initialized, holding local-state variables retained between subsequent activations of the coroutine.
    13811404The symmetric coroutine cycle forms when the consumer calls the producer's @payment@ function, which resumes the producer in the consumer's delivery function.
    13821405When the producer calls @delivery@ again, it resumes the consumer in the @payment@ function.
    1383 Both interface function than return to the their corresponding coroutine-main functions for the next cycle.
     1406Both interface functions then return to their corresponding coroutine-main functions for the next cycle.
    13841407Figure~\ref{f:ProdConsRuntimeStacks} shows the runtime stacks of the program main, and the coroutine mains for @prod@ and @cons@ during the cycling.
    13851408As 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.
     
    13951418
    13961419Terminating 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.
     1420Furthermore, 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.
    13981421In 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.
    13991422% (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.)
     
    14011424The question now is where does control continue?
    14021425
    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.
     1426The 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.
    14041427However, for coroutines, the last resumer is \emph{not} implicitly below the current stack frame, as for generators, because each coroutine's stack is independent.
    14051428Unfortunately, it is impossible to determine statically if a coroutine is in a cycle and unrealistic to check dynamically (graph-cycle problem).
     
    14101433For asymmetric coroutines, it is common for the first resumer (starter) coroutine to be the only resumer;
    14111434for 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.
     1435For 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.
    14131436
    14141437Note, the producer/consumer example does not illustrate the full power of the starter semantics because @cons@ always ends first.
    14151438Assume generator @PingPong@ in Figure~\ref{f:PingPongSymmetricGenerator} is converted to a coroutine.
    14161439Unlike 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.
     1440By adjusting $N$ for either @ping@ or @pong@, it is possible to have either finish first.
    14181441If @pong@ ends first, it resumes its starter @ping@ in its coroutine main, then @ping@ ends and resumes its starter the program main on return;
    14191442if @ping@ ends first, it resumes its starter the program main on return.
    14201443Regardless 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, runnning 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 semnatics, regardless of the coroutine's state (terminated or active), like any other aggregate object.
     1444Once 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.
     1445Hence, 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.
    14231446
    14241447
    14251448\subsection{Generator / Coroutine Implementation}
    14261449
    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, \eg stack.
    1428 There are several solutions to these problem, which follow from the object-oriented flavour of adopting custom types.
     1450A 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.
     1451There are several solutions to this problem, which follow from the object-oriented flavour of adopting custom types.
    14291452
    14301453For object-oriented languages, inheritance is used to provide extra fields and code via explicit inheritance:
     
    14331456\end{cfa}
    14341457% 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.
     1458The 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.
    14361459Alternatives, such as explicitly starting threads as in Java, are repetitive and forgetting to call start is a common source of errors.
    14371460An alternative is composition:
     
    14611484forall( `dtype` T | is_coroutine(T) ) void $suspend$( T & ), resume( T & );
    14621485\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.
     1486Note, 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.
     1487The \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.
     1488The 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.
     1489The @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.
    14671490The 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@.
    14681491
     
    15061529
    15071530Figure~\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.
     1531The coroutine handle is the @coroutine@ instance containing programmer specified type global and communication variables across interface functions.
    15091532The coroutine descriptor contains all implicit declarations needed by the runtime, \eg @suspend@/@resume@, and can be part of the coroutine handle or separate.
    15101533The 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.}
     1534Hence, 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.}
    15141538on 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.
     1539For a VLS stack allocation and deallocation is an inexpensive adjustment of the stack pointer, modulo any stack constructor costs to initial frame setup.
     1540For 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.
     1541It 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.
     1542Currently, \CFA supports stack and heap allocated descriptors but only fixed-sized heap allocated stacks.
    15191543In \CFA debug-mode, the fixed-sized stack is terminated with a write-only page, which catches most stack overflows.
    15201544Experience teaching concurrency with \uC~\cite{CS343} shows fixed-sized stacks are rarely an issue for students.
     
    15391563The 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}.
    15401564Therefore, 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.
     1565The 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.
    15421566Adding \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.
    15431567Uncertainty 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.
     1568The reason is that the scheduler and runtime have complete knowledge about resources and how to best utilized them.
    15451569However, 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;
    15461570otherwise, it is impossible to write meaningful concurrent programs.
     
    15561580\label{s:threads}
    15571581
    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@.
     1582Threading (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@.
    15601583\vspace{4pt}
    15611584\par\noindent
     
    15891612\vspace{1pt}
    15901613\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.
    15921615\begin{cfa}
    15931616thread MyThread {};
     
    15981621} $\C{// deallocate stack-based threads, implicit joins before destruction}$
    15991622\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).
     1623This semantic ensures a thread is started and stopped exactly once, eliminating some programming error, and scales to multiple threads for basic termination synchronization.
     1624For block allocation to arbitrary depth, including recursion, threads are created and destroyed in a lattice structure (tree with top and bottom).
    16021625Arbitrary topologies are possible using dynamic allocation, allowing threads to outlive their declaration scope, identical to normal dynamic allocation.
    16031626\begin{cfa}
     
    16061629        MyThread * team = factory( 10 );
    16071630        // 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$
    16091632}
    16101633\end{cfa}
     
    16701693\end{tabular}
    16711694\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.
     1695Like 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.
     1696Similarly, 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.
    16741697(The qualifier @mutex@ for the destructor parameter is discussed in Section~\ref{s:Monitor}.)
    16751698The 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;
    16761699whereas, 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.
     1700No 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.
    16781701
    16791702
     
    16831706Unrestricted nondeterminism is meaningless as there is no way to know when a result is completed and safe to access.
    16841707To 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 exlusion 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/or incorrect transfer of data.
     1708The 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.
     1709Without 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.
    16871710Preventing or detecting barging is a challenge with low-level locks, but made easier through higher-level constructs.
    16881711This challenge is often split into two different approaches: barging \emph{avoidance} and \emph{prevention}.
     
    16961719Some 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).
    16971720However, 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.
     1721Hence, a programmer must learn and manipulate two sets of design and programming patterns.
    16991722While 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.
     1723In contrast, approaches based on shared-state models more closely resemble the standard call and return programming model, resulting in a single programming paradigm.
    17011724Finally, a newer approach for restricting non-determinism is transactional memory~\cite{Herlihy93}.
    17021725While 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.
     
    17111734For these reasons, \CFA selected monitors as the core high-level concurrency construct, upon which higher-level approaches can be easily constructed.
    17121735
    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}
     1736Figure~\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.)
     1738A \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@.)
     1740More 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).
     1741Restricting acquire and release points eases programming, comprehension, and maintenance, at a slight cost in flexibility and efficiency.
     1742As 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};
     1752int ++?( Aint & `mutex` this ) with(this) { return ++cnt; }
     1753int ?=?( Aint & `mutex` lhs, int rhs ) with(lhs) { cnt = rhs; }
     1754int ?=?(int & lhs, Aint & rhs) with(rhs) { lhs = cnt; }
     1755
    17301756int 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.
     1757Aint x = { 0 }, y = { 0 }, z = { 5 }; // no mutex
     1758++x; ++y; ++z;     // mutex
     1759x = 2; y = i; z = k;  // mutex
     1760i = 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]
     1766class 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}
     1773int i = 0, j = 0, k = 5;
     1774Aint x=new Aint(0), y=new Aint(0), z=new Aint(5);
     1775x.inc(); y.inc(); z.inc();
     1776x.set( 2 ); y.set( i ); z.set( k );
     1777i = 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
     1790Like 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.
    17481799Similar 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;
     1800However, 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;
    17501801RAII is purely a mutual-exclusion mechanism (see Section~\ref{s:Scheduling}).
     1802
     1803Both 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.
     1804Non-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.
     1805Monitor 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}).
     1807Whereas, Java designated members are marked with \lstinline[language=java]|synchronized| that applies to the implicit reference parameter @this@.
     1808In 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.
    17511809
    17521810
     
    17711829\end{tabular}
    17721830\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 ensures there is a mechanism to get (read) the monitor descriptor from its handle, and a special destructor to prevent deallocation if a thread using the shared data.
     1831The @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.
     1832Similarly, 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.
    17751833The 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.
    17761835
    17771836
     
    17791838\label{s:MutexAcquisition}
    17801839
    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 { ... }
     1840For object-oriented programming languages, the mutex property applies to one object, the implicit pointer/reference to the monitor type.
     1841Because \CFA uses a pointer qualifier, other possibilities exist, \eg:
     1842\begin{cfa}
     1843monitor M { ... };
    17931844int f1( M & mutex m ); $\C{// single parameter object}$
    17941845int f2( M * mutex m ); $\C{// single or multiple parameter object}$
     
    17961847int f4( stack( M * ) & mutex m ); $\C{// multiple parameters object}$
    17971848\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{
     1849Function @f1@ has a single object parameter, while functions @f2@ to @f4@ can be a single or multi-element parameter with statically unknown size.
     1850Because of the statically unknown size, \CFA only supports a single reference @mutex@ parameter, @f1@.
     1851
     1852The \CFA @mutex@ qualifier does allow the ability to support multi-monitor functions,\footnote{
    18061853While 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}.
     1854where the number of acquisitions is statically known, called \newterm{bulk acquire}.
    18081855\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.
    18091856Figure~\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.
     
    19331980% 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.
    19341981% 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.)
     1982This 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.)
    19361983While 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.
    19371984Leaving the monitor and retrying (busy waiting) is impractical for high-level programming.
     
    19391986Monitors 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.
    19401987Synchronization 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 versus, 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 of threads 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.
     1990Note, 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.
     1991For 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.
    19471994A 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.
    19481995Preventing barging comes directly from Hoare's semantics in the seminal paper on monitors~\cite[p.~550]{Hoare74}.
     
    19532000Furthermore, \CFA concurrency has no spurious wakeup~\cite[\S~9]{Buhr05a}, which eliminates an implicit self barging.
    19542001
    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 urgent and the signaller continues (solid line).
     2002Monitor 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}.
     2003Figure~\ref{f:MonitorScheduling} shows internal and external scheduling for the bounded-buffer examples in Figure~\ref{f:GenericBoundedBuffer}.
     2004For 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).
    19582005Multiple 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.
     2006When the signaller exits or waits, a thread is implicitly unblocked from urgent, if available, before unblocking a calling thread to prevent barging.
    19602007(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.
     2008Signal 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.
    19622009Specifically, the @wait@ function atomically blocks the calling thread and implicitly releases the monitor lock(s) for all monitors in the function's parameter list.
    19632010Signalling is unconditional because signalling an empty condition queue does nothing.
    19642011It 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.
     2012In \CFA, a condition queue can be created and stored independently.
    19662013
    19672014\begin{figure}
     
    20492096\end{figure}
    20502097
    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.
     2098The @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}.
     2099Signal 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.
    20532100Using @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.
    20542101
    2055 External scheduling in Figure~\ref{f:BBExt} simplifies internal scheduling by 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++}.
     2102For 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++}.
    20562103While prior languages use external scheduling solely for thread interaction, \CFA generalizes it to both monitors and threads.
    20572104External scheduling allows waiting for events from other threads while restricting unrelated events, that would otherwise have to wait on condition queues in the monitor.
     
    20622109Now 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.
    20632110For 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@.
     2111Hence, this mechanism is done in terms of control flow, next call, versus in terms of data, channels, as in Go and Rust @select@.
    20652112While both mechanisms have strengths and weaknesses, \CFA uses the control-flow mechanism to be consistent with other language features.
    20662113
    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.
     2114Figure~\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.
    20682115For 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.
    20692116To 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@.
     
    22292276For 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.
    22302277For 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.
     2278Note, 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.
    22382279This situation shows rechecking the waiting condition and waiting again (signals-as-hints) fails, requiring significant restructured to account for barging.
    22392280
    2240 Both internal and external scheduling extend to multiple monitors in a natural way.
     2281Given external and internal scheduling, what guidelines can a programmer use to select between them?
     2282In 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.
     2283Therefore, there are no condition variables, and hence, no wait and signal, which reduces coding complexity and synchronization errors.
     2284If external scheduling is simpler than internal, why not use it all the time?
     2285Unfortunately, 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.
     2286For example, the dating service cannot be written using external scheduling.
     2287First, scheduling requires knowledge of calling parameters to make matching decisions and parameters of calling threads are unavailable within the monitor.
     2288Specifically, 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.)
     2290Second, 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.
     2291Specifically, 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.
     2292For complex synchronization, both external and internal scheduling can be used to take advantage of best of properties of each.
     2293
     2294Finally, both internal and external scheduling extend to multiple monitors in a natural way.
    22412295\begin{cquote}
    22422296\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
     
    22742328Similarly, for @waitfor( rtn )@, the default semantics is to atomically block the acceptor and release all acquired mutex parameters, \ie @waitfor( rtn : m1, m2 )@.
    22752329To 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.
    22772331% 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.
    22792333Overloaded functions can be disambiguated using a cast
    22802334\begin{cfa}
     
    22852339
    22862340The ability to release a subset of acquired monitors can result in a \newterm{nested monitor}~\cite{Lister77} deadlock (see Section~\ref{s:MutexAcquisition}).
    2287 \newpage
    22882341\begin{cfa}
    22892342void foo( M & mutex m1, M & mutex m2 ) {
     
    23002353
    23012354Figure~\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.
     2355For a @waitfor@ clause to be executed, its @when@ must be true and an outstanding call to its corresponding function(s) must exist.
    23032356The \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.
     2357If 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@.
     2358If 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.
    23062359If there is a @timeout@ clause, it provides an upper bound on waiting.
    23072360If 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.
    23082361Hence, the terminating @else@ clause allows a conditional attempt to accept a call without blocking.
    23092362If 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.
    23112364Finally, there is a shorthand for specifying multiple functions using the same set of monitors: @waitfor( f, g, h : m1, m2, m3 )@.
    23122365
     
    23152368\begin{cfa}
    23162369`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}$
    23182371`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}$
    23202373`or`    ...
    23212374`when` ( $\emph{conditional-expression}$ ) $\C{// optional guard}$
     
    23352388The left example only accepts @mem1@ if @C1@ is true or only @mem2@ if @C2@ is true.
    23362389The right example accepts either @mem1@ or @mem2@ if @C1@ and @C2@ are true.
     2390Hence, the @waitfor@ has parallel semantics, accepting any true @when@ clause.
    23372391
    23382392An 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@.
     
    24292483
    24302484One 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 be immediate passed @m2@ when released, while S retains @m1@ until completion of the outer mutex statement.
     2485However, 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.
    24322486If W1 waited first, the signaller must retain @m1@ amd @m2@ until completion of the outer mutex statement and then pass both to W1.
    24332487% Furthermore, there is an execution sequence where the signaller always finds waiter W2, and hence, waiter W1 starves.
    2434 To support this 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 monitor function/statement, the front waiter on urgent is unblocked if all its monitors are released.
    2436 Implementing a fast subset check for the necessary released monitors is important and discussed in the following sections.
     2488To support these efficient semantics and prevent barging, the implementation maintains a list of monitors acquired for each blocked thread.
     2489When a signaller exits or waits in a mutex function or statement, the front waiter on urgent is unblocked if all its monitors are released.
     2490Implementing a fast subset check for the necessarily released monitors is important and discussed in the following sections.
    24372491% 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.
    24382492
     
    24422496
    24432497In 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.
     2498Knowing 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.
    24452499
    24462500\begin{figure}
     
    24932547Hence, function pointers are used to identify the functions listed in the @waitfor@ statement, stored in a variable-sized array.
    24942548Then, 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.
     2549Each 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.
    24962550
    24972551
     
    25712625
    25722626struct Msg { int i, j; };
    2573 monitor thread GoRtn { int i;  float f;  Msg m; };
     2627mutex thread GoRtn { int i;  float f;  Msg m; };
    25742628void mem1( GoRtn & mutex gortn, int i ) { gortn.i = i; }
    25752629void mem2( GoRtn & mutex gortn, float f ) { gortn.f = f; }
     
    25772631void ^?{}( GoRtn & mutex ) {}
    25782632
    2579 void main( GoRtn & gortn ) with( gortn ) { // thread starts
     2633void main( GoRtn & mutex gortn ) with(gortn) { // thread starts
    25802634
    25812635        for () {
     
    26442698
    26452699\begin{cfa}
    2646 monitor thread DatingService {
     2700mutex thread DatingService {
    26472701        condition Girls[CompCodes], Boys[CompCodes];
    26482702        int girlPhoneNo, boyPhoneNo, ccode;
     
    27082762% \label{f:pingpong}
    27092763% \end{figure}
    2710 Note, the ping/pong threads are globally declared, @pi@/@po@, and hence, start (and possibly complete) before the program main starts.
     2764Note, the ping/pong threads are globally declared, @pi@/@po@, and hence, start and possibly complete before the program main starts.
    27112765\end{comment}
    27122766
    27132767
    2714 \subsection{\texorpdfstring{\protect\lstinline@monitor@ 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.
    27172771All 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:
     2772For 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:
    27192773\begin{cfa}
    27202774void fmt( Fmt & mutex fmt, char ch ) { fmt.ch = ch; resume( fmt ) }
     
    27242778Figure~\ref{f:DirectCommunicationComparison} shows a comparison of direct call-communication in \CFA versus indirect channel-communication in Go.
    27252779(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.
     2782The \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.
    27272783Communication by multiple threads is safe for the @gortn@ thread via mutex calls in \CFA or channel assignment in Go.
     2784The difference between call and channel send occurs for buffered channels making the send asynchronous.
     2785In \CFA, asynchronous call and multiple buffers are provided using an administrator and worker threads~\cite{Gentleman81} and/or futures (not discussed).
    27282786
    27292787Figure~\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 an much work as possible.
     2788When 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.
    27312789Notice, 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.
     2790For 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.
    27332791
    27342792
     
    27362794
    27372795For 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.
     2796Some of these low-level mechanisms are used to build the \CFA runtime, but we always advocate using high-level mechanisms whenever possible.
    27392797
    27402798
     
    27682826
    27692827In 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/explicit dependency graph that ties them together.
     2828If the jobs are dependent, \ie interact, there is an implicit dependency graph that ties them together.
    27712829While removing direct concurrency, and hence the amount of context switching, thread pools significantly limit the interaction that can occur among jobs.
    27722830Indeed, jobs should not block because that also blocks the underlying thread, which effectively means the CPU utilization, and therefore throughput, suffers.
     
    28572915\label{s:RuntimeStructureProcessor}
    28582916
    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.
     2917A 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.
    28602918Programs may use more virtual processors than hardware processors.
    28612919On a multiprocessor, kernel threads are distributed across the hardware processors resulting in virtual processors executing in parallel.
     
    28722930\label{s:Implementation}
    28732931
    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.
     2932A primary implementation challenge is avoiding contention from dynamically allocating memory because of bulk acquire, \eg the internal-scheduling design is almost free of allocations.
    28752933All 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.
    28762934Furthermore, several bulk-acquire operations need a variable amount of memory.
     
    29182976
    29192977There 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.
     2978The 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.
    29212979After a program is debugged, the non-debugging version can be used to significantly decrease space and increase performance.
    29222980
     
    29262984
    29272985To 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 libdill/libmil~\cite{libdill} (M:1)), and use a shared-memory programming model, \eg not message passing.
     2986For 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.
    29292987The 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.
    29302988
     
    29372995The total time is divided by @N@ to obtain the average time for a benchmark.
    29382996Each 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{CforallBenchMarks}.
     2997All omitted tests for other languages are functionally identical to the \CFA tests and available online~\cite{CforallConcurrentBenchmarks}.
    29402998% 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
     3003Creation is measured by creating and deleting a specific kind of control-flow object.
     3004Figure~\ref{f:creation} shows the code for \CFA with results in Table~\ref{t:creation}.
     3005Note, 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.
    29653006
    29663007\begin{multicols}{2}
    29673008\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 {};
     3011void ?{}( MyCoroutine & this ) {
     3012#ifdef EAGER
     3013        resume( this );
     3014#endif
     3015}
     3016void main( MyCoroutine & ) {}
     3017int main() {
     3018        BENCH( for ( N ) { @MyCoroutine c;@ } )
    29743019        sout | result;
    29753020}
    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}
    29833024
    29843025\columnbreak
    29853026
    29863027\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           \\
     3039Python generator                & 123.2         & 124.3         & 4.1           \\
     3040Node.js generator               & 33.4          & 33.5          & 0.3           \\
     3041Goroutine thread                & 751.0         & 750.5         & 3.1           \\
     3042Rust tokio thread               & 1860.0        & 1881.1        & 37.6          \\
     3043Rust thread                             & 53801.0       & 53896.8       & 274.9         \\
     3044Java thread                             & 120274.0      & 120722.9      & 2356.7        \\
     3045Pthreads thread                 & 31465.5       & 31419.5       & 140.4
    30043046\end{tabular}
    30053047\end{multicols}
    30063048
     3049\vspace*{-10pt}
    30073050\paragraph{Internal Scheduling}
    30083051
     
    30103053Figure~\ref{f:schedint} shows the code for \CFA, with results in Table~\ref{t:schedint}.
    30113054Note, 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.
     3055Java 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.
    30133056
    30143057\begin{multicols}{2}
     
    30363079}
    30373080\end{cfa}
     3081\vspace*{-8pt}
    30383082\captionof{figure}{\CFA Internal-scheduling benchmark}
    30393083\label{f:schedint}
     
    31043148\paragraph{Mutual-Exclusion}
    31053149
    3106 Uncontented mutual exclusion, which frequently occurs, is measured by entering/leaving a critical section.
    3107 For monitors, entering and leaving a monitor function is measured, otherwise the language-appropriate mutex-lock is measured.
     3150Uncontented mutual exclusion, which frequently occurs, is measured by entering and leaving a critical section.
     3151For monitors, entering and leaving a mutex function is measured, otherwise the language-appropriate mutex-lock is measured.
    31083152For comparison, a spinning (versus blocking) test-and-test-set lock is presented.
    31093153Figure~\ref{f:mutex} shows the code for \CFA with results in Table~\ref{t:mutex}.
     
    31423186\end{multicols}
    31433187
    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
     3190In 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.)
     3192Similarly, when modularization extends to coroutines and threads, the time for a context switch becomes a relevant factor.
     3193The 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.
     3195For 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@).
     3196The thread test is using yield to enter and return from the runtime kernel, which is two context switches.
     3197The difference in performance between coroutine and thread context-switch is the cost of scheduling for threads, whereas coroutines are self-scheduling.
     3198Figure~\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.
    31493211
    31503212\begin{multicols}{2}
    31513213\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 {};
     3216void main( C & ) { for () { @suspend;@ } }
     3217int main() { // coroutine test
     3218        C c;
     3219        BENCH( for ( N ) { @resume( c );@ } )
    31623220        sout | result;
    31633221}
    3164 \end{cfa}
    3165 \captionof{figure}{\CFA creation benchmark}
    3166 \label{f:creation}
     3222int 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}
    31673229
    31683230\columnbreak
    31693231
    31703232\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} \\
     3237C 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   \\
     3243Python generator        & 40.9          & 41.3          & 1.5   \\
     3244Node.js await           & 1852.2        & 1854.7        & 16.4  \\
     3245Node.js generator       & 33.3          & 33.4          & 0.3   \\
     3246Goroutine thread        & 143.0         & 143.3         & 1.1   \\
     3247Rust async await        & 32.0          & 32.0          & 0.0   \\
     3248Rust tokio thread       & 143.0         & 143.0         & 1.7   \\
     3249Rust thread                     & 332.0         & 331.4         & 2.4   \\
     3250Java thread                     & 405.0         & 415.0         & 17.6  \\
     3251Pthreads thread         & 334.3         & 335.2         & 3.9
    31883252\end{tabular}
    31893253\end{multicols}
     
    31923256\subsection{Discussion}
    31933257
    3194 Languages using 1:1 threading based on pthreads can at best meet or exceed (due to language overhead) the pthread results.
     3258Languages using 1:1 threading based on pthreads can at best meet or exceed, due to language overhead, the pthread results.
    31953259Note, pthreads has a fast zero-contention mutex lock checked in user space.
    31963260Languages with M:N threading have better performance than 1:1 because there is no operating-system interactions.
     
    32003264
    32013265
    3202 \section{Conclusion}
     3266\section{Conclusions and Future Work}
    32033267
    32043268Advanced control-flow will always be difficult, especially when there is temporal ordering and nondeterminism.
     
    32073271Combining these properties creates a number of high-level, efficient, and maintainable control-flow types: generator, coroutine, thread, each of which can be a monitor.
    32083272Eliminated 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@.
    32103274Extending these mechanisms to handle high-level deadlock-free bulk acquire across both mutual exclusion and synchronization is a unique contribution.
    32113275The \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.
    32123276The M:N model is judged to be efficient and provide greater flexibility than a 1:1 threading model.
    32133277These 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.
     3278Performance 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.
    32153279C 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.
    32163280
    3217 
    3218 \section{Future Work}
    3219 
    32203281While control flow in \CFA has a strong start, development is still underway to complete a number of missing features.
    32213282
    3222 \paragraph{Flexible Scheduling}
    3223 \label{futur:sched}
    3224 
     3283\medskip
     3284\textbf{Flexible Scheduling:}
    32253285An important part of concurrency is scheduling.
    3226 Different scheduling algorithms can affect performance (both in terms of average and variation).
     3286Different scheduling algorithms can affect performance, both in terms of average and variation.
    32273287However, no single scheduler is optimal for all workloads and therefore there is value in being able to change the scheduler for given programs.
    32283288One solution is to offer various tuning options, allowing the scheduler to be adjusted to the requirements of the workload.
     
    32303290Currently, 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}.
    32313291
    3232 \paragraph{Non-Blocking I/O}
    3233 \label{futur:nbio}
    3234 
     3292\smallskip
     3293\textbf{Non-Blocking I/O:}
    32353294Many modern workloads are not bound by computation but IO operations, common cases being web servers and XaaS~\cite{XaaS} (anything as a service).
    32363295These types of workloads require significant engineering to amortizing costs of blocking IO-operations.
     
    32413300A non-blocking I/O library is currently under development for \CFA.
    32423301
    3243 \paragraph{Other Concurrency Tools}
    3244 \label{futur:tools}
    3245 
     3302\smallskip
     3303\textbf{Other Concurrency Tools:}
    32463304While monitors offer flexible and powerful concurrency for \CFA, other concurrency tools are also necessary for a complete multi-paradigm concurrency package.
    32473305Examples of such tools can include futures and promises~\cite{promises}, executors and actors.
     
    32493307As well, new \CFA extensions should make it possible to create a uniform interface for virtually all mutual exclusion, including monitors and low-level locks.
    32503308
    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:}
     3311Basic \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.
    32553312This type of concurrency can be achieved both at the language level and at the library level.
    32563313The 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.
     3314The \CFA language features should make it possible to develop a reasonable number of implicit concurrency mechanisms to solve basic HPC data-concurrency problems.
    32583315However, implicit concurrency is a restrictive solution with significant limitations, so it can never replace explicit concurrent programming.
    32593316
  • doc/papers/concurrency/figures/RunTimeStructure.fig

    r07d867b r22f94a4  
    88-2
    991200 2
    10 6 3855 2775 4155 2925
    11 1 3 0 1 0 0 0 0 0 0.000 1 0.0000 3930 2850 30 30 3930 2850 3960 2880
    12 1 3 0 1 0 0 0 0 0 0.000 1 0.0000 4035 2850 30 30 4035 2850 4065 2880
     106 3255 2475 3555 2625
     111 3 0 1 0 0 0 0 0 0.000 1 0.0000 3330 2550 30 30 3330 2550 3360 2580
     121 3 0 1 0 0 0 0 0 0.000 1 0.0000 3435 2550 30 30 3435 2550 3465 2580
    1313-6
    14 6 4755 3525 5055 3675
    15 1 3 0 1 0 0 0 0 0 0.000 1 0.0000 4830 3600 30 30 4830 3600 4860 3630
    16 1 3 0 1 0 0 0 0 0 0.000 1 0.0000 4935 3600 30 30 4935 3600 4965 3630
     146 4155 3225 4455 3375
     151 3 0 1 0 0 0 0 0 0.000 1 0.0000 4230 3300 30 30 4230 3300 4260 3330
     161 3 0 1 0 0 0 0 0 0.000 1 0.0000 4335 3300 30 30 4335 3300 4365 3330
    1717-6
    18 6 4650 2775 4950 2925
    19 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 4725 2850 15 15 4725 2850 4740 2865
    20 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 4800 2850 15 15 4800 2850 4815 2865
    21 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 4875 2850 15 15 4875 2850 4890 2865
     186 4050 2475 4350 2625
     191 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 4125 2550 15 15 4125 2550 4140 2565
     201 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 4200 2550 15 15 4200 2550 4215 2565
     211 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 4275 2550 15 15 4275 2550 4290 2565
    2222-6
    23 6 3225 2400 3525 2550
    24 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 3300 2475 15 15 3300 2475 3315 2490
    25 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 3375 2475 15 15 3375 2475 3390 2490
    26 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 3450 2475 15 15 3450 2475 3465 2490
     236 2625 2100 2925 2250
     241 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 2700 2175 15 15 2700 2175 2715 2190
     251 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 2775 2175 15 15 2775 2175 2790 2190
     261 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 2850 2175 15 15 2850 2175 2865 2190
    2727-6
    28 6 5475 3450 5625 3750
    29 1 3 0 1 -1 -1 0 0 20 0.000 1 4.7120 5550 3525 15 15 5550 3525 5535 3540
    30 1 3 0 1 -1 -1 0 0 20 0.000 1 4.7120 5550 3600 15 15 5550 3600 5535 3615
    31 1 3 0 1 -1 -1 0 0 20 0.000 1 4.7120 5550 3675 15 15 5550 3675 5535 3690
     286 4875 3150 5025 3450
     291 3 0 1 -1 -1 0 0 20 0.000 1 4.7120 4950 3225 15 15 4950 3225 4935 3240
     301 3 0 1 -1 -1 0 0 20 0.000 1 4.7120 4950 3300 15 15 4950 3300 4935 3315
     311 3 0 1 -1 -1 0 0 20 0.000 1 4.7120 4950 3375 15 15 4950 3375 4935 3390
    3232-6
    33 6 4275 3525 4575 3675
    34 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 4350 3600 15 15 4350 3600 4365 3615
    35 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 4425 3600 15 15 4425 3600 4440 3615
    36 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 4500 3600 15 15 4500 3600 4515 3615
     336 3675 3225 3975 3375
     341 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 3750 3300 15 15 3750 3300 3765 3315
     351 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 3825 3300 15 15 3825 3300 3840 3315
     361 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 3900 3300 15 15 3900 3300 3915 3315
    3737-6
    38 6 3225 4125 4650 4425
    39 6 4350 4200 4650 4350
    40 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 4425 4275 15 15 4425 4275 4440 4290
    41 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 4500 4275 15 15 4500 4275 4515 4290
    42 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 4575 4275 15 15 4575 4275 4590 4290
     386 2625 3825 4050 4125
     396 3750 3900 4050 4050
     401 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 3825 3975 15 15 3825 3975 3840 3990
     411 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 3900 3975 15 15 3900 3975 3915 3990
     421 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 3975 3975 15 15 3975 3975 3990 3990
    4343-6
    44 1 1 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3450 4275 225 150 3450 4275 3675 4425
    45 1 1 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4050 4275 225 150 4050 4275 4275 4425
     441 1 0 1 -1 -1 0 0 -1 0.000 1 0.0000 2850 3975 225 150 2850 3975 3075 4125
     451 1 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3450 3975 225 150 3450 3975 3675 4125
    4646-6
    47 6 6675 4125 7500 4425
    48 6 7200 4200 7500 4350
    49 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 7275 4275 15 15 7275 4275 7290 4290
    50 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 7350 4275 15 15 7350 4275 7365 4290
    51 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 7425 4275 15 15 7425 4275 7440 4290
     476 6075 3825 6900 4125
     486 6600 3900 6900 4050
     491 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 6675 3975 15 15 6675 3975 6690 3990
     501 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 6750 3975 15 15 6750 3975 6765 3990
     511 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 6825 3975 15 15 6825 3975 6840 3990
    5252-6
    53 1 1 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6900 4275 225 150 6900 4275 7125 4425
     531 1 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6300 3975 225 150 6300 3975 6525 4125
    5454-6
    55 6 6675 3525 8025 3975
     556 6075 3225 7425 3675
    56562 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2
    5757        1 1 1.00 45.00 90.00
    58          6675 3750 6975 3750
     58         6075 3450 6375 3450
    59592 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2
    6060        1 1 1.00 45.00 90.00
    61          7125 3750 7350 3750
     61         6525 3450 6750 3450
    62622 2 0 1 -1 -1 0 0 -1 0.000 0 0 0 0 0 5
    63          7800 3975 7800 3525 7350 3525 7350 3975 7800 3975
     63         7200 3675 7200 3225 6750 3225 6750 3675 7200 3675
    64642 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2
    6565        1 1 1.00 45.00 90.00
    66          7800 3750 8025 3750
     66         7200 3450 7425 3450
    6767-6
    68 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 5550 2625 150 150 5550 2625 5700 2625
    69 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 5550 3225 150 150 5550 3225 5700 3225
    70 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 5550 3975 150 150 5550 3975 5700 3975
    71 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3525 2850 150 150 3525 2850 3675 2850
    72 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4200 2475 150 150 4200 2475 4350 2475
    73 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4425 2850 150 150 4425 2850 4575 2850
    74 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4650 2475 150 150 4650 2475 4800 2475
    75 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3975 3600 150 150 3975 3600 4125 3600
    76 1 3 0 1 0 0 0 0 0 0.000 1 0.0000 3525 3600 30 30 3525 3600 3555 3630
    77 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3750 2475 150 150 3750 2475 3900 2625
    78 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4875 3600 150 150 4875 3600 5025 3750
    79 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3975 2850 150 150 3975 2850 4125 2850
    80 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 7200 2775 150 150 7200 2775 7350 2775
    81 1 3 0 1 0 0 0 0 0 0.000 1 0.0000 2250 4830 30 30 2250 4830 2280 4860
    82 1 3 0 1 0 0 0 0 0 0.000 1 0.0000 7200 2775 30 30 7200 2775 7230 2805
    83 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3525 3600 150 150 3525 3600 3675 3600
    84 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3875 4800 100 100 3875 4800 3975 4800
    85 1 1 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4650 4800 150 75 4650 4800 4800 4875
     681 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4950 2325 150 150 4950 2325 5100 2325
     691 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4950 2925 150 150 4950 2925 5100 2925
     701 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4950 3675 150 150 4950 3675 5100 3675
     711 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 2925 2550 150 150 2925 2550 3075 2550
     721 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3600 2175 150 150 3600 2175 3750 2175
     731 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3825 2550 150 150 3825 2550 3975 2550
     741 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4050 2175 150 150 4050 2175 4200 2175
     751 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3375 3300 150 150 3375 3300 3525 3300
     761 3 0 1 0 0 0 0 0 0.000 1 0.0000 2925 3300 30 30 2925 3300 2955 3330
     771 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3150 2175 150 150 3150 2175 3300 2325
     781 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4275 3300 150 150 4275 3300 4425 3450
     791 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3375 2550 150 150 3375 2550 3525 2550
     801 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6600 2475 150 150 6600 2475 6750 2475
     811 3 0 1 0 0 0 0 0 0.000 1 0.0000 1650 4530 30 30 1650 4530 1680 4560
     821 3 0 1 0 0 0 0 0 0.000 1 0.0000 6600 2475 30 30 6600 2475 6630 2505
     831 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 2925 3300 150 150 2925 3300 3075 3300
     841 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3275 4500 100 100 3275 4500 3375 4500
     851 1 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4050 4500 150 75 4050 4500 4200 4575
    86862 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 4200
     87         1800 3900 1800 3450 1350 3450 1350 3900 1800 3900
    88882 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 4500
     89         5700 4200 5700 1500 2400 1500 2400 4200 5700 4200
    90902 2 0 1 -1 -1 0 0 -1 0.000 0 0 0 0 0 5
    91          5775 2850 5775 2400 5325 2400 5325 2850 5775 2850
     91         5175 2550 5175 2100 4725 2100 4725 2550 5175 2550
    92922 2 0 1 -1 -1 0 0 -1 0.000 0 0 0 0 0 5
    93          5775 4200 5775 3750 5325 3750 5325 4200 5775 4200
     93         5175 3900 5175 3450 4725 3450 4725 3900 5175 3900
    94942 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2
    9595        1 1 1.00 45.00 90.00
    96          5175 3975 5325 3975
     96         4575 3675 4725 3675
    97972 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2
    9898        1 1 1.00 45.00 90.00
    99          5175 3225 5325 3225
     99         4575 2925 4725 2925
    1001002 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2
    101101        1 1 1.00 45.00 90.00
    102          5175 2625 5325 2625
     102         4575 2325 4725 2325
    1031032 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2
    104104        1 1 1.00 45.00 90.00
    105          5775 3975 5925 3975
     105         5175 3675 5325 3675
    1061062 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2
    107107        1 1 1.00 45.00 90.00
    108          5775 3225 5925 3225
     108         5175 2925 5325 2925
    1091092 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2
    110110        1 1 1.00 45.00 90.00
    111          5775 2625 5925 2625
     111         5175 2325 5325 2325
    1121122 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
    113          5175 3975 5175 2625
     113         4575 3675 4575 2325
    1141142 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2
    115115        1 1 1.00 45.00 90.00
    116          5925 3975 5925 2025
     116         5325 3675 5325 1725
    1171172 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2
    118118        1 1 1.00 45.00 90.00
    119          5925 3750 6225 3750
     119         5325 3450 5625 3450
    1201202 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2
    121121        1 1 1.00 45.00 90.00
    122          3450 2625 3225 2625
     122         2850 2325 2625 2325
    1231232 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 3
    124124        1 1 1.00 45.00 90.00
    125          5925 2025 4200 2025 4200 2250
     125         5325 1725 3600 1725 3600 1950
    1261262 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
    127          3225 2625 3225 3600
     127         2625 2325 2625 3300
    1281282 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2
    129129        1 1 1.00 45.00 90.00
    130          3075 3600 3375 3600
     130         2475 3300 2775 3300
    1311312 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2
    132132        1 1 1.00 45.00 90.00
    133          3675 3600 3825 3600
     133         3075 3300 3225 3300
    1341342 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2
    135135        1 1 1.00 45.00 90.00
    136          4125 3600 4275 3600
     136         3525 3300 3675 3300
    1371372 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2
    138138        1 1 1.00 45.00 90.00
    139          4575 3600 4725 3600
     139         3975 3300 4125 3300
    1401402 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2
    141141        1 1 1.00 45.00 90.00
    142          5025 3600 5175 3600
     142         4425 3300 4575 3300
    1431432 2 0 1 -1 -1 0 0 -1 0.000 0 0 0 0 0 5
    144          5775 3450 5775 3000 5325 3000 5325 3450 5775 3450
     144         5175 3150 5175 2700 4725 2700 4725 3150 5175 3150
    1451452 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 4500
     146         7500 4200 7500 1500 6000 1500 6000 4200 7500 4200
    1471472 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2
    148148        1 1 1.00 45.00 90.00
    149          7050 2775 6825 2775
     149         6450 2475 6225 2475
    1501502 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
    151          6825 2775 6825 3750
     151         6225 2475 6225 3450
    1521522 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 4
    153153        1 1 1.00 45.00 90.00
    154          7875 3750 7875 2325 7200 2325 7200 2550
     154         7275 3450 7275 2025 6600 2025 6600 2250
    1551552 2 0 1 -1 -1 0 0 -1 0.000 0 0 0 0 0 5
    156          5850 4950 5850 4725 5625 4725 5625 4950 5850 4950
     156         5250 4650 5250 4425 5025 4425 5025 4650 5250 4650
    1571572 2 1 1 -1 -1 0 0 -1 3.000 0 0 0 0 0 5
    158          6975 4950 6750 4950 6750 4725 6975 4725 6975 4950
    159 4 1 -1 0 0 0 10 0.0000 2 105 720 5550 4425 Processors\001
    160 4 1 -1 0 0 0 10 0.0000 2 120 1005 4200 3225 Blocked Tasks\001
    161 4 1 -1 0 0 0 10 0.0000 2 150 870 4200 3975 Ready Tasks\001
    162 4 1 -1 0 0 0 10 0.0000 2 135 1095 7350 1725 Other Cluster(s)\001
    163 4 1 -1 0 0 0 10 0.0000 2 105 840 4650 1725 User Cluster\001
    164 4 1 -1 0 0 0 10 0.0000 2 150 615 2175 3675 Manager\001
    165 4 1 -1 0 0 0 10 0.0000 2 105 990 2175 3525 Discrete-event\001
    166 4 1 -1 0 0 0 10 0.0000 2 135 795 2175 4350 preemption\001
    167 4 0 -1 0 0 0 10 0.0000 2 150 1290 2325 4875 genrator/coroutine\001
    168 4 0 -1 0 0 0 10 0.0000 2 120 270 4050 4875 task\001
    169 4 0 -1 0 0 0 10 0.0000 2 105 450 7050 4875 cluster\001
    170 4 0 -1 0 0 0 10 0.0000 2 105 660 5925 4875 processor\001
    171 4 0 -1 0 0 0 10 0.0000 2 105 555 4875 4875 monitor\001
     158         6375 4650 6150 4650 6150 4425 6375 4425 6375 4650
     1594 1 -1 0 0 0 10 0.0000 2 105 720 4950 4125 Processors\001
     1604 1 -1 0 0 0 10 0.0000 2 120 1005 3600 2925 Blocked Tasks\001
     1614 1 -1 0 0 0 10 0.0000 2 150 870 3600 3675 Ready Tasks\001
     1624 1 -1 0 0 0 10 0.0000 2 135 1095 6750 1425 Other Cluster(s)\001
     1634 1 -1 0 0 0 10 0.0000 2 105 840 4050 1425 User Cluster\001
     1644 1 -1 0 0 0 10 0.0000 2 150 615 1575 3375 Manager\001
     1654 1 -1 0 0 0 10 0.0000 2 105 990 1575 3225 Discrete-event\001
     1664 1 -1 0 0 0 10 0.0000 2 135 795 1575 4050 preemption\001
     1674 0 -1 0 0 0 10 0.0000 2 150 1365 1725 4575 generator/coroutine\001
     1684 0 -1 0 0 0 10 0.0000 2 120 270 3450 4575 task\001
     1694 0 -1 0 0 0 10 0.0000 2 105 450 6450 4575 cluster\001
     1704 0 -1 0 0 0 10 0.0000 2 105 660 5325 4575 processor\001
     1714 0 -1 0 0 0 10 0.0000 2 105 555 4275 4575 monitor\001
  • doc/papers/concurrency/mail2

    r07d867b r22f94a4  
    512512Software: Practice and Experience Editorial Office
    513513
     514
     515
     516Date: Sat, 18 Apr 2020 10:42:13 +0000
     517From: Richard Jones <onbehalfof@manuscriptcentral.com>
     518Reply-To: R.E.Jones@kent.ac.uk
     519To: tdelisle@uwaterloo.ca, pabuhr@uwaterloo.ca
     520Subject: Software: Practice and Experience - Decision on Manuscript ID
     521 SPE-19-0219.R1
     522
     52318-Apr-2020
     524
     525Dear Dr Buhr,
     526
     527Many 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
     529I 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
     531A revised version of your manuscript that takes into account the comments of the referee(s) will be reconsidered for publication.
     532
     533Please 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
     535You 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
     537You 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
     539When 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
     541If 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
     543Once again, thank you for submitting your manuscript to Software: Practice and Experience and I look forward to receiving your revision.
     544
     545Sincerely,
     546Richard
     547
     548Prof. Richard Jones
     549Software: Practice and Experience
     550R.E.Jones@kent.ac.uk
     551
     552
     553Referee(s)' Comments to Author:
     554
     555Reviewing: 1
     556
     557Comments to the Author
     558(A relatively short second review)
     559
     560I thank the authors for their revisions and comprehensive response to
     561reviewers' comments --- many of my comments have been successfully
     562addressed by the revisions.  Here I'll structure my comments around
     563the main salient points in that response which I consider would
     564benefit from further explanation.
     565
     566>  Table 1 is moved to the start and explained in detail.
     567
     568I consider this change makes a significant improvement to the paper,
     569laying out the landscape of language features at the start, and thus
     570addresses my main concerns about the paper.
     571
     572I still have a couple of issues --- perhaps the largest is that it's
     573still not clear at this point in the paper what some of these options
     574are, or crucially how they would be used. I don't know if it's
     575possbile to give high-level examples or use cases to be clear about
     576these up front - or if that would duplicate too much information from
     577later in the paper - either way expanding out the discussion - even if
     578just two a couple of sentences for each row - would help me more.  The
     579point is not just to define these categories but to ensure the
     580readers' understanding of these definitons agrees with that used in
     581the paper.
     582
     583in 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
     621For JITTed languages in particular, reporting peak performance needs
     622to "warm up" the JIT with a number of iterators before beginning
     623measurement. Actually for JIT's its even worse: see Edd Barrett et al
     624OOPSLA 2017.
     625   
     626
     627
     628minor 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
     691My typo: the paper's conclusion should come at the end, after the
     692future work section.
     693
     694
     695
     696
     697To encourage accountability, I'm signing my reviews in 2020.
     698For the record, I am James Noble, kjx@ecs.vuw.ac.nz.
     699
     700
     701Reviewing: 2
     702
     703Comments to the Author
     704I 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
     710I am glad to see that the authors have taken on board most of the straightforward improvements I suggested.
     711
     712However, 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
     718The 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
     720Considering 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
     722Given 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
     724I 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
     726Some smaller points:
     727
     728It 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
     730To 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
     733Reviewing: 3
     734
     735Comments to the Author
     736This is the second round of reviewing.
     737
     738As in the first review, I found that the paper (and Cforall) contains
     739a lot of really interesting ideas, but it remains really difficult to
     740have a good sense of which idea I should use and when. This applies in
     741different 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
     748I requested similar things in my previous review and I see that
     749content was added in response to those requests. Unfortunately, I'm
     750not sure that I can say it improved the paper's overall read. I think
     751in some sense the additions were "too much" -- I would have preferred
     752something more like a table or a few paragraphs highlighting the key
     753reasons one would pick one construct or the other.
     754
     755In general, I do wonder if the paper is just trying to do too much.
     756The discussion of clusters and pre-emption in particular feels quite
     757rushed.
     758
     759## Summary
     760
     761I make a number of suggestions below but the two most important
     762I 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
     772There is obviously a lot of overlap between these features, and in
     773particular between coroutines and generators. As noted in the previous
     774review, many languages have chosen to offer *only* generators, and to
     775build coroutines by stacks of generators invoking one another.
     776
     777I believe the newly introduced Section 2 of the paper is trying to
     778motivate why each of these constructs exist, but I did not find it
     779effective. It was dense and difficult to understand. I think the
     780problem is that Section 2 seems to be trying to derive "from first
     781principles" why each construct exists, but I think that a more "top
     782down" approach would be easier to understand.
     783
     784In fact, the end of Section 2.1 (on page 5) contains a particular
     785paragraph that embodies this "top down" approach. It starts,
     786"programmers can now answer three basic questions", and thus gives
     787some practical advice for which construct you should use and when. I
     788think giving some examples of specific applications that this
     789paragraph, combined with some examples of cases where each construct
     790was needed, would be a better approach.
     791
     792I don't think this compariosn needs to be very long. It seems clear
     793enough 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
     801I did appreciate the comparison in Section 2.3 between async-await in
     802JS/Java and generators/coroutines. I agree with its premise that those
     803mechanisms are a poor replacement for generators (and, indeed, JS has
     804a distinct generator mechanism, for example, in part for this reason).
     805I believe I may have asked for this in a previous review, but having
     806read it, I wonder if it is really necessary, since those mechanisms
     807are so different in purpose.
     808
     809## Internal vs external scheduling
     810
     811I find the motivation for supporting both internal and external
     812scheduling to be fairly implicit. After several reads through the
     813section, I came to the conclusion that internal scheduling is more
     814expressive than external scheduling, but sometimes less convenient or
     815clear. Is this correct? If not, it'd be useful to clarify where
     816external scheduling is more expressive.
     817
     818The same is true, I think, of the `signal_block` function, which I
     819have not encountered before; it seems like its behavior can be modeled
     820with multiple condition variables, but that's clearly more complex.
     821
     822One question I had about `signal_block`: what happens if one signals
     823but no other thread is waiting? Does it block until some other thread
     824waits? Or is that user error?
     825
     826I would find it very interesting to try and capture some of the
     827properties that make internal vs external scheduling the better
     828choice.
     829
     830For example, it seems to me that external scheduling works well if
     831there are only a few "key" operations, but that internal scheduling
     832might be better otherwise, simply because it would be useful to have
     833the ability to name a signal that can be referenced by many
     834methods. Consider the bounded buffer from Figure 13: if it had
     835multiple methods for removing elements, and not just `remove`, then
     836the `waitfor(remove)` call in `insert` might not be sufficient.
     837
     838## Comparison of external scheduling to messaging
     839
     840I did enjoy the section comparing external scheduling to Go's
     841messaging mechanism, which I believe is a new addition.
     842
     843I believe that one difference between the Go program and the Cforall
     844equivalent is that the Goroutine has an associated queue, so that
     845multiple messages could be enqueued, whereas the Cforall equivalent is
     846effectively a "bounded buffer" of length 1. Is that correct? I think
     847this should be stated explicitly. (Presumably, one could modify the
     848Cforall program to include an explicit vector of queued messages if
     849desired, but you would also be reimplementing the channel
     850abstraction.)
     851
     852Also, in Figure 20, I believe that there is a missing `mutex` keyword.
     853The fiugre states:
     854
     855```
     856void main(GoRtn & gortn) with(gortn) {
     857```
     858
     859but I think it should probably be as follows:
     860
     861```
     862void main(GoRtn & mutex gortn) with(gortn) {
     863```
     864
     865Unless there is some implicit `mutex` associated with being a main
     866function for a `monitor thread`.
     867
     868## Atomic operations and race freedom
     869
     870I was glad to see that the paper acknowledged that Cforall still had
     871low-level atomic operations, even if their use is discouraged in favor
     872of higher-level alternatives.
     873
     874However, I still feel that the conclusion overstates the value of the
     875contribution here when it says that "Cforall high-level race-free
     876monitors and threads provide the core mechanisms for mutual exclusion
     877and synchronization, without the need for volatile and atomics". I
     878feel confident that Java programmers, for example, would be advised to
     879stick with synchronized methods whenever possible, and it seems to me
     880that they offer similar advantages -- but they sometimes wind up using
     881volatiles for performance reasons.
     882
     883I was also confused by the term "race-free" in that sentence. In
     884particular, I don't think that Cforall has any mechanisms for
     885preventing *data races*, and it clearly doesn't prevent "race
     886conditions" (which would bar all sorts of useful programs). I suppose
     887that "race free" here might be referring to the improvements such as
     888removing barging behavior.
     889
     890## Performance comparisons
     891
     892In my previous review, I requested comparisons against Rust and
     893node.js, and I see that the new version of the paper includes both,
     894which is a good addition.
     895
     896One note on the Rust results: I believe that the results are comparing
     897against the threads found in Rust's standard library, which are
     898essentially a shallow wrapper around pthreads, and hence the
     899performance is quite close to pthread performance (as one would
     900expect). It would perhaps be more interesting to see a comparison
     901built using [tokio] or [async-std], two of the more prominent
     902user-space threading libraries that build on Rust's async-await
     903feature (which operates quite differently than Javascript's
     904async-await, in that it doesn't cause every aync function call to
     905schedule a distinct task).
     906
     907[tokio]: https://tokio.rs/
     908[async-std]: https://async.rs/
     909
     910That said, I am satisfied with the performance results as they are in
     911the current revision.
     912
     913## Minor notes and typos
     914
     915Several figures used the `with` keyword. I deduced that `with(foo)`
     916permits one to write `bar` instead of `foo.bar`. It seems worth
     917introducing. Apologies if this is stated in the paper, if so I missed
     918it.
     919
     920On page 20, section 6.3, "external scheduling and vice versus" should be
     921"external scheduling and vice versa".
     922
     923On page 5, section 2.3, the paper states "we content" but it should be
     924"we contend".
     925
     926Reviewing: Editor
     927
     928A few small comments in addition to those of the referees.
     929
     930Page 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
     932Page 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
     934Page 18, line 17: is using
     935
     936
     937
     938Date: Tue, 16 Jun 2020 13:45:03 +0000
     939From: Aaron Thomas <onbehalfof@manuscriptcentral.com>
     940Reply-To: speoffice@wiley.com
     941To: tdelisle@uwaterloo.ca, pabuhr@uwaterloo.ca
     942Subject: SPE-19-0219.R2 successfully submitted
     943
     94416-Jun-2020
     945
     946Dear Dr Buhr,
     947
     948Your 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
     950Your manuscript number is SPE-19-0219.R2.  Please mention this number in all future correspondence regarding this submission.
     951
     952You 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
     955Thank you for submitting your manuscript to Software: Practice and Experience.
     956
     957Sincerely,
     958
     959Software: Practice and Experience Editorial Office
     960
  • doc/proposals/vtable.md

    r07d867b r22f94a4  
    237237default is provided or not, the second syntax can be used to pick a
    238238parameter on instantiation.
     239
     240### Extension: Object Access
     241This requires that the resolution scope (see below) is at the type level or
     242has explicate points with names. These are the tables and table names used
     243here.
     244
     245The system already knows where to find the virtual table and the object. If
     246the tables have particular identities, or on the user side names, then it is
     247meaningful to check if a binding virtual table is the same* as another. The
     248main use of this is virtual table declarations also give the type they bind
     249and if a binding table matches a known table then the underlyind object in the
     250trait 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
     255This gives one of the main new features of the hierarchical use of virtual
     256tables (see below); the ability to recover the underlying object. Or a pointer
     257of the approprate type it which both reflects the implementation and gives a
     258convenent way to encode the boolean/conditional aspect of the operation which
     259is that a different virtual table might be in use.
     260
     261There are two general ways to reperent this; a cast or a field access. The
     262cast is traditional and would definitely fit if a single pointer repersents
     263a trait object with the virtual table as part of the object. However for a
     264double pointer field access might be more approprate. By this system though
     265it is not the type that is used as the identifier but the virtual table. If
     266there is one table per type than it becomes equivilant again. Otherwise the
     267table has to be used as the identifier and the type is just a result of that
     268which seems important for syntax.
    239269
    240270Hierarchy
     
    560590be used in only some of the declarations.
    561591
    562     trait combiner fee = (summation_instance, sum);
     592    trait combiner fee = {summation_instance, sum};
    563593    trait combiner foe = summation_instance;
    564594
  • 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
    29
    310#include <array>
     
    3542
    3643template<>
    37 thread_local relaxed_list<Node>::TLS relaxed_list<Node>::tls = {};
     44thread_local LIST_VARIANT<Node>::TLS LIST_VARIANT<Node>::tls = {};
    3845
    3946template<>
    40 relaxed_list<Node> * relaxed_list<Node>::head = nullptr;
     47std::atomic_uint32_t LIST_VARIANT<Node>::ticket = { 0 };
    4148
    4249#ifndef NO_STATS
    4350template<>
    44 relaxed_list<Node>::GlobalStats relaxed_list<Node>::global_stats = {};
     51LIST_VARIANT<Node>::GlobalStats LIST_VARIANT<Node>::global_stats = {};
    4552#endif
    4653
     
    5764        size_t valmax = 0;
    5865        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;
    5974};
    6075
     
    6782        std::atomic_size_t valmax = { 0 };
    6883        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;
    6992};
    7093
     
    96119        global.crc_out += local.crc_out;
    97120
     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
    98126        atomic_max(global.valmax, local.valmax);
    99127        atomic_min(global.valmin, local.valmin);
    100128
    101         relaxed_list<Node>::stats_tls_tally();
     129        LIST_VARIANT<Node>::stats_tls_tally();
    102130}
    103131
     
    106134        auto before = Clock::now();
    107135        barrier.wait(0);
     136        bool is_tty = isatty(STDOUT_FILENO);
    108137
    109138        while(true) {
     
    115144                        break;
    116145                }
    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                }
    119150        }
    120151
     
    159190        auto dur_nano = duration_cast<std::nano>(1.0);
    160191
     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        }
    161202        std::cout << "Duration      : " << duration << "s\n";
    162203        std::cout << "ns/Op         : " << ( dur_nano / ops_thread )<< "\n";
     
    164205        std::cout << "Ops/sec       : " << ops_sec << "\n";
    165206        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         }
    170207        #ifndef NO_STATS
    171                 relaxed_list<Node>::stats_print(std::cout);
     208                LIST_VARIANT<Node>::stats_print(std::cout);
    172209        #endif
    173210}
     
    186223        unsigned nslots,
    187224        local_stat_t & local,
    188         relaxed_list<Node> & list
     225        LIST_VARIANT<Node> & list
    189226) {
    190227        while(__builtin_expect(!done.load(std::memory_order_relaxed), true)) {
     
    224261        std::cout << "Initializing ";
    225262        size_t npushed = 0;
    226         relaxed_list<Node> list = { nthread * nqueues };
     263        LIST_VARIANT<Node> list = { nthread, nqueues };
    227264        {
    228265                Node** all_nodes[nthread];
     
    310347        unsigned nnodes,
    311348        local_stat_t & local,
    312         relaxed_list<Node> & list
     349        LIST_VARIANT<Node> & list
    313350) {
    314351        Node * nodes[nnodes];
     
    354391        std::cout << "Initializing ";
    355392        // List being tested
    356         relaxed_list<Node> list = { nthread * nqueues };
     393        LIST_VARIANT<Node> list = { nthread, nqueues };
    357394        {
    358395                enable_stats = true;
     
    395432
    396433                enable_stats = false;
     434        }
     435
     436        print_stats(duration, nthread, global);
     437}
     438
     439// ================================================================================================
     440struct __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
     508void 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;
    397587        }
    398588
     
    410600        unsigned nnodes,
    411601        local_stat_t & local,
    412         relaxed_list<Node> & list
     602        LIST_VARIANT<Node> & list
    413603) {
    414604        Node * nodes[nnodes];
     
    470660
    471661        // List being tested
    472         relaxed_list<Node> list = { nthread * nqueues };
     662        LIST_VARIANT<Node> list = { nthread, nqueues };
    473663        {
    474664                enable_stats = true;
     
    521711        print_stats(duration, nthread, global);
    522712
    523         save_fairness(data_out.get(), 100, nthread, width, length, output);
     713        // save_fairness(data_out.get(), 100, nthread, width, length, output);
    524714}
    525715
     
    547737                Churn,
    548738                PingPong,
     739                Producer,
    549740                Fairness,
    550741                NONE
     
    577768                                case PingPong:
    578769                                        nnodes = 1;
    579                                         nslots = 1;
    580770                                        switch(argc - optind) {
    581771                                        case 0: break;
     
    591781                                                break;
    592782                                        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;
    594803                                                goto usage;
    595804                                        }
     
    662871                                        break;
    663872                                }
     873                                if(iequals(arg, "producer")) {
     874                                        benchmark = Producer;
     875                                        break;
     876                                }
    664877                                if(iequals(arg, "fairness")) {
    665878                                        benchmark = Fairness;
     
    702915                                std::cerr << "Usage: " << argv[0] << ": [options] -b churn [NNODES] [NSLOTS = NNODES]" << std::endl;
    703916                                std::cerr << "  or:  " << argv[0] << ": [options] -b pingpong [NNODES]" << std::endl;
     917                                std::cerr << "  or:  " << argv[0] << ": [options] -b producer [NNODES]" << std::endl;
    704918                                std::cerr << std::endl;
    705919                                std::cerr << "  -d, --duration=DURATION  Duration of the experiment, in seconds" << std::endl;
     
    714928
    715929        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;
    716931        switch(benchmark) {
    717932                case Churn:
     
    720935                case PingPong:
    721936                        runPingPong(nthreads, nqueues, duration, nnodes);
     937                        break;
     938                case Producer:
     939                        runProducer(nthreads, nqueues, duration, nnodes);
    722940                        break;
    723941                case Fairness:
     
    8011019}
    8021020
    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>
    8311049
    8321050/*
  • doc/theses/thierry_delisle_PhD/code/relaxed_list.hpp

    r07d867b r22f94a4  
    11#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
    216
    317#ifndef NO_STATS
     
    519#endif
    620
     21#include <cmath>
     22#include <functional>
    723#include <memory>
    824#include <mutex>
     25#include <thread>
    926#include <type_traits>
    1027
    1128#include "assert.hpp"
    1229#include "utils.hpp"
     30#include "links.hpp"
     31#include "snzi.hpp"
     32#include "snzi-packed.hpp"
     33#include "snzm.hpp"
    1334
    1435using 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;
    7236
    7337struct pick_stat {
     
    7539                size_t attempt = 0;
    7640                size_t success = 0;
     41                size_t local = 0;
    7742        } push;
    7843        struct {
     
    8045                size_t success = 0;
    8146                size_t mask_attempt = 0;
     47                size_t mask_reset = 0;
     48                size_t local = 0;
    8249        } pop;
    8350};
     
    9562
    9663template<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>
    10464class __attribute__((aligned(128))) relaxed_list {
    10565        static_assert(std::is_same<decltype(node_t::_links), _LinksFields_t<node_t>>::value, "Node must have a links field");
    10666
    10767public:
    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
    11196        {
    11297                assertf(7 * 8 * 8 >= numLists, "List currently only supports 448 sublists");
    113                 // assert(sizeof(*this) == 128);
    11498                std::cout << "Constructing Relaxed List with " << numLists << std::endl;
    115 
    116                 #ifndef NO_STATS
    117                         if(head) this->next = head;
    118                         head = this;
    119                 #endif
    12099        }
    121100
     
    130109                while(true) {
    131110                        // Pick a random list
    132                         unsigned i = tls.rng.next() % numLists;
     111                        unsigned i = idx_from_r(tls.rng1.next(), VARIANT == BIAS || VARIANT == BACKBIAS);
    133112
    134113                        #ifndef NO_STATS
     
    139118                        if( !lists[i].lock.try_lock() ) continue;
    140119
    141                         __attribute__((unused)) int num = numNonEmpty;
     120                        #if VARIANT == VANILLA || VARIANT == BITMASK
     121                                __attribute__((unused)) int num = numNonEmpty;
     122                        #endif
    142123
    143124                        // Actually push it
    144125                        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
    154154
    155155                        // Unlock and return
     
    158158                        #ifndef NO_STATS
    159159                                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
    162164                        #endif
    163165                        return;
     
    166168
    167169        __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
    176301                        int nnempty;
    177302                        while(0 != (nnempty = numNonEmpty)) {
    178303                                tls.pick.pop.mask_attempt++;
    179304                                unsigned i, j;
    180                                 // if( numLists < 4 || (numLists / nnempty) < 4 ) {
    181                                 //      // Pick two lists at random
    182                                 //      i = tls.rng.next() % numLists;
    183                                 //      j = tls.rng.next() % numLists;
    184                                 // } else
    185305                                {
    186                                         #ifndef NO_STATS
    187                                                 // tls.pick.push.mask_attempt++;
    188                                         #endif
    189 
    190306                                        // Pick two lists at random
    191307                                        unsigned num = ((numLists - 1) >> 6) + 1;
    192308
    193                                         unsigned ri = tls.rng.next();
    194                                         unsigned rj = tls.rng.next();
     309                                        unsigned ri = tls.rng1.next();
     310                                        unsigned rj = tls.rng1.next();
    195311
    196312                                        unsigned wdxi = (ri >> 6u) % num;
     
    220336                        while(numNonEmpty != 0) {
    221337                                // 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;
    224340
    225341                                if(auto node = try_pop(i, j)) return node;
     
    234350                #ifndef NO_STATS
    235351                        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);
    236357                #endif
    237358
     
    249370                if( !list.lock.try_lock() ) return nullptr;
    250371
    251                 __attribute__((unused)) int num = numNonEmpty;
     372                #if VARIANT == VANILLA || VARIANT == BITMASK
     373                        __attribute__((unused)) int num = numNonEmpty;
     374                #endif
    252375
    253376                // If list is empty, unlock and retry
     
    264387
    265388                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
    273410                }
    274411
    275412                // Unlock and return
    276413                list.lock.unlock();
    277                 assert(numNonEmpty >= 0);
     414                #if VARIANT == VANILLA || VARIANT == BITMASK
     415                        assert(numNonEmpty >= 0);
     416                #endif
    278417                #ifndef NO_STATS
    279418                        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
    282423                #endif
    283424                return node;
    284425        }
    285426
    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;
    331438                }
    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        }
    412441
    413442public:
    414443
    415444        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;
    417448                pick_stat  pick;
    418449                empty_stat empty;
     450                __attribute__((aligned(64))) std::atomic_size_t mask = { 0 };
    419451        } tls;
    420452
     453private:
     454        const unsigned numLists;
     455        __attribute__((aligned(64))) std::unique_ptr<intrusive_queue_t<node_t> []> lists;
     456private:
     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
    421474public:
    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;
    430477
    431478#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 
    440479        static void stats_tls_tally() {
    441480                global_stats.pick.push.attempt += tls.pick.push.attempt;
    442481                global_stats.pick.push.success += tls.pick.push.success;
     482                global_stats.pick.push.local += tls.pick.push.local;
    443483                global_stats.pick.pop .attempt += tls.pick.pop.attempt;
    444484                global_stats.pick.pop .success += tls.pick.pop.success;
    445485                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;
    446488
    447489                global_stats.qstat.push.value += tls.empty.push.value;
     
    457499                                std::atomic_size_t attempt = { 0 };
    458500                                std::atomic_size_t success = { 0 };
     501                                std::atomic_size_t local = { 0 };
    459502                        } push;
    460503                        struct {
     
    462505                                std::atomic_size_t success = { 0 };
    463506                                std::atomic_size_t mask_attempt = { 0 };
     507                                std::atomic_size_t mask_reset = { 0 };
     508                                std::atomic_size_t local = { 0 };
    464509                        } pop;
    465510                } pick;
     
    476521        } global_stats;
    477522
    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 ) {
     523public:
     524        static void stats_print(std::ostream & os ) {
    484525                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                 }
    500526
    501527                const auto & global = global_stats;
     
    504530                double pop_sur  = (100.0 * double(global.pick.pop .success) / global.pick.pop .attempt);
    505531                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";
    510543
    511544                double avgQ_push = double(global.qstat.push.value) / global.qstat.push.count;
     
    515548                os << "Pop    Avg Qs : " << avgQ_pop  << " (" << global.qstat.pop .count << "ops)\n";
    516549                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";
    517553        }
    518554#endif
  • doc/theses/thierry_delisle_PhD/code/utils.hpp

    r07d867b r22f94a4  
    3535};
    3636
     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
     54constexpr uint64_t extendedEuclidY(uint64_t a, uint64_t b);
     55constexpr uint64_t extendedEuclidX(uint64_t a, uint64_t b){
     56    return (b==0) ? 1 : extendedEuclidY(b, a - b * (a / b));
     57}
     58constexpr 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
    3762class Random {
    3863private:
    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
    4071public:
    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);
     77public:
     78        Random(unsigned int seed) {
     79                this->x = seed * a;
    4380        }
    4481
    4582        /** returns pseudorandom x satisfying 0 <= x < n. **/
    4683        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        }
    52102};
    53103
     
    106156}
    107157
     158static inline unsigned rand_bit(unsigned rnum, size_t mask) __attribute__((artificial));
    108159static inline unsigned rand_bit(unsigned rnum, size_t mask) {
    109160        unsigned bit = mask ? rnum % __builtin_popcountl(mask) : 0;
     
    143194#endif
    144195}
     196
     197struct 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
     220static 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
     236static 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  
    1010// Created On       : Fri Aug 26 14:23:51 2005
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Oct 20 08:14:33 2019
    13 // Update Count     : 385
     12// Last Modified On : Sat May 30 18:09:05 2020
     13// Update Count     : 404
    1414//
    1515
     
    3838static string o_file;
    3939static string bprefix;
     40static string lang;                                                                             // -x flag
    4041
    4142
     
    7374                        if ( prefix( val, "-compiler=" ) ) {
    7475                                compiler_path = val.substr( 10 );
     76                        } else if ( prefix( val, "-x=" ) ) {
     77                                lang = val.substr( 3 );
    7578                        } // if
    7679                } // if
     
    100103                        } else if ( prefix( val, "-B=" ) ) {            // location of cfa-cpp
    101104                                bprefix = val.substr( 3 );
     105                        } else if ( prefix( val, "-x=" ) ) {            // ignore
    102106                        } else {                                                                        // normal flag for cfa-cpp
    103107                                args[nargs++] = ( *new string( arg.substr( arg.find_first_of( "=" ) + 1 ) ) ).c_str();
     
    247251
    248252                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
    250259                args[nargs++] = cpp_in;
    251260                if ( o_flag ) {                                                                 // location for output
     
    280289
    281290                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
    283297                args[nargs++] = cpp_in;                                                 // input to cpp
    284298                args[nargs] = nullptr;                                                  // terminate argument list
  • driver/cfa.cc

    r07d867b r22f94a4  
    1010// Created On       : Tue Aug 20 13:44:49 2002
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jan 31 16:48:03 2020
    13 // Update Count     : 421
     12// Last Modified On : Sat May 30 18:28:23 2020
     13// Update Count     : 433
    1414//
    1515
     
    185185                                args[nargs++] = argv[i];                                // pass argument along
    186186                                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                                }
    193203
    194204                        } else if ( arg == "-CFA" ) {
     
    243253                                        lang = arg.substr( 2 );
    244254                                } // 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
    246261                        } else if ( prefix( arg, "-std=" ) || prefix( arg, "--std=" ) ) {
    247262                                std_flag = true;                                                // -std=XX provided
     
    302317
    303318        #ifdef __x86_64__
    304         args[nargs++] = "-mcx16";                                                       // allow double-wide CAA
     319        args[nargs++] = "-mcx16";                                                       // allow double-wide CAS
    305320        #endif // __x86_64__
    306321
     
    420435                args[nargs++] = "-Wl,--pop-state";
    421436                args[nargs++] = "-pthread";
     437                #ifdef __x86_64__
     438                args[nargs++] = "-latomic";                                             // allow double-wide CAS
     439                #endif // __x86_64__
    422440                args[nargs++] = "-ldl";
    423441                args[nargs++] = "-lrt";
  • examples/io/cat.c

    r07d867b r22f94a4  
     1/*
     2This is a simple "cat" example that uses io_uring in IORING_SETUP_IOPOLL mode.
     3It demonstrates the bare minimum needed to use io_uring in polling mode.
     4It uses liburing for simplicity.
     5*/
     6
     7
     8#ifndef _GNU_SOURCE
     9#define _GNU_SOURCE
     10#endif
     11
    112#include <fcntl.h>
    213#include <liburing.h>
    314#include <stdio.h>
     15#include <string.h>
    416#include <unistd.h>
    517
    618struct io_uring ring;
     19
     20__attribute__((aligned(1024))) char data[1024];
    721
    822int main(int argc,  char * argv[]) {
     
    1226      }
    1327
    14       int fd = open(argv[1], 0);
     28      int fd = open(argv[1], O_DIRECT);
    1529      if(fd < 0) {
    1630            printf("Could not open file %s.\n", argv[1]);
     
    1933
    2034      /* prep the array */
    21       char data[512];
    22       struct iovec iov = { data, 512 };
     35      struct iovec iov = { data, 1024 };
    2336
    2437      /* init liburing */
    25       io_uring_queue_init(256, &ring, 0);
     38      io_uring_queue_init(256, &ring, IORING_SETUP_IOPOLL);
    2639
    2740      /* declare required structs */
     
    3245      sqe = io_uring_get_sqe(&ring);
    3346      io_uring_prep_readv(sqe, fd, &iov, 1, 0);
     47      // io_uring_prep_read(sqe, fd, data, 1024, 0);
    3448
    35       sqe->user_data = data;
     49      sqe->user_data = (uint64_t)(uintptr_t)data;
    3650
    3751      /* tell the kernel we have an sqe ready for consumption */
     
    4054      /* wait for the sqe to complete */
    4155      int ret = io_uring_wait_cqe(&ring, &cqe);
    42      
     56
    4357      /* read and process cqe event */
    4458      if(ret == 0) {
    45             char * out = cqe->user_data;
     59            char * out = (char *)(uintptr_t)cqe->user_data;
    4660            signed int len = cqe->res;
    4761            io_uring_cqe_seen(&ring, cqe);
     
    4963            if(len > 0) {
    5064                  printf("%.*s", len, out);
     65            }
     66            else if( len < 0 ) {
     67                  fprintf(stderr, "readv/read returned error : %s\n", strerror(-len));
    5168            }
    5269      }
  • examples/io/filereader.c

    r07d867b r22f94a4  
     1/*
     2This is a file reading example that users io_uring in non-blocking mode.
     3It demonstrates the bare minimum needed to use io_uring.
     4It also optionally pre-registers the file descriptors (and a pipe, just to show it works).
     5It uses liburing for simplicity.
     6*/
     7
     8
    19#include <errno.h>
    210#include <fcntl.h>
     
    917
    1018int 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]);
    1821            return EXIT_FAILURE;
    1922      }
    2023
     24        bool fixed = false;
     25        if(argc == 4) {
     26                fixed = 0 == strcmp(argv[3], "fixed");
     27        }
    2128
    2229      int times = atoi( argv[2] );
     
    3239      }
    3340
     41        int rfd = fd;
     42
    3443        /* prep the array */
    3544      char data[100];
     
    4049      io_uring_queue_init(256, &ring, 0);
    4150
     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
    4271      /* declare required structs */
    4372        printf("Reading %s(%d) %d times\n", argv[1], fd, times);
     
    4675                /* get an sqe and fill in a READV operation */
    4776              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                }
    4981
    5082                /* tell the kernel we have an sqe ready for consumption */
     
    83115
    84116      close(fd);
     117
     118        if(fixed) {
     119                close(pipefds[0]);
     120                close(pipefds[1]);
     121        }
    85122}
  • examples/io/simple/server.c

    r07d867b r22f94a4  
     1/*
     2This is a simple server that users io_uring in blocking mode.
     3It demonstrates the bare minimum needed to use io_uring.
     4It uses liburing for simplicity.
     5*/
     6
     7
    18#include <assert.h>
    29#include <stdio.h>
     
    1623char data[256];
    1724struct iovec iov = { data, 256 };
    18 struct msghdr msg = { "", 0, &iov, 1, NULL, 0, 0 };
     25struct msghdr msg = { (void *)"", 0, &iov, 1, NULL, 0, 0 };
    1926static void async_read(int sock) {
    2027        /* get an sqe and fill in a READ operation */
  • libcfa/configure.ac

    r07d867b r22f94a4  
    88AM_SILENT_RULES([yes])
    99
    10 m4_include([../automake/cfa.m4])
     10m4_include([../tools/build/cfa.m4])
    1111
    1212AM_INIT_AUTOMAKE([subdir-objects])
     
    3030        [  --enable-distcc     whether or not to enable distributed compilation],
    3131        enable_distcc=$enableval, enable_distcc=no)
     32
     33AC_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)
    3236
    3337echo -n "checking for distributated build... "
     
    5559AC_SUBST(CFADIR_HASH)
    5660AC_SUBST(CFA_VERSION)
     61AC_SUBST(DIST_BWLIMIT)
    5762
    5863#==============================================================================
     
    100105AM_CONDITIONAL([BUILDLIB], [test "x${CONFIG_BUILDLIB}" = "xyes"])
    101106
     107AM_T='$(T)'
     108AC_SUBST(AM_T)
     109
    102110#==============================================================================
    103111#Trasforming cc1 will break compilation
     
    118126AC_PROG_MAKE_SET
    119127
    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
     134AH_TEMPLATE([CFA_HAVE_LINUX_IO_URING_H],[Defined if io_uring support is present when compiling libcfathread.])
     135AH_TEMPLATE([CFA_HAVE_IORING_OP_NOP],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_NOP.])
     136AH_TEMPLATE([CFA_HAVE_IORING_OP_READV],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_READV.])
     137AH_TEMPLATE([CFA_HAVE_IORING_OP_WRITEV],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_WRITEV.])
     138AH_TEMPLATE([CFA_HAVE_IORING_OP_FSYNC],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_FSYNC.])
     139AH_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.])
     140AH_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.])
     141AH_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.])
     142AH_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.])
     143AH_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.])
     144AH_TEMPLATE([CFA_HAVE_IORING_OP_SENDMSG],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_SENDMSG.])
     145AH_TEMPLATE([CFA_HAVE_IORING_OP_RECVMSG],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_RECVMSG.])
     146AH_TEMPLATE([CFA_HAVE_IORING_OP_TIMEOUT],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_TIMEOUT.])
     147AH_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.])
     148AH_TEMPLATE([CFA_HAVE_IORING_OP_ACCEPT],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_ACCEPT.])
     149AH_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.])
     150AH_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.])
     151AH_TEMPLATE([CFA_HAVE_IORING_OP_CONNECT],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_CONNECT.])
     152AH_TEMPLATE([CFA_HAVE_IORING_OP_FALLOCATE],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_FALLOCATE.])
     153AH_TEMPLATE([CFA_HAVE_IORING_OP_OPENAT],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_OPENAT.])
     154AH_TEMPLATE([CFA_HAVE_IORING_OP_CLOSE],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_CLOSE.])
     155AH_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.])
     156AH_TEMPLATE([CFA_HAVE_IORING_OP_STATX],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_STATX.])
     157AH_TEMPLATE([CFA_HAVE_IORING_OP_READ],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_READ.])
     158AH_TEMPLATE([CFA_HAVE_IORING_OP_WRITE],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_WRITE.])
     159AH_TEMPLATE([CFA_HAVE_IORING_OP_FADVISE],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_FADVISE.])
     160AH_TEMPLATE([CFA_HAVE_IORING_OP_MADVISE],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_MADVISE.])
     161AH_TEMPLATE([CFA_HAVE_IORING_OP_SEND],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_SEND.])
     162AH_TEMPLATE([CFA_HAVE_IORING_OP_RECV],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_RECV.])
     163AH_TEMPLATE([CFA_HAVE_IORING_OP_OPENAT2],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_OPENAT2.])
     164AH_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.])
     165AH_TEMPLATE([CFA_HAVE_IORING_OP_SPLICE],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_SPLICE.])
     166AH_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.])
     167AH_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.])
     168AH_TEMPLATE([CFA_HAVE_IOSQE_FIXED_FILE],[Defined if io_uring support is present when compiling libcfathread and supports the flag FIXED_FILE.])
     169AH_TEMPLATE([CFA_HAVE_IOSQE_IO_DRAIN],[Defined if io_uring support is present when compiling libcfathread and supports the flag IO_DRAIN.])
     170AH_TEMPLATE([CFA_HAVE_IOSQE_ASYNC],[Defined if io_uring support is present when compiling libcfathread and supports the flag ASYNC.])
     171AH_TEMPLATE([CFA_HAVE_IOSQE_IO_LINK],[Defined if io_uring support is present when compiling libcfathread and supports the flag IO_LINK.])
     172AH_TEMPLATE([CFA_HAVE_IOSQE_IO_HARDLINK],[Defined if io_uring support is present when compiling libcfathread and supports the flag IO_HARDLINK.])
     173AH_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.])
     174AH_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.])
     175AH_TEMPLATE([HAVE_PREADV2],[Defined if preadv2 support is present when compiling libcfathread.])
     176AH_TEMPLATE([HAVE_PWRITEV2],[Defined if pwritev2 support is present when compiling libcfathread.])
     177AH_TEMPLATE([__CFA_NO_STATISTICS__],[Defined if libcfathread was compiled without support for statistics.])
     178
     179define(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])
     180define(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
     182define(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
     188AC_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])
    121224AC_CHECK_FUNCS([preadv2 pwritev2])
    122225
  • libcfa/prelude/Makefile.am

    r07d867b r22f94a4  
    7272if ENABLE_DISTCC
    7373distribution: @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@
    7575        @echo "Dummy file to track distribution to remote hosts" > ${@}
    7676
  • libcfa/prelude/builtins.c

    r07d867b r22f94a4  
    1010// Created On       : Fri Jul 21 16:21:03 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Nov 21 16:31:39 2019
    13 // Update Count     : 101
     12// Last Modified On : Mon Jul 13 21:10:02 2020
     13// Update Count     : 109
    1414//
    1515
     
    9595static inline forall( dtype DT ) DT * intptr( uintptr_t addr ) { return (DT *)addr; }
    9696
     97#if defined(__SIZEOF_INT128__)
     98// constructor for 128-bit numbers (all constants are unsigned as +/- are operators)
     99static 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
    97104// exponentiation operator implementation
    98105
  • 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. */
    16185#undef HAVE_LINUX_IO_URING_H
    17186
     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. */
    18191#undef HAVE_PREADV2
     192
     193/* Define to 1 if you have the `pwritev2' function. */
    19194#undef HAVE_PWRITEV2
    20195
     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. */
    21248#undef __CFA_NO_STATISTICS__
  • libcfa/src/Makefile.am

    r07d867b r22f94a4  
    1111## Created On       : Sun May 31 08:54:01 2015
    1212## Last Modified By : Peter A. Buhr
    13 ## Last Modified On : Mon Mar 16 18:07:59 2020
    14 ## Update Count     : 242
     13## Last Modified On : Mon Jun  1 13:35:33 2020
     14## Update Count     : 248
    1515###############################################################################
    1616
     
    1919ACLOCAL_AMFLAGS  = -I automake
    2020
    21 include $(srcdir)/../../src/cfa.make
     21include $(top_srcdir)/../tools/build/cfa.make
    2222
    2323libdir = ${CFA_LIBDIR}
     
    3939#----------------------------------------------------------------------------------------------------------------
    4040if 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.hfa
    42 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.hfa
     41headers_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
    4444
    45 libsrc = startup.cfa interpose.cfa bits/debug.cfa assert.cfa exception.c virtual.c heap.cfa ${headers:.hfa=.cfa}
     45headers = 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
     49libsrc = startup.cfa interpose.cfa bits/debug.cfa assert.cfa exception.c virtual.c ${headers:.hfa=.cfa}
    4650
    4751# 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}
     52thread_headers_nosrc = bits/random.hfa concurrency/invoke.h concurrency/kernel/fwd.hfa
     53
     54thread_headers = concurrency/coroutine.hfa concurrency/thread.hfa concurrency/kernel.hfa \
     55                concurrency/monitor.hfa concurrency/mutex.hfa
     56
     57thread_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}
    5163else
    5264headers =
     
    96108
    97109prelude.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 ${@}
    99111
    100112prelude.lo: prelude.cfa extras.cf gcc-builtins.cf builtins.cf @LOCAL_CFACC@ @CFACPP@
    101113        ${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 ${@}
    103115
    104116#----------------------------------------------------------------------------------------------------------------
  • libcfa/src/bitmanip.hfa

    r07d867b r22f94a4  
    1111// Created On       : Sat Mar 14 18:12:27 2020
    1212// Last Modified By : Peter A. Buhr
    13 // Last Modified On : Sun Apr 19 22:29:58 2020
    14 // Update Count     : 121
     13// Last Modified On : Mon Aug 10 09:21:02 2020
     14// Update Count     : 139
    1515//
    1616
     
    2121// Bits are numbered 1-N.
    2222
    23 //#include <assert.h>
     23#include <assert.h>
    2424
    2525#define __bitsizeof( n ) (sizeof(n) * __CHAR_BIT__)
     
    4848
    4949        // Count all 0 bits.
    50         unsigned int all0s( unsigned char n ) { return __bitsizeof(n) - __builtin_popcount( n ); }
    51         unsigned int all0s( unsigned short int n ) { return __bitsizeof(n) - __builtin_popcount( n ); }
    52         unsigned int all0s( unsigned int n ) { return __bitsizeof(n) - __builtin_popcount( n ); }
    53         unsigned int all0s( unsigned long int n ) { return __bitsizeof(n) - __builtin_popcountl( n ); }
    54         unsigned int all0s( unsigned long long int n ) { return __bitsizeof(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 ); }
    5555
    5656        // Find least significiant zero bit. (ffs)
     
    8989
    9090        // 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; }
    101101
    102102        // 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; }
    104104
    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; }
    106106        unsigned char floor( unsigned char n, unsigned char align ) { return n / align * align; }
    107107        short int floor( short int n, short int align ) { return n / align * align; }
     
    118118
    119119        // 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 ); }
    130130
    131131        // 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 ); }
    133133
    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 ); }
    144159
    145160        // 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 ); *}
    147162} // distribution
    148163
  • libcfa/src/bits/containers.hfa

    r07d867b r22f94a4  
    194194
    195195                int ?!=?( const __queue(T) & this, __attribute__((unused)) zero_t zero ) {
    196                         return this.head != 0;
     196                        return this.head != 1p;
    197197                }
    198198        }
  • libcfa/src/bits/debug.cfa

    r07d867b r22f94a4  
    1010// Created On       : Thu Mar 30 12:30:01 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Feb  4 13:03:16 2020
    13 // Update Count     : 11
     12// Last Modified On : Wed Jun 17 11:07:13 2020
     13// Update Count     : 12
    1414//
    1515
    16 extern "C" {
    1716#include <stdio.h>
    1817#include <stdlib.h>
     
    2120#include <stdarg.h>
    2221#include <unistd.h>
    23 }
    2422
    2523enum { buffer_size = 4096 };
  • libcfa/src/bits/debug.hfa

    r07d867b r22f94a4  
    1515
    1616#pragma once
     17
     18#include <assert.h>
    1719
    1820#ifdef __CFA_DEBUG__
     
    5254                || defined(__CFA_DEBUG_PRINT_IO__) || defined(__CFA_DEBUG_PRINT_IO_CORE__) \
    5355                || 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__)
    5558        #include <stdio.h>
    5659        #include <unistd.h>
  • libcfa/src/bits/defs.hfa

    r07d867b r22f94a4  
    1616#pragma once
    1717
    18 #include <stdbool.h>
    19 #include <stddef.h>
    2018#include <stdint.h>
    2119
  • libcfa/src/bits/locks.hfa

    r07d867b r22f94a4  
    130130                pthread_mutex_init(&lock, &mattr);
    131131
    132                 pthread_cond_init (&cond, 0p);
     132                pthread_cond_init (&cond, (const pthread_condattr_t *)0p);  // workaround trac#208: cast should not be required
    133133                val = 0;
    134134        }
     
    164164
    165165        #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        }
    166221#endif
  • libcfa/src/bits/signal.hfa

    r07d867b r22f94a4  
    1919#include "bits/defs.hfa"
    2020
    21 extern "C" {
    2221#include <errno.h>
    2322#define __USE_GNU
     
    2625#include <stdlib.h>
    2726#include <string.h>
    28 }
    2927
    3028// Short hands for signal context information
  • libcfa/src/concurrency/alarm.cfa

    r07d867b r22f94a4  
    1010// Created On       : Fri Jun 2 11:31:25 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Jan  5 08:41:36 2020
    13 // Update Count     : 69
     12// Last Modified On : Wed Jun 17 16:11:35 2020
     13// Update Count     : 75
    1414//
    1515
    1616#define __cforall_thread__
    1717
    18 extern "C" {
    1918#include <errno.h>
    2019#include <stdio.h>
     20#include <unistd.h>
    2121#include <string.h>
    22 #include <unistd.h>
    2322#include <sys/time.h>
    24 }
    2523
    2624#include "alarm.hfa"
    27 #include "kernel_private.hfa"
     25#include "kernel/fwd.hfa"
    2826#include "preemption.hfa"
    2927
     
    5553}
    5654
    57 void ?{}( alarm_node_t & this, processor   * proc, Time alarm, Duration period ) with( this ) {
     55void ?{}( alarm_node_t & this, processor * proc, Time alarm, Duration period ) with( this ) {
    5856        this.proc = proc;
    5957        this.alarm = alarm;
  • libcfa/src/concurrency/alarm.hfa

    r07d867b r22f94a4  
    2323#include "time.hfa"
    2424
    25 #include <containers/list.hfa>
     25#include "containers/list.hfa"
    2626
    2727struct $thread;
  • libcfa/src/concurrency/coroutine.cfa

    r07d867b r22f94a4  
    1010// Created On       : Mon Nov 28 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Feb  4 12:29:25 2020
    13 // Update Count     : 16
     12// Last Modified On : Tue May 26 22:06:09 2020
     13// Update Count     : 21
    1414//
    1515
     
    1818#include "coroutine.hfa"
    1919
    20 extern "C" {
    2120#include <stddef.h>
    2221#include <malloc.h>
     
    2423#include <string.h>
    2524#include <unistd.h>
    26 // use this define to make unwind.h play nice, definetely a hack
     25#include <sys/mman.h>                                                                   // mprotect
     26extern "C" {
     27// use this define to make unwind.h play nice, definitely a hack
    2728#define HIDE_EXPORTS
    2829#include <unwind.h>
    2930#undef HIDE_EXPORTS
    30 #include <sys/mman.h>
    3131}
    3232
  • libcfa/src/concurrency/invoke.c

    r07d867b r22f94a4  
    146146
    147147#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
    149157        struct FakeStack {
    150158                float fpRegs[16];                       // floating point registers
  • libcfa/src/concurrency/invoke.h

    r07d867b r22f94a4  
    1717#include "bits/defs.hfa"
    1818#include "bits/locks.hfa"
     19#include "kernel/fwd.hfa"
    1920
    2021#ifdef __cforall
     
    2526#ifndef _INVOKE_H_
    2627#define _INVOKE_H_
    27 
    28 #ifdef __ARM_ARCH
    29         // function prototypes are only really used by these macros on ARM
    30         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 #else
    42         #define TL_GET( member ) kernelTLS.member
    43         #define TL_SET( member, value ) kernelTLS.member = value;
    44 #endif
    45 
    46         #ifdef __cforall
    47         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         #endif
    6228
    6329        struct __stack_context_t {
     
    9258        };
    9359
    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 };
    9661
    9762        struct $coroutine {
     
    10671
    10772                // current execution status for coroutine
    108                 enum coroutine_state state;
     73                enum __Coroutine_State state;
    10974
    11075                // first coroutine to resume this one
     
    161126        };
    162127
     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
    163137        struct $thread {
    164138                // Core threading fields
     
    167141
    168142                // 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;
    171146
    172147                //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;
    173155
    174156                // coroutine body used to store context
     
    184166                struct $monitor *  self_mon_p;
    185167
    186                 // pointer to the cluster on which the thread is running
    187                 struct cluster * curr_cluster;
    188 
    189168                // monitors currently held by this thread
    190169                struct __monitor_group_t monitors;
    191 
    192                 // Link lists fields
    193                 // instrusive link field for threads
    194                 struct $thread * next;
    195170
    196171                struct {
     
    202177                        // previous function to park/unpark the thread
    203178                        const char * park_caller;
    204                         enum coroutine_state park_result;
     179                        int park_result;
     180                        enum __Coroutine_State park_state;
    205181                        bool park_stale;
    206182                        const char * unpark_caller;
    207                         enum coroutine_state unpark_result;
     183                        int unpark_result;
     184                        enum __Coroutine_State unpark_state;
    208185                        bool unpark_stale;
    209186                #endif
     
    218195        #ifdef __cforall
    219196        extern "Cforall" {
     197
    220198                static inline $thread *& get_next( $thread & this ) __attribute__((const)) {
    221                         return this.next;
     199                        return this.link.next;
    222200                }
    223201
  • libcfa/src/concurrency/io.cfa

    r07d867b r22f94a4  
    1414//
    1515
    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
    3932        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>
    4634                #include <sys/syscall.h>
    4735
     
    4937        }
    5038
    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(&params, 0, sizeof(params));
    209 
    210                 uint32_t nentries = entries_per_cluster();
    211 
    212                 int fd = syscall(__NR_io_uring_setup, nentries, &params );
    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;
    44489        }
    44590
     
    44792// I/O Polling
    44893//=============================================================================================
    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        }
    453104
    454105        // Process a single completion message from the io_uring
    455106        // 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);
    458117                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 );
    467134
    468135                // Drain the queue
    469136                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;
    471139
    472140                // Nothing was new return 0
    473141                if (head == tail) {
    474                         return 0;
     142                        return [0, to_submit > 0];
    475143                }
    476144
    477145                uint32_t count = tail - head;
     146                /* paranoid */ verify( count != 0 );
    478147                for(i; count) {
    479                         unsigned idx = (head + i) & (*ring.completion_q.mask);
     148                        unsigned idx = (head + i) & mask;
    480149                        struct io_uring_cqe & cqe = ring.completion_q.cqes[idx];
    481150
    482151                        /* paranoid */ verify(&cqe);
    483152
    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                }
    494155
    495156                // Mark to the kernel that the cqe has been seen
    496157                // 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 );
    497159                __atomic_fetch_add( ring.completion_q.head, count, __ATOMIC_RELAXED );
    498160
    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++;
    524180
    525181                                // 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
    580189                        if(reset < 5) {
    581                                 // If we got something, just yield and check again
    582190                                yield();
    583191                        }
     192                        // We didn't get anything baton pass to the slow poller
    584193                        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);
    589195                                reset = 0;
     196
     197                                // block this thread
     198                                __ioctx_prepare_block( this, ev );
     199                                wait( this.sem );
    590200                        }
    591201                }
     
    599209
    600210// 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
    610212//     listed in sq.array are visible by the kernel. For those not listed, the kernel does not
    611213//     offer any assurance that an entry is not being filled by multiple flags. Therefore, we
    612214//     need to write an allocator that allows allocating concurrently.
    613215//
    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 operation
     216// 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
    617219//     needs to arrive to two concensus at the same time:
    618220//     A - The order in which entries are listed in the array: no two threads must pick the
     
    622224//
    623225
    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;
    651434                const uint32_t mask = *ring.submit_q.mask;
    652435
    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        }
    718471#endif
    719 
    720 // Some forward declarations
    721 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 #endif
    731 #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 #endif
    735 
    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 operations
    760 #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                 #else
    765                         __submit_prelude
    766 
    767                         (*sqe){ IORING_OP_READV, fd, iov, iovcnt, offset };
    768 
    769                         __submit_wait
    770                 #endif
    771         }
    772 #endif
    773 
    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                 #else
    779                         __submit_prelude
    780 
    781                         (*sqe){ IORING_OP_WRITEV, fd, iov, iovcnt, offset };
    782 
    783                         __submit_wait
    784                 #endif
    785         }
    786 #endif
    787 
    788 int cfa_fsync(int fd) {
    789         #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_FSYNC)
    790                 return fsync(fd);
    791         #else
    792                 __submit_prelude
    793 
    794                 (*sqe){ IORING_OP_FSYNC, fd };
    795 
    796                 __submit_wait
    797         #endif
    798 }
    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         #else
    804                 __submit_prelude
    805 
    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_wait
    812         #endif
    813 }
    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         #else
    820                 __submit_prelude
    821 
    822                 (*sqe){ IORING_OP_SENDMSG, sockfd, msg, 1, 0 };
    823                 sqe->msg_flags = flags;
    824 
    825                 __submit_wait
    826         #endif
    827 }
    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         #else
    833                 __submit_prelude
    834 
    835                 (*sqe){ IORING_OP_RECVMSG, sockfd, msg, 1, 0 };
    836                 sqe->msg_flags = flags;
    837 
    838                 __submit_wait
    839         #endif
    840 }
    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         #else
    846                 __submit_prelude
    847 
    848                 (*sqe){ IORING_OP_SEND, sockfd };
    849                 sqe->addr = (uint64_t)buf;
    850                 sqe->len = len;
    851                 sqe->msg_flags = flags;
    852 
    853                 __submit_wait
    854         #endif
    855 }
    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         #else
    861                 __submit_prelude
    862 
    863                 (*sqe){ IORING_OP_RECV, sockfd };
    864                 sqe->addr = (uint64_t)buf;
    865                 sqe->len = len;
    866                 sqe->msg_flags = flags;
    867 
    868                 __submit_wait
    869         #endif
    870 }
    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         #else
    876                 __submit_prelude
    877 
    878                 (*sqe){ IORING_OP_ACCEPT, sockfd };
    879                 sqe->addr = addr;
    880                 sqe->addr2 = addrlen;
    881                 sqe->accept_flags = flags;
    882 
    883                 __submit_wait
    884         #endif
    885 }
    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         #else
    891                 __submit_prelude
    892 
    893                 (*sqe){ IORING_OP_CONNECT, sockfd };
    894                 sqe->addr = (uint64_t)addr;
    895                 sqe->off = addrlen;
    896 
    897                 __submit_wait
    898         #endif
    899 }
    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         #else
    905                 __submit_prelude
    906 
    907                 (*sqe){ IORING_OP_FALLOCATE, fd };
    908                 sqe->off = offset;
    909                 sqe->len = length;
    910                 sqe->mode = mode;
    911 
    912                 __submit_wait
    913         #endif
    914 }
    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         #else
    920                 __submit_prelude
    921 
    922                 (*sqe){ IORING_OP_FADVISE, fd };
    923                 sqe->off = (uint64_t)offset;
    924                 sqe->len = length;
    925                 sqe->fadvise_advice = advice;
    926 
    927                 __submit_wait
    928         #endif
    929 }
    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         #else
    935                 __submit_prelude
    936 
    937                 (*sqe){ IORING_OP_MADVISE, 0 };
    938                 sqe->addr = (uint64_t)addr;
    939                 sqe->len = length;
    940                 sqe->fadvise_advice = advice;
    941 
    942                 __submit_wait
    943         #endif
    944 }
    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         #else
    950                 __submit_prelude
    951 
    952                 (*sqe){ IORING_OP_OPENAT, dirfd };
    953                 sqe->addr = (uint64_t)pathname;
    954                 sqe->open_flags = flags;
    955                 sqe->mode = mode;
    956 
    957                 __submit_wait
    958         #endif
    959 }
    960 
    961 int cfa_close(int fd) {
    962         #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_CLOSE)
    963                 return close( fd );
    964         #else
    965                 __submit_prelude
    966 
    967                 (*sqe){ IORING_OP_CLOSE, fd };
    968 
    969                 __submit_wait
    970         #endif
    971 }
    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         #else
    978                 __submit_prelude
    979 
    980                 (*sqe){ IORING_OP_READ, fd, buf, count, 0 };
    981 
    982                 __submit_wait
    983         #endif
    984 }
    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         #else
    990                 __submit_prelude
    991 
    992                 (*sqe){ IORING_OP_WRITE, fd, buf, count, 0 };
    993 
    994                 __submit_wait
    995         #endif
    996 }
    997 
    998 //-----------------------------------------------------------------------------
    999 // Check if a function is asynchronous
    1000 
    1001 // Macro magic to reduce the size of the following switch case
    1002 #define IS_DEFINED_APPLY(f, ...) f(__VA_ARGS__)
    1003 #define IS_DEFINED_SECOND(first, second, ...) second
    1004 #define IS_DEFINED_TEST(expansion) _CFA_IO_FEATURE_##expansion
    1005 #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                 #endif
    1015 
    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                 #endif
    1022 
    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         #endif
    1098 
    1099         return false;
    1100 }
  • libcfa/src/concurrency/iofwd.hfa

    r07d867b r22f94a4  
    1616#pragma once
    1717
    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>
     19extern "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
     41struct cluster;
     42struct io_context;
     43struct io_cancellation;
     44
     45struct iovec;
     46struct msghdr;
     47struct sockaddr;
     48struct statx;
     49
     50extern 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);
     51extern 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);
     52extern int cfa_fsync(int fd, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p);
     53extern 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);
     54extern 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);
     55extern 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);
     56extern 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);
     57extern 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);
     58extern 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);
     59extern 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);
     60extern 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);
     61extern 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);
     62extern 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);
     63extern 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);
     64extern int cfa_close(int fd, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p);
     65extern 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);
     66extern 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);
     67extern 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);
     68extern 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);
     69extern 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);
    3670
    3771//-----------------------------------------------------------------------------
    3872// Check if a function is blocks a only the user thread
    3973bool has_user_level_blocking( fptr_t func );
     74
     75//-----------------------------------------------------------------------------
     76void register_fixed_files( io_context & ctx , int * files, unsigned count );
     77void register_fixed_files( cluster    & cltr, int * files, unsigned count );
  • libcfa/src/concurrency/kernel.cfa

    r07d867b r22f94a4  
    1010// Created On       : Tue Jan 17 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Feb  4 13:03:15 2020
    13 // Update Count     : 58
     12// Last Modified On : Thu Jul  9 06:22:54 2020
     13// Update Count     : 66
    1414//
    1515
     
    1818
    1919//C Includes
    20 #include <stddef.h>
    2120#include <errno.h>
    22 #include <string.h>
    23 extern "C" {
    2421#include <stdio.h>
    25 #include <fenv.h>
    26 #include <sys/resource.h>
    2722#include <signal.h>
    2823#include <unistd.h>
    29 #include <limits.h>                                                                             // PTHREAD_STACK_MIN
    30 #include <sys/mman.h>                                                                   // mprotect
    31 }
    3224
    3325//CFA Includes
    34 #include "time.hfa"
    3526#include "kernel_private.hfa"
    3627#include "preemption.hfa"
    37 #include "startup.hfa"
    3828
    3929//Private includes
     
    4535// Some assembly required
    4636#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 
    5537        // mxcr : SSE Status and Control bits (control bits are preserved across function calls)
    5638        // fcw  : X87 FPU control word (preserved across function calls)
     
    7456
    7557#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 
    8458        #define __x87_store         \
    8559                uint32_t __mxcr;      \
     
    10276
    10377#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) )
    10878#else
    10979        #error unknown hardware architecture
    11080#endif
    11181
    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 ) ));
     82extern $thread * mainThread;
     83extern processor * mainProcessor;
    11684
    11785//-----------------------------------------------------------------------------
    11886// Kernel Scheduling logic
    11987static $thread * __next_thread(cluster * this);
     88static $thread * __next_thread_slow(cluster * this);
    12089static 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 }
     90static void __wake_one(struct __processor_id_t * id, cluster * cltr);
     91
     92static void push  (__cluster_idles & idles, processor & proc);
     93static void remove(__cluster_idles & idles, processor & proc);
     94static [unsigned idle, unsigned total, * processor] query( & __cluster_idles idles );
     95
    28296
    28397//=============================================================================================
     
    294108
    295109        __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
    298115
    299116        {
     
    304121
    305122                $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() {
    307125                        // Try to get the next thread
    308126                        readyThread = __next_thread( this->cltr );
    309127
    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 );
    314130                        }
    315131
    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;
    326177                        }
     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;
    327186                }
    328187
     
    330189        }
    331190
    332         unregister(this->cltr, this);
    333 
    334191        V( this->terminated );
    335192
     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
    336200        __cfadbg_print_safe(runtime_core, "Kernel : core %p terminated\n", this);
    337 
    338         // HACK : the coroutine context switch expects this_thread to be set
    339         // and it make sense for it to be set in all other cases except here
    340         // fake it
    341         if( this == mainProcessor ) kernelTLS.this_thread = mainThread;
    342201}
    343202
     
    349208// from the processor coroutine to the target thread
    350209static 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
    351215        $coroutine * proc_cor = get_coroutine(this->runner);
    352216
     
    360224        // Actually run the thread
    361225        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;
    369228
    370229                __cfaabi_dbg_debug_do(
     
    374233
    375234                /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     235                /* paranoid */ verify( kernelTLS.this_thread == thrd_dst );
    376236                /* 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
    377237                /* 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
     
    384244                /* 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 );
    385245                /* 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 );
    386247                /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    387248
     
    396257                if(unlikely(thrd_dst->preempted != __NO_PREEMPTION)) {
    397258                        // The thread was preempted, reschedule it and reset the flag
    398                         __schedule_thread( thrd_dst );
     259                        __schedule_thread( (__processor_id_t*)this, thrd_dst );
    399260                        break RUNNING;
    400261                }
    401262
     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
    402274                // 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:
    416279                                // This is case 1, the regular case, nothing more is needed
    417280                                break RUNNING;
    418                         case Rerun:
     281                        case 2:
    419282                                // This is case 2, the racy case, someone tried to run this thread before it finished blocking
    420283                                // In this case, just run it again.
     
    422285                        default:
    423286                                // 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();
    425288                }
    426289        }
     
    429292        proc_cor->state = Active;
    430293        kernelTLS.this_thread = 0p;
     294
     295        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    431296}
    432297
     
    436301        $coroutine * proc_cor = get_coroutine(kernelTLS.this_processor->runner);
    437302        $thread * thrd_src = kernelTLS.this_thread;
     303
     304        #if !defined(__CFA_NO_STATISTICS__)
     305                struct processor * last_proc = kernelTLS.this_processor;
     306        #endif
    438307
    439308        // Run the thread on this processor
     
    451320        }
    452321
     322        #if !defined(__CFA_NO_STATISTICS__)
     323                if(last_proc != kernelTLS.this_processor) {
     324                        __tls_stats()->ready.threads.migration++;
     325                }
     326        #endif
     327
    453328        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    454329        /* 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 );
    455330        /* 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_ONLY
    459 // Context invoker for processors
    460 // This is the entry point for processors (kernel threads)
    461 // It effectively constructs a coroutine by stealing the pthread stack
    462 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 coroutine
    468         // which is needed for the 2-step context switch. However, there is no reason
    469         // 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 state
    478         kernelTLS.this_thread = 0p;
    479 
    480         //We now have a proper context from which to schedule threads
    481         __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't
    484         // resume it to start it like it normally would, it will just context switch
    485         // back to here. Instead directly call the main since we already are on the
    486         // 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 terminated
    492         __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 values
    499                 abort( "%s : internal error, error(%d) %s.", func, ret, strerror( ret ) );
    500         } // if
    501 } // Abort
    502 
    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 attribute
    507 
    508         size_t stacksize;
    509         // default stack size, normally defined by shell limit
    510         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                 } // if
    520         );
    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_ONLY
    532 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 correct
    548         /* paranoid */ verify(src->state == Ready);
    549 
    550         // context switch to specified coroutine
    551         verify( dst->context.SP );
    552         __cfactx_switch( &src->context, &dst->context );
    553         // when __cfactx_switch returns we are back in the src coroutine
    554 
    555         mainThread->curr_cor = &mainThread->self_cor;
    556 
    557         // make sure the current state has been update
    558         /* paranoid */ verify(src->state == Active);
    559 
    560         verify( ! kernelTLS.preemption_state.enabled );
    561 }
    562 
    563 // KERNEL_ONLY
    564 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 the
    573         // 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 the
    575         // coroutine semantics. Since this is a special case, use the current context
    576         // 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 processor
    585         __cfactx_switch( &src->context, &dst->context );
    586331}
    587332
     
    589334// Scheduler routines
    590335// KERNEL ONLY
    591 void __schedule_thread( $thread * thrd ) with( *thrd->curr_cluster ) {
     336void __schedule_thread( struct __processor_id_t * id, $thread * thrd ) {
     337        /* paranoid */ verify( thrd );
     338        /* paranoid */ verify( thrd->state != Halted );
    592339        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    593340        /* 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 );
    598345        /* 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 );
    600347
    601348        if (thrd->preempted == __NO_PREEMPTION) thrd->state = Ready;
    602349
    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 );
    609354
    610355        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     
    612357
    613358// 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;
     359static 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
     371static 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;
    623380}
    624381
    625382// 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 
     383void __unpark(  struct __processor_id_t * id, $thread * thrd __cfaabi_dbg_ctx_param2 ) {
    629384        // record activity
    630385        __cfaabi_dbg_record_thrd( *thrd, false, caller );
    631386
    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:
    636391                        // Wake won the race, the thread will reschedule/rerun itself
    637392                        break;
    638                 case Blocked:
     393                case 0:
    639394                        /* paranoid */ verify( ! thrd->preempted != __NO_PREEMPTION );
     395                        /* paranoid */ verify( thrd->state == Blocked );
    640396
    641397                        // Wake lost the race,
    642                         thrd->state = Blocked;
    643                         __schedule_thread( thrd );
     398                        __schedule_thread( id, thrd );
    644399                        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:
    651400                default:
    652401                        // This makes no sense, something is wrong abort
     
    659408
    660409        disable_interrupts();
    661         __unpark( thrd __cfaabi_dbg_ctx_fwd2 );
     410        __unpark( (__processor_id_t*)kernelTLS.this_processor, thrd __cfaabi_dbg_ctx_fwd2 );
    662411        enable_interrupts( __cfaabi_dbg_ctx );
    663412}
     
    694443
    695444        $thread * thrd = kernelTLS.this_thread;
    696         /* paranoid */ verify(thrd->state == Active || thrd->state == Rerun);
     445        /* paranoid */ verify(thrd->state == Active);
    697446
    698447        // SKULLDUGGERY: It is possible that we are preempting this thread just before
     
    701450        // If that is the case, abandon the preemption.
    702451        bool preempted = false;
    703         if(thrd->next == 0p) {
     452        if(thrd->link.next == 0p) {
    704453                preempted = true;
    705454                thrd->preempted = reason;
     
    715464
    716465//=============================================================================================
    717 // Kernel Setup logic
    718 //=============================================================================================
    719 //-----------------------------------------------------------------------------
    720 // Kernel boot procedures
    721 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 cluster
    731         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 thread
    737         // SKULLDUGGERY: the mainThread steals the process main thread
    738         // which will then be scheduled by the mainProcessor normally
    739         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 processor
    749         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 ctx
    769         // (the coroutine that contains the processing control flow)
    770         mainProcessor = (processor *)&storage_mainProcessor;
    771         (*mainProcessor){};
    772 
    773         //initialize the global state variables
    774         kernelTLS.this_processor = mainProcessor;
    775         kernelTLS.this_thread    = mainThread;
    776 
    777         // Enable preemption
    778         kernel_start_preemption();
    779 
    780         // Add the main thread to the ready queue
    781         // once resume is called on mainProcessor->runner the mainThread needs to be scheduled like any normal thread
    782         __schedule_thread(mainThread);
    783 
    784         // SKULLDUGGERY: Force a context switch to the main processor to set the main thread's context to the current UNIX
    785         // context. Hence, the main thread does not begin through __cfactx_invoke_thread, like all other threads. The trick here is that
    786         // 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 RUNNING
    791 
    792 
    793         // Now that the system is up, finish creating systems that need threading
    794         __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 shutdown
    806         __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 mainThread
    816         // which is currently here
    817         __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 STOPPED
    822 
    823         // Disable preemption
    824         kernel_stop_preemption();
    825 
    826         // Destroy the main processor and its context in reverse order of construction
    827         // These were manually constructed so we need manually destroy them
    828         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 needed
    835         // Since we provided a stack to this taxk it will not destroy anything
    836         /* 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 //=============================================================================================
    848466// Kernel Idle Sleep
    849467//=============================================================================================
    850 static $thread * __halt(processor * this) with( *this ) {
    851         if( do_terminate ) return 0p;
    852 
    853         // First, lock the cluster idle
    854         lock( cltr->idle_lock __cfaabi_dbg_ctx2 );
    855 
    856         // Check if we can find a thread
    857         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 list
    863         move_to_front(cltr->procs, cltr->idles, *this);
    864 
    865         // Unlock the idle lock so we don't go to sleep with a lock
    866         unlock    (cltr->idle_lock);
    867 
    868         // We are ready to sleep
    869         __cfadbg_print_safe(runtime_core, "Kernel : Processor %p ready to sleep\n", this);
    870         wait( idle );
    871 
    872         // We have woken up
    873         __cfadbg_print_safe(runtime_core, "Kernel : Processor %p woke up and ready to run\n", this);
    874 
    875         // Get ourself off the idle list
    876         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 thread
    883         return 0p;
    884 }
    885 
    886468// 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;
     469static 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;
    909493}
    910494
    911495// Unconditionnaly wake a thread
    912 static bool __wake_proc(processor * this) {
     496void __wake_proc(processor * this) {
    913497        __cfadbg_print_safe(runtime_core, "Kernel : waking Processor %p\n", this);
    914498
     
    917501                bool ret = post( this->idle );
    918502        enable_interrupts( __cfaabi_dbg_ctx );
    919 
    920         return ret;
     503}
     504
     505static 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
     516static 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
     527static [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        }
    921537}
    922538
     
    952568
    953569void kernel_abort_msg( void * kernel_data, char * abort_text, int abort_text_size ) {
    954         $thread * thrd = kernel_data;
     570        $thread * thrd = ( $thread * ) kernel_data;
    955571
    956572        if(thrd) {
     
    1050666
    1051667//-----------------------------------------------------------------------------
    1052 // Global Queues
    1053 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 //-----------------------------------------------------------------------------
    1094668// Debug
    1095669__cfaabi_dbg_debug_do(
     
    1118692        return true;
    1119693}
     694
     695//-----------------------------------------------------------------------------
     696// Statistics
     697#if !defined(__CFA_NO_STATISTICS__)
     698        void print_halts( processor & this ) {
     699                this.print_halts = true;
     700        }
     701#endif
    1120702// Local Variables: //
    1121703// mode: c //
  • libcfa/src/concurrency/kernel.hfa

    r07d867b r22f94a4  
    1616#pragma once
    1717
    18 #include <stdbool.h>
    19 #include <stdint.h>
    20 
    2118#include "invoke.h"
    2219#include "time_t.hfa"
    2320#include "coroutine.hfa"
    2421
     22#include "containers/list.hfa"
     23
    2524extern "C" {
    26 #include <pthread.h>
    27 #include <semaphore.h>
     25#include <bits/pthreadtypes.h>
    2826}
    2927
     
    4745extern struct cluster * mainCluster;
    4846
    49 // Processor
     47// Processor id, required for scheduling threads
     48struct __processor_id_t {
     49        unsigned id;
     50
     51        #if !defined(__CFA_NO_STATISTICS__)
     52                struct __stats_t * stats;
     53        #endif
     54};
     55
    5056coroutine processorCtx_t {
    5157        struct processor * proc;
     
    5359
    5460// Wrapper around kernel threads
    55 struct processor {
     61struct __attribute__((aligned(128))) processor {
    5662        // 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
    5771        // Coroutine ctx who does keeps the state of the processor
    5872        struct processorCtx_t runner;
    59 
    60         // Cluster from which to get threads
    61         struct cluster * cltr;
    6273
    6374        // Name of the processor
     
    8192        __bin_sem_t idle;
    8293
    83         // Termination
    84         // Set to true to notify the processor should terminate
    85         volatile bool do_terminate;
    86 
    8794        // Termination synchronisation (user semaphore)
    8895        semaphore terminated;
     
    9299
    93100        // 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
    98107
    99108#ifdef __CFA_DEBUG__
     
    110119static inline void  ?{}(processor & this, const char name[]) { this{name, *mainCluster }; }
    111120
    112 static inline [processor *&, processor *& ] __get( processor & this ) __attribute__((const)) { return this.node.[next, prev]; }
     121DLISTED_MGD_IMPL_OUT(processor)
    113122
    114123//-----------------------------------------------------------------------------
     
    116125struct __io_data;
    117126
    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
     130struct $io_ctx_thread {
     131        struct __io_data * ring;
     132        single_sem sem;
     133        volatile bool done;
     134        $thread self;
     135};
     136
     137
     138struct io_context {
     139        $io_ctx_thread thrd;
     140};
     141
     142struct 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
     152void  ?{}(io_context_params & this);
     153
     154void  ?{}(io_context & this, struct cluster & cl);
     155void  ?{}(io_context & this, struct cluster & cl, const io_context_params & params);
     156void ^?{}(io_context & this);
     157
     158struct io_cancellation {
     159        uint32_t target;
     160};
     161
     162static inline void  ?{}(io_cancellation & this) { this.target = -1u; }
     163static inline void ^?{}(io_cancellation & this) {}
     164bool cancel(io_cancellation & this);
     165
     166//-----------------------------------------------------------------------------
     167// Cluster Tools
     168
     169// Intrusives lanes which are used by the relaxed ready queue
     170struct __attribute__((aligned(128))) __intrusive_lane_t;
     171void  ?{}(__intrusive_lane_t & this);
     172void ^?{}(__intrusive_lane_t & this);
     173
     174// Counter used for wether or not the lanes are all empty
     175struct __attribute__((aligned(128))) __snzi_node_t;
     176struct __snzi_t {
     177        unsigned mask;
     178        int root;
     179        __snzi_node_t * nodes;
     180};
     181
     182void  ?{}( __snzi_t & this, unsigned depth );
     183void ^?{}( __snzi_t & this );
     184
     185//TODO adjust cache size to ARCHITECTURE
     186// Structure holding the relaxed ready queue
     187struct __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
     205void  ?{}(__ready_queue_t & this);
     206void ^?{}(__ready_queue_t & this);
     207
     208// Idle Sleep
     209struct __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};
    120222
    121223//-----------------------------------------------------------------------------
    122224// Cluster
    123 struct cluster {
    124         // Ready queue locks
    125         __spinlock_t ready_queue_lock;
    126 
     225struct __attribute__((aligned(128))) cluster {
    127226        // Ready queue for threads
    128         __queue_t($thread) ready_queue;
     227        __ready_queue_t ready_queue;
    129228
    130229        // Name of the cluster
     
    134233        Duration preemption_rate;
    135234
    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;
    141237
    142238        // List of threads
     
    151247        } node;
    152248
    153         struct __io_data * io;
     249        struct {
     250                io_context * ctxs;
     251                unsigned cnt;
     252        } io;
    154253
    155254        #if !defined(__CFA_NO_STATISTICS__)
    156                 bool print_stats;
     255                struct __stats_t * stats;
     256                int print_stats;
    157257        #endif
    158258};
    159259extern Duration default_preemption();
    160260
    161 void ?{} (cluster & this, const char name[], Duration preemption_rate, int flags);
     261void ?{} (cluster & this, const char name[], Duration preemption_rate, unsigned num_io, const io_context_params & io_params);
    162262void ^?{}(cluster & this);
    163263
    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}; }
     264static inline void ?{} (cluster & this)                                            { io_context_params default_params;    this{"Anonymous Cluster", default_preemption(), 1, default_params}; }
     265static inline void ?{} (cluster & this, Duration preemption_rate)                  { io_context_params default_params;    this{"Anonymous Cluster", preemption_rate, 1, default_params}; }
     266static inline void ?{} (cluster & this, const char name[])                         { io_context_params default_params;    this{name, default_preemption(), 1, default_params}; }
     267static inline void ?{} (cluster & this, unsigned num_io)                           { io_context_params default_params;    this{"Anonymous Cluster", default_preemption(), num_io, default_params}; }
     268static inline void ?{} (cluster & this, Duration preemption_rate, unsigned num_io) { io_context_params default_params;    this{"Anonymous Cluster", preemption_rate, num_io, default_params}; }
     269static inline void ?{} (cluster & this, const char name[], unsigned num_io)        { io_context_params default_params;    this{name, default_preemption(), num_io, default_params}; }
     270static inline void ?{} (cluster & this, const io_context_params & io_params)                                            { this{"Anonymous Cluster", default_preemption(), 1, io_params}; }
     271static inline void ?{} (cluster & this, Duration preemption_rate, const io_context_params & io_params)                  { this{"Anonymous Cluster", preemption_rate, 1, io_params}; }
     272static inline void ?{} (cluster & this, const char name[], const io_context_params & io_params)                         { this{name, default_preemption(), 1, io_params}; }
     273static inline void ?{} (cluster & this, unsigned num_io, const io_context_params & io_params)                           { this{"Anonymous Cluster", default_preemption(), num_io, io_params}; }
     274static 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}; }
     275static inline void ?{} (cluster & this, const char name[], unsigned num_io, const io_context_params & io_params)        { this{name, default_preemption(), num_io, io_params}; }
    170276
    171277static inline [cluster *&, cluster *& ] __get( cluster & this ) __attribute__((const)) { return this.node.[next, prev]; }
     
    175281
    176282#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;
    179285        }
     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 );
    180292#endif
    181293
  • libcfa/src/concurrency/kernel_private.hfa

    r07d867b r22f94a4  
    2020
    2121#include "alarm.hfa"
    22 
     22#include "stats.hfa"
    2323
    2424//-----------------------------------------------------------------------------
    2525// Scheduler
     26
     27struct __attribute__((aligned(128))) __scheduler_lock_id_t;
    2628
    2729extern "C" {
     
    3133}
    3234
    33 void __schedule_thread( $thread * ) __attribute__((nonnull (1)));
     35void __schedule_thread( struct __processor_id_t *, $thread * )
     36#if defined(NDEBUG) || (!defined(__CFA_DEBUG__) && !defined(__CFA_VERIFY__))
     37        __attribute__((nonnull (2)))
     38#endif
     39;
    3440
    3541//Block current thread and release/wake-up the following resources
     
    4349
    4450
    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" )));
    6051
    6152extern cluster * mainCluster;
     
    7364
    7465// 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 );
     66void __unpark( struct __processor_id_t *, $thread * thrd __cfaabi_dbg_ctx_param2 );
     67
     68static 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}
    8385
    8486//-----------------------------------------------------------------------------
    8587// 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 
    9988void doregister( struct cluster * cltr, struct $thread & thrd );
    10089void unregister( struct cluster * cltr, struct $thread & thrd );
    10190
    102 void doregister( struct cluster * cltr, struct processor * proc );
    103 void unregister( struct cluster * cltr, struct processor * proc );
     91//-----------------------------------------------------------------------------
     92// I/O
     93void ^?{}(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
     100struct __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
     114static_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
     118unsigned doregister( struct __processor_id_t * proc );
     119
     120// Unregister a processor from a given cluster using its id, getting back the original pointer
     121void     unregister( struct __processor_id_t * proc );
     122
     123//-----------------------------------------------------------------------
     124// Cluster idle lock/unlock
     125static 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
     136static 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
     149static 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
     158static inline bool __atomic_try_acquire(volatile bool * ll) {
     159        return !__atomic_exchange_n(ll, (bool)true, __ATOMIC_SEQ_CST);
     160}
     161
     162// Release
     163static 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
     173struct __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
     191void  ?{}(__scheduler_RWLock_t & this);
     192void ^?{}(__scheduler_RWLock_t & this);
     193
     194extern __scheduler_RWLock_t * __scheduler_lock;
     195
     196//-----------------------------------------------------------------------
     197// Reader side : acquire when using the ready queue to schedule but not
     198//  creating/destroying queues
     199static 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
     223static 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.
     249uint_fast32_t ready_mutate_lock( void );
     250
     251void 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
     280bool remove_head(struct cluster * cltr, struct $thread * thrd);
     281
     282//-----------------------------------------------------------------------
     283// Increase the width of the ready queue (number of lanes) by 4
     284void ready_queue_grow  (struct cluster * cltr, int target);
     285
     286//-----------------------------------------------------------------------
     287// Decrease the width of the ready queue (number of lanes) by 4
     288void ready_queue_shrink(struct cluster * cltr, int target);
     289
    104290
    105291// Local Variables: //
  • libcfa/src/concurrency/monitor.cfa

    r07d867b r22f94a4  
    114114
    115115                // Some one else has the monitor, wait in line for it
    116                 /* paranoid */ verify( thrd->next == 0p );
     116                /* paranoid */ verify( thrd->link.next == 0p );
    117117                append( this->entry_queue, thrd );
    118                 /* paranoid */ verify( thrd->next == 1p );
     118                /* paranoid */ verify( thrd->link.next == 1p );
    119119
    120120                unlock( this->lock );
     
    199199
    200200                // Some one else has the monitor, wait in line for it
    201                 /* paranoid */ verify( thrd->next == 0p );
     201                /* paranoid */ verify( thrd->link.next == 0p );
    202202                append( this->entry_queue, thrd );
    203                 /* paranoid */ verify( thrd->next == 1p );
     203                /* paranoid */ verify( thrd->link.next == 1p );
    204204                unlock( this->lock );
    205205
     
    761761        $thread * new_owner = pop_head( this->entry_queue );
    762762        /* 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 );
    764764        __set_owner( this, new_owner );
    765765
     
    883883        }
    884884
    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 );
    886886        return ready2run ? node->waiting_thread : 0p;
    887887}
     
    907907        // For each thread in the entry-queue
    908908        for(    $thread ** thrd_it = &entry_queue.head;
    909                 *thrd_it != 1p;
    910                 thrd_it = &(*thrd_it)->next
     909                (*thrd_it) != 1p;
     910                thrd_it = &(*thrd_it)->link.next
    911911        ) {
    912912                // For each acceptable check if it matches
  • libcfa/src/concurrency/mutex.cfa

    r07d867b r22f94a4  
    3030        this.lock{};
    3131        this.blocked_threads{};
     32        this.is_locked = false;
    3233}
    3334
  • libcfa/src/concurrency/preemption.cfa

    r07d867b r22f94a4  
    1010// Created On       : Mon Jun 5 14:20:42 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Dec  5 16:34:05 2019
    13 // Update Count     : 43
     12// Last Modified On : Wed Jun 17 11:36:25 2020
     13// Update Count     : 46
    1414//
    1515
     
    1919#include <assert.h>
    2020
    21 extern "C" {
    2221#include <errno.h>
    2322#include <stdio.h>
     
    2524#include <unistd.h>
    2625#include <limits.h>                                                                             // PTHREAD_STACK_MIN
    27 }
    2826
    2927#include "bits/signal.hfa"
     28#include "kernel_private.hfa"
    3029
    3130#if !defined(__CFA_DEFAULT_PREEMPTION__)
     
    3938// FwdDeclarations : timeout handlers
    4039static void preempt( processor   * this );
    41 static void timeout( $thread * this );
     40static void timeout( struct __processor_id_t * id, $thread * this );
    4241
    4342// FwdDeclarations : Signal handlers
     
    9089
    9190// Tick one frame of the Discrete Event Simulation for alarms
    92 static void tick_preemption() {
     91static void tick_preemption( struct __processor_id_t * id ) {
    9392        alarm_node_t * node = 0p;                                                       // Used in the while loop but cannot be declared in the while condition
    9493        alarm_list_t * alarms = &event_kernel->alarms;          // Local copy for ease of reading
     
    108107                }
    109108                else {
    110                         timeout( node->thrd );
     109                        timeout( id, node->thrd );
    111110                }
    112111
     
    121120        // If there are still alarms pending, reset the timer
    122121        if( & (*alarms)`first ) {
    123                 __cfaabi_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);
    124123                Duration delta = (*alarms)`first.alarm - currtime;
    125124                Duration capped = max(delta, 50`us);
     
    188187        void enable_interrupts( __cfaabi_dbg_ctx_param ) {
    189188                processor   * proc = kernelTLS.this_processor; // Cache the processor now since interrupts can start happening after the atomic store
     189                /* paranoid */ verify( proc );
    190190
    191191                with( kernelTLS.preemption_state ){
     
    268268
    269269// reserved for future use
    270 static void timeout( $thread * this ) {
    271         __unpark( this __cfaabi_dbg_ctx2 );
     270static 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 );
    272275}
    273276
     
    291294// Startup routine to activate preemption
    292295// Called from kernel_startup
    293 void kernel_start_preemption() {
     296void __kernel_alarm_startup() {
    294297        __cfaabi_dbg_print_safe( "Kernel : Starting preemption\n" );
    295298
     
    313316// Shutdown routine to deactivate preemption
    314317// Called from kernel_shutdown
    315 void kernel_stop_preemption() {
     318void __kernel_alarm_shutdown() {
    316319        __cfaabi_dbg_print_safe( "Kernel : Preemption stopping\n" );
    317320
     
    405408// Waits on SIGALRM and send SIGUSR1 to whom ever needs it
    406409static void * alarm_loop( __attribute__((unused)) void * args ) {
     410        __processor_id_t id;
     411        id.id = doregister(&id);
     412
    407413        // Block sigalrms to control when they arrive
    408414        sigset_t mask;
     
    449455                        // __cfaabi_dbg_print_safe( "Kernel : Preemption thread tick\n" );
    450456                        lock( event_kernel->lock __cfaabi_dbg_ctx2 );
    451                         tick_preemption();
     457                        tick_preemption( &id );
    452458                        unlock( event_kernel->lock );
    453459                        break;
     
    462468EXIT:
    463469        __cfaabi_dbg_print_safe( "Kernel : Preemption thread stopping\n" );
     470        unregister(&id);
    464471        return 0p;
    465472}
     
    475482        sigset_t oldset;
    476483        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
    478485        if(ret != 0) { abort("ERROR sigprocmask returned %d", ret); }
    479486
  • libcfa/src/concurrency/preemption.hfa

    r07d867b r22f94a4  
    1616#pragma once
    1717
     18#include "bits/locks.hfa"
    1819#include "alarm.hfa"
    19 #include "kernel_private.hfa"
    2020
    21 void kernel_start_preemption();
    22 void kernel_stop_preemption();
     21struct event_kernel_t {
     22        alarm_list_t alarms;
     23        __spinlock_t lock;
     24};
     25
     26extern event_kernel_t * event_kernel;
     27
    2328void update_preemption( processor * this, Duration duration );
    2429
  • libcfa/src/concurrency/thread.cfa

    r07d867b r22f94a4  
    2828        context{ 0p, 0p };
    2929        self_cor{ name, storage, storageSize };
     30        ticket = 1;
    3031        state = Start;
    3132        preempted = __NO_PREEMPTION;
     
    3536        self_mon_p = &self_mon;
    3637        curr_cluster = &cl;
    37         next = 0p;
     38        link.next = 0p;
     39        link.prev = 0p;
     40        link.preferred = -1;
    3841
    3942        node.next = 0p;
     
    6164        verify( this_thrd->context.SP );
    6265
    63         __schedule_thread(this_thrd);
     66        __schedule_thread( (__processor_id_t *)kernelTLS.this_processor, this_thrd);
    6467        enable_interrupts( __cfaabi_dbg_ctx );
    6568}
  • libcfa/src/concurrency/thread.hfa

    r07d867b r22f94a4  
    8484
    8585//-----------------------------------------------------------------------------
    86 // Thread getters
    87 static inline struct $thread * active_thread () { return TL_GET( this_thread ); }
    88 
    89 //-----------------------------------------------------------------------------
    9086// Scheduler API
    9187
     
    106102bool force_yield( enum __Preemption_Reason );
    107103
    108 static inline void yield() {
    109         force_yield(__MANUAL_PREEMPTION);
    110 }
    111 
    112 // Yield: yield N times
    113 static inline void yield( unsigned times ) {
    114         for( times ) {
    115                 yield();
    116         }
    117 }
    118 
    119104//----------
    120105// sleep: force thread to block and be rescheduled after Duration duration
  • libcfa/src/containers/list.hfa

    r07d867b r22f94a4  
    1414//
    1515
     16#pragma once
     17
    1618#include <assert.h>
    1719
     
    2224\
    2325static inline NODE& $tempcv_e2n(ELEM &node) { \
    24         return node; \
     26        return ( NODE & ) node; \
    2527} \
    2628\
     
    118120        Telem& $tempcv_n2e(Tnode &);
    119121        Tnode& $tempcv_e2n(Telem &);
     122
     123        Telem& ?`next(Tnode &);
     124        Telem& ?`prev(Tnode &);
    120125};
    121126
     
    184189                $next_link(singleton_to_insert) = $next_link(list_pos);
    185190                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;
    187192                        $dlinks(Telem) *list_links = & list->$links;
    188193                        $mgd_link(Telem) *list_last = & list_links->prev;
     
    207212                $prev_link(singleton_to_insert) = $prev_link(list_pos);
    208213                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;
    210215                        $dlinks(Telem) *list_links = & list->$links;
    211216                        $mgd_link(Telem) *list_first = & list_links->next;
     
    272277
    273278                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;
    275280                        $dlinks(Telem) * links_before = & tgt_before->$links;
    276281                        &incoming_from_prev = & links_before->next;
     
    282287
    283288                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;
    285290                        $dlinks(Telem) * links_after = & tgt_after->$links;
    286291                        &incoming_from_next = & links_after->prev;
     
    301306                $prev_link(list_pos) = (Telem*) 0p;
    302307        }
     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
    303345}
    304346
  • libcfa/src/containers/vector.hfa

    r07d867b r22f94a4  
    1010// Created On       : Tue Jul  5 18:00:07 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 10:01:18 2017
    13 // Update Count     : 3
     12// Last Modified On : Wed Jun 17 11:02:46 2020
     13// Update Count     : 4
    1414//
    1515
    1616#pragma once
    1717
    18 extern "C" {
    1918#include <stdbool.h>
    20 }
    2119
    2220//------------------------------------------------------------------------------
  • libcfa/src/exception.c

    r07d867b r22f94a4  
    1010// Created On       : Mon Jun 26 15:13:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Apr 14 12:01:00 2020
    13 // Update Count     : 18
     12// Last Modified On : Thr May 21 12:18:00 2020
     13// Update Count     : 20
    1414//
    1515
     
    8080}
    8181
    82 void __cfaehm_throw_resume(exception_t * except) {
     82void __cfaehm_throw_resume(exception_t * except, void (*defaultHandler)(exception_t *)) {
    8383        struct exception_context_t * context = this_exception_context();
    8484
    8585        __cfadbg_print_safe(exception, "Throwing resumption exception\n");
    8686
    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                        }
    9597                }
    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.
    98101        __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);
    103103}
    104104
     
    121121
    122122
    123 // TERMINATION ===============================================================
    124 
    125 // MEMORY MANAGEMENT (still for integers)
    126 // May have to move to cfa for constructors and destructors (references).
     123// MEMORY MANAGEMENT =========================================================
    127124
    128125// How to clean up an exception in various situations.
     
    203200}
    204201
    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 ==============================================================
    209203
    210204// Function needed by force unwind
     
    228222}
    229223
     224// Cancel the current stack, prefroming approprate clean-up and messaging.
     225void __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.
     237void __cfaehm_cleanup_terminate( void * except ) {
     238        if ( *(void**)except ) __cfaehm_delete_exception( *(exception_t **)except );
     239}
     240
     241static void __cfaehm_cleanup_default( exception_t ** except ) {
     242        __cfaehm_delete_exception( *except );
     243        *except = NULL;
     244}
     245
    230246// 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 ) {
     247static 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 ) {
    233251                printf("UNWIND ERROR missing exception in begin unwind\n");
    234252                abort();
     
    236254
    237255        // 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 );
    239258
    240259        // If we reach here it means something happened. For resumption to work we need to find a way
     
    245264        // the whole stack.
    246265
    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);
    254269                abort();
    255270        }
    256271
    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
     280void __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
     287static __attribute__((noreturn)) void __cfaehm_rethrow_adapter( exception_t * except ) {
     288        // TODO: Print some error message.
     289        (void)except;
    259290        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();
    267291}
    268292
     
    270294        __cfadbg_print_safe(exception, "Rethrowing termination exception\n");
    271295
    272         __cfaehm_begin_unwind();
     296        __cfaehm_begin_unwind( __cfaehm_rethrow_adapter );
     297        abort();
    273298}
    274299
  • libcfa/src/exception.h

    r07d867b r22f94a4  
    1010// Created On       : Mon Jun 26 15:11:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Mar 27 10:16:00 2020
    13 // Update Count     : 9
     12// Last Modified On : Tue May 19 14:17:00 2020
     13// Update Count     : 10
    1414//
    1515
     
    3838
    3939
     40void __cfaehm_cancel_stack(exception_t * except) __attribute__((noreturn));
     41
    4042// Used in throw statement translation.
    41 void __cfaehm_throw_terminate(exception_t * except) __attribute__((noreturn));
     43void __cfaehm_throw_terminate(exception_t * except, void (*)(exception_t *));
    4244void __cfaehm_rethrow_terminate() __attribute__((noreturn));
    43 void __cfaehm_throw_resume(exception_t * except);
     45void __cfaehm_throw_resume(exception_t * except, void (*)(exception_t *));
    4446
    4547// Function catches termination exceptions.
     
    7072#ifdef __cforall
    7173}
     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
     78trait 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
     86trait is_termination_exception(dtype T | is_exception(T)) {
     87        void defaultTerminationHandler(T &);
     88};
     89
     90trait is_resumption_exception(dtype T | is_exception(T)) {
     91        void defaultResumptionHandler(T &);
     92};
     93
     94forall(dtype T | is_termination_exception(T))
     95static inline void $throw(T & except) {
     96        __cfaehm_throw_terminate(
     97                (exception_t *)&except,
     98                (void(*)(exception_t *))defaultTerminationHandler
     99        );
     100}
     101
     102forall(dtype T | is_resumption_exception(T))
     103static inline void $throwResume(T & except) {
     104        __cfaehm_throw_resume(
     105                (exception_t *)&except,
     106                (void(*)(exception_t *))defaultResumptionHandler
     107        );
     108}
     109
     110forall(dtype T | is_exception(T))
     111static inline void cancel_stack(T & except) __attribute__((noreturn)) {
     112        __cfaehm_cancel_stack( (exception_t *)&except );
     113}
     114
     115forall(dtype T | is_exception(T))
     116static inline void defaultTerminationHandler(T & except) {
     117        return cancel_stack( except );
     118}
     119
     120forall(dtype T | is_exception(T))
     121static inline void defaultResumptionHandler(T & except) {
     122        throw except;
     123}
     124
    72125#endif
  • libcfa/src/exception.hfa

    r07d867b r22f94a4  
    1010// Created On       : Thu Apr  7 10:25:00 2020
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Thu Apr  7 10:25:00 2020
    13 // Update Count     : 0
     12// Last Modified On : Tue Aug  4 16:22:00 2020
     13// Update Count     : 3
    1414//
    1515
     
    1818// -----------------------------------------------------------------------------------------------
    1919
    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);
    2721// Declare a trivial exception, one that adds no fields or features.
    2822// 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);
    3127// Create the trival exception. This must be used exactly once and should be used in a .cfa file,
    3228// 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
    3431// TRIVIAL_EXCEPTION(exception_name[, parent_name]);
    3532// Does both of the above, a short hand if the exception is only used in one .cfa file.
     
    3734// base exception. This feature may be removed or changed.
    3835#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, ...) \
    42136        _VTABLE_DECLARATION(exception_name, parent_name)(); \
    43137        struct exception_name { \
     
    46140        void ?{}(exception_name & this); \
    47141        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, ...) \
    49144        void ?{}(exception_name & this) { \
    50145                VTABLE_INIT(this, exception_name); \
     
    55150        _VTABLE_INSTANCE(exception_name, parent_name,)(_GLUE2(exception_name,_msg))
    56151
    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
    61170#define _DATA_EXCEPTION(exception_name, parent_name, ...) \
    62171        _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
    69185#define _VTABLE_DECLARATION(exception_name, parent_name, ...) \
    70186        struct exception_name; \
     187        void mark_exception(exception_name *); \
    71188        VTABLE_TYPE(exception_name); \
    72189        extern VTABLE_TYPE(exception_name) VTABLE_NAME(exception_name); \
     
    79196                _CLOSE
    80197
    81 // VTABLE_INSTANCE(exception_name)(msg [, others...]);
    82 // Create the instance of the virtual table. There must be exactly one instance of a virtual table
    83 // for each exception type. This fills in most of the fields of the virtual table (uses ?=? and
    84 // ^?{}) 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__)
    86198#define _VTABLE_INSTANCE(exception_name, parent_name, ...) \
     199        void mark_exception(exception_name *) {} \
    87200        void _GLUE2(exception_name,_copy)(exception_name * this, exception_name * other) { \
    88201                *this = *other; \
     
    93206                _CLOSE
    94207
    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  
    44// buffer.
    55
    6 #include <bits/containers.hfa>
    76#include <thread.hfa>
    8 #include <stdio.h>
     7#include <containers/list.hfa>
    98
    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
     9forall( 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
    2014
    21     T * remove( Buffer( T ) & mutex buf ) with(buf) {
    22         if ( queue.head != 0 ) wait( delay );                   // no request to process ? => wait
    23 //      return pop_head( queue );
    24     } // remove
    25 } // distribution
     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
    2620
    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
     29struct WRequest {                                                                               // client request, no return
     30        void (* action)( void );
     31        DLISTED_MGD_IMPL_IN(WRequest)
    3032}; // WRequest
     33DLISTED_MGD_IMPL_OUT(WRequest)
    3134
    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; }
     35void ?{}( WRequest & req ) with(req) { action = 0; }
     36void ?{}( WRequest & req, void (* action)( void ) ) with(req) { req.action = action; }
    3537bool stop( WRequest & req ) { return req.action == 0; }
    3638void doit( WRequest & req ) { req.action(); }
    3739
    38 // Each worker has its own work buffer to reduce contention between client and server. Hence, work requests arrive and
    39 // are 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.
    4042
    4143thread Worker {
    42     Buffer( WRequest ) * requests;
    43     unsigned int start, range;
     44        Buffer(WRequest) * requests;
     45        WRequest * request;
     46        unsigned int start, range;
    4447}; // Worker
    4548
    4649void 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     } // for
     50        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
    5457} // Worker::main
    5558
    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];
     59void ?{}( 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];
    5962} // ?{}
    6063
     64WRequest * current_request( Worker & worker ) { return worker.request; }
     65
    6166struct 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
    6874}; // Executor
    6975
    70 static thread_local unsigned int next;                  // demultiplexed across worker buffers
    7176unsigned int tickets( Executor & ex ) with(ex) {
    72     //return uFetchAdd( next, 1 ) % nmailboxes;
    73     return next++ % nmailboxes;                         // no locking, interference randomizes
     77        //return uFetchAdd( next, 1 ) % nrqueues;
     78        return next++ % nrqueues;                                                       // no locking, interference randomizes
    7479} // tickets
    7580
    76 void ?{}( Executor & ex, unsigned int np, unsigned int nw, unsigned int nm, 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 );
     81void ?{}( 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 );
    8388
    84     for ( i; nprocessors ) {
    85         processors[ i ] = new( *cluster );
    86     } // for
     89        for ( i; nprocessors ) {
     90                processors[i] = new( *cluster );
     91        } // for
    8792
    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
    9299} // ?{}
    93100
    94101void ?{}( Executor & ex, unsigned int nprocessors, unsigned int nworkers, bool sepClus = false ) {
    95     ex{ nprocessors, nworkers, nworkers, sepClus };
     102        ex{ nprocessors, nworkers, nworkers, sepClus };
    96103}
    97104void ?{}( Executor & ex, unsigned int nprocessors, bool sepClus = false ) {
    98     ex{ nprocessors, nprocessors, nprocessors, sepClus };
     105        ex{ nprocessors, nprocessors, nprocessors, sepClus };
    99106}
    100 void ?{}( Executor & ex ) {                             // special for current cluster
    101     ex{ 0, active_cluster()->nprocessors, false };
     107void ?{}( Executor & ex ) {                                                             // special for current cluster, no processors added
     108        ex{ 0, active_cluster()->nprocessors, false };
    102109}
    103110void ^?{}( Executor & ex ) with(ex) {
    104     // Add one sentinel per worker to stop them. Since in destructor, no new work should be queued.  Cannot combine next
    105     // 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.
    107114
    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 termination
    112     } // for
    113     for ( i; nworkers ) {
    114         delete( workers[ i ] );
    115     } // for
    116     for ( i; nprocessors ) {
    117         delete( processors[ i ] );
    118     } // for
     115        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
    119126
    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 ); }
    124133} // ^?{}
    125134
    126135void 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 );
    129138} // send
     139
    130140
    131141int counter = 0;
    132142
    133 void workie( void ) {
    134     __atomic_add_fetch( &counter, 1, __ATOMIC_SEQ_CST );
    135 //    fprintf( stderr, "workie\n" );
     143void work( void ) {
     144        __atomic_add_fetch( &counter, 1, __ATOMIC_SEQ_CST );
     145        // fprintf( stderr, "workie\n" );
    136146}
    137147
    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 );
     148int 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 );
    147160}
    148161
    149162// Local Variables: //
     163// tab-width: 4" //
    150164// compile-command: "cfa executor.cfa" //
    151165// End: //
  • libcfa/src/fstream.cfa

    r07d867b r22f94a4  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Feb  7 19:01:01 2020
    13 // Update Count     : 363
     12// Last Modified On : Fri Jun 19 16:24:54 2020
     13// Update Count     : 384
    1414//
    1515
     
    2626
    2727
    28 //*********************************** ofstream ***********************************
     28// *********************************** ofstream ***********************************
    2929
    3030
     
    123123        #ifdef __CFA_DEBUG__
    124124        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 );
    126127        } // if
    127128        #endif // __CFA_DEBUG__
     
    134135
    135136void 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;
    137139
    138140        if ( fclose( (FILE *)(os.$file) ) == EOF ) {
    139141                abort | IO_MSG "close output" | nl | strerror( errno );
    140142        } // if
     143        os.$file = 0p;
    141144} // close
    142145
     
    179182
    180183
    181 //*********************************** ifstream ***********************************
     184// *********************************** ifstream ***********************************
    182185
    183186
     
    219222        #ifdef __CFA_DEBUG__
    220223        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 );
    222226        } // if
    223227        #endif // __CFA_DEBUG__
     
    230234
    231235void 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;
    233238
    234239        if ( fclose( (FILE *)(is.$file) ) == EOF ) {
    235240                abort | IO_MSG "close input" | nl | strerror( errno );
    236241        } // if
     242        is.$file = 0p;
    237243} // close
    238244
     
    276282ifstream & sin = sinFile, & stdin = sinFile;
    277283
     284
     285// *********************************** exceptions ***********************************
     286
     287
     288void ?{}( Open_Failure & this, ofstream & ostream ) {
     289        VTABLE_INIT(this, Open_Failure);
     290        this.ostream = &ostream;
     291        this.tag = 1;
     292}
     293void ?{}( Open_Failure & this, ifstream & istream ) {
     294        VTABLE_INIT(this, Open_Failure);
     295        this.istream = &istream;
     296        this.tag = 0;
     297}
     298const char * Open_Failure_msg(Open_Failure * this) {
     299        return "Open_Failure";
     300}
     301VTABLE_INSTANCE(Open_Failure)(Open_Failure_msg);
     302void throwOpen_Failure( ofstream & ostream ) {
     303        Open_Failure exc = { ostream };
     304}
     305void throwOpen_Failure( ifstream & istream ) {
     306        Open_Failure exc = { istream };
     307}
     308
    278309// Local Variables: //
    279310// tab-width: 4 //
  • libcfa/src/fstream.hfa

    r07d867b r22f94a4  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Feb 17 08:29:23 2020
    13 // Update Count     : 175
     12// Last Modified On : Fri Jun 19 16:29:17 2020
     13// Update Count     : 189
    1414//
    1515
     
    1717
    1818#include "iostream.hfa"
     19#include <exception.hfa>
    1920
    2021
    21 //*********************************** ofstream ***********************************
     22// *********************************** ofstream ***********************************
    2223
    2324
     
    7879
    7980
    80 //*********************************** ifstream ***********************************
     81// *********************************** ifstream ***********************************
    8182
    8283
     
    106107extern ifstream & sin, & stdin;                                                 // aliases
    107108
     109
     110// *********************************** exceptions ***********************************
     111
     112
     113DATA_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
     122void ?{}( Open_Failure & this, ofstream & ostream );
     123void ?{}( Open_Failure & this, ifstream & istream );
     124
    108125// Local Variables: //
    109126// mode: c //
  • libcfa/src/heap.cfa

    r07d867b r22f94a4  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // heap.c --
     7// heap.cfa --
    88//
    99// Author           : Peter A. Buhr
    1010// Created On       : Tue Dec 19 21:58:35 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed May  6 17:29:26 2020
    13 // Update Count     : 727
     12// Last Modified On : Sun Aug  9 12:23:20 2020
     13// Update Count     : 894
    1414//
    1515
     
    2020#include <string.h>                                                                             // memset, memcpy
    2121#include <limits.h>                                                                             // ULONG_MAX
    22 extern "C" {
     22#include <malloc.h>                                                                             // memalign, malloc_usable_size
    2323#include <sys/mman.h>                                                                   // mmap, munmap
    24 } // extern "C"
    25 
    26 #include "bits/align.hfa"                                                               // libPow2
     24
     25#include "bits/align.hfa"                                                               // libAlign
    2726#include "bits/defs.hfa"                                                                // likely, unlikely
    2827#include "bits/locks.hfa"                                                               // __spinlock_t
    2928#include "startup.hfa"                                                                  // STARTUP_PRIORITY_MEMORY
    3029//#include "stdlib.hfa"                                                                 // bsearchl
    31 #include "malloc.h"
    3230#include "bitmanip.hfa"                                                                 // ceiling
    3331
     
    8280};
    8381
     82size_t default_mmap_start() __attribute__(( weak )) {
     83        return __CFA_DEFAULT_MMAP_START__;
     84} // default_mmap_start
     85
    8486size_t default_heap_expansion() __attribute__(( weak )) {
    8587        return __CFA_DEFAULT_HEAP_EXPANSION__;
    8688} // default_heap_expansion
    8789
    88 size_t default_mmap_start() __attribute__(( weak )) {
    89         return __CFA_DEFAULT_MMAP_START__;
    90 } // default_mmap_start
    91 
    9290
    9391#ifdef __CFA_DEBUG__
    94 static unsigned int allocFree;                                                  // running total of allocations minus frees
     92static size_t allocUnfreed;                                                             // running total of allocations minus frees
    9593
    9694static void prtUnfreed() {
    97         if ( allocFree != 0 ) {
     95        if ( allocUnfreed != 0 ) {
    9896                // DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT.
    9997                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"
    10199                                                        "Possible cause is unfreed storage allocated by the program or system/library routines called from the program.\n",
    102                                                         (long int)getpid(), allocFree, allocFree ); // always print the UNIX pid
     100                                                        (long int)getpid(), allocUnfreed, allocUnfreed ); // always print the UNIX pid
    103101                __cfaabi_bits_write( STDERR_FILENO, helpText, len ); // print debug/nodebug
    104102        } // if
     
    107105extern "C" {
    108106        void heapAppStart() {                                                           // called by __cfaabi_appready_startup
    109                 allocFree = 0;
     107                allocUnfreed = 0;
    110108        } // heapAppStart
    111109
     
    128126#define LOCKFREE 1
    129127#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
    132133#endif // LOCKFREE
    133134
     
    137138
    138139struct HeapManager {
    139 //      struct FreeHeader;                                                                      // forward declaration
    140 
    141140        struct Storage {
    142141                struct Header {                                                                 // header
     
    146145                                                struct {                                                // 4-byte word => 8-byte header, 8-byte word => 16-byte header
    147146                                                        #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ && __SIZEOF_POINTER__ == 4
    148                                                         uint32_t padding;                       // unused, force home/blocksize to overlay alignment in fake header
     147                                                        uint64_t padding;                       // unused, force home/blocksize to overlay alignment in fake header
    149148                                                        #endif // __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ && __SIZEOF_POINTER__ == 4
    150149
    151150                                                        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)
    153152                                                                // 2nd low-order bit => zero filled
    154153                                                                void * home;                    // allocated block points back to home locations (must overlay alignment)
    155154                                                                size_t blockSize;               // size for munmap (must overlay alignment)
    156                                                                 #if BUCKLOCK == SPINLOCK
     155                                                                #if BUCKETLOCK == SPINLOCK
    157156                                                                Storage * next;                 // freed block points next freed block of same size
    158157                                                                #endif // SPINLOCK
    159158                                                        };
     159                                                        size_t size;                            // allocation size in bytes
    160160
    161161                                                        #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ && __SIZEOF_POINTER__ == 4
    162                                                         uint32_t padding;                       // unused, force home/blocksize to overlay alignment in fake header
     162                                                        uint64_t padding;                       // unused, force home/blocksize to overlay alignment in fake header
    163163                                                        #endif // __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ && __SIZEOF_POINTER__ == 4
    164164                                                };
    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)
    168167                                                #endif // LOCKFREE
    169168                                        };
    170169                                } real; // RealHeader
     170
    171171                                struct FakeHeader {
    172172                                        #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
    175174                                        #endif // __ORDER_LITTLE_ENDIAN__
    176175
     
    182181                                } fake; // FakeHeader
    183182                        } kind; // Kind
    184                         size_t size;                                                            // allocation size in bytes
    185183                } header; // Header
    186184                char pad[libAlign() - sizeof( Header )];
     
    191189
    192190        struct FreeHeader {
    193                 #if BUCKLOCK == SPINLOCK
     191                #if BUCKETLOCK == SPINLOCK
    194192                __spinlock_t lock;                                                              // must be first field for alignment
    195193                Storage * freeList;
    196                 #elif BUCKLOCK == LOCKFREE
    197                 // future code
    198                 StackLF<Storage> freeList;
    199194                #else
    200                         #error undefined lock type for bucket lock
    201                 #endif // SPINLOCK
     195                StackLF(Storage) freeList;
     196                #endif // BUCKETLOCK
    202197                size_t blockSize;                                                               // size of allocations on this list
    203198        }; // FreeHeader
     
    212207}; // HeapManager
    213208
     209#if BUCKETLOCK == LOCKFREE
     210static 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
    214217static inline size_t getKey( const HeapManager.FreeHeader & freeheader ) { return freeheader.blockSize; }
    215218
     
    218221#define __STATISTICS__
    219222
    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.
    222226static const unsigned int bucketSizes[] @= {                    // different bucket sizes
    223         16, 32, 48, 64 + sizeof(HeapManager.Storage), // 4
    224         96, 112, 128 + sizeof(HeapManager.Storage), // 3
     227        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
    225229        160, 192, 224, 256 + sizeof(HeapManager.Storage), // 4
    226230        320, 384, 448, 512 + sizeof(HeapManager.Storage), // 4
     
    240244};
    241245
    242 static_assert( NoBucketSizes == sizeof(bucketSizes) / sizeof(bucketSizes[0]), "size of bucket array wrong" );
     246static_assert( NoBucketSizes == sizeof(bucketSizes) / sizeof(bucketSizes[0] ), "size of bucket array wrong" );
    243247
    244248#ifdef FASTLOOKUP
     
    251255static bool heapBoot = 0;                                                               // detect recursion during boot
    252256#endif // __CFA_DEBUG__
     257
     258// The constructor for heapManager is called explicitly in memory_startup.
    253259static HeapManager heapManager __attribute__(( aligned (128) )) @= {}; // size of cache line to prevent false sharing
    254260
     
    256262#ifdef __STATISTICS__
    257263// Heap statistics counters.
     264static unsigned int malloc_calls;
     265static unsigned long long int malloc_storage;
     266static unsigned int aalloc_calls;
     267static unsigned long long int aalloc_storage;
     268static unsigned int calloc_calls;
     269static unsigned long long int calloc_storage;
     270static unsigned int memalign_calls;
     271static unsigned long long int memalign_storage;
     272static unsigned int amemalign_calls;
     273static unsigned long long int amemalign_storage;
     274static unsigned int cmemalign_calls;
     275static unsigned long long int cmemalign_storage;
     276static unsigned int resize_calls;
     277static unsigned long long int resize_storage;
     278static unsigned int realloc_calls;
     279static unsigned long long int realloc_storage;
     280static unsigned int free_calls;
     281static unsigned long long int free_storage;
     282static unsigned int mmap_calls;
    258283static unsigned long long int mmap_storage;
    259 static unsigned int mmap_calls;
     284static unsigned int munmap_calls;
    260285static unsigned long long int munmap_storage;
    261 static unsigned int munmap_calls;
     286static unsigned int sbrk_calls;
    262287static 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;
    282288// Statistics file descriptor (changed by malloc_stats_fd).
    283 static int statfd = STDERR_FILENO;                                              // default stderr
     289static int stat_fd = STDERR_FILENO;                                             // default stderr
    284290
    285291// Use "write" because streams may be shutdown when calls are made.
     
    301307                                                                        "  sbrk: calls %u / storage %llu\n",
    302308                                                                        malloc_calls, malloc_storage,
    303                                                                         aalloc_calls, calloc_storage,
     309                                                                        aalloc_calls, aalloc_storage,
    304310                                                                        calloc_calls, calloc_storage,
    305311                                                                        memalign_calls, memalign_storage,
     
    354360
    355361
    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 // } // noMemory
    361 
    362 
    363362// thunk problem
    364363size_t Bsearchl( unsigned int key, const unsigned int * vals, size_t dim ) {
     
    407406
    408407static inline void checkAlign( size_t alignment ) {
    409         if ( alignment < libAlign() || ! libPow2( alignment ) ) {
     408        if ( alignment < libAlign() || ! is_pow2( alignment ) ) {
    410409                abort( "Alignment %zu for memory allocation is less than %d and/or not a power of 2.", alignment, libAlign() );
    411410        } // if
     
    429428                #endif // __CFA_DEBUG__
    430429                header = realHeader( header );                                  // backup from fake to real header
     430        } else {
     431                alignment = libAlign();                                                 // => no fake header
    431432        } // if
    432433} // fakeHeader
    433434
    434435
    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 ) {
     436static 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 ) {
    436438        header = headerAddr( addr );
    437439
    438         if ( unlikely( heapEnd < addr ) ) {                                     // mmapped ?
     440  if ( unlikely( heapEnd < addr ) ) {                                   // mmapped ?
    439441                fakeHeader( header, alignment );
    440442                size = header->kind.real.blockSize & -3;                // mmap size
     
    464466} // headers
    465467
    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
     470static inline void * extend( size_t size ) with( heapManager ) {
    468471        lock( extlock __cfaabi_dbg_ctx2 );
    469472        ptrdiff_t rem = heapRemaining - size;
     
    471474                // If the size requested is bigger than the current remaining storage, increase the size of the heap.
    472475
    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 ?
    475478                        unlock( extlock );
    476                         errno = ENOMEM;
    477                         return 0p;
     479                        abort( NO_MEMORY_MSG, size );                           // give up
    478480                } // if
    479481                #ifdef __STATISTICS__
     
    496498
    497499
    498 static inline void * doMalloc( size_t size ) with ( heapManager ) {
     500static inline void * doMalloc( size_t size ) with( heapManager ) {
    499501        HeapManager.Storage * block;                                            // pointer to new block of storage
    500502
     
    512514                        posn = Bsearchl( (unsigned int)tsize, bucketSizes, (size_t)maxBucketsUsed );
    513515                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 ?
    527518                tsize = freeElem->blockSize;                                    // total space needed for request
    528519
    529520                // Spin until the lock is acquired for this particular size of block.
    530521
    531                 #if defined( SPINLOCK )
     522                #if BUCKETLOCK == SPINLOCK
    532523                lock( freeElem->lock __cfaabi_dbg_ctx2 );
    533524                block = freeElem->freeList;                                             // remove node from stack
    534525                #else
    535                 block = freeElem->freeList.pop();
    536                 #endif // SPINLOCK
     526                block = pop( freeElem->freeList );
     527                #endif // BUCKETLOCK
    537528                if ( unlikely( block == 0p ) ) {                                // no free block ?
    538                         #if defined( SPINLOCK )
     529                        #if BUCKETLOCK == SPINLOCK
    539530                        unlock( freeElem->lock );
    540                         #endif // SPINLOCK
     531                        #endif // BUCKETLOCK
    541532
    542533                        // Freelist for that size was empty, so carve it out of the heap if there's enough left, or get some more
     
    544535
    545536                        block = (HeapManager.Storage *)extend( tsize ); // mutual exclusion on call
    546   if ( unlikely( block == 0p ) ) return 0p;
    547                 #if defined( SPINLOCK )
     537                #if BUCKETLOCK == SPINLOCK
    548538                } else {
    549539                        freeElem->freeList = block->header.kind.real.next;
    550540                        unlock( freeElem->lock );
    551                 #endif // SPINLOCK
     541                #endif // BUCKETLOCK
    552542                } // if
    553543
     
    555545        } else {                                                                                        // large size => mmap
    556546  if ( unlikely( size > ULONG_MAX - pageSize ) ) return 0p;
    557                 tsize = libCeiling( tsize, pageSize );                  // must be multiple of page size
     547                tsize = ceiling2( tsize, pageSize );                    // must be multiple of page size
    558548                #ifdef __STATISTICS__
    559549                __atomic_add_fetch( &mmap_calls, 1, __ATOMIC_SEQ_CST );
    560550                __atomic_add_fetch( &mmap_storage, tsize, __ATOMIC_SEQ_CST );
    561551                #endif // __STATISTICS__
     552
    562553                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
    564556                        // Do not call strerror( errno ) as it may call malloc.
    565557                        abort( "(HeapManager &)0x%p.doMalloc() : internal error, mmap failure, size:%zu error:%d.", &heapManager, tsize, errno );
    566                 } // if
     558                } //if
    567559                #ifdef __CFA_DEBUG__
    568560                // Set new memory to garbage so subsequent uninitialized usages might fail.
     
    572564        } // if
    573565
    574         block->header.size = size;                                                      // store allocation size
     566        block->header.kind.real.size = size;                            // store allocation size
    575567        void * addr = &(block->data);                                           // adjust off header to user bytes
     568        verify( ((uintptr_t)addr & (libAlign() - 1)) == 0 ); // minimum alignment ?
    576569
    577570        #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 );
    580572        if ( traceHeap() ) {
    581573                enum { BufferSize = 64 };
    582574                char helpText[BufferSize];
    583575                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 );
    585576                __cfaabi_bits_write( STDERR_FILENO, helpText, len ); // print debug/nodebug
    586577        } // if
     
    591582
    592583
    593 static inline void doFree( void * addr ) with ( heapManager ) {
     584static inline void doFree( void * addr ) with( heapManager ) {
    594585        #ifdef __CFA_DEBUG__
    595586        if ( unlikely( heapManager.heapBegin == 0p ) ) {
     
    623614                free_storage += size;
    624615                #endif // __STATISTICS__
    625                 #if defined( SPINLOCK )
     616                #if BUCKETLOCK == SPINLOCK
    626617                lock( freeElem->lock __cfaabi_dbg_ctx2 );               // acquire spin lock
    627618                header->kind.real.next = freeElem->freeList;    // push on stack
     
    629620                unlock( freeElem->lock );                                               // release spin lock
    630621                #else
    631                 freeElem->freeList.push( *(HeapManager.Storage *)header );
    632                 #endif // SPINLOCK
     622                push( freeElem->freeList, *(HeapManager.Storage *)header );
     623                #endif // BUCKETLOCK
    633624        } // if
    634625
    635626        #ifdef __CFA_DEBUG__
    636         __atomic_add_fetch( &allocFree, -size, __ATOMIC_SEQ_CST );
     627        __atomic_add_fetch( &allocUnfreed, -size, __ATOMIC_SEQ_CST );
    637628        if ( traceHeap() ) {
    638                 enum { BufferSize = 64 };
    639                 char helpText[BufferSize];
     629                char helpText[64];
    640630                int len = snprintf( helpText, sizeof(helpText), "Free( %p ) size:%zu\n", addr, size );
    641631                __cfaabi_bits_write( STDERR_FILENO, helpText, len ); // print debug/nodebug
     
    645635
    646636
    647 size_t prtFree( HeapManager & manager ) with ( manager ) {
     637size_t prtFree( HeapManager & manager ) with( manager ) {
    648638        size_t total = 0;
    649639        #ifdef __STATISTICS__
     
    657647                #endif // __STATISTICS__
    658648
    659                 #if defined( SPINLOCK )
     649                #if BUCKETLOCK == SPINLOCK
    660650                for ( HeapManager.Storage * p = freeLists[i].freeList; p != 0p; p = p->header.kind.real.next ) {
    661651                #else
    662                 for ( HeapManager.Storage * p = freeLists[i].freeList.top(); p != 0p; p = p->header.kind.real.next.top ) {
    663                 #endif // SPINLOCK
     652                for ( HeapManager.Storage * p = top( freeLists[i].freeList ); p != 0p; p = (p)`next->top ) {
     653                #endif // BUCKETLOCK
    664654                        total += size;
    665655                        #ifdef __STATISTICS__
     
    681671
    682672
    683 static void ?{}( HeapManager & manager ) with ( manager ) {
     673static void ?{}( HeapManager & manager ) with( manager ) {
    684674        pageSize = sysconf( _SC_PAGESIZE );
    685675
     
    702692
    703693        char * end = (char *)sbrk( 0 );
    704         heapBegin = heapEnd = sbrk( (char *)libCeiling( (long unsigned int)end, libAlign() ) - end ); // move start of heap to multiple of alignment
     694        heapBegin = heapEnd = sbrk( (char *)ceiling2( (long unsigned int)end, libAlign() ) - end ); // move start of heap to multiple of alignment
    705695} // HeapManager
    706696
     
    710700        if ( traceHeapTerm() ) {
    711701                printStats();
    712                 // if ( prtfree() ) prtFree( heapManager, true );
     702                // prtUnfreed() called in heapAppStop()
    713703        } // if
    714704        #endif // __STATISTICS__
     
    719709void memory_startup( void ) {
    720710        #ifdef __CFA_DEBUG__
    721         if ( unlikely( heapBoot ) ) {                                           // check for recursion during system boot
     711        if ( heapBoot ) {                                                                       // check for recursion during system boot
    722712                // DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT.
    723713                abort( "boot() : internal error, recursively invoked during system boot." );
     
    726716        #endif // __CFA_DEBUG__
    727717
    728         //assert( heapManager.heapBegin != 0 );
     718        //verify( heapManager.heapBegin != 0 );
    729719        //heapManager{};
    730720        if ( heapManager.heapBegin == 0p ) heapManager{};       // sanity check
     
    738728
    739729static 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
    742733#if __SIZEOF_POINTER__ == 8
    743734        verify( size < ((typeof(size_t))1 << 48) );
    744735#endif // __SIZEOF_POINTER__ == 8
    745         void * addr = doMalloc( size );
    746         if ( unlikely( addr == 0p ) ) errno = ENOMEM;           // POSIX
    747         return addr;
     736        return doMalloc( size );
    748737} // mallocNoStats
    749738
     
    751740static inline void * callocNoStats( size_t dim, size_t elemSize ) {
    752741        size_t size = dim * elemSize;
     742  if ( unlikely( size ) == 0 ) return 0p;                               // 0 BYTE ALLOCATION RETURNS NULL POINTER
    753743        char * addr = (char *)mallocNoStats( size );
    754   if ( unlikely( addr == 0p ) ) return 0p;
    755744
    756745        HeapManager.Storage.Header * header;
    757746        HeapManager.FreeHeader * freeElem;
    758747        size_t bsize, alignment;
    759         bool mapped __attribute__(( unused )) = headers( "calloc", addr, header, freeElem, bsize, alignment );
    760748        #ifndef __CFA_DEBUG__
     749        bool mapped =
     750        #endif // __CFA_DEBUG__
     751                headers( "calloc", addr, header, freeElem, bsize, alignment );
     752        #ifndef __CFA_DEBUG__
     753
    761754        // Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero.
    762755        if ( ! mapped )
    763756        #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
    766758                // `-header`-addr                      `-size
    767                 memset( addr, '\0', bsize - sizeof(HeapManager.Storage) ); // set to zeros
     759                memset( addr, '\0', size );                                             // set to zeros
    768760
    769761        header->kind.real.blockSize |= 2;                                       // mark as zero filled
     
    772764
    773765
    774 static inline void * memalignNoStats( size_t alignment, size_t size ) { // necessary for malloc statistics
     766static inline void * memalignNoStats( size_t alignment, size_t size ) {
     767  if ( unlikely( size ) == 0 ) return 0p;                               // 0 BYTE ALLOCATION RETURNS NULL POINTER
     768
    775769        #ifdef __CFA_DEBUG__
    776770        checkAlign( alignment );                                                        // check alignment
     
    790784        // add sizeof(Storage) for fake header
    791785        char * addr = (char *)mallocNoStats( size + alignment - libAlign() + sizeof(HeapManager.Storage) );
    792   if ( unlikely( addr == 0p ) ) return addr;
    793786
    794787        // 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 );
    796789
    797790        // address of header from malloc
    798791        HeapManager.Storage.Header * realHeader = headerAddr( addr );
     792        realHeader->kind.real.size = size;                                      // correct size to eliminate above alignment offset
    799793        // address of fake header * before* the alignment location
    800794        HeapManager.Storage.Header * fakeHeader = headerAddr( user );
     
    810804static inline void * cmemalignNoStats( size_t alignment, size_t dim, size_t elemSize ) {
    811805        size_t size = dim * elemSize;
     806  if ( unlikely( size ) == 0 ) return 0p;                               // 0 BYTE ALLOCATION RETURNS NULL POINTER
    812807        char * addr = (char *)memalignNoStats( alignment, size );
    813   if ( unlikely( addr == 0p ) ) return 0p;
     808
    814809        HeapManager.Storage.Header * header;
    815810        HeapManager.FreeHeader * freeElem;
    816811        size_t bsize;
    817         bool mapped __attribute__(( unused )) = headers( "cmemalign", addr, header, freeElem, bsize, alignment );
    818812        #ifndef __CFA_DEBUG__
     813        bool mapped =
     814        #endif // __CFA_DEBUG__
     815                headers( "cmemalign", addr, header, freeElem, bsize, alignment );
     816
    819817        // 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__
    820819        if ( ! mapped )
    821820        #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
    823824
    824825        header->kind.real.blockSize |= 2;                                       // mark as zero filled
    825826        return addr;
    826827} // cmemalignNoStats
    827 
    828 
    829 // supported mallopt options
    830 #ifndef M_MMAP_THRESHOLD
    831 #define M_MMAP_THRESHOLD (-1)
    832 #endif // M_TOP_PAD
    833 #ifndef M_TOP_PAD
    834 #define M_TOP_PAD (-2)
    835 #endif // M_TOP_PAD
    836828
    837829
     
    851843        // Same as malloc() except size bytes is an array of dim elements each of elemSize bytes.
    852844        void * aalloc( size_t dim, size_t elemSize ) {
     845                size_t size = dim * elemSize;
    853846                #ifdef __STATISTICS__
    854847                __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 );
    859852        } // aalloc
    860853
     
    869862                return callocNoStats( dim, elemSize );
    870863        } // calloc
     864
    871865
    872866        // Change the size of the memory block pointed to by oaddr to size bytes. The contents are undefined.  If oaddr is
     
    877871                #ifdef __STATISTICS__
    878872                __atomic_add_fetch( &resize_calls, 1, __ATOMIC_SEQ_CST );
    879                 __atomic_add_fetch( &resize_storage, size, __ATOMIC_SEQ_CST );
    880873                #endif // __STATISTICS__
    881874
    882875                // 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
    885883
    886884                HeapManager.Storage.Header * header;
    887885                HeapManager.FreeHeader * freeElem;
    888                 size_t bsize, oalign = 0;
     886                size_t bsize, oalign;
    889887                headers( "resize", oaddr, header, freeElem, bsize, oalign );
    890888
    891889                size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket
    892890                // same size, DO NOT preserve STICKY PROPERTIES.
    893           if ( oalign == 0 && size <= odsize && odsize <= size * 2 ) { // allow 50% wasted storage for smaller size
     891                if ( oalign <= libAlign() && size <= odsize && odsize <= size * 2 ) { // allow 50% wasted storage for smaller size
    894892                        header->kind.real.blockSize &= -2;                      // no alignment and turn off 0 fill
     893                        header->kind.real.size = size;                          // reset allocation size
    895894                        return oaddr;
    896895                } // if
    897        
     896
     897                #ifdef __STATISTICS__
     898                __atomic_add_fetch( &resize_storage, size, __ATOMIC_SEQ_CST );
     899                #endif // __STATISTICS__
     900
    898901                // change size, DO NOT preserve STICKY PROPERTIES.
    899902                free( oaddr );
    900                 void * naddr = mallocNoStats( size );                   // create new area
    901                 return naddr;
     903                return mallocNoStats( size );                                   // create new area
    902904        } // resize
    903905
     
    908910                #ifdef __STATISTICS__
    909911                __atomic_add_fetch( &realloc_calls, 1, __ATOMIC_SEQ_CST );
    910                 __atomic_add_fetch( &realloc_storage, size, __ATOMIC_SEQ_CST );
    911912                #endif // __STATISTICS__
    912913
    913914                // 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
    916922
    917923                HeapManager.Storage.Header * header;
    918924                HeapManager.FreeHeader * freeElem;
    919                 size_t bsize, oalign = 0;
     925                size_t bsize, oalign;
    920926                headers( "realloc", oaddr, header, freeElem, bsize, oalign );
    921927
    922928                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
    926936                        return oaddr;
    927937                } // if
    928938
     939                #ifdef __STATISTICS__
     940                __atomic_add_fetch( &realloc_storage, size, __ATOMIC_SEQ_CST );
     941                #endif // __STATISTICS__
     942
    929943                // change size and copy old content to new storage
    930944
    931945                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
    937960                        } // 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
    952962                return naddr;
    953963        } // realloc
    954964
     965
    955966        // Same as malloc() except the memory address is a multiple of alignment, which must be a power of two. (obsolete)
    956967        void * memalign( size_t alignment, size_t size ) {
     
    966977        // Same as aalloc() with memory alignment.
    967978        void * amemalign( size_t alignment, size_t dim, size_t elemSize ) {
     979                size_t size = dim * elemSize;
    968980                #ifdef __STATISTICS__
    969981                __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 );
    974986        } // amemalign
    975987
     
    9971009        // free(3).
    9981010        int posix_memalign( void ** memptr, size_t alignment, size_t size ) {
    999           if ( alignment < sizeof(void *) || ! libPow2( alignment ) ) return EINVAL; // check alignment
     1011          if ( alignment < libAlign() || ! is_pow2( alignment ) ) return EINVAL; // check alignment
    10001012                * memptr = memalign( alignment, size );
    1001           if ( unlikely( * memptr == 0p ) ) return ENOMEM;
    10021013                return 0;
    10031014        } // posix_memalign
     
    10121023        // Same as valloc but rounds size to multiple of page size.
    10131024        void * pvalloc( size_t size ) {
    1014                 return memalign( pageSize, libCeiling( size, pageSize ) );
     1025                return memalign( pageSize, ceiling2( size, pageSize ) );
    10151026        } // pvalloc
    10161027
     
    10501061        } // malloc_alignment
    10511062
     1063
    10521064        // Set the alignment for an the allocation and return previous alignment or 0 if no alignment.
    10531065        size_t $malloc_alignment_set( void * addr, size_t alignment ) {
     
    10901102        // Returns original total allocation size (not bucket size) => array size is dimension * sizeif(T).
    10911103        size_t malloc_size( void * addr ) {
    1092           if ( unlikely( addr == 0p ) ) return false;           // null allocation is not zero fill
     1104          if ( unlikely( addr == 0p ) ) return 0;                       // null allocation has zero size
    10931105                HeapManager.Storage.Header * header = headerAddr( addr );
    10941106                if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ?
    10951107                        header = realHeader( header );                          // backup from fake to real header
    10961108                } // if
    1097                 return header->size;
     1109                return header->kind.real.size;
    10981110        } // malloc_size
    10991111
    11001112        // Set allocation size and return previous size.
    11011113        size_t $malloc_size_set( void * addr, size_t size ) {
    1102           if ( unlikely( addr == 0p ) ) return false;           // null allocation is not zero fill
     1114          if ( unlikely( addr == 0p ) ) return 0;                       // null allocation has 0 size
    11031115                HeapManager.Storage.Header * header = headerAddr( addr );
    11041116                if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ?
    11051117                        header = realHeader( header );                          // backup from fake to real header
    11061118                } // 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;
    11091121                return ret;
    11101122        } // $malloc_size_set
     
    11201132
    11211133                headers( "malloc_usable_size", addr, header, freeElem, bsize, alignment );
    1122                 return dataStorage( bsize, addr, header );      // data storage in bucket
     1134                return dataStorage( bsize, addr, header );              // data storage in bucket
    11231135        } // malloc_usable_size
    11241136
     
    11321144        } // malloc_stats
    11331145
     1146
    11341147        // Changes the file descripter where malloc_stats() writes statistics.
    11351148        int malloc_stats_fd( int fd __attribute__(( unused )) ) {
    11361149                #ifdef __STATISTICS__
    1137                 int temp = statfd;
    1138                 statfd = fd;
     1150                int temp = stat_fd;
     1151                stat_fd = fd;
    11391152                return temp;
    11401153                #else
     
    11571170        } // mallopt
    11581171
     1172
    11591173        // Attempt to release free memory at the top of the heap (by calling sbrk with a suitable argument).
    11601174        int malloc_trim( size_t ) {
     
    11671181        // malloc).
    11681182        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__
    11701185                return printStatsXML( stream );
     1186                #else
     1187                return 0;                                                                               // unsupported
     1188                #endif // __STATISTICS__
    11711189        } // malloc_info
    11721190
     
    11831201        // Restores the state of all malloc internal bookkeeping variables to the values recorded in the opaque data
    11841202        // structure pointed to by state.
    1185         int malloc_set_state( void * ptr ) {
     1203        int malloc_set_state( void * ) {
    11861204                return 0;                                                                               // unsupported
    11871205        } // malloc_set_state
     
    11931211        #ifdef __STATISTICS__
    11941212        __atomic_add_fetch( &resize_calls, 1, __ATOMIC_SEQ_CST );
    1195         __atomic_add_fetch( &resize_storage, size, __ATOMIC_SEQ_CST );
    11961213        #endif // __STATISTICS__
    11971214
    11981215        // 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
    12041225        #ifdef __CFA_DEBUG__
    12051226        else
     
    12091230        HeapManager.Storage.Header * header;
    12101231        HeapManager.FreeHeader * freeElem;
    1211         size_t bsize, oalign = 0;
     1232        size_t bsize, oalign;
    12121233        headers( "resize", oaddr, header, freeElem, bsize, oalign );
    12131234        size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket
    12141235
    12151236        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 ?
    12171238                        headerAddr( oaddr )->kind.fake.alignment = nalign | 1; // update alignment (could be the same)
    12181239                } // if
    12191240                if ( size <= odsize && odsize <= size * 2 ) {   // allow 50% wasted storage for smaller size
    12201241                        header->kind.real.blockSize &= -2;                      // turn off 0 fill
     1242                        header->kind.real.size = size;                          // reset allocation size
    12211243                        return oaddr;
    12221244                } // if
    12231245        } // if
    12241246
    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.
    12341252        free( oaddr );
    1235         return naddr;
     1253        return memalignNoStats( nalign, size );                         // create new aligned area
    12361254} // resize
    12371255
    12381256
    12391257void * realloc( void * oaddr, size_t nalign, size_t size ) {
    1240         if ( unlikely( nalign == 0 ) ) nalign = libAlign();     // reset alignment to minimum
     1258        if ( unlikely( nalign < libAlign() ) ) nalign = libAlign(); // reset alignment to minimum
    12411259        #ifdef __CFA_DEBUG__
    12421260        else
     
    12461264        HeapManager.Storage.Header * header;
    12471265        HeapManager.FreeHeader * freeElem;
    1248         size_t bsize, oalign = 0;
     1266        size_t bsize, oalign;
    12491267        headers( "realloc", oaddr, header, freeElem, bsize, oalign );
    1250         size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket
    12511268
    12521269        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 ?
    12541271                        headerAddr( oaddr )->kind.fake.alignment = nalign | 1; // update alignment (could be the same)
    12551272                } // if
     
    12651282
    12661283        // 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 cases
     1284  if ( unlikely( size == 0 ) ) { free( oaddr ); return 0p; } // special cases
    12681285  if ( unlikely( oaddr == 0p ) ) return memalignNoStats( nalign, size );
    12691286
    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
    12761291
    12771292        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
    12811294        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
    12821302        return naddr;
    12831303} // realloc
  • libcfa/src/iostream.cfa

    r07d867b r22f94a4  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat May  2 18:30:25 2020
    13 // Update Count     : 1017
     12// Last Modified On : Mon Aug 10 09:32:14 2020
     13// Update Count     : 1126
    1414//
    1515
    1616#include "iostream.hfa"
    1717
    18 extern "C" {
    1918#include <stdio.h>
    2019#include <stdbool.h>                                                                    // true/false
    2120#include <stdint.h>                                                                             // UINT64_MAX
     21#include <float.h>                                                                              // DBL_DIG, LDBL_DIG
     22#include <math.h>                                                                               // isfinite
     23#include <complex.h>                                                                    // creal, cimag
    2224//#include <string.h>                                                                   // strlen, strcmp
     25extern "C" {
    2326extern size_t strlen (const char *__s) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
    2427extern int strcmp (const char *__s1, const char *__s2) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));
    2528extern char *strcpy (char *__restrict __dest, const char *__restrict __src) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2)));
    2629extern 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_DIG
    28 #include <math.h>                                                                               // isfinite
    29 #include <complex.h>                                                                    // creal, cimag
    3030} // extern "C"
    3131
    32 #include <bitmanip.hfa>                                                                 // fms
    33 
    34 
    35 //*********************************** ostream ***********************************
     32#include <bitmanip.hfa>                                                                 // high1
     33
     34
     35// *********************************** ostream ***********************************
    3636
    3737
     
    167167        #define P10_UINT64 10_000_000_000_000_000_000_ULL       // 19 zeroes
    168168
    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)
    171175                        base10_128( os, val / P10_UINT64 );                     // recursive
    172176                        fmt( os, "%.19lu", (uint64_t)(val % P10_UINT64) );
     
    176180        } // base10_128
    177181
    178         static void base10_128( ostype & os, int128 val ) {
     182        static inline void base10_128( ostype & os, int128 val ) {
    179183                if ( val < 0 ) {
    180184                        fmt( os, "-" );                                                         // leading negative sign
     
    447451} // distribution
    448452
    449 //*********************************** manipulators ***********************************
    450 
    451 //*********************************** integral ***********************************
     453// *********************************** manipulators ***********************************
     454
     455// *********************************** integral ***********************************
    452456
    453457static const char * shortbin[] = { "0", "1", "10", "11", "100", "101", "110", "111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111" };
     
    455459
    456460// Default prefix for non-decimal prints is 0b, 0, 0x.
    457 #define IntegralFMTImpl( T, CODE, IFMTNP, IFMTP ) \
     461#define IntegralFMTImpl( T, IFMTNP, IFMTP ) \
    458462forall( dtype ostype | ostream( ostype ) ) { \
    459463        ostype & ?|?( ostype & os, _Ostream_Manip(T) f ) { \
     
    506510                        if ( f.flags.left && spaces > 0 ) fmt( os, "%*s", spaces, " " ); \
    507511                        return os; \
    508                 } /* if  */ \
     512                } /* if */ \
    509513\
    510514                char fmtstr[sizeof(IFMTP)];                                             /* sizeof includes '\0' */ \
     
    516520                if ( ! f.flags.nobsdp ) { fmtstr[star] = '#'; star -= 1; } \
    517521                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; } \
    519523                if ( f.flags.pad0 && ! f.flags.pc ) { fmtstr[star] = '0'; star -= 1; } \
    520524                fmtstr[star] = '%'; \
     
    522526                if ( ! f.flags.pc ) {                                                   /* no precision */ \
    523527                        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 ); */ \
    525529                        fmt( os, &fmtstr[star], f.wd, f.val ); \
    526530                } else {                                                                                /* precision */ \
    527531                        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 ); */ \
    529533                        fmt( os, &fmtstr[star], f.wd, f.pc, f.val ); \
    530534                } /* if */ \
     
    534538} // distribution
    535539
    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 
     540IntegralFMTImpl( signed char, "%    *hh ", "%    *.*hh " )
     541IntegralFMTImpl( unsigned char, "%    *hh ", "%    *.*hh " )
     542IntegralFMTImpl( signed short int, "%    *h ", "%    *.*h " )
     543IntegralFMTImpl( unsigned short int, "%    *h ", "%    *.*h " )
     544IntegralFMTImpl( signed int, "%    * ", "%    *.* " )
     545IntegralFMTImpl( unsigned int, "%    * ", "%    *.* " )
     546IntegralFMTImpl( signed long int, "%    *l ", "%    *.*l " )
     547IntegralFMTImpl( unsigned long int, "%    *l ", "%    *.*l " )
     548IntegralFMTImpl( signed long long int, "%    *ll ", "%    *.*ll " )
     549IntegralFMTImpl( unsigned long long int, "%    *ll ", "%    *.*ll " )
     550
     551#if 0
    548552#if defined( __SIZEOF_INT128__ )
    549553// Default prefix for non-decimal prints is 0b, 0, 0x.
     
    611615                                                sepOff( os ); \
    612616                                                fmt2.flags.left = true; \
    613                                                 int msigd = ceiling( high1( fmt.val ), 3 ); \
     617                                                int msigd = ceiling_div( high1( fmt.val ), 3 ); \
    614618                                                fmt2.wd = f.wd - (fmt.pc > msigd ? fmt.pc : msigd); \
    615619                                                if ( ! fmt.flags.nobsdp ) fmt2.wd -= 1; /* compensate for 0 base specifier */ \
     
    663667IntegralFMTImpl128( unsigned int128, unsigned, 'u', "%    *ll ", "%    *.*ll " )
    664668#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.
     674forall( dtype ostype | ostream( ostype ) )
     675static 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 ) \
     739forall( 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
     758IntegralFMTImpl128( int128 )
     759IntegralFMTImpl128( unsigned int128 )
     760#endif // __SIZEOF_INT128__
     761#endif // 0
     762
     763// *********************************** floating point ***********************************
    667764
    668765#define PrintWithDP2( os, format, val, ... ) \
     
    720817FloatingPointFMTImpl( long double, "%    *L ", "%    *.*L " )
    721818
    722 //*********************************** character ***********************************
     819// *********************************** character ***********************************
    723820
    724821forall( dtype ostype | ostream( ostype ) ) {
     
    753850} // distribution
    754851
    755 //*********************************** C string ***********************************
     852// *********************************** C string ***********************************
    756853
    757854forall( dtype ostype | ostream( ostype ) ) {
     
    800897
    801898
    802 //*********************************** istream ***********************************
     899// *********************************** istream ***********************************
    803900
    804901
     
    877974        } // ?|?
    878975
     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__
    879997
    880998        istype & ?|?( istype & is, float & f ) {
     
    9461064} // distribution
    9471065
    948 //*********************************** manipulators ***********************************
     1066// *********************************** manipulators ***********************************
    9491067
    9501068forall( dtype istype | istream( istype ) )
  • libcfa/src/iostream.hfa

    r07d867b r22f94a4  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb 20 15:30:56 2020
    13 // Update Count     : 337
     12// Last Modified On : Thu Jul 16 07:43:32 2020
     13// Update Count     : 348
    1414//
    1515
     
    1919
    2020
    21 //*********************************** ostream ***********************************
     21// *********************************** ostream ***********************************
    2222
    2323
     
    156156} // distribution
    157157
    158 //*********************************** manipulators ***********************************
     158// *********************************** manipulators ***********************************
    159159
    160160forall( otype T )
     
    166166                unsigned char all;
    167167                struct {
     168                        unsigned char neg:1;                                            // val is negative
    168169                        unsigned char pc:1;                                                     // precision specified
    169170                        unsigned char left:1;                                           // left justify
     
    175176}; // _Ostream_Manip
    176177
    177 //*********************************** integral ***********************************
     178// *********************************** integral ***********************************
    178179
    179180// See 6.7.9. 19) The initialization shall occur in initializer list order, each initializer provided for a particular
     
    215216IntegralFMTDecl( int128, 'd' )
    216217IntegralFMTDecl( unsigned int128, 'u' )
    217 #endif
    218 
    219 //*********************************** floating point ***********************************
     218#endif // __SIZEOF_INT128__
     219
     220// *********************************** floating point ***********************************
    220221
    221222// Default suffix for values with no fraction is "."
     
    246247FloatingPointFMTDecl( long double )
    247248
    248 //*********************************** character ***********************************
     249// *********************************** character ***********************************
    249250
    250251static inline {
     
    263264} // ?|?
    264265
    265 //*********************************** C string ***********************************
     266// *********************************** C string ***********************************
    266267
    267268static inline {
     
    282283
    283284
    284 //*********************************** istream ***********************************
     285// *********************************** istream ***********************************
    285286
    286287
     
    314315        istype & ?|?( istype &, unsigned int & );
    315316        istype & ?|?( istype &, long int & );
     317        istype & ?|?( istype &, unsigned long int & );
    316318        istype & ?|?( istype &, long long int & );
    317         istype & ?|?( istype &, unsigned long int & );
    318319        istype & ?|?( istype &, unsigned long long int & );
     320#if defined( __SIZEOF_INT128__ )
     321        istype & ?|?( istype &, int128 & );
     322        istype & ?|?( istype &, unsigned int128 & );
     323#endif // __SIZEOF_INT128__
    319324
    320325        istype & ?|?( istype &, float & );
     
    336341} // distribution
    337342
    338 //*********************************** manipulators ***********************************
     343// *********************************** manipulators ***********************************
    339344
    340345struct _Istream_Cstr {
     
    358363        _Istream_Cstr excl( const char scanset[], char * s ) { return (_Istream_Cstr){ s, scanset, -1, { .flags.inex : true } }; }
    359364        _Istream_Cstr & excl( const char scanset[], _Istream_Cstr & fmt ) { fmt.scanset = scanset; fmt.flags.inex = true; return fmt; }
    360         _Istream_Cstr ignore( const 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 } }; }
    361366        _Istream_Cstr & ignore( _Istream_Cstr & fmt ) { fmt.flags.ignore = true; return fmt; }
    362367        _Istream_Cstr wdi( unsigned int w, char s[] ) { return (_Istream_Cstr)@{ s, 0p, w, { .all : 0 } }; }
     
    370375
    371376static inline {
    372         _Istream_Char ignore( const char c ) { return (_Istream_Char)@{ true }; }
     377        _Istream_Char ignore( const char ) { return (_Istream_Char)@{ true }; }
    373378        _Istream_Char & ignore( _Istream_Char & fmt ) { fmt.ignore = true; return fmt; }
    374379} // distribution
    375380forall( dtype istype | istream( istype ) ) istype & ?|?( istype & is, _Istream_Char f );
    376381
    377 forall( otype T )
     382forall( dtype T | sized( T ) )
    378383struct _Istream_Manip {
    379384        T & val;                                                                                        // polymorphic base-type
     
    413418
    414419
    415 //*********************************** time ***********************************
     420// *********************************** time ***********************************
    416421
    417422
  • libcfa/src/stdhdr/assert.h

    r07d867b r22f94a4  
    3333        #define verify(x) assert(x)
    3434        #define verifyf(x, ...) assertf(x, __VA_ARGS__)
     35        #define verifyfail(...)
    3536        #define __CFA_WITH_VERIFY__
    3637#else
    3738        #define verify(x)
    3839        #define verifyf(x, ...)
     40        #define verifyfail(...)
    3941#endif
    4042
  • libcfa/src/stdhdr/malloc.h

    r07d867b r22f94a4  
    1010// Created On       : Thu Jul 20 15:58:16 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Apr 16 22:44:06 2020
    13 // Update Count     : 13
     12// Last Modified On : Wed May 27 14:13:14 2020
     13// Update Count     : 18
    1414//
    15 
    16 
    17 size_t default_mmap_start();                                                    // CFA extras
    18 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"
    4115
    4216extern "C" {
    4317#include_next <malloc.h>                                                                // has internal check for multiple expansion
    4418} // extern "C"
     19
     20#include <heap.hfa>
    4521
    4622// Local Variables: //
  • libcfa/src/stdlib.cfa

    r07d867b r22f94a4  
    1010// Created On       : Thu Jan 28 17:10:29 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Apr 16 22:43:33 2020
    13 // Update Count     : 498
     12// Last Modified On : Sun Jul 19 15:05:28 2020
     13// Update Count     : 501
    1414//
    1515
     
    2626//---------------------------------------
    2727
    28 forall( dtype T | sized(T) ) {
    29         T * alloc_set( T ptr[], size_t dim, char fill ) {       // realloc array with fill
    30                 size_t olen = malloc_usable_size( ptr );                // current allocation
    31                 void * nptr = (void *)realloc( (void *)ptr, dim * sizeof(T) ); // C realloc
    32                 size_t nlen = malloc_usable_size( nptr );               // new allocation
    33                 if ( nlen > olen ) {                                                    // larger ?
    34                         memset( (char *)nptr + olen, (int)fill, nlen - olen ); // initialize added storage
    35                 } // if
    36                 return (T *)nptr;
    37         } // alloc_set
    38 
    39         T * alloc_set( T ptr[], size_t dim, T fill ) {          // realloc array with fill
    40                 size_t olen = malloc_usable_size( ptr );                // current allocation
    41                 void * nptr = (void *)realloc( (void *)ptr, dim * sizeof(T) ); // C realloc
    42                 size_t nlen = malloc_usable_size( nptr );               // new allocation
    43                 if ( nlen > olen ) {                                                    // larger ?
    44                         for ( i; malloc_size( ptr ) / sizeof(T) ~ dim ) {
    45                                 memcpy( &ptr[i], &fill, sizeof(T) );    // initialize with fill value
    46                         } // for
    47                 } // if
    48                 return (T *)nptr;
    49         } // alloc_align_set
    50 
    51         T * alloc_align_set( T ptr[], size_t align, char fill ) { // aligned realloc with fill
    52                 size_t olen = malloc_usable_size( ptr );                // current allocation
    53                 void * nptr = (void *)realloc( (void *)ptr, align, sizeof(T) ); // CFA realloc
    54                 // char * nptr = alloc_align( ptr, align );
    55                 size_t nlen = malloc_usable_size( nptr );               // new allocation
    56                 if ( nlen > olen ) {                                                    // larger ?
    57                         memset( (char *)nptr + olen, (int)fill, nlen - olen ); // initialize added storage
    58                 } // if
    59                 return (T *)nptr;
    60         } // alloc_align_set
    61 
    62         T * alloc_align_set( T ptr[], size_t align, size_t dim, T fill ) { // aligned realloc with fill
    63                 size_t olen = malloc_usable_size( ptr );                // current allocation
    64                 void * nptr = (void *)realloc( (void *)ptr, align, sizeof(T) ); // CFA realloc
    65                 // char * nptr = alloc_align( ptr, align );
    66                 size_t nlen = malloc_usable_size( nptr );               // new allocation
    67                 if ( nlen > olen ) {                                                    // larger ?
    68                         for ( i; dim ) { memcpy( &ptr[i], &fill, sizeof(T) ); } // initialize with fill value
    69                 } // if
    70                 return (T *)nptr;
    71         } // alloc_align_set
    72 } // distribution
    73 
    7428// allocation/deallocation and constructor/destructor, non-array types
    7529forall( dtype T | sized(T), ttype Params | { void ?{}( T &, Params ); } )
     
    7832} // new
    7933
    80 forall( dtype T | sized(T) | { void ^?{}( T & ); } )
     34forall( dtype T | { void ^?{}( T & ); } )
    8135void delete( T * ptr ) {
    8236        if ( ptr ) {                                                                            // ignore null
     
    8640} // delete
    8741
    88 forall( dtype T, ttype Params | sized(T) | { void ^?{}( T & ); void delete( Params ); } )
     42forall( dtype T, ttype Params | { void ^?{}( T & ); void delete( Params ); } )
    8943void delete( T * ptr, Params rest ) {
    90         if ( ptr ) {                                                                            // ignore null
    91                 ^(*ptr){};                                                                              // run destructor
    92                 free( ptr );
    93         } // if
     44        delete( ptr );
    9445        delete( rest );
    9546} // delete
     
    277228extern "C" {                                                                                    // override C version
    278229        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
    280231} // extern "C"
    281232
  • libcfa/src/stdlib.hfa

    r07d867b r22f94a4  
    1010// Created On       : Thu Jan 28 17:12:35 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Apr 16 22:44:05 2020
    13 // Update Count     : 432
     12// Last Modified On : Thu Jul 30 16:14:58 2020
     13// Update Count     : 490
    1414//
    1515
     
    2020
    2121#include <stdlib.h>                                                                             // *alloc, strto*, ato*
     22#include <heap.hfa>
    2223
    2324// Reduce includes by explicitly defining these routines.
    2425extern "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
    2928        void * memset( void * dest, int fill, size_t size ); // string.h
    3029        void * memcpy( void * dest, const void * src, size_t size ); // string.h
    31         void * resize( void * oaddr, size_t size );                     // CFA heap
    3230} // extern "C"
    33 
    34 void * resize( void * oaddr, size_t nalign, size_t size ); // CFA heap
    35 void * realloc( void * oaddr, size_t nalign, size_t size ); // CFA heap
    3631
    3732//---------------------------------------
     
    4439//---------------------------------------
    4540
     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
    4656static inline forall( dtype T | sized(T) ) {
    4757        // Cforall safe equivalents, i.e., implicit size specification
    4858
    4959        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 );
    5261        } // malloc
    5362
     63        T * aalloc( size_t dim ) {
     64                $ARRAY_ALLOC( aalloc, amemalign, dim );
     65        } // aalloc
     66
    5467        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 );
    5769        } // calloc
    5870
     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
    5977        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
    6181        } // realloc
    6282
     
    6585        } // memalign
    6686
     87        T * amemalign( size_t align, size_t dim ) {
     88                return (T *)amemalign( align, dim, sizeof(T) ); // CFA amemalign
     89        } // amemalign
     90
    6791        T * cmemalign( size_t align, size_t dim  ) {
    6892                return (T *)cmemalign( align, dim, sizeof(T) ); // CFA cmemalign
     
    76100                return posix_memalign( (void **)ptr, align, sizeof(T) ); // C posix_memalign
    77101        } // 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
    78110} // distribution
    79111
     
    86118
    87119        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 );
    90121        } // alloc
    91122
    92123        forall( dtype S | sized(S) )
    93124        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
    99131                } 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
    110133                } // if
    111134        } // alloc
     
    132155                return (T *)memcpy( (T *)alloc( dim ), fill, dim * sizeof(T) ); // initialize with fill value
    133156        } // 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
    139180} // distribution
    140181
     
    148189        } // alloc_align
    149190
    150         T * alloc_align( T ptr[], size_t align ) {                      // aligned realloc array
    151                 return (T *)(void *)realloc( (void *)ptr, align, sizeof(T) ); // CFA realloc
     191        T * alloc_align( T * ptr, size_t align ) {                      // aligned realloc array
     192                return (T *)(void *)realloc( (void *)ptr, align, sizeof(T) ); // CFA C realloc
    152193        } // alloc_align
    153194
     
    182223                return (T *)memcpy( (T *)alloc_align( align, dim ), fill, dim * sizeof(T) );
    183224        } // 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
    191248} // distribution
    192249
     
    215272// Cforall allocation/deallocation and constructor/destructor, non-array types
    216273forall( 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 );
     274forall( dtype T | { void ^?{}( T & ); } ) void delete( T * ptr );
     275forall( dtype T, ttype Params | { void ^?{}( T & ); void delete( Params ); } ) void delete( T * ptr, Params rest );
    219276
    220277// Cforall allocation/deallocation and constructor/destructor, array types
     
    287344extern "C" {                                                                                    // override C version
    288345        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;
    290348} // extern "C"
    291349
     
    294352        long int random( long int u ) { if ( u < 0 ) return random( u, 0 ); else return random( 0, u ); } // [0,u)
    295353        unsigned long int random( void ) { return lrand48(); }
     354        unsigned long int random( unsigned long int u ) { return lrand48() % u; } // [0,u)
    296355        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)
    298356
    299357        char random( void ) { return (unsigned long int)random(); }
  • libcfa/src/time.hfa

    r07d867b r22f94a4  
    1010// Created On       : Wed Mar 14 23:18:57 2018
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Feb  4 08:24:32 2020
    13 // Update Count     : 654
     12// Last Modified On : Wed Jun 17 16:13:00 2020
     13// Update Count     : 663
    1414//
    1515
     
    2020
    2121#include <time.h>                                                                               // timespec
    22 extern "C" {
    2322#include <sys/time.h>                                                                   // timeval
    24 }
    2523#include <time_t.hfa>                                                                   // Duration/Time types
    2624
     
    9189        int64_t ?`w( Duration dur ) { return dur.tn / (7LL * 24LL * 60LL * 60LL * TIMEGRAN); }
    9290
     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
    93100        Duration max( Duration lhs, Duration rhs ) { return  (lhs.tn < rhs.tn) ? rhs : lhs;}
    94101        Duration min( Duration lhs, Duration rhs ) { return !(rhs.tn < lhs.tn) ? lhs : rhs;}
  • longrun_tests/Makefile.am

    r07d867b r22f94a4  
    1818ACLOCAL_AMFLAGS  = -I automake
    1919
    20 include $(top_srcdir)/src/cfa.make
     20include $(top_srcdir)/tools/build/cfa.make
    2121
    2222repeats=10
  • src/Common/PassVisitor.proto.h

    r07d867b r22f94a4  
    3838        };
    3939
    40         std::stack< cleanup_t, std::vector<cleanup_t> > cleanups;
     40        std::stack< cleanup_t, std::vector< cleanup_t > > cleanups;
    4141};
    4242
  • src/Common/ScopedMap.h

    r07d867b r22f94a4  
    9393
    9494                reference operator* () { return *it; }
    95                 pointer operator-> () { return it.operator->(); }
     95                pointer operator-> () const { return it.operator->(); }
    9696
    9797                iterator& operator++ () {
  • src/Concurrency/Keywords.cc

    r07d867b r22f94a4  
    510510                                                new CastExpr(
    511511                                                        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
    513514                                                )
    514515                                        )
     
    888889                        new SingleInit( new UntypedExpr(
    889890                                new NameExpr( "get_monitor" ),
    890                                 {  new CastExpr( new VariableExpr( args.front() ), arg_type ) }
     891                                {  new CastExpr( new VariableExpr( args.front() ), arg_type, false ) }
    891892                        ))
    892893                );
     
    909910                                        {
    910911                                                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 ) )
    912913                                        },
    913914                                        noDesignators,
     
    946947                                        return new SingleInit( new UntypedExpr(
    947948                                                new NameExpr( "get_monitor" ),
    948                                                 {  new CastExpr( new VariableExpr( var ), type ) }
     949                                                {  new CastExpr( new VariableExpr( var ), type, false ) }
    949950                                        ) );
    950951                                })
     
    970971                                                new SingleInit( new VariableExpr( monitors ) ),
    971972                                                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 ) )
    973974                                        },
    974975                                        noDesignators,
  • src/Concurrency/Waitfor.cc

    r07d867b r22f94a4  
    384384                                                                decl_monitor
    385385                                                        )
    386                                                 )
     386                                                ),
     387                                                false
    387388                                        );
    388389
     
    408409                        new CompoundStmt({
    409410                                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 ),
    411412                                makeAccStatement( acceptables, index, "data"   , new VariableExpr( monitors )                                              , indexer ),
    412413                                makeAccStatement( acceptables, index, "size"   , new ConstantExpr( Constant::from_ulong( clause.target.arguments.size() ) ), indexer ),
     
    531532                                                                decl_mask
    532533                                                        )
    533                                                 )
     534                                                ),
     535                                                false
    534536                                        ),
    535537                                        timeout
  • src/ControlStruct/ExceptTranslate.cc

    r07d867b r22f94a4  
    1010// Created On       : Wed Jun 14 16:49:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Mar 27 11:58:00 2020
    13 // Update Count     : 13
     12// Last Modified On : Wed Jun 24 11:18:00 2020
     13// Update Count     : 17
    1414//
    1515
     
    6464        }
    6565
    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 {
    78168                // The built in types used in translation.
    79169                StructDecl * except_decl;
     
    82172
    83173                // 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 );
    90174                CompoundStmt * take_try_block( TryStmt * tryStmt );
    91175                FunctionDecl * create_try_wrapper( CompoundStmt * body );
     
    101185                FunctionDecl * create_finally_wrapper( TryStmt * tryStmt );
    102186                ObjectDecl * create_finally_hook( FunctionDecl * finally_wrapper );
     187                Statement * create_resume_rethrow( ThrowStmt * throwStmt );
    103188
    104189                // Types used in translation, make sure to use clone.
     
    121206
    122207        public:
    123                 ExceptionMutatorCore() :
    124                         cur_context( NoHandler ),
    125                         handler_except_decl( nullptr ),
     208                TryMutatorCore() :
    126209                        except_decl( nullptr ), node_decl( nullptr ), hook_decl( nullptr ),
    127210                        try_func_t( noQualifiers, false ),
     
    132215                {}
    133216
    134                 void premutate( CatchStmt *catchStmt );
    135217                void premutate( StructDecl *structDecl );
     218                Statement * postmutate( TryStmt *tryStmt );
    136219                Statement * postmutate( ThrowStmt *throwStmt );
    137                 Statement * postmutate( TryStmt *tryStmt );
    138220        };
    139221
    140         void ExceptionMutatorCore::init_func_types() {
     222        void TryMutatorCore::init_func_types() {
    141223                assert( except_decl );
    142224
     
    196278        }
    197279
    198         // ThrowStmt Mutation Helpers
    199 
    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 
    257280        // TryStmt Mutation Helpers
    258281
    259         CompoundStmt * ExceptionMutatorCore::take_try_block( TryStmt *tryStmt ) {
     282        CompoundStmt * TryMutatorCore::take_try_block( TryStmt *tryStmt ) {
    260283                CompoundStmt * block = tryStmt->get_block();
    261284                tryStmt->set_block( nullptr );
     
    263286        }
    264287
    265         FunctionDecl * ExceptionMutatorCore::create_try_wrapper(
     288        FunctionDecl * TryMutatorCore::create_try_wrapper(
    266289                        CompoundStmt *body ) {
    267290
     
    270293        }
    271294
    272         FunctionDecl * ExceptionMutatorCore::create_terminate_catch(
     295        FunctionDecl * TryMutatorCore::create_terminate_catch(
    273296                        CatchList &handlers ) {
    274297                std::list<CaseStmt *> handler_wrappers;
     
    350373        // Create a single check from a moddified handler.
    351374        // except_obj is referenced, modded_handler will be freed.
    352         CompoundStmt * ExceptionMutatorCore::create_single_matcher(
     375        CompoundStmt * TryMutatorCore::create_single_matcher(
    353376                        DeclarationWithType * except_obj, CatchStmt * modded_handler ) {
    354377                // {
     
    388411        }
    389412
    390         FunctionDecl * ExceptionMutatorCore::create_terminate_match(
     413        FunctionDecl * TryMutatorCore::create_terminate_match(
    391414                        CatchList &handlers ) {
    392415                // int match(exception * except) {
     
    425448        }
    426449
    427         CompoundStmt * ExceptionMutatorCore::create_terminate_caller(
     450        CompoundStmt * TryMutatorCore::create_terminate_caller(
    428451                        FunctionDecl * try_wrapper,
    429452                        FunctionDecl * terminate_catch,
     
    443466        }
    444467
    445         FunctionDecl * ExceptionMutatorCore::create_resume_handler(
     468        FunctionDecl * TryMutatorCore::create_resume_handler(
    446469                        CatchList &handlers ) {
    447470                // bool handle(exception * except) {
     
    480503        }
    481504
    482         CompoundStmt * ExceptionMutatorCore::create_resume_wrapper(
     505        CompoundStmt * TryMutatorCore::create_resume_wrapper(
    483506                        Statement * wraps,
    484507                        FunctionDecl * resume_handler ) {
     
    524547        }
    525548
    526         FunctionDecl * ExceptionMutatorCore::create_finally_wrapper(
     549        FunctionDecl * TryMutatorCore::create_finally_wrapper(
    527550                        TryStmt * tryStmt ) {
    528                 // void finally() { <finally code> }
     551                // void finally() { `finally->block` }
    529552                FinallyStmt * finally = tryStmt->get_finally();
    530553                CompoundStmt * body = finally->get_block();
     
    537560        }
    538561
    539         ObjectDecl * ExceptionMutatorCore::create_finally_hook(
     562        ObjectDecl * TryMutatorCore::create_finally_hook(
    540563                        FunctionDecl * finally_wrapper ) {
    541564                // struct __cfaehm_cleanup_hook __finally_hook
    542                 //      __attribute__((cleanup( finally_wrapper )));
     565                //      __attribute__((cleanup( `finally_wrapper` )));
    543566
    544567                // Make Cleanup Attribute.
     
    564587        }
    565588
     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
    566599        // 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 ) {
    592601                if ( !structDecl->has_body() ) {
    593602                        // Skip children?
     
    604613                        hook_decl = structDecl;
    605614                }
    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 ) {
    637618                assert( except_decl );
    638619                assert( node_decl );
     
    688669        }
    689670
    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;
    692679                mutateAll( translationUnit, translator );
    693680        }
     681
     682        void translateTries( std::list< Declaration *> & translationUnit ) {
     683                PassVisitor<TryMutatorCore> translator;
     684                mutateAll( translationUnit, translator );
     685        }
    694686}
  • src/ControlStruct/ExceptTranslate.h

    r07d867b r22f94a4  
    99// Author           : Andrew Beach
    1010// Created On       : Tus Jun 06 10:13:00 2017
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:19:23 2017
    13 // Update Count     : 4
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Tus May 19 11:47:00 2020
     13// Update Count     : 5
    1414//
    1515
     
    2121
    2222namespace 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         */
    2633}
    2734
  • src/GenPoly/InstantiateGeneric.cc

    r07d867b r22f94a4  
    99// Author           : Aaron B. Moss
    1010// Created On       : Thu Aug 04 18:33:00 2016
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Thu Aug 04 18:33:00 2016
    13 // Update Count     : 1
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed Jul 16 10:17:00 2020
     13// Update Count     : 2
    1414//
    1515#include "InstantiateGeneric.h"
     
    297297        }
    298298
     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
    299311        void GenericInstantiator::stripDtypeParams( AggregateDecl *base, std::list< TypeDecl* >& baseParams, const std::list< TypeExpr* >& typeSubs ) {
    300312                substituteMembers( base->get_members(), baseParams, typeSubs );
     
    373385                                concDecl->set_body( inst->get_baseStruct()->has_body() );
    374386                                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                                }
    376392                                concDecl->acceptMutator( *visitor ); // recursively instantiate members
    377393                                declsToAddBefore.push_back( concDecl ); // must occur before declaration is added so that member instantiations appear first
     
    423439                                concDecl->set_body( inst->get_baseUnion()->has_body() );
    424440                                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                                }
    426446                                concDecl->acceptMutator( *visitor ); // recursively instantiate members
    427447                                declsToAddBefore.push_back( concDecl ); // must occur before declaration is added so that member instantiations appear first
  • src/GenPoly/Specialize.cc

    r07d867b r22f94a4  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Dec 13 23:40:49 2019
    13 // Update Count     : 32
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thr Jul  2 17:42:00 2020
     13// Update Count     : 33
    1414//
    1515
     
    4242
    4343namespace GenPoly {
    44         struct Specialize final : public WithConstTypeSubstitution, public WithStmtsToAdd, public WithVisitorRef<Specialize> {
     44        struct Specialize final : public WithConstTypeSubstitution,
     45                        public WithDeclsToAdd, public WithVisitorRef<Specialize> {
    4546                Expression * postmutate( ApplicationExpr *applicationExpr );
    4647                Expression * postmutate( CastExpr *castExpr );
     
    248249                } // if
    249250
    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                }
    262267
    263268                // add return (or valueless expression) to the thunk
     
    270275                thunkFunc->statements->kids.push_back( appStmt );
    271276
    272                 // add thunk definition to queue of statements to add
    273                 stmtsToAddBefore.push_back( new DeclStmt( thunkFunc ) );
     277                // Add the thunk definition (converted to DeclStmt if appproprate).
     278                declsToAddBefore.push_back( thunkFunc );
    274279                // return address of thunk function as replacement expression
    275280                return new AddressExpr( new VariableExpr( thunkFunc ) );
  • src/Parser/DeclarationNode.cc

    r07d867b r22f94a4  
    1010// Created On       : Sat May 16 12:34:05 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Dec 16 15:32:22 2019
    13 // Update Count     : 1133
     12// Last Modified On : Tue Jun  9 20:26:55 2020
     13// Update Count     : 1134
    1414//
    1515
     
    11151115        // SUE's cannot have function specifiers, either
    11161116        //
    1117         //    inlne _Noreturn struct S { ... };         // disallowed
    1118         //    inlne _Noreturn enum   E { ... };         // disallowed
     1117        //    inline _Noreturn struct S { ... };                // disallowed
     1118        //    inline _Noreturn enum   E { ... };                // disallowed
    11191119        if ( funcSpecs.any() ) {
    11201120                SemanticError( this, "invalid function specifier for " );
  • src/Parser/ExpressionNode.cc

    r07d867b r22f94a4  
    1010// Created On       : Sat May 16 13:17:07 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Dec 18 21:14:58 2019
    13 // Update Count     : 981
     12// Last Modified On : Wed Jul 15 08:24:08 2020
     13// Update Count     : 1046
    1414//
    1515
     
    8585        } // if
    8686        // 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"
    8888} // lnthSuffix
    8989
     
    108108} // valueToType
    109109
     110static 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
    110121Expression * build_constantInteger( string & str ) {
    111122        static const BasicType::Kind kind[2][6] = {
    112123                // 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, },
    115126        };
    116127
     
    120131        }; // lnthsInt
    121132
    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;
    126136
    127137        int type = -1;                                                                          // 0 => short, 1 => char, 2 => int, 3 => long int, 4 => long long int, 5 => int128
     
    139149        } // if
    140150
     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
    141186        // Cannot be just "0"/"1"; sscanf stops at the suffix, if any; value goes over the wall => always generate
    142187
     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       
    143192        if ( str[0] == '0' ) {                                                          // radix character ?
    144193                dec = false;
    145194                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
    147207                        //printf( "%llx %llu\n", v, v );
    148208                } 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 );
    156217                        //printf( "%#llx %llu\n", v, v );
    157218                } 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
    159247                        //printf( "%#llo %llu\n", v, v );
    160248                } // if
    161249        } 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
    163280                //printf( "%llu\n", v );
    164281        } // if
    165282
    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 ); */
    205287
    206288        //if ( !( 0 <= type && type <= 6 ) ) { printf( "%s %lu %d %s\n", fred.c_str(), fred.length(), type, str.c_str() ); }
     
    214296        } else if ( ltype != -1 ) {                                                     // explicit length ?
    215297                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 ) );
    217302                } else {                                                                                // explicit length, (length_type)constant
    218303                        ret = new CastExpr( ret, new TypeInstType( Type::Qualifiers(), lnthsInt[Unsigned][ltype], false ), false );
     
    342427                if ( str[1] == '8' ) goto Default;                              // utf-8 characters => array of char
    343428                // 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 );
    345430                break;
    346431          case 'U':
    347                 strtype = new TypeInstType( Type::Qualifiers( Type::Const ), "char32_t", false );
     432                strtype = new TypeInstType( Type::Qualifiers( ), "char32_t", false );
    348433                break;
    349434          case 'L':
    350                 strtype = new TypeInstType( Type::Qualifiers( Type::Const ), "wchar_t", false );
     435                strtype = new TypeInstType( Type::Qualifiers( ), "wchar_t", false );
    351436                break;
    352437          Default:                                                                                      // char default string type
    353438          default:
    354                 strtype = new BasicType( Type::Qualifiers( Type::Const ), BasicType::Char );
     439                strtype = new BasicType( Type::Qualifiers( ), BasicType::Char );
    355440        } // switch
    356441        ArrayType * at = new ArrayType( noQualifiers, strtype,
  • src/Parser/ParseNode.h

    r07d867b r22f94a4  
    1010// Created On       : Sat May 16 13:28:16 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Feb  7 17:56:02 2020
    13 // Update Count     : 891
     12// Last Modified On : Mon Jul  6 09:33:32 2020
     13// Update Count     : 892
    1414//
    1515
     
    8686class InitializerNode : public ParseNode {
    8787  public:
    88         InitializerNode( ExpressionNode *, bool aggrp = false,  ExpressionNode * des = nullptr );
     88        InitializerNode( ExpressionNode *, bool aggrp = false, ExpressionNode * des = nullptr );
    8989        InitializerNode( InitializerNode *, bool aggrp = false, ExpressionNode * des = nullptr );
    9090        InitializerNode( bool isDelete );
  • src/Parser/module.mk

    r07d867b r22f94a4  
    1717BUILT_SOURCES = Parser/parser.hh
    1818
    19 AM_YFLAGS = -d -t -v
     19AM_YFLAGS = -d -t -v -Wno-yacc
    2020
    2121SRC += \
  • src/Parser/parser.yy

    r07d867b r22f94a4  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Apr 27 12:25:42 2020
    13 // Update Count     : 4483
     12// Last Modified On : Thu May 28 12:11:45 2020
     13// Update Count     : 4500
    1414//
    1515
     
    329329%type<en> conditional_expression                constant_expression                     assignment_expression           assignment_expression_opt
    330330%type<en> comma_expression                              comma_expression_opt
    331 %type<en> argument_expression_list              argument_expression                     default_initialize_opt
     331%type<en> argument_expression_list_opt          argument_expression                     default_initialize_opt
    332332%type<ifctl> if_control_expression
    333333%type<fctl> for_control_expression              for_control_expression_list
     
    624624                // equivalent to the old x[i,j].
    625625                { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, $3 ) ); }
    626         | postfix_expression '{' argument_expression_list '}' // CFA, constructor call
     626        | postfix_expression '{' argument_expression_list_opt '}' // CFA, constructor call
    627627                {
    628628                        Token fn;
     
    630630                        $$ = new ExpressionNode( new ConstructorExpr( build_func( new ExpressionNode( build_varref( fn ) ), (ExpressionNode *)( $1 )->set_last( $3 ) ) ) );
    631631                }
    632         | postfix_expression '(' argument_expression_list ')'
     632        | postfix_expression '(' argument_expression_list_opt ')'
    633633                { $$ = new ExpressionNode( build_func( $1, $3 ) ); }
    634634        | postfix_expression '`' identifier                                     // CFA, postfix call
     
    662662        | '(' type_no_function ')' '@' '{' initializer_list_opt comma_opt '}' // CFA, explicit C compound-literal
    663663                { $$ = new ExpressionNode( build_compoundLiteral( $2, (new InitializerNode( $6, true ))->set_maybeConstructed( false ) ) ); }
    664         | '^' primary_expression '{' argument_expression_list '}' // CFA, destructor call
     664        | '^' primary_expression '{' argument_expression_list_opt '}' // CFA, destructor call
    665665                {
    666666                        Token fn;
     
    670670        ;
    671671
    672 argument_expression_list:
     672argument_expression_list_opt:
    673673        // empty
    674674                { $$ = nullptr; }
    675675        | argument_expression
    676         | argument_expression_list ',' argument_expression
     676        | argument_expression_list_opt ',' argument_expression
    677677                { $$ = (ExpressionNode *)($1->set_last( $3 )); }
    678678        ;
     
    11961196                { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), new ExpressionNode( build_constantInteger( *new string( "0" ) ) ),
    11971197                                                OperKinds::LThan, $1->clone(), new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); }
    1198         | '=' comma_expression                                                                  // CFA
     1198        | '=' comma_expression                                                          // CFA
    11991199                { $$ = forCtrl( $2, new string( DeclarationNode::anonymous.newName() ), new ExpressionNode( build_constantInteger( *new string( "0" ) ) ),
    12001200                                                OperKinds::LEThan, $2->clone(), new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); }
     
    12031203        | comma_expression inclexcl comma_expression '~' comma_expression // CFA
    12041204                { $$ = 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 ); }
    12051207        | comma_expression ';' comma_expression                         // CFA
    12061208                { $$ = forCtrl( $3, $1, new ExpressionNode( build_constantInteger( *new string( "0" ) ) ),
    12071209                                                OperKinds::LThan, $3->clone(), new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); }
    1208         | comma_expression ';' '=' comma_expression                             // CFA
     1210        | comma_expression ';' '=' comma_expression                     // CFA
    12091211                { $$ = forCtrl( $4, $1, new ExpressionNode( build_constantInteger( *new string( "0" ) ) ),
    12101212                                                OperKinds::LEThan, $4->clone(), new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); }
     
    13041306// If MUTEX becomes a general qualifier, there are shift/reduce conflicts, so change syntax to "with mutex".
    13051307mutex_statement:
    1306         MUTEX '(' argument_expression_list ')' statement
     1308        MUTEX '(' argument_expression_list_opt ')' statement
    13071309                { SemanticError( yylloc, "Mutex statement is currently unimplemented." ); $$ = nullptr; }
    13081310        ;
     
    13211323        WAITFOR '(' cast_expression ')'
    13221324                { $$ = $3; }
    1323 //      | WAITFOR '(' cast_expression ',' argument_expression_list ')'
     1325//      | WAITFOR '(' cast_expression ',' argument_expression_list_opt ')'
    13241326//              { $$ = (ExpressionNode *)$3->set_last( $5 ); }
    1325         | WAITFOR '(' cast_expression_list ':' argument_expression_list ')'
     1327        | WAITFOR '(' cast_expression_list ':' argument_expression_list_opt ')'
    13261328                { $$ = (ExpressionNode *)($3->set_last( $5 )); }
    13271329        ;
     
    13301332        cast_expression
    13311333        | 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; }
    13331336        ;
    13341337
     
    20952098
    20962099aggregate_control:                                                                              // CFA
    2097         GENERATOR
     2100        MONITOR
     2101                { yyy = true; $$ = AggregateDecl::Monitor; }
     2102        | MUTEX STRUCT
     2103                { yyy = true; $$ = AggregateDecl::Monitor; }
     2104        | GENERATOR
    20982105                { yyy = true; $$ = AggregateDecl::Generator; }
    2099         | MONITOR GENERATOR
     2106        | MUTEX GENERATOR
    21002107                { SemanticError( yylloc, "monitor generator is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }
    21012108        | COROUTINE
    21022109                { yyy = true; $$ = AggregateDecl::Coroutine; }
    2103         | MONITOR
    2104                 { yyy = true; $$ = AggregateDecl::Monitor; }
    2105         | MONITOR COROUTINE
     2110        | MUTEX COROUTINE
    21062111                { SemanticError( yylloc, "monitor coroutine is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }
    21072112        | THREAD
    21082113                { yyy = true; $$ = AggregateDecl::Thread; }
    2109         | MONITOR THREAD
     2114        | MUTEX THREAD
    21102115                { SemanticError( yylloc, "monitor thread is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }
    21112116        ;
     
    27742779        | attr_name
    27752780                { $$ = DeclarationNode::newAttribute( $1 ); }
    2776         | attr_name '(' argument_expression_list ')'
     2781        | attr_name '(' argument_expression_list_opt ')'
    27772782                { $$ = DeclarationNode::newAttribute( $1, $3 ); }
    27782783        ;
  • src/ResolvExpr/AlternativeFinder.cc

    r07d867b r22f94a4  
    12161216                        unify( castExpr->result, alt.expr->result, alt.env, needAssertions,
    12171217                                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 );
    12201222                        PRINT(
    12211223                                std::cerr << "working on cast with result: " << castExpr->result << std::endl;
     
    16981700
    16991701                                // 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;
    17011704                                // xxx - do some inspecting on this line... why isn't result bound to initAlt.type?
    17021705
    1703                                 Cost thisCost = castCost( alt.expr->result, toType, alt.expr->get_lvalue(),
     1706                                Cost thisCost = computeConversionCost( alt.expr->result, toType, alt.expr->get_lvalue(),
    17041707                                        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                               
    17051721                                if ( thisCost != Cost::infinity ) {
    17061722                                        // count one safe conversion for each value that is thrown away
  • src/ResolvExpr/ConversionCost.cc

    r07d867b r22f94a4  
    1010// Created On       : Sun May 17 07:06:19 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Oct  4 14:45:00 2019
     12// Last Modified On : Wed Jul 29 16:11:00 2020
    1313// Update Count     : 28
    1414//
     
    392392        void ConversionCost::postvisit( const FunctionType * ) {}
    393393
    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                         } // if
    400                 } // if
    401                 */
    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                         } // if
    410                 } // if
    411                 */
    412         }
    413 
    414394        void ConversionCost::postvisit( const EnumInstType * ) {
    415395                static Type::Qualifiers q;
     
    685665}
    686666
    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 
    709667void ConversionCost_new::postvisit( const ast::EnumInstType * enumInstType ) {
    710668        (void)enumInstType;
  • src/ResolvExpr/ConversionCost.h

    r07d867b r22f94a4  
    1010// Created On       : Sun May 17 09:37:28 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Oct  4 14:59:00 2019
     12// Last Modified On : Wed Jul 29 16:12:00 2020
    1313// Update Count     : 7
    1414//
     
    5151                void postvisit( const ReferenceType * refType );
    5252                void postvisit( const FunctionType * functionType );
    53                 void postvisit( const StructInstType * aggregateUseType );
    54                 void postvisit( const UnionInstType * aggregateUseType );
    5553                void postvisit( const EnumInstType * aggregateUseType );
    5654                void postvisit( const TraitInstType * aggregateUseType );
     
    105103        void postvisit( const ast::ReferenceType * refType );
    106104        void postvisit( const ast::FunctionType * functionType );
    107         void postvisit( const ast::StructInstType * structInstType );
    108         void postvisit( const ast::UnionInstType * unionInstType );
    109105        void postvisit( const ast::EnumInstType * enumInstType );
    110106        void postvisit( const ast::TraitInstType * traitInstType );
  • src/SynTree/Expression.h

    r07d867b r22f94a4  
    206206  public:
    207207        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;
    209219
    210220        CastExpr( Expression * arg, bool isGenerated = true );
  • src/Virtual/ExpandCasts.cc

    r07d867b r22f94a4  
    1010// Created On       : Mon Jul 24 13:59:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tus Aug  2 14:59:00 2017
    13 // Update Count     : 1
     12// Last Modified On : Fri Jul 31 10:29:00 2020
     13// Update Count     : 4
    1414//
    1515
     
    1818#include <cassert>                 // for assert, assertf
    1919#include <iterator>                // for back_inserter, inserter
    20 #include <map>                     // for map, _Rb_tree_iterator, map<>::ite...
    2120#include <string>                  // for string, allocator, operator==, ope...
    22 #include <utility>                 // for pair
    2321
    2422#include "Common/PassVisitor.h"    // for PassVisitor
     23#include "Common/ScopedMap.h"      // for ScopedMap
    2524#include "Common/SemanticError.h"  // for SemanticError
     25#include "SymTab/Mangler.h"        // for mangleType
    2626#include "SynTree/Declaration.h"   // for ObjectDecl, StructDecl, FunctionDecl
    2727#include "SynTree/Expression.h"    // for VirtualCastExpr, CastExpr, Address...
     
    3131
    3232namespace 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        };
    3367
    3468        /* Currently virtual depends on the rather brittle name matching between
     
    3973         */
    4074
     75        namespace {
     76
    4177        std::string get_vtable_name( std::string const & name ) {
    4278                return name + "_vtable";
     
    5389        std::string get_vtable_inst_name_root( std::string const & name ) {
    5490                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" );
    5991        }
    6092
     
    6496        }
    6597
     98        } // namespace
     99
    66100        class VirtualCastCore {
    67         std::map<std::string, ObjectDecl *> vtable_instances;
    68         FunctionDecl *vcast_decl;
    69         StructDecl *pvt_decl;
    70 
    71101                Type * pointer_to_pvt(int level_of_indirection) {
    72102                        Type * type = new StructInstType(
     
    80110        public:
    81111                VirtualCastCore() :
    82                         vtable_instances(), vcast_decl( nullptr ), pvt_decl( nullptr )
     112                        indexer(), vcast_decl( nullptr ), pvt_decl( nullptr )
    83113                {}
    84114
     
    88118
    89119                Expression * postmutate( VirtualCastExpr * castExpr );
     120
     121                VirtualTableMap indexer;
     122        private:
     123                FunctionDecl *vcast_decl;
     124                StructDecl *pvt_decl;
    90125        };
    91126
     
    107142        void VirtualCastCore::premutate( ObjectDecl * objectDecl ) {
    108143                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
    112223
    113224        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." );
    115226
    116227                assert( vcast_decl );
    117228                assert( pvt_decl );
    118229
    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                }
    140236
    141237                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                                 //      ),
    149238                        new ApplicationExpr( VariableExpr::functionPointer( vcast_decl ), {
    150239                                        new CastExpr(
     
    163252                castExpr->set_result( nullptr );
    164253                delete castExpr;
     254                delete vtable_type;
    165255                return result;
    166256        }
  • src/main.cc

    r07d867b r22f94a4  
    99// Author           : Peter Buhr and Rob Schluntz
    1010// Created On       : Fri May 15 23:12:02 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Feb  8 08:33:50 2020
    13 // Update Count     : 633
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Tue May 19 12:03:00 2020
     13// Update Count     : 634
    1414//
    1515
     
    312312                } // if
    313313
     314                PASS( "Translate Throws", ControlStruct::translateThrows( translationUnit ) );
    314315                PASS( "Fix Labels", ControlStruct::fixLabels( translationUnit ) );
    315316                PASS( "Fix Names", CodeGen::fixNames( translationUnit ) );
     
    360361                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
    361362
    362                 PASS( "Translate EHM" , ControlStruct::translateEHM( translationUnit ) );
     363                PASS( "Translate Tries" , ControlStruct::translateTries( translationUnit ) );
    363364
    364365                PASS( "Gen Waitfor" , Concurrency::generateWaitFor( translationUnit ) );
  • tests/.expect/alloc.txt

    r07d867b r22f94a4  
    30300xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef
    3131CFA realloc array alloc, fill
    32 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede
     320xdeadbeef 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
    3333CFA realloc array alloc, fill
    34340xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef
    3535CFA realloc array alloc, fill
    36 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede
     360xdeadbeef 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
    3737
    3838C   memalign 42 42.5
  • tests/.expect/bitmanip3.x64.txt

    r07d867b r22f94a4  
    404404
    405405signed char
    406 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(-2, 0) = 0
    407406floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(-3, 1) = -3
    408407floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(-4, 2) = -4
     
    415414
    416415unsigned char
    417 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(254, 0) = 0
    418416floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(253, 1) = 253
    419417floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(252, 2) = 252
     
    426424
    427425short int
    428 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(-2, 0) = 0
    429426floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(-3, 1) = -3
    430427floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(-4, 2) = -4
     
    445442
    446443unsigned short int
    447 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(65534, 0) = 0
    448444floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(65533, 1) = 65533
    449445floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(65532, 2) = 65532
     
    464460
    465461int
    466 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(-2, 0) = 0
    467462floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(-3, 1) = -3
    468463floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(-4, 2) = -4
     
    499494
    500495unsigned int
    501 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(4294967294, 0) = 0
    502496floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(4294967293, 1) = 4294967293
    503497floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(4294967292, 2) = 4294967292
     
    534528
    535529long int
    536 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(-2, 0) = 0
    537530floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(-3, 1) = -3
    538531floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(-4, 2) = -4
     
    601594
    602595unsigned long int
    603 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(18446744073709551614, 0) = 0
    604596floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(18446744073709551613, 1) = 18446744073709551613
    605597floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(18446744073709551612, 2) = 18446744073709551612
     
    668660
    669661long long int
    670 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(-2, 0) = 0
    671662floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(-3, 1) = -3
    672663floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(-4, 2) = -4
     
    735726
    736727unsigned long long int
    737 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(18446744073709551614, 0) = 0
    738728floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(18446744073709551613, 1) = 18446744073709551613
    739729floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(18446744073709551612, 2) = 18446744073709551612
     
    11961186
    11971187signed char
    1198 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(-2, 0) = 0
    11991188ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(-3, 1) = -3
    12001189ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(-4, 2) = -4
     
    12071196
    12081197unsigned char
    1209 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(254, 0) = 0
    12101198ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(253, 1) = 253
    12111199ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(252, 2) = 252
     
    12181206
    12191207short int
    1220 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(-2, 0) = 0
    12211208ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(-3, 1) = -3
    12221209ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(-4, 2) = -4
     
    12371224
    12381225unsigned short int
    1239 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(65534, 0) = 0
    12401226ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(65533, 1) = 65533
    12411227ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(65532, 2) = 65532
     
    12561242
    12571243int
    1258 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(-2, 0) = 0
    12591244ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(-3, 1) = -3
    12601245ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(-4, 2) = -4
     
    12911276
    12921277unsigned int
    1293 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(4294967294, 0) = 0
    12941278ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(4294967293, 1) = 4294967293
    12951279ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(4294967292, 2) = 4294967292
     
    13261310
    13271311long int
    1328 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(-2, 0) = 0
    13291312ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(-3, 1) = -3
    13301313ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(-4, 2) = -4
     
    13931376
    13941377unsigned long int
    1395 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(18446744073709551614, 0) = 0
    13961378ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(18446744073709551613, 1) = 18446744073709551613
    13971379ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(18446744073709551612, 2) = 18446744073709551612
     
    14601442
    14611443long long int
    1462 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(-2, 0) = 0
    14631444ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(-3, 1) = -3
    14641445ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(-4, 2) = -4
     
    15271508
    15281509unsigned long long int
    1529 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(18446744073709551614, 0) = 0
    15301510ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(18446744073709551613, 1) = 18446744073709551613
    15311511ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(18446744073709551612, 2) = 18446744073709551612
     
    15941574
    15951575
     1576ceiling_div
     1577
     1578signed char
     1579ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(-3, 1) = -3
     1580ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(-4, 2) = -1
     1581ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(-6, 4) = 0
     1582ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(-10, 8) = 0
     1583ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(-18, 16) = 0
     1584ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(-34, 32) = 0
     1585ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(-66, 64) = 0
     1586ceiling_div(-128, -128) = 2, ceiling_div(-126, -128) = 1, ceiling_div(126, -128) = 0
     1587
     1588unsigned char
     1589ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(253, 1) = 253
     1590ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(252, 2) = 126
     1591ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(250, 4) = 63
     1592ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(246, 8) = 31
     1593ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(238, 16) = 15
     1594ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(222, 32) = 7
     1595ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(190, 64) = 3
     1596ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(126, 128) = 1
     1597
     1598short int
     1599ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(-3, 1) = -3
     1600ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(-4, 2) = -1
     1601ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(-6, 4) = 0
     1602ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(-10, 8) = 0
     1603ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(-18, 16) = 0
     1604ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(-34, 32) = 0
     1605ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(-66, 64) = 0
     1606ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(-130, 128) = 0
     1607ceiling_div(256, 256) = 1, ceiling_div(258, 256) = 2, ceiling_div(-258, 256) = 0
     1608ceiling_div(512, 512) = 1, ceiling_div(514, 512) = 2, ceiling_div(-514, 512) = 0
     1609ceiling_div(1024, 1024) = 1, ceiling_div(1026, 1024) = 2, ceiling_div(-1026, 1024) = 0
     1610ceiling_div(2048, 2048) = 1, ceiling_div(2050, 2048) = 2, ceiling_div(-2050, 2048) = 0
     1611ceiling_div(4096, 4096) = 1, ceiling_div(4098, 4096) = 2, ceiling_div(-4098, 4096) = 0
     1612ceiling_div(8192, 8192) = 1, ceiling_div(8194, 8192) = 2, ceiling_div(-8194, 8192) = 0
     1613ceiling_div(16384, 16384) = 1, ceiling_div(16386, 16384) = 2, ceiling_div(-16386, 16384) = 0
     1614ceiling_div(-32768, -32768) = 2, ceiling_div(-32766, -32768) = 1, ceiling_div(32766, -32768) = 0
     1615
     1616unsigned short int
     1617ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(65533, 1) = 65533
     1618ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(65532, 2) = 32766
     1619ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(65530, 4) = 16383
     1620ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(65526, 8) = 8191
     1621ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(65518, 16) = 4095
     1622ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(65502, 32) = 2047
     1623ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(65470, 64) = 1023
     1624ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(65406, 128) = 511
     1625ceiling_div(256, 256) = 1, ceiling_div(258, 256) = 2, ceiling_div(65278, 256) = 255
     1626ceiling_div(512, 512) = 1, ceiling_div(514, 512) = 2, ceiling_div(65022, 512) = 127
     1627ceiling_div(1024, 1024) = 1, ceiling_div(1026, 1024) = 2, ceiling_div(64510, 1024) = 63
     1628ceiling_div(2048, 2048) = 1, ceiling_div(2050, 2048) = 2, ceiling_div(63486, 2048) = 31
     1629ceiling_div(4096, 4096) = 1, ceiling_div(4098, 4096) = 2, ceiling_div(61438, 4096) = 15
     1630ceiling_div(8192, 8192) = 1, ceiling_div(8194, 8192) = 2, ceiling_div(57342, 8192) = 7
     1631ceiling_div(16384, 16384) = 1, ceiling_div(16386, 16384) = 2, ceiling_div(49150, 16384) = 3
     1632ceiling_div(32768, 32768) = 1, ceiling_div(32770, 32768) = 2, ceiling_div(32766, 32768) = 1
     1633
     1634int
     1635ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(-3, 1) = -3
     1636ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(-4, 2) = -1
     1637ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(-6, 4) = 0
     1638ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(-10, 8) = 0
     1639ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(-18, 16) = 0
     1640ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(-34, 32) = 0
     1641ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(-66, 64) = 0
     1642ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(-130, 128) = 0
     1643ceiling_div(256, 256) = 1, ceiling_div(258, 256) = 2, ceiling_div(-258, 256) = 0
     1644ceiling_div(512, 512) = 1, ceiling_div(514, 512) = 2, ceiling_div(-514, 512) = 0
     1645ceiling_div(1024, 1024) = 1, ceiling_div(1026, 1024) = 2, ceiling_div(-1026, 1024) = 0
     1646ceiling_div(2048, 2048) = 1, ceiling_div(2050, 2048) = 2, ceiling_div(-2050, 2048) = 0
     1647ceiling_div(4096, 4096) = 1, ceiling_div(4098, 4096) = 2, ceiling_div(-4098, 4096) = 0
     1648ceiling_div(8192, 8192) = 1, ceiling_div(8194, 8192) = 2, ceiling_div(-8194, 8192) = 0
     1649ceiling_div(16384, 16384) = 1, ceiling_div(16386, 16384) = 2, ceiling_div(-16386, 16384) = 0
     1650ceiling_div(32768, 32768) = 1, ceiling_div(32770, 32768) = 2, ceiling_div(-32770, 32768) = 0
     1651ceiling_div(65536, 65536) = 1, ceiling_div(65538, 65536) = 2, ceiling_div(-65538, 65536) = 0
     1652ceiling_div(131072, 131072) = 1, ceiling_div(131074, 131072) = 2, ceiling_div(-131074, 131072) = 0
     1653ceiling_div(262144, 262144) = 1, ceiling_div(262146, 262144) = 2, ceiling_div(-262146, 262144) = 0
     1654ceiling_div(524288, 524288) = 1, ceiling_div(524290, 524288) = 2, ceiling_div(-524290, 524288) = 0
     1655ceiling_div(1048576, 1048576) = 1, ceiling_div(1048578, 1048576) = 2, ceiling_div(-1048578, 1048576) = 0
     1656ceiling_div(2097152, 2097152) = 1, ceiling_div(2097154, 2097152) = 2, ceiling_div(-2097154, 2097152) = 0
     1657ceiling_div(4194304, 4194304) = 1, ceiling_div(4194306, 4194304) = 2, ceiling_div(-4194306, 4194304) = 0
     1658ceiling_div(8388608, 8388608) = 1, ceiling_div(8388610, 8388608) = 2, ceiling_div(-8388610, 8388608) = 0
     1659ceiling_div(16777216, 16777216) = 1, ceiling_div(16777218, 16777216) = 2, ceiling_div(-16777218, 16777216) = 0
     1660ceiling_div(33554432, 33554432) = 1, ceiling_div(33554434, 33554432) = 2, ceiling_div(-33554434, 33554432) = 0
     1661ceiling_div(67108864, 67108864) = 1, ceiling_div(67108866, 67108864) = 2, ceiling_div(-67108866, 67108864) = 0
     1662ceiling_div(134217728, 134217728) = 1, ceiling_div(134217730, 134217728) = 2, ceiling_div(-134217730, 134217728) = 0
     1663ceiling_div(268435456, 268435456) = 1, ceiling_div(268435458, 268435456) = 2, ceiling_div(-268435458, 268435456) = 0
     1664ceiling_div(536870912, 536870912) = 1, ceiling_div(536870914, 536870912) = 2, ceiling_div(-536870914, 536870912) = 0
     1665ceiling_div(1073741824, 1073741824) = 1, ceiling_div(1073741826, 1073741824) = -1, ceiling_div(-1073741826, 1073741824) = 0
     1666ceiling_div(-2147483648, -2147483648) = 0, ceiling_div(-2147483646, -2147483648) = 0, ceiling_div(2147483646, -2147483648) = 0
     1667
     1668unsigned int
     1669ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(4294967293, 1) = 4294967293
     1670ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(4294967292, 2) = 2147483646
     1671ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(4294967290, 4) = 1073741823
     1672ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(4294967286, 8) = 536870911
     1673ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(4294967278, 16) = 268435455
     1674ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(4294967262, 32) = 134217727
     1675ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(4294967230, 64) = 67108863
     1676ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(4294967166, 128) = 33554431
     1677ceiling_div(256, 256) = 1, ceiling_div(258, 256) = 2, ceiling_div(4294967038, 256) = 16777215
     1678ceiling_div(512, 512) = 1, ceiling_div(514, 512) = 2, ceiling_div(4294966782, 512) = 8388607
     1679ceiling_div(1024, 1024) = 1, ceiling_div(1026, 1024) = 2, ceiling_div(4294966270, 1024) = 4194303
     1680ceiling_div(2048, 2048) = 1, ceiling_div(2050, 2048) = 2, ceiling_div(4294965246, 2048) = 2097151
     1681ceiling_div(4096, 4096) = 1, ceiling_div(4098, 4096) = 2, ceiling_div(4294963198, 4096) = 1048575
     1682ceiling_div(8192, 8192) = 1, ceiling_div(8194, 8192) = 2, ceiling_div(4294959102, 8192) = 524287
     1683ceiling_div(16384, 16384) = 1, ceiling_div(16386, 16384) = 2, ceiling_div(4294950910, 16384) = 262143
     1684ceiling_div(32768, 32768) = 1, ceiling_div(32770, 32768) = 2, ceiling_div(4294934526, 32768) = 131071
     1685ceiling_div(65536, 65536) = 1, ceiling_div(65538, 65536) = 2, ceiling_div(4294901758, 65536) = 65535
     1686ceiling_div(131072, 131072) = 1, ceiling_div(131074, 131072) = 2, ceiling_div(4294836222, 131072) = 32767
     1687ceiling_div(262144, 262144) = 1, ceiling_div(262146, 262144) = 2, ceiling_div(4294705150, 262144) = 16383
     1688ceiling_div(524288, 524288) = 1, ceiling_div(524290, 524288) = 2, ceiling_div(4294443006, 524288) = 8191
     1689ceiling_div(1048576, 1048576) = 1, ceiling_div(1048578, 1048576) = 2, ceiling_div(4293918718, 1048576) = 4095
     1690ceiling_div(2097152, 2097152) = 1, ceiling_div(2097154, 2097152) = 2, ceiling_div(4292870142, 2097152) = 2047
     1691ceiling_div(4194304, 4194304) = 1, ceiling_div(4194306, 4194304) = 2, ceiling_div(4290772990, 4194304) = 1023
     1692ceiling_div(8388608, 8388608) = 1, ceiling_div(8388610, 8388608) = 2, ceiling_div(4286578686, 8388608) = 511
     1693ceiling_div(16777216, 16777216) = 1, ceiling_div(16777218, 16777216) = 2, ceiling_div(4278190078, 16777216) = 255
     1694ceiling_div(33554432, 33554432) = 1, ceiling_div(33554434, 33554432) = 2, ceiling_div(4261412862, 33554432) = 127
     1695ceiling_div(67108864, 67108864) = 1, ceiling_div(67108866, 67108864) = 2, ceiling_div(4227858430, 67108864) = 63
     1696ceiling_div(134217728, 134217728) = 1, ceiling_div(134217730, 134217728) = 2, ceiling_div(4160749566, 134217728) = 31
     1697ceiling_div(268435456, 268435456) = 1, ceiling_div(268435458, 268435456) = 2, ceiling_div(4026531838, 268435456) = 15
     1698ceiling_div(536870912, 536870912) = 1, ceiling_div(536870914, 536870912) = 2, ceiling_div(3758096382, 536870912) = 7
     1699ceiling_div(1073741824, 1073741824) = 1, ceiling_div(1073741826, 1073741824) = 2, ceiling_div(3221225470, 1073741824) = 3
     1700ceiling_div(2147483648, 2147483648) = 1, ceiling_div(2147483650, 2147483648) = 0, ceiling_div(2147483646, 2147483648) = 1
     1701
     1702long int
     1703ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(-3, 1) = -3
     1704ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(-4, 2) = -1
     1705ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(-6, 4) = 0
     1706ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(-10, 8) = 0
     1707ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(-18, 16) = 0
     1708ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(-34, 32) = 0
     1709ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(-66, 64) = 0
     1710ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(-130, 128) = 0
     1711ceiling_div(256, 256) = 1, ceiling_div(258, 256) = 2, ceiling_div(-258, 256) = 0
     1712ceiling_div(512, 512) = 1, ceiling_div(514, 512) = 2, ceiling_div(-514, 512) = 0
     1713ceiling_div(1024, 1024) = 1, ceiling_div(1026, 1024) = 2, ceiling_div(-1026, 1024) = 0
     1714ceiling_div(2048, 2048) = 1, ceiling_div(2050, 2048) = 2, ceiling_div(-2050, 2048) = 0
     1715ceiling_div(4096, 4096) = 1, ceiling_div(4098, 4096) = 2, ceiling_div(-4098, 4096) = 0
     1716ceiling_div(8192, 8192) = 1, ceiling_div(8194, 8192) = 2, ceiling_div(-8194, 8192) = 0
     1717ceiling_div(16384, 16384) = 1, ceiling_div(16386, 16384) = 2, ceiling_div(-16386, 16384) = 0
     1718ceiling_div(32768, 32768) = 1, ceiling_div(32770, 32768) = 2, ceiling_div(-32770, 32768) = 0
     1719ceiling_div(65536, 65536) = 1, ceiling_div(65538, 65536) = 2, ceiling_div(-65538, 65536) = 0
     1720ceiling_div(131072, 131072) = 1, ceiling_div(131074, 131072) = 2, ceiling_div(-131074, 131072) = 0
     1721ceiling_div(262144, 262144) = 1, ceiling_div(262146, 262144) = 2, ceiling_div(-262146, 262144) = 0
     1722ceiling_div(524288, 524288) = 1, ceiling_div(524290, 524288) = 2, ceiling_div(-524290, 524288) = 0
     1723ceiling_div(1048576, 1048576) = 1, ceiling_div(1048578, 1048576) = 2, ceiling_div(-1048578, 1048576) = 0
     1724ceiling_div(2097152, 2097152) = 1, ceiling_div(2097154, 2097152) = 2, ceiling_div(-2097154, 2097152) = 0
     1725ceiling_div(4194304, 4194304) = 1, ceiling_div(4194306, 4194304) = 2, ceiling_div(-4194306, 4194304) = 0
     1726ceiling_div(8388608, 8388608) = 1, ceiling_div(8388610, 8388608) = 2, ceiling_div(-8388610, 8388608) = 0
     1727ceiling_div(16777216, 16777216) = 1, ceiling_div(16777218, 16777216) = 2, ceiling_div(-16777218, 16777216) = 0
     1728ceiling_div(33554432, 33554432) = 1, ceiling_div(33554434, 33554432) = 2, ceiling_div(-33554434, 33554432) = 0
     1729ceiling_div(67108864, 67108864) = 1, ceiling_div(67108866, 67108864) = 2, ceiling_div(-67108866, 67108864) = 0
     1730ceiling_div(134217728, 134217728) = 1, ceiling_div(134217730, 134217728) = 2, ceiling_div(-134217730, 134217728) = 0
     1731ceiling_div(268435456, 268435456) = 1, ceiling_div(268435458, 268435456) = 2, ceiling_div(-268435458, 268435456) = 0
     1732ceiling_div(536870912, 536870912) = 1, ceiling_div(536870914, 536870912) = 2, ceiling_div(-536870914, 536870912) = 0
     1733ceiling_div(1073741824, 1073741824) = 1, ceiling_div(1073741826, 1073741824) = 2, ceiling_div(-1073741826, 1073741824) = 0
     1734ceiling_div(2147483648, 2147483648) = 1, ceiling_div(2147483650, 2147483648) = 2, ceiling_div(-2147483650, 2147483648) = 0
     1735ceiling_div(4294967296, 4294967296) = 1, ceiling_div(4294967298, 4294967296) = 2, ceiling_div(-4294967298, 4294967296) = 0
     1736ceiling_div(8589934592, 8589934592) = 1, ceiling_div(8589934594, 8589934592) = 2, ceiling_div(-8589934594, 8589934592) = 0
     1737ceiling_div(17179869184, 17179869184) = 1, ceiling_div(17179869186, 17179869184) = 2, ceiling_div(-17179869186, 17179869184) = 0
     1738ceiling_div(34359738368, 34359738368) = 1, ceiling_div(34359738370, 34359738368) = 2, ceiling_div(-34359738370, 34359738368) = 0
     1739ceiling_div(68719476736, 68719476736) = 1, ceiling_div(68719476738, 68719476736) = 2, ceiling_div(-68719476738, 68719476736) = 0
     1740ceiling_div(137438953472, 137438953472) = 1, ceiling_div(137438953474, 137438953472) = 2, ceiling_div(-137438953474, 137438953472) = 0
     1741ceiling_div(274877906944, 274877906944) = 1, ceiling_div(274877906946, 274877906944) = 2, ceiling_div(-274877906946, 274877906944) = 0
     1742ceiling_div(549755813888, 549755813888) = 1, ceiling_div(549755813890, 549755813888) = 2, ceiling_div(-549755813890, 549755813888) = 0
     1743ceiling_div(1099511627776, 1099511627776) = 1, ceiling_div(1099511627778, 1099511627776) = 2, ceiling_div(-1099511627778, 1099511627776) = 0
     1744ceiling_div(2199023255552, 2199023255552) = 1, ceiling_div(2199023255554, 2199023255552) = 2, ceiling_div(-2199023255554, 2199023255552) = 0
     1745ceiling_div(4398046511104, 4398046511104) = 1, ceiling_div(4398046511106, 4398046511104) = 2, ceiling_div(-4398046511106, 4398046511104) = 0
     1746ceiling_div(8796093022208, 8796093022208) = 1, ceiling_div(8796093022210, 8796093022208) = 2, ceiling_div(-8796093022210, 8796093022208) = 0
     1747ceiling_div(17592186044416, 17592186044416) = 1, ceiling_div(17592186044418, 17592186044416) = 2, ceiling_div(-17592186044418, 17592186044416) = 0
     1748ceiling_div(35184372088832, 35184372088832) = 1, ceiling_div(35184372088834, 35184372088832) = 2, ceiling_div(-35184372088834, 35184372088832) = 0
     1749ceiling_div(70368744177664, 70368744177664) = 1, ceiling_div(70368744177666, 70368744177664) = 2, ceiling_div(-70368744177666, 70368744177664) = 0
     1750ceiling_div(140737488355328, 140737488355328) = 1, ceiling_div(140737488355330, 140737488355328) = 2, ceiling_div(-140737488355330, 140737488355328) = 0
     1751ceiling_div(281474976710656, 281474976710656) = 1, ceiling_div(281474976710658, 281474976710656) = 2, ceiling_div(-281474976710658, 281474976710656) = 0
     1752ceiling_div(562949953421312, 562949953421312) = 1, ceiling_div(562949953421314, 562949953421312) = 2, ceiling_div(-562949953421314, 562949953421312) = 0
     1753ceiling_div(1125899906842624, 1125899906842624) = 1, ceiling_div(1125899906842626, 1125899906842624) = 2, ceiling_div(-1125899906842626, 1125899906842624) = 0
     1754ceiling_div(2251799813685248, 2251799813685248) = 1, ceiling_div(2251799813685250, 2251799813685248) = 2, ceiling_div(-2251799813685250, 2251799813685248) = 0
     1755ceiling_div(4503599627370496, 4503599627370496) = 1, ceiling_div(4503599627370498, 4503599627370496) = 2, ceiling_div(-4503599627370498, 4503599627370496) = 0
     1756ceiling_div(9007199254740992, 9007199254740992) = 1, ceiling_div(9007199254740994, 9007199254740992) = 2, ceiling_div(-9007199254740994, 9007199254740992) = 0
     1757ceiling_div(18014398509481984, 18014398509481984) = 1, ceiling_div(18014398509481986, 18014398509481984) = 2, ceiling_div(-18014398509481986, 18014398509481984) = 0
     1758ceiling_div(36028797018963968, 36028797018963968) = 1, ceiling_div(36028797018963970, 36028797018963968) = 2, ceiling_div(-36028797018963970, 36028797018963968) = 0
     1759ceiling_div(72057594037927936, 72057594037927936) = 1, ceiling_div(72057594037927938, 72057594037927936) = 2, ceiling_div(-72057594037927938, 72057594037927936) = 0
     1760ceiling_div(144115188075855872, 144115188075855872) = 1, ceiling_div(144115188075855874, 144115188075855872) = 2, ceiling_div(-144115188075855874, 144115188075855872) = 0
     1761ceiling_div(288230376151711744, 288230376151711744) = 1, ceiling_div(288230376151711746, 288230376151711744) = 2, ceiling_div(-288230376151711746, 288230376151711744) = 0
     1762ceiling_div(576460752303423488, 576460752303423488) = 1, ceiling_div(576460752303423490, 576460752303423488) = 2, ceiling_div(-576460752303423490, 576460752303423488) = 0
     1763ceiling_div(1152921504606846976, 1152921504606846976) = 1, ceiling_div(1152921504606846978, 1152921504606846976) = 2, ceiling_div(-1152921504606846978, 1152921504606846976) = 0
     1764ceiling_div(2305843009213693952, 2305843009213693952) = 1, ceiling_div(2305843009213693954, 2305843009213693952) = 2, ceiling_div(-2305843009213693954, 2305843009213693952) = 0
     1765ceiling_div(4611686018427387904, 4611686018427387904) = 1, ceiling_div(4611686018427387906, 4611686018427387904) = -1, ceiling_div(-4611686018427387906, 4611686018427387904) = 0
     1766ceiling_div(-9223372036854775808, -9223372036854775808) = 0, ceiling_div(-9223372036854775806, -9223372036854775808) = 0, ceiling_div(9223372036854775806, -9223372036854775808) = 0
     1767
     1768unsigned long int
     1769ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(18446744073709551613, 1) = 18446744073709551613
     1770ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(18446744073709551612, 2) = 9223372036854775806
     1771ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(18446744073709551610, 4) = 4611686018427387903
     1772ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(18446744073709551606, 8) = 2305843009213693951
     1773ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(18446744073709551598, 16) = 1152921504606846975
     1774ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(18446744073709551582, 32) = 576460752303423487
     1775ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(18446744073709551550, 64) = 288230376151711743
     1776ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(18446744073709551486, 128) = 144115188075855871
     1777ceiling_div(256, 256) = 1, ceiling_div(258, 256) = 2, ceiling_div(18446744073709551358, 256) = 72057594037927935
     1778ceiling_div(512, 512) = 1, ceiling_div(514, 512) = 2, ceiling_div(18446744073709551102, 512) = 36028797018963967
     1779ceiling_div(1024, 1024) = 1, ceiling_div(1026, 1024) = 2, ceiling_div(18446744073709550590, 1024) = 18014398509481983
     1780ceiling_div(2048, 2048) = 1, ceiling_div(2050, 2048) = 2, ceiling_div(18446744073709549566, 2048) = 9007199254740991
     1781ceiling_div(4096, 4096) = 1, ceiling_div(4098, 4096) = 2, ceiling_div(18446744073709547518, 4096) = 4503599627370495
     1782ceiling_div(8192, 8192) = 1, ceiling_div(8194, 8192) = 2, ceiling_div(18446744073709543422, 8192) = 2251799813685247
     1783ceiling_div(16384, 16384) = 1, ceiling_div(16386, 16384) = 2, ceiling_div(18446744073709535230, 16384) = 1125899906842623
     1784ceiling_div(32768, 32768) = 1, ceiling_div(32770, 32768) = 2, ceiling_div(18446744073709518846, 32768) = 562949953421311
     1785ceiling_div(65536, 65536) = 1, ceiling_div(65538, 65536) = 2, ceiling_div(18446744073709486078, 65536) = 281474976710655
     1786ceiling_div(131072, 131072) = 1, ceiling_div(131074, 131072) = 2, ceiling_div(18446744073709420542, 131072) = 140737488355327
     1787ceiling_div(262144, 262144) = 1, ceiling_div(262146, 262144) = 2, ceiling_div(18446744073709289470, 262144) = 70368744177663
     1788ceiling_div(524288, 524288) = 1, ceiling_div(524290, 524288) = 2, ceiling_div(18446744073709027326, 524288) = 35184372088831
     1789ceiling_div(1048576, 1048576) = 1, ceiling_div(1048578, 1048576) = 2, ceiling_div(18446744073708503038, 1048576) = 17592186044415
     1790ceiling_div(2097152, 2097152) = 1, ceiling_div(2097154, 2097152) = 2, ceiling_div(18446744073707454462, 2097152) = 8796093022207
     1791ceiling_div(4194304, 4194304) = 1, ceiling_div(4194306, 4194304) = 2, ceiling_div(18446744073705357310, 4194304) = 4398046511103
     1792ceiling_div(8388608, 8388608) = 1, ceiling_div(8388610, 8388608) = 2, ceiling_div(18446744073701163006, 8388608) = 2199023255551
     1793ceiling_div(16777216, 16777216) = 1, ceiling_div(16777218, 16777216) = 2, ceiling_div(18446744073692774398, 16777216) = 1099511627775
     1794ceiling_div(33554432, 33554432) = 1, ceiling_div(33554434, 33554432) = 2, ceiling_div(18446744073675997182, 33554432) = 549755813887
     1795ceiling_div(67108864, 67108864) = 1, ceiling_div(67108866, 67108864) = 2, ceiling_div(18446744073642442750, 67108864) = 274877906943
     1796ceiling_div(134217728, 134217728) = 1, ceiling_div(134217730, 134217728) = 2, ceiling_div(18446744073575333886, 134217728) = 137438953471
     1797ceiling_div(268435456, 268435456) = 1, ceiling_div(268435458, 268435456) = 2, ceiling_div(18446744073441116158, 268435456) = 68719476735
     1798ceiling_div(536870912, 536870912) = 1, ceiling_div(536870914, 536870912) = 2, ceiling_div(18446744073172680702, 536870912) = 34359738367
     1799ceiling_div(1073741824, 1073741824) = 1, ceiling_div(1073741826, 1073741824) = 2, ceiling_div(18446744072635809790, 1073741824) = 17179869183
     1800ceiling_div(2147483648, 2147483648) = 1, ceiling_div(2147483650, 2147483648) = 2, ceiling_div(18446744071562067966, 2147483648) = 8589934591
     1801ceiling_div(4294967296, 4294967296) = 1, ceiling_div(4294967298, 4294967296) = 2, ceiling_div(18446744069414584318, 4294967296) = 4294967295
     1802ceiling_div(8589934592, 8589934592) = 1, ceiling_div(8589934594, 8589934592) = 2, ceiling_div(18446744065119617022, 8589934592) = 2147483647
     1803ceiling_div(17179869184, 17179869184) = 1, ceiling_div(17179869186, 17179869184) = 2, ceiling_div(18446744056529682430, 17179869184) = 1073741823
     1804ceiling_div(34359738368, 34359738368) = 1, ceiling_div(34359738370, 34359738368) = 2, ceiling_div(18446744039349813246, 34359738368) = 536870911
     1805ceiling_div(68719476736, 68719476736) = 1, ceiling_div(68719476738, 68719476736) = 2, ceiling_div(18446744004990074878, 68719476736) = 268435455
     1806ceiling_div(137438953472, 137438953472) = 1, ceiling_div(137438953474, 137438953472) = 2, ceiling_div(18446743936270598142, 137438953472) = 134217727
     1807ceiling_div(274877906944, 274877906944) = 1, ceiling_div(274877906946, 274877906944) = 2, ceiling_div(18446743798831644670, 274877906944) = 67108863
     1808ceiling_div(549755813888, 549755813888) = 1, ceiling_div(549755813890, 549755813888) = 2, ceiling_div(18446743523953737726, 549755813888) = 33554431
     1809ceiling_div(1099511627776, 1099511627776) = 1, ceiling_div(1099511627778, 1099511627776) = 2, ceiling_div(18446742974197923838, 1099511627776) = 16777215
     1810ceiling_div(2199023255552, 2199023255552) = 1, ceiling_div(2199023255554, 2199023255552) = 2, ceiling_div(18446741874686296062, 2199023255552) = 8388607
     1811ceiling_div(4398046511104, 4398046511104) = 1, ceiling_div(4398046511106, 4398046511104) = 2, ceiling_div(18446739675663040510, 4398046511104) = 4194303
     1812ceiling_div(8796093022208, 8796093022208) = 1, ceiling_div(8796093022210, 8796093022208) = 2, ceiling_div(18446735277616529406, 8796093022208) = 2097151
     1813ceiling_div(17592186044416, 17592186044416) = 1, ceiling_div(17592186044418, 17592186044416) = 2, ceiling_div(18446726481523507198, 17592186044416) = 1048575
     1814ceiling_div(35184372088832, 35184372088832) = 1, ceiling_div(35184372088834, 35184372088832) = 2, ceiling_div(18446708889337462782, 35184372088832) = 524287
     1815ceiling_div(70368744177664, 70368744177664) = 1, ceiling_div(70368744177666, 70368744177664) = 2, ceiling_div(18446673704965373950, 70368744177664) = 262143
     1816ceiling_div(140737488355328, 140737488355328) = 1, ceiling_div(140737488355330, 140737488355328) = 2, ceiling_div(18446603336221196286, 140737488355328) = 131071
     1817ceiling_div(281474976710656, 281474976710656) = 1, ceiling_div(281474976710658, 281474976710656) = 2, ceiling_div(18446462598732840958, 281474976710656) = 65535
     1818ceiling_div(562949953421312, 562949953421312) = 1, ceiling_div(562949953421314, 562949953421312) = 2, ceiling_div(18446181123756130302, 562949953421312) = 32767
     1819ceiling_div(1125899906842624, 1125899906842624) = 1, ceiling_div(1125899906842626, 1125899906842624) = 2, ceiling_div(18445618173802708990, 1125899906842624) = 16383
     1820ceiling_div(2251799813685248, 2251799813685248) = 1, ceiling_div(2251799813685250, 2251799813685248) = 2, ceiling_div(18444492273895866366, 2251799813685248) = 8191
     1821ceiling_div(4503599627370496, 4503599627370496) = 1, ceiling_div(4503599627370498, 4503599627370496) = 2, ceiling_div(18442240474082181118, 4503599627370496) = 4095
     1822ceiling_div(9007199254740992, 9007199254740992) = 1, ceiling_div(9007199254740994, 9007199254740992) = 2, ceiling_div(18437736874454810622, 9007199254740992) = 2047
     1823ceiling_div(18014398509481984, 18014398509481984) = 1, ceiling_div(18014398509481986, 18014398509481984) = 2, ceiling_div(18428729675200069630, 18014398509481984) = 1023
     1824ceiling_div(36028797018963968, 36028797018963968) = 1, ceiling_div(36028797018963970, 36028797018963968) = 2, ceiling_div(18410715276690587646, 36028797018963968) = 511
     1825ceiling_div(72057594037927936, 72057594037927936) = 1, ceiling_div(72057594037927938, 72057594037927936) = 2, ceiling_div(18374686479671623678, 72057594037927936) = 255
     1826ceiling_div(144115188075855872, 144115188075855872) = 1, ceiling_div(144115188075855874, 144115188075855872) = 2, ceiling_div(18302628885633695742, 144115188075855872) = 127
     1827ceiling_div(288230376151711744, 288230376151711744) = 1, ceiling_div(288230376151711746, 288230376151711744) = 2, ceiling_div(18158513697557839870, 288230376151711744) = 63
     1828ceiling_div(576460752303423488, 576460752303423488) = 1, ceiling_div(576460752303423490, 576460752303423488) = 2, ceiling_div(17870283321406128126, 576460752303423488) = 31
     1829ceiling_div(1152921504606846976, 1152921504606846976) = 1, ceiling_div(1152921504606846978, 1152921504606846976) = 2, ceiling_div(17293822569102704638, 1152921504606846976) = 15
     1830ceiling_div(2305843009213693952, 2305843009213693952) = 1, ceiling_div(2305843009213693954, 2305843009213693952) = 2, ceiling_div(16140901064495857662, 2305843009213693952) = 7
     1831ceiling_div(4611686018427387904, 4611686018427387904) = 1, ceiling_div(4611686018427387906, 4611686018427387904) = 2, ceiling_div(13835058055282163710, 4611686018427387904) = 3
     1832ceiling_div(9223372036854775808, 9223372036854775808) = 1, ceiling_div(9223372036854775810, 9223372036854775808) = 0, ceiling_div(9223372036854775806, 9223372036854775808) = 1
     1833
     1834long long int
     1835ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(-3, 1) = -3
     1836ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(-4, 2) = -1
     1837ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(-6, 4) = 0
     1838ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(-10, 8) = 0
     1839ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(-18, 16) = 0
     1840ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(-34, 32) = 0
     1841ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(-66, 64) = 0
     1842ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(-130, 128) = 0
     1843ceiling_div(256, 256) = 1, ceiling_div(258, 256) = 2, ceiling_div(-258, 256) = 0
     1844ceiling_div(512, 512) = 1, ceiling_div(514, 512) = 2, ceiling_div(-514, 512) = 0
     1845ceiling_div(1024, 1024) = 1, ceiling_div(1026, 1024) = 2, ceiling_div(-1026, 1024) = 0
     1846ceiling_div(2048, 2048) = 1, ceiling_div(2050, 2048) = 2, ceiling_div(-2050, 2048) = 0
     1847ceiling_div(4096, 4096) = 1, ceiling_div(4098, 4096) = 2, ceiling_div(-4098, 4096) = 0
     1848ceiling_div(8192, 8192) = 1, ceiling_div(8194, 8192) = 2, ceiling_div(-8194, 8192) = 0
     1849ceiling_div(16384, 16384) = 1, ceiling_div(16386, 16384) = 2, ceiling_div(-16386, 16384) = 0
     1850ceiling_div(32768, 32768) = 1, ceiling_div(32770, 32768) = 2, ceiling_div(-32770, 32768) = 0
     1851ceiling_div(65536, 65536) = 1, ceiling_div(65538, 65536) = 2, ceiling_div(-65538, 65536) = 0
     1852ceiling_div(131072, 131072) = 1, ceiling_div(131074, 131072) = 2, ceiling_div(-131074, 131072) = 0
     1853ceiling_div(262144, 262144) = 1, ceiling_div(262146, 262144) = 2, ceiling_div(-262146, 262144) = 0
     1854ceiling_div(524288, 524288) = 1, ceiling_div(524290, 524288) = 2, ceiling_div(-524290, 524288) = 0
     1855ceiling_div(1048576, 1048576) = 1, ceiling_div(1048578, 1048576) = 2, ceiling_div(-1048578, 1048576) = 0
     1856ceiling_div(2097152, 2097152) = 1, ceiling_div(2097154, 2097152) = 2, ceiling_div(-2097154, 2097152) = 0
     1857ceiling_div(4194304, 4194304) = 1, ceiling_div(4194306, 4194304) = 2, ceiling_div(-4194306, 4194304) = 0
     1858ceiling_div(8388608, 8388608) = 1, ceiling_div(8388610, 8388608) = 2, ceiling_div(-8388610, 8388608) = 0
     1859ceiling_div(16777216, 16777216) = 1, ceiling_div(16777218, 16777216) = 2, ceiling_div(-16777218, 16777216) = 0
     1860ceiling_div(33554432, 33554432) = 1, ceiling_div(33554434, 33554432) = 2, ceiling_div(-33554434, 33554432) = 0
     1861ceiling_div(67108864, 67108864) = 1, ceiling_div(67108866, 67108864) = 2, ceiling_div(-67108866, 67108864) = 0
     1862ceiling_div(134217728, 134217728) = 1, ceiling_div(134217730, 134217728) = 2, ceiling_div(-134217730, 134217728) = 0
     1863ceiling_div(268435456, 268435456) = 1, ceiling_div(268435458, 268435456) = 2, ceiling_div(-268435458, 268435456) = 0
     1864ceiling_div(536870912, 536870912) = 1, ceiling_div(536870914, 536870912) = 2, ceiling_div(-536870914, 536870912) = 0
     1865ceiling_div(1073741824, 1073741824) = 1, ceiling_div(1073741826, 1073741824) = 2, ceiling_div(-1073741826, 1073741824) = 0
     1866ceiling_div(2147483648, 2147483648) = 1, ceiling_div(2147483650, 2147483648) = 2, ceiling_div(-2147483650, 2147483648) = 0
     1867ceiling_div(4294967296, 4294967296) = 1, ceiling_div(4294967298, 4294967296) = 2, ceiling_div(-4294967298, 4294967296) = 0
     1868ceiling_div(8589934592, 8589934592) = 1, ceiling_div(8589934594, 8589934592) = 2, ceiling_div(-8589934594, 8589934592) = 0
     1869ceiling_div(17179869184, 17179869184) = 1, ceiling_div(17179869186, 17179869184) = 2, ceiling_div(-17179869186, 17179869184) = 0
     1870ceiling_div(34359738368, 34359738368) = 1, ceiling_div(34359738370, 34359738368) = 2, ceiling_div(-34359738370, 34359738368) = 0
     1871ceiling_div(68719476736, 68719476736) = 1, ceiling_div(68719476738, 68719476736) = 2, ceiling_div(-68719476738, 68719476736) = 0
     1872ceiling_div(137438953472, 137438953472) = 1, ceiling_div(137438953474, 137438953472) = 2, ceiling_div(-137438953474, 137438953472) = 0
     1873ceiling_div(274877906944, 274877906944) = 1, ceiling_div(274877906946, 274877906944) = 2, ceiling_div(-274877906946, 274877906944) = 0
     1874ceiling_div(549755813888, 549755813888) = 1, ceiling_div(549755813890, 549755813888) = 2, ceiling_div(-549755813890, 549755813888) = 0
     1875ceiling_div(1099511627776, 1099511627776) = 1, ceiling_div(1099511627778, 1099511627776) = 2, ceiling_div(-1099511627778, 1099511627776) = 0
     1876ceiling_div(2199023255552, 2199023255552) = 1, ceiling_div(2199023255554, 2199023255552) = 2, ceiling_div(-2199023255554, 2199023255552) = 0
     1877ceiling_div(4398046511104, 4398046511104) = 1, ceiling_div(4398046511106, 4398046511104) = 2, ceiling_div(-4398046511106, 4398046511104) = 0
     1878ceiling_div(8796093022208, 8796093022208) = 1, ceiling_div(8796093022210, 8796093022208) = 2, ceiling_div(-8796093022210, 8796093022208) = 0
     1879ceiling_div(17592186044416, 17592186044416) = 1, ceiling_div(17592186044418, 17592186044416) = 2, ceiling_div(-17592186044418, 17592186044416) = 0
     1880ceiling_div(35184372088832, 35184372088832) = 1, ceiling_div(35184372088834, 35184372088832) = 2, ceiling_div(-35184372088834, 35184372088832) = 0
     1881ceiling_div(70368744177664, 70368744177664) = 1, ceiling_div(70368744177666, 70368744177664) = 2, ceiling_div(-70368744177666, 70368744177664) = 0
     1882ceiling_div(140737488355328, 140737488355328) = 1, ceiling_div(140737488355330, 140737488355328) = 2, ceiling_div(-140737488355330, 140737488355328) = 0
     1883ceiling_div(281474976710656, 281474976710656) = 1, ceiling_div(281474976710658, 281474976710656) = 2, ceiling_div(-281474976710658, 281474976710656) = 0
     1884ceiling_div(562949953421312, 562949953421312) = 1, ceiling_div(562949953421314, 562949953421312) = 2, ceiling_div(-562949953421314, 562949953421312) = 0
     1885ceiling_div(1125899906842624, 1125899906842624) = 1, ceiling_div(1125899906842626, 1125899906842624) = 2, ceiling_div(-1125899906842626, 1125899906842624) = 0
     1886ceiling_div(2251799813685248, 2251799813685248) = 1, ceiling_div(2251799813685250, 2251799813685248) = 2, ceiling_div(-2251799813685250, 2251799813685248) = 0
     1887ceiling_div(4503599627370496, 4503599627370496) = 1, ceiling_div(4503599627370498, 4503599627370496) = 2, ceiling_div(-4503599627370498, 4503599627370496) = 0
     1888ceiling_div(9007199254740992, 9007199254740992) = 1, ceiling_div(9007199254740994, 9007199254740992) = 2, ceiling_div(-9007199254740994, 9007199254740992) = 0
     1889ceiling_div(18014398509481984, 18014398509481984) = 1, ceiling_div(18014398509481986, 18014398509481984) = 2, ceiling_div(-18014398509481986, 18014398509481984) = 0
     1890ceiling_div(36028797018963968, 36028797018963968) = 1, ceiling_div(36028797018963970, 36028797018963968) = 2, ceiling_div(-36028797018963970, 36028797018963968) = 0
     1891ceiling_div(72057594037927936, 72057594037927936) = 1, ceiling_div(72057594037927938, 72057594037927936) = 2, ceiling_div(-72057594037927938, 72057594037927936) = 0
     1892ceiling_div(144115188075855872, 144115188075855872) = 1, ceiling_div(144115188075855874, 144115188075855872) = 2, ceiling_div(-144115188075855874, 144115188075855872) = 0
     1893ceiling_div(288230376151711744, 288230376151711744) = 1, ceiling_div(288230376151711746, 288230376151711744) = 2, ceiling_div(-288230376151711746, 288230376151711744) = 0
     1894ceiling_div(576460752303423488, 576460752303423488) = 1, ceiling_div(576460752303423490, 576460752303423488) = 2, ceiling_div(-576460752303423490, 576460752303423488) = 0
     1895ceiling_div(1152921504606846976, 1152921504606846976) = 1, ceiling_div(1152921504606846978, 1152921504606846976) = 2, ceiling_div(-1152921504606846978, 1152921504606846976) = 0
     1896ceiling_div(2305843009213693952, 2305843009213693952) = 1, ceiling_div(2305843009213693954, 2305843009213693952) = 2, ceiling_div(-2305843009213693954, 2305843009213693952) = 0
     1897ceiling_div(4611686018427387904, 4611686018427387904) = 1, ceiling_div(4611686018427387906, 4611686018427387904) = -1, ceiling_div(-4611686018427387906, 4611686018427387904) = 0
     1898ceiling_div(-9223372036854775808, -9223372036854775808) = 0, ceiling_div(-9223372036854775806, -9223372036854775808) = 0, ceiling_div(9223372036854775806, -9223372036854775808) = 0
     1899
     1900unsigned long long int
     1901ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(18446744073709551613, 1) = 18446744073709551613
     1902ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(18446744073709551612, 2) = 9223372036854775806
     1903ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(18446744073709551610, 4) = 4611686018427387903
     1904ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(18446744073709551606, 8) = 2305843009213693951
     1905ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(18446744073709551598, 16) = 1152921504606846975
     1906ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(18446744073709551582, 32) = 576460752303423487
     1907ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(18446744073709551550, 64) = 288230376151711743
     1908ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(18446744073709551486, 128) = 144115188075855871
     1909ceiling_div(256, 256) = 1, ceiling_div(258, 256) = 2, ceiling_div(18446744073709551358, 256) = 72057594037927935
     1910ceiling_div(512, 512) = 1, ceiling_div(514, 512) = 2, ceiling_div(18446744073709551102, 512) = 36028797018963967
     1911ceiling_div(1024, 1024) = 1, ceiling_div(1026, 1024) = 2, ceiling_div(18446744073709550590, 1024) = 18014398509481983
     1912ceiling_div(2048, 2048) = 1, ceiling_div(2050, 2048) = 2, ceiling_div(18446744073709549566, 2048) = 9007199254740991
     1913ceiling_div(4096, 4096) = 1, ceiling_div(4098, 4096) = 2, ceiling_div(18446744073709547518, 4096) = 4503599627370495
     1914ceiling_div(8192, 8192) = 1, ceiling_div(8194, 8192) = 2, ceiling_div(18446744073709543422, 8192) = 2251799813685247
     1915ceiling_div(16384, 16384) = 1, ceiling_div(16386, 16384) = 2, ceiling_div(18446744073709535230, 16384) = 1125899906842623
     1916ceiling_div(32768, 32768) = 1, ceiling_div(32770, 32768) = 2, ceiling_div(18446744073709518846, 32768) = 562949953421311
     1917ceiling_div(65536, 65536) = 1, ceiling_div(65538, 65536) = 2, ceiling_div(18446744073709486078, 65536) = 281474976710655
     1918ceiling_div(131072, 131072) = 1, ceiling_div(131074, 131072) = 2, ceiling_div(18446744073709420542, 131072) = 140737488355327
     1919ceiling_div(262144, 262144) = 1, ceiling_div(262146, 262144) = 2, ceiling_div(18446744073709289470, 262144) = 70368744177663
     1920ceiling_div(524288, 524288) = 1, ceiling_div(524290, 524288) = 2, ceiling_div(18446744073709027326, 524288) = 35184372088831
     1921ceiling_div(1048576, 1048576) = 1, ceiling_div(1048578, 1048576) = 2, ceiling_div(18446744073708503038, 1048576) = 17592186044415
     1922ceiling_div(2097152, 2097152) = 1, ceiling_div(2097154, 2097152) = 2, ceiling_div(18446744073707454462, 2097152) = 8796093022207
     1923ceiling_div(4194304, 4194304) = 1, ceiling_div(4194306, 4194304) = 2, ceiling_div(18446744073705357310, 4194304) = 4398046511103
     1924ceiling_div(8388608, 8388608) = 1, ceiling_div(8388610, 8388608) = 2, ceiling_div(18446744073701163006, 8388608) = 2199023255551
     1925ceiling_div(16777216, 16777216) = 1, ceiling_div(16777218, 16777216) = 2, ceiling_div(18446744073692774398, 16777216) = 1099511627775
     1926ceiling_div(33554432, 33554432) = 1, ceiling_div(33554434, 33554432) = 2, ceiling_div(18446744073675997182, 33554432) = 549755813887
     1927ceiling_div(67108864, 67108864) = 1, ceiling_div(67108866, 67108864) = 2, ceiling_div(18446744073642442750, 67108864) = 274877906943
     1928ceiling_div(134217728, 134217728) = 1, ceiling_div(134217730, 134217728) = 2, ceiling_div(18446744073575333886, 134217728) = 137438953471
     1929ceiling_div(268435456, 268435456) = 1, ceiling_div(268435458, 268435456) = 2, ceiling_div(18446744073441116158, 268435456) = 68719476735
     1930ceiling_div(536870912, 536870912) = 1, ceiling_div(536870914, 536870912) = 2, ceiling_div(18446744073172680702, 536870912) = 34359738367
     1931ceiling_div(1073741824, 1073741824) = 1, ceiling_div(1073741826, 1073741824) = 2, ceiling_div(18446744072635809790, 1073741824) = 17179869183
     1932ceiling_div(2147483648, 2147483648) = 1, ceiling_div(2147483650, 2147483648) = 2, ceiling_div(18446744071562067966, 2147483648) = 8589934591
     1933ceiling_div(4294967296, 4294967296) = 1, ceiling_div(4294967298, 4294967296) = 2, ceiling_div(18446744069414584318, 4294967296) = 4294967295
     1934ceiling_div(8589934592, 8589934592) = 1, ceiling_div(8589934594, 8589934592) = 2, ceiling_div(18446744065119617022, 8589934592) = 2147483647
     1935ceiling_div(17179869184, 17179869184) = 1, ceiling_div(17179869186, 17179869184) = 2, ceiling_div(18446744056529682430, 17179869184) = 1073741823
     1936ceiling_div(34359738368, 34359738368) = 1, ceiling_div(34359738370, 34359738368) = 2, ceiling_div(18446744039349813246, 34359738368) = 536870911
     1937ceiling_div(68719476736, 68719476736) = 1, ceiling_div(68719476738, 68719476736) = 2, ceiling_div(18446744004990074878, 68719476736) = 268435455
     1938ceiling_div(137438953472, 137438953472) = 1, ceiling_div(137438953474, 137438953472) = 2, ceiling_div(18446743936270598142, 137438953472) = 134217727
     1939ceiling_div(274877906944, 274877906944) = 1, ceiling_div(274877906946, 274877906944) = 2, ceiling_div(18446743798831644670, 274877906944) = 67108863
     1940ceiling_div(549755813888, 549755813888) = 1, ceiling_div(549755813890, 549755813888) = 2, ceiling_div(18446743523953737726, 549755813888) = 33554431
     1941ceiling_div(1099511627776, 1099511627776) = 1, ceiling_div(1099511627778, 1099511627776) = 2, ceiling_div(18446742974197923838, 1099511627776) = 16777215
     1942ceiling_div(2199023255552, 2199023255552) = 1, ceiling_div(2199023255554, 2199023255552) = 2, ceiling_div(18446741874686296062, 2199023255552) = 8388607
     1943ceiling_div(4398046511104, 4398046511104) = 1, ceiling_div(4398046511106, 4398046511104) = 2, ceiling_div(18446739675663040510, 4398046511104) = 4194303
     1944ceiling_div(8796093022208, 8796093022208) = 1, ceiling_div(8796093022210, 8796093022208) = 2, ceiling_div(18446735277616529406, 8796093022208) = 2097151
     1945ceiling_div(17592186044416, 17592186044416) = 1, ceiling_div(17592186044418, 17592186044416) = 2, ceiling_div(18446726481523507198, 17592186044416) = 1048575
     1946ceiling_div(35184372088832, 35184372088832) = 1, ceiling_div(35184372088834, 35184372088832) = 2, ceiling_div(18446708889337462782, 35184372088832) = 524287
     1947ceiling_div(70368744177664, 70368744177664) = 1, ceiling_div(70368744177666, 70368744177664) = 2, ceiling_div(18446673704965373950, 70368744177664) = 262143
     1948ceiling_div(140737488355328, 140737488355328) = 1, ceiling_div(140737488355330, 140737488355328) = 2, ceiling_div(18446603336221196286, 140737488355328) = 131071
     1949ceiling_div(281474976710656, 281474976710656) = 1, ceiling_div(281474976710658, 281474976710656) = 2, ceiling_div(18446462598732840958, 281474976710656) = 65535
     1950ceiling_div(562949953421312, 562949953421312) = 1, ceiling_div(562949953421314, 562949953421312) = 2, ceiling_div(18446181123756130302, 562949953421312) = 32767
     1951ceiling_div(1125899906842624, 1125899906842624) = 1, ceiling_div(1125899906842626, 1125899906842624) = 2, ceiling_div(18445618173802708990, 1125899906842624) = 16383
     1952ceiling_div(2251799813685248, 2251799813685248) = 1, ceiling_div(2251799813685250, 2251799813685248) = 2, ceiling_div(18444492273895866366, 2251799813685248) = 8191
     1953ceiling_div(4503599627370496, 4503599627370496) = 1, ceiling_div(4503599627370498, 4503599627370496) = 2, ceiling_div(18442240474082181118, 4503599627370496) = 4095
     1954ceiling_div(9007199254740992, 9007199254740992) = 1, ceiling_div(9007199254740994, 9007199254740992) = 2, ceiling_div(18437736874454810622, 9007199254740992) = 2047
     1955ceiling_div(18014398509481984, 18014398509481984) = 1, ceiling_div(18014398509481986, 18014398509481984) = 2, ceiling_div(18428729675200069630, 18014398509481984) = 1023
     1956ceiling_div(36028797018963968, 36028797018963968) = 1, ceiling_div(36028797018963970, 36028797018963968) = 2, ceiling_div(18410715276690587646, 36028797018963968) = 511
     1957ceiling_div(72057594037927936, 72057594037927936) = 1, ceiling_div(72057594037927938, 72057594037927936) = 2, ceiling_div(18374686479671623678, 72057594037927936) = 255
     1958ceiling_div(144115188075855872, 144115188075855872) = 1, ceiling_div(144115188075855874, 144115188075855872) = 2, ceiling_div(18302628885633695742, 144115188075855872) = 127
     1959ceiling_div(288230376151711744, 288230376151711744) = 1, ceiling_div(288230376151711746, 288230376151711744) = 2, ceiling_div(18158513697557839870, 288230376151711744) = 63
     1960ceiling_div(576460752303423488, 576460752303423488) = 1, ceiling_div(576460752303423490, 576460752303423488) = 2, ceiling_div(17870283321406128126, 576460752303423488) = 31
     1961ceiling_div(1152921504606846976, 1152921504606846976) = 1, ceiling_div(1152921504606846978, 1152921504606846976) = 2, ceiling_div(17293822569102704638, 1152921504606846976) = 15
     1962ceiling_div(2305843009213693952, 2305843009213693952) = 1, ceiling_div(2305843009213693954, 2305843009213693952) = 2, ceiling_div(16140901064495857662, 2305843009213693952) = 7
     1963ceiling_div(4611686018427387904, 4611686018427387904) = 1, ceiling_div(4611686018427387906, 4611686018427387904) = 2, ceiling_div(13835058055282163710, 4611686018427387904) = 3
     1964ceiling_div(9223372036854775808, 9223372036854775808) = 1, ceiling_div(9223372036854775810, 9223372036854775808) = 0, ceiling_div(9223372036854775806, 9223372036854775808) = 1
     1965
     1966
    15961967ceiling
    15971968
    15981969signed char
    15991970ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(-3, 1) = -3
    1600 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(-4, 2) = -1
    1601 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(-6, 4) = 0
    1602 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(-10, 8) = 0
    1603 ceiling(16, 16) = 1, ceiling(18, 16) = 2, ceiling(-18, 16) = 0
    1604 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(-34, 32) = 0
    1605 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(-66, 64) = 0
    1606 ceiling(-128, -128) = 2, ceiling(-126, -128) = 1, ceiling(126, -128) = 0
     1971ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(-4, 2) = -4
     1972ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(-6, 4) = 0
     1973ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(-10, 8) = 0
     1974ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(-18, 16) = 0
     1975ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(-34, 32) = 0
     1976ceiling(64, 64) = 64, ceiling(66, 64) = -128, ceiling(-66, 64) = 0
     1977ceiling(-128, -128) = -128, ceiling(-126, -128) = -128, ceiling(126, -128) = 0
    16071978
    16081979unsigned char
    16091980ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(253, 1) = 253
    1610 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(252, 2) = 126
    1611 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(250, 4) = 63
    1612 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(246, 8) = 31
    1613 ceiling(16, 16) = 1, ceiling(18, 16) = 2, ceiling(238, 16) = 15
    1614 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(222, 32) = 7
    1615 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(190, 64) = 3
    1616 ceiling(128, 128) = 1, ceiling(130, 128) = 2, ceiling(126, 128) = 1
     1981ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(252, 2) = 252
     1982ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(250, 4) = 252
     1983ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(246, 8) = 248
     1984ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(238, 16) = 240
     1985ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(222, 32) = 224
     1986ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(190, 64) = 192
     1987ceiling(128, 128) = 128, ceiling(130, 128) = 0, ceiling(126, 128) = 128
    16171988
    16181989short int
    16191990ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(-3, 1) = -3
    1620 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(-4, 2) = -1
    1621 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(-6, 4) = 0
    1622 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(-10, 8) = 0
    1623 ceiling(16, 16) = 1, ceiling(18, 16) = 2, ceiling(-18, 16) = 0
    1624 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(-34, 32) = 0
    1625 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(-66, 64) = 0
    1626 ceiling(128, 128) = 1, ceiling(130, 128) = 2, ceiling(-130, 128) = 0
    1627 ceiling(256, 256) = 1, ceiling(258, 256) = 2, ceiling(-258, 256) = 0
    1628 ceiling(512, 512) = 1, ceiling(514, 512) = 2, ceiling(-514, 512) = 0
    1629 ceiling(1024, 1024) = 1, ceiling(1026, 1024) = 2, ceiling(-1026, 1024) = 0
    1630 ceiling(2048, 2048) = 1, ceiling(2050, 2048) = 2, ceiling(-2050, 2048) = 0
    1631 ceiling(4096, 4096) = 1, ceiling(4098, 4096) = 2, ceiling(-4098, 4096) = 0
    1632 ceiling(8192, 8192) = 1, ceiling(8194, 8192) = 2, ceiling(-8194, 8192) = 0
    1633 ceiling(16384, 16384) = 1, ceiling(16386, 16384) = 2, ceiling(-16386, 16384) = 0
    1634 ceiling(-32768, -32768) = 2, ceiling(-32766, -32768) = 1, ceiling(32766, -32768) = 0
     1991ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(-4, 2) = -4
     1992ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(-6, 4) = 0
     1993ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(-10, 8) = 0
     1994ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(-18, 16) = 0
     1995ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(-34, 32) = 0
     1996ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(-66, 64) = 0
     1997ceiling(128, 128) = 128, ceiling(130, 128) = 256, ceiling(-130, 128) = 0
     1998ceiling(256, 256) = 256, ceiling(258, 256) = 512, ceiling(-258, 256) = 0
     1999ceiling(512, 512) = 512, ceiling(514, 512) = 1024, ceiling(-514, 512) = 0
     2000ceiling(1024, 1024) = 1024, ceiling(1026, 1024) = 2048, ceiling(-1026, 1024) = 0
     2001ceiling(2048, 2048) = 2048, ceiling(2050, 2048) = 4096, ceiling(-2050, 2048) = 0
     2002ceiling(4096, 4096) = 4096, ceiling(4098, 4096) = 8192, ceiling(-4098, 4096) = 0
     2003ceiling(8192, 8192) = 8192, ceiling(8194, 8192) = 16384, ceiling(-8194, 8192) = 0
     2004ceiling(16384, 16384) = 16384, ceiling(16386, 16384) = -32768, ceiling(-16386, 16384) = 0
     2005ceiling(-32768, -32768) = -32768, ceiling(-32766, -32768) = -32768, ceiling(32766, -32768) = 0
    16352006
    16362007unsigned short int
    16372008ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(65533, 1) = 65533
    1638 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(65532, 2) = 32766
    1639 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(65530, 4) = 16383
    1640 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(65526, 8) = 8191
    1641 ceiling(16, 16) = 1, ceiling(18, 16) = 2, ceiling(65518, 16) = 4095
    1642 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(65502, 32) = 2047
    1643 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(65470, 64) = 1023
    1644 ceiling(128, 128) = 1, ceiling(130, 128) = 2, ceiling(65406, 128) = 511
    1645 ceiling(256, 256) = 1, ceiling(258, 256) = 2, ceiling(65278, 256) = 255
    1646 ceiling(512, 512) = 1, ceiling(514, 512) = 2, ceiling(65022, 512) = 127
    1647 ceiling(1024, 1024) = 1, ceiling(1026, 1024) = 2, ceiling(64510, 1024) = 63
    1648 ceiling(2048, 2048) = 1, ceiling(2050, 2048) = 2, ceiling(63486, 2048) = 31
    1649 ceiling(4096, 4096) = 1, ceiling(4098, 4096) = 2, ceiling(61438, 4096) = 15
    1650 ceiling(8192, 8192) = 1, ceiling(8194, 8192) = 2, ceiling(57342, 8192) = 7
    1651 ceiling(16384, 16384) = 1, ceiling(16386, 16384) = 2, ceiling(49150, 16384) = 3
    1652 ceiling(32768, 32768) = 1, ceiling(32770, 32768) = 2, ceiling(32766, 32768) = 1
     2009ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(65532, 2) = 65532
     2010ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(65530, 4) = 65532
     2011ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(65526, 8) = 65528
     2012ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(65518, 16) = 65520
     2013ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(65502, 32) = 65504
     2014ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(65470, 64) = 65472
     2015ceiling(128, 128) = 128, ceiling(130, 128) = 256, ceiling(65406, 128) = 65408
     2016ceiling(256, 256) = 256, ceiling(258, 256) = 512, ceiling(65278, 256) = 65280
     2017ceiling(512, 512) = 512, ceiling(514, 512) = 1024, ceiling(65022, 512) = 65024
     2018ceiling(1024, 1024) = 1024, ceiling(1026, 1024) = 2048, ceiling(64510, 1024) = 64512
     2019ceiling(2048, 2048) = 2048, ceiling(2050, 2048) = 4096, ceiling(63486, 2048) = 63488
     2020ceiling(4096, 4096) = 4096, ceiling(4098, 4096) = 8192, ceiling(61438, 4096) = 61440
     2021ceiling(8192, 8192) = 8192, ceiling(8194, 8192) = 16384, ceiling(57342, 8192) = 57344
     2022ceiling(16384, 16384) = 16384, ceiling(16386, 16384) = 32768, ceiling(49150, 16384) = 49152
     2023ceiling(32768, 32768) = 32768, ceiling(32770, 32768) = 0, ceiling(32766, 32768) = 32768
    16532024
    16542025int
    16552026ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(-3, 1) = -3
    1656 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(-4, 2) = -1
    1657 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(-6, 4) = 0
    1658 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(-10, 8) = 0
    1659 ceiling(16, 16) = 1, ceiling(18, 16) = 2, ceiling(-18, 16) = 0
    1660 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(-34, 32) = 0
    1661 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(-66, 64) = 0
    1662 ceiling(128, 128) = 1, ceiling(130, 128) = 2, ceiling(-130, 128) = 0
    1663 ceiling(256, 256) = 1, ceiling(258, 256) = 2, ceiling(-258, 256) = 0
    1664 ceiling(512, 512) = 1, ceiling(514, 512) = 2, ceiling(-514, 512) = 0
    1665 ceiling(1024, 1024) = 1, ceiling(1026, 1024) = 2, ceiling(-1026, 1024) = 0
    1666 ceiling(2048, 2048) = 1, ceiling(2050, 2048) = 2, ceiling(-2050, 2048) = 0
    1667 ceiling(4096, 4096) = 1, ceiling(4098, 4096) = 2, ceiling(-4098, 4096) = 0
    1668 ceiling(8192, 8192) = 1, ceiling(8194, 8192) = 2, ceiling(-8194, 8192) = 0
    1669 ceiling(16384, 16384) = 1, ceiling(16386, 16384) = 2, ceiling(-16386, 16384) = 0
    1670 ceiling(32768, 32768) = 1, ceiling(32770, 32768) = 2, ceiling(-32770, 32768) = 0
    1671 ceiling(65536, 65536) = 1, ceiling(65538, 65536) = 2, ceiling(-65538, 65536) = 0
    1672 ceiling(131072, 131072) = 1, ceiling(131074, 131072) = 2, ceiling(-131074, 131072) = 0
    1673 ceiling(262144, 262144) = 1, ceiling(262146, 262144) = 2, ceiling(-262146, 262144) = 0
    1674 ceiling(524288, 524288) = 1, ceiling(524290, 524288) = 2, ceiling(-524290, 524288) = 0
    1675 ceiling(1048576, 1048576) = 1, ceiling(1048578, 1048576) = 2, ceiling(-1048578, 1048576) = 0
    1676 ceiling(2097152, 2097152) = 1, ceiling(2097154, 2097152) = 2, ceiling(-2097154, 2097152) = 0
    1677 ceiling(4194304, 4194304) = 1, ceiling(4194306, 4194304) = 2, ceiling(-4194306, 4194304) = 0
    1678 ceiling(8388608, 8388608) = 1, ceiling(8388610, 8388608) = 2, ceiling(-8388610, 8388608) = 0
    1679 ceiling(16777216, 16777216) = 1, ceiling(16777218, 16777216) = 2, ceiling(-16777218, 16777216) = 0
    1680 ceiling(33554432, 33554432) = 1, ceiling(33554434, 33554432) = 2, ceiling(-33554434, 33554432) = 0
    1681 ceiling(67108864, 67108864) = 1, ceiling(67108866, 67108864) = 2, ceiling(-67108866, 67108864) = 0
    1682 ceiling(134217728, 134217728) = 1, ceiling(134217730, 134217728) = 2, ceiling(-134217730, 134217728) = 0
    1683 ceiling(268435456, 268435456) = 1, ceiling(268435458, 268435456) = 2, ceiling(-268435458, 268435456) = 0
    1684 ceiling(536870912, 536870912) = 1, ceiling(536870914, 536870912) = 2, ceiling(-536870914, 536870912) = 0
    1685 ceiling(1073741824, 1073741824) = 1, ceiling(1073741826, 1073741824) = -1, ceiling(-1073741826, 1073741824) = 0
    1686 ceiling(-2147483648, -2147483648) = 0, ceiling(-2147483646, -2147483648) = 0, ceiling(2147483646, -2147483648) = 0
     2027ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(-4, 2) = -4
     2028ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(-6, 4) = 0
     2029ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(-10, 8) = 0
     2030ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(-18, 16) = 0
     2031ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(-34, 32) = 0
     2032ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(-66, 64) = 0
     2033ceiling(128, 128) = 128, ceiling(130, 128) = 256, ceiling(-130, 128) = 0
     2034ceiling(256, 256) = 256, ceiling(258, 256) = 512, ceiling(-258, 256) = 0
     2035ceiling(512, 512) = 512, ceiling(514, 512) = 1024, ceiling(-514, 512) = 0
     2036ceiling(1024, 1024) = 1024, ceiling(1026, 1024) = 2048, ceiling(-1026, 1024) = 0
     2037ceiling(2048, 2048) = 2048, ceiling(2050, 2048) = 4096, ceiling(-2050, 2048) = 0
     2038ceiling(4096, 4096) = 4096, ceiling(4098, 4096) = 8192, ceiling(-4098, 4096) = 0
     2039ceiling(8192, 8192) = 8192, ceiling(8194, 8192) = 16384, ceiling(-8194, 8192) = 0
     2040ceiling(16384, 16384) = 16384, ceiling(16386, 16384) = 32768, ceiling(-16386, 16384) = 0
     2041ceiling(32768, 32768) = 32768, ceiling(32770, 32768) = 65536, ceiling(-32770, 32768) = 0
     2042ceiling(65536, 65536) = 65536, ceiling(65538, 65536) = 131072, ceiling(-65538, 65536) = 0
     2043ceiling(131072, 131072) = 131072, ceiling(131074, 131072) = 262144, ceiling(-131074, 131072) = 0
     2044ceiling(262144, 262144) = 262144, ceiling(262146, 262144) = 524288, ceiling(-262146, 262144) = 0
     2045ceiling(524288, 524288) = 524288, ceiling(524290, 524288) = 1048576, ceiling(-524290, 524288) = 0
     2046ceiling(1048576, 1048576) = 1048576, ceiling(1048578, 1048576) = 2097152, ceiling(-1048578, 1048576) = 0
     2047ceiling(2097152, 2097152) = 2097152, ceiling(2097154, 2097152) = 4194304, ceiling(-2097154, 2097152) = 0
     2048ceiling(4194304, 4194304) = 4194304, ceiling(4194306, 4194304) = 8388608, ceiling(-4194306, 4194304) = 0
     2049ceiling(8388608, 8388608) = 8388608, ceiling(8388610, 8388608) = 16777216, ceiling(-8388610, 8388608) = 0
     2050ceiling(16777216, 16777216) = 16777216, ceiling(16777218, 16777216) = 33554432, ceiling(-16777218, 16777216) = 0
     2051ceiling(33554432, 33554432) = 33554432, ceiling(33554434, 33554432) = 67108864, ceiling(-33554434, 33554432) = 0
     2052ceiling(67108864, 67108864) = 67108864, ceiling(67108866, 67108864) = 134217728, ceiling(-67108866, 67108864) = 0
     2053ceiling(134217728, 134217728) = 134217728, ceiling(134217730, 134217728) = 268435456, ceiling(-134217730, 134217728) = 0
     2054ceiling(268435456, 268435456) = 268435456, ceiling(268435458, 268435456) = 536870912, ceiling(-268435458, 268435456) = 0
     2055ceiling(536870912, 536870912) = 536870912, ceiling(536870914, 536870912) = 1073741824, ceiling(-536870914, 536870912) = 0
     2056ceiling(1073741824, 1073741824) = 1073741824, ceiling(1073741826, 1073741824) = -1073741824, ceiling(-1073741826, 1073741824) = 0
     2057ceiling(-2147483648, -2147483648) = -2147483648, ceiling(-2147483646, -2147483648) = 0, ceiling(2147483646, -2147483648) = 0
    16872058
    16882059unsigned int
    16892060ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(4294967293, 1) = 4294967293
    1690 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(4294967292, 2) = 2147483646
    1691 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(4294967290, 4) = 1073741823
    1692 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(4294967286, 8) = 536870911
    1693 ceiling(16, 16) = 1, ceiling(18, 16) = 2, ceiling(4294967278, 16) = 268435455
    1694 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(4294967262, 32) = 134217727
    1695 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(4294967230, 64) = 67108863
    1696 ceiling(128, 128) = 1, ceiling(130, 128) = 2, ceiling(4294967166, 128) = 33554431
    1697 ceiling(256, 256) = 1, ceiling(258, 256) = 2, ceiling(4294967038, 256) = 16777215
    1698 ceiling(512, 512) = 1, ceiling(514, 512) = 2, ceiling(4294966782, 512) = 8388607
    1699 ceiling(1024, 1024) = 1, ceiling(1026, 1024) = 2, ceiling(4294966270, 1024) = 4194303
    1700 ceiling(2048, 2048) = 1, ceiling(2050, 2048) = 2, ceiling(4294965246, 2048) = 2097151
    1701 ceiling(4096, 4096) = 1, ceiling(4098, 4096) = 2, ceiling(4294963198, 4096) = 1048575
    1702 ceiling(8192, 8192) = 1, ceiling(8194, 8192) = 2, ceiling(4294959102, 8192) = 524287
    1703 ceiling(16384, 16384) = 1, ceiling(16386, 16384) = 2, ceiling(4294950910, 16384) = 262143
    1704 ceiling(32768, 32768) = 1, ceiling(32770, 32768) = 2, ceiling(4294934526, 32768) = 131071
    1705 ceiling(65536, 65536) = 1, ceiling(65538, 65536) = 2, ceiling(4294901758, 65536) = 65535
    1706 ceiling(131072, 131072) = 1, ceiling(131074, 131072) = 2, ceiling(4294836222, 131072) = 32767
    1707 ceiling(262144, 262144) = 1, ceiling(262146, 262144) = 2, ceiling(4294705150, 262144) = 16383
    1708 ceiling(524288, 524288) = 1, ceiling(524290, 524288) = 2, ceiling(4294443006, 524288) = 8191
    1709 ceiling(1048576, 1048576) = 1, ceiling(1048578, 1048576) = 2, ceiling(4293918718, 1048576) = 4095
    1710 ceiling(2097152, 2097152) = 1, ceiling(2097154, 2097152) = 2, ceiling(4292870142, 2097152) = 2047
    1711 ceiling(4194304, 4194304) = 1, ceiling(4194306, 4194304) = 2, ceiling(4290772990, 4194304) = 1023
    1712 ceiling(8388608, 8388608) = 1, ceiling(8388610, 8388608) = 2, ceiling(4286578686, 8388608) = 511
    1713 ceiling(16777216, 16777216) = 1, ceiling(16777218, 16777216) = 2, ceiling(4278190078, 16777216) = 255
    1714 ceiling(33554432, 33554432) = 1, ceiling(33554434, 33554432) = 2, ceiling(4261412862, 33554432) = 127
    1715 ceiling(67108864, 67108864) = 1, ceiling(67108866, 67108864) = 2, ceiling(4227858430, 67108864) = 63
    1716 ceiling(134217728, 134217728) = 1, ceiling(134217730, 134217728) = 2, ceiling(4160749566, 134217728) = 31
    1717 ceiling(268435456, 268435456) = 1, ceiling(268435458, 268435456) = 2, ceiling(4026531838, 268435456) = 15
    1718 ceiling(536870912, 536870912) = 1, ceiling(536870914, 536870912) = 2, ceiling(3758096382, 536870912) = 7
    1719 ceiling(1073741824, 1073741824) = 1, ceiling(1073741826, 1073741824) = 2, ceiling(3221225470, 1073741824) = 3
    1720 ceiling(2147483648, 2147483648) = 1, ceiling(2147483650, 2147483648) = 0, ceiling(2147483646, 2147483648) = 1
     2061ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(4294967292, 2) = 4294967292
     2062ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(4294967290, 4) = 4294967292
     2063ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(4294967286, 8) = 4294967288
     2064ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(4294967278, 16) = 4294967280
     2065ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(4294967262, 32) = 4294967264
     2066ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(4294967230, 64) = 4294967232
     2067ceiling(128, 128) = 128, ceiling(130, 128) = 256, ceiling(4294967166, 128) = 4294967168
     2068ceiling(256, 256) = 256, ceiling(258, 256) = 512, ceiling(4294967038, 256) = 4294967040
     2069ceiling(512, 512) = 512, ceiling(514, 512) = 1024, ceiling(4294966782, 512) = 4294966784
     2070ceiling(1024, 1024) = 1024, ceiling(1026, 1024) = 2048, ceiling(4294966270, 1024) = 4294966272
     2071ceiling(2048, 2048) = 2048, ceiling(2050, 2048) = 4096, ceiling(4294965246, 2048) = 4294965248
     2072ceiling(4096, 4096) = 4096, ceiling(4098, 4096) = 8192, ceiling(4294963198, 4096) = 4294963200
     2073ceiling(8192, 8192) = 8192, ceiling(8194, 8192) = 16384, ceiling(4294959102, 8192) = 4294959104
     2074ceiling(16384, 16384) = 16384, ceiling(16386, 16384) = 32768, ceiling(4294950910, 16384) = 4294950912
     2075ceiling(32768, 32768) = 32768, ceiling(32770, 32768) = 65536, ceiling(4294934526, 32768) = 4294934528
     2076ceiling(65536, 65536) = 65536, ceiling(65538, 65536) = 131072, ceiling(4294901758, 65536) = 4294901760
     2077ceiling(131072, 131072) = 131072, ceiling(131074, 131072) = 262144, ceiling(4294836222, 131072) = 4294836224
     2078ceiling(262144, 262144) = 262144, ceiling(262146, 262144) = 524288, ceiling(4294705150, 262144) = 4294705152
     2079ceiling(524288, 524288) = 524288, ceiling(524290, 524288) = 1048576, ceiling(4294443006, 524288) = 4294443008
     2080ceiling(1048576, 1048576) = 1048576, ceiling(1048578, 1048576) = 2097152, ceiling(4293918718, 1048576) = 4293918720
     2081ceiling(2097152, 2097152) = 2097152, ceiling(2097154, 2097152) = 4194304, ceiling(4292870142, 2097152) = 4292870144
     2082ceiling(4194304, 4194304) = 4194304, ceiling(4194306, 4194304) = 8388608, ceiling(4290772990, 4194304) = 4290772992
     2083ceiling(8388608, 8388608) = 8388608, ceiling(8388610, 8388608) = 16777216, ceiling(4286578686, 8388608) = 4286578688
     2084ceiling(16777216, 16777216) = 16777216, ceiling(16777218, 16777216) = 33554432, ceiling(4278190078, 16777216) = 4278190080
     2085ceiling(33554432, 33554432) = 33554432, ceiling(33554434, 33554432) = 67108864, ceiling(4261412862, 33554432) = 4261412864
     2086ceiling(67108864, 67108864) = 67108864, ceiling(67108866, 67108864) = 134217728, ceiling(4227858430, 67108864) = 4227858432
     2087ceiling(134217728, 134217728) = 134217728, ceiling(134217730, 134217728) = 268435456, ceiling(4160749566, 134217728) = 4160749568
     2088ceiling(268435456, 268435456) = 268435456, ceiling(268435458, 268435456) = 536870912, ceiling(4026531838, 268435456) = 4026531840
     2089ceiling(536870912, 536870912) = 536870912, ceiling(536870914, 536870912) = 1073741824, ceiling(3758096382, 536870912) = 3758096384
     2090ceiling(1073741824, 1073741824) = 1073741824, ceiling(1073741826, 1073741824) = 2147483648, ceiling(3221225470, 1073741824) = 3221225472
     2091ceiling(2147483648, 2147483648) = 2147483648, ceiling(2147483650, 2147483648) = 0, ceiling(2147483646, 2147483648) = 2147483648
    17212092
    17222093long int
    17232094ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(-3, 1) = -3
    1724 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(-4, 2) = -1
    1725 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(-6, 4) = 0
    1726 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(-10, 8) = 0
    1727 ceiling(16, 16) = 1, ceiling(18, 16) = 2, ceiling(-18, 16) = 0
    1728 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(-34, 32) = 0
    1729 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(-66, 64) = 0
    1730 ceiling(128, 128) = 1, ceiling(130, 128) = 2, ceiling(-130, 128) = 0
    1731 ceiling(256, 256) = 1, ceiling(258, 256) = 2, ceiling(-258, 256) = 0
    1732 ceiling(512, 512) = 1, ceiling(514, 512) = 2, ceiling(-514, 512) = 0
    1733 ceiling(1024, 1024) = 1, ceiling(1026, 1024) = 2, ceiling(-1026, 1024) = 0
    1734 ceiling(2048, 2048) = 1, ceiling(2050, 2048) = 2, ceiling(-2050, 2048) = 0
    1735 ceiling(4096, 4096) = 1, ceiling(4098, 4096) = 2, ceiling(-4098, 4096) = 0
    1736 ceiling(8192, 8192) = 1, ceiling(8194, 8192) = 2, ceiling(-8194, 8192) = 0
    1737 ceiling(16384, 16384) = 1, ceiling(16386, 16384) = 2, ceiling(-16386, 16384) = 0
    1738 ceiling(32768, 32768) = 1, ceiling(32770, 32768) = 2, ceiling(-32770, 32768) = 0
    1739 ceiling(65536, 65536) = 1, ceiling(65538, 65536) = 2, ceiling(-65538, 65536) = 0
    1740 ceiling(131072, 131072) = 1, ceiling(131074, 131072) = 2, ceiling(-131074, 131072) = 0
    1741 ceiling(262144, 262144) = 1, ceiling(262146, 262144) = 2, ceiling(-262146, 262144) = 0
    1742 ceiling(524288, 524288) = 1, ceiling(524290, 524288) = 2, ceiling(-524290, 524288) = 0
    1743 ceiling(1048576, 1048576) = 1, ceiling(1048578, 1048576) = 2, ceiling(-1048578, 1048576) = 0
    1744 ceiling(2097152, 2097152) = 1, ceiling(2097154, 2097152) = 2, ceiling(-2097154, 2097152) = 0
    1745 ceiling(4194304, 4194304) = 1, ceiling(4194306, 4194304) = 2, ceiling(-4194306, 4194304) = 0
    1746 ceiling(8388608, 8388608) = 1, ceiling(8388610, 8388608) = 2, ceiling(-8388610, 8388608) = 0
    1747 ceiling(16777216, 16777216) = 1, ceiling(16777218, 16777216) = 2, ceiling(-16777218, 16777216) = 0
    1748 ceiling(33554432, 33554432) = 1, ceiling(33554434, 33554432) = 2, ceiling(-33554434, 33554432) = 0
    1749 ceiling(67108864, 67108864) = 1, ceiling(67108866, 67108864) = 2, ceiling(-67108866, 67108864) = 0
    1750 ceiling(134217728, 134217728) = 1, ceiling(134217730, 134217728) = 2, ceiling(-134217730, 134217728) = 0
    1751 ceiling(268435456, 268435456) = 1, ceiling(268435458, 268435456) = 2, ceiling(-268435458, 268435456) = 0
    1752 ceiling(536870912, 536870912) = 1, ceiling(536870914, 536870912) = 2, ceiling(-536870914, 536870912) = 0
    1753 ceiling(1073741824, 1073741824) = 1, ceiling(1073741826, 1073741824) = 2, ceiling(-1073741826, 1073741824) = 0
    1754 ceiling(2147483648, 2147483648) = 1, ceiling(2147483650, 2147483648) = 2, ceiling(-2147483650, 2147483648) = 0
    1755 ceiling(4294967296, 4294967296) = 1, ceiling(4294967298, 4294967296) = 2, ceiling(-4294967298, 4294967296) = 0
    1756 ceiling(8589934592, 8589934592) = 1, ceiling(8589934594, 8589934592) = 2, ceiling(-8589934594, 8589934592) = 0
    1757 ceiling(17179869184, 17179869184) = 1, ceiling(17179869186, 17179869184) = 2, ceiling(-17179869186, 17179869184) = 0
    1758 ceiling(34359738368, 34359738368) = 1, ceiling(34359738370, 34359738368) = 2, ceiling(-34359738370, 34359738368) = 0
    1759 ceiling(68719476736, 68719476736) = 1, ceiling(68719476738, 68719476736) = 2, ceiling(-68719476738, 68719476736) = 0
    1760 ceiling(137438953472, 137438953472) = 1, ceiling(137438953474, 137438953472) = 2, ceiling(-137438953474, 137438953472) = 0
    1761 ceiling(274877906944, 274877906944) = 1, ceiling(274877906946, 274877906944) = 2, ceiling(-274877906946, 274877906944) = 0
    1762 ceiling(549755813888, 549755813888) = 1, ceiling(549755813890, 549755813888) = 2, ceiling(-549755813890, 549755813888) = 0
    1763 ceiling(1099511627776, 1099511627776) = 1, ceiling(1099511627778, 1099511627776) = 2, ceiling(-1099511627778, 1099511627776) = 0
    1764 ceiling(2199023255552, 2199023255552) = 1, ceiling(2199023255554, 2199023255552) = 2, ceiling(-2199023255554, 2199023255552) = 0
    1765 ceiling(4398046511104, 4398046511104) = 1, ceiling(4398046511106, 4398046511104) = 2, ceiling(-4398046511106, 4398046511104) = 0
    1766 ceiling(8796093022208, 8796093022208) = 1, ceiling(8796093022210, 8796093022208) = 2, ceiling(-8796093022210, 8796093022208) = 0
    1767 ceiling(17592186044416, 17592186044416) = 1, ceiling(17592186044418, 17592186044416) = 2, ceiling(-17592186044418, 17592186044416) = 0
    1768 ceiling(35184372088832, 35184372088832) = 1, ceiling(35184372088834, 35184372088832) = 2, ceiling(-35184372088834, 35184372088832) = 0
    1769 ceiling(70368744177664, 70368744177664) = 1, ceiling(70368744177666, 70368744177664) = 2, ceiling(-70368744177666, 70368744177664) = 0
    1770 ceiling(140737488355328, 140737488355328) = 1, ceiling(140737488355330, 140737488355328) = 2, ceiling(-140737488355330, 140737488355328) = 0
    1771 ceiling(281474976710656, 281474976710656) = 1, ceiling(281474976710658, 281474976710656) = 2, ceiling(-281474976710658, 281474976710656) = 0
    1772 ceiling(562949953421312, 562949953421312) = 1, ceiling(562949953421314, 562949953421312) = 2, ceiling(-562949953421314, 562949953421312) = 0
    1773 ceiling(1125899906842624, 1125899906842624) = 1, ceiling(1125899906842626, 1125899906842624) = 2, ceiling(-1125899906842626, 1125899906842624) = 0
    1774 ceiling(2251799813685248, 2251799813685248) = 1, ceiling(2251799813685250, 2251799813685248) = 2, ceiling(-2251799813685250, 2251799813685248) = 0
    1775 ceiling(4503599627370496, 4503599627370496) = 1, ceiling(4503599627370498, 4503599627370496) = 2, ceiling(-4503599627370498, 4503599627370496) = 0
    1776 ceiling(9007199254740992, 9007199254740992) = 1, ceiling(9007199254740994, 9007199254740992) = 2, ceiling(-9007199254740994, 9007199254740992) = 0
    1777 ceiling(18014398509481984, 18014398509481984) = 1, ceiling(18014398509481986, 18014398509481984) = 2, ceiling(-18014398509481986, 18014398509481984) = 0
    1778 ceiling(36028797018963968, 36028797018963968) = 1, ceiling(36028797018963970, 36028797018963968) = 2, ceiling(-36028797018963970, 36028797018963968) = 0
    1779 ceiling(72057594037927936, 72057594037927936) = 1, ceiling(72057594037927938, 72057594037927936) = 2, ceiling(-72057594037927938, 72057594037927936) = 0
    1780 ceiling(144115188075855872, 144115188075855872) = 1, ceiling(144115188075855874, 144115188075855872) = 2, ceiling(-144115188075855874, 144115188075855872) = 0
    1781 ceiling(288230376151711744, 288230376151711744) = 1, ceiling(288230376151711746, 288230376151711744) = 2, ceiling(-288230376151711746, 288230376151711744) = 0
    1782 ceiling(576460752303423488, 576460752303423488) = 1, ceiling(576460752303423490, 576460752303423488) = 2, ceiling(-576460752303423490, 576460752303423488) = 0
    1783 ceiling(1152921504606846976, 1152921504606846976) = 1, ceiling(1152921504606846978, 1152921504606846976) = 2, ceiling(-1152921504606846978, 1152921504606846976) = 0
    1784 ceiling(2305843009213693952, 2305843009213693952) = 1, ceiling(2305843009213693954, 2305843009213693952) = 2, ceiling(-2305843009213693954, 2305843009213693952) = 0
    1785 ceiling(4611686018427387904, 4611686018427387904) = 1, ceiling(4611686018427387906, 4611686018427387904) = -1, ceiling(-4611686018427387906, 4611686018427387904) = 0
    1786 ceiling(-9223372036854775808, -9223372036854775808) = 0, ceiling(-9223372036854775806, -9223372036854775808) = 0, ceiling(9223372036854775806, -9223372036854775808) = 0
     2095ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(-4, 2) = -4
     2096ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(-6, 4) = 0
     2097ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(-10, 8) = 0
     2098ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(-18, 16) = 0
     2099ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(-34, 32) = 0
     2100ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(-66, 64) = 0
     2101ceiling(128, 128) = 128, ceiling(130, 128) = 256, ceiling(-130, 128) = 0
     2102ceiling(256, 256) = 256, ceiling(258, 256) = 512, ceiling(-258, 256) = 0
     2103ceiling(512, 512) = 512, ceiling(514, 512) = 1024, ceiling(-514, 512) = 0
     2104ceiling(1024, 1024) = 1024, ceiling(1026, 1024) = 2048, ceiling(-1026, 1024) = 0
     2105ceiling(2048, 2048) = 2048, ceiling(2050, 2048) = 4096, ceiling(-2050, 2048) = 0
     2106ceiling(4096, 4096) = 4096, ceiling(4098, 4096) = 8192, ceiling(-4098, 4096) = 0
     2107ceiling(8192, 8192) = 8192, ceiling(8194, 8192) = 16384, ceiling(-8194, 8192) = 0
     2108ceiling(16384, 16384) = 16384, ceiling(16386, 16384) = 32768, ceiling(-16386, 16384) = 0
     2109ceiling(32768, 32768) = 32768, ceiling(32770, 32768) = 65536, ceiling(-32770, 32768) = 0
     2110ceiling(65536, 65536) = 65536, ceiling(65538, 65536) = 131072, ceiling(-65538, 65536) = 0
     2111ceiling(131072, 131072) = 131072, ceiling(131074, 131072) = 262144, ceiling(-131074, 131072) = 0
     2112ceiling(262144, 262144) = 262144, ceiling(262146, 262144) = 524288, ceiling(-262146, 262144) = 0
     2113ceiling(524288, 524288) = 524288, ceiling(524290, 524288) = 1048576, ceiling(-524290, 524288) = 0
     2114ceiling(1048576, 1048576) = 1048576, ceiling(1048578, 1048576) = 2097152, ceiling(-1048578, 1048576) = 0
     2115ceiling(2097152, 2097152) = 2097152, ceiling(2097154, 2097152) = 4194304, ceiling(-2097154, 2097152) = 0
     2116ceiling(4194304, 4194304) = 4194304, ceiling(4194306, 4194304) = 8388608, ceiling(-4194306, 4194304) = 0
     2117ceiling(8388608, 8388608) = 8388608, ceiling(8388610, 8388608) = 16777216, ceiling(-8388610, 8388608) = 0
     2118ceiling(16777216, 16777216) = 16777216, ceiling(16777218, 16777216) = 33554432, ceiling(-16777218, 16777216) = 0
     2119ceiling(33554432, 33554432) = 33554432, ceiling(33554434, 33554432) = 67108864, ceiling(-33554434, 33554432) = 0
     2120ceiling(67108864, 67108864) = 67108864, ceiling(67108866, 67108864) = 134217728, ceiling(-67108866, 67108864) = 0
     2121ceiling(134217728, 134217728) = 134217728, ceiling(134217730, 134217728) = 268435456, ceiling(-134217730, 134217728) = 0
     2122ceiling(268435456, 268435456) = 268435456, ceiling(268435458, 268435456) = 536870912, ceiling(-268435458, 268435456) = 0
     2123ceiling(536870912, 536870912) = 536870912, ceiling(536870914, 536870912) = 1073741824, ceiling(-536870914, 536870912) = 0
     2124ceiling(1073741824, 1073741824) = 1073741824, ceiling(1073741826, 1073741824) = 2147483648, ceiling(-1073741826, 1073741824) = 0
     2125ceiling(2147483648, 2147483648) = 2147483648, ceiling(2147483650, 2147483648) = 4294967296, ceiling(-2147483650, 2147483648) = 0
     2126ceiling(4294967296, 4294967296) = 4294967296, ceiling(4294967298, 4294967296) = 8589934592, ceiling(-4294967298, 4294967296) = 0
     2127ceiling(8589934592, 8589934592) = 8589934592, ceiling(8589934594, 8589934592) = 17179869184, ceiling(-8589934594, 8589934592) = 0
     2128ceiling(17179869184, 17179869184) = 17179869184, ceiling(17179869186, 17179869184) = 34359738368, ceiling(-17179869186, 17179869184) = 0
     2129ceiling(34359738368, 34359738368) = 34359738368, ceiling(34359738370, 34359738368) = 68719476736, ceiling(-34359738370, 34359738368) = 0
     2130ceiling(68719476736, 68719476736) = 68719476736, ceiling(68719476738, 68719476736) = 137438953472, ceiling(-68719476738, 68719476736) = 0
     2131ceiling(137438953472, 137438953472) = 137438953472, ceiling(137438953474, 137438953472) = 274877906944, ceiling(-137438953474, 137438953472) = 0
     2132ceiling(274877906944, 274877906944) = 274877906944, ceiling(274877906946, 274877906944) = 549755813888, ceiling(-274877906946, 274877906944) = 0
     2133ceiling(549755813888, 549755813888) = 549755813888, ceiling(549755813890, 549755813888) = 1099511627776, ceiling(-549755813890, 549755813888) = 0
     2134ceiling(1099511627776, 1099511627776) = 1099511627776, ceiling(1099511627778, 1099511627776) = 2199023255552, ceiling(-1099511627778, 1099511627776) = 0
     2135ceiling(2199023255552, 2199023255552) = 2199023255552, ceiling(2199023255554, 2199023255552) = 4398046511104, ceiling(-2199023255554, 2199023255552) = 0
     2136ceiling(4398046511104, 4398046511104) = 4398046511104, ceiling(4398046511106, 4398046511104) = 8796093022208, ceiling(-4398046511106, 4398046511104) = 0
     2137ceiling(8796093022208, 8796093022208) = 8796093022208, ceiling(8796093022210, 8796093022208) = 17592186044416, ceiling(-8796093022210, 8796093022208) = 0
     2138ceiling(17592186044416, 17592186044416) = 17592186044416, ceiling(17592186044418, 17592186044416) = 35184372088832, ceiling(-17592186044418, 17592186044416) = 0
     2139ceiling(35184372088832, 35184372088832) = 35184372088832, ceiling(35184372088834, 35184372088832) = 70368744177664, ceiling(-35184372088834, 35184372088832) = 0
     2140ceiling(70368744177664, 70368744177664) = 70368744177664, ceiling(70368744177666, 70368744177664) = 140737488355328, ceiling(-70368744177666, 70368744177664) = 0
     2141ceiling(140737488355328, 140737488355328) = 140737488355328, ceiling(140737488355330, 140737488355328) = 281474976710656, ceiling(-140737488355330, 140737488355328) = 0
     2142ceiling(281474976710656, 281474976710656) = 281474976710656, ceiling(281474976710658, 281474976710656) = 562949953421312, ceiling(-281474976710658, 281474976710656) = 0
     2143ceiling(562949953421312, 562949953421312) = 562949953421312, ceiling(562949953421314, 562949953421312) = 1125899906842624, ceiling(-562949953421314, 562949953421312) = 0
     2144ceiling(1125899906842624, 1125899906842624) = 1125899906842624, ceiling(1125899906842626, 1125899906842624) = 2251799813685248, ceiling(-1125899906842626, 1125899906842624) = 0
     2145ceiling(2251799813685248, 2251799813685248) = 2251799813685248, ceiling(2251799813685250, 2251799813685248) = 4503599627370496, ceiling(-2251799813685250, 2251799813685248) = 0
     2146ceiling(4503599627370496, 4503599627370496) = 4503599627370496, ceiling(4503599627370498, 4503599627370496) = 9007199254740992, ceiling(-4503599627370498, 4503599627370496) = 0
     2147ceiling(9007199254740992, 9007199254740992) = 9007199254740992, ceiling(9007199254740994, 9007199254740992) = 18014398509481984, ceiling(-9007199254740994, 9007199254740992) = 0
     2148ceiling(18014398509481984, 18014398509481984) = 18014398509481984, ceiling(18014398509481986, 18014398509481984) = 36028797018963968, ceiling(-18014398509481986, 18014398509481984) = 0
     2149ceiling(36028797018963968, 36028797018963968) = 36028797018963968, ceiling(36028797018963970, 36028797018963968) = 72057594037927936, ceiling(-36028797018963970, 36028797018963968) = 0
     2150ceiling(72057594037927936, 72057594037927936) = 72057594037927936, ceiling(72057594037927938, 72057594037927936) = 144115188075855872, ceiling(-72057594037927938, 72057594037927936) = 0
     2151ceiling(144115188075855872, 144115188075855872) = 144115188075855872, ceiling(144115188075855874, 144115188075855872) = 288230376151711744, ceiling(-144115188075855874, 144115188075855872) = 0
     2152ceiling(288230376151711744, 288230376151711744) = 288230376151711744, ceiling(288230376151711746, 288230376151711744) = 576460752303423488, ceiling(-288230376151711746, 288230376151711744) = 0
     2153ceiling(576460752303423488, 576460752303423488) = 576460752303423488, ceiling(576460752303423490, 576460752303423488) = 1152921504606846976, ceiling(-576460752303423490, 576460752303423488) = 0
     2154ceiling(1152921504606846976, 1152921504606846976) = 1152921504606846976, ceiling(1152921504606846978, 1152921504606846976) = 2305843009213693952, ceiling(-1152921504606846978, 1152921504606846976) = 0
     2155ceiling(2305843009213693952, 2305843009213693952) = 2305843009213693952, ceiling(2305843009213693954, 2305843009213693952) = 4611686018427387904, ceiling(-2305843009213693954, 2305843009213693952) = 0
     2156ceiling(4611686018427387904, 4611686018427387904) = 4611686018427387904, ceiling(4611686018427387906, 4611686018427387904) = -4611686018427387904, ceiling(-4611686018427387906, 4611686018427387904) = 0
     2157ceiling(-9223372036854775808, -9223372036854775808) = -9223372036854775808, ceiling(-9223372036854775806, -9223372036854775808) = 0, ceiling(9223372036854775806, -9223372036854775808) = 0
    17872158
    17882159unsigned long int
    17892160ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(18446744073709551613, 1) = 18446744073709551613
    1790 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(18446744073709551612, 2) = 9223372036854775806
    1791 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(18446744073709551610, 4) = 4611686018427387903
    1792 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(18446744073709551606, 8) = 2305843009213693951
    1793 ceiling(16, 16) = 1, ceiling(18, 16) = 2, ceiling(18446744073709551598, 16) = 1152921504606846975
    1794 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(18446744073709551582, 32) = 576460752303423487
    1795 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(18446744073709551550, 64) = 288230376151711743
    1796 ceiling(128, 128) = 1, ceiling(130, 128) = 2, ceiling(18446744073709551486, 128) = 144115188075855871
    1797 ceiling(256, 256) = 1, ceiling(258, 256) = 2, ceiling(18446744073709551358, 256) = 72057594037927935
    1798 ceiling(512, 512) = 1, ceiling(514, 512) = 2, ceiling(18446744073709551102, 512) = 36028797018963967
    1799 ceiling(1024, 1024) = 1, ceiling(1026, 1024) = 2, ceiling(18446744073709550590, 1024) = 18014398509481983
    1800 ceiling(2048, 2048) = 1, ceiling(2050, 2048) = 2, ceiling(18446744073709549566, 2048) = 9007199254740991
    1801 ceiling(4096, 4096) = 1, ceiling(4098, 4096) = 2, ceiling(18446744073709547518, 4096) = 4503599627370495
    1802 ceiling(8192, 8192) = 1, ceiling(8194, 8192) = 2, ceiling(18446744073709543422, 8192) = 2251799813685247
    1803 ceiling(16384, 16384) = 1, ceiling(16386, 16384) = 2, ceiling(18446744073709535230, 16384) = 1125899906842623
    1804 ceiling(32768, 32768) = 1, ceiling(32770, 32768) = 2, ceiling(18446744073709518846, 32768) = 562949953421311
    1805 ceiling(65536, 65536) = 1, ceiling(65538, 65536) = 2, ceiling(18446744073709486078, 65536) = 281474976710655
    1806 ceiling(131072, 131072) = 1, ceiling(131074, 131072) = 2, ceiling(18446744073709420542, 131072) = 140737488355327
    1807 ceiling(262144, 262144) = 1, ceiling(262146, 262144) = 2, ceiling(18446744073709289470, 262144) = 70368744177663
    1808 ceiling(524288, 524288) = 1, ceiling(524290, 524288) = 2, ceiling(18446744073709027326, 524288) = 35184372088831
    1809 ceiling(1048576, 1048576) = 1, ceiling(1048578, 1048576) = 2, ceiling(18446744073708503038, 1048576) = 17592186044415
    1810 ceiling(2097152, 2097152) = 1, ceiling(2097154, 2097152) = 2, ceiling(18446744073707454462, 2097152) = 8796093022207
    1811 ceiling(4194304, 4194304) = 1, ceiling(4194306, 4194304) = 2, ceiling(18446744073705357310, 4194304) = 4398046511103
    1812 ceiling(8388608, 8388608) = 1, ceiling(8388610, 8388608) = 2, ceiling(18446744073701163006, 8388608) = 2199023255551
    1813 ceiling(16777216, 16777216) = 1, ceiling(16777218, 16777216) = 2, ceiling(18446744073692774398, 16777216) = 1099511627775
    1814 ceiling(33554432, 33554432) = 1, ceiling(33554434, 33554432) = 2, ceiling(18446744073675997182, 33554432) = 549755813887
    1815 ceiling(67108864, 67108864) = 1, ceiling(67108866, 67108864) = 2, ceiling(18446744073642442750, 67108864) = 274877906943
    1816 ceiling(134217728, 134217728) = 1, ceiling(134217730, 134217728) = 2, ceiling(18446744073575333886, 134217728) = 137438953471
    1817 ceiling(268435456, 268435456) = 1, ceiling(268435458, 268435456) = 2, ceiling(18446744073441116158, 268435456) = 68719476735
    1818 ceiling(536870912, 536870912) = 1, ceiling(536870914, 536870912) = 2, ceiling(18446744073172680702, 536870912) = 34359738367
    1819 ceiling(1073741824, 1073741824) = 1, ceiling(1073741826, 1073741824) = 2, ceiling(18446744072635809790, 1073741824) = 17179869183
    1820 ceiling(2147483648, 2147483648) = 1, ceiling(2147483650, 2147483648) = 2, ceiling(18446744071562067966, 2147483648) = 8589934591
    1821 ceiling(4294967296, 4294967296) = 1, ceiling(4294967298, 4294967296) = 2, ceiling(18446744069414584318, 4294967296) = 4294967295
    1822 ceiling(8589934592, 8589934592) = 1, ceiling(8589934594, 8589934592) = 2, ceiling(18446744065119617022, 8589934592) = 2147483647
    1823 ceiling(17179869184, 17179869184) = 1, ceiling(17179869186, 17179869184) = 2, ceiling(18446744056529682430, 17179869184) = 1073741823
    1824 ceiling(34359738368, 34359738368) = 1, ceiling(34359738370, 34359738368) = 2, ceiling(18446744039349813246, 34359738368) = 536870911
    1825 ceiling(68719476736, 68719476736) = 1, ceiling(68719476738, 68719476736) = 2, ceiling(18446744004990074878, 68719476736) = 268435455
    1826 ceiling(137438953472, 137438953472) = 1, ceiling(137438953474, 137438953472) = 2, ceiling(18446743936270598142, 137438953472) = 134217727
    1827 ceiling(274877906944, 274877906944) = 1, ceiling(274877906946, 274877906944) = 2, ceiling(18446743798831644670, 274877906944) = 67108863
    1828 ceiling(549755813888, 549755813888) = 1, ceiling(549755813890, 549755813888) = 2, ceiling(18446743523953737726, 549755813888) = 33554431
    1829 ceiling(1099511627776, 1099511627776) = 1, ceiling(1099511627778, 1099511627776) = 2, ceiling(18446742974197923838, 1099511627776) = 16777215
    1830 ceiling(2199023255552, 2199023255552) = 1, ceiling(2199023255554, 2199023255552) = 2, ceiling(18446741874686296062, 2199023255552) = 8388607
    1831 ceiling(4398046511104, 4398046511104) = 1, ceiling(4398046511106, 4398046511104) = 2, ceiling(18446739675663040510, 4398046511104) = 4194303
    1832 ceiling(8796093022208, 8796093022208) = 1, ceiling(8796093022210, 8796093022208) = 2, ceiling(18446735277616529406, 8796093022208) = 2097151
    1833 ceiling(17592186044416, 17592186044416) = 1, ceiling(17592186044418, 17592186044416) = 2, ceiling(18446726481523507198, 17592186044416) = 1048575
    1834 ceiling(35184372088832, 35184372088832) = 1, ceiling(35184372088834, 35184372088832) = 2, ceiling(18446708889337462782, 35184372088832) = 524287
    1835 ceiling(70368744177664, 70368744177664) = 1, ceiling(70368744177666, 70368744177664) = 2, ceiling(18446673704965373950, 70368744177664) = 262143
    1836 ceiling(140737488355328, 140737488355328) = 1, ceiling(140737488355330, 140737488355328) = 2, ceiling(18446603336221196286, 140737488355328) = 131071
    1837 ceiling(281474976710656, 281474976710656) = 1, ceiling(281474976710658, 281474976710656) = 2, ceiling(18446462598732840958, 281474976710656) = 65535
    1838 ceiling(562949953421312, 562949953421312) = 1, ceiling(562949953421314, 562949953421312) = 2, ceiling(18446181123756130302, 562949953421312) = 32767
    1839 ceiling(1125899906842624, 1125899906842624) = 1, ceiling(1125899906842626, 1125899906842624) = 2, ceiling(18445618173802708990, 1125899906842624) = 16383
    1840 ceiling(2251799813685248, 2251799813685248) = 1, ceiling(2251799813685250, 2251799813685248) = 2, ceiling(18444492273895866366, 2251799813685248) = 8191
    1841 ceiling(4503599627370496, 4503599627370496) = 1, ceiling(4503599627370498, 4503599627370496) = 2, ceiling(18442240474082181118, 4503599627370496) = 4095
    1842 ceiling(9007199254740992, 9007199254740992) = 1, ceiling(9007199254740994, 9007199254740992) = 2, ceiling(18437736874454810622, 9007199254740992) = 2047
    1843 ceiling(18014398509481984, 18014398509481984) = 1, ceiling(18014398509481986, 18014398509481984) = 2, ceiling(18428729675200069630, 18014398509481984) = 1023
    1844 ceiling(36028797018963968, 36028797018963968) = 1, ceiling(36028797018963970, 36028797018963968) = 2, ceiling(18410715276690587646, 36028797018963968) = 511
    1845 ceiling(72057594037927936, 72057594037927936) = 1, ceiling(72057594037927938, 72057594037927936) = 2, ceiling(18374686479671623678, 72057594037927936) = 255
    1846 ceiling(144115188075855872, 144115188075855872) = 1, ceiling(144115188075855874, 144115188075855872) = 2, ceiling(18302628885633695742, 144115188075855872) = 127
    1847 ceiling(288230376151711744, 288230376151711744) = 1, ceiling(288230376151711746, 288230376151711744) = 2, ceiling(18158513697557839870, 288230376151711744) = 63
    1848 ceiling(576460752303423488, 576460752303423488) = 1, ceiling(576460752303423490, 576460752303423488) = 2, ceiling(17870283321406128126, 576460752303423488) = 31
    1849 ceiling(1152921504606846976, 1152921504606846976) = 1, ceiling(1152921504606846978, 1152921504606846976) = 2, ceiling(17293822569102704638, 1152921504606846976) = 15
    1850 ceiling(2305843009213693952, 2305843009213693952) = 1, ceiling(2305843009213693954, 2305843009213693952) = 2, ceiling(16140901064495857662, 2305843009213693952) = 7
    1851 ceiling(4611686018427387904, 4611686018427387904) = 1, ceiling(4611686018427387906, 4611686018427387904) = 2, ceiling(13835058055282163710, 4611686018427387904) = 3
    1852 ceiling(9223372036854775808, 9223372036854775808) = 1, ceiling(9223372036854775810, 9223372036854775808) = 0, ceiling(9223372036854775806, 9223372036854775808) = 1
     2161ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(18446744073709551612, 2) = 18446744073709551612
     2162ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(18446744073709551610, 4) = 18446744073709551612
     2163ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(18446744073709551606, 8) = 18446744073709551608
     2164ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(18446744073709551598, 16) = 18446744073709551600
     2165ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(18446744073709551582, 32) = 18446744073709551584
     2166ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(18446744073709551550, 64) = 18446744073709551552
     2167ceiling(128, 128) = 128, ceiling(130, 128) = 256, ceiling(18446744073709551486, 128) = 18446744073709551488
     2168ceiling(256, 256) = 256, ceiling(258, 256) = 512, ceiling(18446744073709551358, 256) = 18446744073709551360
     2169ceiling(512, 512) = 512, ceiling(514, 512) = 1024, ceiling(18446744073709551102, 512) = 18446744073709551104
     2170ceiling(1024, 1024) = 1024, ceiling(1026, 1024) = 2048, ceiling(18446744073709550590, 1024) = 18446744073709550592
     2171ceiling(2048, 2048) = 2048, ceiling(2050, 2048) = 4096, ceiling(18446744073709549566, 2048) = 18446744073709549568
     2172ceiling(4096, 4096) = 4096, ceiling(4098, 4096) = 8192, ceiling(18446744073709547518, 4096) = 18446744073709547520
     2173ceiling(8192, 8192) = 8192, ceiling(8194, 8192) = 16384, ceiling(18446744073709543422, 8192) = 18446744073709543424
     2174ceiling(16384, 16384) = 16384, ceiling(16386, 16384) = 32768, ceiling(18446744073709535230, 16384) = 18446744073709535232
     2175ceiling(32768, 32768) = 32768, ceiling(32770, 32768) = 65536, ceiling(18446744073709518846, 32768) = 18446744073709518848
     2176ceiling(65536, 65536) = 65536, ceiling(65538, 65536) = 131072, ceiling(18446744073709486078, 65536) = 18446744073709486080
     2177ceiling(131072, 131072) = 131072, ceiling(131074, 131072) = 262144, ceiling(18446744073709420542, 131072) = 18446744073709420544
     2178ceiling(262144, 262144) = 262144, ceiling(262146, 262144) = 524288, ceiling(18446744073709289470, 262144) = 18446744073709289472
     2179ceiling(524288, 524288) = 524288, ceiling(524290, 524288) = 1048576, ceiling(18446744073709027326, 524288) = 18446744073709027328
     2180ceiling(1048576, 1048576) = 1048576, ceiling(1048578, 1048576) = 2097152, ceiling(18446744073708503038, 1048576) = 18446744073708503040
     2181ceiling(2097152, 2097152) = 2097152, ceiling(2097154, 2097152) = 4194304, ceiling(18446744073707454462, 2097152) = 18446744073707454464
     2182ceiling(4194304, 4194304) = 4194304, ceiling(4194306, 4194304) = 8388608, ceiling(18446744073705357310, 4194304) = 18446744073705357312
     2183ceiling(8388608, 8388608) = 8388608, ceiling(8388610, 8388608) = 16777216, ceiling(18446744073701163006, 8388608) = 18446744073701163008
     2184ceiling(16777216, 16777216) = 16777216, ceiling(16777218, 16777216) = 33554432, ceiling(18446744073692774398, 16777216) = 18446744073692774400
     2185ceiling(33554432, 33554432) = 33554432, ceiling(33554434, 33554432) = 67108864, ceiling(18446744073675997182, 33554432) = 18446744073675997184
     2186ceiling(67108864, 67108864) = 67108864, ceiling(67108866, 67108864) = 134217728, ceiling(18446744073642442750, 67108864) = 18446744073642442752
     2187ceiling(134217728, 134217728) = 134217728, ceiling(134217730, 134217728) = 268435456, ceiling(18446744073575333886, 134217728) = 18446744073575333888
     2188ceiling(268435456, 268435456) = 268435456, ceiling(268435458, 268435456) = 536870912, ceiling(18446744073441116158, 268435456) = 18446744073441116160
     2189ceiling(536870912, 536870912) = 536870912, ceiling(536870914, 536870912) = 1073741824, ceiling(18446744073172680702, 536870912) = 18446744073172680704
     2190ceiling(1073741824, 1073741824) = 1073741824, ceiling(1073741826, 1073741824) = 2147483648, ceiling(18446744072635809790, 1073741824) = 18446744072635809792
     2191ceiling(2147483648, 2147483648) = 2147483648, ceiling(2147483650, 2147483648) = 4294967296, ceiling(18446744071562067966, 2147483648) = 18446744071562067968
     2192ceiling(4294967296, 4294967296) = 4294967296, ceiling(4294967298, 4294967296) = 8589934592, ceiling(18446744069414584318, 4294967296) = 18446744069414584320
     2193ceiling(8589934592, 8589934592) = 8589934592, ceiling(8589934594, 8589934592) = 17179869184, ceiling(18446744065119617022, 8589934592) = 18446744065119617024
     2194ceiling(17179869184, 17179869184) = 17179869184, ceiling(17179869186, 17179869184) = 34359738368, ceiling(18446744056529682430, 17179869184) = 18446744056529682432
     2195ceiling(34359738368, 34359738368) = 34359738368, ceiling(34359738370, 34359738368) = 68719476736, ceiling(18446744039349813246, 34359738368) = 18446744039349813248
     2196ceiling(68719476736, 68719476736) = 68719476736, ceiling(68719476738, 68719476736) = 137438953472, ceiling(18446744004990074878, 68719476736) = 18446744004990074880
     2197ceiling(137438953472, 137438953472) = 137438953472, ceiling(137438953474, 137438953472) = 274877906944, ceiling(18446743936270598142, 137438953472) = 18446743936270598144
     2198ceiling(274877906944, 274877906944) = 274877906944, ceiling(274877906946, 274877906944) = 549755813888, ceiling(18446743798831644670, 274877906944) = 18446743798831644672
     2199ceiling(549755813888, 549755813888) = 549755813888, ceiling(549755813890, 549755813888) = 1099511627776, ceiling(18446743523953737726, 549755813888) = 18446743523953737728
     2200ceiling(1099511627776, 1099511627776) = 1099511627776, ceiling(1099511627778, 1099511627776) = 2199023255552, ceiling(18446742974197923838, 1099511627776) = 18446742974197923840
     2201ceiling(2199023255552, 2199023255552) = 2199023255552, ceiling(2199023255554, 2199023255552) = 4398046511104, ceiling(18446741874686296062, 2199023255552) = 18446741874686296064
     2202ceiling(4398046511104, 4398046511104) = 4398046511104, ceiling(4398046511106, 4398046511104) = 8796093022208, ceiling(18446739675663040510, 4398046511104) = 18446739675663040512
     2203ceiling(8796093022208, 8796093022208) = 8796093022208, ceiling(8796093022210, 8796093022208) = 17592186044416, ceiling(18446735277616529406, 8796093022208) = 18446735277616529408
     2204ceiling(17592186044416, 17592186044416) = 17592186044416, ceiling(17592186044418, 17592186044416) = 35184372088832, ceiling(18446726481523507198, 17592186044416) = 18446726481523507200
     2205ceiling(35184372088832, 35184372088832) = 35184372088832, ceiling(35184372088834, 35184372088832) = 70368744177664, ceiling(18446708889337462782, 35184372088832) = 18446708889337462784
     2206ceiling(70368744177664, 70368744177664) = 70368744177664, ceiling(70368744177666, 70368744177664) = 140737488355328, ceiling(18446673704965373950, 70368744177664) = 18446673704965373952
     2207ceiling(140737488355328, 140737488355328) = 140737488355328, ceiling(140737488355330, 140737488355328) = 281474976710656, ceiling(18446603336221196286, 140737488355328) = 18446603336221196288
     2208ceiling(281474976710656, 281474976710656) = 281474976710656, ceiling(281474976710658, 281474976710656) = 562949953421312, ceiling(18446462598732840958, 281474976710656) = 18446462598732840960
     2209ceiling(562949953421312, 562949953421312) = 562949953421312, ceiling(562949953421314, 562949953421312) = 1125899906842624, ceiling(18446181123756130302, 562949953421312) = 18446181123756130304
     2210ceiling(1125899906842624, 1125899906842624) = 1125899906842624, ceiling(1125899906842626, 1125899906842624) = 2251799813685248, ceiling(18445618173802708990, 1125899906842624) = 18445618173802708992
     2211ceiling(2251799813685248, 2251799813685248) = 2251799813685248, ceiling(2251799813685250, 2251799813685248) = 4503599627370496, ceiling(18444492273895866366, 2251799813685248) = 18444492273895866368
     2212ceiling(4503599627370496, 4503599627370496) = 4503599627370496, ceiling(4503599627370498, 4503599627370496) = 9007199254740992, ceiling(18442240474082181118, 4503599627370496) = 18442240474082181120
     2213ceiling(9007199254740992, 9007199254740992) = 9007199254740992, ceiling(9007199254740994, 9007199254740992) = 18014398509481984, ceiling(18437736874454810622, 9007199254740992) = 18437736874454810624
     2214ceiling(18014398509481984, 18014398509481984) = 18014398509481984, ceiling(18014398509481986, 18014398509481984) = 36028797018963968, ceiling(18428729675200069630, 18014398509481984) = 18428729675200069632
     2215ceiling(36028797018963968, 36028797018963968) = 36028797018963968, ceiling(36028797018963970, 36028797018963968) = 72057594037927936, ceiling(18410715276690587646, 36028797018963968) = 18410715276690587648
     2216ceiling(72057594037927936, 72057594037927936) = 72057594037927936, ceiling(72057594037927938, 72057594037927936) = 144115188075855872, ceiling(18374686479671623678, 72057594037927936) = 18374686479671623680
     2217ceiling(144115188075855872, 144115188075855872) = 144115188075855872, ceiling(144115188075855874, 144115188075855872) = 288230376151711744, ceiling(18302628885633695742, 144115188075855872) = 18302628885633695744
     2218ceiling(288230376151711744, 288230376151711744) = 288230376151711744, ceiling(288230376151711746, 288230376151711744) = 576460752303423488, ceiling(18158513697557839870, 288230376151711744) = 18158513697557839872
     2219ceiling(576460752303423488, 576460752303423488) = 576460752303423488, ceiling(576460752303423490, 576460752303423488) = 1152921504606846976, ceiling(17870283321406128126, 576460752303423488) = 17870283321406128128
     2220ceiling(1152921504606846976, 1152921504606846976) = 1152921504606846976, ceiling(1152921504606846978, 1152921504606846976) = 2305843009213693952, ceiling(17293822569102704638, 1152921504606846976) = 17293822569102704640
     2221ceiling(2305843009213693952, 2305843009213693952) = 2305843009213693952, ceiling(2305843009213693954, 2305843009213693952) = 4611686018427387904, ceiling(16140901064495857662, 2305843009213693952) = 16140901064495857664
     2222ceiling(4611686018427387904, 4611686018427387904) = 4611686018427387904, ceiling(4611686018427387906, 4611686018427387904) = 9223372036854775808, ceiling(13835058055282163710, 4611686018427387904) = 13835058055282163712
     2223ceiling(9223372036854775808, 9223372036854775808) = 9223372036854775808, ceiling(9223372036854775810, 9223372036854775808) = 0, ceiling(9223372036854775806, 9223372036854775808) = 9223372036854775808
    18532224
    18542225long long int
    18552226ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(-3, 1) = -3
    1856 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(-4, 2) = -1
    1857 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(-6, 4) = 0
    1858 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(-10, 8) = 0
    1859 ceiling(16, 16) = 1, ceiling(18, 16) = 2, ceiling(-18, 16) = 0
    1860 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(-34, 32) = 0
    1861 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(-66, 64) = 0
    1862 ceiling(128, 128) = 1, ceiling(130, 128) = 2, ceiling(-130, 128) = 0
    1863 ceiling(256, 256) = 1, ceiling(258, 256) = 2, ceiling(-258, 256) = 0
    1864 ceiling(512, 512) = 1, ceiling(514, 512) = 2, ceiling(-514, 512) = 0
    1865 ceiling(1024, 1024) = 1, ceiling(1026, 1024) = 2, ceiling(-1026, 1024) = 0
    1866 ceiling(2048, 2048) = 1, ceiling(2050, 2048) = 2, ceiling(-2050, 2048) = 0
    1867 ceiling(4096, 4096) = 1, ceiling(4098, 4096) = 2, ceiling(-4098, 4096) = 0
    1868 ceiling(8192, 8192) = 1, ceiling(8194, 8192) = 2, ceiling(-8194, 8192) = 0
    1869 ceiling(16384, 16384) = 1, ceiling(16386, 16384) = 2, ceiling(-16386, 16384) = 0
    1870 ceiling(32768, 32768) = 1, ceiling(32770, 32768) = 2, ceiling(-32770, 32768) = 0
    1871 ceiling(65536, 65536) = 1, ceiling(65538, 65536) = 2, ceiling(-65538, 65536) = 0
    1872 ceiling(131072, 131072) = 1, ceiling(131074, 131072) = 2, ceiling(-131074, 131072) = 0
    1873 ceiling(262144, 262144) = 1, ceiling(262146, 262144) = 2, ceiling(-262146, 262144) = 0
    1874 ceiling(524288, 524288) = 1, ceiling(524290, 524288) = 2, ceiling(-524290, 524288) = 0
    1875 ceiling(1048576, 1048576) = 1, ceiling(1048578, 1048576) = 2, ceiling(-1048578, 1048576) = 0
    1876 ceiling(2097152, 2097152) = 1, ceiling(2097154, 2097152) = 2, ceiling(-2097154, 2097152) = 0
    1877 ceiling(4194304, 4194304) = 1, ceiling(4194306, 4194304) = 2, ceiling(-4194306, 4194304) = 0
    1878 ceiling(8388608, 8388608) = 1, ceiling(8388610, 8388608) = 2, ceiling(-8388610, 8388608) = 0
    1879 ceiling(16777216, 16777216) = 1, ceiling(16777218, 16777216) = 2, ceiling(-16777218, 16777216) = 0
    1880 ceiling(33554432, 33554432) = 1, ceiling(33554434, 33554432) = 2, ceiling(-33554434, 33554432) = 0
    1881 ceiling(67108864, 67108864) = 1, ceiling(67108866, 67108864) = 2, ceiling(-67108866, 67108864) = 0
    1882 ceiling(134217728, 134217728) = 1, ceiling(134217730, 134217728) = 2, ceiling(-134217730, 134217728) = 0
    1883 ceiling(268435456, 268435456) = 1, ceiling(268435458, 268435456) = 2, ceiling(-268435458, 268435456) = 0
    1884 ceiling(536870912, 536870912) = 1, ceiling(536870914, 536870912) = 2, ceiling(-536870914, 536870912) = 0
    1885 ceiling(1073741824, 1073741824) = 1, ceiling(1073741826, 1073741824) = 2, ceiling(-1073741826, 1073741824) = 0
    1886 ceiling(2147483648, 2147483648) = 1, ceiling(2147483650, 2147483648) = 2, ceiling(-2147483650, 2147483648) = 0
    1887 ceiling(4294967296, 4294967296) = 1, ceiling(4294967298, 4294967296) = 2, ceiling(-4294967298, 4294967296) = 0
    1888 ceiling(8589934592, 8589934592) = 1, ceiling(8589934594, 8589934592) = 2, ceiling(-8589934594, 8589934592) = 0
    1889 ceiling(17179869184, 17179869184) = 1, ceiling(17179869186, 17179869184) = 2, ceiling(-17179869186, 17179869184) = 0
    1890 ceiling(34359738368, 34359738368) = 1, ceiling(34359738370, 34359738368) = 2, ceiling(-34359738370, 34359738368) = 0
    1891 ceiling(68719476736, 68719476736) = 1, ceiling(68719476738, 68719476736) = 2, ceiling(-68719476738, 68719476736) = 0
    1892 ceiling(137438953472, 137438953472) = 1, ceiling(137438953474, 137438953472) = 2, ceiling(-137438953474, 137438953472) = 0
    1893 ceiling(274877906944, 274877906944) = 1, ceiling(274877906946, 274877906944) = 2, ceiling(-274877906946, 274877906944) = 0
    1894 ceiling(549755813888, 549755813888) = 1, ceiling(549755813890, 549755813888) = 2, ceiling(-549755813890, 549755813888) = 0
    1895 ceiling(1099511627776, 1099511627776) = 1, ceiling(1099511627778, 1099511627776) = 2, ceiling(-1099511627778, 1099511627776) = 0
    1896 ceiling(2199023255552, 2199023255552) = 1, ceiling(2199023255554, 2199023255552) = 2, ceiling(-2199023255554, 2199023255552) = 0
    1897 ceiling(4398046511104, 4398046511104) = 1, ceiling(4398046511106, 4398046511104) = 2, ceiling(-4398046511106, 4398046511104) = 0
    1898 ceiling(8796093022208, 8796093022208) = 1, ceiling(8796093022210, 8796093022208) = 2, ceiling(-8796093022210, 8796093022208) = 0
    1899 ceiling(17592186044416, 17592186044416) = 1, ceiling(17592186044418, 17592186044416) = 2, ceiling(-17592186044418, 17592186044416) = 0
    1900 ceiling(35184372088832, 35184372088832) = 1, ceiling(35184372088834, 35184372088832) = 2, ceiling(-35184372088834, 35184372088832) = 0
    1901 ceiling(70368744177664, 70368744177664) = 1, ceiling(70368744177666, 70368744177664) = 2, ceiling(-70368744177666, 70368744177664) = 0
    1902 ceiling(140737488355328, 140737488355328) = 1, ceiling(140737488355330, 140737488355328) = 2, ceiling(-140737488355330, 140737488355328) = 0
    1903 ceiling(281474976710656, 281474976710656) = 1, ceiling(281474976710658, 281474976710656) = 2, ceiling(-281474976710658, 281474976710656) = 0
    1904 ceiling(562949953421312, 562949953421312) = 1, ceiling(562949953421314, 562949953421312) = 2, ceiling(-562949953421314, 562949953421312) = 0
    1905 ceiling(1125899906842624, 1125899906842624) = 1, ceiling(1125899906842626, 1125899906842624) = 2, ceiling(-1125899906842626, 1125899906842624) = 0
    1906 ceiling(2251799813685248, 2251799813685248) = 1, ceiling(2251799813685250, 2251799813685248) = 2, ceiling(-2251799813685250, 2251799813685248) = 0
    1907 ceiling(4503599627370496, 4503599627370496) = 1, ceiling(4503599627370498, 4503599627370496) = 2, ceiling(-4503599627370498, 4503599627370496) = 0
    1908 ceiling(9007199254740992, 9007199254740992) = 1, ceiling(9007199254740994, 9007199254740992) = 2, ceiling(-9007199254740994, 9007199254740992) = 0
    1909 ceiling(18014398509481984, 18014398509481984) = 1, ceiling(18014398509481986, 18014398509481984) = 2, ceiling(-18014398509481986, 18014398509481984) = 0
    1910 ceiling(36028797018963968, 36028797018963968) = 1, ceiling(36028797018963970, 36028797018963968) = 2, ceiling(-36028797018963970, 36028797018963968) = 0
    1911 ceiling(72057594037927936, 72057594037927936) = 1, ceiling(72057594037927938, 72057594037927936) = 2, ceiling(-72057594037927938, 72057594037927936) = 0
    1912 ceiling(144115188075855872, 144115188075855872) = 1, ceiling(144115188075855874, 144115188075855872) = 2, ceiling(-144115188075855874, 144115188075855872) = 0
    1913 ceiling(288230376151711744, 288230376151711744) = 1, ceiling(288230376151711746, 288230376151711744) = 2, ceiling(-288230376151711746, 288230376151711744) = 0
    1914 ceiling(576460752303423488, 576460752303423488) = 1, ceiling(576460752303423490, 576460752303423488) = 2, ceiling(-576460752303423490, 576460752303423488) = 0
    1915 ceiling(1152921504606846976, 1152921504606846976) = 1, ceiling(1152921504606846978, 1152921504606846976) = 2, ceiling(-1152921504606846978, 1152921504606846976) = 0
    1916 ceiling(2305843009213693952, 2305843009213693952) = 1, ceiling(2305843009213693954, 2305843009213693952) = 2, ceiling(-2305843009213693954, 2305843009213693952) = 0
    1917 ceiling(4611686018427387904, 4611686018427387904) = 1, ceiling(4611686018427387906, 4611686018427387904) = -1, ceiling(-4611686018427387906, 4611686018427387904) = 0
    1918 ceiling(-9223372036854775808, -9223372036854775808) = 0, ceiling(-9223372036854775806, -9223372036854775808) = 0, ceiling(9223372036854775806, -9223372036854775808) = 0
     2227ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(-4, 2) = -4
     2228ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(-6, 4) = 0
     2229ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(-10, 8) = 0
     2230ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(-18, 16) = 0
     2231ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(-34, 32) = 0
     2232ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(-66, 64) = 0
     2233ceiling(128, 128) = 128, ceiling(130, 128) = 256, ceiling(-130, 128) = 0
     2234ceiling(256, 256) = 256, ceiling(258, 256) = 512, ceiling(-258, 256) = 0
     2235ceiling(512, 512) = 512, ceiling(514, 512) = 1024, ceiling(-514, 512) = 0
     2236ceiling(1024, 1024) = 1024, ceiling(1026, 1024) = 2048, ceiling(-1026, 1024) = 0
     2237ceiling(2048, 2048) = 2048, ceiling(2050, 2048) = 4096, ceiling(-2050, 2048) = 0
     2238ceiling(4096, 4096) = 4096, ceiling(4098, 4096) = 8192, ceiling(-4098, 4096) = 0
     2239ceiling(8192, 8192) = 8192, ceiling(8194, 8192) = 16384, ceiling(-8194, 8192) = 0
     2240ceiling(16384, 16384) = 16384, ceiling(16386, 16384) = 32768, ceiling(-16386, 16384) = 0
     2241ceiling(32768, 32768) = 32768, ceiling(32770, 32768) = 65536, ceiling(-32770, 32768) = 0
     2242ceiling(65536, 65536) = 65536, ceiling(65538, 65536) = 131072, ceiling(-65538, 65536) = 0
     2243ceiling(131072, 131072) = 131072, ceiling(131074, 131072) = 262144, ceiling(-131074, 131072) = 0
     2244ceiling(262144, 262144) = 262144, ceiling(262146, 262144) = 524288, ceiling(-262146, 262144) = 0
     2245ceiling(524288, 524288) = 524288, ceiling(524290, 524288) = 1048576, ceiling(-524290, 524288) = 0
     2246ceiling(1048576, 1048576) = 1048576, ceiling(1048578, 1048576) = 2097152, ceiling(-1048578, 1048576) = 0
     2247ceiling(2097152, 2097152) = 2097152, ceiling(2097154, 2097152) = 4194304, ceiling(-2097154, 2097152) = 0
     2248ceiling(4194304, 4194304) = 4194304, ceiling(4194306, 4194304) = 8388608, ceiling(-4194306, 4194304) = 0
     2249ceiling(8388608, 8388608) = 8388608, ceiling(8388610, 8388608) = 16777216, ceiling(-8388610, 8388608) = 0
     2250ceiling(16777216, 16777216) = 16777216, ceiling(16777218, 16777216) = 33554432, ceiling(-16777218, 16777216) = 0
     2251ceiling(33554432, 33554432) = 33554432, ceiling(33554434, 33554432) = 67108864, ceiling(-33554434, 33554432) = 0
     2252ceiling(67108864, 67108864) = 67108864, ceiling(67108866, 67108864) = 134217728, ceiling(-67108866, 67108864) = 0
     2253ceiling(134217728, 134217728) = 134217728, ceiling(134217730, 134217728) = 268435456, ceiling(-134217730, 134217728) = 0
     2254ceiling(268435456, 268435456) = 268435456, ceiling(268435458, 268435456) = 536870912, ceiling(-268435458, 268435456) = 0
     2255ceiling(536870912, 536870912) = 536870912, ceiling(536870914, 536870912) = 1073741824, ceiling(-536870914, 536870912) = 0
     2256ceiling(1073741824, 1073741824) = 1073741824, ceiling(1073741826, 1073741824) = 2147483648, ceiling(-1073741826, 1073741824) = 0
     2257ceiling(2147483648, 2147483648) = 2147483648, ceiling(2147483650, 2147483648) = 4294967296, ceiling(-2147483650, 2147483648) = 0
     2258ceiling(4294967296, 4294967296) = 4294967296, ceiling(4294967298, 4294967296) = 8589934592, ceiling(-4294967298, 4294967296) = 0
     2259ceiling(8589934592, 8589934592) = 8589934592, ceiling(8589934594, 8589934592) = 17179869184, ceiling(-8589934594, 8589934592) = 0
     2260ceiling(17179869184, 17179869184) = 17179869184, ceiling(17179869186, 17179869184) = 34359738368, ceiling(-17179869186, 17179869184) = 0
     2261ceiling(34359738368, 34359738368) = 34359738368, ceiling(34359738370, 34359738368) = 68719476736, ceiling(-34359738370, 34359738368) = 0
     2262ceiling(68719476736, 68719476736) = 68719476736, ceiling(68719476738, 68719476736) = 137438953472, ceiling(-68719476738, 68719476736) = 0
     2263ceiling(137438953472, 137438953472) = 137438953472, ceiling(137438953474, 137438953472) = 274877906944, ceiling(-137438953474, 137438953472) = 0
     2264ceiling(274877906944, 274877906944) = 274877906944, ceiling(274877906946, 274877906944) = 549755813888, ceiling(-274877906946, 274877906944) = 0
     2265ceiling(549755813888, 549755813888) = 549755813888, ceiling(549755813890, 549755813888) = 1099511627776, ceiling(-549755813890, 549755813888) = 0
     2266ceiling(1099511627776, 1099511627776) = 1099511627776, ceiling(1099511627778, 1099511627776) = 2199023255552, ceiling(-1099511627778, 1099511627776) = 0
     2267ceiling(2199023255552, 2199023255552) = 2199023255552, ceiling(2199023255554, 2199023255552) = 4398046511104, ceiling(-2199023255554, 2199023255552) = 0
     2268ceiling(4398046511104, 4398046511104) = 4398046511104, ceiling(4398046511106, 4398046511104) = 8796093022208, ceiling(-4398046511106, 4398046511104) = 0
     2269ceiling(8796093022208, 8796093022208) = 8796093022208, ceiling(8796093022210, 8796093022208) = 17592186044416, ceiling(-8796093022210, 8796093022208) = 0
     2270ceiling(17592186044416, 17592186044416) = 17592186044416, ceiling(17592186044418, 17592186044416) = 35184372088832, ceiling(-17592186044418, 17592186044416) = 0
     2271ceiling(35184372088832, 35184372088832) = 35184372088832, ceiling(35184372088834, 35184372088832) = 70368744177664, ceiling(-35184372088834, 35184372088832) = 0
     2272ceiling(70368744177664, 70368744177664) = 70368744177664, ceiling(70368744177666, 70368744177664) = 140737488355328, ceiling(-70368744177666, 70368744177664) = 0
     2273ceiling(140737488355328, 140737488355328) = 140737488355328, ceiling(140737488355330, 140737488355328) = 281474976710656, ceiling(-140737488355330, 140737488355328) = 0
     2274ceiling(281474976710656, 281474976710656) = 281474976710656, ceiling(281474976710658, 281474976710656) = 562949953421312, ceiling(-281474976710658, 281474976710656) = 0
     2275ceiling(562949953421312, 562949953421312) = 562949953421312, ceiling(562949953421314, 562949953421312) = 1125899906842624, ceiling(-562949953421314, 562949953421312) = 0
     2276ceiling(1125899906842624, 1125899906842624) = 1125899906842624, ceiling(1125899906842626, 1125899906842624) = 2251799813685248, ceiling(-1125899906842626, 1125899906842624) = 0
     2277ceiling(2251799813685248, 2251799813685248) = 2251799813685248, ceiling(2251799813685250, 2251799813685248) = 4503599627370496, ceiling(-2251799813685250, 2251799813685248) = 0
     2278ceiling(4503599627370496, 4503599627370496) = 4503599627370496, ceiling(4503599627370498, 4503599627370496) = 9007199254740992, ceiling(-4503599627370498, 4503599627370496) = 0
     2279ceiling(9007199254740992, 9007199254740992) = 9007199254740992, ceiling(9007199254740994, 9007199254740992) = 18014398509481984, ceiling(-9007199254740994, 9007199254740992) = 0
     2280ceiling(18014398509481984, 18014398509481984) = 18014398509481984, ceiling(18014398509481986, 18014398509481984) = 36028797018963968, ceiling(-18014398509481986, 18014398509481984) = 0
     2281ceiling(36028797018963968, 36028797018963968) = 36028797018963968, ceiling(36028797018963970, 36028797018963968) = 72057594037927936, ceiling(-36028797018963970, 36028797018963968) = 0
     2282ceiling(72057594037927936, 72057594037927936) = 72057594037927936, ceiling(72057594037927938, 72057594037927936) = 144115188075855872, ceiling(-72057594037927938, 72057594037927936) = 0
     2283ceiling(144115188075855872, 144115188075855872) = 144115188075855872, ceiling(144115188075855874, 144115188075855872) = 288230376151711744, ceiling(-144115188075855874, 144115188075855872) = 0
     2284ceiling(288230376151711744, 288230376151711744) = 288230376151711744, ceiling(288230376151711746, 288230376151711744) = 576460752303423488, ceiling(-288230376151711746, 288230376151711744) = 0
     2285ceiling(576460752303423488, 576460752303423488) = 576460752303423488, ceiling(576460752303423490, 576460752303423488) = 1152921504606846976, ceiling(-576460752303423490, 576460752303423488) = 0
     2286ceiling(1152921504606846976, 1152921504606846976) = 1152921504606846976, ceiling(1152921504606846978, 1152921504606846976) = 2305843009213693952, ceiling(-1152921504606846978, 1152921504606846976) = 0
     2287ceiling(2305843009213693952, 2305843009213693952) = 2305843009213693952, ceiling(2305843009213693954, 2305843009213693952) = 4611686018427387904, ceiling(-2305843009213693954, 2305843009213693952) = 0
     2288ceiling(4611686018427387904, 4611686018427387904) = 4611686018427387904, ceiling(4611686018427387906, 4611686018427387904) = -4611686018427387904, ceiling(-4611686018427387906, 4611686018427387904) = 0
     2289ceiling(-9223372036854775808, -9223372036854775808) = -9223372036854775808, ceiling(-9223372036854775806, -9223372036854775808) = 0, ceiling(9223372036854775806, -9223372036854775808) = 0
    19192290
    19202291unsigned long long int
    19212292ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(18446744073709551613, 1) = 18446744073709551613
    1922 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(18446744073709551612, 2) = 9223372036854775806
    1923 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(18446744073709551610, 4) = 4611686018427387903
    1924 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(18446744073709551606, 8) = 2305843009213693951
    1925 ceiling(16, 16) = 1, ceiling(18, 16) = 2, ceiling(18446744073709551598, 16) = 1152921504606846975
    1926 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(18446744073709551582, 32) = 576460752303423487
    1927 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(18446744073709551550, 64) = 288230376151711743
    1928 ceiling(128, 128) = 1, ceiling(130, 128) = 2, ceiling(18446744073709551486, 128) = 144115188075855871
    1929 ceiling(256, 256) = 1, ceiling(258, 256) = 2, ceiling(18446744073709551358, 256) = 72057594037927935
    1930 ceiling(512, 512) = 1, ceiling(514, 512) = 2, ceiling(18446744073709551102, 512) = 36028797018963967
    1931 ceiling(1024, 1024) = 1, ceiling(1026, 1024) = 2, ceiling(18446744073709550590, 1024) = 18014398509481983
    1932 ceiling(2048, 2048) = 1, ceiling(2050, 2048) = 2, ceiling(18446744073709549566, 2048) = 9007199254740991
    1933 ceiling(4096, 4096) = 1, ceiling(4098, 4096) = 2, ceiling(18446744073709547518, 4096) = 4503599627370495
    1934 ceiling(8192, 8192) = 1, ceiling(8194, 8192) = 2, ceiling(18446744073709543422, 8192) = 2251799813685247
    1935 ceiling(16384, 16384) = 1, ceiling(16386, 16384) = 2, ceiling(18446744073709535230, 16384) = 1125899906842623
    1936 ceiling(32768, 32768) = 1, ceiling(32770, 32768) = 2, ceiling(18446744073709518846, 32768) = 562949953421311
    1937 ceiling(65536, 65536) = 1, ceiling(65538, 65536) = 2, ceiling(18446744073709486078, 65536) = 281474976710655
    1938 ceiling(131072, 131072) = 1, ceiling(131074, 131072) = 2, ceiling(18446744073709420542, 131072) = 140737488355327
    1939 ceiling(262144, 262144) = 1, ceiling(262146, 262144) = 2, ceiling(18446744073709289470, 262144) = 70368744177663
    1940 ceiling(524288, 524288) = 1, ceiling(524290, 524288) = 2, ceiling(18446744073709027326, 524288) = 35184372088831
    1941 ceiling(1048576, 1048576) = 1, ceiling(1048578, 1048576) = 2, ceiling(18446744073708503038, 1048576) = 17592186044415
    1942 ceiling(2097152, 2097152) = 1, ceiling(2097154, 2097152) = 2, ceiling(18446744073707454462, 2097152) = 8796093022207
    1943 ceiling(4194304, 4194304) = 1, ceiling(4194306, 4194304) = 2, ceiling(18446744073705357310, 4194304) = 4398046511103
    1944 ceiling(8388608, 8388608) = 1, ceiling(8388610, 8388608) = 2, ceiling(18446744073701163006, 8388608) = 2199023255551
    1945 ceiling(16777216, 16777216) = 1, ceiling(16777218, 16777216) = 2, ceiling(18446744073692774398, 16777216) = 1099511627775
    1946 ceiling(33554432, 33554432) = 1, ceiling(33554434, 33554432) = 2, ceiling(18446744073675997182, 33554432) = 549755813887
    1947 ceiling(67108864, 67108864) = 1, ceiling(67108866, 67108864) = 2, ceiling(18446744073642442750, 67108864) = 274877906943
    1948 ceiling(134217728, 134217728) = 1, ceiling(134217730, 134217728) = 2, ceiling(18446744073575333886, 134217728) = 137438953471
    1949 ceiling(268435456, 268435456) = 1, ceiling(268435458, 268435456) = 2, ceiling(18446744073441116158, 268435456) = 68719476735
    1950 ceiling(536870912, 536870912) = 1, ceiling(536870914, 536870912) = 2, ceiling(18446744073172680702, 536870912) = 34359738367
    1951 ceiling(1073741824, 1073741824) = 1, ceiling(1073741826, 1073741824) = 2, ceiling(18446744072635809790, 1073741824) = 17179869183
    1952 ceiling(2147483648, 2147483648) = 1, ceiling(2147483650, 2147483648) = 2, ceiling(18446744071562067966, 2147483648) = 8589934591
    1953 ceiling(4294967296, 4294967296) = 1, ceiling(4294967298, 4294967296) = 2, ceiling(18446744069414584318, 4294967296) = 4294967295
    1954 ceiling(8589934592, 8589934592) = 1, ceiling(8589934594, 8589934592) = 2, ceiling(18446744065119617022, 8589934592) = 2147483647
    1955 ceiling(17179869184, 17179869184) = 1, ceiling(17179869186, 17179869184) = 2, ceiling(18446744056529682430, 17179869184) = 1073741823
    1956 ceiling(34359738368, 34359738368) = 1, ceiling(34359738370, 34359738368) = 2, ceiling(18446744039349813246, 34359738368) = 536870911
    1957 ceiling(68719476736, 68719476736) = 1, ceiling(68719476738, 68719476736) = 2, ceiling(18446744004990074878, 68719476736) = 268435455
    1958 ceiling(137438953472, 137438953472) = 1, ceiling(137438953474, 137438953472) = 2, ceiling(18446743936270598142, 137438953472) = 134217727
    1959 ceiling(274877906944, 274877906944) = 1, ceiling(274877906946, 274877906944) = 2, ceiling(18446743798831644670, 274877906944) = 67108863
    1960 ceiling(549755813888, 549755813888) = 1, ceiling(549755813890, 549755813888) = 2, ceiling(18446743523953737726, 549755813888) = 33554431
    1961 ceiling(1099511627776, 1099511627776) = 1, ceiling(1099511627778, 1099511627776) = 2, ceiling(18446742974197923838, 1099511627776) = 16777215
    1962 ceiling(2199023255552, 2199023255552) = 1, ceiling(2199023255554, 2199023255552) = 2, ceiling(18446741874686296062, 2199023255552) = 8388607
    1963 ceiling(4398046511104, 4398046511104) = 1, ceiling(4398046511106, 4398046511104) = 2, ceiling(18446739675663040510, 4398046511104) = 4194303
    1964 ceiling(8796093022208, 8796093022208) = 1, ceiling(8796093022210, 8796093022208) = 2, ceiling(18446735277616529406, 8796093022208) = 2097151
    1965 ceiling(17592186044416, 17592186044416) = 1, ceiling(17592186044418, 17592186044416) = 2, ceiling(18446726481523507198, 17592186044416) = 1048575
    1966 ceiling(35184372088832, 35184372088832) = 1, ceiling(35184372088834, 35184372088832) = 2, ceiling(18446708889337462782, 35184372088832) = 524287
    1967 ceiling(70368744177664, 70368744177664) = 1, ceiling(70368744177666, 70368744177664) = 2, ceiling(18446673704965373950, 70368744177664) = 262143
    1968 ceiling(140737488355328, 140737488355328) = 1, ceiling(140737488355330, 140737488355328) = 2, ceiling(18446603336221196286, 140737488355328) = 131071
    1969 ceiling(281474976710656, 281474976710656) = 1, ceiling(281474976710658, 281474976710656) = 2, ceiling(18446462598732840958, 281474976710656) = 65535
    1970 ceiling(562949953421312, 562949953421312) = 1, ceiling(562949953421314, 562949953421312) = 2, ceiling(18446181123756130302, 562949953421312) = 32767
    1971 ceiling(1125899906842624, 1125899906842624) = 1, ceiling(1125899906842626, 1125899906842624) = 2, ceiling(18445618173802708990, 1125899906842624) = 16383
    1972 ceiling(2251799813685248, 2251799813685248) = 1, ceiling(2251799813685250, 2251799813685248) = 2, ceiling(18444492273895866366, 2251799813685248) = 8191
    1973 ceiling(4503599627370496, 4503599627370496) = 1, ceiling(4503599627370498, 4503599627370496) = 2, ceiling(18442240474082181118, 4503599627370496) = 4095
    1974 ceiling(9007199254740992, 9007199254740992) = 1, ceiling(9007199254740994, 9007199254740992) = 2, ceiling(18437736874454810622, 9007199254740992) = 2047
    1975 ceiling(18014398509481984, 18014398509481984) = 1, ceiling(18014398509481986, 18014398509481984) = 2, ceiling(18428729675200069630, 18014398509481984) = 1023
    1976 ceiling(36028797018963968, 36028797018963968) = 1, ceiling(36028797018963970, 36028797018963968) = 2, ceiling(18410715276690587646, 36028797018963968) = 511
    1977 ceiling(72057594037927936, 72057594037927936) = 1, ceiling(72057594037927938, 72057594037927936) = 2, ceiling(18374686479671623678, 72057594037927936) = 255
    1978 ceiling(144115188075855872, 144115188075855872) = 1, ceiling(144115188075855874, 144115188075855872) = 2, ceiling(18302628885633695742, 144115188075855872) = 127
    1979 ceiling(288230376151711744, 288230376151711744) = 1, ceiling(288230376151711746, 288230376151711744) = 2, ceiling(18158513697557839870, 288230376151711744) = 63
    1980 ceiling(576460752303423488, 576460752303423488) = 1, ceiling(576460752303423490, 576460752303423488) = 2, ceiling(17870283321406128126, 576460752303423488) = 31
    1981 ceiling(1152921504606846976, 1152921504606846976) = 1, ceiling(1152921504606846978, 1152921504606846976) = 2, ceiling(17293822569102704638, 1152921504606846976) = 15
    1982 ceiling(2305843009213693952, 2305843009213693952) = 1, ceiling(2305843009213693954, 2305843009213693952) = 2, ceiling(16140901064495857662, 2305843009213693952) = 7
    1983 ceiling(4611686018427387904, 4611686018427387904) = 1, ceiling(4611686018427387906, 4611686018427387904) = 2, ceiling(13835058055282163710, 4611686018427387904) = 3
    1984 ceiling(9223372036854775808, 9223372036854775808) = 1, ceiling(9223372036854775810, 9223372036854775808) = 0, ceiling(9223372036854775806, 9223372036854775808) = 1
    1985 
     2293ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(18446744073709551612, 2) = 18446744073709551612
     2294ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(18446744073709551610, 4) = 18446744073709551612
     2295ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(18446744073709551606, 8) = 18446744073709551608
     2296ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(18446744073709551598, 16) = 18446744073709551600
     2297ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(18446744073709551582, 32) = 18446744073709551584
     2298ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(18446744073709551550, 64) = 18446744073709551552
     2299ceiling(128, 128) = 128, ceiling(130, 128) = 256, ceiling(18446744073709551486, 128) = 18446744073709551488
     2300ceiling(256, 256) = 256, ceiling(258, 256) = 512, ceiling(18446744073709551358, 256) = 18446744073709551360
     2301ceiling(512, 512) = 512, ceiling(514, 512) = 1024, ceiling(18446744073709551102, 512) = 18446744073709551104
     2302ceiling(1024, 1024) = 1024, ceiling(1026, 1024) = 2048, ceiling(18446744073709550590, 1024) = 18446744073709550592
     2303ceiling(2048, 2048) = 2048, ceiling(2050, 2048) = 4096, ceiling(18446744073709549566, 2048) = 18446744073709549568
     2304ceiling(4096, 4096) = 4096, ceiling(4098, 4096) = 8192, ceiling(18446744073709547518, 4096) = 18446744073709547520
     2305ceiling(8192, 8192) = 8192, ceiling(8194, 8192) = 16384, ceiling(18446744073709543422, 8192) = 18446744073709543424
     2306ceiling(16384, 16384) = 16384, ceiling(16386, 16384) = 32768, ceiling(18446744073709535230, 16384) = 18446744073709535232
     2307ceiling(32768, 32768) = 32768, ceiling(32770, 32768) = 65536, ceiling(18446744073709518846, 32768) = 18446744073709518848
     2308ceiling(65536, 65536) = 65536, ceiling(65538, 65536) = 131072, ceiling(18446744073709486078, 65536) = 18446744073709486080
     2309ceiling(131072, 131072) = 131072, ceiling(131074, 131072) = 262144, ceiling(18446744073709420542, 131072) = 18446744073709420544
     2310ceiling(262144, 262144) = 262144, ceiling(262146, 262144) = 524288, ceiling(18446744073709289470, 262144) = 18446744073709289472
     2311ceiling(524288, 524288) = 524288, ceiling(524290, 524288) = 1048576, ceiling(18446744073709027326, 524288) = 18446744073709027328
     2312ceiling(1048576, 1048576) = 1048576, ceiling(1048578, 1048576) = 2097152, ceiling(18446744073708503038, 1048576) = 18446744073708503040
     2313ceiling(2097152, 2097152) = 2097152, ceiling(2097154, 2097152) = 4194304, ceiling(18446744073707454462, 2097152) = 18446744073707454464
     2314ceiling(4194304, 4194304) = 4194304, ceiling(4194306, 4194304) = 8388608, ceiling(18446744073705357310, 4194304) = 18446744073705357312
     2315ceiling(8388608, 8388608) = 8388608, ceiling(8388610, 8388608) = 16777216, ceiling(18446744073701163006, 8388608) = 18446744073701163008
     2316ceiling(16777216, 16777216) = 16777216, ceiling(16777218, 16777216) = 33554432, ceiling(18446744073692774398, 16777216) = 18446744073692774400
     2317ceiling(33554432, 33554432) = 33554432, ceiling(33554434, 33554432) = 67108864, ceiling(18446744073675997182, 33554432) = 18446744073675997184
     2318ceiling(67108864, 67108864) = 67108864, ceiling(67108866, 67108864) = 134217728, ceiling(18446744073642442750, 67108864) = 18446744073642442752
     2319ceiling(134217728, 134217728) = 134217728, ceiling(134217730, 134217728) = 268435456, ceiling(18446744073575333886, 134217728) = 18446744073575333888
     2320ceiling(268435456, 268435456) = 268435456, ceiling(268435458, 268435456) = 536870912, ceiling(18446744073441116158, 268435456) = 18446744073441116160
     2321ceiling(536870912, 536870912) = 536870912, ceiling(536870914, 536870912) = 1073741824, ceiling(18446744073172680702, 536870912) = 18446744073172680704
     2322ceiling(1073741824, 1073741824) = 1073741824, ceiling(1073741826, 1073741824) = 2147483648, ceiling(18446744072635809790, 1073741824) = 18446744072635809792
     2323ceiling(2147483648, 2147483648) = 2147483648, ceiling(2147483650, 2147483648) = 4294967296, ceiling(18446744071562067966, 2147483648) = 18446744071562067968
     2324ceiling(4294967296, 4294967296) = 4294967296, ceiling(4294967298, 4294967296) = 8589934592, ceiling(18446744069414584318, 4294967296) = 18446744069414584320
     2325ceiling(8589934592, 8589934592) = 8589934592, ceiling(8589934594, 8589934592) = 17179869184, ceiling(18446744065119617022, 8589934592) = 18446744065119617024
     2326ceiling(17179869184, 17179869184) = 17179869184, ceiling(17179869186, 17179869184) = 34359738368, ceiling(18446744056529682430, 17179869184) = 18446744056529682432
     2327ceiling(34359738368, 34359738368) = 34359738368, ceiling(34359738370, 34359738368) = 68719476736, ceiling(18446744039349813246, 34359738368) = 18446744039349813248
     2328ceiling(68719476736, 68719476736) = 68719476736, ceiling(68719476738, 68719476736) = 137438953472, ceiling(18446744004990074878, 68719476736) = 18446744004990074880
     2329ceiling(137438953472, 137438953472) = 137438953472, ceiling(137438953474, 137438953472) = 274877906944, ceiling(18446743936270598142, 137438953472) = 18446743936270598144
     2330ceiling(274877906944, 274877906944) = 274877906944, ceiling(274877906946, 274877906944) = 549755813888, ceiling(18446743798831644670, 274877906944) = 18446743798831644672
     2331ceiling(549755813888, 549755813888) = 549755813888, ceiling(549755813890, 549755813888) = 1099511627776, ceiling(18446743523953737726, 549755813888) = 18446743523953737728
     2332ceiling(1099511627776, 1099511627776) = 1099511627776, ceiling(1099511627778, 1099511627776) = 2199023255552, ceiling(18446742974197923838, 1099511627776) = 18446742974197923840
     2333ceiling(2199023255552, 2199023255552) = 2199023255552, ceiling(2199023255554, 2199023255552) = 4398046511104, ceiling(18446741874686296062, 2199023255552) = 18446741874686296064
     2334ceiling(4398046511104, 4398046511104) = 4398046511104, ceiling(4398046511106, 4398046511104) = 8796093022208, ceiling(18446739675663040510, 4398046511104) = 18446739675663040512
     2335ceiling(8796093022208, 8796093022208) = 8796093022208, ceiling(8796093022210, 8796093022208) = 17592186044416, ceiling(18446735277616529406, 8796093022208) = 18446735277616529408
     2336ceiling(17592186044416, 17592186044416) = 17592186044416, ceiling(17592186044418, 17592186044416) = 35184372088832, ceiling(18446726481523507198, 17592186044416) = 18446726481523507200
     2337ceiling(35184372088832, 35184372088832) = 35184372088832, ceiling(35184372088834, 35184372088832) = 70368744177664, ceiling(18446708889337462782, 35184372088832) = 18446708889337462784
     2338ceiling(70368744177664, 70368744177664) = 70368744177664, ceiling(70368744177666, 70368744177664) = 140737488355328, ceiling(18446673704965373950, 70368744177664) = 18446673704965373952
     2339ceiling(140737488355328, 140737488355328) = 140737488355328, ceiling(140737488355330, 140737488355328) = 281474976710656, ceiling(18446603336221196286, 140737488355328) = 18446603336221196288
     2340ceiling(281474976710656, 281474976710656) = 281474976710656, ceiling(281474976710658, 281474976710656) = 562949953421312, ceiling(18446462598732840958, 281474976710656) = 18446462598732840960
     2341ceiling(562949953421312, 562949953421312) = 562949953421312, ceiling(562949953421314, 562949953421312) = 1125899906842624, ceiling(18446181123756130302, 562949953421312) = 18446181123756130304
     2342ceiling(1125899906842624, 1125899906842624) = 1125899906842624, ceiling(1125899906842626, 1125899906842624) = 2251799813685248, ceiling(18445618173802708990, 1125899906842624) = 18445618173802708992
     2343ceiling(2251799813685248, 2251799813685248) = 2251799813685248, ceiling(2251799813685250, 2251799813685248) = 4503599627370496, ceiling(18444492273895866366, 2251799813685248) = 18444492273895866368
     2344ceiling(4503599627370496, 4503599627370496) = 4503599627370496, ceiling(4503599627370498, 4503599627370496) = 9007199254740992, ceiling(18442240474082181118, 4503599627370496) = 18442240474082181120
     2345ceiling(9007199254740992, 9007199254740992) = 9007199254740992, ceiling(9007199254740994, 9007199254740992) = 18014398509481984, ceiling(18437736874454810622, 9007199254740992) = 18437736874454810624
     2346ceiling(18014398509481984, 18014398509481984) = 18014398509481984, ceiling(18014398509481986, 18014398509481984) = 36028797018963968, ceiling(18428729675200069630, 18014398509481984) = 18428729675200069632
     2347ceiling(36028797018963968, 36028797018963968) = 36028797018963968, ceiling(36028797018963970, 36028797018963968) = 72057594037927936, ceiling(18410715276690587646, 36028797018963968) = 18410715276690587648
     2348ceiling(72057594037927936, 72057594037927936) = 72057594037927936, ceiling(72057594037927938, 72057594037927936) = 144115188075855872, ceiling(18374686479671623678, 72057594037927936) = 18374686479671623680
     2349ceiling(144115188075855872, 144115188075855872) = 144115188075855872, ceiling(144115188075855874, 144115188075855872) = 288230376151711744, ceiling(18302628885633695742, 144115188075855872) = 18302628885633695744
     2350ceiling(288230376151711744, 288230376151711744) = 288230376151711744, ceiling(288230376151711746, 288230376151711744) = 576460752303423488, ceiling(18158513697557839870, 288230376151711744) = 18158513697557839872
     2351ceiling(576460752303423488, 576460752303423488) = 576460752303423488, ceiling(576460752303423490, 576460752303423488) = 1152921504606846976, ceiling(17870283321406128126, 576460752303423488) = 17870283321406128128
     2352ceiling(1152921504606846976, 1152921504606846976) = 1152921504606846976, ceiling(1152921504606846978, 1152921504606846976) = 2305843009213693952, ceiling(17293822569102704638, 1152921504606846976) = 17293822569102704640
     2353ceiling(2305843009213693952, 2305843009213693952) = 2305843009213693952, ceiling(2305843009213693954, 2305843009213693952) = 4611686018427387904, ceiling(16140901064495857662, 2305843009213693952) = 16140901064495857664
     2354ceiling(4611686018427387904, 4611686018427387904) = 4611686018427387904, ceiling(4611686018427387906, 4611686018427387904) = 9223372036854775808, ceiling(13835058055282163710, 4611686018427387904) = 13835058055282163712
     2355ceiling(9223372036854775808, 9223372036854775808) = 9223372036854775808, ceiling(9223372036854775810, 9223372036854775808) = 0, ceiling(9223372036854775806, 9223372036854775808) = 9223372036854775808
     2356
  • tests/.expect/bitmanip3.x86.txt

    r07d867b r22f94a4  
    340340
    341341signed char
    342 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(-2, 0) = 0
    343342floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(-3, 1) = -3
    344343floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(-4, 2) = -4
     
    351350
    352351unsigned char
    353 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(254, 0) = 0
    354352floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(253, 1) = 253
    355353floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(252, 2) = 252
     
    362360
    363361short int
    364 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(-2, 0) = 0
    365362floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(-3, 1) = -3
    366363floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(-4, 2) = -4
     
    381378
    382379unsigned short int
    383 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(65534, 0) = 0
    384380floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(65533, 1) = 65533
    385381floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(65532, 2) = 65532
     
    400396
    401397int
    402 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(-2, 0) = 0
    403398floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(-3, 1) = -3
    404399floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(-4, 2) = -4
     
    435430
    436431unsigned int
    437 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(4294967294, 0) = 0
    438432floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(4294967293, 1) = 4294967293
    439433floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(4294967292, 2) = 4294967292
     
    470464
    471465long int
    472 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(-2, 0) = 0
    473466floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(-3, 1) = -3
    474467floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(-4, 2) = -4
     
    505498
    506499unsigned long int
    507 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(4294967294, 0) = 0
    508500floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(4294967293, 1) = 4294967293
    509501floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(4294967292, 2) = 4294967292
     
    540532
    541533long long int
    542 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(-2, 0) = 0
    543534floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(-3, 1) = -3
    544535floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(-4, 2) = -4
     
    607598
    608599unsigned long long int
    609 floor2(0, 0) = 0, floor2(2, 0) = 0, floor2(18446744073709551614, 0) = 0
    610600floor2(1, 1) = 1, floor2(3, 1) = 3, floor2(18446744073709551613, 1) = 18446744073709551613
    611601floor2(2, 2) = 2, floor2(4, 2) = 4, floor2(18446744073709551612, 2) = 18446744073709551612
     
    1004994
    1005995signed char
    1006 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(-2, 0) = 0
    1007996ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(-3, 1) = -3
    1008997ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(-4, 2) = -4
     
    10151004
    10161005unsigned char
    1017 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(254, 0) = 0
    10181006ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(253, 1) = 253
    10191007ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(252, 2) = 252
     
    10261014
    10271015short int
    1028 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(-2, 0) = 0
    10291016ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(-3, 1) = -3
    10301017ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(-4, 2) = -4
     
    10451032
    10461033unsigned short int
    1047 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(65534, 0) = 0
    10481034ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(65533, 1) = 65533
    10491035ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(65532, 2) = 65532
     
    10641050
    10651051int
    1066 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(-2, 0) = 0
    10671052ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(-3, 1) = -3
    10681053ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(-4, 2) = -4
     
    10991084
    11001085unsigned int
    1101 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(4294967294, 0) = 0
    11021086ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(4294967293, 1) = 4294967293
    11031087ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(4294967292, 2) = 4294967292
     
    11341118
    11351119long int
    1136 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(-2, 0) = 0
    11371120ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(-3, 1) = -3
    11381121ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(-4, 2) = -4
     
    11691152
    11701153unsigned long int
    1171 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(4294967294, 0) = 0
    11721154ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(4294967293, 1) = 4294967293
    11731155ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(4294967292, 2) = 4294967292
     
    12041186
    12051187long long int
    1206 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(-2, 0) = 0
    12071188ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(-3, 1) = -3
    12081189ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(-4, 2) = -4
     
    12711252
    12721253unsigned long long int
    1273 ceiling2(0, 0) = 0, ceiling2(2, 0) = 0, ceiling2(18446744073709551614, 0) = 0
    12741254ceiling2(1, 1) = 1, ceiling2(3, 1) = 3, ceiling2(18446744073709551613, 1) = 18446744073709551613
    12751255ceiling2(2, 2) = 2, ceiling2(4, 2) = 4, ceiling2(18446744073709551612, 2) = 18446744073709551612
     
    13381318
    13391319
     1320ceiling_div
     1321
     1322signed char
     1323ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(-3, 1) = -3
     1324ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(-4, 2) = -1
     1325ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(-6, 4) = 0
     1326ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(-10, 8) = 0
     1327ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(-18, 16) = 0
     1328ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(-34, 32) = 0
     1329ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(-66, 64) = 0
     1330ceiling_div(-128, -128) = 2, ceiling_div(-126, -128) = 1, ceiling_div(126, -128) = 0
     1331
     1332unsigned char
     1333ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(253, 1) = 253
     1334ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(252, 2) = 126
     1335ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(250, 4) = 63
     1336ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(246, 8) = 31
     1337ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(238, 16) = 15
     1338ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(222, 32) = 7
     1339ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(190, 64) = 3
     1340ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(126, 128) = 1
     1341
     1342short int
     1343ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(-3, 1) = -3
     1344ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(-4, 2) = -1
     1345ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(-6, 4) = 0
     1346ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(-10, 8) = 0
     1347ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(-18, 16) = 0
     1348ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(-34, 32) = 0
     1349ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(-66, 64) = 0
     1350ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(-130, 128) = 0
     1351ceiling_div(256, 256) = 1, ceiling_div(258, 256) = 2, ceiling_div(-258, 256) = 0
     1352ceiling_div(512, 512) = 1, ceiling_div(514, 512) = 2, ceiling_div(-514, 512) = 0
     1353ceiling_div(1024, 1024) = 1, ceiling_div(1026, 1024) = 2, ceiling_div(-1026, 1024) = 0
     1354ceiling_div(2048, 2048) = 1, ceiling_div(2050, 2048) = 2, ceiling_div(-2050, 2048) = 0
     1355ceiling_div(4096, 4096) = 1, ceiling_div(4098, 4096) = 2, ceiling_div(-4098, 4096) = 0
     1356ceiling_div(8192, 8192) = 1, ceiling_div(8194, 8192) = 2, ceiling_div(-8194, 8192) = 0
     1357ceiling_div(16384, 16384) = 1, ceiling_div(16386, 16384) = 2, ceiling_div(-16386, 16384) = 0
     1358ceiling_div(-32768, -32768) = 2, ceiling_div(-32766, -32768) = 1, ceiling_div(32766, -32768) = 0
     1359
     1360unsigned short int
     1361ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(65533, 1) = 65533
     1362ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(65532, 2) = 32766
     1363ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(65530, 4) = 16383
     1364ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(65526, 8) = 8191
     1365ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(65518, 16) = 4095
     1366ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(65502, 32) = 2047
     1367ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(65470, 64) = 1023
     1368ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(65406, 128) = 511
     1369ceiling_div(256, 256) = 1, ceiling_div(258, 256) = 2, ceiling_div(65278, 256) = 255
     1370ceiling_div(512, 512) = 1, ceiling_div(514, 512) = 2, ceiling_div(65022, 512) = 127
     1371ceiling_div(1024, 1024) = 1, ceiling_div(1026, 1024) = 2, ceiling_div(64510, 1024) = 63
     1372ceiling_div(2048, 2048) = 1, ceiling_div(2050, 2048) = 2, ceiling_div(63486, 2048) = 31
     1373ceiling_div(4096, 4096) = 1, ceiling_div(4098, 4096) = 2, ceiling_div(61438, 4096) = 15
     1374ceiling_div(8192, 8192) = 1, ceiling_div(8194, 8192) = 2, ceiling_div(57342, 8192) = 7
     1375ceiling_div(16384, 16384) = 1, ceiling_div(16386, 16384) = 2, ceiling_div(49150, 16384) = 3
     1376ceiling_div(32768, 32768) = 1, ceiling_div(32770, 32768) = 2, ceiling_div(32766, 32768) = 1
     1377
     1378int
     1379ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(-3, 1) = -3
     1380ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(-4, 2) = -1
     1381ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(-6, 4) = 0
     1382ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(-10, 8) = 0
     1383ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(-18, 16) = 0
     1384ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(-34, 32) = 0
     1385ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(-66, 64) = 0
     1386ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(-130, 128) = 0
     1387ceiling_div(256, 256) = 1, ceiling_div(258, 256) = 2, ceiling_div(-258, 256) = 0
     1388ceiling_div(512, 512) = 1, ceiling_div(514, 512) = 2, ceiling_div(-514, 512) = 0
     1389ceiling_div(1024, 1024) = 1, ceiling_div(1026, 1024) = 2, ceiling_div(-1026, 1024) = 0
     1390ceiling_div(2048, 2048) = 1, ceiling_div(2050, 2048) = 2, ceiling_div(-2050, 2048) = 0
     1391ceiling_div(4096, 4096) = 1, ceiling_div(4098, 4096) = 2, ceiling_div(-4098, 4096) = 0
     1392ceiling_div(8192, 8192) = 1, ceiling_div(8194, 8192) = 2, ceiling_div(-8194, 8192) = 0
     1393ceiling_div(16384, 16384) = 1, ceiling_div(16386, 16384) = 2, ceiling_div(-16386, 16384) = 0
     1394ceiling_div(32768, 32768) = 1, ceiling_div(32770, 32768) = 2, ceiling_div(-32770, 32768) = 0
     1395ceiling_div(65536, 65536) = 1, ceiling_div(65538, 65536) = 2, ceiling_div(-65538, 65536) = 0
     1396ceiling_div(131072, 131072) = 1, ceiling_div(131074, 131072) = 2, ceiling_div(-131074, 131072) = 0
     1397ceiling_div(262144, 262144) = 1, ceiling_div(262146, 262144) = 2, ceiling_div(-262146, 262144) = 0
     1398ceiling_div(524288, 524288) = 1, ceiling_div(524290, 524288) = 2, ceiling_div(-524290, 524288) = 0
     1399ceiling_div(1048576, 1048576) = 1, ceiling_div(1048578, 1048576) = 2, ceiling_div(-1048578, 1048576) = 0
     1400ceiling_div(2097152, 2097152) = 1, ceiling_div(2097154, 2097152) = 2, ceiling_div(-2097154, 2097152) = 0
     1401ceiling_div(4194304, 4194304) = 1, ceiling_div(4194306, 4194304) = 2, ceiling_div(-4194306, 4194304) = 0
     1402ceiling_div(8388608, 8388608) = 1, ceiling_div(8388610, 8388608) = 2, ceiling_div(-8388610, 8388608) = 0
     1403ceiling_div(16777216, 16777216) = 1, ceiling_div(16777218, 16777216) = 2, ceiling_div(-16777218, 16777216) = 0
     1404ceiling_div(33554432, 33554432) = 1, ceiling_div(33554434, 33554432) = 2, ceiling_div(-33554434, 33554432) = 0
     1405ceiling_div(67108864, 67108864) = 1, ceiling_div(67108866, 67108864) = 2, ceiling_div(-67108866, 67108864) = 0
     1406ceiling_div(134217728, 134217728) = 1, ceiling_div(134217730, 134217728) = 2, ceiling_div(-134217730, 134217728) = 0
     1407ceiling_div(268435456, 268435456) = 1, ceiling_div(268435458, 268435456) = 2, ceiling_div(-268435458, 268435456) = 0
     1408ceiling_div(536870912, 536870912) = 1, ceiling_div(536870914, 536870912) = 2, ceiling_div(-536870914, 536870912) = 0
     1409ceiling_div(1073741824, 1073741824) = 1, ceiling_div(1073741826, 1073741824) = -1, ceiling_div(-1073741826, 1073741824) = 0
     1410ceiling_div(-2147483648, -2147483648) = 0, ceiling_div(-2147483646, -2147483648) = 0, ceiling_div(2147483646, -2147483648) = 0
     1411
     1412unsigned int
     1413ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(4294967293, 1) = 4294967293
     1414ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(4294967292, 2) = 2147483646
     1415ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(4294967290, 4) = 1073741823
     1416ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(4294967286, 8) = 536870911
     1417ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(4294967278, 16) = 268435455
     1418ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(4294967262, 32) = 134217727
     1419ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(4294967230, 64) = 67108863
     1420ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(4294967166, 128) = 33554431
     1421ceiling_div(256, 256) = 1, ceiling_div(258, 256) = 2, ceiling_div(4294967038, 256) = 16777215
     1422ceiling_div(512, 512) = 1, ceiling_div(514, 512) = 2, ceiling_div(4294966782, 512) = 8388607
     1423ceiling_div(1024, 1024) = 1, ceiling_div(1026, 1024) = 2, ceiling_div(4294966270, 1024) = 4194303
     1424ceiling_div(2048, 2048) = 1, ceiling_div(2050, 2048) = 2, ceiling_div(4294965246, 2048) = 2097151
     1425ceiling_div(4096, 4096) = 1, ceiling_div(4098, 4096) = 2, ceiling_div(4294963198, 4096) = 1048575
     1426ceiling_div(8192, 8192) = 1, ceiling_div(8194, 8192) = 2, ceiling_div(4294959102, 8192) = 524287
     1427ceiling_div(16384, 16384) = 1, ceiling_div(16386, 16384) = 2, ceiling_div(4294950910, 16384) = 262143
     1428ceiling_div(32768, 32768) = 1, ceiling_div(32770, 32768) = 2, ceiling_div(4294934526, 32768) = 131071
     1429ceiling_div(65536, 65536) = 1, ceiling_div(65538, 65536) = 2, ceiling_div(4294901758, 65536) = 65535
     1430ceiling_div(131072, 131072) = 1, ceiling_div(131074, 131072) = 2, ceiling_div(4294836222, 131072) = 32767
     1431ceiling_div(262144, 262144) = 1, ceiling_div(262146, 262144) = 2, ceiling_div(4294705150, 262144) = 16383
     1432ceiling_div(524288, 524288) = 1, ceiling_div(524290, 524288) = 2, ceiling_div(4294443006, 524288) = 8191
     1433ceiling_div(1048576, 1048576) = 1, ceiling_div(1048578, 1048576) = 2, ceiling_div(4293918718, 1048576) = 4095
     1434ceiling_div(2097152, 2097152) = 1, ceiling_div(2097154, 2097152) = 2, ceiling_div(4292870142, 2097152) = 2047
     1435ceiling_div(4194304, 4194304) = 1, ceiling_div(4194306, 4194304) = 2, ceiling_div(4290772990, 4194304) = 1023
     1436ceiling_div(8388608, 8388608) = 1, ceiling_div(8388610, 8388608) = 2, ceiling_div(4286578686, 8388608) = 511
     1437ceiling_div(16777216, 16777216) = 1, ceiling_div(16777218, 16777216) = 2, ceiling_div(4278190078, 16777216) = 255
     1438ceiling_div(33554432, 33554432) = 1, ceiling_div(33554434, 33554432) = 2, ceiling_div(4261412862, 33554432) = 127
     1439ceiling_div(67108864, 67108864) = 1, ceiling_div(67108866, 67108864) = 2, ceiling_div(4227858430, 67108864) = 63
     1440ceiling_div(134217728, 134217728) = 1, ceiling_div(134217730, 134217728) = 2, ceiling_div(4160749566, 134217728) = 31
     1441ceiling_div(268435456, 268435456) = 1, ceiling_div(268435458, 268435456) = 2, ceiling_div(4026531838, 268435456) = 15
     1442ceiling_div(536870912, 536870912) = 1, ceiling_div(536870914, 536870912) = 2, ceiling_div(3758096382, 536870912) = 7
     1443ceiling_div(1073741824, 1073741824) = 1, ceiling_div(1073741826, 1073741824) = 2, ceiling_div(3221225470, 1073741824) = 3
     1444ceiling_div(2147483648, 2147483648) = 1, ceiling_div(2147483650, 2147483648) = 0, ceiling_div(2147483646, 2147483648) = 1
     1445
     1446long int
     1447ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(-3, 1) = -3
     1448ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(-4, 2) = -1
     1449ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(-6, 4) = 0
     1450ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(-10, 8) = 0
     1451ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(-18, 16) = 0
     1452ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(-34, 32) = 0
     1453ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(-66, 64) = 0
     1454ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(-130, 128) = 0
     1455ceiling_div(256, 256) = 1, ceiling_div(258, 256) = 2, ceiling_div(-258, 256) = 0
     1456ceiling_div(512, 512) = 1, ceiling_div(514, 512) = 2, ceiling_div(-514, 512) = 0
     1457ceiling_div(1024, 1024) = 1, ceiling_div(1026, 1024) = 2, ceiling_div(-1026, 1024) = 0
     1458ceiling_div(2048, 2048) = 1, ceiling_div(2050, 2048) = 2, ceiling_div(-2050, 2048) = 0
     1459ceiling_div(4096, 4096) = 1, ceiling_div(4098, 4096) = 2, ceiling_div(-4098, 4096) = 0
     1460ceiling_div(8192, 8192) = 1, ceiling_div(8194, 8192) = 2, ceiling_div(-8194, 8192) = 0
     1461ceiling_div(16384, 16384) = 1, ceiling_div(16386, 16384) = 2, ceiling_div(-16386, 16384) = 0
     1462ceiling_div(32768, 32768) = 1, ceiling_div(32770, 32768) = 2, ceiling_div(-32770, 32768) = 0
     1463ceiling_div(65536, 65536) = 1, ceiling_div(65538, 65536) = 2, ceiling_div(-65538, 65536) = 0
     1464ceiling_div(131072, 131072) = 1, ceiling_div(131074, 131072) = 2, ceiling_div(-131074, 131072) = 0
     1465ceiling_div(262144, 262144) = 1, ceiling_div(262146, 262144) = 2, ceiling_div(-262146, 262144) = 0
     1466ceiling_div(524288, 524288) = 1, ceiling_div(524290, 524288) = 2, ceiling_div(-524290, 524288) = 0
     1467ceiling_div(1048576, 1048576) = 1, ceiling_div(1048578, 1048576) = 2, ceiling_div(-1048578, 1048576) = 0
     1468ceiling_div(2097152, 2097152) = 1, ceiling_div(2097154, 2097152) = 2, ceiling_div(-2097154, 2097152) = 0
     1469ceiling_div(4194304, 4194304) = 1, ceiling_div(4194306, 4194304) = 2, ceiling_div(-4194306, 4194304) = 0
     1470ceiling_div(8388608, 8388608) = 1, ceiling_div(8388610, 8388608) = 2, ceiling_div(-8388610, 8388608) = 0
     1471ceiling_div(16777216, 16777216) = 1, ceiling_div(16777218, 16777216) = 2, ceiling_div(-16777218, 16777216) = 0
     1472ceiling_div(33554432, 33554432) = 1, ceiling_div(33554434, 33554432) = 2, ceiling_div(-33554434, 33554432) = 0
     1473ceiling_div(67108864, 67108864) = 1, ceiling_div(67108866, 67108864) = 2, ceiling_div(-67108866, 67108864) = 0
     1474ceiling_div(134217728, 134217728) = 1, ceiling_div(134217730, 134217728) = 2, ceiling_div(-134217730, 134217728) = 0
     1475ceiling_div(268435456, 268435456) = 1, ceiling_div(268435458, 268435456) = 2, ceiling_div(-268435458, 268435456) = 0
     1476ceiling_div(536870912, 536870912) = 1, ceiling_div(536870914, 536870912) = 2, ceiling_div(-536870914, 536870912) = 0
     1477ceiling_div(1073741824, 1073741824) = 1, ceiling_div(1073741826, 1073741824) = -1, ceiling_div(-1073741826, 1073741824) = 0
     1478ceiling_div(-2147483648, -2147483648) = 0, ceiling_div(-2147483646, -2147483648) = 0, ceiling_div(2147483646, -2147483648) = 0
     1479
     1480unsigned long int
     1481ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(4294967293, 1) = 4294967293
     1482ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(4294967292, 2) = 2147483646
     1483ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(4294967290, 4) = 1073741823
     1484ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(4294967286, 8) = 536870911
     1485ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(4294967278, 16) = 268435455
     1486ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(4294967262, 32) = 134217727
     1487ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(4294967230, 64) = 67108863
     1488ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(4294967166, 128) = 33554431
     1489ceiling_div(256, 256) = 1, ceiling_div(258, 256) = 2, ceiling_div(4294967038, 256) = 16777215
     1490ceiling_div(512, 512) = 1, ceiling_div(514, 512) = 2, ceiling_div(4294966782, 512) = 8388607
     1491ceiling_div(1024, 1024) = 1, ceiling_div(1026, 1024) = 2, ceiling_div(4294966270, 1024) = 4194303
     1492ceiling_div(2048, 2048) = 1, ceiling_div(2050, 2048) = 2, ceiling_div(4294965246, 2048) = 2097151
     1493ceiling_div(4096, 4096) = 1, ceiling_div(4098, 4096) = 2, ceiling_div(4294963198, 4096) = 1048575
     1494ceiling_div(8192, 8192) = 1, ceiling_div(8194, 8192) = 2, ceiling_div(4294959102, 8192) = 524287
     1495ceiling_div(16384, 16384) = 1, ceiling_div(16386, 16384) = 2, ceiling_div(4294950910, 16384) = 262143
     1496ceiling_div(32768, 32768) = 1, ceiling_div(32770, 32768) = 2, ceiling_div(4294934526, 32768) = 131071
     1497ceiling_div(65536, 65536) = 1, ceiling_div(65538, 65536) = 2, ceiling_div(4294901758, 65536) = 65535
     1498ceiling_div(131072, 131072) = 1, ceiling_div(131074, 131072) = 2, ceiling_div(4294836222, 131072) = 32767
     1499ceiling_div(262144, 262144) = 1, ceiling_div(262146, 262144) = 2, ceiling_div(4294705150, 262144) = 16383
     1500ceiling_div(524288, 524288) = 1, ceiling_div(524290, 524288) = 2, ceiling_div(4294443006, 524288) = 8191
     1501ceiling_div(1048576, 1048576) = 1, ceiling_div(1048578, 1048576) = 2, ceiling_div(4293918718, 1048576) = 4095
     1502ceiling_div(2097152, 2097152) = 1, ceiling_div(2097154, 2097152) = 2, ceiling_div(4292870142, 2097152) = 2047
     1503ceiling_div(4194304, 4194304) = 1, ceiling_div(4194306, 4194304) = 2, ceiling_div(4290772990, 4194304) = 1023
     1504ceiling_div(8388608, 8388608) = 1, ceiling_div(8388610, 8388608) = 2, ceiling_div(4286578686, 8388608) = 511
     1505ceiling_div(16777216, 16777216) = 1, ceiling_div(16777218, 16777216) = 2, ceiling_div(4278190078, 16777216) = 255
     1506ceiling_div(33554432, 33554432) = 1, ceiling_div(33554434, 33554432) = 2, ceiling_div(4261412862, 33554432) = 127
     1507ceiling_div(67108864, 67108864) = 1, ceiling_div(67108866, 67108864) = 2, ceiling_div(4227858430, 67108864) = 63
     1508ceiling_div(134217728, 134217728) = 1, ceiling_div(134217730, 134217728) = 2, ceiling_div(4160749566, 134217728) = 31
     1509ceiling_div(268435456, 268435456) = 1, ceiling_div(268435458, 268435456) = 2, ceiling_div(4026531838, 268435456) = 15
     1510ceiling_div(536870912, 536870912) = 1, ceiling_div(536870914, 536870912) = 2, ceiling_div(3758096382, 536870912) = 7
     1511ceiling_div(1073741824, 1073741824) = 1, ceiling_div(1073741826, 1073741824) = 2, ceiling_div(3221225470, 1073741824) = 3
     1512ceiling_div(2147483648, 2147483648) = 1, ceiling_div(2147483650, 2147483648) = 0, ceiling_div(2147483646, 2147483648) = 1
     1513
     1514long long int
     1515ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(-3, 1) = -3
     1516ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(-4, 2) = -1
     1517ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(-6, 4) = 0
     1518ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(-10, 8) = 0
     1519ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(-18, 16) = 0
     1520ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(-34, 32) = 0
     1521ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(-66, 64) = 0
     1522ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(-130, 128) = 0
     1523ceiling_div(256, 256) = 1, ceiling_div(258, 256) = 2, ceiling_div(-258, 256) = 0
     1524ceiling_div(512, 512) = 1, ceiling_div(514, 512) = 2, ceiling_div(-514, 512) = 0
     1525ceiling_div(1024, 1024) = 1, ceiling_div(1026, 1024) = 2, ceiling_div(-1026, 1024) = 0
     1526ceiling_div(2048, 2048) = 1, ceiling_div(2050, 2048) = 2, ceiling_div(-2050, 2048) = 0
     1527ceiling_div(4096, 4096) = 1, ceiling_div(4098, 4096) = 2, ceiling_div(-4098, 4096) = 0
     1528ceiling_div(8192, 8192) = 1, ceiling_div(8194, 8192) = 2, ceiling_div(-8194, 8192) = 0
     1529ceiling_div(16384, 16384) = 1, ceiling_div(16386, 16384) = 2, ceiling_div(-16386, 16384) = 0
     1530ceiling_div(32768, 32768) = 1, ceiling_div(32770, 32768) = 2, ceiling_div(-32770, 32768) = 0
     1531ceiling_div(65536, 65536) = 1, ceiling_div(65538, 65536) = 2, ceiling_div(-65538, 65536) = 0
     1532ceiling_div(131072, 131072) = 1, ceiling_div(131074, 131072) = 2, ceiling_div(-131074, 131072) = 0
     1533ceiling_div(262144, 262144) = 1, ceiling_div(262146, 262144) = 2, ceiling_div(-262146, 262144) = 0
     1534ceiling_div(524288, 524288) = 1, ceiling_div(524290, 524288) = 2, ceiling_div(-524290, 524288) = 0
     1535ceiling_div(1048576, 1048576) = 1, ceiling_div(1048578, 1048576) = 2, ceiling_div(-1048578, 1048576) = 0
     1536ceiling_div(2097152, 2097152) = 1, ceiling_div(2097154, 2097152) = 2, ceiling_div(-2097154, 2097152) = 0
     1537ceiling_div(4194304, 4194304) = 1, ceiling_div(4194306, 4194304) = 2, ceiling_div(-4194306, 4194304) = 0
     1538ceiling_div(8388608, 8388608) = 1, ceiling_div(8388610, 8388608) = 2, ceiling_div(-8388610, 8388608) = 0
     1539ceiling_div(16777216, 16777216) = 1, ceiling_div(16777218, 16777216) = 2, ceiling_div(-16777218, 16777216) = 0
     1540ceiling_div(33554432, 33554432) = 1, ceiling_div(33554434, 33554432) = 2, ceiling_div(-33554434, 33554432) = 0
     1541ceiling_div(67108864, 67108864) = 1, ceiling_div(67108866, 67108864) = 2, ceiling_div(-67108866, 67108864) = 0
     1542ceiling_div(134217728, 134217728) = 1, ceiling_div(134217730, 134217728) = 2, ceiling_div(-134217730, 134217728) = 0
     1543ceiling_div(268435456, 268435456) = 1, ceiling_div(268435458, 268435456) = 2, ceiling_div(-268435458, 268435456) = 0
     1544ceiling_div(536870912, 536870912) = 1, ceiling_div(536870914, 536870912) = 2, ceiling_div(-536870914, 536870912) = 0
     1545ceiling_div(1073741824, 1073741824) = 1, ceiling_div(1073741826, 1073741824) = 2, ceiling_div(-1073741826, 1073741824) = 0
     1546ceiling_div(2147483648, 2147483648) = 1, ceiling_div(2147483650, 2147483648) = 2, ceiling_div(-2147483650, 2147483648) = 0
     1547ceiling_div(4294967296, 4294967296) = 1, ceiling_div(4294967298, 4294967296) = 2, ceiling_div(-4294967298, 4294967296) = 0
     1548ceiling_div(8589934592, 8589934592) = 1, ceiling_div(8589934594, 8589934592) = 2, ceiling_div(-8589934594, 8589934592) = 0
     1549ceiling_div(17179869184, 17179869184) = 1, ceiling_div(17179869186, 17179869184) = 2, ceiling_div(-17179869186, 17179869184) = 0
     1550ceiling_div(34359738368, 34359738368) = 1, ceiling_div(34359738370, 34359738368) = 2, ceiling_div(-34359738370, 34359738368) = 0
     1551ceiling_div(68719476736, 68719476736) = 1, ceiling_div(68719476738, 68719476736) = 2, ceiling_div(-68719476738, 68719476736) = 0
     1552ceiling_div(137438953472, 137438953472) = 1, ceiling_div(137438953474, 137438953472) = 2, ceiling_div(-137438953474, 137438953472) = 0
     1553ceiling_div(274877906944, 274877906944) = 1, ceiling_div(274877906946, 274877906944) = 2, ceiling_div(-274877906946, 274877906944) = 0
     1554ceiling_div(549755813888, 549755813888) = 1, ceiling_div(549755813890, 549755813888) = 2, ceiling_div(-549755813890, 549755813888) = 0
     1555ceiling_div(1099511627776, 1099511627776) = 1, ceiling_div(1099511627778, 1099511627776) = 2, ceiling_div(-1099511627778, 1099511627776) = 0
     1556ceiling_div(2199023255552, 2199023255552) = 1, ceiling_div(2199023255554, 2199023255552) = 2, ceiling_div(-2199023255554, 2199023255552) = 0
     1557ceiling_div(4398046511104, 4398046511104) = 1, ceiling_div(4398046511106, 4398046511104) = 2, ceiling_div(-4398046511106, 4398046511104) = 0
     1558ceiling_div(8796093022208, 8796093022208) = 1, ceiling_div(8796093022210, 8796093022208) = 2, ceiling_div(-8796093022210, 8796093022208) = 0
     1559ceiling_div(17592186044416, 17592186044416) = 1, ceiling_div(17592186044418, 17592186044416) = 2, ceiling_div(-17592186044418, 17592186044416) = 0
     1560ceiling_div(35184372088832, 35184372088832) = 1, ceiling_div(35184372088834, 35184372088832) = 2, ceiling_div(-35184372088834, 35184372088832) = 0
     1561ceiling_div(70368744177664, 70368744177664) = 1, ceiling_div(70368744177666, 70368744177664) = 2, ceiling_div(-70368744177666, 70368744177664) = 0
     1562ceiling_div(140737488355328, 140737488355328) = 1, ceiling_div(140737488355330, 140737488355328) = 2, ceiling_div(-140737488355330, 140737488355328) = 0
     1563ceiling_div(281474976710656, 281474976710656) = 1, ceiling_div(281474976710658, 281474976710656) = 2, ceiling_div(-281474976710658, 281474976710656) = 0
     1564ceiling_div(562949953421312, 562949953421312) = 1, ceiling_div(562949953421314, 562949953421312) = 2, ceiling_div(-562949953421314, 562949953421312) = 0
     1565ceiling_div(1125899906842624, 1125899906842624) = 1, ceiling_div(1125899906842626, 1125899906842624) = 2, ceiling_div(-1125899906842626, 1125899906842624) = 0
     1566ceiling_div(2251799813685248, 2251799813685248) = 1, ceiling_div(2251799813685250, 2251799813685248) = 2, ceiling_div(-2251799813685250, 2251799813685248) = 0
     1567ceiling_div(4503599627370496, 4503599627370496) = 1, ceiling_div(4503599627370498, 4503599627370496) = 2, ceiling_div(-4503599627370498, 4503599627370496) = 0
     1568ceiling_div(9007199254740992, 9007199254740992) = 1, ceiling_div(9007199254740994, 9007199254740992) = 2, ceiling_div(-9007199254740994, 9007199254740992) = 0
     1569ceiling_div(18014398509481984, 18014398509481984) = 1, ceiling_div(18014398509481986, 18014398509481984) = 2, ceiling_div(-18014398509481986, 18014398509481984) = 0
     1570ceiling_div(36028797018963968, 36028797018963968) = 1, ceiling_div(36028797018963970, 36028797018963968) = 2, ceiling_div(-36028797018963970, 36028797018963968) = 0
     1571ceiling_div(72057594037927936, 72057594037927936) = 1, ceiling_div(72057594037927938, 72057594037927936) = 2, ceiling_div(-72057594037927938, 72057594037927936) = 0
     1572ceiling_div(144115188075855872, 144115188075855872) = 1, ceiling_div(144115188075855874, 144115188075855872) = 2, ceiling_div(-144115188075855874, 144115188075855872) = 0
     1573ceiling_div(288230376151711744, 288230376151711744) = 1, ceiling_div(288230376151711746, 288230376151711744) = 2, ceiling_div(-288230376151711746, 288230376151711744) = 0
     1574ceiling_div(576460752303423488, 576460752303423488) = 1, ceiling_div(576460752303423490, 576460752303423488) = 2, ceiling_div(-576460752303423490, 576460752303423488) = 0
     1575ceiling_div(1152921504606846976, 1152921504606846976) = 1, ceiling_div(1152921504606846978, 1152921504606846976) = 2, ceiling_div(-1152921504606846978, 1152921504606846976) = 0
     1576ceiling_div(2305843009213693952, 2305843009213693952) = 1, ceiling_div(2305843009213693954, 2305843009213693952) = 2, ceiling_div(-2305843009213693954, 2305843009213693952) = 0
     1577ceiling_div(4611686018427387904, 4611686018427387904) = 1, ceiling_div(4611686018427387906, 4611686018427387904) = -1, ceiling_div(-4611686018427387906, 4611686018427387904) = 0
     1578ceiling_div(-9223372036854775808, -9223372036854775808) = 0, ceiling_div(-9223372036854775806, -9223372036854775808) = 0, ceiling_div(9223372036854775806, -9223372036854775808) = 0
     1579
     1580unsigned long long int
     1581ceiling_div(1, 1) = 1, ceiling_div(3, 1) = 3, ceiling_div(18446744073709551613, 1) = 18446744073709551613
     1582ceiling_div(2, 2) = 1, ceiling_div(4, 2) = 2, ceiling_div(18446744073709551612, 2) = 9223372036854775806
     1583ceiling_div(4, 4) = 1, ceiling_div(6, 4) = 2, ceiling_div(18446744073709551610, 4) = 4611686018427387903
     1584ceiling_div(8, 8) = 1, ceiling_div(10, 8) = 2, ceiling_div(18446744073709551606, 8) = 2305843009213693951
     1585ceiling_div(16, 16) = 1, ceiling_div(18, 16) = 2, ceiling_div(18446744073709551598, 16) = 1152921504606846975
     1586ceiling_div(32, 32) = 1, ceiling_div(34, 32) = 2, ceiling_div(18446744073709551582, 32) = 576460752303423487
     1587ceiling_div(64, 64) = 1, ceiling_div(66, 64) = 2, ceiling_div(18446744073709551550, 64) = 288230376151711743
     1588ceiling_div(128, 128) = 1, ceiling_div(130, 128) = 2, ceiling_div(18446744073709551486, 128) = 144115188075855871
     1589ceiling_div(256, 256) = 1, ceiling_div(258, 256) = 2, ceiling_div(18446744073709551358, 256) = 72057594037927935
     1590ceiling_div(512, 512) = 1, ceiling_div(514, 512) = 2, ceiling_div(18446744073709551102, 512) = 36028797018963967
     1591ceiling_div(1024, 1024) = 1, ceiling_div(1026, 1024) = 2, ceiling_div(18446744073709550590, 1024) = 18014398509481983
     1592ceiling_div(2048, 2048) = 1, ceiling_div(2050, 2048) = 2, ceiling_div(18446744073709549566, 2048) = 9007199254740991
     1593ceiling_div(4096, 4096) = 1, ceiling_div(4098, 4096) = 2, ceiling_div(18446744073709547518, 4096) = 4503599627370495
     1594ceiling_div(8192, 8192) = 1, ceiling_div(8194, 8192) = 2, ceiling_div(18446744073709543422, 8192) = 2251799813685247
     1595ceiling_div(16384, 16384) = 1, ceiling_div(16386, 16384) = 2, ceiling_div(18446744073709535230, 16384) = 1125899906842623
     1596ceiling_div(32768, 32768) = 1, ceiling_div(32770, 32768) = 2, ceiling_div(18446744073709518846, 32768) = 562949953421311
     1597ceiling_div(65536, 65536) = 1, ceiling_div(65538, 65536) = 2, ceiling_div(18446744073709486078, 65536) = 281474976710655
     1598ceiling_div(131072, 131072) = 1, ceiling_div(131074, 131072) = 2, ceiling_div(18446744073709420542, 131072) = 140737488355327
     1599ceiling_div(262144, 262144) = 1, ceiling_div(262146, 262144) = 2, ceiling_div(18446744073709289470, 262144) = 70368744177663
     1600ceiling_div(524288, 524288) = 1, ceiling_div(524290, 524288) = 2, ceiling_div(18446744073709027326, 524288) = 35184372088831
     1601ceiling_div(1048576, 1048576) = 1, ceiling_div(1048578, 1048576) = 2, ceiling_div(18446744073708503038, 1048576) = 17592186044415
     1602ceiling_div(2097152, 2097152) = 1, ceiling_div(2097154, 2097152) = 2, ceiling_div(18446744073707454462, 2097152) = 8796093022207
     1603ceiling_div(4194304, 4194304) = 1, ceiling_div(4194306, 4194304) = 2, ceiling_div(18446744073705357310, 4194304) = 4398046511103
     1604ceiling_div(8388608, 8388608) = 1, ceiling_div(8388610, 8388608) = 2, ceiling_div(18446744073701163006, 8388608) = 2199023255551
     1605ceiling_div(16777216, 16777216) = 1, ceiling_div(16777218, 16777216) = 2, ceiling_div(18446744073692774398, 16777216) = 1099511627775
     1606ceiling_div(33554432, 33554432) = 1, ceiling_div(33554434, 33554432) = 2, ceiling_div(18446744073675997182, 33554432) = 549755813887
     1607ceiling_div(67108864, 67108864) = 1, ceiling_div(67108866, 67108864) = 2, ceiling_div(18446744073642442750, 67108864) = 274877906943
     1608ceiling_div(134217728, 134217728) = 1, ceiling_div(134217730, 134217728) = 2, ceiling_div(18446744073575333886, 134217728) = 137438953471
     1609ceiling_div(268435456, 268435456) = 1, ceiling_div(268435458, 268435456) = 2, ceiling_div(18446744073441116158, 268435456) = 68719476735
     1610ceiling_div(536870912, 536870912) = 1, ceiling_div(536870914, 536870912) = 2, ceiling_div(18446744073172680702, 536870912) = 34359738367
     1611ceiling_div(1073741824, 1073741824) = 1, ceiling_div(1073741826, 1073741824) = 2, ceiling_div(18446744072635809790, 1073741824) = 17179869183
     1612ceiling_div(2147483648, 2147483648) = 1, ceiling_div(2147483650, 2147483648) = 2, ceiling_div(18446744071562067966, 2147483648) = 8589934591
     1613ceiling_div(4294967296, 4294967296) = 1, ceiling_div(4294967298, 4294967296) = 2, ceiling_div(18446744069414584318, 4294967296) = 4294967295
     1614ceiling_div(8589934592, 8589934592) = 1, ceiling_div(8589934594, 8589934592) = 2, ceiling_div(18446744065119617022, 8589934592) = 2147483647
     1615ceiling_div(17179869184, 17179869184) = 1, ceiling_div(17179869186, 17179869184) = 2, ceiling_div(18446744056529682430, 17179869184) = 1073741823
     1616ceiling_div(34359738368, 34359738368) = 1, ceiling_div(34359738370, 34359738368) = 2, ceiling_div(18446744039349813246, 34359738368) = 536870911
     1617ceiling_div(68719476736, 68719476736) = 1, ceiling_div(68719476738, 68719476736) = 2, ceiling_div(18446744004990074878, 68719476736) = 268435455
     1618ceiling_div(137438953472, 137438953472) = 1, ceiling_div(137438953474, 137438953472) = 2, ceiling_div(18446743936270598142, 137438953472) = 134217727
     1619ceiling_div(274877906944, 274877906944) = 1, ceiling_div(274877906946, 274877906944) = 2, ceiling_div(18446743798831644670, 274877906944) = 67108863
     1620ceiling_div(549755813888, 549755813888) = 1, ceiling_div(549755813890, 549755813888) = 2, ceiling_div(18446743523953737726, 549755813888) = 33554431
     1621ceiling_div(1099511627776, 1099511627776) = 1, ceiling_div(1099511627778, 1099511627776) = 2, ceiling_div(18446742974197923838, 1099511627776) = 16777215
     1622ceiling_div(2199023255552, 2199023255552) = 1, ceiling_div(2199023255554, 2199023255552) = 2, ceiling_div(18446741874686296062, 2199023255552) = 8388607
     1623ceiling_div(4398046511104, 4398046511104) = 1, ceiling_div(4398046511106, 4398046511104) = 2, ceiling_div(18446739675663040510, 4398046511104) = 4194303
     1624ceiling_div(8796093022208, 8796093022208) = 1, ceiling_div(8796093022210, 8796093022208) = 2, ceiling_div(18446735277616529406, 8796093022208) = 2097151
     1625ceiling_div(17592186044416, 17592186044416) = 1, ceiling_div(17592186044418, 17592186044416) = 2, ceiling_div(18446726481523507198, 17592186044416) = 1048575
     1626ceiling_div(35184372088832, 35184372088832) = 1, ceiling_div(35184372088834, 35184372088832) = 2, ceiling_div(18446708889337462782, 35184372088832) = 524287
     1627ceiling_div(70368744177664, 70368744177664) = 1, ceiling_div(70368744177666, 70368744177664) = 2, ceiling_div(18446673704965373950, 70368744177664) = 262143
     1628ceiling_div(140737488355328, 140737488355328) = 1, ceiling_div(140737488355330, 140737488355328) = 2, ceiling_div(18446603336221196286, 140737488355328) = 131071
     1629ceiling_div(281474976710656, 281474976710656) = 1, ceiling_div(281474976710658, 281474976710656) = 2, ceiling_div(18446462598732840958, 281474976710656) = 65535
     1630ceiling_div(562949953421312, 562949953421312) = 1, ceiling_div(562949953421314, 562949953421312) = 2, ceiling_div(18446181123756130302, 562949953421312) = 32767
     1631ceiling_div(1125899906842624, 1125899906842624) = 1, ceiling_div(1125899906842626, 1125899906842624) = 2, ceiling_div(18445618173802708990, 1125899906842624) = 16383
     1632ceiling_div(2251799813685248, 2251799813685248) = 1, ceiling_div(2251799813685250, 2251799813685248) = 2, ceiling_div(18444492273895866366, 2251799813685248) = 8191
     1633ceiling_div(4503599627370496, 4503599627370496) = 1, ceiling_div(4503599627370498, 4503599627370496) = 2, ceiling_div(18442240474082181118, 4503599627370496) = 4095
     1634ceiling_div(9007199254740992, 9007199254740992) = 1, ceiling_div(9007199254740994, 9007199254740992) = 2, ceiling_div(18437736874454810622, 9007199254740992) = 2047
     1635ceiling_div(18014398509481984, 18014398509481984) = 1, ceiling_div(18014398509481986, 18014398509481984) = 2, ceiling_div(18428729675200069630, 18014398509481984) = 1023
     1636ceiling_div(36028797018963968, 36028797018963968) = 1, ceiling_div(36028797018963970, 36028797018963968) = 2, ceiling_div(18410715276690587646, 36028797018963968) = 511
     1637ceiling_div(72057594037927936, 72057594037927936) = 1, ceiling_div(72057594037927938, 72057594037927936) = 2, ceiling_div(18374686479671623678, 72057594037927936) = 255
     1638ceiling_div(144115188075855872, 144115188075855872) = 1, ceiling_div(144115188075855874, 144115188075855872) = 2, ceiling_div(18302628885633695742, 144115188075855872) = 127
     1639ceiling_div(288230376151711744, 288230376151711744) = 1, ceiling_div(288230376151711746, 288230376151711744) = 2, ceiling_div(18158513697557839870, 288230376151711744) = 63
     1640ceiling_div(576460752303423488, 576460752303423488) = 1, ceiling_div(576460752303423490, 576460752303423488) = 2, ceiling_div(17870283321406128126, 576460752303423488) = 31
     1641ceiling_div(1152921504606846976, 1152921504606846976) = 1, ceiling_div(1152921504606846978, 1152921504606846976) = 2, ceiling_div(17293822569102704638, 1152921504606846976) = 15
     1642ceiling_div(2305843009213693952, 2305843009213693952) = 1, ceiling_div(2305843009213693954, 2305843009213693952) = 2, ceiling_div(16140901064495857662, 2305843009213693952) = 7
     1643ceiling_div(4611686018427387904, 4611686018427387904) = 1, ceiling_div(4611686018427387906, 4611686018427387904) = 2, ceiling_div(13835058055282163710, 4611686018427387904) = 3
     1644ceiling_div(9223372036854775808, 9223372036854775808) = 1, ceiling_div(9223372036854775810, 9223372036854775808) = 0, ceiling_div(9223372036854775806, 9223372036854775808) = 1
     1645
     1646
    13401647ceiling
    13411648
    13421649signed char
    13431650ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(-3, 1) = -3
    1344 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(-4, 2) = -1
    1345 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(-6, 4) = 0
    1346 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(-10, 8) = 0
    1347 ceiling(16, 16) = 1, ceiling(18, 16) = 2, ceiling(-18, 16) = 0
    1348 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(-34, 32) = 0
    1349 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(-66, 64) = 0
    1350 ceiling(-128, -128) = 2, ceiling(-126, -128) = 1, ceiling(126, -128) = 0
     1651ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(-4, 2) = -4
     1652ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(-6, 4) = 0
     1653ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(-10, 8) = 0
     1654ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(-18, 16) = 0
     1655ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(-34, 32) = 0
     1656ceiling(64, 64) = 64, ceiling(66, 64) = -128, ceiling(-66, 64) = 0
     1657ceiling(-128, -128) = -128, ceiling(-126, -128) = -128, ceiling(126, -128) = 0
    13511658
    13521659unsigned char
    13531660ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(253, 1) = 253
    1354 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(252, 2) = 126
    1355 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(250, 4) = 63
    1356 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(246, 8) = 31
    1357 ceiling(16, 16) = 1, ceiling(18, 16) = 2, ceiling(238, 16) = 15
    1358 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(222, 32) = 7
    1359 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(190, 64) = 3
    1360 ceiling(128, 128) = 1, ceiling(130, 128) = 2, ceiling(126, 128) = 1
     1661ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(252, 2) = 252
     1662ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(250, 4) = 252
     1663ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(246, 8) = 248
     1664ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(238, 16) = 240
     1665ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(222, 32) = 224
     1666ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(190, 64) = 192
     1667ceiling(128, 128) = 128, ceiling(130, 128) = 0, ceiling(126, 128) = 128
    13611668
    13621669short int
    13631670ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(-3, 1) = -3
    1364 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(-4, 2) = -1
    1365 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(-6, 4) = 0
    1366 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(-10, 8) = 0
    1367 ceiling(16, 16) = 1, ceiling(18, 16) = 2, ceiling(-18, 16) = 0
    1368 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(-34, 32) = 0
    1369 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(-66, 64) = 0
    1370 ceiling(128, 128) = 1, ceiling(130, 128) = 2, ceiling(-130, 128) = 0
    1371 ceiling(256, 256) = 1, ceiling(258, 256) = 2, ceiling(-258, 256) = 0
    1372 ceiling(512, 512) = 1, ceiling(514, 512) = 2, ceiling(-514, 512) = 0
    1373 ceiling(1024, 1024) = 1, ceiling(1026, 1024) = 2, ceiling(-1026, 1024) = 0
    1374 ceiling(2048, 2048) = 1, ceiling(2050, 2048) = 2, ceiling(-2050, 2048) = 0
    1375 ceiling(4096, 4096) = 1, ceiling(4098, 4096) = 2, ceiling(-4098, 4096) = 0
    1376 ceiling(8192, 8192) = 1, ceiling(8194, 8192) = 2, ceiling(-8194, 8192) = 0
    1377 ceiling(16384, 16384) = 1, ceiling(16386, 16384) = 2, ceiling(-16386, 16384) = 0
    1378 ceiling(-32768, -32768) = 2, ceiling(-32766, -32768) = 1, ceiling(32766, -32768) = 0
     1671ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(-4, 2) = -4
     1672ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(-6, 4) = 0
     1673ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(-10, 8) = 0
     1674ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(-18, 16) = 0
     1675ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(-34, 32) = 0
     1676ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(-66, 64) = 0
     1677ceiling(128, 128) = 128, ceiling(130, 128) = 256, ceiling(-130, 128) = 0
     1678ceiling(256, 256) = 256, ceiling(258, 256) = 512, ceiling(-258, 256) = 0
     1679ceiling(512, 512) = 512, ceiling(514, 512) = 1024, ceiling(-514, 512) = 0
     1680ceiling(1024, 1024) = 1024, ceiling(1026, 1024) = 2048, ceiling(-1026, 1024) = 0
     1681ceiling(2048, 2048) = 2048, ceiling(2050, 2048) = 4096, ceiling(-2050, 2048) = 0
     1682ceiling(4096, 4096) = 4096, ceiling(4098, 4096) = 8192, ceiling(-4098, 4096) = 0
     1683ceiling(8192, 8192) = 8192, ceiling(8194, 8192) = 16384, ceiling(-8194, 8192) = 0
     1684ceiling(16384, 16384) = 16384, ceiling(16386, 16384) = -32768, ceiling(-16386, 16384) = 0
     1685ceiling(-32768, -32768) = -32768, ceiling(-32766, -32768) = -32768, ceiling(32766, -32768) = 0
    13791686
    13801687unsigned short int
    13811688ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(65533, 1) = 65533
    1382 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(65532, 2) = 32766
    1383 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(65530, 4) = 16383
    1384 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(65526, 8) = 8191
    1385 ceiling(16, 16) = 1, ceiling(18, 16) = 2, ceiling(65518, 16) = 4095
    1386 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(65502, 32) = 2047
    1387 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(65470, 64) = 1023
    1388 ceiling(128, 128) = 1, ceiling(130, 128) = 2, ceiling(65406, 128) = 511
    1389 ceiling(256, 256) = 1, ceiling(258, 256) = 2, ceiling(65278, 256) = 255
    1390 ceiling(512, 512) = 1, ceiling(514, 512) = 2, ceiling(65022, 512) = 127
    1391 ceiling(1024, 1024) = 1, ceiling(1026, 1024) = 2, ceiling(64510, 1024) = 63
    1392 ceiling(2048, 2048) = 1, ceiling(2050, 2048) = 2, ceiling(63486, 2048) = 31
    1393 ceiling(4096, 4096) = 1, ceiling(4098, 4096) = 2, ceiling(61438, 4096) = 15
    1394 ceiling(8192, 8192) = 1, ceiling(8194, 8192) = 2, ceiling(57342, 8192) = 7
    1395 ceiling(16384, 16384) = 1, ceiling(16386, 16384) = 2, ceiling(49150, 16384) = 3
    1396 ceiling(32768, 32768) = 1, ceiling(32770, 32768) = 2, ceiling(32766, 32768) = 1
     1689ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(65532, 2) = 65532
     1690ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(65530, 4) = 65532
     1691ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(65526, 8) = 65528
     1692ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(65518, 16) = 65520
     1693ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(65502, 32) = 65504
     1694ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(65470, 64) = 65472
     1695ceiling(128, 128) = 128, ceiling(130, 128) = 256, ceiling(65406, 128) = 65408
     1696ceiling(256, 256) = 256, ceiling(258, 256) = 512, ceiling(65278, 256) = 65280
     1697ceiling(512, 512) = 512, ceiling(514, 512) = 1024, ceiling(65022, 512) = 65024
     1698ceiling(1024, 1024) = 1024, ceiling(1026, 1024) = 2048, ceiling(64510, 1024) = 64512
     1699ceiling(2048, 2048) = 2048, ceiling(2050, 2048) = 4096, ceiling(63486, 2048) = 63488
     1700ceiling(4096, 4096) = 4096, ceiling(4098, 4096) = 8192, ceiling(61438, 4096) = 61440
     1701ceiling(8192, 8192) = 8192, ceiling(8194, 8192) = 16384, ceiling(57342, 8192) = 57344
     1702ceiling(16384, 16384) = 16384, ceiling(16386, 16384) = 32768, ceiling(49150, 16384) = 49152
     1703ceiling(32768, 32768) = 32768, ceiling(32770, 32768) = 0, ceiling(32766, 32768) = 32768
    13971704
    13981705int
    13991706ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(-3, 1) = -3
    1400 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(-4, 2) = -1
    1401 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(-6, 4) = 0
    1402 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(-10, 8) = 0
    1403 ceiling(16, 16) = 1, ceiling(18, 16) = 2, ceiling(-18, 16) = 0
    1404 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(-34, 32) = 0
    1405 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(-66, 64) = 0
    1406 ceiling(128, 128) = 1, ceiling(130, 128) = 2, ceiling(-130, 128) = 0
    1407 ceiling(256, 256) = 1, ceiling(258, 256) = 2, ceiling(-258, 256) = 0
    1408 ceiling(512, 512) = 1, ceiling(514, 512) = 2, ceiling(-514, 512) = 0
    1409 ceiling(1024, 1024) = 1, ceiling(1026, 1024) = 2, ceiling(-1026, 1024) = 0
    1410 ceiling(2048, 2048) = 1, ceiling(2050, 2048) = 2, ceiling(-2050, 2048) = 0
    1411 ceiling(4096, 4096) = 1, ceiling(4098, 4096) = 2, ceiling(-4098, 4096) = 0
    1412 ceiling(8192, 8192) = 1, ceiling(8194, 8192) = 2, ceiling(-8194, 8192) = 0
    1413 ceiling(16384, 16384) = 1, ceiling(16386, 16384) = 2, ceiling(-16386, 16384) = 0
    1414 ceiling(32768, 32768) = 1, ceiling(32770, 32768) = 2, ceiling(-32770, 32768) = 0
    1415 ceiling(65536, 65536) = 1, ceiling(65538, 65536) = 2, ceiling(-65538, 65536) = 0
    1416 ceiling(131072, 131072) = 1, ceiling(131074, 131072) = 2, ceiling(-131074, 131072) = 0
    1417 ceiling(262144, 262144) = 1, ceiling(262146, 262144) = 2, ceiling(-262146, 262144) = 0
    1418 ceiling(524288, 524288) = 1, ceiling(524290, 524288) = 2, ceiling(-524290, 524288) = 0
    1419 ceiling(1048576, 1048576) = 1, ceiling(1048578, 1048576) = 2, ceiling(-1048578, 1048576) = 0
    1420 ceiling(2097152, 2097152) = 1, ceiling(2097154, 2097152) = 2, ceiling(-2097154, 2097152) = 0
    1421 ceiling(4194304, 4194304) = 1, ceiling(4194306, 4194304) = 2, ceiling(-4194306, 4194304) = 0
    1422 ceiling(8388608, 8388608) = 1, ceiling(8388610, 8388608) = 2, ceiling(-8388610, 8388608) = 0
    1423 ceiling(16777216, 16777216) = 1, ceiling(16777218, 16777216) = 2, ceiling(-16777218, 16777216) = 0
    1424 ceiling(33554432, 33554432) = 1, ceiling(33554434, 33554432) = 2, ceiling(-33554434, 33554432) = 0
    1425 ceiling(67108864, 67108864) = 1, ceiling(67108866, 67108864) = 2, ceiling(-67108866, 67108864) = 0
    1426 ceiling(134217728, 134217728) = 1, ceiling(134217730, 134217728) = 2, ceiling(-134217730, 134217728) = 0
    1427 ceiling(268435456, 268435456) = 1, ceiling(268435458, 268435456) = 2, ceiling(-268435458, 268435456) = 0
    1428 ceiling(536870912, 536870912) = 1, ceiling(536870914, 536870912) = 2, ceiling(-536870914, 536870912) = 0
    1429 ceiling(1073741824, 1073741824) = 1, ceiling(1073741826, 1073741824) = -1, ceiling(-1073741826, 1073741824) = 0
    1430 ceiling(-2147483648, -2147483648) = 0, ceiling(-2147483646, -2147483648) = 0, ceiling(2147483646, -2147483648) = 0
     1707ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(-4, 2) = -4
     1708ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(-6, 4) = 0
     1709ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(-10, 8) = 0
     1710ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(-18, 16) = 0
     1711ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(-34, 32) = 0
     1712ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(-66, 64) = 0
     1713ceiling(128, 128) = 128, ceiling(130, 128) = 256, ceiling(-130, 128) = 0
     1714ceiling(256, 256) = 256, ceiling(258, 256) = 512, ceiling(-258, 256) = 0
     1715ceiling(512, 512) = 512, ceiling(514, 512) = 1024, ceiling(-514, 512) = 0
     1716ceiling(1024, 1024) = 1024, ceiling(1026, 1024) = 2048, ceiling(-1026, 1024) = 0
     1717ceiling(2048, 2048) = 2048, ceiling(2050, 2048) = 4096, ceiling(-2050, 2048) = 0
     1718ceiling(4096, 4096) = 4096, ceiling(4098, 4096) = 8192, ceiling(-4098, 4096) = 0
     1719ceiling(8192, 8192) = 8192, ceiling(8194, 8192) = 16384, ceiling(-8194, 8192) = 0
     1720ceiling(16384, 16384) = 16384, ceiling(16386, 16384) = 32768, ceiling(-16386, 16384) = 0
     1721ceiling(32768, 32768) = 32768, ceiling(32770, 32768) = 65536, ceiling(-32770, 32768) = 0
     1722ceiling(65536, 65536) = 65536, ceiling(65538, 65536) = 131072, ceiling(-65538, 65536) = 0
     1723ceiling(131072, 131072) = 131072, ceiling(131074, 131072) = 262144, ceiling(-131074, 131072) = 0
     1724ceiling(262144, 262144) = 262144, ceiling(262146, 262144) = 524288, ceiling(-262146, 262144) = 0
     1725ceiling(524288, 524288) = 524288, ceiling(524290, 524288) = 1048576, ceiling(-524290, 524288) = 0
     1726ceiling(1048576, 1048576) = 1048576, ceiling(1048578, 1048576) = 2097152, ceiling(-1048578, 1048576) = 0
     1727ceiling(2097152, 2097152) = 2097152, ceiling(2097154, 2097152) = 4194304, ceiling(-2097154, 2097152) = 0
     1728ceiling(4194304, 4194304) = 4194304, ceiling(4194306, 4194304) = 8388608, ceiling(-4194306, 4194304) = 0
     1729ceiling(8388608, 8388608) = 8388608, ceiling(8388610, 8388608) = 16777216, ceiling(-8388610, 8388608) = 0
     1730ceiling(16777216, 16777216) = 16777216, ceiling(16777218, 16777216) = 33554432, ceiling(-16777218, 16777216) = 0
     1731ceiling(33554432, 33554432) = 33554432, ceiling(33554434, 33554432) = 67108864, ceiling(-33554434, 33554432) = 0
     1732ceiling(67108864, 67108864) = 67108864, ceiling(67108866, 67108864) = 134217728, ceiling(-67108866, 67108864) = 0
     1733ceiling(134217728, 134217728) = 134217728, ceiling(134217730, 134217728) = 268435456, ceiling(-134217730, 134217728) = 0
     1734ceiling(268435456, 268435456) = 268435456, ceiling(268435458, 268435456) = 536870912, ceiling(-268435458, 268435456) = 0
     1735ceiling(536870912, 536870912) = 536870912, ceiling(536870914, 536870912) = 1073741824, ceiling(-536870914, 536870912) = 0
     1736ceiling(1073741824, 1073741824) = 1073741824, ceiling(1073741826, 1073741824) = -1073741824, ceiling(-1073741826, 1073741824) = 0
     1737ceiling(-2147483648, -2147483648) = -2147483648, ceiling(-2147483646, -2147483648) = 0, ceiling(2147483646, -2147483648) = 0
    14311738
    14321739unsigned int
    14331740ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(4294967293, 1) = 4294967293
    1434 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(4294967292, 2) = 2147483646
    1435 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(4294967290, 4) = 1073741823
    1436 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(4294967286, 8) = 536870911
    1437 ceiling(16, 16) = 1, ceiling(18, 16) = 2, ceiling(4294967278, 16) = 268435455
    1438 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(4294967262, 32) = 134217727
    1439 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(4294967230, 64) = 67108863
    1440 ceiling(128, 128) = 1, ceiling(130, 128) = 2, ceiling(4294967166, 128) = 33554431
    1441 ceiling(256, 256) = 1, ceiling(258, 256) = 2, ceiling(4294967038, 256) = 16777215
    1442 ceiling(512, 512) = 1, ceiling(514, 512) = 2, ceiling(4294966782, 512) = 8388607
    1443 ceiling(1024, 1024) = 1, ceiling(1026, 1024) = 2, ceiling(4294966270, 1024) = 4194303
    1444 ceiling(2048, 2048) = 1, ceiling(2050, 2048) = 2, ceiling(4294965246, 2048) = 2097151
    1445 ceiling(4096, 4096) = 1, ceiling(4098, 4096) = 2, ceiling(4294963198, 4096) = 1048575
    1446 ceiling(8192, 8192) = 1, ceiling(8194, 8192) = 2, ceiling(4294959102, 8192) = 524287
    1447 ceiling(16384, 16384) = 1, ceiling(16386, 16384) = 2, ceiling(4294950910, 16384) = 262143
    1448 ceiling(32768, 32768) = 1, ceiling(32770, 32768) = 2, ceiling(4294934526, 32768) = 131071
    1449 ceiling(65536, 65536) = 1, ceiling(65538, 65536) = 2, ceiling(4294901758, 65536) = 65535
    1450 ceiling(131072, 131072) = 1, ceiling(131074, 131072) = 2, ceiling(4294836222, 131072) = 32767
    1451 ceiling(262144, 262144) = 1, ceiling(262146, 262144) = 2, ceiling(4294705150, 262144) = 16383
    1452 ceiling(524288, 524288) = 1, ceiling(524290, 524288) = 2, ceiling(4294443006, 524288) = 8191
    1453 ceiling(1048576, 1048576) = 1, ceiling(1048578, 1048576) = 2, ceiling(4293918718, 1048576) = 4095
    1454 ceiling(2097152, 2097152) = 1, ceiling(2097154, 2097152) = 2, ceiling(4292870142, 2097152) = 2047
    1455 ceiling(4194304, 4194304) = 1, ceiling(4194306, 4194304) = 2, ceiling(4290772990, 4194304) = 1023
    1456 ceiling(8388608, 8388608) = 1, ceiling(8388610, 8388608) = 2, ceiling(4286578686, 8388608) = 511
    1457 ceiling(16777216, 16777216) = 1, ceiling(16777218, 16777216) = 2, ceiling(4278190078, 16777216) = 255
    1458 ceiling(33554432, 33554432) = 1, ceiling(33554434, 33554432) = 2, ceiling(4261412862, 33554432) = 127
    1459 ceiling(67108864, 67108864) = 1, ceiling(67108866, 67108864) = 2, ceiling(4227858430, 67108864) = 63
    1460 ceiling(134217728, 134217728) = 1, ceiling(134217730, 134217728) = 2, ceiling(4160749566, 134217728) = 31
    1461 ceiling(268435456, 268435456) = 1, ceiling(268435458, 268435456) = 2, ceiling(4026531838, 268435456) = 15
    1462 ceiling(536870912, 536870912) = 1, ceiling(536870914, 536870912) = 2, ceiling(3758096382, 536870912) = 7
    1463 ceiling(1073741824, 1073741824) = 1, ceiling(1073741826, 1073741824) = 2, ceiling(3221225470, 1073741824) = 3
    1464 ceiling(2147483648, 2147483648) = 1, ceiling(2147483650, 2147483648) = 0, ceiling(2147483646, 2147483648) = 1
     1741ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(4294967292, 2) = 4294967292
     1742ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(4294967290, 4) = 4294967292
     1743ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(4294967286, 8) = 4294967288
     1744ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(4294967278, 16) = 4294967280
     1745ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(4294967262, 32) = 4294967264
     1746ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(4294967230, 64) = 4294967232
     1747ceiling(128, 128) = 128, ceiling(130, 128) = 256, ceiling(4294967166, 128) = 4294967168
     1748ceiling(256, 256) = 256, ceiling(258, 256) = 512, ceiling(4294967038, 256) = 4294967040
     1749ceiling(512, 512) = 512, ceiling(514, 512) = 1024, ceiling(4294966782, 512) = 4294966784
     1750ceiling(1024, 1024) = 1024, ceiling(1026, 1024) = 2048, ceiling(4294966270, 1024) = 4294966272
     1751ceiling(2048, 2048) = 2048, ceiling(2050, 2048) = 4096, ceiling(4294965246, 2048) = 4294965248
     1752ceiling(4096, 4096) = 4096, ceiling(4098, 4096) = 8192, ceiling(4294963198, 4096) = 4294963200
     1753ceiling(8192, 8192) = 8192, ceiling(8194, 8192) = 16384, ceiling(4294959102, 8192) = 4294959104
     1754ceiling(16384, 16384) = 16384, ceiling(16386, 16384) = 32768, ceiling(4294950910, 16384) = 4294950912
     1755ceiling(32768, 32768) = 32768, ceiling(32770, 32768) = 65536, ceiling(4294934526, 32768) = 4294934528
     1756ceiling(65536, 65536) = 65536, ceiling(65538, 65536) = 131072, ceiling(4294901758, 65536) = 4294901760
     1757ceiling(131072, 131072) = 131072, ceiling(131074, 131072) = 262144, ceiling(4294836222, 131072) = 4294836224
     1758ceiling(262144, 262144) = 262144, ceiling(262146, 262144) = 524288, ceiling(4294705150, 262144) = 4294705152
     1759ceiling(524288, 524288) = 524288, ceiling(524290, 524288) = 1048576, ceiling(4294443006, 524288) = 4294443008
     1760ceiling(1048576, 1048576) = 1048576, ceiling(1048578, 1048576) = 2097152, ceiling(4293918718, 1048576) = 4293918720
     1761ceiling(2097152, 2097152) = 2097152, ceiling(2097154, 2097152) = 4194304, ceiling(4292870142, 2097152) = 4292870144
     1762ceiling(4194304, 4194304) = 4194304, ceiling(4194306, 4194304) = 8388608, ceiling(4290772990, 4194304) = 4290772992
     1763ceiling(8388608, 8388608) = 8388608, ceiling(8388610, 8388608) = 16777216, ceiling(4286578686, 8388608) = 4286578688
     1764ceiling(16777216, 16777216) = 16777216, ceiling(16777218, 16777216) = 33554432, ceiling(4278190078, 16777216) = 4278190080
     1765ceiling(33554432, 33554432) = 33554432, ceiling(33554434, 33554432) = 67108864, ceiling(4261412862, 33554432) = 4261412864
     1766ceiling(67108864, 67108864) = 67108864, ceiling(67108866, 67108864) = 134217728, ceiling(4227858430, 67108864) = 4227858432
     1767ceiling(134217728, 134217728) = 134217728, ceiling(134217730, 134217728) = 268435456, ceiling(4160749566, 134217728) = 4160749568
     1768ceiling(268435456, 268435456) = 268435456, ceiling(268435458, 268435456) = 536870912, ceiling(4026531838, 268435456) = 4026531840
     1769ceiling(536870912, 536870912) = 536870912, ceiling(536870914, 536870912) = 1073741824, ceiling(3758096382, 536870912) = 3758096384
     1770ceiling(1073741824, 1073741824) = 1073741824, ceiling(1073741826, 1073741824) = 2147483648, ceiling(3221225470, 1073741824) = 3221225472
     1771ceiling(2147483648, 2147483648) = 2147483648, ceiling(2147483650, 2147483648) = 0, ceiling(2147483646, 2147483648) = 2147483648
    14651772
    14661773long int
    14671774ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(-3, 1) = -3
    1468 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(-4, 2) = -1
    1469 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(-6, 4) = 0
    1470 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(-10, 8) = 0
    1471 ceiling(16, 16) = 1, ceiling(18, 16) = 2, ceiling(-18, 16) = 0
    1472 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(-34, 32) = 0
    1473 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(-66, 64) = 0
    1474 ceiling(128, 128) = 1, ceiling(130, 128) = 2, ceiling(-130, 128) = 0
    1475 ceiling(256, 256) = 1, ceiling(258, 256) = 2, ceiling(-258, 256) = 0
    1476 ceiling(512, 512) = 1, ceiling(514, 512) = 2, ceiling(-514, 512) = 0
    1477 ceiling(1024, 1024) = 1, ceiling(1026, 1024) = 2, ceiling(-1026, 1024) = 0
    1478 ceiling(2048, 2048) = 1, ceiling(2050, 2048) = 2, ceiling(-2050, 2048) = 0
    1479 ceiling(4096, 4096) = 1, ceiling(4098, 4096) = 2, ceiling(-4098, 4096) = 0
    1480 ceiling(8192, 8192) = 1, ceiling(8194, 8192) = 2, ceiling(-8194, 8192) = 0
    1481 ceiling(16384, 16384) = 1, ceiling(16386, 16384) = 2, ceiling(-16386, 16384) = 0
    1482 ceiling(32768, 32768) = 1, ceiling(32770, 32768) = 2, ceiling(-32770, 32768) = 0
    1483 ceiling(65536, 65536) = 1, ceiling(65538, 65536) = 2, ceiling(-65538, 65536) = 0
    1484 ceiling(131072, 131072) = 1, ceiling(131074, 131072) = 2, ceiling(-131074, 131072) = 0
    1485 ceiling(262144, 262144) = 1, ceiling(262146, 262144) = 2, ceiling(-262146, 262144) = 0
    1486 ceiling(524288, 524288) = 1, ceiling(524290, 524288) = 2, ceiling(-524290, 524288) = 0
    1487 ceiling(1048576, 1048576) = 1, ceiling(1048578, 1048576) = 2, ceiling(-1048578, 1048576) = 0
    1488 ceiling(2097152, 2097152) = 1, ceiling(2097154, 2097152) = 2, ceiling(-2097154, 2097152) = 0
    1489 ceiling(4194304, 4194304) = 1, ceiling(4194306, 4194304) = 2, ceiling(-4194306, 4194304) = 0
    1490 ceiling(8388608, 8388608) = 1, ceiling(8388610, 8388608) = 2, ceiling(-8388610, 8388608) = 0
    1491 ceiling(16777216, 16777216) = 1, ceiling(16777218, 16777216) = 2, ceiling(-16777218, 16777216) = 0
    1492 ceiling(33554432, 33554432) = 1, ceiling(33554434, 33554432) = 2, ceiling(-33554434, 33554432) = 0
    1493 ceiling(67108864, 67108864) = 1, ceiling(67108866, 67108864) = 2, ceiling(-67108866, 67108864) = 0
    1494 ceiling(134217728, 134217728) = 1, ceiling(134217730, 134217728) = 2, ceiling(-134217730, 134217728) = 0
    1495 ceiling(268435456, 268435456) = 1, ceiling(268435458, 268435456) = 2, ceiling(-268435458, 268435456) = 0
    1496 ceiling(536870912, 536870912) = 1, ceiling(536870914, 536870912) = 2, ceiling(-536870914, 536870912) = 0
    1497 ceiling(1073741824, 1073741824) = 1, ceiling(1073741826, 1073741824) = -1, ceiling(-1073741826, 1073741824) = 0
    1498 ceiling(-2147483648, -2147483648) = 0, ceiling(-2147483646, -2147483648) = 0, ceiling(2147483646, -2147483648) = 0
     1775ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(-4, 2) = -4
     1776ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(-6, 4) = 0
     1777ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(-10, 8) = 0
     1778ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(-18, 16) = 0
     1779ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(-34, 32) = 0
     1780ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(-66, 64) = 0
     1781ceiling(128, 128) = 128, ceiling(130, 128) = 256, ceiling(-130, 128) = 0
     1782ceiling(256, 256) = 256, ceiling(258, 256) = 512, ceiling(-258, 256) = 0
     1783ceiling(512, 512) = 512, ceiling(514, 512) = 1024, ceiling(-514, 512) = 0
     1784ceiling(1024, 1024) = 1024, ceiling(1026, 1024) = 2048, ceiling(-1026, 1024) = 0
     1785ceiling(2048, 2048) = 2048, ceiling(2050, 2048) = 4096, ceiling(-2050, 2048) = 0
     1786ceiling(4096, 4096) = 4096, ceiling(4098, 4096) = 8192, ceiling(-4098, 4096) = 0
     1787ceiling(8192, 8192) = 8192, ceiling(8194, 8192) = 16384, ceiling(-8194, 8192) = 0
     1788ceiling(16384, 16384) = 16384, ceiling(16386, 16384) = 32768, ceiling(-16386, 16384) = 0
     1789ceiling(32768, 32768) = 32768, ceiling(32770, 32768) = 65536, ceiling(-32770, 32768) = 0
     1790ceiling(65536, 65536) = 65536, ceiling(65538, 65536) = 131072, ceiling(-65538, 65536) = 0
     1791ceiling(131072, 131072) = 131072, ceiling(131074, 131072) = 262144, ceiling(-131074, 131072) = 0
     1792ceiling(262144, 262144) = 262144, ceiling(262146, 262144) = 524288, ceiling(-262146, 262144) = 0
     1793ceiling(524288, 524288) = 524288, ceiling(524290, 524288) = 1048576, ceiling(-524290, 524288) = 0
     1794ceiling(1048576, 1048576) = 1048576, ceiling(1048578, 1048576) = 2097152, ceiling(-1048578, 1048576) = 0
     1795ceiling(2097152, 2097152) = 2097152, ceiling(2097154, 2097152) = 4194304, ceiling(-2097154, 2097152) = 0
     1796ceiling(4194304, 4194304) = 4194304, ceiling(4194306, 4194304) = 8388608, ceiling(-4194306, 4194304) = 0
     1797ceiling(8388608, 8388608) = 8388608, ceiling(8388610, 8388608) = 16777216, ceiling(-8388610, 8388608) = 0
     1798ceiling(16777216, 16777216) = 16777216, ceiling(16777218, 16777216) = 33554432, ceiling(-16777218, 16777216) = 0
     1799ceiling(33554432, 33554432) = 33554432, ceiling(33554434, 33554432) = 67108864, ceiling(-33554434, 33554432) = 0
     1800ceiling(67108864, 67108864) = 67108864, ceiling(67108866, 67108864) = 134217728, ceiling(-67108866, 67108864) = 0
     1801ceiling(134217728, 134217728) = 134217728, ceiling(134217730, 134217728) = 268435456, ceiling(-134217730, 134217728) = 0
     1802ceiling(268435456, 268435456) = 268435456, ceiling(268435458, 268435456) = 536870912, ceiling(-268435458, 268435456) = 0
     1803ceiling(536870912, 536870912) = 536870912, ceiling(536870914, 536870912) = 1073741824, ceiling(-536870914, 536870912) = 0
     1804ceiling(1073741824, 1073741824) = 1073741824, ceiling(1073741826, 1073741824) = -1073741824, ceiling(-1073741826, 1073741824) = 0
     1805ceiling(-2147483648, -2147483648) = -2147483648, ceiling(-2147483646, -2147483648) = 0, ceiling(2147483646, -2147483648) = 0
    14991806
    15001807unsigned long int
    15011808ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(4294967293, 1) = 4294967293
    1502 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(4294967292, 2) = 2147483646
    1503 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(4294967290, 4) = 1073741823
    1504 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(4294967286, 8) = 536870911
    1505 ceiling(16, 16) = 1, ceiling(18, 16) = 2, ceiling(4294967278, 16) = 268435455
    1506 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(4294967262, 32) = 134217727
    1507 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(4294967230, 64) = 67108863
    1508 ceiling(128, 128) = 1, ceiling(130, 128) = 2, ceiling(4294967166, 128) = 33554431
    1509 ceiling(256, 256) = 1, ceiling(258, 256) = 2, ceiling(4294967038, 256) = 16777215
    1510 ceiling(512, 512) = 1, ceiling(514, 512) = 2, ceiling(4294966782, 512) = 8388607
    1511 ceiling(1024, 1024) = 1, ceiling(1026, 1024) = 2, ceiling(4294966270, 1024) = 4194303
    1512 ceiling(2048, 2048) = 1, ceiling(2050, 2048) = 2, ceiling(4294965246, 2048) = 2097151
    1513 ceiling(4096, 4096) = 1, ceiling(4098, 4096) = 2, ceiling(4294963198, 4096) = 1048575
    1514 ceiling(8192, 8192) = 1, ceiling(8194, 8192) = 2, ceiling(4294959102, 8192) = 524287
    1515 ceiling(16384, 16384) = 1, ceiling(16386, 16384) = 2, ceiling(4294950910, 16384) = 262143
    1516 ceiling(32768, 32768) = 1, ceiling(32770, 32768) = 2, ceiling(4294934526, 32768) = 131071
    1517 ceiling(65536, 65536) = 1, ceiling(65538, 65536) = 2, ceiling(4294901758, 65536) = 65535
    1518 ceiling(131072, 131072) = 1, ceiling(131074, 131072) = 2, ceiling(4294836222, 131072) = 32767
    1519 ceiling(262144, 262144) = 1, ceiling(262146, 262144) = 2, ceiling(4294705150, 262144) = 16383
    1520 ceiling(524288, 524288) = 1, ceiling(524290, 524288) = 2, ceiling(4294443006, 524288) = 8191
    1521 ceiling(1048576, 1048576) = 1, ceiling(1048578, 1048576) = 2, ceiling(4293918718, 1048576) = 4095
    1522 ceiling(2097152, 2097152) = 1, ceiling(2097154, 2097152) = 2, ceiling(4292870142, 2097152) = 2047
    1523 ceiling(4194304, 4194304) = 1, ceiling(4194306, 4194304) = 2, ceiling(4290772990, 4194304) = 1023
    1524 ceiling(8388608, 8388608) = 1, ceiling(8388610, 8388608) = 2, ceiling(4286578686, 8388608) = 511
    1525 ceiling(16777216, 16777216) = 1, ceiling(16777218, 16777216) = 2, ceiling(4278190078, 16777216) = 255
    1526 ceiling(33554432, 33554432) = 1, ceiling(33554434, 33554432) = 2, ceiling(4261412862, 33554432) = 127
    1527 ceiling(67108864, 67108864) = 1, ceiling(67108866, 67108864) = 2, ceiling(4227858430, 67108864) = 63
    1528 ceiling(134217728, 134217728) = 1, ceiling(134217730, 134217728) = 2, ceiling(4160749566, 134217728) = 31
    1529 ceiling(268435456, 268435456) = 1, ceiling(268435458, 268435456) = 2, ceiling(4026531838, 268435456) = 15
    1530 ceiling(536870912, 536870912) = 1, ceiling(536870914, 536870912) = 2, ceiling(3758096382, 536870912) = 7
    1531 ceiling(1073741824, 1073741824) = 1, ceiling(1073741826, 1073741824) = 2, ceiling(3221225470, 1073741824) = 3
    1532 ceiling(2147483648, 2147483648) = 1, ceiling(2147483650, 2147483648) = 0, ceiling(2147483646, 2147483648) = 1
     1809ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(4294967292, 2) = 4294967292
     1810ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(4294967290, 4) = 4294967292
     1811ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(4294967286, 8) = 4294967288
     1812ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(4294967278, 16) = 4294967280
     1813ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(4294967262, 32) = 4294967264
     1814ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(4294967230, 64) = 4294967232
     1815ceiling(128, 128) = 128, ceiling(130, 128) = 256, ceiling(4294967166, 128) = 4294967168
     1816ceiling(256, 256) = 256, ceiling(258, 256) = 512, ceiling(4294967038, 256) = 4294967040
     1817ceiling(512, 512) = 512, ceiling(514, 512) = 1024, ceiling(4294966782, 512) = 4294966784
     1818ceiling(1024, 1024) = 1024, ceiling(1026, 1024) = 2048, ceiling(4294966270, 1024) = 4294966272
     1819ceiling(2048, 2048) = 2048, ceiling(2050, 2048) = 4096, ceiling(4294965246, 2048) = 4294965248
     1820ceiling(4096, 4096) = 4096, ceiling(4098, 4096) = 8192, ceiling(4294963198, 4096) = 4294963200
     1821ceiling(8192, 8192) = 8192, ceiling(8194, 8192) = 16384, ceiling(4294959102, 8192) = 4294959104
     1822ceiling(16384, 16384) = 16384, ceiling(16386, 16384) = 32768, ceiling(4294950910, 16384) = 4294950912
     1823ceiling(32768, 32768) = 32768, ceiling(32770, 32768) = 65536, ceiling(4294934526, 32768) = 4294934528
     1824ceiling(65536, 65536) = 65536, ceiling(65538, 65536) = 131072, ceiling(4294901758, 65536) = 4294901760
     1825ceiling(131072, 131072) = 131072, ceiling(131074, 131072) = 262144, ceiling(4294836222, 131072) = 4294836224
     1826ceiling(262144, 262144) = 262144, ceiling(262146, 262144) = 524288, ceiling(4294705150, 262144) = 4294705152
     1827ceiling(524288, 524288) = 524288, ceiling(524290, 524288) = 1048576, ceiling(4294443006, 524288) = 4294443008
     1828ceiling(1048576, 1048576) = 1048576, ceiling(1048578, 1048576) = 2097152, ceiling(4293918718, 1048576) = 4293918720
     1829ceiling(2097152, 2097152) = 2097152, ceiling(2097154, 2097152) = 4194304, ceiling(4292870142, 2097152) = 4292870144
     1830ceiling(4194304, 4194304) = 4194304, ceiling(4194306, 4194304) = 8388608, ceiling(4290772990, 4194304) = 4290772992
     1831ceiling(8388608, 8388608) = 8388608, ceiling(8388610, 8388608) = 16777216, ceiling(4286578686, 8388608) = 4286578688
     1832ceiling(16777216, 16777216) = 16777216, ceiling(16777218, 16777216) = 33554432, ceiling(4278190078, 16777216) = 4278190080
     1833ceiling(33554432, 33554432) = 33554432, ceiling(33554434, 33554432) = 67108864, ceiling(4261412862, 33554432) = 4261412864
     1834ceiling(67108864, 67108864) = 67108864, ceiling(67108866, 67108864) = 134217728, ceiling(4227858430, 67108864) = 4227858432
     1835ceiling(134217728, 134217728) = 134217728, ceiling(134217730, 134217728) = 268435456, ceiling(4160749566, 134217728) = 4160749568
     1836ceiling(268435456, 268435456) = 268435456, ceiling(268435458, 268435456) = 536870912, ceiling(4026531838, 268435456) = 4026531840
     1837ceiling(536870912, 536870912) = 536870912, ceiling(536870914, 536870912) = 1073741824, ceiling(3758096382, 536870912) = 3758096384
     1838ceiling(1073741824, 1073741824) = 1073741824, ceiling(1073741826, 1073741824) = 2147483648, ceiling(3221225470, 1073741824) = 3221225472
     1839ceiling(2147483648, 2147483648) = 2147483648, ceiling(2147483650, 2147483648) = 0, ceiling(2147483646, 2147483648) = 2147483648
    15331840
    15341841long long int
    15351842ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(-3, 1) = -3
    1536 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(-4, 2) = -1
    1537 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(-6, 4) = 0
    1538 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(-10, 8) = 0
    1539 ceiling(16, 16) = 1, ceiling(18, 16) = 2, ceiling(-18, 16) = 0
    1540 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(-34, 32) = 0
    1541 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(-66, 64) = 0
    1542 ceiling(128, 128) = 1, ceiling(130, 128) = 2, ceiling(-130, 128) = 0
    1543 ceiling(256, 256) = 1, ceiling(258, 256) = 2, ceiling(-258, 256) = 0
    1544 ceiling(512, 512) = 1, ceiling(514, 512) = 2, ceiling(-514, 512) = 0
    1545 ceiling(1024, 1024) = 1, ceiling(1026, 1024) = 2, ceiling(-1026, 1024) = 0
    1546 ceiling(2048, 2048) = 1, ceiling(2050, 2048) = 2, ceiling(-2050, 2048) = 0
    1547 ceiling(4096, 4096) = 1, ceiling(4098, 4096) = 2, ceiling(-4098, 4096) = 0
    1548 ceiling(8192, 8192) = 1, ceiling(8194, 8192) = 2, ceiling(-8194, 8192) = 0
    1549 ceiling(16384, 16384) = 1, ceiling(16386, 16384) = 2, ceiling(-16386, 16384) = 0
    1550 ceiling(32768, 32768) = 1, ceiling(32770, 32768) = 2, ceiling(-32770, 32768) = 0
    1551 ceiling(65536, 65536) = 1, ceiling(65538, 65536) = 2, ceiling(-65538, 65536) = 0
    1552 ceiling(131072, 131072) = 1, ceiling(131074, 131072) = 2, ceiling(-131074, 131072) = 0
    1553 ceiling(262144, 262144) = 1, ceiling(262146, 262144) = 2, ceiling(-262146, 262144) = 0
    1554 ceiling(524288, 524288) = 1, ceiling(524290, 524288) = 2, ceiling(-524290, 524288) = 0
    1555 ceiling(1048576, 1048576) = 1, ceiling(1048578, 1048576) = 2, ceiling(-1048578, 1048576) = 0
    1556 ceiling(2097152, 2097152) = 1, ceiling(2097154, 2097152) = 2, ceiling(-2097154, 2097152) = 0
    1557 ceiling(4194304, 4194304) = 1, ceiling(4194306, 4194304) = 2, ceiling(-4194306, 4194304) = 0
    1558 ceiling(8388608, 8388608) = 1, ceiling(8388610, 8388608) = 2, ceiling(-8388610, 8388608) = 0
    1559 ceiling(16777216, 16777216) = 1, ceiling(16777218, 16777216) = 2, ceiling(-16777218, 16777216) = 0
    1560 ceiling(33554432, 33554432) = 1, ceiling(33554434, 33554432) = 2, ceiling(-33554434, 33554432) = 0
    1561 ceiling(67108864, 67108864) = 1, ceiling(67108866, 67108864) = 2, ceiling(-67108866, 67108864) = 0
    1562 ceiling(134217728, 134217728) = 1, ceiling(134217730, 134217728) = 2, ceiling(-134217730, 134217728) = 0
    1563 ceiling(268435456, 268435456) = 1, ceiling(268435458, 268435456) = 2, ceiling(-268435458, 268435456) = 0
    1564 ceiling(536870912, 536870912) = 1, ceiling(536870914, 536870912) = 2, ceiling(-536870914, 536870912) = 0
    1565 ceiling(1073741824, 1073741824) = 1, ceiling(1073741826, 1073741824) = 2, ceiling(-1073741826, 1073741824) = 0
    1566 ceiling(2147483648, 2147483648) = 1, ceiling(2147483650, 2147483648) = 2, ceiling(-2147483650, 2147483648) = 0
    1567 ceiling(4294967296, 4294967296) = 1, ceiling(4294967298, 4294967296) = 2, ceiling(-4294967298, 4294967296) = 0
    1568 ceiling(8589934592, 8589934592) = 1, ceiling(8589934594, 8589934592) = 2, ceiling(-8589934594, 8589934592) = 0
    1569 ceiling(17179869184, 17179869184) = 1, ceiling(17179869186, 17179869184) = 2, ceiling(-17179869186, 17179869184) = 0
    1570 ceiling(34359738368, 34359738368) = 1, ceiling(34359738370, 34359738368) = 2, ceiling(-34359738370, 34359738368) = 0
    1571 ceiling(68719476736, 68719476736) = 1, ceiling(68719476738, 68719476736) = 2, ceiling(-68719476738, 68719476736) = 0
    1572 ceiling(137438953472, 137438953472) = 1, ceiling(137438953474, 137438953472) = 2, ceiling(-137438953474, 137438953472) = 0
    1573 ceiling(274877906944, 274877906944) = 1, ceiling(274877906946, 274877906944) = 2, ceiling(-274877906946, 274877906944) = 0
    1574 ceiling(549755813888, 549755813888) = 1, ceiling(549755813890, 549755813888) = 2, ceiling(-549755813890, 549755813888) = 0
    1575 ceiling(1099511627776, 1099511627776) = 1, ceiling(1099511627778, 1099511627776) = 2, ceiling(-1099511627778, 1099511627776) = 0
    1576 ceiling(2199023255552, 2199023255552) = 1, ceiling(2199023255554, 2199023255552) = 2, ceiling(-2199023255554, 2199023255552) = 0
    1577 ceiling(4398046511104, 4398046511104) = 1, ceiling(4398046511106, 4398046511104) = 2, ceiling(-4398046511106, 4398046511104) = 0
    1578 ceiling(8796093022208, 8796093022208) = 1, ceiling(8796093022210, 8796093022208) = 2, ceiling(-8796093022210, 8796093022208) = 0
    1579 ceiling(17592186044416, 17592186044416) = 1, ceiling(17592186044418, 17592186044416) = 2, ceiling(-17592186044418, 17592186044416) = 0
    1580 ceiling(35184372088832, 35184372088832) = 1, ceiling(35184372088834, 35184372088832) = 2, ceiling(-35184372088834, 35184372088832) = 0
    1581 ceiling(70368744177664, 70368744177664) = 1, ceiling(70368744177666, 70368744177664) = 2, ceiling(-70368744177666, 70368744177664) = 0
    1582 ceiling(140737488355328, 140737488355328) = 1, ceiling(140737488355330, 140737488355328) = 2, ceiling(-140737488355330, 140737488355328) = 0
    1583 ceiling(281474976710656, 281474976710656) = 1, ceiling(281474976710658, 281474976710656) = 2, ceiling(-281474976710658, 281474976710656) = 0
    1584 ceiling(562949953421312, 562949953421312) = 1, ceiling(562949953421314, 562949953421312) = 2, ceiling(-562949953421314, 562949953421312) = 0
    1585 ceiling(1125899906842624, 1125899906842624) = 1, ceiling(1125899906842626, 1125899906842624) = 2, ceiling(-1125899906842626, 1125899906842624) = 0
    1586 ceiling(2251799813685248, 2251799813685248) = 1, ceiling(2251799813685250, 2251799813685248) = 2, ceiling(-2251799813685250, 2251799813685248) = 0
    1587 ceiling(4503599627370496, 4503599627370496) = 1, ceiling(4503599627370498, 4503599627370496) = 2, ceiling(-4503599627370498, 4503599627370496) = 0
    1588 ceiling(9007199254740992, 9007199254740992) = 1, ceiling(9007199254740994, 9007199254740992) = 2, ceiling(-9007199254740994, 9007199254740992) = 0
    1589 ceiling(18014398509481984, 18014398509481984) = 1, ceiling(18014398509481986, 18014398509481984) = 2, ceiling(-18014398509481986, 18014398509481984) = 0
    1590 ceiling(36028797018963968, 36028797018963968) = 1, ceiling(36028797018963970, 36028797018963968) = 2, ceiling(-36028797018963970, 36028797018963968) = 0
    1591 ceiling(72057594037927936, 72057594037927936) = 1, ceiling(72057594037927938, 72057594037927936) = 2, ceiling(-72057594037927938, 72057594037927936) = 0
    1592 ceiling(144115188075855872, 144115188075855872) = 1, ceiling(144115188075855874, 144115188075855872) = 2, ceiling(-144115188075855874, 144115188075855872) = 0
    1593 ceiling(288230376151711744, 288230376151711744) = 1, ceiling(288230376151711746, 288230376151711744) = 2, ceiling(-288230376151711746, 288230376151711744) = 0
    1594 ceiling(576460752303423488, 576460752303423488) = 1, ceiling(576460752303423490, 576460752303423488) = 2, ceiling(-576460752303423490, 576460752303423488) = 0
    1595 ceiling(1152921504606846976, 1152921504606846976) = 1, ceiling(1152921504606846978, 1152921504606846976) = 2, ceiling(-1152921504606846978, 1152921504606846976) = 0
    1596 ceiling(2305843009213693952, 2305843009213693952) = 1, ceiling(2305843009213693954, 2305843009213693952) = 2, ceiling(-2305843009213693954, 2305843009213693952) = 0
    1597 ceiling(4611686018427387904, 4611686018427387904) = 1, ceiling(4611686018427387906, 4611686018427387904) = -1, ceiling(-4611686018427387906, 4611686018427387904) = 0
    1598 ceiling(-9223372036854775808, -9223372036854775808) = 0, ceiling(-9223372036854775806, -9223372036854775808) = 0, ceiling(9223372036854775806, -9223372036854775808) = 0
     1843ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(-4, 2) = -4
     1844ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(-6, 4) = 0
     1845ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(-10, 8) = 0
     1846ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(-18, 16) = 0
     1847ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(-34, 32) = 0
     1848ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(-66, 64) = 0
     1849ceiling(128, 128) = 128, ceiling(130, 128) = 256, ceiling(-130, 128) = 0
     1850ceiling(256, 256) = 256, ceiling(258, 256) = 512, ceiling(-258, 256) = 0
     1851ceiling(512, 512) = 512, ceiling(514, 512) = 1024, ceiling(-514, 512) = 0
     1852ceiling(1024, 1024) = 1024, ceiling(1026, 1024) = 2048, ceiling(-1026, 1024) = 0
     1853ceiling(2048, 2048) = 2048, ceiling(2050, 2048) = 4096, ceiling(-2050, 2048) = 0
     1854ceiling(4096, 4096) = 4096, ceiling(4098, 4096) = 8192, ceiling(-4098, 4096) = 0
     1855ceiling(8192, 8192) = 8192, ceiling(8194, 8192) = 16384, ceiling(-8194, 8192) = 0
     1856ceiling(16384, 16384) = 16384, ceiling(16386, 16384) = 32768, ceiling(-16386, 16384) = 0
     1857ceiling(32768, 32768) = 32768, ceiling(32770, 32768) = 65536, ceiling(-32770, 32768) = 0
     1858ceiling(65536, 65536) = 65536, ceiling(65538, 65536) = 131072, ceiling(-65538, 65536) = 0
     1859ceiling(131072, 131072) = 131072, ceiling(131074, 131072) = 262144, ceiling(-131074, 131072) = 0
     1860ceiling(262144, 262144) = 262144, ceiling(262146, 262144) = 524288, ceiling(-262146, 262144) = 0
     1861ceiling(524288, 524288) = 524288, ceiling(524290, 524288) = 1048576, ceiling(-524290, 524288) = 0
     1862ceiling(1048576, 1048576) = 1048576, ceiling(1048578, 1048576) = 2097152, ceiling(-1048578, 1048576) = 0
     1863ceiling(2097152, 2097152) = 2097152, ceiling(2097154, 2097152) = 4194304, ceiling(-2097154, 2097152) = 0
     1864ceiling(4194304, 4194304) = 4194304, ceiling(4194306, 4194304) = 8388608, ceiling(-4194306, 4194304) = 0
     1865ceiling(8388608, 8388608) = 8388608, ceiling(8388610, 8388608) = 16777216, ceiling(-8388610, 8388608) = 0
     1866ceiling(16777216, 16777216) = 16777216, ceiling(16777218, 16777216) = 33554432, ceiling(-16777218, 16777216) = 0
     1867ceiling(33554432, 33554432) = 33554432, ceiling(33554434, 33554432) = 67108864, ceiling(-33554434, 33554432) = 0
     1868ceiling(67108864, 67108864) = 67108864, ceiling(67108866, 67108864) = 134217728, ceiling(-67108866, 67108864) = 0
     1869ceiling(134217728, 134217728) = 134217728, ceiling(134217730, 134217728) = 268435456, ceiling(-134217730, 134217728) = 0
     1870ceiling(268435456, 268435456) = 268435456, ceiling(268435458, 268435456) = 536870912, ceiling(-268435458, 268435456) = 0
     1871ceiling(536870912, 536870912) = 536870912, ceiling(536870914, 536870912) = 1073741824, ceiling(-536870914, 536870912) = 0
     1872ceiling(1073741824, 1073741824) = 1073741824, ceiling(1073741826, 1073741824) = 2147483648, ceiling(-1073741826, 1073741824) = 0
     1873ceiling(2147483648, 2147483648) = 2147483648, ceiling(2147483650, 2147483648) = 4294967296, ceiling(-2147483650, 2147483648) = 0
     1874ceiling(4294967296, 4294967296) = 4294967296, ceiling(4294967298, 4294967296) = 8589934592, ceiling(-4294967298, 4294967296) = 0
     1875ceiling(8589934592, 8589934592) = 8589934592, ceiling(8589934594, 8589934592) = 17179869184, ceiling(-8589934594, 8589934592) = 0
     1876ceiling(17179869184, 17179869184) = 17179869184, ceiling(17179869186, 17179869184) = 34359738368, ceiling(-17179869186, 17179869184) = 0
     1877ceiling(34359738368, 34359738368) = 34359738368, ceiling(34359738370, 34359738368) = 68719476736, ceiling(-34359738370, 34359738368) = 0
     1878ceiling(68719476736, 68719476736) = 68719476736, ceiling(68719476738, 68719476736) = 137438953472, ceiling(-68719476738, 68719476736) = 0
     1879ceiling(137438953472, 137438953472) = 137438953472, ceiling(137438953474, 137438953472) = 274877906944, ceiling(-137438953474, 137438953472) = 0
     1880ceiling(274877906944, 274877906944) = 274877906944, ceiling(274877906946, 274877906944) = 549755813888, ceiling(-274877906946, 274877906944) = 0
     1881ceiling(549755813888, 549755813888) = 549755813888, ceiling(549755813890, 549755813888) = 1099511627776, ceiling(-549755813890, 549755813888) = 0
     1882ceiling(1099511627776, 1099511627776) = 1099511627776, ceiling(1099511627778, 1099511627776) = 2199023255552, ceiling(-1099511627778, 1099511627776) = 0
     1883ceiling(2199023255552, 2199023255552) = 2199023255552, ceiling(2199023255554, 2199023255552) = 4398046511104, ceiling(-2199023255554, 2199023255552) = 0
     1884ceiling(4398046511104, 4398046511104) = 4398046511104, ceiling(4398046511106, 4398046511104) = 8796093022208, ceiling(-4398046511106, 4398046511104) = 0
     1885ceiling(8796093022208, 8796093022208) = 8796093022208, ceiling(8796093022210, 8796093022208) = 17592186044416, ceiling(-8796093022210, 8796093022208) = 0
     1886ceiling(17592186044416, 17592186044416) = 17592186044416, ceiling(17592186044418, 17592186044416) = 35184372088832, ceiling(-17592186044418, 17592186044416) = 0
     1887ceiling(35184372088832, 35184372088832) = 35184372088832, ceiling(35184372088834, 35184372088832) = 70368744177664, ceiling(-35184372088834, 35184372088832) = 0
     1888ceiling(70368744177664, 70368744177664) = 70368744177664, ceiling(70368744177666, 70368744177664) = 140737488355328, ceiling(-70368744177666, 70368744177664) = 0
     1889ceiling(140737488355328, 140737488355328) = 140737488355328, ceiling(140737488355330, 140737488355328) = 281474976710656, ceiling(-140737488355330, 140737488355328) = 0
     1890ceiling(281474976710656, 281474976710656) = 281474976710656, ceiling(281474976710658, 281474976710656) = 562949953421312, ceiling(-281474976710658, 281474976710656) = 0
     1891ceiling(562949953421312, 562949953421312) = 562949953421312, ceiling(562949953421314, 562949953421312) = 1125899906842624, ceiling(-562949953421314, 562949953421312) = 0
     1892ceiling(1125899906842624, 1125899906842624) = 1125899906842624, ceiling(1125899906842626, 1125899906842624) = 2251799813685248, ceiling(-1125899906842626, 1125899906842624) = 0
     1893ceiling(2251799813685248, 2251799813685248) = 2251799813685248, ceiling(2251799813685250, 2251799813685248) = 4503599627370496, ceiling(-2251799813685250, 2251799813685248) = 0
     1894ceiling(4503599627370496, 4503599627370496) = 4503599627370496, ceiling(4503599627370498, 4503599627370496) = 9007199254740992, ceiling(-4503599627370498, 4503599627370496) = 0
     1895ceiling(9007199254740992, 9007199254740992) = 9007199254740992, ceiling(9007199254740994, 9007199254740992) = 18014398509481984, ceiling(-9007199254740994, 9007199254740992) = 0
     1896ceiling(18014398509481984, 18014398509481984) = 18014398509481984, ceiling(18014398509481986, 18014398509481984) = 36028797018963968, ceiling(-18014398509481986, 18014398509481984) = 0
     1897ceiling(36028797018963968, 36028797018963968) = 36028797018963968, ceiling(36028797018963970, 36028797018963968) = 72057594037927936, ceiling(-36028797018963970, 36028797018963968) = 0
     1898ceiling(72057594037927936, 72057594037927936) = 72057594037927936, ceiling(72057594037927938, 72057594037927936) = 144115188075855872, ceiling(-72057594037927938, 72057594037927936) = 0
     1899ceiling(144115188075855872, 144115188075855872) = 144115188075855872, ceiling(144115188075855874, 144115188075855872) = 288230376151711744, ceiling(-144115188075855874, 144115188075855872) = 0
     1900ceiling(288230376151711744, 288230376151711744) = 288230376151711744, ceiling(288230376151711746, 288230376151711744) = 576460752303423488, ceiling(-288230376151711746, 288230376151711744) = 0
     1901ceiling(576460752303423488, 576460752303423488) = 576460752303423488, ceiling(576460752303423490, 576460752303423488) = 1152921504606846976, ceiling(-576460752303423490, 576460752303423488) = 0
     1902ceiling(1152921504606846976, 1152921504606846976) = 1152921504606846976, ceiling(1152921504606846978, 1152921504606846976) = 2305843009213693952, ceiling(-1152921504606846978, 1152921504606846976) = 0
     1903ceiling(2305843009213693952, 2305843009213693952) = 2305843009213693952, ceiling(2305843009213693954, 2305843009213693952) = 4611686018427387904, ceiling(-2305843009213693954, 2305843009213693952) = 0
     1904ceiling(4611686018427387904, 4611686018427387904) = 4611686018427387904, ceiling(4611686018427387906, 4611686018427387904) = -4611686018427387904, ceiling(-4611686018427387906, 4611686018427387904) = 0
     1905ceiling(-9223372036854775808, -9223372036854775808) = -9223372036854775808, ceiling(-9223372036854775806, -9223372036854775808) = 0, ceiling(9223372036854775806, -9223372036854775808) = 0
    15991906
    16001907unsigned long long int
    16011908ceiling(1, 1) = 1, ceiling(3, 1) = 3, ceiling(18446744073709551613, 1) = 18446744073709551613
    1602 ceiling(2, 2) = 1, ceiling(4, 2) = 2, ceiling(18446744073709551612, 2) = 9223372036854775806
    1603 ceiling(4, 4) = 1, ceiling(6, 4) = 2, ceiling(18446744073709551610, 4) = 4611686018427387903
    1604 ceiling(8, 8) = 1, ceiling(10, 8) = 2, ceiling(18446744073709551606, 8) = 2305843009213693951
    1605 ceiling(16, 16) = 1, ceiling(18, 16) = 2, ceiling(18446744073709551598, 16) = 1152921504606846975
    1606 ceiling(32, 32) = 1, ceiling(34, 32) = 2, ceiling(18446744073709551582, 32) = 576460752303423487
    1607 ceiling(64, 64) = 1, ceiling(66, 64) = 2, ceiling(18446744073709551550, 64) = 288230376151711743
    1608 ceiling(128, 128) = 1, ceiling(130, 128) = 2, ceiling(18446744073709551486, 128) = 144115188075855871
    1609 ceiling(256, 256) = 1, ceiling(258, 256) = 2, ceiling(18446744073709551358, 256) = 72057594037927935
    1610 ceiling(512, 512) = 1, ceiling(514, 512) = 2, ceiling(18446744073709551102, 512) = 36028797018963967
    1611 ceiling(1024, 1024) = 1, ceiling(1026, 1024) = 2, ceiling(18446744073709550590, 1024) = 18014398509481983
    1612 ceiling(2048, 2048) = 1, ceiling(2050, 2048) = 2, ceiling(18446744073709549566, 2048) = 9007199254740991
    1613 ceiling(4096, 4096) = 1, ceiling(4098, 4096) = 2, ceiling(18446744073709547518, 4096) = 4503599627370495
    1614 ceiling(8192, 8192) = 1, ceiling(8194, 8192) = 2, ceiling(18446744073709543422, 8192) = 2251799813685247
    1615 ceiling(16384, 16384) = 1, ceiling(16386, 16384) = 2, ceiling(18446744073709535230, 16384) = 1125899906842623
    1616 ceiling(32768, 32768) = 1, ceiling(32770, 32768) = 2, ceiling(18446744073709518846, 32768) = 562949953421311
    1617 ceiling(65536, 65536) = 1, ceiling(65538, 65536) = 2, ceiling(18446744073709486078, 65536) = 281474976710655
    1618 ceiling(131072, 131072) = 1, ceiling(131074, 131072) = 2, ceiling(18446744073709420542, 131072) = 140737488355327
    1619 ceiling(262144, 262144) = 1, ceiling(262146, 262144) = 2, ceiling(18446744073709289470, 262144) = 70368744177663
    1620 ceiling(524288, 524288) = 1, ceiling(524290, 524288) = 2, ceiling(18446744073709027326, 524288) = 35184372088831
    1621 ceiling(1048576, 1048576) = 1, ceiling(1048578, 1048576) = 2, ceiling(18446744073708503038, 1048576) = 17592186044415
    1622 ceiling(2097152, 2097152) = 1, ceiling(2097154, 2097152) = 2, ceiling(18446744073707454462, 2097152) = 8796093022207
    1623 ceiling(4194304, 4194304) = 1, ceiling(4194306, 4194304) = 2, ceiling(18446744073705357310, 4194304) = 4398046511103
    1624 ceiling(8388608, 8388608) = 1, ceiling(8388610, 8388608) = 2, ceiling(18446744073701163006, 8388608) = 2199023255551
    1625 ceiling(16777216, 16777216) = 1, ceiling(16777218, 16777216) = 2, ceiling(18446744073692774398, 16777216) = 1099511627775
    1626 ceiling(33554432, 33554432) = 1, ceiling(33554434, 33554432) = 2, ceiling(18446744073675997182, 33554432) = 549755813887
    1627 ceiling(67108864, 67108864) = 1, ceiling(67108866, 67108864) = 2, ceiling(18446744073642442750, 67108864) = 274877906943
    1628 ceiling(134217728, 134217728) = 1, ceiling(134217730, 134217728) = 2, ceiling(18446744073575333886, 134217728) = 137438953471
    1629 ceiling(268435456, 268435456) = 1, ceiling(268435458, 268435456) = 2, ceiling(18446744073441116158, 268435456) = 68719476735
    1630 ceiling(536870912, 536870912) = 1, ceiling(536870914, 536870912) = 2, ceiling(18446744073172680702, 536870912) = 34359738367
    1631 ceiling(1073741824, 1073741824) = 1, ceiling(1073741826, 1073741824) = 2, ceiling(18446744072635809790, 1073741824) = 17179869183
    1632 ceiling(2147483648, 2147483648) = 1, ceiling(2147483650, 2147483648) = 2, ceiling(18446744071562067966, 2147483648) = 8589934591
    1633 ceiling(4294967296, 4294967296) = 1, ceiling(4294967298, 4294967296) = 2, ceiling(18446744069414584318, 4294967296) = 4294967295
    1634 ceiling(8589934592, 8589934592) = 1, ceiling(8589934594, 8589934592) = 2, ceiling(18446744065119617022, 8589934592) = 2147483647
    1635 ceiling(17179869184, 17179869184) = 1, ceiling(17179869186, 17179869184) = 2, ceiling(18446744056529682430, 17179869184) = 1073741823
    1636 ceiling(34359738368, 34359738368) = 1, ceiling(34359738370, 34359738368) = 2, ceiling(18446744039349813246, 34359738368) = 536870911
    1637 ceiling(68719476736, 68719476736) = 1, ceiling(68719476738, 68719476736) = 2, ceiling(18446744004990074878, 68719476736) = 268435455
    1638 ceiling(137438953472, 137438953472) = 1, ceiling(137438953474, 137438953472) = 2, ceiling(18446743936270598142, 137438953472) = 134217727
    1639 ceiling(274877906944, 274877906944) = 1, ceiling(274877906946, 274877906944) = 2, ceiling(18446743798831644670, 274877906944) = 67108863
    1640 ceiling(549755813888, 549755813888) = 1, ceiling(549755813890, 549755813888) = 2, ceiling(18446743523953737726, 549755813888) = 33554431
    1641 ceiling(1099511627776, 1099511627776) = 1, ceiling(1099511627778, 1099511627776) = 2, ceiling(18446742974197923838, 1099511627776) = 16777215
    1642 ceiling(2199023255552, 2199023255552) = 1, ceiling(2199023255554, 2199023255552) = 2, ceiling(18446741874686296062, 2199023255552) = 8388607
    1643 ceiling(4398046511104, 4398046511104) = 1, ceiling(4398046511106, 4398046511104) = 2, ceiling(18446739675663040510, 4398046511104) = 4194303
    1644 ceiling(8796093022208, 8796093022208) = 1, ceiling(8796093022210, 8796093022208) = 2, ceiling(18446735277616529406, 8796093022208) = 2097151
    1645 ceiling(17592186044416, 17592186044416) = 1, ceiling(17592186044418, 17592186044416) = 2, ceiling(18446726481523507198, 17592186044416) = 1048575
    1646 ceiling(35184372088832, 35184372088832) = 1, ceiling(35184372088834, 35184372088832) = 2, ceiling(18446708889337462782, 35184372088832) = 524287
    1647 ceiling(70368744177664, 70368744177664) = 1, ceiling(70368744177666, 70368744177664) = 2, ceiling(18446673704965373950, 70368744177664) = 262143
    1648 ceiling(140737488355328, 140737488355328) = 1, ceiling(140737488355330, 140737488355328) = 2, ceiling(18446603336221196286, 140737488355328) = 131071
    1649 ceiling(281474976710656, 281474976710656) = 1, ceiling(281474976710658, 281474976710656) = 2, ceiling(18446462598732840958, 281474976710656) = 65535
    1650 ceiling(562949953421312, 562949953421312) = 1, ceiling(562949953421314, 562949953421312) = 2, ceiling(18446181123756130302, 562949953421312) = 32767
    1651 ceiling(1125899906842624, 1125899906842624) = 1, ceiling(1125899906842626, 1125899906842624) = 2, ceiling(18445618173802708990, 1125899906842624) = 16383
    1652 ceiling(2251799813685248, 2251799813685248) = 1, ceiling(2251799813685250, 2251799813685248) = 2, ceiling(18444492273895866366, 2251799813685248) = 8191
    1653 ceiling(4503599627370496, 4503599627370496) = 1, ceiling(4503599627370498, 4503599627370496) = 2, ceiling(18442240474082181118, 4503599627370496) = 4095
    1654 ceiling(9007199254740992, 9007199254740992) = 1, ceiling(9007199254740994, 9007199254740992) = 2, ceiling(18437736874454810622, 9007199254740992) = 2047
    1655 ceiling(18014398509481984, 18014398509481984) = 1, ceiling(18014398509481986, 18014398509481984) = 2, ceiling(18428729675200069630, 18014398509481984) = 1023
    1656 ceiling(36028797018963968, 36028797018963968) = 1, ceiling(36028797018963970, 36028797018963968) = 2, ceiling(18410715276690587646, 36028797018963968) = 511
    1657 ceiling(72057594037927936, 72057594037927936) = 1, ceiling(72057594037927938, 72057594037927936) = 2, ceiling(18374686479671623678, 72057594037927936) = 255
    1658 ceiling(144115188075855872, 144115188075855872) = 1, ceiling(144115188075855874, 144115188075855872) = 2, ceiling(18302628885633695742, 144115188075855872) = 127
    1659 ceiling(288230376151711744, 288230376151711744) = 1, ceiling(288230376151711746, 288230376151711744) = 2, ceiling(18158513697557839870, 288230376151711744) = 63
    1660 ceiling(576460752303423488, 576460752303423488) = 1, ceiling(576460752303423490, 576460752303423488) = 2, ceiling(17870283321406128126, 576460752303423488) = 31
    1661 ceiling(1152921504606846976, 1152921504606846976) = 1, ceiling(1152921504606846978, 1152921504606846976) = 2, ceiling(17293822569102704638, 1152921504606846976) = 15
    1662 ceiling(2305843009213693952, 2305843009213693952) = 1, ceiling(2305843009213693954, 2305843009213693952) = 2, ceiling(16140901064495857662, 2305843009213693952) = 7
    1663 ceiling(4611686018427387904, 4611686018427387904) = 1, ceiling(4611686018427387906, 4611686018427387904) = 2, ceiling(13835058055282163710, 4611686018427387904) = 3
    1664 ceiling(9223372036854775808, 9223372036854775808) = 1, ceiling(9223372036854775810, 9223372036854775808) = 0, ceiling(9223372036854775806, 9223372036854775808) = 1
    1665 
     1909ceiling(2, 2) = 2, ceiling(4, 2) = 4, ceiling(18446744073709551612, 2) = 18446744073709551612
     1910ceiling(4, 4) = 4, ceiling(6, 4) = 8, ceiling(18446744073709551610, 4) = 18446744073709551612
     1911ceiling(8, 8) = 8, ceiling(10, 8) = 16, ceiling(18446744073709551606, 8) = 18446744073709551608
     1912ceiling(16, 16) = 16, ceiling(18, 16) = 32, ceiling(18446744073709551598, 16) = 18446744073709551600
     1913ceiling(32, 32) = 32, ceiling(34, 32) = 64, ceiling(18446744073709551582, 32) = 18446744073709551584
     1914ceiling(64, 64) = 64, ceiling(66, 64) = 128, ceiling(18446744073709551550, 64) = 18446744073709551552
     1915ceiling(128, 128) = 128, ceiling(130, 128) = 256, ceiling(18446744073709551486, 128) = 18446744073709551488
     1916ceiling(256, 256) = 256, ceiling(258, 256) = 512, ceiling(18446744073709551358, 256) = 18446744073709551360
     1917ceiling(512, 512) = 512, ceiling(514, 512) = 1024, ceiling(18446744073709551102, 512) = 18446744073709551104
     1918ceiling(1024, 1024) = 1024, ceiling(1026, 1024) = 2048, ceiling(18446744073709550590, 1024) = 18446744073709550592
     1919ceiling(2048, 2048) = 2048, ceiling(2050, 2048) = 4096, ceiling(18446744073709549566, 2048) = 18446744073709549568
     1920ceiling(4096, 4096) = 4096, ceiling(4098, 4096) = 8192, ceiling(18446744073709547518, 4096) = 18446744073709547520
     1921ceiling(8192, 8192) = 8192, ceiling(8194, 8192) = 16384, ceiling(18446744073709543422, 8192) = 18446744073709543424
     1922ceiling(16384, 16384) = 16384, ceiling(16386, 16384) = 32768, ceiling(18446744073709535230, 16384) = 18446744073709535232
     1923ceiling(32768, 32768) = 32768, ceiling(32770, 32768) = 65536, ceiling(18446744073709518846, 32768) = 18446744073709518848
     1924ceiling(65536, 65536) = 65536, ceiling(65538, 65536) = 131072, ceiling(18446744073709486078, 65536) = 18446744073709486080
     1925ceiling(131072, 131072) = 131072, ceiling(131074, 131072) = 262144, ceiling(18446744073709420542, 131072) = 18446744073709420544
     1926ceiling(262144, 262144) = 262144, ceiling(262146, 262144) = 524288, ceiling(18446744073709289470, 262144) = 18446744073709289472
     1927ceiling(524288, 524288) = 524288, ceiling(524290, 524288) = 1048576, ceiling(18446744073709027326, 524288) = 18446744073709027328
     1928ceiling(1048576, 1048576) = 1048576, ceiling(1048578, 1048576) = 2097152, ceiling(18446744073708503038, 1048576) = 18446744073708503040
     1929ceiling(2097152, 2097152) = 2097152, ceiling(2097154, 2097152) = 4194304, ceiling(18446744073707454462, 2097152) = 18446744073707454464
     1930ceiling(4194304, 4194304) = 4194304, ceiling(4194306, 4194304) = 8388608, ceiling(18446744073705357310, 4194304) = 18446744073705357312
     1931ceiling(8388608, 8388608) = 8388608, ceiling(8388610, 8388608) = 16777216, ceiling(18446744073701163006, 8388608) = 18446744073701163008
     1932ceiling(16777216, 16777216) = 16777216, ceiling(16777218, 16777216) = 33554432, ceiling(18446744073692774398, 16777216) = 18446744073692774400
     1933ceiling(33554432, 33554432) = 33554432, ceiling(33554434, 33554432) = 67108864, ceiling(18446744073675997182, 33554432) = 18446744073675997184
     1934ceiling(67108864, 67108864) = 67108864, ceiling(67108866, 67108864) = 134217728, ceiling(18446744073642442750, 67108864) = 18446744073642442752
     1935ceiling(134217728, 134217728) = 134217728, ceiling(134217730, 134217728) = 268435456, ceiling(18446744073575333886, 134217728) = 18446744073575333888
     1936ceiling(268435456, 268435456) = 268435456, ceiling(268435458, 268435456) = 536870912, ceiling(18446744073441116158, 268435456) = 18446744073441116160
     1937ceiling(536870912, 536870912) = 536870912, ceiling(536870914, 536870912) = 1073741824, ceiling(18446744073172680702, 536870912) = 18446744073172680704
     1938ceiling(1073741824, 1073741824) = 1073741824, ceiling(1073741826, 1073741824) = 2147483648, ceiling(18446744072635809790, 1073741824) = 18446744072635809792
     1939ceiling(2147483648, 2147483648) = 2147483648, ceiling(2147483650, 2147483648) = 4294967296, ceiling(18446744071562067966, 2147483648) = 18446744071562067968
     1940ceiling(4294967296, 4294967296) = 4294967296, ceiling(4294967298, 4294967296) = 8589934592, ceiling(18446744069414584318, 4294967296) = 18446744069414584320
     1941ceiling(8589934592, 8589934592) = 8589934592, ceiling(8589934594, 8589934592) = 17179869184, ceiling(18446744065119617022, 8589934592) = 18446744065119617024
     1942ceiling(17179869184, 17179869184) = 17179869184, ceiling(17179869186, 17179869184) = 34359738368, ceiling(18446744056529682430, 17179869184) = 18446744056529682432
     1943ceiling(34359738368, 34359738368) = 34359738368, ceiling(34359738370, 34359738368) = 68719476736, ceiling(18446744039349813246, 34359738368) = 18446744039349813248
     1944ceiling(68719476736, 68719476736) = 68719476736, ceiling(68719476738, 68719476736) = 137438953472, ceiling(18446744004990074878, 68719476736) = 18446744004990074880
     1945ceiling(137438953472, 137438953472) = 137438953472, ceiling(137438953474, 137438953472) = 274877906944, ceiling(18446743936270598142, 137438953472) = 18446743936270598144
     1946ceiling(274877906944, 274877906944) = 274877906944, ceiling(274877906946, 274877906944) = 549755813888, ceiling(18446743798831644670, 274877906944) = 18446743798831644672
     1947ceiling(549755813888, 549755813888) = 549755813888, ceiling(549755813890, 549755813888) = 1099511627776, ceiling(18446743523953737726, 549755813888) = 18446743523953737728
     1948ceiling(1099511627776, 1099511627776) = 1099511627776, ceiling(1099511627778, 1099511627776) = 2199023255552, ceiling(18446742974197923838, 1099511627776) = 18446742974197923840
     1949ceiling(2199023255552, 2199023255552) = 2199023255552, ceiling(2199023255554, 2199023255552) = 4398046511104, ceiling(18446741874686296062, 2199023255552) = 18446741874686296064
     1950ceiling(4398046511104, 4398046511104) = 4398046511104, ceiling(4398046511106, 4398046511104) = 8796093022208, ceiling(18446739675663040510, 4398046511104) = 18446739675663040512
     1951ceiling(8796093022208, 8796093022208) = 8796093022208, ceiling(8796093022210, 8796093022208) = 17592186044416, ceiling(18446735277616529406, 8796093022208) = 18446735277616529408
     1952ceiling(17592186044416, 17592186044416) = 17592186044416, ceiling(17592186044418, 17592186044416) = 35184372088832, ceiling(18446726481523507198, 17592186044416) = 18446726481523507200
     1953ceiling(35184372088832, 35184372088832) = 35184372088832, ceiling(35184372088834, 35184372088832) = 70368744177664, ceiling(18446708889337462782, 35184372088832) = 18446708889337462784
     1954ceiling(70368744177664, 70368744177664) = 70368744177664, ceiling(70368744177666, 70368744177664) = 140737488355328, ceiling(18446673704965373950, 70368744177664) = 18446673704965373952
     1955ceiling(140737488355328, 140737488355328) = 140737488355328, ceiling(140737488355330, 140737488355328) = 281474976710656, ceiling(18446603336221196286, 140737488355328) = 18446603336221196288
     1956ceiling(281474976710656, 281474976710656) = 281474976710656, ceiling(281474976710658, 281474976710656) = 562949953421312, ceiling(18446462598732840958, 281474976710656) = 18446462598732840960
     1957ceiling(562949953421312, 562949953421312) = 562949953421312, ceiling(562949953421314, 562949953421312) = 1125899906842624, ceiling(18446181123756130302, 562949953421312) = 18446181123756130304
     1958ceiling(1125899906842624, 1125899906842624) = 1125899906842624, ceiling(1125899906842626, 1125899906842624) = 2251799813685248, ceiling(18445618173802708990, 1125899906842624) = 18445618173802708992
     1959ceiling(2251799813685248, 2251799813685248) = 2251799813685248, ceiling(2251799813685250, 2251799813685248) = 4503599627370496, ceiling(18444492273895866366, 2251799813685248) = 18444492273895866368
     1960ceiling(4503599627370496, 4503599627370496) = 4503599627370496, ceiling(4503599627370498, 4503599627370496) = 9007199254740992, ceiling(18442240474082181118, 4503599627370496) = 18442240474082181120
     1961ceiling(9007199254740992, 9007199254740992) = 9007199254740992, ceiling(9007199254740994, 9007199254740992) = 18014398509481984, ceiling(18437736874454810622, 9007199254740992) = 18437736874454810624
     1962ceiling(18014398509481984, 18014398509481984) = 18014398509481984, ceiling(18014398509481986, 18014398509481984) = 36028797018963968, ceiling(18428729675200069630, 18014398509481984) = 18428729675200069632
     1963ceiling(36028797018963968, 36028797018963968) = 36028797018963968, ceiling(36028797018963970, 36028797018963968) = 72057594037927936, ceiling(18410715276690587646, 36028797018963968) = 18410715276690587648
     1964ceiling(72057594037927936, 72057594037927936) = 72057594037927936, ceiling(72057594037927938, 72057594037927936) = 144115188075855872, ceiling(18374686479671623678, 72057594037927936) = 18374686479671623680
     1965ceiling(144115188075855872, 144115188075855872) = 144115188075855872, ceiling(144115188075855874, 144115188075855872) = 288230376151711744, ceiling(18302628885633695742, 144115188075855872) = 18302628885633695744
     1966ceiling(288230376151711744, 288230376151711744) = 288230376151711744, ceiling(288230376151711746, 288230376151711744) = 576460752303423488, ceiling(18158513697557839870, 288230376151711744) = 18158513697557839872
     1967ceiling(576460752303423488, 576460752303423488) = 576460752303423488, ceiling(576460752303423490, 576460752303423488) = 1152921504606846976, ceiling(17870283321406128126, 576460752303423488) = 17870283321406128128
     1968ceiling(1152921504606846976, 1152921504606846976) = 1152921504606846976, ceiling(1152921504606846978, 1152921504606846976) = 2305843009213693952, ceiling(17293822569102704638, 1152921504606846976) = 17293822569102704640
     1969ceiling(2305843009213693952, 2305843009213693952) = 2305843009213693952, ceiling(2305843009213693954, 2305843009213693952) = 4611686018427387904, ceiling(16140901064495857662, 2305843009213693952) = 16140901064495857664
     1970ceiling(4611686018427387904, 4611686018427387904) = 4611686018427387904, ceiling(4611686018427387906, 4611686018427387904) = 9223372036854775808, ceiling(13835058055282163710, 4611686018427387904) = 13835058055282163712
     1971ceiling(9223372036854775808, 9223372036854775808) = 9223372036854775808, ceiling(9223372036854775810, 9223372036854775808) = 0, ceiling(9223372036854775806, 9223372036854775808) = 9223372036854775808
     1972
  • tests/.expect/castError.txt

    r07d867b r22f94a4  
    1 castError.cfa:21:1 error: Cannot choose between 3 alternatives for expression
     1castError.cfa:23:1 error: Cannot choose between 3 alternatives for expression
    22Explicit Cast of:
    33  Name: f
     
    3535
    3636
    37 castError.cfa:26:1 error: Cannot choose between 2 alternatives for expression
     37castError.cfa:28:1 error: Cannot choose between 2 alternatives for expression
    3838Generated Cast of:
    3939  Comma Expression:
     
    6262
    6363
     64castError.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  
    88//
    99// Author           : Peter A. Buhr
    10 // Created On       : Tue Jul 16 16:47:22 2019
     10// Created On       : Fri Jun 19 13:44:05 2020
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jul 17 18:04:44 2019
    13 // Update Count     : 26
     12// Last Modified On : Fri Jun 19 17:58:03 2020
     13// Update Count     : 4
    1414//
    1515
    1616#include <fstream.hfa>
    17 #include <stdlib.hfa>                                                                   // new/delete
     17#include <exception.hfa>
    1818
    1919int 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
    2223        try {
    2324                choose ( argc ) {
    2425                  case 2, 3:
    25                           in = new( (const char *)argv[1] );            // open input file first as output creates file
    26                           if ( argc == 3 ) out = new( (const char *)argv[2] ); // only open output if input opens as output created if nonexistent
    27                   case 1: ;                                     // use default files
     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
    2829                  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) ] ]";
    3031                } // 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
    3138
    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
    3541
    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
    4548} // main
    4649
  • tests/.expect/functions.x64.txt

    r07d867b r22f94a4  
    121121
    122122}
     123struct _conc__tuple2_0;
    123124struct _conc__tuple2_0 {
    124125    signed int field_0;
     
    157158
    158159}
     160struct _conc__tuple3_1;
    159161struct _conc__tuple3_1 {
    160162    signed int field_0;
     
    170172    __attribute__ ((unused)) struct _conc__tuple3_1 _X9_retval_fT3iii_1 = {  };
    171173}
     174struct _conc__tuple3_2;
    172175struct _conc__tuple3_2 {
    173176    signed int field_0;
     
    260263    __attribute__ ((unused)) signed int *const _X10_retval_f3KPi_1;
    261264}
     265struct _conc__tuple2_3;
    262266struct _conc__tuple2_3 {
    263267    signed int *field_0;
  • tests/.expect/functions.x86.txt

    r07d867b r22f94a4  
    121121
    122122}
     123struct _conc__tuple2_0;
    123124struct _conc__tuple2_0 {
    124125    signed int field_0;
     
    157158
    158159}
     160struct _conc__tuple3_1;
    159161struct _conc__tuple3_1 {
    160162    signed int field_0;
     
    170172    __attribute__ ((unused)) struct _conc__tuple3_1 _X9_retval_fT3iii_1 = {  };
    171173}
     174struct _conc__tuple3_2;
    172175struct _conc__tuple3_2 {
    173176    signed int field_0;
     
    260263    __attribute__ ((unused)) signed int *const _X10_retval_f3KPi_1;
    261264}
     265struct _conc__tuple2_3;
    262266struct _conc__tuple2_3 {
    263267    signed int *field_0;
  • tests/.expect/time.txt

    r07d867b r22f94a4  
    1110800 2 3.375 12 1.00001
     20.125 0.0333333333333333 3.375 12000. 1000010.
    230 2 3.375
    347 7 7
  • tests/.in/copyfile.txt

    r07d867b r22f94a4  
    88//
    99// Author           : Peter A. Buhr
    10 // Created On       : Tue Jul 16 16:47:22 2019
     10// Created On       : Fri Jun 19 13:44:05 2020
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jul 17 18:04:44 2019
    13 // Update Count     : 26
     12// Last Modified On : Fri Jun 19 17:58:03 2020
     13// Update Count     : 4
    1414//
    1515
    1616#include <fstream.hfa>
    17 #include <stdlib.hfa>                                                                   // new/delete
     17#include <exception.hfa>
    1818
    1919int 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
    2223        try {
    2324                choose ( argc ) {
    2425                  case 2, 3:
    25                           in = new( (const char *)argv[1] );            // open input file first as output creates file
    26                           if ( argc == 3 ) out = new( (const char *)argv[2] ); // only open output if input opens as output created if nonexistent
    27                   case 1: ;                                     // use default files
     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
    2829                  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) ] ]";
    3031                } // 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
    3138
    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
    3541
    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
    4548} // main
    4649
  • tests/.in/manipulatorsInput.txt

    r07d867b r22f94a4  
    27273.5 3.5 3.456E+23.456E+2 -0x1.2p-3 3.5 0X1.23p3     3.5
    28283.5 3.5 3.456E+23.456E+2 -0x1.2p-3 3.5 0X1.23p3     3.5
     2925 -25 42798
     301402432282 1505850196993244515
     31394749758663249135511342
     3212935154696204706112391834394
     33
     34423859149128410414395372834994551
     35
     36
     3713889016598639747063234935497057631587
     38170141183460469231731687303715884105727
     39340282366920938463463374607431768211455
     40-340282366920938463463374607431768211455
     41340282366920938463463374607431768211455999
     421234567890123456789 -1234567890123456789
  • tests/Makefile.am

    r07d867b r22f94a4  
    1818ACLOCAL_AMFLAGS  = -I automake
    1919
    20 include $(top_srcdir)/src/cfa.make
     20include $(top_srcdir)/tools/build/cfa.make
     21
     22DEFAULT_INCLUDES = -I${abs_srcdir}
    2123
    2224debug=yes
  • tests/avltree/avl1.cfa

    r07d867b r22f94a4  
    2424tree(K, V) * create(K key, V value) {
    2525  // 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)));
    2727  (*t){ key, value };
    2828  return t;
  • tests/bitmanip3.cfa

    r07d867b r22f94a4  
    1010// Created On       : Tue Apr  7 21:22:59 2020
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Apr 21 16:25:09 2020
    13 // Update Count     : 61
     12// Last Modified On : Mon Aug 10 09:31:35 2020
     13// Update Count     : 65
    1414//
    1515
     
    134134
    135135        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 );
    139139        for ( sc = 1; sc != 0; sc <<= 1 ) {
    140140                scr1 = floor2( sc, sc ); scr2 = floor2( sc + 2hh, sc ); scr3 = floor2( -sc - 2hh, sc );
     
    144144
    145145        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 );
    149149        for ( uc = 1; uc != 0; uc <<= 1 ) {
    150150                ucr1 = floor2( uc, uc ); ucr2 = floor2( uc + 2hh, uc ); ucr3 = floor2( -uc - 2hh, uc );
     
    154154
    155155        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 );
    159159        for ( si = 1; si != 0; si <<= 1 ) {
    160160                sir1 = floor2( si, si ); sir2 = floor2( si + 2hh, si ); sir3 = floor2( -si - 2hh, si );
     
    164164
    165165        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 );
    169169        for ( usi = 1; usi != 0; usi <<= 1 ) {
    170170                usir1 = floor2( usi, usi ); usir2 = floor2( usi + 2hh, usi ); usir3 = floor2( -usi - 2hh, usi );
     
    174174
    175175        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 );
    179179        for ( i = 1; i != 0; i <<= 1 ) {
    180180                ir1 = floor2( i, i ); ir2 = floor2( i + 2hh, i ); ir3 = floor2( -i - 2hh, i );
     
    184184
    185185        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 );
    189189        for ( ui = 1; ui != 0; ui <<= 1 ) {
    190190                uir1 = floor2( ui, ui ); uir2 = floor2( ui + 2hh, ui ); uir3 = floor2( -ui - 2hh, ui );
     
    194194
    195195        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 );
    199199        for ( li = 1; li != 0; li <<= 1 ) {
    200200                lir1 = floor2( li, li ); lir2 = floor2( li + 2hh, li ); lir3 = floor2( -li - 2hh, li );
     
    204204
    205205        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 );
    209209        for ( uli = 1; uli != 0; uli <<= 1 ) {
    210210                ulir1 = floor2( uli, uli ); ulir2 = floor2( uli + 2hh, uli ); ulir3 = floor2( -uli - 2hh, uli );
     
    214214
    215215        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 );
    219219        for ( lli = 1; lli != 0; lli <<= 1 ) {
    220220                llir1 = floor2( lli, lli ); llir2 = floor2( lli + 2hh, lli ); llir3 = floor2( -lli - 2hh, lli );
     
    224224
    225225        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 );
    229229        for ( ulli = 1; ulli != 0; ulli <<= 1 ) {
    230230                ullir1 = floor2( ulli, ulli ); ullir2 = floor2( ulli + 2hh, ulli ); ullir3 = floor2( -ulli - 2hh, ulli );
     
    312312
    313313        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 );
    317317        for ( sc = 1; sc != 0; sc <<= 1 ) {
    318318                scr1 = ceiling2( sc, sc ); scr2 = ceiling2( sc + 2hh, sc ); scr3 = ceiling2( -sc - 2hh, sc );
     
    322322
    323323        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 );
    327327        for ( uc = 1; uc != 0; uc <<= 1 ) {
    328328                ucr1 = ceiling2( uc, uc ); ucr2 = ceiling2( uc + 2hh, uc ); ucr3 = ceiling2( -uc - 2hh, uc );
     
    332332
    333333        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 );
    337337        for ( si = 1; si != 0; si <<= 1 ) {
    338338                sir1 = ceiling2( si, si ); sir2 = ceiling2( si + 2hh, si ); sir3 = ceiling2( -si - 2hh, si );
     
    342342
    343343        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 );
    347347        for ( usi = 1; usi != 0; usi <<= 1 ) {
    348348                usir1 = ceiling2( usi, usi ); usir2 = ceiling2( usi + 2hh, usi ); usir3 = ceiling2( -usi - 2hh, usi );
     
    352352
    353353        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 );
    357357        for ( i = 1; i != 0; i <<= 1 ) {
    358358                ir1 = ceiling2( i, i ); ir2 = ceiling2( i + 2hh, i ); ir3 = ceiling2( -i - 2hh, i );
     
    362362
    363363        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 );
    367367        for ( ui = 1; ui != 0; ui <<= 1 ) {
    368368                uir1 = ceiling2( ui, ui ); uir2 = ceiling2( ui + 2hh, ui ); uir3 = ceiling2( -ui - 2hh, ui );
     
    372372
    373373        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 );
    377377        for ( li = 1; li != 0; li <<= 1 ) {
    378378                lir1 = ceiling2( li, li ); lir2 = ceiling2( li + 2hh, li ); lir3 = ceiling2( -li - 2hh, li );
     
    382382
    383383        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 );
    387387        for ( uli = 1; uli != 0; uli <<= 1 ) {
    388388                ulir1 = ceiling2( uli, uli ); ulir2 = ceiling2( uli + 2hh, uli ); ulir3 = ceiling2( -uli - 2hh, uli );
     
    392392
    393393        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 );
    397397        for ( lli = 1; lli != 0; lli <<= 1 ) {
    398398                llir1 = ceiling2( lli, lli ); llir2 = ceiling2( lli + 2hh, lli ); llir3 = ceiling2( -lli - 2hh, lli );
     
    402402
    403403        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 );
    407407        for ( ulli = 1; ulli != 0; ulli <<= 1 ) {
    408408                ullir1 = ceiling2( ulli, ulli ); ullir2 = ceiling2( ulli + 2hh, ulli ); ullir3 = ceiling2( -ulli - 2hh, ulli );
    409409                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 );
    410484        } // for
    411485        printf( "\n" );
  • tests/castError.cfa

    r07d867b r22f94a4  
    1414//
    1515
     16forall(otype T) struct S { T p; };
    1617int f;
     18S(int) sint;
    1719
    1820void f() {
     
    2527        short int v;
    2628        3, v;           // implicit void cast
     29
     30        (S(char)) sint;
    2731}
    2832
  • tests/concurrent/examples/datingService.cfa

    r07d867b r22f94a4  
    3535                signal_block( Boys[ccode] );                                    // restart boy to set phone number
    3636        } // 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;
    3838        return BoyPhoneNo;
    3939} // DatingService girl
     
    4747                signal_block( Girls[ccode] );                                   // restart girl to set phone number
    4848        } // if
    49         //sout | " Boy:" | PhoneNo | "is dating Girl" | GirlPhoneNo | "with ccode" | ccode;
     49        // sout | " Boy:" | PhoneNo | "is dating Girl" | GirlPhoneNo | "with ccode" | ccode;
    5050        return GirlPhoneNo;
    5151} // DatingService boy
  • tests/concurrent/signal/block.cfa

    r07d867b r22f94a4  
    8282        if( !is_empty( cond ) ) {
    8383
    84                 $thread * next = front( cond );
     84                $thread * next = ( $thread * ) front( cond );
    8585
    8686                if( ! signal_block( cond ) ) {
  • tests/concurrent/signal/disjoint.cfa

    r07d867b r22f94a4  
    2121#endif
    2222
     23// This tests checks what happens when someone barges in the midle of the release
     24// of a bulk of monitors.
     25
    2326enum state_t { WAIT, SIGNAL, BARGE };
    2427
    2528monitor global_t {};
    26 global_t mut;
    2729
    2830monitor global_data_t;
     
    3335        int counter;
    3436        state_t state;
    35 } data;
     37};
     38
     39// Use a global struct because the order needs to match with Signaller thread
     40struct {
     41        global_t mut;
     42        global_data_t data;
     43} globals;
    3644
    3745condition cond;
     
    4048
    4149void ?{}( global_data_t & this ) {
    42         this.counter == 0;
     50        this.counter = 0;
    4351        this.state = BARGE;
    4452}
     
    5361
    5462thread Barger {};
     63void ?{}( Barger & this ) {
     64        ((thread&)this){ "Barger Thread" };
     65}
    5566
    5667void main( Barger & this ) {
    5768        while( !all_done ) {
    58                 barge( data );
     69                barge( globals.data );
    5970                yield();
    6071        }
     
    7889
    7990thread Waiter {};
     91void ?{}( Waiter & this ) {
     92        ((thread&)this){ "Waiter Thread" };
     93}
    8094
    8195void main( Waiter & this ) {
    82         while( wait( mut, data ) ) { KICK_WATCHDOG; yield(); }
     96        while( wait( globals.mut, globals.data ) ) { KICK_WATCHDOG; yield(); }
    8397}
    8498
     
    92106
    93107void logic( global_t & mutex a ) {
    94         signal( cond, a, data );
     108        signal( cond, a, globals.data );
    95109
    96110        yield( random( 10 ) );
    97111
    98112        //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;
    102116        }
    103117}
    104118
    105119thread Signaller {};
     120void ?{}( Signaller & this ) {
     121        ((thread&)this){ "Signaller Thread" };
     122}
    106123
    107124void main( Signaller & this ) {
    108125        while( !all_done ) {
    109                 logic( mut );
     126                logic( globals.mut );
    110127                yield();
    111128        }
  • tests/concurrent/waitfor/when.cfa

    r07d867b r22f94a4  
    5757
    5858void 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
    5963        for( int i = 0; i < N; i++ ) {
    6064                   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  
    88//
    99// Author           : Peter A. Buhr
    10 // Created On       : Tue Jul 16 16:47:22 2019
     10// Created On       : Fri Jun 19 13:44:05 2020
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jul 17 18:04:44 2019
    13 // Update Count     : 26
     12// Last Modified On : Sun Jul  5 11:27:43 2020
     13// Update Count     : 5
    1414//
    1515
    1616#include <fstream.hfa>
    17 #include <stdlib.hfa>                                                                   // new/delete
     17#include <exception.hfa>
    1818
    1919int 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
    2223        try {
    23                 choose ( argc ) {
     24                choose ( argc ) {                                                               // terminate if command-line errors
    2425                  case 2, 3:
    25                           in = new( (const char *)argv[1] );            // open input file first as output creates file
    26                           if ( argc == 3 ) out = new( (const char *)argv[2] ); // only open output if input opens as output created if nonexistent
    27                   case 1: ;                                     // use default files
    28                   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) ] ]";
    3031                } // 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
    3138
    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
    3541
    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
    4548} // main
    4649
  • tests/errors/.expect/completeType.x64.txt

    r07d867b r22f94a4  
    132132?=?: pointer to function
    133133        ... with parameters
    134           reference to instance of type _104_0_T (not function type)
    135           instance of type _104_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)
    136136        ... returning
    137           _retval__operator_assign: instance of type _104_0_T (not function type)
     137          _retval__operator_assign: instance of type _109_0_T (not function type)
    138138          ... with attributes:
    139139            Attribute with name: unused
  • tests/exceptions/.expect/resume.txt

    r07d867b r22f94a4  
    44end of try clause
    55Exiting: simple try clause
     6
     7catch-all
    68
    79throwing child exception
     
    2931inner catch
    3032outer catch
     33
     34throw
     35rethrow
     36handle
  • tests/exceptions/.expect/terminate.txt

    r07d867b r22f94a4  
    33simple catch
    44Exiting: simple catch clause
     5
     6catch-all
    57
    68throwing child exception
     
    2729inner catch
    2830outer catch
     31
     32throw
     33rethrow
     34handle
  • tests/exceptions/conditional.cfa

    r07d867b r22f94a4  
    1717};
    1818
    19 void num_error_msg(num_error * this) {
     19const char * num_error_msg(num_error * this) {
    2020    if ( ! this->msg ) {
    2121        static const char * base = "Num Error with code: X";
     
    5656
    5757        try {
    58                 throw &exc;
     58                throw exc;
    5959        } catch (num_error * error ; 3 == error->virtual_table->code( error )) {
    6060                caught_num_error(3, error);
     
    6464
    6565        try {
    66                 throwResume &exc;
     66                throwResume exc;
    6767        } catchResume (num_error * error ; 3 == error->virtual_table->code( error )) {
    6868                caught_num_error(3, error);
  • tests/exceptions/data-except.cfa

    r07d867b r22f94a4  
    2828
    2929        try {
    30                 throw &except;
     30                throw except;
    3131        } catch (paired * exc) {
    3232                printf("%s(%d, %d)\n", paired_msg(exc), exc->first, exc->second);
     
    3737
    3838        try {
    39                 throwResume &except;
     39                throwResume except;
    4040        } catchResume (paired * exc) {
    4141                printf("%s(%d, %d)\n", paired_msg(exc), exc->first, exc->second);
  • tests/exceptions/finally.cfa

    r07d867b r22f94a4  
    1212                try {
    1313                        printf("termination throw\n");
    14                         throw &exc;
     14                        throw exc;
    1515                } finally {
    1616                        loud_exit a = "termination inner finally";
     
    2828                try {
    2929                        printf("resumption throw\n");
    30                         throwResume &exc;
     30                        throwResume exc;
    3131                } finally {
    3232                        loud_exit a = "resumption inner finally";
  • tests/exceptions/interact.cfa

    r07d867b r22f94a4  
    1010        // Resume falls back to terminate.
    1111        try {
    12                 throwResume &(star){};
     12                throwResume (star){};
    1313        } catch (star *) {
    1414                printf("caught as termination\n");
     
    1717        try {
    1818                loud_region a = "try block with resume throw";
    19                 throwResume &(star){};
     19                throwResume (star){};
    2020        } catch (star *) {
    2121                printf("caught as termination\n");
     
    2929        try {
    3030                try {
    31                         throw &(star){};
     31                        throw (star){};
    3232                } catchResume (star *) {
    3333                        printf("resume catch on terminate\n");
     
    4343        try {
    4444                try {
    45                         throwResume &(star){};
     45                        throwResume (star){};
    4646                } catch (star *) {
    4747                        printf("terminate catch on resume\n");
     
    5858                try {
    5959                        try {
    60                                 throw &(star){};
     60                                throw (star){};
    6161                        } catchResume (star *) {
    6262                                printf("inner resume catch (error)\n");
     
    6464                } catch (star * error) {
    6565                        printf("termination catch, will resume\n");
    66                         throwResume error;
     66                        throwResume *error;
    6767                }
    6868        } catchResume (star *) {
     
    7575                try {
    7676                        try {
    77                                 throwResume &(star){};
     77                                throwResume (star){};
    7878                        } catch (star *) {
    7979                                printf("inner termination catch\n");
     
    8181                } catchResume (star * error) {
    8282                        printf("resumption catch, will terminate\n");
    83                         throw error;
     83                        throw *error;
    8484                }
    8585        } catch (star *) {
     
    9494                                try {
    9595                                        printf("throwing resume moon\n");
    96                                         throwResume &(moon){};
     96                                        throwResume (moon){};
    9797                                } catch (star *) {
    9898                                        printf("termination catch\n");
    9999                                }
    100100                                printf("throwing resume star\n");
    101                                 throwResume &(star){};
     101                                throwResume (star){};
    102102                        } catchResume (star *) {
    103103                                printf("resumption star catch\n");
     
    105105                } catchResume (moon *) {
    106106                        printf("resumption moon catch, will terminate\n");
    107                         throw &(star){};
     107                        throw (star){};
    108108                }
    109109        } catchResume (star *) {
  • tests/exceptions/resume.cfa

    r07d867b r22f94a4  
    99TRIVIAL_EXCEPTION(moment_of, zen);
    1010
     11void in_void(void);
     12
    1113int main(int argc, char * argv[]) {
    1214        // The simple throw catchResume test.
     
    1416                loud_exit a = "simple try clause";
    1517                printf("simple throw\n");
    16                 throwResume &(zen){};
     18                throwResume (zen){};
    1719                printf("end of try clause\n");
    1820        } catchResume (zen * error) {
     
    2224        printf("\n");
    2325
     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
    2434        // Catch a parent of the given exception.
    2535        try {
    2636                printf("throwing child exception\n");
    27                 throwResume &(moment_of){};
     37                throwResume (moment_of){};
    2838        } catchResume (zen *) {
    2939                printf("inner parent match\n");
     
    3646        try {
    3747                try {
    38                         throwResume &(yin){};
     48                        throwResume (yin){};
    3949                } catchResume (zen *) {
    4050                        printf("caught yin as zen\n");
     
    5262                        loud_exit a = "rethrow inner try";
    5363                        printf("rethrow inner try\n");
    54                         throwResume &(zen){};
     64                        throwResume (zen){};
    5565                } catchResume (zen *) {
    5666                        loud_exit a = "rethrowing catch clause";
     
    6777        try {
    6878                try {
    69                         throwResume &(yin){};
     79                        throwResume (yin){};
    7080                } catchResume (yin *) {
    7181                        printf("caught yin, will throw yang\n");
    72                         throwResume &(yang){};
     82                        throwResume (yang){};
    7383                } catchResume (yang *) {
    7484                        printf("caught exception from same try\n");
     
    8393                try {
    8494                        printf("throwing first exception\n");
    85                         throwResume &(yin){};
     95                        throwResume (yin){};
    8696                } catchResume (yin *) {
    8797                        printf("caught first exception\n");
    8898                        try {
    8999                                printf("throwing second exception\n");
    90                                 throwResume &(yang){};
     100                                throwResume (yang){};
    91101                        } catchResume (yang *) {
    92102                                printf("caught second exception\n");
     
    104114        try {
    105115                try {
    106                         throwResume &(zen){};
    107                         throwResume &(zen){};
     116                        throwResume (zen){};
     117                        throwResume (zen){};
    108118                } catchResume (zen *) {
    109119                        printf("inner catch\n");
    110120                }
    111                 throwResume &(zen){};
     121                throwResume (zen){};
    112122        } catchResume (zen *) {
    113123                printf("outer catch\n");
    114124        }
     125        printf("\n");
     126
     127        in_void();
    115128}
     129
     130// Do a throw and rethrow in a void function.
     131void 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  
    99TRIVIAL_EXCEPTION(moment_of, zen);
    1010
     11void in_void(void);
     12
    1113int main(int argc, char * argv[]) {
    1214        // The simple throw catch test.
     
    1416                loud_exit a = "simple try clause";
    1517                printf("simple throw\n");
    16                 throw &(zen){};
     18                throw (zen){};
    1719                printf("end of try clause\n");
    1820        } catch (zen * error) {
    19         loud_exit a = "simple catch clause";
     21                loud_exit a = "simple catch clause";
    2022                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");
    2131        }
    2232        printf("\n");
     
    2535        try {
    2636                printf("throwing child exception\n");
    27                 throw &(moment_of){};
     37                throw (moment_of){};
    2838        } catch (zen *) {
    2939                printf("inner parent match\n");
     
    3646        try {
    3747                try {
    38                         throw &(yin){};
     48                        throw (yin){};
    3949                } catch (zen *) {
    4050                        printf("caught yin as zen\n");
     
    5262                        loud_exit a = "rethrow inner try";
    5363                        printf("rethrow inner try\n");
    54                         throw &(zen){};
     64                        throw (zen){};
    5565                } catch (zen *) {
    5666                        loud_exit a = "rethrowing catch clause";
     
    6777        try {
    6878                try {
    69                         throw &(yin){};
     79                        throw (yin){};
    7080                } catch (yin *) {
    7181                        printf("caught yin, will throw yang\n");
    72                         throw &(yang){};
     82                        throw (yang){};
    7383                } catch (yang *) {
    7484                        printf("caught exception from same try\n");
     
    8393                try {
    8494                        printf("throwing first exception\n");
    85                         throw &(yin){};
     95                        throw (yin){};
    8696                } catch (yin *) {
    8797                        printf("caught first exception\n");
    8898                        try {
    8999                                printf("throwing second exception\n");
    90                                 throw &(yang){};
     100                                throw (yang){};
    91101                        } catch (yang *) {
    92102                                printf("caught second exception\n");
     
    104114        try {
    105115                try {
    106                         throw &(zen){};
    107                         throw &(zen){};
     116                        throw (zen){};
     117                        throw (zen){};
    108118                } catch (zen *) {
    109119                        printf("inner catch\n");
    110120                }
    111                 throw &(zen){};
     121                throw (zen){};
    112122        } catch (zen *) {
    113123                printf("outer catch\n");
    114124        }
     125        printf("\n");
     126
     127        in_void();
    115128}
     129
     130// Do a throw and rethrow in a void function.
     131void 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  
    1010// Created On       : Tue Nov  6 17:54:56 2018
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Nov 24 12:34:51 2019
    13 // Update Count     : 28
     12// Last Modified On : Tue Aug  4 06:36:17 2020
     13// Update Count     : 56
    1414//
    1515
     
    7575                size_t s = (i + 1) * 20;
    7676                char * area = (char *)malloc( s );
    77                 if ( area == 0p ) abort( "malloc/free out of memory" );
    7877                area[0] = '\345'; area[s - 1] = '\345';                 // fill first/last
    7978                area[malloc_usable_size( area ) - 1] = '\345';  // fill ultimate byte
     
    8483                size_t s = i + 1;                                                               // +1 to make initialization simpler
    8584                locns[i] = (char *)malloc( s );
    86                 if ( locns[i] == 0p ) abort( "malloc/free out of memory" );
    8785                locns[i][0] = '\345'; locns[i][s - 1] = '\345'; // fill first/last
    8886                locns[i][malloc_usable_size( locns[i] ) - 1] = '\345'; // fill ultimate byte
     
    10098                size_t s = i + default_mmap_start();                    // cross over point
    10199                char * area = (char *)malloc( s );
    102                 if ( area == 0p ) abort( "malloc/free out of memory" );
    103100                area[0] = '\345'; area[s - 1] = '\345';                 // fill first/last
    104101                area[malloc_usable_size( area ) - 1] = '\345';  // fill ultimate byte
     
    109106                size_t s = i + default_mmap_start();                    // cross over point
    110107                locns[i] = (char *)malloc( s );
    111                 if ( locns[i] == 0p ) abort( "malloc/free out of memory" );
    112108                locns[i][0] = '\345'; locns[i][s - 1] = '\345'; // fill first/last
    113109                locns[i][malloc_usable_size( locns[i] ) - 1] = '\345'; // fill ultimate byte
     
    125121                size_t s = (i + 1) * 20;
    126122                char * area = (char *)calloc( 5, s );
    127                 if ( area == 0p ) abort( "calloc/free out of memory" );
    128123                if ( area[0] != '\0' || area[s - 1] != '\0' ||
    129                          area[malloc_usable_size( area ) - 1] != '\0' ||
     124                         area[malloc_size( area ) - 1] != '\0' ||
    130125                         ! malloc_zero_fill( area ) ) abort( "calloc/free corrupt storage1" );
    131126                area[0] = '\345'; area[s - 1] = '\345';                 // fill first/last
     
    137132                size_t s = i + 1;
    138133                locns[i] = (char *)calloc( 5, s );
    139                 if ( locns[i] == 0p ) abort( "calloc/free out of memory" );
    140134                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' ||
    142136                         ! malloc_zero_fill( locns[i] ) ) abort( "calloc/free corrupt storage2" );
    143137                locns[i][0] = '\345'; locns[i][s - 1] = '\345'; // fill first/last
     
    156150                size_t s = i + default_mmap_start();                    // cross over point
    157151                char * area = (char *)calloc( 1, s );
    158                 if ( area == 0p ) abort( "calloc/free out of memory" );
    159152                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" );
    161154                if ( ! malloc_zero_fill( area ) ) abort( "calloc/free corrupt storage4.3" );
    162155                area[0] = '\345'; area[s - 1] = '\345';                 // fill first/last
     
    168161                size_t s = i + default_mmap_start();                    // cross over point
    169162                locns[i] = (char *)calloc( 1, s );
    170                 if ( locns[i] == 0p ) abort( "calloc/free out of memory" );
    171163                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' ||
    173165                         ! malloc_zero_fill( locns[i] ) ) abort( "calloc/free corrupt storage5" );
    174166                locns[i][0] = '\345'; locns[i][s - 1] = '\345'; // fill first/last
     
    188180                for ( s; 1 ~ NoOfAllocs ) {                                             // allocation of size 0 can return null
    189181                        char * area = (char *)memalign( a, s );
    190                         if ( area == 0p ) abort( "memalign/free out of memory" );
    191182                        //sout | i | area;
    192183                        if ( (size_t)area % a != 0 || malloc_alignment( area ) != a ) { // check for initial alignment
     
    206197                        size_t s = i + default_mmap_start();            // cross over point
    207198                        char * area = (char *)memalign( a, s );
    208                         if ( area == 0p ) abort( "memalign/free out of memory" );
    209199                        //sout | i | area;
    210200                        if ( (size_t)area % a != 0 || malloc_alignment( area ) != a ) { // check for initial alignment
     
    222212                // initial N byte allocation
    223213                char * area = (char *)calloc( 5, i );
    224                 if ( area == 0p ) abort( "calloc/realloc/free out of memory" );
    225214                if ( area[0] != '\0' || area[i - 1] != '\0' ||
    226                          area[malloc_usable_size( area ) - 1] != '\0' ||
     215                         area[malloc_size( area ) - 1] != '\0' ||
    227216                         ! malloc_zero_fill( area ) ) abort( "calloc/realloc/free corrupt storage1" );
    228217
     
    230219                for ( s; i ~ 256 * 1024 ~ 26 ) {                                // start at initial memory request
    231220                        area = (char *)realloc( area, s );                      // attempt to reuse storage
    232                         if ( area == 0p ) abort( "calloc/realloc/free out of memory" );
    233221                        if ( area[0] != '\0' || area[s - 1] != '\0' ||
    234                                  area[malloc_usable_size( area ) - 1] != '\0' ||
     222                                 area[malloc_size( area ) - 1] != '\0' ||
    235223                                 ! malloc_zero_fill( area ) ) abort( "calloc/realloc/free corrupt storage2" );
    236224                } // for
     
    244232                size_t s = i + default_mmap_start();                    // cross over point
    245233                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" );
    247235                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 ) );
    250239
    251240                // Do not start this loop index at 0 because realloc of 0 bytes frees the storage.
    252241                for ( r; i ~ 256 * 1024 ~ 26 ) {                                // start at initial memory request
    253242                        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" );
    255244                        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 storage2" );
     245                                 area[malloc_size( area ) - 1] != '\0' ||
     246                                 ! malloc_zero_fill( area ) ) abort( "calloc/realloc/free corrupt storage4" );
    258247                } // for
    259248                free( area );
     
    266255                // initial N byte allocation
    267256                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 ?
    269258                //sout | alignments[a] | area;
    270259                if ( (size_t)area % a != 0 || malloc_alignment( area ) != a ) { // check for initial alignment
     
    277266                        if ( area[0] != '\345' || area[s - 2] != '\345' ) abort( "memalign/realloc/free corrupt storage" );
    278267                        area = (char *)realloc( area, s );                      // attempt to reuse storage
    279                         if ( area == 0p ) abort( "memalign/realloc/free out of memory" ); // no storage ?
    280268                        //sout | i | area;
    281269                        if ( (size_t)area % a != 0 ) {                          // check for initial alignment
     
    293281                for ( s; 1 ~ limit ) {                                                  // allocation of size 0 can return null
    294282                        char * area = (char *)cmemalign( a, 1, s );
    295                         if ( area == 0p ) abort( "cmemalign/free out of memory" );
    296283                        //sout | i | area;
    297284                        if ( (size_t)area % a != 0 || malloc_alignment( area ) != a ) { // check for initial alignment
     
    299286                        } // if
    300287                        if ( area[0] != '\0' || area[s - 1] != '\0' ||
    301                                  area[malloc_usable_size( area ) - 1] != '\0' ||
     288                                 area[malloc_size( area ) - 1] != '\0' ||
    302289                                 ! malloc_zero_fill( area ) ) abort( "cmemalign/free corrupt storage" );
    303290                        area[0] = '\345'; area[s - 1] = '\345';         // fill first/last byte
     
    312299                // initial N byte allocation
    313300                char * area = (char *)cmemalign( a, 1, amount ); // aligned N-byte allocation
    314                 if ( area == 0p ) abort( "cmemalign/realloc/free out of memory" ); // no storage ?
    315301                //sout | alignments[a] | area;
    316302                if ( (size_t)area % a != 0 || malloc_alignment( area ) != a ) { // check for initial alignment
     
    318304                } // if
    319305                if ( area[0] != '\0' || area[amount - 1] != '\0' ||
    320                          area[malloc_usable_size( area ) - 1] != '\0' ||
     306                         area[malloc_size( area ) - 1] != '\0' ||
    321307                         ! malloc_zero_fill( area ) ) abort( "cmemalign/realloc/free corrupt storage1" );
    322308                area[0] = '\345'; area[amount - 2] = '\345';    // fill first/penultimate byte
     
    326312                        if ( area[0] != '\345' || area[s - 2] != '\345' ) abort( "cmemalign/realloc/free corrupt storage2" );
    327313                        area = (char *)realloc( area, s );                      // attempt to reuse storage
    328                         if ( area == 0p ) abort( "cmemalign/realloc/free out of memory" ); // no storage ?
    329314                        //sout | i | area;
    330315                        if ( (size_t)area % a != 0 || malloc_alignment( area ) != a ) { // check for initial alignment
    331316                                abort( "cmemalign/realloc/free bad alignment %p", area );
    332317                        } // 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' ||
    335320                                 ! malloc_zero_fill( area ) ) abort( "cmemalign/realloc/free corrupt storage3" );
    336321                        area[s - 1] = '\345';                                           // fill last byte
     
    345330                // initial N byte allocation
    346331                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 ?
    348332                //sout | alignments[a] | area | endl;
    349333                if ( (size_t)area % a != 0 || malloc_alignment( area ) != a ) { // check for initial alignment
     
    356340                        if ( area[0] != '\345' || area[s - 2] != '\345' ) abort( "memalign/realloc/free corrupt storage" );
    357341                        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 ?
    359342                        //sout | i | area | endl;
    360343                        if ( (size_t)area % a * 2 != 0 ) {                      // check for initial alignment
     
    371354        for ( size_t a = libAlign() + libAlign(); a <= limit; a += a ) { // generate powers of 2
    372355                // 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
    375357                //sout | alignments[a] | area | endl;
    376358                if ( (size_t)area % a != 0 || malloc_alignment( area ) != a ) { // check for initial alignment
     
    378360                } // if
    379361                if ( area[0] != '\0' || area[amount - 1] != '\0' ||
    380                          area[malloc_usable_size( area ) - 1] != '\0' ||
     362                         area[malloc_size( area ) - 1] != '\0' ||
    381363                         ! malloc_zero_fill( area ) ) abort( "cmemalign/realloc with align/free corrupt storage1" );
    382364                area[0] = '\345'; area[amount - 2] = '\345';    // fill first/penultimate byte
     
    386368                        if ( area[0] != '\345' || area[s - 2] != '\345' ) abort( "cmemalign/realloc with align/free corrupt storage2" );
    387369                        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 ?
    389370                        //sout | i | area | endl;
    390371                        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 );
    392373                        } // if
    393374                        if ( area[s - 1] != '\0' || area[s - 1] != '\0' ||
    394                                  area[malloc_usable_size( area ) - 1] != '\0' ||
     375                                 area[malloc_size( area ) - 1] != '\0' ||
    395376                                 ! malloc_zero_fill( area ) ) abort( "cmemalign/realloc/free corrupt storage3" );
    396377                        area[s - 1] = '\345';                                           // fill last byte
  • tests/io2.cfa

    r07d867b r22f94a4  
    121121
    122122        [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
    124124        sout | t3;
    125125        sepSetTuple( sout, " " );
  • tests/list/.expect/dlist-insert-remove.txt

    r07d867b r22f94a4  
    146414640.7
    14651465-
     1466
     1467~~~~~~~~~~ End removal tests on Headed List: First ~~~~~~~~~~
     1468
     1469~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     1470Test 16-i.  Modifying Freds on MINE
     1471~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     1472==== fred by MINE before
     14731.7
     14742.7
     14753.7
     1476-
     14771.7
     1478-
     14793.7
     1480-
     14813.7
     14822.7
     14831.7
     1484-
     1485==== fred by YOURS before
     14861.7
     14872.7
     14883.7
     1489-
     14901.7
     1491-
     14923.7
     1493-
     14943.7
     14952.7
     14961.7
     1497-
     1498==== fred by MINE after
     14992.7
     15003.7
     1501-
     15022.7
     1503-
     15043.7
     1505-
     15063.7
     15072.7
     1508-
     1509==== fred by YOURS after
     15101.7
     15112.7
     15123.7
     1513-
     15141.7
     1515-
     15163.7
     1517-
     15183.7
     15192.7
     15201.7
     1521-
     1522==== fred by MINE after
     15231.7
     1524-
     15251.7
     1526-
     1527-
     1528-
     1529~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     1530Test 16-ii.  Modifying Freds on YOURS
     1531~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     1532==== fred by MINE before
     15331.7
     15342.7
     15353.7
     1536-
     15371.7
     1538-
     15393.7
     1540-
     15413.7
     15422.7
     15431.7
     1544-
     1545==== fred by YOURS before
     15461.7
     15472.7
     15483.7
     1549-
     15501.7
     1551-
     15523.7
     1553-
     15543.7
     15552.7
     15561.7
     1557-
     1558==== fred by MINE after
     15591.7
     15602.7
     15613.7
     1562-
     15631.7
     1564-
     15653.7
     1566-
     15673.7
     15682.7
     15691.7
     1570-
     1571==== fred by YOURS after
     15722.7
     15733.7
     1574-
     15752.7
     1576-
     15773.7
     1578-
     15793.7
     15802.7
     1581-
     1582==== fred by YOURS after
     15831.7
     1584-
     15851.7
     1586-
     1587-
     1588-
     1589~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     1590Test 16-iii.  Modifying Maries
     1591~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     1592==== mary before
     15931.7
     15942.7
     15953.7
     1596-
     15971.7
     1598-
     15993.7
     1600-
     16013.7
     16022.7
     16031.7
     1604-
     1605==== mary after
     16062.7
     16073.7
     1608-
     16092.7
     1610-
     16113.7
     1612-
     16133.7
     16142.7
     1615-
     1616==== mary after
     16171.7
     1618-
     16191.7
     1620-
     1621-
     1622-
     1623
     1624~~~~~~~~~~ End removal tests on Headed List: Last ~~~~~~~~~~
     1625
     1626~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     1627Test 17-i.  Modifying Freds on MINE
     1628~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     1629==== fred by MINE before
     16301.7
     16312.7
     16323.7
     1633-
     16341.7
     1635-
     16363.7
     1637-
     16383.7
     16392.7
     16401.7
     1641-
     1642==== fred by YOURS before
     16431.7
     16442.7
     16453.7
     1646-
     16471.7
     1648-
     16493.7
     1650-
     16513.7
     16522.7
     16531.7
     1654-
     1655==== fred by MINE after
     16561.7
     16572.7
     1658-
     16591.7
     1660-
     16612.7
     1662-
     16632.7
     16641.7
     1665-
     1666==== fred by YOURS after
     16671.7
     16682.7
     16693.7
     1670-
     16711.7
     1672-
     16733.7
     1674-
     16753.7
     16762.7
     16771.7
     1678-
     1679==== fred by MINE after
     16803.7
     1681-
     16823.7
     1683-
     1684-
     1685-
     1686~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     1687Test 17-ii.  Modifying Freds on YOURS
     1688~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     1689==== fred by MINE before
     16901.7
     16912.7
     16923.7
     1693-
     16941.7
     1695-
     16963.7
     1697-
     16983.7
     16992.7
     17001.7
     1701-
     1702==== fred by YOURS before
     17031.7
     17042.7
     17053.7
     1706-
     17071.7
     1708-
     17093.7
     1710-
     17113.7
     17122.7
     17131.7
     1714-
     1715==== fred by MINE after
     17161.7
     17172.7
     17183.7
     1719-
     17201.7
     1721-
     17223.7
     1723-
     17243.7
     17252.7
     17261.7
     1727-
     1728==== fred by YOURS after
     17291.7
     17302.7
     1731-
     17321.7
     1733-
     17342.7
     1735-
     17362.7
     17371.7
     1738-
     1739==== fred by YOURS after
     17403.7
     1741-
     17423.7
     1743-
     1744-
     1745-
     1746~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     1747Test 17-iii.  Modifying Maries
     1748~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     1749==== mary before
     17501.7
     17512.7
     17523.7
     1753-
     17541.7
     1755-
     17563.7
     1757-
     17583.7
     17592.7
     17601.7
     1761-
     1762==== mary after
     17631.7
     17642.7
     1765-
     17661.7
     1767-
     17682.7
     1769-
     17702.7
     17711.7
     1772-
     1773==== mary after
     17743.7
     1775-
     17763.7
     1777-
     1778-
     1779-
  • tests/list/dlist-insert-remove.cfa

    r07d867b r22f94a4  
    11871187////////////////////////////////////////////////////////////
    11881188//
     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
     1199void 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
     1235void 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
     1271void 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
     1298void 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
     1334void 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
     1370void 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//
    11891399// Section 5
    11901400//
     
    14221632        test__remove_of_sole__mary();
    14231633
     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
    14241672        return 0;
    14251673}
  • tests/manipulatorsInput.cfa

    r07d867b r22f94a4  
    77// Created On       : Sat Jun  8 17:58:54 2019
    88// Last Modified By : Peter A. Buhr
    9 // Last Modified On : Thu Jun 13 17:41:43 2019
    10 // Update Count     : 37
     9// Last Modified On : Wed Jul 15 15:56:03 2020
     10// Update Count     : 47
    1111//
    1212
     
    152152                sin | ignore( wdi( 8, ldc ) );                  sout | ldc;
    153153        }
     154#if defined( __SIZEOF_INT128__ )
     155        {
     156                int128 val;
     157                for ( 15 ) {
     158                        sin | val;
     159                        sout | val;
     160                }
     161        }
     162#endif // __SIZEOF_INT128__
    154163} // main
    155164
  • tests/manipulatorsOutput3.cfa

    r07d867b r22f94a4  
    11#include <fstream.hfa>
     2
    23int 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  
    6969                        else :                                          text = "FAILED with code %d" % retcode
    7070
    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]))
    7272                return text
    73 
    74         @staticmethod
    75         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  
    387387                while True:
    388388                        yield i.next(max(expire - time.time(), 0))
     389
     390def 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  
    3838        } // for
    3939        sout | nl;
    40         for ( i; 0 ~ size ) {           // C version
     40        for ( i; 0 ~ size ) {           // C version, returns void*
    4141                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 );
    4343                sout | key | ':' | *v | ", ";
    4444        } // for
  • tests/test.py

    r07d867b r22f94a4  
    361361
    362362                # 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 ))
    394395                sys.exit( failed )
  • tests/time.cfa

    r07d867b r22f94a4  
    1010// Created On       : Tue Mar 27 17:24:56 2018
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Jan  5 18:27:37 2020
    13 // Update Count     : 34
     12// Last Modified On : Thu Jun 18 18:14:49 2020
     13// Update Count     : 37
    1414//
    1515
     
    2020        Duration d1 = 3`h, d2 = 2`s, d3 = 3.375`s, d4 = 12`s, d5 = 1`s + 10_000`ns;
    2121        sout | d1 | d2 | d3 | d4 | d5;
     22        sout | d1`dd | d2`dm | d3`ds | d4`dms | d5`dus;
    2223        d1 = 0;
    2324        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) \
     1AM_T_CFA = $(am__t_CFA_@AM_T@)
     2am__t_CFA_ =
     3am__t_CFA_0 =
     4am__t_CFA_1 = /usr/bin/time --quiet -f "$@ %E" # trailling space is necessary
     5
     6
     7CFACOMPILE = $(AM_T_CFA)$(CFACC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CFAFLAGS) $(CFAFLAGS) $(AM_CFLAGS) $(CFLAGS)
     8LTCFACOMPILE = $(AM_T_CFA)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
    39        $(LIBTOOLFLAGS) --mode=compile $(CFACC) $(DEFS) \
    410        $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CFAFLAGS) $(AM_CFLAGS) $(CFAFLAGS) $(CFLAGS)
  • tools/build/push2dist.sh

    r07d867b r22f94a4  
    22
    33hash="$1"
     4bwlim="$2"
    45valid=$(distcc -j 2> /dev/null)
    56# if test "${valid}" != 0
     
    2425function push() {
    2526        ssh ${host} "mkdir -p ~/.cfadistcc/${hash}/"
    26         rsync -a ${dV} ${files} ${host}:~/.cfadistcc/${hash}/.
     27        rsync --bwlimit=${bwlim} -a ${dV} ${files} ${host}:~/.cfadistcc/${hash}/.
    2728}
    2829
  • tools/gdb/utils-gdb.py

    r07d867b r22f94a4  
    5959                                         thread_ptr = gdb.lookup_type('struct $thread').pointer(),
    6060                                                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'))
    6262
    6363def get_addr(addr):
Note: See TracChangeset for help on using the changeset viewer.