Benny Prijono | 0a749f1 | 2005-10-31 21:02:30 +0000 | [diff] [blame^] | 1 | /* $Header: /pjproject-0.3/pjlib/src/pj/except.c 6 10/14/05 12:26a Bennylp $ */
|
| 2 | /*
|
| 3 | * $Log: /pjproject-0.3/pjlib/src/pj/except.c $
|
| 4 | *
|
| 5 | * 6 10/14/05 12:26a Bennylp
|
| 6 | * Finished error code framework, some fixes in ioqueue, etc. Pretty
|
| 7 | * major.
|
| 8 | *
|
| 9 | * 5 9/21/05 1:39p Bennylp
|
| 10 | * Periodic checkin for backup.
|
| 11 | *
|
| 12 | * 4 9/17/05 10:37a Bennylp
|
| 13 | * Major reorganization towards version 0.3.
|
| 14 | *
|
| 15 | */
|
| 16 | #include <pj/except.h>
|
| 17 | #include <pj/os.h>
|
| 18 | #include <pj/assert.h>
|
| 19 | #include <pj/log.h>
|
| 20 | #include <pj/errno.h>
|
| 21 |
|
| 22 | static long thread_local_id = -1;
|
| 23 |
|
| 24 | #if defined(PJ_HAS_EXCEPTION_NAMES) && PJ_HAS_EXCEPTION_NAMES != 0
|
| 25 | static const char *exception_id_names[PJ_MAX_EXCEPTION_ID];
|
| 26 | #else
|
| 27 | /*
|
| 28 | * Start from 1 (not 0)!!!
|
| 29 | * Exception 0 is reserved for normal path of setjmp()!!!
|
| 30 | */
|
| 31 | static int last_exception_id = 1;
|
| 32 | #endif /* PJ_HAS_EXCEPTION_NAMES */
|
| 33 |
|
| 34 |
|
| 35 | PJ_DEF(void) pj_throw_exception_(int exception_id)
|
| 36 | {
|
| 37 | struct pj_exception_state_t *handler;
|
| 38 |
|
| 39 | handler = pj_thread_local_get(thread_local_id);
|
| 40 | if (handler == NULL) {
|
| 41 | PJ_LOG(1,("except.c", "!!!FATAL: unhandled exception %d!\n", exception_id));
|
| 42 | pj_assert(handler != NULL);
|
| 43 | /* This will crash the system! */
|
| 44 | }
|
| 45 | pj_longjmp(handler->state, exception_id);
|
| 46 | }
|
| 47 |
|
| 48 | PJ_DEF(void) pj_push_exception_handler_(struct pj_exception_state_t *rec)
|
| 49 | {
|
| 50 | struct pj_exception_state_t *parent_handler = NULL;
|
| 51 |
|
| 52 | if (thread_local_id == -1) {
|
| 53 | pj_thread_local_alloc(&thread_local_id);
|
| 54 | pj_assert(thread_local_id != -1);
|
| 55 | }
|
| 56 | parent_handler = pj_thread_local_get(thread_local_id);
|
| 57 | rec->prev = parent_handler;
|
| 58 | pj_thread_local_set(thread_local_id, rec);
|
| 59 | }
|
| 60 |
|
| 61 | PJ_DEF(void) pj_pop_exception_handler_(void)
|
| 62 | {
|
| 63 | struct pj_exception_state_t *handler;
|
| 64 |
|
| 65 | handler = pj_thread_local_get(thread_local_id);
|
| 66 | pj_assert(handler != NULL);
|
| 67 | pj_thread_local_set(thread_local_id, handler->prev);
|
| 68 | }
|
| 69 |
|
| 70 | #if defined(PJ_HAS_EXCEPTION_NAMES) && PJ_HAS_EXCEPTION_NAMES != 0
|
| 71 | PJ_DEF(pj_status_t) pj_exception_id_alloc( const char *name,
|
| 72 | pj_exception_id_t *id)
|
| 73 | {
|
| 74 | unsigned i;
|
| 75 |
|
| 76 | pj_enter_critical_section();
|
| 77 |
|
| 78 | /*
|
| 79 | * Start from 1 (not 0)!!!
|
| 80 | * Exception 0 is reserved for normal path of setjmp()!!!
|
| 81 | */
|
| 82 | for (i=1; i<PJ_MAX_EXCEPTION_ID; ++i) {
|
| 83 | if (exception_id_names[i] == NULL) {
|
| 84 | exception_id_names[i] = name;
|
| 85 | *id = i;
|
| 86 | pj_leave_critical_section();
|
| 87 | return PJ_SUCCESS;
|
| 88 | }
|
| 89 | }
|
| 90 |
|
| 91 | pj_leave_critical_section();
|
| 92 | return PJ_ETOOMANY;
|
| 93 | }
|
| 94 |
|
| 95 | PJ_DEF(pj_status_t) pj_exception_id_free( pj_exception_id_t id )
|
| 96 | {
|
| 97 | /*
|
| 98 | * Start from 1 (not 0)!!!
|
| 99 | * Exception 0 is reserved for normal path of setjmp()!!!
|
| 100 | */
|
| 101 | PJ_ASSERT_RETURN(id>0 && id<PJ_MAX_EXCEPTION_ID, PJ_EINVAL);
|
| 102 |
|
| 103 | pj_enter_critical_section();
|
| 104 | exception_id_names[id] = NULL;
|
| 105 | pj_leave_critical_section();
|
| 106 |
|
| 107 | return PJ_SUCCESS;
|
| 108 |
|
| 109 | }
|
| 110 |
|
| 111 | PJ_DEF(const char*) pj_exception_id_name(pj_exception_id_t id)
|
| 112 | {
|
| 113 | /*
|
| 114 | * Start from 1 (not 0)!!!
|
| 115 | * Exception 0 is reserved for normal path of setjmp()!!!
|
| 116 | */
|
| 117 | PJ_ASSERT_RETURN(id>0 && id<PJ_MAX_EXCEPTION_ID, "<Invalid ID>");
|
| 118 |
|
| 119 | if (exception_id_names[id] == NULL)
|
| 120 | return "<Unallocated ID>";
|
| 121 |
|
| 122 | return exception_id_names[id];
|
| 123 | }
|
| 124 |
|
| 125 | #else /* PJ_HAS_EXCEPTION_NAMES */
|
| 126 | PJ_DEF(pj_status_t) pj_exception_id_alloc( const char *name,
|
| 127 | pj_exception_id_t *id)
|
| 128 | {
|
| 129 | PJ_ASSERT_RETURN(last_exception_id < PJ_MAX_EXCEPTION_ID-1, PJ_ETOOMANY);
|
| 130 |
|
| 131 | *id = last_exception_id++
|
| 132 | return PJ_SUCCESS;
|
| 133 | }
|
| 134 |
|
| 135 | PJ_DEF(pj_status_t) pj_exception_id_free( pj_exception_id_t id )
|
| 136 | {
|
| 137 | return PJ_SUCCESS;
|
| 138 | }
|
| 139 |
|
| 140 | PJ_DEF(const char*) pj_exception_id_name(pj_exception_id_t id)
|
| 141 | {
|
| 142 | return "";
|
| 143 | }
|
| 144 |
|
| 145 | #endif /* PJ_HAS_EXCEPTION_NAMES */
|
| 146 |
|
| 147 |
|
| 148 |
|