Changes in / [0e4df2e:2802824]


Ignore:
Files:
3 deleted
24 edited

Legend:

Unmodified
Added
Removed
  • driver/cfa.cc

    r0e4df2e r2802824  
    1010// Created On       : Tue Aug 20 13:44:49 2002
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon May 18 13:26:26 2020
    13 // Update Count     : 424
     12// Last Modified On : Fri Jan 31 16:48:03 2020
     13// Update Count     : 421
    1414//
    1515
     
    301301        } // for
    302302
     303        #ifdef __x86_64__
     304        args[nargs++] = "-mcx16";                                                       // allow double-wide CAA
     305        #endif // __x86_64__
     306
    303307        #ifdef __DEBUG_H__
    304308        cerr << "args:";
     
    415419                args[nargs++] = "-lcfa";
    416420                args[nargs++] = "-Wl,--pop-state";
    417                 #ifdef __x86_64__
    418                 args[nargs++] = "-mcx16";                                               // allow double-wide CAS
    419                 args[nargs++] = "-latomic";
    420                 #endif // __x86_64__
    421421                args[nargs++] = "-pthread";
    422422                args[nargs++] = "-ldl";
  • libcfa/src/Makefile.am

    r0e4df2e r2802824  
    1111## Created On       : Sun May 31 08:54:01 2015
    1212## Last Modified By : Peter A. Buhr
    13 ## Last Modified On : Sun May 17 21:10:26 2020
    14 ## Update Count     : 243
     13## Last Modified On : Mon Mar 16 18:07:59 2020
     14## Update Count     : 242
    1515###############################################################################
    1616
     
    3939#----------------------------------------------------------------------------------------------------------------
    4040if BUILDLIB
    41 headers_nosrc = bitmanip.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 containers/list.hfa
     41headers_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
    4342headers = fstream.hfa iostream.hfa iterator.hfa limits.hfa rational.hfa time.hfa stdlib.hfa common.hfa \
    44                 containers/maybe.hfa containers/pair.hfa containers/result.hfa containers/stackLockFree.hfa containers/vector.hfa
     43          containers/maybe.hfa containers/pair.hfa containers/result.hfa containers/vector.hfa
    4544
    4645libsrc = startup.cfa interpose.cfa bits/debug.cfa assert.cfa exception.c virtual.c heap.cfa ${headers:.hfa=.cfa}
  • libcfa/src/Makefile.in

    r0e4df2e r2802824  
    241241        containers/maybe.hfa containers/pair.hfa containers/result.hfa \
    242242        containers/vector.hfa bitmanip.hfa math.hfa gmp.hfa time_t.hfa \
    243         clock.hfa bits/align.hfa bits/containers.hfa bits/defs.hfa \
     243        bits/align.hfa bits/containers.hfa bits/defs.hfa \
    244244        bits/debug.hfa bits/locks.hfa containers/list.hfa \
    245245        concurrency/coroutine.hfa concurrency/thread.hfa \
     
    465465
    466466#----------------------------------------------------------------------------------------------------------------
    467 @BUILDLIB_TRUE@headers_nosrc = bitmanip.hfa math.hfa gmp.hfa time_t.hfa clock.hfa \
    468 @BUILDLIB_TRUE@         bits/align.hfa bits/containers.hfa bits/defs.hfa bits/debug.hfa bits/locks.hfa containers/list.hfa
    469 
     467@BUILDLIB_TRUE@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
    470468@BUILDLIB_FALSE@headers =
    471469@BUILDLIB_TRUE@headers = fstream.hfa iostream.hfa iterator.hfa limits.hfa rational.hfa time.hfa stdlib.hfa common.hfa \
    472 @BUILDLIB_TRUE@         containers/maybe.hfa containers/pair.hfa containers/result.hfa containers/vector.hfa
     470@BUILDLIB_TRUE@   containers/maybe.hfa containers/pair.hfa containers/result.hfa containers/vector.hfa
    473471
    474472@BUILDLIB_FALSE@libsrc =
  • libcfa/src/concurrency/io.cfa

    r0e4df2e r2802824  
    124124
    125125                // Like head/tail but not seen by the kernel
     126                volatile uint32_t alloc;
    126127                volatile uint32_t * ready;
    127128                uint32_t ready_cnt;
     
    140141                        struct {
    141142                                struct {
    142                                         volatile unsigned long long int rdy;
    143                                         volatile unsigned long long int csm;
    144                                         volatile unsigned long long int avl;
     143                                        volatile unsigned long long int val;
    145144                                        volatile unsigned long long int cnt;
     145                                        volatile unsigned long long int block;
    146146                                } submit_avg;
    147147                                struct {
     
    150150                                        volatile unsigned long long int block;
    151151                                } look_avg;
    152                                 struct {
    153                                         volatile unsigned long long int val;
    154                                         volatile unsigned long long int cnt;
    155                                         volatile unsigned long long int block;
    156                                 } alloc_avg;
    157152                        } stats;
    158153                #endif
     
    284279                sq.dropped = (         uint32_t *)(((intptr_t)sq.ring_ptr) + params.sq_off.dropped);
    285280                sq.array   = (         uint32_t *)(((intptr_t)sq.ring_ptr) + params.sq_off.array);
    286 
    287                 {
    288                         const uint32_t num = *sq.num;
    289                         for( i; num ) {
    290                                 sq.sqes[i].user_data = 0ul64;
    291                         }
    292                 }
     281                sq.alloc = *sq.tail;
    293282
    294283                if( io_flags & CFA_CLUSTER_IO_POLLER_THREAD_SUBMITS ) {
     
    333322                // Initialize statistics
    334323                #if !defined(__CFA_NO_STATISTICS__)
    335                         this.io->submit_q.stats.submit_avg.rdy = 0;
    336                         this.io->submit_q.stats.submit_avg.csm = 0;
    337                         this.io->submit_q.stats.submit_avg.avl = 0;
    338                         this.io->submit_q.stats.submit_avg.cnt = 0;
     324                        this.io->submit_q.stats.submit_avg.val   = 0;
     325                        this.io->submit_q.stats.submit_avg.cnt   = 0;
     326                        this.io->submit_q.stats.submit_avg.block = 0;
    339327                        this.io->submit_q.stats.look_avg.val   = 0;
    340328                        this.io->submit_q.stats.look_avg.cnt   = 0;
    341329                        this.io->submit_q.stats.look_avg.block = 0;
    342                         this.io->submit_q.stats.alloc_avg.val   = 0;
    343                         this.io->submit_q.stats.alloc_avg.cnt   = 0;
    344                         this.io->submit_q.stats.alloc_avg.block = 0;
    345330                        this.io->completion_q.stats.completed_avg.val = 0;
    346331                        this.io->completion_q.stats.completed_avg.slow_cnt = 0;
     
    399384                                        this.ready_queue.head = 1p;
    400385                                        thrd.next = 0p;
    401                                         __cfaabi_dbg_debug_do( thrd.unpark_stale = true );
    402386
    403387                                        // Fixup the thread state
     
    442426                        if(this.print_stats) {
    443427                                with(this.io->submit_q.stats, this.io->completion_q.stats) {
    444                                         double avgrdy = ((double)submit_avg.rdy) / submit_avg.cnt;
    445                                         double avgcsm = ((double)submit_avg.csm) / submit_avg.cnt;
    446                                         double avgavl = ((double)submit_avg.avl) / submit_avg.cnt;
    447 
    448428                                        double lavgv = 0;
    449429                                        double lavgb = 0;
     
    453433                                        }
    454434
    455                                         double aavgv = 0;
    456                                         double aavgb = 0;
    457                                         if(alloc_avg.cnt != 0) {
    458                                                 aavgv = ((double)alloc_avg.val  ) / alloc_avg.cnt;
    459                                                 aavgb = ((double)alloc_avg.block) / alloc_avg.cnt;
    460                                         }
    461 
    462435                                        __cfaabi_bits_print_safe( STDOUT_FILENO,
    463436                                                "----- I/O uRing Stats -----\n"
    464437                                                "- total submit calls     : %'15llu\n"
    465                                                 "- avg ready entries      : %'18.2lf\n"
    466                                                 "- avg submitted entries  : %'18.2lf\n"
    467                                                 "- avg available entries  : %'18.2lf\n"
     438                                                "- avg submit             : %'18.2lf\n"
     439                                                "- pre-submit block %%     : %'18.2lf\n"
    468440                                                "- total ready search     : %'15llu\n"
    469441                                                "- avg ready search len   : %'18.2lf\n"
    470442                                                "- avg ready search block : %'18.2lf\n"
    471                                                 "- total alloc search     : %'15llu\n"
    472                                                 "- avg alloc search len   : %'18.2lf\n"
    473                                                 "- avg alloc search block : %'18.2lf\n"
    474443                                                "- total wait calls       : %'15llu   (%'llu slow, %'llu fast)\n"
    475444                                                "- avg completion/wait    : %'18.2lf\n",
    476445                                                submit_avg.cnt,
    477                                                 avgrdy,
    478                                                 avgcsm,
    479                                                 avgavl,
     446                                                ((double)submit_avg.val) / submit_avg.cnt,
     447                                                (100.0 * submit_avg.block) / submit_avg.cnt,
    480448                                                look_avg.cnt,
    481449                                                lavgv,
    482450                                                lavgb,
    483                                                 alloc_avg.cnt,
    484                                                 aavgv,
    485                                                 aavgb,
    486451                                                completed_avg.slow_cnt + completed_avg.fast_cnt,
    487452                                                completed_avg.slow_cnt,  completed_avg.fast_cnt,
     
    529494
    530495                        // If the poller thread also submits, then we need to aggregate the submissions which are ready
    531                         uint32_t tail = *ring.submit_q.tail;
     496                        uint32_t * tail = ring.submit_q.tail;
    532497                        const uint32_t mask = *ring.submit_q.mask;
    533498
     
    541506
    542507                                // If we got a real submission, append it to the list
    543                                 ring.submit_q.array[ (tail + to_submit) & mask ] = idx & mask;
     508                                ring.submit_q.array[ ((*tail) + to_submit) & mask ] = idx & mask;
    544509                                to_submit++;
    545510                        }
    546511
    547512                        // Increment the tail based on how many we are ready to submit
    548                         __atomic_fetch_add(ring.submit_q.tail, to_submit, __ATOMIC_SEQ_CST);
    549                 }
    550 
    551                 const uint32_t smask = *ring.submit_q.mask;
    552                 uint32_t shead = *ring.submit_q.head;
     513                        __atomic_fetch_add(tail, to_submit, __ATOMIC_SEQ_CST);
     514
     515                        // update statistics
     516                        #if !defined(__CFA_NO_STATISTICS__)
     517                                ring.submit_q.stats.submit_avg.val += to_submit;
     518                                ring.submit_q.stats.submit_avg.cnt += 1;
     519                        #endif
     520                }
     521
    553522                int ret = syscall( __NR_io_uring_enter, ring.fd, to_submit, waitcnt, IORING_ENTER_GETEVENTS, mask, _NSIG / 8);
    554523                if( ret < 0 ) {
     
    562531                }
    563532
    564                 verify( (shead + ret) == *ring.submit_q.head );
    565 
    566                 // Release the consumed SQEs
    567                 for( i; ret ) {
    568                         uint32_t idx = ring.submit_q.array[ (i + shead) & smask ];
    569                         ring.submit_q.sqes[ idx ].user_data = 0;
    570                 }
    571 
    572                 uint32_t avail = 0;
    573                 uint32_t sqe_num = *ring.submit_q.num;
    574                 for(i; sqe_num) {
    575                         if( ring.submit_q.sqes[ i ].user_data == 0 ) avail++;
    576                 }
    577 
    578                 // update statistics
    579                 #if !defined(__CFA_NO_STATISTICS__)
    580                         ring.submit_q.stats.submit_avg.rdy += to_submit;
    581                         ring.submit_q.stats.submit_avg.csm += ret;
    582                         ring.submit_q.stats.submit_avg.avl += avail;
    583                         ring.submit_q.stats.submit_avg.cnt += 1;
    584                 #endif
    585 
    586533                // Drain the queue
    587534                unsigned head = *ring.completion_q.head;
    588                 unsigned tail = *ring.completion_q.tail;
    589                 const uint32_t mask = *ring.completion_q.mask;
    590 
    591                 // Memory barrier
    592                 __atomic_thread_fence( __ATOMIC_SEQ_CST );
     535                unsigned tail = __atomic_load_n(ring.completion_q.tail, __ATOMIC_ACQUIRE);
    593536
    594537                // Nothing was new return 0
     
    599542                uint32_t count = tail - head;
    600543                for(i; count) {
    601                         unsigned idx = (head + i) & mask;
     544                        unsigned idx = (head + i) & (*ring.completion_q.mask);
    602545                        struct io_uring_cqe & cqe = ring.completion_q.cqes[idx];
    603546
     
    613556
    614557                // Allow new submissions to happen
    615                 // V(ring.submit, count);
     558                V(ring.submit, count);
    616559
    617560                // Mark to the kernel that the cqe has been seen
    618561                // Ensure that the kernel only sees the new value of the head index after the CQEs have been read.
    619                 __atomic_thread_fence( __ATOMIC_SEQ_CST );
    620562                __atomic_fetch_add( ring.completion_q.head, count, __ATOMIC_RELAXED );
    621563
     
    768710//
    769711
    770         static inline [* struct io_uring_sqe, uint32_t] __submit_alloc( struct __io_data & ring, uint64_t data ) {
    771                 verify( data != 0 );
    772 
    773                 // Prepare the data we need
    774                 __attribute((unused)) int len   = 0;
    775                 __attribute((unused)) int block = 0;
    776                 uint32_t cnt = *ring.submit_q.num;
    777                 uint32_t mask = *ring.submit_q.mask;
    778                 uint32_t off = __tls_rand();
    779 
    780                 // Loop around looking for an available spot
    781                 LOOKING: for() {
    782                         // Look through the list starting at some offset
    783                         for(i; cnt) {
    784                                 uint64_t expected = 0;
    785                                 uint32_t idx = (i + off) & mask;
    786                                 struct io_uring_sqe * sqe = &ring.submit_q.sqes[idx];
    787                                 volatile uint64_t * udata = &sqe->user_data;
    788 
    789                                 if( *udata == expected &&
    790                                         __atomic_compare_exchange_n( udata, &expected, data, true, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED ) )
    791                                 {
    792                                         // update statistics
    793                                         #if !defined(__CFA_NO_STATISTICS__)
    794                                                 __atomic_fetch_add( &ring.submit_q.stats.alloc_avg.val,   len,   __ATOMIC_RELAXED );
    795                                                 __atomic_fetch_add( &ring.submit_q.stats.alloc_avg.block, block, __ATOMIC_RELAXED );
    796                                                 __atomic_fetch_add( &ring.submit_q.stats.alloc_avg.cnt,   1,     __ATOMIC_RELAXED );
    797                                         #endif
    798 
    799                                         // Success return the data
    800                                         return [sqe, idx];
    801                                 }
    802                                 verify(expected != data);
    803 
    804                                 len ++;
    805                         }
    806 
    807                         block++;
    808                         yield();
    809                 }
     712        static inline [* struct io_uring_sqe, uint32_t] __submit_alloc( struct __io_data & ring ) {
     713                // Wait for a spot to be available
     714                __attribute__((unused)) bool blocked = P(ring.submit);
     715                #if !defined(__CFA_NO_STATISTICS__)
     716                        __atomic_fetch_add( &ring.submit_q.stats.submit_avg.block, blocked ? 1ul64 : 0ul64, __ATOMIC_RELAXED );
     717                #endif
     718
     719                // Allocate the sqe
     720                uint32_t idx = __atomic_fetch_add(&ring.submit_q.alloc, 1ul32, __ATOMIC_SEQ_CST);
     721
     722                // Mask the idx now to allow make everything easier to check
     723                idx &= *ring.submit_q.mask;
     724
     725                // Return the sqe
     726                return [&ring.submit_q.sqes[ idx ], idx];
    810727        }
    811728
     
    825742                        __attribute((unused)) int len   = 0;
    826743                        __attribute((unused)) int block = 0;
     744                        uint32_t expected = -1ul32;
    827745                        uint32_t ready_mask = ring.submit_q.ready_cnt - 1;
    828746                        uint32_t off = __tls_rand();
     
    830748                                for(i; ring.submit_q.ready_cnt) {
    831749                                        uint32_t ii = (i + off) & ready_mask;
    832                                         uint32_t expected = -1ul32;
    833750                                        if( __atomic_compare_exchange_n( &ring.submit_q.ready[ii], &expected, idx, true, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED ) ) {
    834751                                                break LOOKING;
    835752                                        }
    836                                         verify(expected != idx);
    837753
    838754                                        len ++;
     
    876792                        // update statistics
    877793                        #if !defined(__CFA_NO_STATISTICS__)
    878                                 ring.submit_q.stats.submit_avg.csm += 1;
     794                                ring.submit_q.stats.submit_avg.val += 1;
    879795                                ring.submit_q.stats.submit_avg.cnt += 1;
    880796                        #endif
     
    915831
    916832        #define __submit_prelude \
    917                 io_user_data data = { 0, active_thread() }; \
    918                 struct __io_data & ring = *data.thrd->curr_cluster->io; \
     833                struct __io_data & ring = *active_cluster()->io; \
    919834                struct io_uring_sqe * sqe; \
    920835                uint32_t idx; \
    921                 [sqe, idx] = __submit_alloc( ring, (uint64_t)&data );
     836                [sqe, idx] = __submit_alloc( ring );
    922837
    923838        #define __submit_wait \
     839                io_user_data data = { 0, active_thread() }; \
    924840                /*__cfaabi_bits_print_safe( STDERR_FILENO, "Preparing user data %p for %p\n", &data, data.thrd );*/ \
    925                 verify( sqe->user_data == (uint64_t)&data ); \
     841                sqe->user_data = (uint64_t)&data; \
    926842                __submit( ring, idx ); \
    927843                park( __cfaabi_dbg_ctx ); \
  • libcfa/src/concurrency/kernel.cfa

    r0e4df2e r2802824  
    648648
    649649        // record activity
    650         __cfaabi_dbg_debug_do( char * old_caller = thrd->unpark_caller; )
    651650        __cfaabi_dbg_record_thrd( *thrd, false, caller );
    652651
  • libcfa/src/containers/list.hfa

    r0e4df2e r2802824  
    301301                $prev_link(list_pos) = (Telem*) 0p;
    302302        }
    303 
    304         static inline bool ?`is_empty(dlist(Tnode, Telem) &list) {
    305                 assert( &list != 0p );
    306                 $dlinks(Telem) *listLinks = & list.$links;
    307                 if (listLinks->next.is_terminator) {
    308                         assert(listLinks->prev.is_terminator);
    309                         assert(listLinks->next.terminator);
    310                         assert(listLinks->prev.terminator);
    311                         return true;
    312                 } else {
    313                         assert(!listLinks->prev.is_terminator);
    314                         assert(listLinks->next.elem);
    315                         assert(listLinks->prev.elem);
    316                         return false;
    317                 }
    318         }
    319 
    320         static inline Telem & pop_first(dlist(Tnode, Telem) &list) {
    321                 assert( &list != 0p );
    322                 assert( !list`is_empty );
    323                 $dlinks(Telem) *listLinks = & list.$links;
    324                 Telem & first = *listLinks->next.elem;
    325                 Tnode & list_pos_first  = $tempcv_e2n( first );
    326                 remove(list_pos_first);
    327                 return first;
    328         }
    329 
    330         static inline Telem & pop_last(dlist(Tnode, Telem) &list) {
    331                 assert( &list != 0p );
    332                 assert( !list`is_empty );
    333                 $dlinks(Telem) *listLinks = & list.$links;
    334                 Telem & last = *listLinks->prev.elem;
    335                 Tnode & list_pos_last  = $tempcv_e2n( last );
    336                 remove(list_pos_last);
    337                 return last;
    338         }
    339 
    340303}
    341304
  • libcfa/src/exception.c

    r0e4df2e r2802824  
    1010// Created On       : Mon Jun 26 15:13:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Thr May 21 12:18:00 2020
    13 // Update Count     : 20
     12// Last Modified On : Tue Apr 14 12:01:00 2020
     13// Update Count     : 18
    1414//
    1515
     
    8080}
    8181
    82 void __cfaehm_throw_resume(exception_t * except, void (*defaultHandler)(exception_t *)) {
     82void __cfaehm_throw_resume(exception_t * except) {
    8383        struct exception_context_t * context = this_exception_context();
    8484
     
    9696        }
    9797
    98         // No handler found, fall back to the default operation.
    9998        __cfadbg_print_safe(exception, "Unhandled exception\n");
    100         defaultHandler(except);
     99
     100        // Fall back to termination:
     101        __cfaehm_throw_terminate(except);
     102        // TODO: Default handler for resumption.
    101103}
    102104
     
    221223
    222224// Cancel the current stack, prefroming approprate clean-up and messaging.
    223 void __cfaehm_cancel_stack( exception_t * exception ) {
     225static __attribute__((noreturn)) void __cfaehm_cancel_stack(
     226                exception_t * exception ) {
    224227        // TODO: Detect current stack and pick a particular stop-function.
    225228        _Unwind_Reason_Code ret;
     
    237240}
    238241
    239 static void __cfaehm_cleanup_default( exception_t ** except ) {
    240         __cfaehm_delete_exception( *except );
    241         *except = NULL;
    242 }
    243 
    244242// The exception that is being thrown must already be stored.
    245 static void __cfaehm_begin_unwind(void(*defaultHandler)(exception_t *)) {
    246         struct exception_context_t * context = this_exception_context();
    247         struct _Unwind_Exception * storage = &this_exception_storage;
    248         if ( NULL == context->current_exception ) {
     243static __attribute__((noreturn)) void __cfaehm_begin_unwind(void) {
     244        if ( ! this_exception_context()->current_exception ) {
    249245                printf("UNWIND ERROR missing exception in begin unwind\n");
    250246                abort();
     
    252248
    253249        // Call stdlibc to raise the exception
    254         __cfadbg_print_safe(exception, "Begin unwinding (storage &p, context %p)\n", storage, context);
    255         _Unwind_Reason_Code ret = _Unwind_RaiseException( storage );
     250        _Unwind_Reason_Code ret = _Unwind_RaiseException( &this_exception_storage );
    256251
    257252        // If we reach here it means something happened. For resumption to work we need to find a way
     
    262257        // the whole stack.
    263258
     259        // No handler found, go to the default operation.
     260        // Currently this will always be a cancellation.
     261        if ( ret == _URC_END_OF_STACK ) {
     262                __cfadbg_print_safe(exception, "Uncaught exception %p\n", &this_exception_storage);
     263
     264                __cfaehm_cancel_stack(this_exception_context()->current_exception);
     265        }
     266
    264267        // We did not simply reach the end of the stack without finding a handler. This is an error.
    265         if ( ret != _URC_END_OF_STACK ) {
    266                 printf("UNWIND ERROR %d after raise exception\n", ret);
    267                 abort();
    268         }
    269 
    270         // No handler found, go to the default operation.
    271         __cfadbg_print_safe(exception, "Uncaught exception %p\n", storage);
    272 
    273         __attribute__((cleanup(__cfaehm_cleanup_default)))
    274         exception_t * exception = context->current_exception;
    275         defaultHandler( exception );
    276 }
    277 
    278 void __cfaehm_throw_terminate( exception_t * val, void (*defaultHandler)(exception_t *) ) {
     268        printf("UNWIND ERROR %d after raise exception\n", ret);
     269        abort();
     270}
     271
     272void __cfaehm_throw_terminate( exception_t * val ) {
    279273        __cfadbg_print_safe(exception, "Throwing termination exception\n");
    280274
    281275        __cfaehm_allocate_exception( val );
    282         __cfaehm_begin_unwind( defaultHandler );
    283 }
    284 
    285 static __attribute__((noreturn)) void __cfaehm_rethrow_adapter( exception_t * except ) {
    286         // TODO: Print some error message.
    287         (void)except;
    288         abort();
     276        __cfaehm_begin_unwind();
    289277}
    290278
     
    292280        __cfadbg_print_safe(exception, "Rethrowing termination exception\n");
    293281
    294         __cfaehm_begin_unwind( __cfaehm_rethrow_adapter );
    295         abort();
     282        __cfaehm_begin_unwind();
    296283}
    297284
  • libcfa/src/exception.h

    r0e4df2e r2802824  
    1010// Created On       : Mon Jun 26 15:11:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue May 19 14:17:00 2020
    13 // Update Count     : 10
     12// Last Modified On : Fri Mar 27 10:16:00 2020
     13// Update Count     : 9
    1414//
    1515
     
    3838
    3939
    40 void __cfaehm_cancel_stack(exception_t * except) __attribute__((noreturn));
    41 
    4240// Used in throw statement translation.
    43 void __cfaehm_throw_terminate(exception_t * except, void (*)(exception_t *));
     41void __cfaehm_throw_terminate(exception_t * except) __attribute__((noreturn));
    4442void __cfaehm_rethrow_terminate() __attribute__((noreturn));
    45 void __cfaehm_throw_resume(exception_t * except, void (*)(exception_t *));
     43void __cfaehm_throw_resume(exception_t * except);
    4644
    4745// Function catches termination exceptions.
     
    7270#ifdef __cforall
    7371}
    74 
    75 // Not all the built-ins can be expressed in C. These can't be
    76 // implemented in the .c file either so they all have to be inline.
    77 
    78 trait is_exception(dtype T) {
    79         /* The first field must be a pointer to a virtual table.
    80          * That virtual table must be a decendent of the base exception virtual tab$
    81          */
    82         void mark_exception(T *);
    83         // This is never used and should be a no-op.
    84 };
    85 
    86 trait is_termination_exception(dtype T | is_exception(T)) {
    87         void defaultTerminationHandler(T &);
    88 };
    89 
    90 trait is_resumption_exception(dtype T | is_exception(T)) {
    91         void defaultResumptionHandler(T &);
    92 };
    93 
    94 forall(dtype T | is_termination_exception(T))
    95 static inline void $throw(T & except) {
    96         __cfaehm_throw_terminate(
    97                 (exception_t *)&except,
    98                 (void(*)(exception_t *))defaultTerminationHandler
    99         );
    100 }
    101 
    102 forall(dtype T | is_resumption_exception(T))
    103 static inline void $throwResume(T & except) {
    104         __cfaehm_throw_resume(
    105                 (exception_t *)&except,
    106                 (void(*)(exception_t *))defaultResumptionHandler
    107         );
    108 }
    109 
    110 forall(dtype T | is_exception(T))
    111 static inline void cancel_stack(T & except) __attribute__((noreturn)) {
    112         __cfaehm_cancel_stack( (exception_t *)&except );
    113 }
    114 
    115 forall(dtype T | is_exception(T))
    116 static inline void defaultTerminationHandler(T & except) {
    117         return cancel_stack( except );
    118 }
    119 
    120 forall(dtype T | is_exception(T))
    121 static inline void defaultResumptionHandler(T & except) {
    122         throw except;
    123 }
    124 
    12572#endif
  • libcfa/src/exception.hfa

    r0e4df2e r2802824  
    1010// Created On       : Thu Apr  7 10:25:00 2020
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue May 19 14:17:00 2020
    13 // Update Count     : 2
     12// Last Modified On : Thu Apr  7 10:25:00 2020
     13// Update Count     : 0
    1414//
    1515
     
    6969#define _VTABLE_DECLARATION(exception_name, parent_name, ...) \
    7070        struct exception_name; \
    71         void mark_exception(exception_name *); \
    7271        VTABLE_TYPE(exception_name); \
    7372        extern VTABLE_TYPE(exception_name) VTABLE_NAME(exception_name); \
     
    8685#define VTABLE_INSTANCE(...) _EXC_DISPATCH(_VTABLE_INSTANCE, __VA_ARGS__)
    8786#define _VTABLE_INSTANCE(exception_name, parent_name, ...) \
    88         void mark_exception(exception_name *) {} \
    8987        void _GLUE2(exception_name,_copy)(exception_name * this, exception_name * other) { \
    9088                *this = *other; \
  • libcfa/src/executor.cfa

    r0e4df2e r2802824  
    44// buffer.
    55
    6 #include <containers/list.hfa>
     6#include <bits/containers.hfa>
    77#include <thread.hfa>
    88#include <stdio.h>
    99
     10forall( dtype T )
     11monitor Buffer {                                        // unbounded buffer
     12    __queue_t( T ) queue;                               // unbounded list of work requests
     13    condition delay;
     14}; // Buffer
     15forall( dtype T | is_node(T) ) {
     16    void insert( Buffer( T ) & mutex buf, T * elem ) with(buf) {
     17        append( queue, elem );                          // insert element into buffer
     18        signal( delay );                                // restart
     19    } // insert
     20
     21    T * remove( Buffer( T ) & mutex buf ) with(buf) {
     22        if ( queue.head != 0 ) wait( delay );                   // no request to process ? => wait
     23//      return pop_head( queue );
     24    } // remove
     25} // distribution
     26
    1027struct WRequest {                                       // client request, no return
    1128    void (* action)( void );
    12     DLISTED_MGD_IMPL_IN(WRequest)
     29    WRequest * next;                                    // intrusive queue field
    1330}; // WRequest
    14 DLISTED_MGD_IMPL_OUT(WRequest)
    1531
    16 void ?{}( WRequest & req ) with(req) { action = 0; }
    17 void ?{}( WRequest & req, void (* action)( void ) ) with(req) { req.action = action; }
     32WRequest *& get_next( WRequest & this ) { return this.next; }
     33void ?{}( WRequest & req ) with(req) { action = 0; next = 0; }
     34void ?{}( WRequest & req, void (* action)( void ) ) with(req) { req.action = action; next = 0; }
    1835bool stop( WRequest & req ) { return req.action == 0; }
    1936void doit( WRequest & req ) { req.action(); }
    20 
    21 monitor WRBuffer {                                      // unbounded buffer
    22     dlist( WRequest, WRequest ) queue;                  // unbounded list of work requests
    23     condition delay;
    24 }; // WRBuffer
    25 
    26 void insert( WRBuffer & mutex buf, WRequest * elem ) with(buf) {
    27     insert_last( queue, *elem );                        // insert element into buffer
    28     signal( delay );                                    // restart
    29 } // insert
    30 
    31 WRequest * remove( WRBuffer & mutex buf ) with(buf) {
    32     if ( queue`is_empty ) wait( delay );                // no request to process ? => wait
    33     return & pop_first( queue );
    34 } // remove
    3537
    3638// Each worker has its own work buffer to reduce contention between client and server. Hence, work requests arrive and
     
    3840
    3941thread Worker {
    40     WRBuffer * requests;
     42    Buffer( WRequest ) * requests;
    4143    unsigned int start, range;
    4244}; // Worker
     
    5254} // Worker::main
    5355
    54 void ?{}( Worker & worker, cluster * wc, WRBuffer * requests, unsigned int start, unsigned int range ) {
     56void ?{}( Worker & worker, cluster * wc, Buffer( WRequest ) * requests, unsigned int start, unsigned int range ) {
    5557    (*get_thread(worker)){ *wc };                       // create on given cluster
    5658    worker.[requests, start, range] = [requests, start, range];
     
    6062    cluster * cluster;                                  // if workers execute on separate cluster
    6163    processor ** processors;                            // array of virtual processors adding parallelism for workers
    62     WRBuffer * requests;                                // list of work requests
     64    Buffer( WRequest ) * requests;                      // list of work requests
    6365    Worker ** workers;                                  // array of workers executing work requests
    6466    unsigned int nprocessors, nworkers, nmailboxes;     // number of mailboxes/workers/processor tasks
     
    7779    cluster = sepClus ? new( "Executor" ) : active_cluster();
    7880    processors = (processor **)anew( nprocessors );
    79     requests = (WRBuffer *)anew( nmailboxes );
     81    requests = anew( nmailboxes );
    8082    workers = (Worker **)anew( nworkers );
    8183
     
    139141        for ( i; 3000 ) {
    140142            send( exector, workie );
    141             if ( i % 100 == 0 ) {
    142 //              fprintf( stderr, "%d\n", i );
    143                 yield();
    144             }
     143            if ( i % 100 ) yield();
    145144        } // for
    146145    }
  • libcfa/src/heap.cfa

    r0e4df2e r2802824  
    1010// Created On       : Tue Dec 19 21:58:35 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun May 17 20:58:17 2020
    13 // Update Count     : 762
     12// Last Modified On : Wed May  6 17:29:26 2020
     13// Update Count     : 727
    1414//
    1515
     
    128128#define LOCKFREE 1
    129129#define BUCKETLOCK SPINLOCK
    130 #if BUCKETLOCK == SPINLOCK
    131 #elif BUCKETLOCK == LOCKFREE
    132 #include <stackLockFree.hfa>
    133 #else
    134         #error undefined lock type for bucket lock
     130#if BUCKETLOCK == LOCKFREE
     131#include <uStackLF.h>
    135132#endif // LOCKFREE
    136133
     
    140137
    141138struct HeapManager {
     139//      struct FreeHeader;                                                                      // forward declaration
     140
    142141        struct Storage {
    143142                struct Header {                                                                 // header
     
    147146                                                struct {                                                // 4-byte word => 8-byte header, 8-byte word => 16-byte header
    148147                                                        #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ && __SIZEOF_POINTER__ == 4
    149                                                         uint64_t padding;                       // unused, force home/blocksize to overlay alignment in fake header
     148                                                        uint32_t padding;                       // unused, force home/blocksize to overlay alignment in fake header
    150149                                                        #endif // __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ && __SIZEOF_POINTER__ == 4
    151150
    152151                                                        union {
    153                                                                 // FreeHeader * home;           // allocated block points back to home locations (must overlay alignment)
     152//                                                              FreeHeader * home;              // allocated block points back to home locations (must overlay alignment)
    154153                                                                // 2nd low-order bit => zero filled
    155154                                                                void * home;                    // allocated block points back to home locations (must overlay alignment)
    156155                                                                size_t blockSize;               // size for munmap (must overlay alignment)
    157                                                                 #if BUCKETLOCK == SPINLOCK
     156                                                                #if BUCKLOCK == SPINLOCK
    158157                                                                Storage * next;                 // freed block points next freed block of same size
    159158                                                                #endif // SPINLOCK
    160159                                                        };
    161                                                         size_t size;                            // allocation size in bytes
    162160
    163161                                                        #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ && __SIZEOF_POINTER__ == 4
    164                                                         uint64_t padding;                       // unused, force home/blocksize to overlay alignment in fake header
     162                                                        uint32_t padding;                       // unused, force home/blocksize to overlay alignment in fake header
    165163                                                        #endif // __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ && __SIZEOF_POINTER__ == 4
    166164                                                };
    167                                                 #if BUCKETLOCK == LOCKFREE
    168                                                 Link(Storage) next;                             // freed block points next freed block of same size (double-wide)
     165                                                // future code
     166                                                #if BUCKLOCK == LOCKFREE
     167                                                Stack<Storage>::Link next;              // freed block points next freed block of same size (double-wide)
    169168                                                #endif // LOCKFREE
    170169                                        };
    171170                                } real; // RealHeader
    172 
    173171                                struct FakeHeader {
    174172                                        #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
    175                                         uint32_t alignment;                                     // 1st low-order bit => fake header & alignment
     173                                        // 1st low-order bit => fake header & alignment
     174                                        uint32_t alignment;
    176175                                        #endif // __ORDER_LITTLE_ENDIAN__
    177176
     
    183182                                } fake; // FakeHeader
    184183                        } kind; // Kind
     184                        size_t size;                                                            // allocation size in bytes
    185185                } header; // Header
    186186                char pad[libAlign() - sizeof( Header )];
     
    191191
    192192        struct FreeHeader {
    193                 #if BUCKETLOCK == SPINLOCK
     193                #if BUCKLOCK == SPINLOCK
    194194                __spinlock_t lock;                                                              // must be first field for alignment
    195195                Storage * freeList;
     196                #elif BUCKLOCK == LOCKFREE
     197                // future code
     198                StackLF<Storage> freeList;
    196199                #else
    197                 StackLF(Storage) freeList;
    198                 #endif // BUCKETLOCK
     200                        #error undefined lock type for bucket lock
     201                #endif // SPINLOCK
    199202                size_t blockSize;                                                               // size of allocations on this list
    200203        }; // FreeHeader
     
    208211        size_t heapRemaining;                                                           // amount of storage not allocated in the current chunk
    209212}; // HeapManager
    210 
    211 #if BUCKETLOCK == LOCKFREE
    212 static inline Link(HeapManager.Storage) * getNext( HeapManager.Storage * this ) { return &this->header.kind.real.next; }
    213 static inline void ?{}( HeapManager.FreeHeader & ) {}
    214 static inline void ^?{}( HeapManager.FreeHeader & ) {}
    215 #endif // LOCKFREE
    216213
    217214static inline size_t getKey( const HeapManager.FreeHeader & freeheader ) { return freeheader.blockSize; }
     
    254251static bool heapBoot = 0;                                                               // detect recursion during boot
    255252#endif // __CFA_DEBUG__
    256 
    257 // The constructor for heapManager is called explicitly in memory_startup.
    258253static HeapManager heapManager __attribute__(( aligned (128) )) @= {}; // size of cache line to prevent false sharing
    259254
     
    359354
    360355
     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
    361363// thunk problem
    362364size_t Bsearchl( unsigned int key, const unsigned int * vals, size_t dim ) {
     
    404406
    405407
    406 // static inline void noMemory() {
    407 //      abort( "Heap memory exhausted at %zu bytes.\n"
    408 //                 "Possible cause is very large memory allocation and/or large amount of unfreed storage allocated by the program or system/library routines.",
    409 //                 ((char *)(sbrk( 0 )) - (char *)(heapManager.heapBegin)) );
    410 // } // noMemory
    411 
    412 
    413408static inline void checkAlign( size_t alignment ) {
    414409        if ( alignment < libAlign() || ! libPow2( alignment ) ) {
     
    438433
    439434
    440 static inline bool headers( const char name[] __attribute__(( unused )), void * addr, HeapManager.Storage.Header *& header, HeapManager.FreeHeader *& freeElem,
    441                                                         size_t & size, size_t & alignment ) with( heapManager ) {
     435static 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 ) {
    442436        header = headerAddr( addr );
    443437
     
    471465
    472466
    473 static inline void * extend( size_t size ) with( heapManager ) {
     467static inline void * extend( size_t size ) with ( heapManager ) {
    474468        lock( extlock __cfaabi_dbg_ctx2 );
    475469        ptrdiff_t rem = heapRemaining - size;
     
    502496
    503497
    504 static inline void * doMalloc( size_t size ) with( heapManager ) {
     498static inline void * doMalloc( size_t size ) with ( heapManager ) {
    505499        HeapManager.Storage * block;                                            // pointer to new block of storage
    506500
     
    535529                // Spin until the lock is acquired for this particular size of block.
    536530
    537                 #if BUCKETLOCK == SPINLOCK
     531                #if defined( SPINLOCK )
    538532                lock( freeElem->lock __cfaabi_dbg_ctx2 );
    539533                block = freeElem->freeList;                                             // remove node from stack
    540534                #else
    541                 block = pop( freeElem->freeList );
    542                 #endif // BUCKETLOCK
     535                block = freeElem->freeList.pop();
     536                #endif // SPINLOCK
    543537                if ( unlikely( block == 0p ) ) {                                // no free block ?
    544                         #if BUCKETLOCK == SPINLOCK
     538                        #if defined( SPINLOCK )
    545539                        unlock( freeElem->lock );
    546                         #endif // BUCKETLOCK
     540                        #endif // SPINLOCK
    547541
    548542                        // Freelist for that size was empty, so carve it out of the heap if there's enough left, or get some more
     
    550544
    551545                        block = (HeapManager.Storage *)extend( tsize ); // mutual exclusion on call
    552         if ( unlikely( block == 0p ) ) return 0p;
    553                 #if BUCKETLOCK == SPINLOCK
     546  if ( unlikely( block == 0p ) ) return 0p;
     547                #if defined( SPINLOCK )
    554548                } else {
    555549                        freeElem->freeList = block->header.kind.real.next;
    556550                        unlock( freeElem->lock );
    557                 #endif // BUCKETLOCK
     551                #endif // SPINLOCK
    558552                } // if
    559553
     
    578572        } // if
    579573
    580         block->header.kind.real.size = size;                            // store allocation size
     574        block->header.size = size;                                                      // store allocation size
    581575        void * addr = &(block->data);                                           // adjust off header to user bytes
    582576
     
    597591
    598592
    599 static inline void doFree( void * addr ) with( heapManager ) {
     593static inline void doFree( void * addr ) with ( heapManager ) {
    600594        #ifdef __CFA_DEBUG__
    601595        if ( unlikely( heapManager.heapBegin == 0p ) ) {
     
    629623                free_storage += size;
    630624                #endif // __STATISTICS__
    631                 #if BUCKETLOCK == SPINLOCK
     625                #if defined( SPINLOCK )
    632626                lock( freeElem->lock __cfaabi_dbg_ctx2 );               // acquire spin lock
    633627                header->kind.real.next = freeElem->freeList;    // push on stack
     
    635629                unlock( freeElem->lock );                                               // release spin lock
    636630                #else
    637                 push( freeElem->freeList, *(HeapManager.Storage *)header );
    638                 #endif // BUCKETLOCK
     631                freeElem->freeList.push( *(HeapManager.Storage *)header );
     632                #endif // SPINLOCK
    639633        } // if
    640634
     
    651645
    652646
    653 size_t prtFree( HeapManager & manager ) with( manager ) {
     647size_t prtFree( HeapManager & manager ) with ( manager ) {
    654648        size_t total = 0;
    655649        #ifdef __STATISTICS__
     
    663657                #endif // __STATISTICS__
    664658
    665                 #if BUCKETLOCK == SPINLOCK
     659                #if defined( SPINLOCK )
    666660                for ( HeapManager.Storage * p = freeLists[i].freeList; p != 0p; p = p->header.kind.real.next ) {
    667661                #else
    668                 for ( HeapManager.Storage * p = top( freeLists[i].freeList ); p != 0p; /* p = getNext( p )->top */) {
    669                         typeof(p) temp = getNext( p )->top;                     // FIX ME: direct assignent fails, initialization works
    670                         p = temp;
    671                 #endif // BUCKETLOCK
     662                for ( HeapManager.Storage * p = freeLists[i].freeList.top(); p != 0p; p = p->header.kind.real.next.top ) {
     663                #endif // SPINLOCK
    672664                        total += size;
    673665                        #ifdef __STATISTICS__
     
    689681
    690682
    691 static void ?{}( HeapManager & manager ) with( manager ) {
     683static void ?{}( HeapManager & manager ) with ( manager ) {
    692684        pageSize = sysconf( _SC_PAGESIZE );
    693685
     
    11031095                        header = realHeader( header );                          // backup from fake to real header
    11041096                } // if
    1105                 return header->kind.real.size;
     1097                return header->size;
    11061098        } // malloc_size
    11071099
     
    11131105                        header = realHeader( header );                          // backup from fake to real header
    11141106                } // if
    1115                 size_t ret = header->kind.real.size;
    1116                 header->kind.real.size = size;
     1107                size_t ret = header->size;
     1108                header->size = size;
    11171109                return ret;
    11181110        } // $malloc_size_set
  • libcfa/src/stdlib.hfa

    r0e4df2e r2802824  
    1010// Created On       : Thu Jan 28 17:12:35 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed May 13 17:23:51 2020
    13 // Update Count     : 435
     12// Last Modified On : Thu Apr 16 22:44:05 2020
     13// Update Count     : 432
    1414//
    1515
     
    2323// Reduce includes by explicitly defining these routines.
    2424extern "C" {
    25         void * aalloc( size_t dim, size_t elemSize );           // CFA heap
    26         void * resize( void * oaddr, size_t size );                     // CFA heap
    2725        void * memalign( size_t align, size_t size );           // malloc.h
    28         void * amemalign( size_t align, size_t dim, size_t elemSize ); // CFA heap
    29         void * cmemalign( size_t align, size_t noOfElems, size_t elemSize ); // CFA heap
     26        size_t malloc_usable_size( void * ptr );                        // malloc.h
    3027        size_t malloc_size( void * addr );                                      // CFA heap
    31         size_t malloc_usable_size( void * ptr );                        // malloc.h
     28        void * cmemalign( size_t alignment, size_t noOfElems, size_t elemSize ); // CFA heap
    3229        void * memset( void * dest, int fill, size_t size ); // string.h
    3330        void * memcpy( void * dest, const void * src, size_t size ); // string.h
     31        void * resize( void * oaddr, size_t size );                     // CFA heap
    3432} // extern "C"
    3533
     
    5452        } // malloc
    5553
    56         T * aalloc( size_t dim ) {
    57                 if ( _Alignof(T) <= libAlign() ) return (T *)(void *)aalloc( dim, (size_t)sizeof(T) ); // CFA aalloc
    58                 else return (T *)amemalign( _Alignof(T), dim, sizeof(T) );
    59         } // aalloc
    60 
    6154        T * calloc( size_t dim ) {
    6255                if ( _Alignof(T) <= libAlign() )return (T *)(void *)calloc( dim, sizeof(T) ); // C calloc
     
    6457        } // calloc
    6558
    66         T * resize( T * ptr, size_t size ) {                            // CFA realloc, eliminate return-type cast
    67                 return (T *)(void *)resize( (void *)ptr, size ); // C realloc
    68         } // resize
    69 
    7059        T * realloc( T * ptr, size_t size ) {                           // CFA realloc, eliminate return-type cast
    7160                return (T *)(void *)realloc( (void *)ptr, size ); // C realloc
     
    7665        } // memalign
    7766
    78         T * amemalign( size_t align, size_t dim ) {
    79                 return (T *)amemalign( align, dim, sizeof(T) ); // CFA amemalign
    80         } // amemalign
    81 
    8267        T * cmemalign( size_t align, size_t dim  ) {
    8368                return (T *)cmemalign( align, dim, sizeof(T) ); // CFA cmemalign
     
    10186
    10287        T * alloc( size_t dim ) {
    103                 return aalloc( 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) );
    10490        } // alloc
    10591
     
    120106                        return (T *)(void *)realloc( (void *)ptr, dim * sizeof(T) ); // C realloc
    121107                } else {
    122                         return resize( ptr, dim * sizeof(T) );          // resize
     108                        struct __Unknown {};
     109                        return alloc( (__Unknown *)ptr, dim );          // reuse, cheat making T/S different types
    123110                } // if
    124111        } // alloc
     
    161148        } // alloc_align
    162149
    163         T * alloc_align( T * ptr, size_t align ) {                      // aligned realloc array
     150        T * alloc_align( T ptr[], size_t align ) {                      // aligned realloc array
    164151                return (T *)(void *)realloc( (void *)ptr, align, sizeof(T) ); // CFA realloc
    165152        } // alloc_align
  • src/ControlStruct/ExceptTranslate.cc

    r0e4df2e r2802824  
    1010// Created On       : Wed Jun 14 16:49:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Thr May 21 13:18:00 2020
    13 // Update Count     : 15
     12// Last Modified On : Fri Mar 27 11:58:00 2020
     13// Update Count     : 13
    1414//
    1515
     
    6464        }
    6565
    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                 Statement * create_resume_rethrow( ThrowStmt * throwStmt );
    75 
    76         public:
    77                 ThrowMutatorCore() :
    78                         terminate_handler_except( nullptr ),
    79                         cur_context( NoHandler )
    80                 {}
    81 
    82                 void premutate( CatchStmt *catchStmt );
    83                 Statement * postmutate( ThrowStmt *throwStmt );
    84         };
    85 
    86         // ThrowStmt Mutation Helpers
    87 
    88         Statement * ThrowMutatorCore::create_either_throw(
    89                         ThrowStmt * throwStmt, const char * throwFunc ) {
    90                 // `throwFunc`( `throwStmt->get_name()` );
    91                 UntypedExpr * call = new UntypedExpr( new NameExpr( throwFunc ) );
    92                 call->get_args().push_back( throwStmt->get_expr() );
    93                 throwStmt->set_expr( nullptr );
    94                 delete throwStmt;
    95                 return new ExprStmt( call );
    96         }
    97 
    98         Statement * ThrowMutatorCore::create_terminate_rethrow(
    99                         ThrowStmt *throwStmt ) {
    100                 // { `terminate_handler_except` = 0p; __rethrow_terminate(); }
    101                 assert( nullptr == throwStmt->get_expr() );
    102                 assert( terminate_handler_except );
    103 
    104                 CompoundStmt * result = new CompoundStmt();
    105                 result->labels =  throwStmt->labels;
    106                 result->push_back( new ExprStmt( UntypedExpr::createAssign(
    107                         nameOf( terminate_handler_except ),
    108                         new ConstantExpr( Constant::null(
    109                                 //new PointerType(
    110                                 //      noQualifiers,
    111                                         terminate_handler_except->get_type()->clone()
    112                                 //      )
    113                                 ) )
    114                         ) ) );
    115                 result->push_back( new ExprStmt(
    116                         new UntypedExpr( new NameExpr( "__cfaehm_rethrow_terminate" ) )
    117                         ) );
    118                 delete throwStmt;
    119                 return result;
    120         }
    121 
    122         Statement * ThrowMutatorCore::create_resume_rethrow(
    123                         ThrowStmt *throwStmt ) {
    124                 // return false;
    125                 Statement * result = new ReturnStmt(
    126                         new ConstantExpr( Constant::from_bool( false ) )
    127                         );
    128                 result->labels = throwStmt->labels;
    129                 delete throwStmt;
    130                 return result;
    131         }
    132 
    133         // Visiting/Mutating Functions
    134 
    135         void ThrowMutatorCore::premutate( CatchStmt *catchStmt ) {
    136                 // Validate the statement's form.
    137                 ObjectDecl * decl = dynamic_cast<ObjectDecl *>( catchStmt->get_decl() );
    138                 // Also checking the type would be nice.
    139                 if ( decl ) {
    140                         // Pass.
    141                 } else if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
    142                         SemanticError(catchStmt->location, "catch must have exception type");
    143                 } else {
    144                         SemanticError(catchStmt->location, "catchResume must have exception type");
    145                 }
    146 
    147                 // Track the handler context.
    148                 GuardValue( cur_context );
    149                 if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
    150                         cur_context = TerHandler;
    151 
    152                         GuardValue( terminate_handler_except );
    153                         terminate_handler_except = decl;
    154                 } else {
    155                         cur_context = ResHandler;
    156                 }
    157         }
    158 
    159         Statement * ThrowMutatorCore::postmutate( ThrowStmt *throwStmt ) {
    160                 // Ignoring throwStmt->get_target() for now.
    161                 if ( ThrowStmt::Terminate == throwStmt->get_kind() ) {
    162                         if ( throwStmt->get_expr() ) {
    163                                 return create_either_throw( throwStmt, "$throw" );
    164                         } else if ( TerHandler == cur_context ) {
    165                                 return create_terminate_rethrow( throwStmt );
    166                         } else {
    167                                 abort("Invalid throw in %s at %i\n",
    168                                         throwStmt->location.filename.c_str(),
    169                                         throwStmt->location.first_line);
    170                         }
    171                 } else {
    172                         if ( throwStmt->get_expr() ) {
    173                                 return create_either_throw( throwStmt, "$throwResume" );
    174                         } else if ( ResHandler == cur_context ) {
    175                                 return create_resume_rethrow( throwStmt );
    176                         } else {
    177                                 abort("Invalid throwResume in %s at %i\n",
    178                                         throwStmt->location.filename.c_str(),
    179                                         throwStmt->location.first_line);
    180                         }
    181                 }
    182         }
    183 
    184         class TryMutatorCore {
     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
    18578                // The built in types used in translation.
    18679                StructDecl * except_decl;
     
    18982
    19083                // 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 );
    19190                CompoundStmt * take_try_block( TryStmt * tryStmt );
    19291                FunctionDecl * create_try_wrapper( CompoundStmt * body );
     
    222121
    223122        public:
    224                 TryMutatorCore() :
     123                ExceptionMutatorCore() :
     124                        cur_context( NoHandler ),
     125                        handler_except_decl( nullptr ),
    225126                        except_decl( nullptr ), node_decl( nullptr ), hook_decl( nullptr ),
    226127                        try_func_t( noQualifiers, false ),
     
    231132                {}
    232133
     134                void premutate( CatchStmt *catchStmt );
    233135                void premutate( StructDecl *structDecl );
    234136                Statement * postmutate( ThrowStmt *throwStmt );
     
    236138        };
    237139
    238         void TryMutatorCore::init_func_types() {
     140        void ExceptionMutatorCore::init_func_types() {
    239141                assert( except_decl );
    240142
     
    294196        }
    295197
     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
    296257        // TryStmt Mutation Helpers
    297258
    298         CompoundStmt * TryMutatorCore::take_try_block( TryStmt *tryStmt ) {
     259        CompoundStmt * ExceptionMutatorCore::take_try_block( TryStmt *tryStmt ) {
    299260                CompoundStmt * block = tryStmt->get_block();
    300261                tryStmt->set_block( nullptr );
     
    302263        }
    303264
    304         FunctionDecl * TryMutatorCore::create_try_wrapper(
     265        FunctionDecl * ExceptionMutatorCore::create_try_wrapper(
    305266                        CompoundStmt *body ) {
    306267
     
    309270        }
    310271
    311         FunctionDecl * TryMutatorCore::create_terminate_catch(
     272        FunctionDecl * ExceptionMutatorCore::create_terminate_catch(
    312273                        CatchList &handlers ) {
    313274                std::list<CaseStmt *> handler_wrappers;
     
    389350        // Create a single check from a moddified handler.
    390351        // except_obj is referenced, modded_handler will be freed.
    391         CompoundStmt * TryMutatorCore::create_single_matcher(
     352        CompoundStmt * ExceptionMutatorCore::create_single_matcher(
    392353                        DeclarationWithType * except_obj, CatchStmt * modded_handler ) {
    393354                // {
     
    427388        }
    428389
    429         FunctionDecl * TryMutatorCore::create_terminate_match(
     390        FunctionDecl * ExceptionMutatorCore::create_terminate_match(
    430391                        CatchList &handlers ) {
    431392                // int match(exception * except) {
     
    464425        }
    465426
    466         CompoundStmt * TryMutatorCore::create_terminate_caller(
     427        CompoundStmt * ExceptionMutatorCore::create_terminate_caller(
    467428                        FunctionDecl * try_wrapper,
    468429                        FunctionDecl * terminate_catch,
     
    482443        }
    483444
    484         FunctionDecl * TryMutatorCore::create_resume_handler(
     445        FunctionDecl * ExceptionMutatorCore::create_resume_handler(
    485446                        CatchList &handlers ) {
    486447                // bool handle(exception * except) {
     
    519480        }
    520481
    521         CompoundStmt * TryMutatorCore::create_resume_wrapper(
     482        CompoundStmt * ExceptionMutatorCore::create_resume_wrapper(
    522483                        Statement * wraps,
    523484                        FunctionDecl * resume_handler ) {
     
    563524        }
    564525
    565         FunctionDecl * TryMutatorCore::create_finally_wrapper(
     526        FunctionDecl * ExceptionMutatorCore::create_finally_wrapper(
    566527                        TryStmt * tryStmt ) {
    567                 // void finally() { `finally->block` }
     528                // void finally() { <finally code> }
    568529                FinallyStmt * finally = tryStmt->get_finally();
    569530                CompoundStmt * body = finally->get_block();
     
    576537        }
    577538
    578         ObjectDecl * TryMutatorCore::create_finally_hook(
     539        ObjectDecl * ExceptionMutatorCore::create_finally_hook(
    579540                        FunctionDecl * finally_wrapper ) {
    580541                // struct __cfaehm_cleanup_hook __finally_hook
    581                 //      __attribute__((cleanup( `finally_wrapper` )));
     542                //      __attribute__((cleanup( finally_wrapper )));
    582543
    583544                // Make Cleanup Attribute.
     
    604565
    605566        // Visiting/Mutating Functions
    606         void TryMutatorCore::premutate( StructDecl *structDecl ) {
     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 ) {
    607592                if ( !structDecl->has_body() ) {
    608593                        // Skip children?
     
    619604                        hook_decl = structDecl;
    620605                }
    621         }
    622 
    623         Statement * TryMutatorCore::postmutate( ThrowStmt * ) {
    624                 // All throws should be removed by this point.
    625                 assert( false );
    626         }
    627 
    628         Statement * TryMutatorCore::postmutate( TryStmt *tryStmt ) {
     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 ) {
    629637                assert( except_decl );
    630638                assert( node_decl );
     
    680688        }
    681689
    682         void translateThrows( std::list< Declaration *> & translationUnit ) {
    683                 PassVisitor<ThrowMutatorCore> translator;
     690        void translateEHM( std::list< Declaration *> & translationUnit ) {
     691                PassVisitor<ExceptionMutatorCore> translator;
    684692                mutateAll( translationUnit, translator );
    685693        }
    686 
    687         void translateTries( std::list< Declaration *> & translationUnit ) {
    688                 PassVisitor<TryMutatorCore> translator;
    689                 mutateAll( translationUnit, translator );
    690         }
    691694}
  • src/ControlStruct/ExceptTranslate.h

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

    r0e4df2e r2802824  
    99// Author           : Peter Buhr and Rob Schluntz
    1010// Created On       : Fri May 15 23:12:02 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Tue May 19 12:03:00 2020
    13 // Update Count     : 634
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Feb  8 08:33:50 2020
     13// Update Count     : 633
    1414//
    1515
     
    312312                } // if
    313313
    314                 PASS( "Translate Throws", ControlStruct::translateThrows( translationUnit ) );
    315314                PASS( "Fix Labels", ControlStruct::fixLabels( translationUnit ) );
    316315                PASS( "Fix Names", CodeGen::fixNames( translationUnit ) );
     
    355354                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
    356355
    357                 PASS( "Translate Tries" , ControlStruct::translateTries( translationUnit ) );
     356                PASS( "Translate EHM" , ControlStruct::translateEHM( translationUnit ) );
    358357
    359358                PASS( "Gen Waitfor" , Concurrency::generateWaitFor( translationUnit ) );
  • tests/errors/.expect/completeType.txt

    r0e4df2e r2802824  
    132132?=?: pointer to function
    133133        ... with parameters
    134           reference to instance of type _108_0_T (not function type)
    135           instance of type _108_0_T (not function type)
     134          reference to instance of type _104_0_T (not function type)
     135          instance of type _104_0_T (not function type)
    136136        ... returning
    137           _retval__operator_assign: instance of type _108_0_T (not function type)
     137          _retval__operator_assign: instance of type _104_0_T (not function type)
    138138          ... with attributes:
    139139            Attribute with name: unused
  • tests/exceptions/conditional.cfa

    r0e4df2e r2802824  
    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

    r0e4df2e r2802824  
    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

    r0e4df2e r2802824  
    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

    r0e4df2e r2802824  
    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

    r0e4df2e r2802824  
    1414                loud_exit a = "simple try clause";
    1515                printf("simple throw\n");
    16                 throwResume (zen){};
     16                throwResume &(zen){};
    1717                printf("end of try clause\n");
    1818        } catchResume (zen * error) {
     
    2424        // Throw catch-all test.
    2525        try {
    26                 throwResume (zen){};
     26                throwResume &(zen){};
    2727        } catchResume (exception_t * error) {
    2828                printf("catch-all\n");
     
    3333        try {
    3434                printf("throwing child exception\n");
    35                 throwResume (moment_of){};
     35                throwResume &(moment_of){};
    3636        } catchResume (zen *) {
    3737                printf("inner parent match\n");
     
    4444        try {
    4545                try {
    46                         throwResume (yin){};
     46                        throwResume &(yin){};
    4747                } catchResume (zen *) {
    4848                        printf("caught yin as zen\n");
     
    6060                        loud_exit a = "rethrow inner try";
    6161                        printf("rethrow inner try\n");
    62                         throwResume (zen){};
     62                        throwResume &(zen){};
    6363                } catchResume (zen *) {
    6464                        loud_exit a = "rethrowing catch clause";
     
    7575        try {
    7676                try {
    77                         throwResume (yin){};
     77                        throwResume &(yin){};
    7878                } catchResume (yin *) {
    7979                        printf("caught yin, will throw yang\n");
    80                         throwResume (yang){};
     80                        throwResume &(yang){};
    8181                } catchResume (yang *) {
    8282                        printf("caught exception from same try\n");
     
    9191                try {
    9292                        printf("throwing first exception\n");
    93                         throwResume (yin){};
     93                        throwResume &(yin){};
    9494                } catchResume (yin *) {
    9595                        printf("caught first exception\n");
    9696                        try {
    9797                                printf("throwing second exception\n");
    98                                 throwResume (yang){};
     98                                throwResume &(yang){};
    9999                        } catchResume (yang *) {
    100100                                printf("caught second exception\n");
     
    112112        try {
    113113                try {
    114                         throwResume (zen){};
    115                         throwResume (zen){};
     114                        throwResume &(zen){};
     115                        throwResume &(zen){};
    116116                } catchResume (zen *) {
    117117                        printf("inner catch\n");
    118118                }
    119                 throwResume (zen){};
     119                throwResume &(zen){};
    120120        } catchResume (zen *) {
    121121                printf("outer catch\n");
  • tests/exceptions/terminate.cfa

    r0e4df2e r2802824  
    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) {
     
    2424        // Throw catch-all test.
    2525        try {
    26                 throw (zen){};
     26                throw &(zen){};
    2727        } catch (exception_t * error) {
    2828                printf("catch-all\n");
     
    3333        try {
    3434                printf("throwing child exception\n");
    35                 throw (moment_of){};
     35                throw &(moment_of){};
    3636        } catch (zen *) {
    3737                printf("inner parent match\n");
     
    4444        try {
    4545                try {
    46                         throw (yin){};
     46                        throw &(yin){};
    4747                } catch (zen *) {
    4848                        printf("caught yin as zen\n");
     
    6060                        loud_exit a = "rethrow inner try";
    6161                        printf("rethrow inner try\n");
    62                         throw (zen){};
     62                        throw &(zen){};
    6363                } catch (zen *) {
    6464                        loud_exit a = "rethrowing catch clause";
     
    7575        try {
    7676                try {
    77                         throw (yin){};
     77                        throw &(yin){};
    7878                } catch (yin *) {
    7979                        printf("caught yin, will throw yang\n");
    80                         throw (yang){};
     80                        throw &(yang){};
    8181                } catch (yang *) {
    8282                        printf("caught exception from same try\n");
     
    9191                try {
    9292                        printf("throwing first exception\n");
    93                         throw (yin){};
     93                        throw &(yin){};
    9494                } catch (yin *) {
    9595                        printf("caught first exception\n");
    9696                        try {
    9797                                printf("throwing second exception\n");
    98                                 throw (yang){};
     98                                throw &(yang){};
    9999                        } catch (yang *) {
    100100                                printf("caught second exception\n");
     
    112112        try {
    113113                try {
    114                         throw (zen){};
    115                         throw (zen){};
     114                        throw &(zen){};
     115                        throw &(zen){};
    116116                } catch (zen *) {
    117117                        printf("inner catch\n");
    118118                }
    119                 throw (zen){};
     119                throw &(zen){};
    120120        } catch (zen *) {
    121121                printf("outer catch\n");
  • tests/list/.expect/dlist-insert-remove.txt

    r0e4df2e r2802824  
    146414640.7
    14651465-
    1466 
    1467 ~~~~~~~~~~ End removal tests on Headed List: First ~~~~~~~~~~
    1468 
    1469 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1470 Test 16-i.  Modifying Freds on MINE
    1471 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1472 ==== fred by MINE before
    1473 1.7
    1474 2.7
    1475 3.7
    1476 -
    1477 1.7
    1478 -
    1479 3.7
    1480 -
    1481 3.7
    1482 2.7
    1483 1.7
    1484 -
    1485 ==== fred by YOURS before
    1486 1.7
    1487 2.7
    1488 3.7
    1489 -
    1490 1.7
    1491 -
    1492 3.7
    1493 -
    1494 3.7
    1495 2.7
    1496 1.7
    1497 -
    1498 ==== fred by MINE after
    1499 2.7
    1500 3.7
    1501 -
    1502 2.7
    1503 -
    1504 3.7
    1505 -
    1506 3.7
    1507 2.7
    1508 -
    1509 ==== fred by YOURS after
    1510 1.7
    1511 2.7
    1512 3.7
    1513 -
    1514 1.7
    1515 -
    1516 3.7
    1517 -
    1518 3.7
    1519 2.7
    1520 1.7
    1521 -
    1522 ==== fred by MINE after
    1523 1.7
    1524 -
    1525 1.7
    1526 -
    1527 -
    1528 -
    1529 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1530 Test 16-ii.  Modifying Freds on YOURS
    1531 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1532 ==== fred by MINE before
    1533 1.7
    1534 2.7
    1535 3.7
    1536 -
    1537 1.7
    1538 -
    1539 3.7
    1540 -
    1541 3.7
    1542 2.7
    1543 1.7
    1544 -
    1545 ==== fred by YOURS before
    1546 1.7
    1547 2.7
    1548 3.7
    1549 -
    1550 1.7
    1551 -
    1552 3.7
    1553 -
    1554 3.7
    1555 2.7
    1556 1.7
    1557 -
    1558 ==== fred by MINE after
    1559 1.7
    1560 2.7
    1561 3.7
    1562 -
    1563 1.7
    1564 -
    1565 3.7
    1566 -
    1567 3.7
    1568 2.7
    1569 1.7
    1570 -
    1571 ==== fred by YOURS after
    1572 2.7
    1573 3.7
    1574 -
    1575 2.7
    1576 -
    1577 3.7
    1578 -
    1579 3.7
    1580 2.7
    1581 -
    1582 ==== fred by YOURS after
    1583 1.7
    1584 -
    1585 1.7
    1586 -
    1587 -
    1588 -
    1589 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1590 Test 16-iii.  Modifying Maries
    1591 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1592 ==== mary before
    1593 1.7
    1594 2.7
    1595 3.7
    1596 -
    1597 1.7
    1598 -
    1599 3.7
    1600 -
    1601 3.7
    1602 2.7
    1603 1.7
    1604 -
    1605 ==== mary after
    1606 2.7
    1607 3.7
    1608 -
    1609 2.7
    1610 -
    1611 3.7
    1612 -
    1613 3.7
    1614 2.7
    1615 -
    1616 ==== mary after
    1617 1.7
    1618 -
    1619 1.7
    1620 -
    1621 -
    1622 -
    1623 
    1624 ~~~~~~~~~~ End removal tests on Headed List: Last ~~~~~~~~~~
    1625 
    1626 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1627 Test 17-i.  Modifying Freds on MINE
    1628 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1629 ==== fred by MINE before
    1630 1.7
    1631 2.7
    1632 3.7
    1633 -
    1634 1.7
    1635 -
    1636 3.7
    1637 -
    1638 3.7
    1639 2.7
    1640 1.7
    1641 -
    1642 ==== fred by YOURS before
    1643 1.7
    1644 2.7
    1645 3.7
    1646 -
    1647 1.7
    1648 -
    1649 3.7
    1650 -
    1651 3.7
    1652 2.7
    1653 1.7
    1654 -
    1655 ==== fred by MINE after
    1656 1.7
    1657 2.7
    1658 -
    1659 1.7
    1660 -
    1661 2.7
    1662 -
    1663 2.7
    1664 1.7
    1665 -
    1666 ==== fred by YOURS after
    1667 1.7
    1668 2.7
    1669 3.7
    1670 -
    1671 1.7
    1672 -
    1673 3.7
    1674 -
    1675 3.7
    1676 2.7
    1677 1.7
    1678 -
    1679 ==== fred by MINE after
    1680 3.7
    1681 -
    1682 3.7
    1683 -
    1684 -
    1685 -
    1686 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1687 Test 17-ii.  Modifying Freds on YOURS
    1688 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1689 ==== fred by MINE before
    1690 1.7
    1691 2.7
    1692 3.7
    1693 -
    1694 1.7
    1695 -
    1696 3.7
    1697 -
    1698 3.7
    1699 2.7
    1700 1.7
    1701 -
    1702 ==== fred by YOURS before
    1703 1.7
    1704 2.7
    1705 3.7
    1706 -
    1707 1.7
    1708 -
    1709 3.7
    1710 -
    1711 3.7
    1712 2.7
    1713 1.7
    1714 -
    1715 ==== fred by MINE after
    1716 1.7
    1717 2.7
    1718 3.7
    1719 -
    1720 1.7
    1721 -
    1722 3.7
    1723 -
    1724 3.7
    1725 2.7
    1726 1.7
    1727 -
    1728 ==== fred by YOURS after
    1729 1.7
    1730 2.7
    1731 -
    1732 1.7
    1733 -
    1734 2.7
    1735 -
    1736 2.7
    1737 1.7
    1738 -
    1739 ==== fred by YOURS after
    1740 3.7
    1741 -
    1742 3.7
    1743 -
    1744 -
    1745 -
    1746 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1747 Test 17-iii.  Modifying Maries
    1748 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1749 ==== mary before
    1750 1.7
    1751 2.7
    1752 3.7
    1753 -
    1754 1.7
    1755 -
    1756 3.7
    1757 -
    1758 3.7
    1759 2.7
    1760 1.7
    1761 -
    1762 ==== mary after
    1763 1.7
    1764 2.7
    1765 -
    1766 1.7
    1767 -
    1768 2.7
    1769 -
    1770 2.7
    1771 1.7
    1772 -
    1773 ==== mary after
    1774 3.7
    1775 -
    1776 3.7
    1777 -
    1778 -
    1779 -
  • tests/list/dlist-insert-remove.cfa

    r0e4df2e r2802824  
    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 
    1199 void test__pop_first__fred_mine() {
    1200 
    1201         fred f1 = {1.7};
    1202         fred f2 = {2.7};
    1203         fred f3 = {3.7};
    1204 
    1205         dlist(fred_in_mine, fred) flm;
    1206         insert_last(flm, f1);
    1207         insert_last(flm, f2);
    1208         insert_last(flm, f3);
    1209 
    1210         dlist(fred_in_yours, fred) fly;
    1211         insert_last(fly, f1);
    1212         insert_last(fly, f2);
    1213         insert_last(fly, f3);
    1214 
    1215         printMyFreddies(flm`first, flm`last, 1);     // 1.7, 2.7, 3.7;  1.7;  3.7;  3.7, 2.7, 1.7
    1216         printYourFreddies(fly`first, fly`last, 1);   // 1.7, 2.7, 3.7;  1.7;  3.7;  3.7, 2.7, 1.7
    1217 
    1218         verify(validate(fly));
    1219         verify(validate(flm));
    1220 
    1221         fred & popped = pop_first(flm);
    1222 
    1223         verify(validate(fly));
    1224         verify(validate(flm));
    1225 
    1226         printMyFreddies(flm`first, flm`last, 0);     // 2.7, 3.7;       2.7;  3.7;  3.7, 2.7      (modified)
    1227         printYourFreddies(fly`first, fly`last, 0);   // 1.7, 2.7, 3.7;  1.7;  3.7;  3.7, 2.7, 1.7 (unmodified)
    1228 
    1229         // observe f1 is now solo in mine; in yours, it was just traversed
    1230         printMyFreddies(f1, *0p, 0);    // 1.7; 1.7; ;
    1231 
    1232         assert( &popped == & f1 );
    1233 }
    1234 
    1235 void test__pop_first__fred_yours() {
    1236 
    1237         fred f1 = {1.7};
    1238         fred f2 = {2.7};
    1239         fred f3 = {3.7};
    1240 
    1241         dlist(fred_in_mine, fred) flm;
    1242         insert_last(flm, f1);
    1243         insert_last(flm, f2);
    1244         insert_last(flm, f3);
    1245 
    1246         dlist(fred_in_yours, fred) fly;
    1247         insert_last(fly, f1);
    1248         insert_last(fly, f2);
    1249         insert_last(fly, f3);
    1250 
    1251         printMyFreddies(flm`first, flm`last, 1);     // 1.7, 2.7, 3.7;  1.7;  3.7;  3.7, 2.7, 1.7
    1252         printYourFreddies(fly`first, fly`last, 1);   // 1.7, 2.7, 3.7;  1.7;  3.7;  3.7, 2.7, 1.7
    1253 
    1254         verify(validate(fly));
    1255         verify(validate(flm));
    1256 
    1257         fred & popped = pop_first(fly);
    1258 
    1259         verify(validate(fly));
    1260         verify(validate(flm));
    1261 
    1262         printMyFreddies(flm`first, flm`last, 0);     // 1.7, 2.7, 3.7;  1.7;  3.7;  3.7, 2.7, 1.7 (unmodified)
    1263         printYourFreddies(fly`first, fly`last, 0);   // 2.7, 3.7;       2.7;  3.7;  3.7, 2.7      (modified)
    1264 
    1265         // observe f1 is now solo in yours; in mine, it was just traversed
    1266         printYourFreddies(f1, *0p, 0);    // 1.7; 1.7; ;
    1267 
    1268         assert( &popped == &f1 );
    1269 }
    1270 
    1271 void test__pop_first__maries() {
    1272 
    1273         mary m1 = {1.7};
    1274         mary m2 = {2.7};
    1275         mary m3 = {3.7};
    1276 
    1277         dlist(mary, mary) ml;
    1278         insert_last(ml, m1);
    1279         insert_last(ml, m2);
    1280         insert_last(ml, m3);
    1281 
    1282         printMariatheotokos(ml`first, ml`last, 1);     // 1.7, 2.7, 3.7;  1.7;  3.7;  3.7, 2.7, 1.7
    1283 
    1284         verify(validate(ml));
    1285 
    1286         mary & popped = pop_first(ml);
    1287 
    1288         verify(validate(ml));
    1289 
    1290         printMariatheotokos(ml`first, ml`last, 0);     // 2.7, 3.7;       2.7;  3.7;  3.7, 2.7      (modified)
    1291 
    1292         // observe m1 is now solo
    1293         printMariatheotokos(m1, *0p, 0);               // 1.7; 1.7; ;
    1294 
    1295         assert( &popped == &m1 );
    1296 }
    1297 
    1298 void test__pop_last__fred_mine() {
    1299 
    1300         fred f1 = {1.7};
    1301         fred f2 = {2.7};
    1302         fred f3 = {3.7};
    1303 
    1304         dlist(fred_in_mine, fred) flm;
    1305         insert_last(flm, f1);
    1306         insert_last(flm, f2);
    1307         insert_last(flm, f3);
    1308 
    1309         dlist(fred_in_yours, fred) fly;
    1310         insert_last(fly, f1);
    1311         insert_last(fly, f2);
    1312         insert_last(fly, f3);
    1313 
    1314         printMyFreddies(flm`first, flm`last, 1);     // 1.7, 2.7, 3.7;  1.7;  3.7;  3.7, 2.7, 1.7
    1315         printYourFreddies(fly`first, fly`last, 1);   // 1.7, 2.7, 3.7;  1.7;  3.7;  3.7, 2.7, 1.7
    1316 
    1317         verify(validate(fly));
    1318         verify(validate(flm));
    1319 
    1320         fred & popped = pop_last(flm);
    1321 
    1322         verify(validate(fly));
    1323         verify(validate(flm));
    1324 
    1325         printMyFreddies(flm`first, flm`last, 0);     // 1.7, 2.7;       1.7;  2.7;  2.7, 1.7      (modified)
    1326         printYourFreddies(fly`first, fly`last, 0);   // 1.7, 2.7, 3.7;  1.7;  3.7;  3.7, 2.7, 1.7 (unmodified)
    1327 
    1328         // observe f3 is now solo in mine; in yours, it was just traversed
    1329         printMyFreddies(f3, *0p, 0);    // 3.7; 3.7; ;
    1330 
    1331         assert( &popped == & f3 );
    1332 }
    1333 
    1334 void test__pop_last__fred_yours() {
    1335 
    1336         fred f1 = {1.7};
    1337         fred f2 = {2.7};
    1338         fred f3 = {3.7};
    1339 
    1340         dlist(fred_in_mine, fred) flm;
    1341         insert_last(flm, f1);
    1342         insert_last(flm, f2);
    1343         insert_last(flm, f3);
    1344 
    1345         dlist(fred_in_yours, fred) fly;
    1346         insert_last(fly, f1);
    1347         insert_last(fly, f2);
    1348         insert_last(fly, f3);
    1349 
    1350         printMyFreddies(flm`first, flm`last, 1);     // 1.7, 2.7, 3.7;  1.7;  3.7;  3.7, 2.7, 1.7
    1351         printYourFreddies(fly`first, fly`last, 1);   // 1.7, 2.7, 3.7;  1.7;  3.7;  3.7, 2.7, 1.7
    1352 
    1353         verify(validate(fly));
    1354         verify(validate(flm));
    1355 
    1356         fred & popped = pop_last(fly);
    1357 
    1358         verify(validate(fly));
    1359         verify(validate(flm));
    1360 
    1361         printMyFreddies(flm`first, flm`last, 0);     // 1.7, 2.7, 3.7;  1.7;  3.7;  3.7, 2.7, 1.7 (unmodified)
    1362         printYourFreddies(fly`first, fly`last, 0);   // 1.7, 2.7;       1.7;  2.7;  2.7, 1.7      (modified)
    1363 
    1364         // observe f3 is now solo in yours; in mine, it was just traversed
    1365         printYourFreddies(f3, *0p, 0);    // 3.7; 3.7; ;
    1366 
    1367         assert( &popped == & f3 );
    1368 }
    1369 
    1370 void test__pop_last__maries() {
    1371 
    1372         mary m1 = {1.7};
    1373         mary m2 = {2.7};
    1374         mary m3 = {3.7};
    1375 
    1376         dlist(mary, mary) ml;
    1377         insert_last(ml, m1);
    1378         insert_last(ml, m2);
    1379         insert_last(ml, m3);
    1380 
    1381         printMariatheotokos(ml`first, ml`last, 1);     // 1.7, 2.7, 3.7;  1.7;  3.7;  3.7, 2.7, 1.7
    1382 
    1383         verify(validate(ml));
    1384 
    1385         mary & popped = pop_last(ml);
    1386 
    1387         verify(validate(ml));
    1388 
    1389         printMariatheotokos(ml`first, ml`last, 0);     // 1.7, 1.7;       1.7;  2.7;  2.7, 1.7      (modified)
    1390 
    1391         // observe m1 is now solo
    1392         printMariatheotokos(m3, *0p, 0);               // 3.7; 3.7; ;
    1393 
    1394         assert( &popped == &m3 );
    1395 }
    1396 
    1397 ////////////////////////////////////////////////////////////
    1398 //
    13991189// Section 5
    14001190//
     
    16321422        test__remove_of_sole__mary();
    16331423
    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 
    16721424        return 0;
    16731425}
Note: See TracChangeset for help on using the changeset viewer.