blob: 0525caeeecc6b61654557f5e9e1118d42fde93e4 [file] [log] [blame]
Benny Prijono0a749f12005-10-31 21:02:30 +00001/* $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
22static 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
35PJ_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
48PJ_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
61PJ_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
71PJ_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
95PJ_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
111PJ_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 */
126PJ_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
135PJ_DEF(pj_status_t) pj_exception_id_free( pj_exception_id_t id )
136{
137 return PJ_SUCCESS;
138}
139
140PJ_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