Changeset af7acb9


Ignore:
Timestamp:
May 8, 2020, 11:53:29 AM (17 months ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
arm-eh, jacob/cs343-translation, master, new-ast, new-ast-unique-expr
Children:
04bc1c0
Parents:
6ec07e5 (diff), e68d092 (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' of plg.uwaterloo.ca:software/cfa/cfa-cc

Files:
3 added
1 deleted
18 edited

Legend:

Unmodified
Added
Removed
  • benchmark/io/readv.cfa

    r6ec07e5 raf7acb9  
    1616#include <thread.hfa>
    1717#include <time.hfa>
    18 
    19 #if !defined(HAVE_LINUX_IO_URING_H)
    20 #warning no io uring
    21 #endif
    2218
    2319extern bool traceHeapOn();
     
    5349        while(__atomic_load_n(&run, __ATOMIC_RELAXED)) {
    5450                int r = cfa_preadv2(fd, &iov, 1, 0, 0);
    55                 if(r < 0) abort(strerror(-r));
     51                if(r < 0) abort("%s\n", strerror(-r));
    5652
    5753                __atomic_fetch_add( &count, 1, __ATOMIC_SEQ_CST );
     
    6359        unsigned long int nthreads = 2;
    6460        unsigned long int nprocs   = 1;
    65 
    66         printf("Setting local\n");
    67         setlocale(LC_NUMERIC, "");
     61        int flags = 0;
    6862
    6963        arg_loop:
    7064        for(;;) {
    7165                static struct option options[] = {
    72                         {"duration",  required_argument, 0, 'd'},
    73                         {"nthreads",  required_argument, 0, 't'},
    74                         {"nprocs",    required_argument, 0, 'p'},
    75                         {"bufsize",   required_argument, 0, 'b'},
     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'},
    7671                        {0, 0, 0, 0}
    7772                };
    7873
    7974                int idx = 0;
    80                 int opt = getopt_long(argc, argv, "d:t:p:b:", options, &idx);
     75                int opt = getopt_long(argc, argv, "d:t:p:b:u", options, &idx);
    8176
    8277                const char * arg = optarg ? optarg : "";
     
    115110                                }
    116111                                break;
     112                        case 'u':
     113                                flags |= CFA_CLUSTER_IO_POLLER_USER_THREAD;
     114                                break;
    117115                        // Other cases
    118116                        default: /* ? */
     
    135133        }
    136134
    137         printf("Running %lu threads over %lu processors for %lf seconds\n", nthreads, nprocs, duration);
     135        printf("Running %lu threads, reading %lu bytes each, over %lu processors for %lf seconds\n", nthreads, buflen, nprocs, duration);
    138136
    139137        {
    140138                Time start, end;
    141                 cluster cl = { "IO Cluster" };
     139                cluster cl = { "IO Cluster", flags };
    142140                the_cluster = &cl;
    143141                #if !defined(__CFA_NO_STATISTICS__)
     
    161159                        }
    162160                }
    163                 printf("Took %ld ms\n", (end - start)`ms);
    164                 printf("Total reads:      %'zu\n", count);
    165                 printf("Reads per second: %'lf\n", ((double)count) / (end - start)`s);
     161                printf("Took %'ld ms\n", (end - start)`ms);
     162                printf("Total reads      : %'15zu\n", count);
     163                printf("Reads per second : %'18.2lf\n", ((double)count) / (end - start)`s);
     164                printf("Total read size  : %'15zu\n", buflen * count);
     165                printf("Bytes per second : %'18.2lf\n", ((double)count * buflen) / (end - start)`s);
    166166        }
    167167
  • doc/bibliography/pl.bib

    r6ec07e5 raf7acb9  
    47594759    contributer = {pabuhr@plg},
    47604760    author      = {Gregory R. Andrews},
    4761     title       = {A Method for Solving Synronization Problems},
     4761    title       = {A Method for Solving Synchronization Problems},
    47624762    journal     = scp,
    47634763    volume      = 13,
  • libcfa/prelude/defines.hfa.in

    r6ec07e5 raf7acb9  
    1919#undef HAVE_PWRITEV2
    2020
    21 // #define __CFA_IO_POLLING_USER__
    22 // #define __CFA_IO_POLLING_KERNEL__
     21#undef __CFA_NO_STATISTICS__
  • libcfa/src/concurrency/io.cfa

    r6ec07e5 raf7acb9  
    2020
    2121#if !defined(HAVE_LINUX_IO_URING_H)
    22         void __kernel_io_startup( cluster &, bool ) {
     22        void __kernel_io_startup( cluster &, int, bool ) {
    2323                // Nothing to do without io_uring
    2424        }
     
    8686        #endif
    8787
    88         #if defined(__CFA_IO_POLLING_USER__)
    89                 void ?{}( __io_poller_fast & this, struct cluster & cltr ) {
    90                         this.ring = &cltr.io;
    91                         (this.thrd){ "Fast I/O Poller", cltr };
    92                 }
    93                 void ^?{}( __io_poller_fast & mutex this );
    94         void main( __io_poller_fast & this );
    95         static inline $thread * get_thread( __io_poller_fast & this ) { return &this.thrd; }
    96                 void ^?{}( __io_poller_fast & mutex this ) {}
    97         #endif
     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        };
    98199
    99200//=============================================================================================
    100201// I/O Startup / Shutdown logic
    101202//=============================================================================================
    102         void __kernel_io_startup( cluster & this, bool main_cluster ) {
     203        void __kernel_io_startup( cluster & this, int io_flags, bool main_cluster ) {
     204                this.io = malloc();
     205
    103206                // Step 1 : call to setup
    104207                struct io_uring_params params;
     
    113216
    114217                // Step 2 : mmap result
    115                 memset(&this.io, 0, sizeof(struct io_ring));
    116                 struct io_uring_sq & sq = this.io.submit_q;
    117                 struct io_uring_cq & cq = this.io.completion_q;
     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;
    118221
    119222                // calculate the right ring size
     
    193296
    194297                // Update the global ring info
    195                 this.io.flags = params.flags;
    196                 this.io.fd    = fd;
    197                 this.io.done  = false;
    198                 (this.io.submit){ min(*sq.num, *cq.num) };
     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) };
    199303
    200304                // Initialize statistics
    201305                #if !defined(__CFA_NO_STATISTICS__)
    202                         this.io.submit_q.stats.submit_avg.val = 0;
    203                         this.io.submit_q.stats.submit_avg.cnt = 0;
    204                         this.io.completion_q.stats.completed_avg.val = 0;
    205                         this.io.completion_q.stats.completed_avg.cnt = 0;
     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;
    206312                #endif
    207313
     
    212318
    213319        void __kernel_io_finish_start( cluster & this ) {
    214                 #if defined(__CFA_IO_POLLING_USER__)
     320                if( this.io->cltr_flags & CFA_CLUSTER_IO_POLLER_USER_THREAD ) {
    215321                        __cfadbg_print_safe(io_core, "Kernel I/O : Creating fast poller for cluter %p\n", &this);
    216                         (this.io.poller.fast){ this };
    217                         __thrd_start( this.io.poller.fast, main );
    218                 #endif
     322                        (this.io->poller.fast){ this };
     323                        __thrd_start( this.io->poller.fast, main );
     324                }
    219325
    220326                // Create the poller thread
    221327                __cfadbg_print_safe(io_core, "Kernel I/O : Creating slow poller for cluter %p\n", &this);
    222                 this.io.poller.slow.stack = __create_pthread( &this.io.poller.slow.kthrd, __io_poller_slow, &this );
     328                this.io->poller.slow.stack = __create_pthread( &this.io->poller.slow.kthrd, __io_poller_slow, &this );
    223329        }
    224330
     
    226332                __cfadbg_print_safe(io_core, "Kernel I/O : Stopping pollers for cluster\n", &this);
    227333                // Notify the poller thread of the shutdown
    228                 __atomic_store_n(&this.io.done, true, __ATOMIC_SEQ_CST);
     334                __atomic_store_n(&this.io->done, true, __ATOMIC_SEQ_CST);
    229335
    230336                // Stop the IO Poller
    231337                sigval val = { 1 };
    232                 pthread_sigqueue( this.io.poller.slow.kthrd, SIGUSR1, val );
    233                 #if defined(__CFA_IO_POLLING_USER__)
    234                         post( this.io.poller.sem );
    235                 #endif
     338                pthread_sigqueue( this.io->poller.slow.kthrd, SIGUSR1, val );
     339                post( this.io->poller.sem );
    236340
    237341                // Wait for the poller thread to finish
    238                 pthread_join( this.io.poller.slow.kthrd, 0p );
    239                 free( this.io.poller.slow.stack );
     342                pthread_join( this.io->poller.slow.kthrd, 0p );
     343                free( this.io->poller.slow.stack );
    240344
    241345                __cfadbg_print_safe(io_core, "Kernel I/O : Slow poller stopped for cluster\n", &this);
    242346
    243                 #if defined(__CFA_IO_POLLING_USER__)
     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
    244380                        // unpark the fast io_poller
    245                         unpark( &this.io.poller.fast.thrd __cfaabi_dbg_ctx2 );
    246 
    247                         ^(this.io.poller.fast){};
     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){};
    248393
    249394                        __cfadbg_print_safe(io_core, "Kernel I/O : Fast poller stopped for cluster\n", &this);
    250                 #endif
     395                }
    251396        }
    252397
     
    259404                #if !defined(__CFA_NO_STATISTICS__)
    260405                        if(this.print_stats) {
    261                                 __cfaabi_bits_print_safe( STDERR_FILENO,
    262                                         "----- I/O uRing Stats -----\n"
    263                                         "- total submit calls  : %llu\n"
    264                                         "- avg submit          : %lf\n"
    265                                         "- total wait calls    : %llu\n"
    266                                         "- avg completion/wait : %lf\n",
    267                                         this.io.submit_q.stats.submit_avg.cnt,
    268                                         ((double)this.io.submit_q.stats.submit_avg.val) / this.io.submit_q.stats.submit_avg.cnt,
    269                                         this.io.completion_q.stats.completed_avg.cnt,
    270                                         ((double)this.io.completion_q.stats.completed_avg.val) / this.io.completion_q.stats.completed_avg.cnt
    271                                 );
     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                                }
    272422                        }
    273423                #endif
    274424
    275425                // Shutdown the io rings
    276                 struct io_uring_sq & sq = this.io.submit_q;
    277                 struct io_uring_cq & cq = this.io.completion_q;
     426                struct __submition_data  & sq = this.io->submit_q;
     427                struct __completion_data & cq = this.io->completion_q;
    278428
    279429                // unmap the submit queue entries
     
    289439
    290440                // close the file descriptor
    291                 close(this.io.fd);
     441                close(this.io->fd);
     442
     443                free( this.io );
    292444        }
    293445
     
    302454        // Process a single completion message from the io_uring
    303455        // This is NOT thread-safe
    304         static int __drain_io( struct io_ring & ring, sigset_t * mask, int waitcnt, bool in_kernel ) {
     456        static int __drain_io( struct __io_data & ring, sigset_t * mask, int waitcnt, bool in_kernel ) {
    305457                int ret = syscall( __NR_io_uring_enter, ring.fd, 0, waitcnt, IORING_ENTER_GETEVENTS, mask, _NSIG / 8);
    306458                if( ret < 0 ) {
     
    320472                // Nothing was new return 0
    321473                if (head == tail) {
    322                         #if !defined(__CFA_NO_STATISTICS__)
    323                                 ring.completion_q.stats.completed_avg.cnt += 1;
    324                         #endif
    325474                        return 0;
    326475                }
     
    348497                __atomic_fetch_add( ring.completion_q.head, count, __ATOMIC_RELAXED );
    349498
    350                 // Update statistics
    351                 #if !defined(__CFA_NO_STATISTICS__)
    352                         ring.completion_q.stats.completed_avg.val += count;
    353                         ring.completion_q.stats.completed_avg.cnt += 1;
    354                 #endif
    355 
    356499                return count;
    357500        }
     
    359502        static void * __io_poller_slow( void * arg ) {
    360503                cluster * cltr = (cluster *)arg;
    361                 struct io_ring & ring = cltr->io;
     504                struct __io_data & ring = *cltr->io;
    362505
    363506                sigset_t mask;
     
    372515                verify( (*ring.completion_q.head) == (*ring.completion_q.tail) );
    373516
    374                 while(!__atomic_load_n(&ring.done, __ATOMIC_SEQ_CST)) {
    375                         #if defined(__CFA_IO_POLLING_USER__)
    376 
     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)) {
    377521                                // In the user-thread approach drain and if anything was drained,
    378522                                // batton pass to the user-thread
    379523                                int count = __drain_io( ring, &mask, 1, true );
     524
     525                                // 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
    380531                                if(count > 0) {
    381532                                        __cfadbg_print_safe(io_core, "Kernel I/O : Moving to ring %p to fast poller\n", &ring);
     
    383534                                        wait( ring.poller.sem );
    384535                                }
    385 
    386                         #else
    387 
     536                        }
     537                }
     538                else {
     539                        while(!__atomic_load_n(&ring.done, __ATOMIC_SEQ_CST)) {
    388540                                //In the naive approach, just poll the io completion queue directly
    389                                 __drain_io( ring, &mask, 1, true );
    390 
     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;
    391577                        #endif
    392                 }
    393 
    394                 return 0p;
    395         }
    396 
    397         #if defined(__CFA_IO_POLLING_USER__)
    398                 void main( __io_poller_fast & this ) {
    399                         // Start parked
    400                         park( __cfaabi_dbg_ctx );
    401 
    402                         // Then loop until we need to start
    403                         while(!__atomic_load_n(&this.ring->done, __ATOMIC_SEQ_CST)) {
    404                                 // Drain the io
    405                                 if(0 > __drain_io( *this.ring, 0p, 0, false )) {
    406                                         // If we got something, just yield and check again
    407                                         yield();
    408                                 }
    409                                 else {
    410                                         // We didn't get anything baton pass to the slow poller
    411                                         __cfadbg_print_safe(io_core, "Kernel I/O : Moving to ring %p to slow poller\n", &this.ring);
    412                                         post( this.ring->poller.sem );
    413                                         park( __cfaabi_dbg_ctx );
    414                                 }
     578
     579                        this.waiting = true;
     580                        if(reset < 5) {
     581                                // If we got something, just yield and check again
     582                                yield();
    415583                        }
    416                 }
    417         #endif
     584                        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 );
     589                                reset = 0;
     590                        }
     591                }
     592
     593                __cfadbg_print_safe(io_core, "Kernel I/O : Fast poller for ring %p stopping\n", &this.ring);
     594        }
    418595
    419596//=============================================================================================
     
    445622//
    446623
    447         static inline [* struct io_uring_sqe, uint32_t] __submit_alloc( struct io_ring & ring ) {
     624        static inline [* struct io_uring_sqe, uint32_t] __submit_alloc( struct __io_data & ring ) {
    448625                // Wait for a spot to be available
    449                 P(ring.submit);
     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
    450630
    451631                // Allocate the sqe
     
    463643        }
    464644
    465         static inline void __submit( struct io_ring & ring, uint32_t idx ) {
     645        static inline void __submit( struct __io_data & ring, uint32_t idx ) {
    466646                // get mutual exclusion
    467647                lock(ring.submit_q.lock __cfaabi_dbg_ctx2);
     
    524704
    525705        #define __submit_prelude \
    526                 struct io_ring & ring = active_cluster()->io; \
     706                struct __io_data & ring = *active_cluster()->io; \
    527707                struct io_uring_sqe * sqe; \
    528708                uint32_t idx; \
  • libcfa/src/concurrency/kernel.cfa

    r6ec07e5 raf7acb9  
    256256}
    257257
    258 void ?{}(cluster & this, const char name[], Duration preemption_rate) with( this ) {
     258void ?{}(cluster & this, const char name[], Duration preemption_rate, int io_flags) with( this ) {
    259259        this.name = name;
    260260        this.preemption_rate = preemption_rate;
     
    270270        threads{ __get };
    271271
    272         __kernel_io_startup( this, &this == mainCluster );
     272        __kernel_io_startup( this, io_flags, &this == mainCluster );
    273273
    274274        doregister(this);
     
    993993void ^?{}(semaphore & this) {}
    994994
    995 void P(semaphore & this) with( this ){
     995bool P(semaphore & this) with( this ){
    996996        lock( lock __cfaabi_dbg_ctx2 );
    997997        count -= 1;
     
    10031003                unlock( lock );
    10041004                park( __cfaabi_dbg_ctx );
     1005                return true;
    10051006        }
    10061007        else {
    10071008            unlock( lock );
     1009            return false;
    10081010        }
    10091011}
  • libcfa/src/concurrency/kernel.hfa

    r6ec07e5 raf7acb9  
    3838void  ?{}(semaphore & this, int count = 1);
    3939void ^?{}(semaphore & this);
    40 void   P (semaphore & this);
     40bool   P (semaphore & this);
    4141bool   V (semaphore & this);
    4242bool   V (semaphore & this, unsigned count);
     
    114114//-----------------------------------------------------------------------------
    115115// I/O
    116 #if defined(HAVE_LINUX_IO_URING_H)
    117 struct io_uring_sq {
    118         // Head and tail of the ring (associated with array)
    119         volatile uint32_t * head;
    120         volatile uint32_t * tail;
     116struct __io_data;
    121117
    122         // The actual kernel ring which uses head/tail
    123         // indexes into the sqes arrays
    124         uint32_t * array;
    125 
    126         // number of entries and mask to go with it
    127         const uint32_t * num;
    128         const uint32_t * mask;
    129 
    130         // Submission flags (Not sure what for)
    131         uint32_t * flags;
    132 
    133         // number of sqes not submitted (whatever that means)
    134         uint32_t * dropped;
    135 
    136         // Like head/tail but not seen by the kernel
    137         volatile uint32_t alloc;
    138         volatile uint32_t ready;
    139 
    140         __spinlock_t lock;
    141 
    142         // A buffer of sqes (not the actual ring)
    143         struct io_uring_sqe * sqes;
    144 
    145         // The location and size of the mmaped area
    146         void * ring_ptr;
    147         size_t ring_sz;
    148 
    149         // Statistics
    150         #if !defined(__CFA_NO_STATISTICS__)
    151                 struct {
    152                         struct {
    153                                 unsigned long long int val;
    154                                 unsigned long long int cnt;
    155                         } submit_avg;
    156                 } stats;
    157         #endif
    158 };
    159 
    160 struct io_uring_cq {
    161         // Head and tail of the ring
    162         volatile uint32_t * head;
    163         volatile uint32_t * tail;
    164 
    165         // number of entries and mask to go with it
    166         const uint32_t * mask;
    167         const uint32_t * num;
    168 
    169         // number of cqes not submitted (whatever that means)
    170         uint32_t * overflow;
    171 
    172         // the kernel ring
    173         struct io_uring_cqe * cqes;
    174 
    175         // The location and size of the mmaped area
    176         void * ring_ptr;
    177         size_t ring_sz;
    178 
    179         // Statistics
    180         #if !defined(__CFA_NO_STATISTICS__)
    181                 struct {
    182                         struct {
    183                                 unsigned long long int val;
    184                                 unsigned long long int cnt;
    185                         } completed_avg;
    186                 } stats;
    187         #endif
    188 };
    189 
    190 #if defined(__CFA_IO_POLLING_USER__)
    191         struct __io_poller_fast {
    192                 struct io_ring * ring;
    193                 $thread thrd;
    194         };
    195 #endif
    196 
    197 struct io_ring {
    198         struct io_uring_sq submit_q;
    199         struct io_uring_cq completion_q;
    200         uint32_t flags;
    201         int fd;
    202         semaphore submit;
    203         volatile bool done;
    204         struct {
    205                 struct {
    206                         void * stack;
    207                         pthread_t kthrd;
    208                 } slow;
    209                 #if defined(__CFA_IO_POLLING_USER__)
    210                         __io_poller_fast fast;
    211                         __bin_sem_t sem;
    212                 #endif
    213         } poller;
    214 };
    215 #endif
     118#define CFA_CLUSTER_IO_POLLER_USER_THREAD 1 << 0
     119// #define CFA_CLUSTER_IO_POLLER_KERNEL_SIDE 1 << 1
    216120
    217121//-----------------------------------------------------------------------------
     
    247151        } node;
    248152
    249         #if defined(HAVE_LINUX_IO_URING_H)
    250                 struct io_ring io;
    251         #endif
     153        struct __io_data * io;
    252154
    253155        #if !defined(__CFA_NO_STATISTICS__)
     
    257159extern Duration default_preemption();
    258160
    259 void ?{} (cluster & this, const char name[], Duration preemption_rate);
     161void ?{} (cluster & this, const char name[], Duration preemption_rate, int flags);
    260162void ^?{}(cluster & this);
    261163
    262 static inline void ?{} (cluster & this)                           { this{"Anonymous Cluster", default_preemption()}; }
    263 static inline void ?{} (cluster & this, Duration preemption_rate) { this{"Anonymous Cluster", preemption_rate}; }
    264 static inline void ?{} (cluster & this, const char name[])        { this{name, default_preemption()}; }
     164static inline void ?{} (cluster & this)                                      { this{"Anonymous Cluster", default_preemption(), 0}; }
     165static inline void ?{} (cluster & this, Duration preemption_rate)            { this{"Anonymous Cluster", preemption_rate, 0}; }
     166static inline void ?{} (cluster & this, const char name[])                   { this{name, default_preemption(), 0}; }
     167static inline void ?{} (cluster & this, int flags)                           { this{"Anonymous Cluster", default_preemption(), flags}; }
     168static inline void ?{} (cluster & this, Duration preemption_rate, int flags) { this{"Anonymous Cluster", preemption_rate, flags}; }
     169static inline void ?{} (cluster & this, const char name[], int flags)        { this{name, default_preemption(), flags}; }
    265170
    266171static inline [cluster *&, cluster *& ] __get( cluster & this ) __attribute__((const)) { return this.node.[next, prev]; }
  • libcfa/src/concurrency/kernel_private.hfa

    r6ec07e5 raf7acb9  
    5959extern volatile thread_local __cfa_kernel_preemption_state_t preemption_state __attribute__ ((tls_model ( "initial-exec" )));
    6060
     61extern cluster * mainCluster;
     62
    6163//-----------------------------------------------------------------------------
    6264// Threads
     
    7577//-----------------------------------------------------------------------------
    7678// I/O
    77 void __kernel_io_startup     ( cluster &, bool );
     79void __kernel_io_startup     ( cluster &, int, bool );
    7880void __kernel_io_finish_start( cluster & );
    7981void __kernel_io_prepare_stop( cluster & );
  • libcfa/src/heap.cfa

    r6ec07e5 raf7acb9  
    1010// Created On       : Tue Dec 19 21:58:35 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Apr 18 17:43:15 2020
    13 // Update Count     : 718
     12// Last Modified On : Wed May  6 17:29:26 2020
     13// Update Count     : 727
    1414//
    1515
     
    1919#include <errno.h>                                                                              // errno
    2020#include <string.h>                                                                             // memset, memcpy
     21#include <limits.h>                                                                             // ULONG_MAX
    2122extern "C" {
    2223#include <sys/mman.h>                                                                   // mmap, munmap
    2324} // extern "C"
    2425
    25 // #comment TD : Many of these should be merged into math I believe
    2626#include "bits/align.hfa"                                                               // libPow2
    2727#include "bits/defs.hfa"                                                                // likely, unlikely
     
    3030//#include "stdlib.hfa"                                                                 // bsearchl
    3131#include "malloc.h"
     32#include "bitmanip.hfa"                                                                 // ceiling
    3233
    3334#define MIN(x, y) (y > x ? x : y)
     
    8182};
    8283
     84size_t default_heap_expansion() __attribute__(( weak )) {
     85        return __CFA_DEFAULT_HEAP_EXPANSION__;
     86} // default_heap_expansion
     87
    8388size_t default_mmap_start() __attribute__(( weak )) {
    8489        return __CFA_DEFAULT_MMAP_START__;
    8590} // default_mmap_start
    86 
    87 size_t default_heap_expansion() __attribute__(( weak )) {
    88         return __CFA_DEFAULT_HEAP_EXPANSION__;
    89 } // default_heap_expansion
    9091
    9192
     
    360361
    361362
    362 static inline bool setHeapExpand( size_t value ) {
    363   if ( heapExpand < pageSize ) return true;
    364         heapExpand = value;
    365         return false;
    366 } // setHeapExpand
    367 
    368 
    369363// thunk problem
    370364size_t Bsearchl( unsigned int key, const unsigned int * vals, size_t dim ) {
     
    383377
    384378static inline bool setMmapStart( size_t value ) {               // true => mmapped, false => sbrk
    385   if ( value < pageSize || bucketSizes[NoBucketSizes - 1] < value ) return true;
     379  if ( value < pageSize || bucketSizes[NoBucketSizes - 1] < value ) return false;
    386380        mmapStart = value;                                                                      // set global
    387381
     
    390384        assert( maxBucketsUsed < NoBucketSizes );                       // subscript failure ?
    391385        assert( mmapStart <= bucketSizes[maxBucketsUsed] ); // search failure ?
    392         return false;
     386        return true;
    393387} // setMmapStart
    394388
     
    449443
    450444        #ifdef __CFA_DEBUG__
    451         checkHeader( addr < heapBegin || header < (HeapManager.Storage.Header *)heapBegin, name, addr ); // bad low address ?
     445        checkHeader( addr < heapBegin, name, addr );            // bad low address ?
    452446        #endif // __CFA_DEBUG__
    453447
     
    508502        // along with the block and is a multiple of the alignment size.
    509503
    510   if ( unlikely( size > ~0ul - sizeof(HeapManager.Storage) ) ) return 0p;
     504  if ( unlikely( size > ULONG_MAX - sizeof(HeapManager.Storage) ) ) return 0p;
    511505        size_t tsize = size + sizeof(HeapManager.Storage);
    512506        if ( likely( tsize < mmapStart ) ) {                            // small size => sbrk
     
    560554                block->header.kind.real.home = freeElem;                // pointer back to free list of apropriate size
    561555        } else {                                                                                        // large size => mmap
    562   if ( unlikely( size > ~0ul - pageSize ) ) return 0p;
     556  if ( unlikely( size > ULONG_MAX - pageSize ) ) return 0p;
    563557                tsize = libCeiling( tsize, pageSize );                  // must be multiple of page size
    564558                #ifdef __STATISTICS__
     
    702696        #endif // FASTLOOKUP
    703697
    704         if ( setMmapStart( default_mmap_start() ) ) {
     698        if ( ! setMmapStart( default_mmap_start() ) ) {
    705699                abort( "HeapManager : internal error, mmap start initialization failure." );
    706700        } // if
     
    708702
    709703        char * end = (char *)sbrk( 0 );
    710         sbrk( (char *)libCeiling( (long unsigned int)end, libAlign() ) - end ); // move start of heap to multiple of alignment
    711         heapBegin = heapEnd = sbrk( 0 );                                        // get new start point
     704        heapBegin = heapEnd = sbrk( (char *)libCeiling( (long unsigned int)end, libAlign() ) - end ); // move start of heap to multiple of alignment
    712705} // HeapManager
    713706
     
    735728        //assert( heapManager.heapBegin != 0 );
    736729        //heapManager{};
    737         if ( heapManager.heapBegin == 0p ) heapManager{};
     730        if ( heapManager.heapBegin == 0p ) heapManager{};       // sanity check
    738731} // memory_startup
    739732
     
    863856                #endif // __STATISTICS__
    864857
    865                 size_t size = dim * elemSize;
    866                 char * addr = (char *)mallocNoStats( size );
    867           if ( unlikely( addr == 0p ) ) return 0p;
    868 
    869                 HeapManager.Storage.Header * header;
    870                 HeapManager.FreeHeader * freeElem;
    871                 size_t bsize, alignment;
    872                 headers( "aalloc", addr, header, freeElem, bsize, alignment );
    873 
    874                 header->kind.real.blockSize |= 2;                               // mark as zero filled
    875                 return addr;
     858                return mallocNoStats( dim * elemSize );
    876859        } // aalloc
    877860
     
    914897       
    915898                // change size, DO NOT preserve STICKY PROPERTIES.
     899                free( oaddr );
    916900                void * naddr = mallocNoStats( size );                   // create new area
    917                 free( oaddr );
    918901                return naddr;
    919902        } // resize
     
    988971                #endif // __STATISTICS__
    989972
    990                 size_t size = dim * elemSize;
    991                 char * addr = (char *)memalignNoStats( alignment, size );
    992           if ( unlikely( addr == 0p ) ) return 0p;
    993                 HeapManager.Storage.Header * header;
    994                 HeapManager.FreeHeader * freeElem;
    995                 size_t bsize;
    996                 headers( "amemalign", addr, header, freeElem, bsize, alignment );
    997 
    998                 header->kind.real.blockSize |= 2;                               // mark as zero filled
    999                 return addr;
     973                return memalignNoStats( alignment, dim * elemSize );
    1000974        } // amemalign
    1001975
     
    10431017
    10441018        // Frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc()
    1045         // or realloc().  Otherwise, or if free(ptr) has already been called before, undefined behavior occurs. If ptr is
     1019        // or realloc().  Otherwise, or if free(ptr) has already been called before, undefined behaviour occurs. If ptr is
    10461020        // 0p, no operation is performed.
    10471021        void free( void * addr ) {
     
    11701144
    11711145
    1172         // Adjusts parameters that control the behavior of the memory-allocation functions (see malloc). The param argument
     1146        // Adjusts parameters that control the behaviour of the memory-allocation functions (see malloc). The param argument
    11731147        // specifies the parameter to be modified, and value specifies the new value for that parameter.
    11741148        int mallopt( int option, int value ) {
    11751149                choose( option ) {
    11761150                  case M_TOP_PAD:
    1177                         if ( setHeapExpand( value ) ) return 1;
     1151                        heapExpand = ceiling( value, pageSize ); return 1;
    11781152                  case M_MMAP_THRESHOLD:
    11791153                        if ( setMmapStart( value ) ) return 1;
     1154                        break;
    11801155                } // switch
    11811156                return 0;                                                                               // error, unsupported
  • libcfa/src/iostream.cfa

    r6ec07e5 raf7acb9  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Apr 30 10:50:31 2020
    13 // Update Count     : 1001
     12// Last Modified On : Sat May  2 18:30:25 2020
     13// Update Count     : 1017
    1414//
    1515
     
    583583                                        if ( fmt.flags.pc && fmt.pc > 64 ) fmt.pc -= 64; else { fmt.flags.pc = false; fmt.pc = 0; } \
    584584                                        if ( fmt.flags.left ) { \
    585                                                 fmt2.wd = fmt.wd; \
    586                                                 if ( fmt2.wd <= 64 ) { \
    587                                                         fmt2.wd = 64; \
    588                                                 } else { \
    589                                                         if ( fmt.pc > 0 ) { \
    590                                                                 fmt2.wd -= fmt.pc; \
    591                                                         } else { \
    592                                                                 fmt2.wd = fmt.wd - high1( msig ); \
    593                                                         } /* if */ \
    594                                                         if ( ! fmt.flags.nobsdp ) fmt2.wd -= 2; \
    595                                                         if ( fmt2.wd < 0 ) fmt2.wd = 0; \
    596                                                         fmt2.flags.left = true; \
    597                                                         fmt.wd = 0; \
    598                                                 } /* if */ \
    599                                                 printf( "left %d %d %x\n", f.wd, f.pc, f.all ); \
    600                                                 printf( "left %d %d %x\n", fmt.wd, fmt.pc, fmt.all ); \
     585                                                fmt.flags.left = false; \
     586                                                fmt.wd = 0; \
     587                                                /* printf( "L %llo %llo %llo %d %d '%c' %x\n", msig, lsig, fmt.val, fmt.wd, fmt.pc, fmt.base, fmt.all ); */ \
     588                                                fmt2.flags.left = true; \
     589                                                int msigd = high1( msig ); \
     590                                                fmt2.wd = f.wd - (fmt.pc > msigd ? fmt.pc : msigd); \
     591                                                if ( ! fmt.flags.nobsdp ) fmt2.wd -= 2; /* compensate for 0b base specifier */ \
     592                                                if ( (int)fmt2.wd < 64 ) fmt2.wd = 64; /* cast deals with negative value */ \
     593                                                fmt2.flags.pc = true; fmt2.pc = 64; \
    601594                                        } else { \
    602595                                                if ( fmt.wd > 64 ) fmt.wd -= 64; \
    603                                                 /* if ( ! fmt.flags.nobsdp && fmt.pc < fmt.wd ) fmt.wd -= 1; */ \
     596                                                else fmt.wd = 1; \
     597                                                /* printf( "R %llo %llo %llo %d %d '%c' %x\n", msig, lsig, fmt.val, fmt.wd, fmt.pc, fmt.base, fmt.all ); */ \
    604598                                                fmt2.wd = 64; \
    605                                                 /* printf( "R %llo %llo %llo %llo %d %d '%c' %x\n", msig, lsig, fmt.val, fmt2.val, fmt.wd, fmt.pc, fmt.base, fmt.all ); */ \
    606599                                        } /* if */ \
    607                                         /* printf( "\nC %llo %d %d '%c' %x\n", fmt2.val, fmt2.wd, fmt2.pc, fmt2.base, fmt2.all ); */ \
     600                                        /* printf( "C %llo %d %d '%c' %x\n", fmt2.val, fmt2.wd, fmt2.pc, fmt2.base, fmt2.all ); */ \
    608601                                        (ostype &)(os | fmt | "" | fmt2); \
    609602                                } else if ( f.base == 'o' ) { \
     
    614607                                                fmt.flags.left = false; \
    615608                                                fmt.wd = 0; \
    616                                                 /* if ( fmt2.val > 1 && fmt.flags.pc && fmt.pc > 0 ) fmt.pc -= 1; */ \
    617609                                                /* printf( "L %llo %llo %llo %d %d '%c' %x %llo %d %d '%c' %x\n", msig, lsig, fmt.val, fmt.wd, fmt.pc, fmt.base, fmt.all, fmt2.val, fmt2.wd, fmt2.pc, fmt2.base, fmt2.all ); */ \
    618610                                                (ostype &)(os | fmt | "" | fmt2); \
    619611                                                sepOff( os ); \
    620612                                                fmt2.flags.left = true; \
    621                                                 int msigd = ceiling( high1( fmt.val ), 3 ) + 1; \
    622                                                 fmt2.wd = f.wd - (fmt.pc > msigd ? fmt.pc : msigd) - 1; \
     613                                                int msigd = ceiling( high1( fmt.val ), 3 ); \
     614                                                fmt2.wd = f.wd - (fmt.pc > msigd ? fmt.pc : msigd); \
     615                                                if ( ! fmt.flags.nobsdp ) fmt2.wd -= 1; /* compensate for 0 base specifier */ \
    623616                                                if ( (int)fmt2.wd < 21 ) fmt2.wd = 21; /* cast deals with negative value */ \
    624617                                                fmt2.flags.pc = true; fmt2.pc = 21; \
    625618                                        } else { \
    626619                                                if ( fmt.wd > 22 ) fmt.wd -= 22; \
    627                                                 /* compensate for leading 0 */ \
    628                                                 /*if ( ! fmt.flags.nobsdp && fmt.pc < fmt.wd ) fmt.wd -= 1;*/ \
    629                                                 fmt2.wd = 1; \
     620                                                else fmt.wd = 1; \
    630621                                                /* printf( "R %llo %llo %llo %d %d '%c' %x %llo %d %d '%c' %x\n", msig, lsig, fmt.val, fmt.wd, fmt.pc, fmt.base, fmt.all, fmt2.val, fmt2.wd, fmt2.pc, fmt2.base, fmt2.all ); */ \
    631622                                                (ostype &)(os | fmt | "" | fmt2); \
     
    636627                                        /* printf( "\nC %llo %d %d '%c' %x\n", fmt2.val, fmt2.wd, fmt2.pc, fmt2.base, fmt2.all ); */ \
    637628                                        (ostype &)(os | fmt2); \
    638                                 } else { \
    639                                         if ( fmt.flags.pc && fmt.pc > 16 ) fmt.pc -= 16; \
     629                                } else { /* f.base == 'x'  | f.base == 'X' */ \
     630                                        if ( fmt.flags.pc && fmt.pc > 16 ) fmt.pc -= 16; else { fmt.flags.pc = false; fmt.pc = 0; } \
    640631                                        if ( fmt.flags.left ) { \
    641                                                 fmt2.wd = fmt.wd; \
    642                                                 if ( fmt2.wd <= 16 ) { \
    643                                                         fmt2.wd = 16; \
    644                                                 } else { \
    645                                                         if ( fmt.pc > 0 ) { \
    646                                                                 fmt2.wd -= fmt.pc; \
    647                                                         } else { \
    648                                                                 fmt2.wd = fmt.wd - ceiling2( high1( msig ), 4 ) / 4; \
    649                                                         } /* if */ \
    650                                                         if ( ! fmt.flags.nobsdp ) fmt2.wd -= 2; \
    651                                                         if ( fmt2.wd < 0 ) fmt2.wd = 0; \
    652                                                         fmt2.flags.left = true; \
    653                                                         fmt.wd = 0; \
    654                                                 } /* if */ \
     632                                                fmt.flags.left = false; \
     633                                                fmt.wd = 0; \
     634                                                /* printf( "L %llo %llo %llo %d %d '%c' %x\n", msig, lsig, fmt.val, fmt.wd, fmt.pc, fmt.base, fmt.all ); */ \
     635                                                fmt2.flags.left = true; \
     636                                                int msigd = high1( msig ); \
     637                                                fmt2.wd = f.wd - (fmt.pc > msigd ? fmt.pc : msigd); \
     638                                                if ( ! fmt.flags.nobsdp ) fmt2.wd -= 2; /* compensate for 0x base specifier */ \
     639                                                if ( (int)fmt2.wd < 16 ) fmt2.wd = 16; /* cast deals with negative value */ \
     640                                                fmt2.flags.pc = true; fmt2.pc = 16; \
    655641                                        } else { \
     642                                                if ( fmt.wd > 16 ) fmt.wd -= 16; \
     643                                                else fmt.wd = 1; \
     644                                                /* printf( "R %llo %llo %llo %d %d '%c' %x\n", msig, lsig, fmt.val, fmt.wd, fmt.pc, fmt.base, fmt.all ); */ \
    656645                                                fmt2.wd = 16; \
    657                                                 if ( fmt.wd > 16 ) fmt.wd -= 16; \
    658646                                        } /* if */ \
    659                                         fmt2.pc = 16; fmt2.flags.pc = true; \
     647                                        /* printf( "C %llo %d %d '%c' %x\n", fmt2.val, fmt2.wd, fmt2.pc, fmt2.base, fmt2.all ); */ \
    660648                                        (ostype &)(os | fmt | "" | fmt2); \
    661649                                } /* if */ \
  • libcfa/src/startup.cfa

    r6ec07e5 raf7acb9  
    1414//
    1515
    16 #include <time.h>                                                                               // tzset
     16#include <time.h>                // tzset
     17#include <locale.h>        // setlocale
    1718#include "startup.hfa"
    1819
     
    2122    void __cfaabi_appready_startup( void ) {
    2223                tzset();                                                                                // initialize time global variables
     24                setlocale(LC_NUMERIC, "");
    2325                #ifdef __CFA_DEBUG__
    2426                extern void heapAppStart();
  • src/Parser/parser.yy

    r6ec07e5 raf7acb9  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Mar  6 17:26:45 2020
    13 // Update Count     : 4474
     12// Last Modified On : Mon Apr 27 12:25:42 2020
     13// Update Count     : 4483
    1414//
    1515
     
    966966
    967967tuple_expression_list:
    968         assignment_expression_opt
    969         | tuple_expression_list ',' assignment_expression_opt
     968        assignment_expression
     969        | '@'                                                                                           // CFA
     970                { SemanticError( yylloc, "Eliding tuple element with '@' is currently unimplemented." ); $$ = nullptr; }
     971        | tuple_expression_list ',' assignment_expression
    970972                { $$ = (ExpressionNode *)($1->set_last( $3 )); }
     973        | tuple_expression_list ',' '@'
     974                { SemanticError( yylloc, "Eliding tuple element with '@' is currently unimplemented." ); $$ = nullptr; }
    971975        ;
    972976
  • tests/exceptions/conditional.cfa

    r6ec07e5 raf7acb9  
    44// up the non-trivial exception is reasonable to do.
    55
    6 #include "except-mac.hfa"
     6#include <exception.hfa>
    77#include <stdio.h>
    88
    9 DECLARE_EXCEPT(num_error, BASE_EXCEPT,
     9VTABLE_DECLARATION(num_error)(
    1010        int (*code)(num_error *this);
    1111);
     
    3636    this.num = other.num;
    3737}
    38 void copy(num_error * this, num_error * other) {
    39         *this = *other;
    40 }
    4138void ^?{}(num_error & this) {
    4239    if( this.msg ) free( this.msg );
     
    4643}
    4744
    48 VTABLE_INSTANCE(num_error, BASE_EXCEPT, copy, ^?{},
    49         num_error_msg, num_error_code
     45VTABLE_INSTANCE(num_error)(
     46        num_error_msg,
     47        num_error_code,
    5048);
    5149
     
    5856
    5957        try {
    60                 THROW(&exc);
     58                throw &exc;
    6159        } catch (num_error * error ; 3 == error->virtual_table->code( error )) {
    6260                caught_num_error(3, error);
     
    6664
    6765        try {
    68                 THROW_RESUME(&exc);
     66                throwResume &exc;
    6967        } catchResume (num_error * error ; 3 == error->virtual_table->code( error )) {
    7068                caught_num_error(3, error);
  • tests/exceptions/finally.cfa

    r6ec07e5 raf7acb9  
    11// Finally Clause Tests
    22
    3 #include "except-mac.hfa"
     3#include <exception.hfa>
    44#include "except-io.hfa"
    55
     
    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                         THROW_RESUME(&exc);
     30                        throwResume &exc;
    3131                } finally {
    3232                        loud_exit a = "resumption inner finally";
  • tests/exceptions/interact.cfa

    r6ec07e5 raf7acb9  
    11// Testing Interactions Between Termination and Resumption
    22
    3 #include "except-mac.hfa"
     3#include <exception.hfa>
    44#include "except-io.hfa"
    55
     
    1010        // Resume falls back to terminate.
    1111        try {
    12                 THROW_RESUME(&(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                 THROW_RESUME(&(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                         THROW_RESUME(&(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                         THROW_RESUME(error);
     66                        throwResume error;
    6767                }
    6868        } catchResume (star *) {
     
    7575                try {
    7676                        try {
    77                                 THROW_RESUME(&(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                                         THROW_RESUME(&(moon){});
     96                                        throwResume &(moon){};
    9797                                } catch (star *) {
    9898                                        printf("termination catch\n");
    9999                                }
    100100                                printf("throwing resume star\n");
    101                                 THROW_RESUME(&(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

    r6ec07e5 raf7acb9  
    11// Resumption Exception Tests
    22
    3 #include "except-mac.hfa"
     3#include <exception.hfa>
    44#include "except-io.hfa"
    55
     
    1414                loud_exit a = "simple try clause";
    1515                printf("simple throw\n");
    16                 THROW_RESUME(&(zen){});
     16                throwResume &(zen){};
    1717                printf("end of try clause\n");
    1818        } catchResume (zen * error) {
     
    2525        try {
    2626                printf("throwing child exception\n");
    27                 THROW_RESUME(&(moment_of){});
     27                throwResume &(moment_of){};
    2828        } catchResume (zen *) {
    2929                printf("inner parent match\n");
     
    3636        try {
    3737                try {
    38                         THROW_RESUME(&(yin){});
     38                        throwResume &(yin){};
    3939                } catchResume (zen *) {
    4040                        printf("caught yin as zen\n");
     
    5252                        loud_exit a = "rethrow inner try";
    5353                        printf("rethrow inner try\n");
    54                         THROW_RESUME(&(zen){});
     54                        throwResume &(zen){};
    5555                } catchResume (zen *) {
    5656                        loud_exit a = "rethrowing catch clause";
     
    6767        try {
    6868                try {
    69                         THROW_RESUME(&(yin){});
     69                        throwResume &(yin){};
    7070                } catchResume (yin *) {
    7171                        printf("caught yin, will throw yang\n");
    72                         THROW_RESUME(&(yang){});
     72                        throwResume &(yang){};
    7373                } catchResume (yang *) {
    7474                        printf("caught exception from same try\n");
     
    8383                try {
    8484                        printf("throwing first exception\n");
    85                         THROW_RESUME(&(yin){});
     85                        throwResume &(yin){};
    8686                } catchResume (yin *) {
    8787                        printf("caught first exception\n");
    8888                        try {
    8989                                printf("throwing second exception\n");
    90                                 THROW_RESUME(&(yang){});
     90                                throwResume &(yang){};
    9191                        } catchResume (yang *) {
    9292                                printf("caught second exception\n");
     
    104104        try {
    105105                try {
    106                         THROW_RESUME(&(zen){});
    107                         THROW_RESUME(&(zen){});
     106                        throwResume &(zen){};
     107                        throwResume &(zen){};
    108108                } catchResume (zen *) {
    109109                        printf("inner catch\n");
    110110                }
    111                 THROW_RESUME(&(zen){});
     111                throwResume &(zen){};
    112112        } catchResume (zen *) {
    113113                printf("outer catch\n");
  • tests/exceptions/terminate.cfa

    r6ec07e5 raf7acb9  
    11// Termination Exception Tests
    22
    3 #include "except-mac.hfa"
     3#include <exception.hfa>
    44#include "except-io.hfa"
    55
     
    1414                loud_exit a = "simple try clause";
    1515                printf("simple throw\n");
    16                 THROW(&(zen){});
     16                throw &(zen){};
    1717                printf("end of try clause\n");
    1818        } catch (zen * error) {
     
    2525        try {
    2626                printf("throwing child exception\n");
    27                 THROW(&(moment_of){});
     27                throw &(moment_of){};
    2828        } catch (zen *) {
    2929                printf("inner parent match\n");
     
    3636        try {
    3737                try {
    38                         THROW(&(yin){});
     38                        throw &(yin){};
    3939                } catch (zen *) {
    4040                        printf("caught yin as zen\n");
     
    5252                        loud_exit a = "rethrow inner try";
    5353                        printf("rethrow inner try\n");
    54                         THROW(&(zen){});
     54                        throw &(zen){};
    5555                } catch (zen *) {
    5656                        loud_exit a = "rethrowing catch clause";
     
    6767        try {
    6868                try {
    69                         THROW(&(yin){});
     69                        throw &(yin){};
    7070                } catch (yin *) {
    7171                        printf("caught yin, will throw yang\n");
    72                         THROW(&(yang){});
     72                        throw &(yang){};
    7373                } catch (yang *) {
    7474                        printf("caught exception from same try\n");
     
    8383                try {
    8484                        printf("throwing first exception\n");
    85                         THROW(&(yin){});
     85                        throw &(yin){};
    8686                } catch (yin *) {
    8787                        printf("caught first exception\n");
    8888                        try {
    8989                                printf("throwing second exception\n");
    90                                 THROW(&(yang){});
     90                                throw &(yang){};
    9191                        } catch (yang *) {
    9292                                printf("caught second exception\n");
     
    104104        try {
    105105                try {
    106                         THROW(&(zen){});
    107                         THROW(&(zen){});
     106                        throw &(zen){};
     107                        throw &(zen){};
    108108                } catch (zen *) {
    109109                        printf("inner catch\n");
    110110                }
    111                 THROW(&(zen){});
     111                throw &(zen){};
    112112        } catch (zen *) {
    113113                printf("outer catch\n");
  • tests/manipulatorsOutput1.cfa

    r6ec07e5 raf7acb9  
    77// Created On       : Sat Jun  8 18:04:11 2019
    88// Last Modified By : Peter A. Buhr
    9 // Last Modified On : Mon Jun 10 12:37:28 2019
    10 // Update Count     : 8
     9// Last Modified On : Fri May  1 11:51:44 2020
     10// Update Count     : 9
    1111//
    1212
     
    1717        signed char sc = -12;
    1818        printf( "%hhd %2hhd %5.2hhd %-5.2hhd %hho %#hho %hhx %#hhx %#8hhx %#8.10hhx %#8.3hhX %+-8.3hhd %08hhd\n", sc, sc, sc, sc, sc, sc, sc, sc, sc, sc, sc, sc, sc );
    19         sout | sc | wd(2,sc) | wd(5,2,sc) | left(wd(5,2,sc)) | nobase(oct(sc)) | oct(sc) | nobase(hex(sc)) | hex(sc) | wd(8,hex(sc)) | wd(8,10,hex(sc)) | upcase(wd(8,3,hex(sc))) | left(sign(upcase(wd(8,3,sc)))) | pad0(wd(8,sc));
     19        sout | sc | wd(2,sc) | wd(5,2,sc) | left(wd(5,2,sc)) | nobase(oct(sc)) | oct(sc) | nonl;
     20        sout | nobase(hex(sc)) | hex(sc) | wd(8,hex(sc)) | wd(8,10,hex(sc)) | upcase(wd(8,3,hex(sc))) | nonl;
     21        sout | left(sign(upcase(wd(8,3,sc)))) | pad0(wd(8,sc));
    2022
    2123        sout | "unsigned char";
    2224        unsigned char usc = 12;
    2325        printf( "%hhu %2hhu %5.2hhu %-5.2hhu %hho %#hho %hhx %#hhx %#8hhx %#8.10hhx %#8.3hhX %-8.3hhu %08hhu\n", usc, usc, usc, usc, usc, usc, usc, usc, usc, usc, usc, usc, usc );
    24         sout | usc | wd(2,usc) | wd(5,2,usc) | left(wd(5,2,usc)) | nobase(oct(usc)) | oct(usc) | nobase(hex(usc)) | hex(usc) | wd(8,hex(usc)) | wd(8,10,hex(usc)) | upcase(wd(8,3,hex(usc))) | left(upcase(wd(8,3,usc))) | pad0(wd(8,usc));
     26        sout | usc | wd(2,usc) | wd(5,2,usc) | left(wd(5,2,usc)) | nobase(oct(usc)) | oct(usc) | nonl;
     27        sout | nobase(hex(usc)) | hex(usc) | wd(8,hex(usc)) | wd(8,10,hex(usc)) | upcase(wd(8,3,hex(usc))) | nonl;
     28        sout | left(upcase(wd(8,3,usc))) | pad0(wd(8,usc));
    2529
    2630        sout | "signed short int";
    2731        signed short int si = -12;
    2832        printf( "%hd %2hd %5.2hd %-5.2hd %ho %#ho %hx %#hx %#8hx %#8.10hx %#8.3hX %+-8.3hd %08hd\n", si, si, si, si, si, si, si, si, si, si, si, si, si );
    29         sout | si | wd(2,si) | wd(5,2,si) | left(wd(5,2,si)) | nobase(oct(si)) | oct(si) | nobase(hex(si)) | hex(si) | wd(8,hex(si)) | wd(8,10,hex(si)) | upcase(wd(8,3,hex(si))) | left(sign(upcase(wd(8,3,si)))) | pad0(wd(8,si));
     33        sout | si | wd(2,si) | wd(5,2,si) | left(wd(5,2,si)) | nobase(oct(si)) | oct(si) | nonl;
     34        sout | nobase(hex(si)) | hex(si) | wd(8,hex(si)) | wd(8,10,hex(si)) | upcase(wd(8,3,hex(si))) | nonl;
     35        sout | left(sign(upcase(wd(8,3,si)))) | pad0(wd(8,si));
    3036
    3137        sout | "unsigned short int";
    3238        unsigned short int usi = 12;
    3339        printf( "%hu %2hu %5.2hu %-5.2hu %ho %#ho %hx %#hx %#8hx %#8.10hx %#8.3hX %-8.3hu %08hu\n", usi, usi, usi, usi, usi, usi, usi, usi, usi, usi, usi, usi, usi );
    34         sout | usi | wd(2,usi) | wd(5,2,usi) | left(wd(5,2,usi)) | nobase(oct(usi)) | oct(usi) | nobase(hex(usi)) | hex(usi) | wd(8,hex(usi)) | wd(8,10,hex(usi)) | upcase(wd(8,3,hex(usi))) | left(upcase(wd(8,3,usi))) | pad0(wd(8,usi));
     40        sout | usi | wd(2,usi) | wd(5,2,usi) | left(wd(5,2,usi)) | nobase(oct(usi)) | oct(usi) | nonl;
     41        sout | nobase(hex(usi)) | hex(usi) | wd(8,hex(usi)) | wd(8,10,hex(usi)) | upcase(wd(8,3,hex(usi))) | nonl;
     42        sout | left(upcase(wd(8,3,usi))) | pad0(wd(8,usi));
    3543
    3644        sout | "signed int";
    3745        signed int i = -12;
    3846        printf( "%d %2d %5.2d %-5.2d %o %#o %x %#x %#8x %#8.10x %#8.3X %+-8.3d %08d\n", i, i, i, i, i, i, i, i, i, i, i, i, i );
    39         sout | i | wd(2,i) | wd(5,2,i) | left(wd(5,2,i)) | nobase(oct(i)) | oct(i) | nobase(hex(i)) | hex(i) | wd(8,hex(i)) | wd(8,10,hex(i)) | upcase(wd(8,3,hex(i))) | left(sign(upcase(wd(8,3,i)))) | pad0(wd(8,i));
     47        sout | i | wd(2,i) | wd(5,2,i) | left(wd(5,2,i)) | nobase(oct(i)) | oct(i) | nonl;
     48        sout | nobase(hex(i)) | hex(i) | wd(8,hex(i)) | wd(8,10,hex(i)) | upcase(wd(8,3,hex(i))) | nonl;
     49        sout | left(sign(upcase(wd(8,3,i)))) | pad0(wd(8,i));
    4050
    4151        sout | "unsigned int";
    4252        unsigned int ui = 12;
    4353        printf( "%u %2u %5.2u %-5.2u %o %#o %x %#x %#8x %#8.10x %#8.3X %-8.3u %08u\n", ui, ui, ui, ui, ui, ui, ui, ui, ui, ui, ui, ui, ui );
    44         sout | ui | wd(2,ui) | wd(5,2,ui) | left(wd(5,2,ui)) | nobase(oct(ui)) | oct(ui) | nobase(hex(ui)) | hex(ui) | wd(8,hex(ui)) | wd(8,10,hex(ui)) | upcase(wd(8,3,hex(ui))) | left(upcase(wd(8,3,ui))) | pad0(wd(8,ui));
     54        sout | ui | wd(2,ui) | wd(5,2,ui) | left(wd(5,2,ui)) | nobase(oct(ui)) | oct(ui) | nonl;
     55        sout | nobase(hex(ui)) | hex(ui) | wd(8,hex(ui)) | wd(8,10,hex(ui)) | upcase(wd(8,3,hex(ui))) | nonl;
     56        sout | left(upcase(wd(8,3,ui))) | pad0(wd(8,ui));
    4557
    4658        sout | "signed long long int";
    4759        signed long long int lli = -12;
    4860        printf( "%lld %2lld %5.2lld %-5.2lld %llo %#llo %llx %#llx %#8llx %#8.10llx %#8.3llX %+-8.3lld %08lld\n", lli, lli, lli, lli, lli, lli, lli, lli, lli, lli, lli, lli, lli );
    49         sout | lli | wd(2,lli) | wd(5,2,lli) | left(wd(5,2,lli)) | nobase(oct(lli)) | oct(lli) | nobase(hex(lli)) | hex(lli) | wd(8,hex(lli)) | wd(8,10,hex(lli)) | upcase(wd(8,3,hex(lli))) | left(sign(upcase(wd(8,3,lli)))) | pad0(wd(8,lli));
     61        sout | lli | wd(2,lli) | wd(5,2,lli) | left(wd(5,2,lli)) | nobase(oct(lli)) | oct(lli) | nonl;
     62        sout | nobase(hex(lli)) | hex(lli) | wd(8,hex(lli)) | wd(8,10,hex(lli)) | upcase(wd(8,3,hex(lli))) | nonl;
     63        sout | left(sign(upcase(wd(8,3,lli)))) | pad0(wd(8,lli));
    5064
    5165        sout | "unsigned long long int";
    5266        unsigned long long int ulli = 12;
    5367        printf( "%llu %2llu %5.2llu %-5.2llu %llo %#llo %llx %#llx %#8llx %#8.10llx %#8.3llX %-8.3llu %08llu\n", ulli, ulli, ulli, ulli, ulli, ulli, ulli, ulli, ulli, ulli, ulli, ulli, ulli );
    54         sout | ulli | wd(2,ulli) | wd(5,2,ulli) | left(wd(5,2,ulli)) | nobase(oct(ulli)) | oct(ulli) | nobase(hex(ulli)) | hex(ulli) | wd(8,hex(ulli)) | wd(8,10,hex(ulli)) | upcase(wd(8,3,hex(ulli))) | left(upcase(wd(8,3,ulli))) | pad0(wd(8,ulli));
     68        sout | ulli | wd(2,ulli) | wd(5,2,ulli) | left(wd(5,2,ulli)) | nobase(oct(ulli)) | oct(ulli) | nonl;
     69        sout | nobase(hex(ulli)) | hex(ulli) | wd(8,hex(ulli)) | wd(8,10,hex(ulli)) | upcase(wd(8,3,hex(ulli))) | nonl;
     70        sout | left(upcase(wd(8,3,ulli))) | pad0(wd(8,ulli));
    5571
    5672        sout | nl | "binary integral";
    57         sout | bin(0) | bin(13) | upcase(bin(13)) | nobase(bin(13)) | left(wd(8,bin(13))) | wd(8,bin(13)) | pad0(left(wd(8,bin(13)))) | pad0(wd(8,bin(13))) | pad0(wd(8,10,bin(13))) | pad0(wd(8,6,bin(13)));
     73        sout | bin(0) | bin(13) | upcase(bin(13)) | nobase(bin(13)) | left(wd(8,bin(13))) | wd(8,bin(13)) | nonl;
     74        sout | pad0(left(wd(8,bin(13)))) | pad0(wd(8,bin(13))) | pad0(wd(8,10,bin(13))) | pad0(wd(8,6,bin(13)));
    5875
    5976
     
    6279        printf( "%g  %8g %#8g %g %8g %8.0g %#8.0g %8.2g %#8.2g %-8.2g %-8.2g %-#8.2g %-+8.2g %-+#8.2g %08.2g %8.2E %8.2a %#8.2A %#8.2e\n",
    6380                    0.0,3.0F,3.0F, f,  f,    f,     f,    f,     f,  3.0F,      f,      f,      f,       f,     f,    f,    f,     f,     f );
    64         sout | 0.0 | wd(8, 3.0F) | nodp(wd(8, 3.0F)) | f | wd(8, f) | ws(8,0, f) | nodp(ws(8,0, f)) | ws(8,2, f) | nodp(ws(8,2, f)) | left(ws(8,2, 3.0F)) | left(ws(8,2, f)) | left(nodp(ws(8,2, f))) | left(sign(ws(8,2, f))) | left(sign(nodp(ws(8,2, f)))) | pad0(ws(8,2, f)) | upcase(wd(8,2, sci(f))) | wd(8,2, hex(f)) | upcase(wd(8,2, hex(f))) | nodp(wd(8,2, sci(f)));
     81        sout | 0.0 | wd(8, 3.0F) | nodp(wd(8, 3.0F)) | f | wd(8, f) | ws(8,0, f) | nodp(ws(8,0, f)) | ws(8,2, f) | nodp(ws(8,2, f)) | nonl;
     82        sout | left(ws(8,2, 3.0F)) | left(ws(8,2, f)) | left(nodp(ws(8,2, f))) | left(sign(ws(8,2, f))) | left(sign(nodp(ws(8,2, f)))) | nonl;
     83        sout | pad0(ws(8,2, f)) | upcase(wd(8,2, sci(f))) | wd(8,2, hex(f)) | upcase(wd(8,2, hex(f))) | nodp(wd(8,2, sci(f)));
    6584
    6685        sout | "double";
     
    6887        printf( "%g  %#8f %g %8f %#8.0f %8.0f %8.2f %-8.2f %-+#8.2f %08.2F %8.2E %8.2a %8.2A %8.2e\n",
    6988                        0.0,  3.0, d,  d,     d,    d,    d,     d,       d,     d,    d,    d,    d,    d );
    70         sout | 0.0 | wd(8, 3.0) | d | wd(8, d) | nodp(wd(8,0, d)) | wd(8,0, d) | wd(8,2, d) | left(wd(8,2, d)) | left(sign(wd(8,2, d))) | pad0(upcase(wd(8,2, d))) | upcase(wd(8,2, sci(d))) | wd(8,2, hex(d)) | upcase(wd(8,2, hex(d))) | wd(8,2, sci(d));
     89        sout | 0.0 | wd(8, 3.0) | d | wd(8, d) | nodp(wd(8,0, d)) | wd(8,0, d) | wd(8,2, d) | nonl;
     90        sout | left(wd(8,2, d)) | left(sign(wd(8,2, d))) | pad0(upcase(wd(8,2, d))) | upcase(wd(8,2, sci(d))) | wd(8,2, hex(d)) | upcase(wd(8,2, hex(d))) | wd(8,2, sci(d));
    7191
    7292        sout | "long double";
     
    7494        printf( "%Lg  %#8Lf %Lg %8Lf %#8.0Lf %8.0Lf %8.2Lf %-8.2Lf %-+#8.2Lf %08.2LF %8.2LE %8.2La %8.2LA %8.2Le\n",
    7595                        0.0L,  3.0L, ld,  ld,     ld,    ld,    ld,     ld,       ld,     ld,    ld,    ld,    ld,    ld );
    76         sout | 0.0L | wd(8, 3.0L) | ld | wd(8, ld) | nodp(wd(8,0, ld)) | wd(8,0, ld) | wd(8,2, ld) | left(wd(8,2, ld)) | left(sign(wd(8,2, ld))) | pad0(upcase(wd(8,2, ld))) | upcase(wd(8,2, sci(ld))) | wd(8,2, hex(ld)) | upcase(wd(8,2, hex(ld))) | wd(8,2, sci(ld));
     96        sout | 0.0L | wd(8, 3.0L) | ld | wd(8, ld) | nodp(wd(8,0, ld)) | wd(8,0, ld) | wd(8,2, ld) | nonl;
     97        sout | left(wd(8,2, ld)) | left(sign(wd(8,2, ld))) | pad0(upcase(wd(8,2, ld))) | upcase(wd(8,2, sci(ld))) | wd(8,2, hex(ld)) | upcase(wd(8,2, hex(ld))) | wd(8,2, sci(ld));
    7798
    7899
     
    80101        char c = 'a';
    81102        printf( "%c %2c %5c %-5c %hho %#hho %hhx %#hhx %#8hhx %#8hhX %-8c %8c\n", c, c, c, c, c, c, c, c, c, c, c, c );
    82         sout | c | ' ' | wd(2,c) | wd(5,c) | left(wd(5,c)) | nobase(oct(c)) | oct(c) | nobase(hex(c)) | hex(c) | wd(8,hex(c)) | upcase(wd(8,hex(c))) | left(wd(8,c)) | wd(8,c);
     103        sout | c | ' ' | wd(2,c) | wd(5,c) | left(wd(5,c)) | nobase(oct(c)) | oct(c) | nonl;
     104        sout | nobase(hex(c)) | hex(c) | wd(8,hex(c)) | upcase(wd(8,hex(c))) | left(wd(8,c)) | wd(8,c);
    83105
    84106        sout | nl | "string";
  • tests/manipulatorsOutput3.cfa

    r6ec07e5 raf7acb9  
    5252    sout | left(wd( 10,40, oct(y) )) | 'X';
    5353
    54     y = 123456789;
     54    y = 01234567;
    5555    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';
    5659    sout | nl;
    5760
     
    6669    sout | left(wd( 45,49, upcase(hex(x)) )) | 'X';
    6770
    68     sout | nl | nl;
     71    sout | nl;
    6972
    7073    int128 divisor = 0x4b3b4ca85a86c47a;
    7174    divisor <<= 16;
    7275    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;
    7397
    74     // base 10
     98    // decimal
     99    sout | "base 10";
    75100    sout | divisor;
    76101    sout | wd(2, divisor);
     
    87112    sout | pad0(wd(40, divisor));
    88113    sout | pad0(sign(wd(40,divisor)));
    89    
    90     // base 2
    91     sout | upcase(bin(divisor));
    92     sout | wd(38, upcase(bin(divisor)));
    93     sout | wd(40, upcase(bin(divisor)));
    94     sout | wd(40, 38, upcase(bin(divisor)));
    95     sout | wd(40, 30, upcase(bin(divisor)));
    96     sout | pad0(sign(wd(40, 38, upcase(bin(divisor)))));
    97    
    98     // oct
    99     sout | upcase(oct(divisor));
    100     sout | wd(38, upcase(oct(divisor)));
    101     sout | wd(40, upcase(oct(divisor)));
    102     sout | wd(40, 38, upcase(oct(divisor)));
    103     sout | wd(40, 30, upcase(oct(divisor)));
    104     sout | pad0(sign(wd(40, 38, upcase(oct(divisor)))));
     114    sout | nl;
    105115   
    106116    // hex
     117    sout | "base 16";
    107118    sout | upcase(hex(divisor));
    108119    sout | wd(38, upcase(hex(divisor)));
     
    111122    sout | wd(40, 30, upcase(hex(divisor)));
    112123    sout | pad0(sign(wd(40, 38, upcase(hex(divisor)))));
     124    sout | nl;
    113125
    114126   
Note: See TracChangeset for help on using the changeset viewer.