Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/exception.c

    r381132b r80ec409  
    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 : Wed Aug 12 13:55:00 2020
     13// Update Count     : 21
    1414//
    1515
     
    2828#include <unwind.h>
    2929#include <bits/debug.hfa>
     30#include "concurrency/invoke.h"
    3031#include "stdhdr/assert.h"
    3132
     
    5960
    6061// Temperary global exception context. Does not work with concurency.
    61 struct exception_context_t {
    62         struct __cfaehm_try_resume_node * top_resume;
    63 
    64         exception_t * current_exception;
    65         int current_handler_index;
    66 } static shared_stack = {NULL, NULL, 0};
     62static struct exception_context_t shared_stack = {NULL, NULL};
    6763
    6864// Get the current exception context.
     
    122118
    123119// MEMORY MANAGEMENT =========================================================
     120
     121struct __cfaehm_node {
     122        struct _Unwind_Exception unwind_exception;
     123        struct __cfaehm_node * next;
     124        int handler_index;
     125};
     126
     127#define NODE_TO_EXCEPT(node) ((exception_t *)(1 + (node)))
     128#define EXCEPT_TO_NODE(except) ((struct __cfaehm_node *)(except) - 1)
     129#define UNWIND_TO_NODE(unwind) ((struct __cfaehm_node *)(unwind))
     130#define NULL_MAP(map, ptr) ((ptr) ? (map(ptr)) : NULL)
    124131
    125132// How to clean up an exception in various situations.
     
    137144}
    138145
    139 // We need a piece of storage to raise the exception, for now its a single
    140 // piece.
    141 static struct _Unwind_Exception this_exception_storage;
    142 
    143 struct __cfaehm_node {
    144         struct __cfaehm_node * next;
    145 };
    146 
    147 #define NODE_TO_EXCEPT(node) ((exception_t *)(1 + (node)))
    148 #define EXCEPT_TO_NODE(except) ((struct __cfaehm_node *)(except) - 1)
    149 
    150146// Creates a copy of the indicated exception and sets current_exception to it.
    151147static void __cfaehm_allocate_exception( exception_t * except ) {
     
    161157        }
    162158
     159        // Initialize the node:
     160        exception_t * except_store = NODE_TO_EXCEPT(store);
     161        store->unwind_exception.exception_class = __cfaehm_exception_class;
     162        store->unwind_exception.exception_cleanup = __cfaehm_exception_cleanup;
     163        store->handler_index = 0;
     164        except->virtual_table->copy( except_store, except );
     165
    163166        // Add the node to the list:
    164         store->next = EXCEPT_TO_NODE(context->current_exception);
    165         context->current_exception = NODE_TO_EXCEPT(store);
    166 
    167         // Copy the exception to storage.
    168         except->virtual_table->copy( context->current_exception, except );
    169 
    170         // Set up the exception storage.
    171         this_exception_storage.exception_class = __cfaehm_exception_class;
    172         this_exception_storage.exception_cleanup = __cfaehm_exception_cleanup;
     167        store->next = NULL_MAP(EXCEPT_TO_NODE, context->current_exception);
     168        context->current_exception = except_store;
    173169}
    174170
     
    185181        if ( context->current_exception == except ) {
    186182                node = to_free->next;
    187                 context->current_exception = (node) ? NODE_TO_EXCEPT(node) : 0;
     183                context->current_exception = NULL_MAP(NODE_TO_EXCEPT, node);
    188184        } else {
    189185                node = EXCEPT_TO_NODE(context->current_exception);
     
    213209        // Verify actions follow the rules we expect.
    214210        verify((actions & _UA_CLEANUP_PHASE) && (actions & _UA_FORCE_UNWIND));
    215         verify(!(actions & (_UA_SEARCH_PHASE | _UA_HANDER_FRAME)));
     211        verify(!(actions & (_UA_SEARCH_PHASE | _UA_HANDLER_FRAME)));
    216212
    217213        if ( actions & _UA_END_OF_STACK ) {
     
    222218}
    223219
     220static struct _Unwind_Exception cancel_exception_storage;
     221
    224222// Cancel the current stack, prefroming approprate clean-up and messaging.
    225223void __cfaehm_cancel_stack( exception_t * exception ) {
    226224        // TODO: Detect current stack and pick a particular stop-function.
    227225        _Unwind_Reason_Code ret;
    228         ret = _Unwind_ForcedUnwind( &this_exception_storage, _Stop_Fn, (void*)0x22 );
     226        ret = _Unwind_ForcedUnwind( &cancel_exception_storage, _Stop_Fn, (void*)0x22 );
    229227        printf("UNWIND ERROR %d after force unwind\n", ret);
    230228        abort();
     
    247245static void __cfaehm_begin_unwind(void(*defaultHandler)(exception_t *)) {
    248246        struct exception_context_t * context = this_exception_context();
    249         struct _Unwind_Exception * storage = &this_exception_storage;
    250247        if ( NULL == context->current_exception ) {
    251248                printf("UNWIND ERROR missing exception in begin unwind\n");
    252249                abort();
    253250        }
     251        struct _Unwind_Exception * storage =
     252                &EXCEPT_TO_NODE(context->current_exception)->unwind_exception;
    254253
    255254        // Call stdlibc to raise the exception
     
    419418                                _Unwind_Reason_Code ret = (0 == index)
    420419                                        ? _URC_CONTINUE_UNWIND : _URC_HANDLER_FOUND;
    421                                 context->current_handler_index = index;
     420                                UNWIND_TO_NODE(unwind_exception)->handler_index = index;
    422421
    423422                                // Based on the return value, check if we matched the exception
     
    425424                                        __cfadbg_print_safe(exception, " handler found\n");
    426425                                } else {
     426                                        // TODO: Continue the search if there is more in the table.
    427427                                        __cfadbg_print_safe(exception, " no handler\n");
    428428                                }
     
    516516        // Exception handler
    517517        // Note: Saving the exception context on the stack breaks termination exceptions.
    518         catch_block( this_exception_context()->current_handler_index,
     518        catch_block( EXCEPT_TO_NODE( this_exception_context()->current_exception )->handler_index,
    519519                     this_exception_context()->current_exception );
    520520}
Note: See TracChangeset for help on using the changeset viewer.