Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/libcfa/exception.c

    rcbce272 rb947fb2  
    99// Author           : Andrew Beach
    1010// Created On       : Mon Jun 26 15:13:00 2017
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Aug  4 15:20:00 2017
    13 // Update Count     : 6
    14 //
    15 
    16 #include <stddef.h> // for size_t
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Wed Jul 26 10:37:51 2017
     13// Update Count     : 2
     14//
    1715
    1816#include "exception.h"
     
    3432#include "lsda.h"
    3533
    36 
    37 // Base exception vtable is abstract, you should not have base exceptions.
    38 struct __cfaehm__base_exception_t_vtable
    39                 ___cfaehm__base_exception_t_vtable_instance = {
    40         .parent = NULL,
    41         .size = 0,
    42         .copy = NULL,
    43         .free = NULL,
    44         .msg = NULL
    45 };
    46 
    47 
    4834// Temperary global exception context. Does not work with concurency.
    49 struct exception_context_t {
     35struct shared_stack_t {
    5036    struct __cfaehm__try_resume_node * top_resume;
    5137    struct __cfaehm__try_resume_node * current_resume;
    5238
    53     exception * current_exception;
     39    exception current_exception;
    5440    int current_handler_index;
    5541} shared_stack = {NULL, NULL, 0, 0};
    5642
    57 // Get the current exception context.
    58 // There can be a single global until multithreading occurs, then each stack
    59 // needs its own. It will have to be updated to handle that.
    60 struct exception_context_t * this_exception_context() {
    61         return &shared_stack;
    62 }
    63 //#define SAVE_EXCEPTION_CONTEXT(to_name)
    64 //struct exception_context_t * to_name = this_exception_context();
    65 //exception * this_exception() {
    66 //    return this_exception_context()->current_exception;
    67 //}
    6843
    6944
     
    8055
    8156        // DEBUG
    82         printf("Throwing resumption exception\n");
     57        printf("Throwing resumption exception %d\n", *except);
    8358
    8459        struct __cfaehm__try_resume_node * original_head = shared_stack.current_resume;
     
    9469        }
    9570
    96         printf("Unhandled exception\n");
     71        printf("Unhandled exception %d\n", *except);
    9772        shared_stack.current_resume = original_head;
    9873
     
    11994// TERMINATION ===============================================================
    12095
    121 // MEMORY MANAGEMENT (still for integers)
    122 // May have to move to cfa for constructors and destructors (references).
    123 
    124 struct __cfaehm__node {
    125         struct __cfaehm__node * next;
    126 };
    127 
    128 #define NODE_TO_EXCEPT(node) ((exception *)(1 + (node)))
    129 #define EXCEPT_TO_NODE(except) ((struct __cfaehm__node *)(except) - 1)
    130 
    131 // Creates a copy of the indicated exception and sets current_exception to it.
    132 static void __cfaehm__allocate_exception( exception * except ) {
    133         struct exception_context_t * context = this_exception_context();
    134 
    135         // Allocate memory for the exception.
    136         struct __cfaehm__node * store = malloc(
    137                 sizeof( struct __cfaehm__node ) + except->virtual_table->size );
    138 
    139         if ( ! store ) {
    140                 // Failure: cannot allocate exception. Terminate thread.
    141                 abort(); // <- Although I think it might be the process.
    142         }
    143 
    144         // Add the node to the list:
    145         store->next = EXCEPT_TO_NODE(context->current_exception);
    146         context->current_exception = NODE_TO_EXCEPT(store);
    147 
    148         // Copy the exception to storage.
    149         except->virtual_table->copy( context->current_exception, except );
    150 }
    151 
    152 // Delete the provided exception, unsetting current_exception if relivant.
    153 static void __cfaehm__delete_exception( exception * except ) {
    154         struct exception_context_t * context = this_exception_context();
    155 
    156         // DEBUG
    157         printf( "Deleting Exception\n");
    158 
    159         // Remove the exception from the list.
    160         struct __cfaehm__node * to_free = EXCEPT_TO_NODE(except);
    161         struct __cfaehm__node * node;
    162 
    163         if ( context->current_exception == except ) {
    164                 node = to_free->next;
    165                 context->current_exception = (node) ? NODE_TO_EXCEPT(node) : 0;
    166         } else {
    167                 node = EXCEPT_TO_NODE(context->current_exception);
    168                 // It may always be in the first or second position.
    169                 while( to_free != node->next ) {
    170                         node = node->next;
    171                 }
    172                 node->next = to_free->next;
    173         }
    174 
    175         // Free the old exception node.
    176         except->virtual_table->free( except );
    177         free( to_free );
    178 }
    179 
    180 // If this isn't a rethrow (*except==0), delete the provided exception.
    181 void __cfaehm__cleanup_terminate( void * except ) {
    182         if ( *(void**)except ) __cfaehm__delete_exception( *(exception**)except );
    183 }
    184 
     96// Requires -fexceptions to work.
     97
     98// Global which defines the current exception.  Currently an int just to make matching easier.
     99//int this_exception; (became shared_stack.current_exception)
    185100
    186101// We need a piece of storage to raise the exception
     
    202117}
    203118
    204 // The exception that is being thrown must already be stored.
    205 __attribute__((noreturn)) void __cfaehm__begin_unwind(void) {
    206         if ( ! this_exception_context()->current_exception ) {
    207                 printf("UNWIND ERROR missing exception in begin unwind\n");
    208                 abort();
    209         }
    210 
     119void __cfaehm__throw_terminate( exception * val ) {
     120        // Store the current exception
     121        shared_stack.current_exception = *val;
     122
     123        // DEBUG
     124        printf("Throwing termination exception %d\n", *val);
    211125
    212126        // Call stdlibc to raise the exception
     
    234148}
    235149
    236 void __cfaehm__throw_terminate( exception * val ) {
    237         // DEBUG
    238         printf("Throwing termination exception\n");
    239 
    240         __cfaehm__allocate_exception( val );
    241         __cfaehm__begin_unwind();
    242 }
    243 
     150// Nesting this the other way would probably be faster.
    244151void __cfaehm__rethrow_terminate(void) {
    245152        // DEBUG
    246153        printf("Rethrowing termination exception\n");
    247154
    248         __cfaehm__begin_unwind();
     155        __cfaehm__throw_terminate(&shared_stack.current_exception);
    249156}
    250157
     
    356263                                        _Unwind_Reason_Code (*matcher)(exception *) =
    357264                                                MATCHER_FROM_CONTEXT(context);
    358                                         int index = matcher(shared_stack.current_exception);
     265                                        int index = matcher(&shared_stack.current_exception);
    359266                                        _Unwind_Reason_Code ret = (0 == index)
    360267                                                ? _URC_CONTINUE_UNWIND : _URC_HANDLER_FOUND;
     
    452359        // Exception handler
    453360        catch_block( shared_stack.current_handler_index,
    454                      shared_stack.current_exception );
     361                    &shared_stack.current_exception );
    455362}
    456363
Note: See TracChangeset for help on using the changeset viewer.