comparison nss/lib/base/error.c @ 0:1e5118fa0cb1

This is NSS with a Cmake Buildsyste To compile a static NSS library for Windows we've used the Chromium-NSS fork and added a Cmake buildsystem to compile it statically for Windows. See README.chromium for chromium changes and README.trustbridge for our modifications.
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 28 Jul 2014 10:47:06 +0200
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:1e5118fa0cb1
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 /*
6 * error.c
7 *
8 * This file contains the code implementing the per-thread error
9 * stacks upon which most NSS routines report their errors.
10 */
11
12 #ifndef BASE_H
13 #include "base.h"
14 #endif /* BASE_H */
15 #include <limits.h> /* for UINT_MAX */
16 #include <string.h> /* for memmove */
17
18 #define NSS_MAX_ERROR_STACK_COUNT 16 /* error codes */
19
20 /*
21 * The stack itself has a header, and a sequence of integers.
22 * The header records the amount of space (as measured in stack
23 * slots) already allocated for the stack, and the count of the
24 * number of records currently being used.
25 */
26
27 struct stack_header_str {
28 PRUint16 space;
29 PRUint16 count;
30 };
31
32 struct error_stack_str {
33 struct stack_header_str header;
34 PRInt32 stack[1];
35 };
36 typedef struct error_stack_str error_stack;
37
38 /*
39 * error_stack_index
40 *
41 * Thread-private data must be indexed. This is that index.
42 * See PR_NewThreadPrivateIndex for more information.
43 *
44 * Thread-private data indexes are in the range [0, 127].
45 */
46
47 #define INVALID_TPD_INDEX UINT_MAX
48 static PRUintn error_stack_index = INVALID_TPD_INDEX;
49
50 /*
51 * call_once
52 *
53 * The thread-private index must be obtained (once!) at runtime.
54 * This block is used for that one-time call.
55 */
56
57 static PRCallOnceType error_call_once;
58
59 /*
60 * error_once_function
61 *
62 * This is the once-called callback.
63 */
64 static PRStatus
65 error_once_function ( void)
66 {
67 return PR_NewThreadPrivateIndex(&error_stack_index, PR_Free);
68 }
69
70 /*
71 * error_get_my_stack
72 *
73 * This routine returns the calling thread's error stack, creating
74 * it if necessary. It may return NULL upon error, which implicitly
75 * means that it ran out of memory.
76 */
77
78 static error_stack *
79 error_get_my_stack ( void)
80 {
81 PRStatus st;
82 error_stack *rv;
83 PRUintn new_size;
84 PRUint32 new_bytes;
85 error_stack *new_stack;
86
87 if( INVALID_TPD_INDEX == error_stack_index ) {
88 st = PR_CallOnce(&error_call_once, error_once_function);
89 if( PR_SUCCESS != st ) {
90 return (error_stack *)NULL;
91 }
92 }
93
94 rv = (error_stack *)PR_GetThreadPrivate(error_stack_index);
95 if( (error_stack *)NULL == rv ) {
96 /* Doesn't exist; create one */
97 new_size = 16;
98 } else if( rv->header.count == rv->header.space &&
99 rv->header.count < NSS_MAX_ERROR_STACK_COUNT ) {
100 /* Too small, expand it */
101 new_size = PR_MIN( rv->header.space * 2, NSS_MAX_ERROR_STACK_COUNT);
102 } else {
103 /* Okay, return it */
104 return rv;
105 }
106
107 new_bytes = (new_size * sizeof(PRInt32)) + sizeof(error_stack);
108 /* Use NSPR's calloc/realloc, not NSS's, to avoid loops! */
109 new_stack = PR_Calloc(1, new_bytes);
110
111 if( (error_stack *)NULL != new_stack ) {
112 if( (error_stack *)NULL != rv ) {
113 (void)nsslibc_memcpy(new_stack,rv,rv->header.space);
114 }
115 new_stack->header.space = new_size;
116 }
117
118 /* Set the value, whether or not the allocation worked */
119 PR_SetThreadPrivate(error_stack_index, new_stack);
120 return new_stack;
121 }
122
123 /*
124 * The error stack
125 *
126 * The public methods relating to the error stack are:
127 *
128 * NSS_GetError
129 * NSS_GetErrorStack
130 *
131 * The nonpublic methods relating to the error stack are:
132 *
133 * nss_SetError
134 * nss_ClearErrorStack
135 *
136 */
137
138 /*
139 * NSS_GetError
140 *
141 * This routine returns the highest-level (most general) error set
142 * by the most recent NSS library routine called by the same thread
143 * calling this routine.
144 *
145 * This routine cannot fail. However, it may return zero, which
146 * indicates that the previous NSS library call did not set an error.
147 *
148 * Return value:
149 * 0 if no error has been set
150 * A nonzero error number
151 */
152
153 NSS_IMPLEMENT PRInt32
154 NSS_GetError ( void)
155 {
156 error_stack *es = error_get_my_stack();
157
158 if( (error_stack *)NULL == es ) {
159 return NSS_ERROR_NO_MEMORY; /* Good guess! */
160 }
161
162 if( 0 == es->header.count ) {
163 return 0;
164 }
165
166 return es->stack[ es->header.count-1 ];
167 }
168
169 /*
170 * NSS_GetErrorStack
171 *
172 * This routine returns a pointer to an array of integers, containing
173 * the entire sequence or "stack" of errors set by the most recent NSS
174 * library routine called by the same thread calling this routine.
175 * NOTE: the caller DOES NOT OWN the memory pointed to by the return
176 * value. The pointer will remain valid until the calling thread
177 * calls another NSS routine. The lowest-level (most specific) error
178 * is first in the array, and the highest-level is last. The array is
179 * zero-terminated. This routine may return NULL upon error; this
180 * indicates a low-memory situation.
181 *
182 * Return value:
183 * NULL upon error, which is an implied NSS_ERROR_NO_MEMORY
184 * A NON-caller-owned pointer to an array of integers
185 */
186
187 NSS_IMPLEMENT PRInt32 *
188 NSS_GetErrorStack ( void)
189 {
190 error_stack *es = error_get_my_stack();
191
192 if( (error_stack *)NULL == es ) {
193 return (PRInt32 *)NULL;
194 }
195
196 /* Make sure it's terminated */
197 es->stack[ es->header.count ] = 0;
198
199 return es->stack;
200 }
201
202 /*
203 * nss_SetError
204 *
205 * This routine places a new error code on the top of the calling
206 * thread's error stack. Calling this routine wiht an error code
207 * of zero will clear the error stack.
208 */
209
210 NSS_IMPLEMENT void
211 nss_SetError ( PRUint32 error)
212 {
213 error_stack *es;
214
215 if( 0 == error ) {
216 nss_ClearErrorStack();
217 return;
218 }
219
220 es = error_get_my_stack();
221 if( (error_stack *)NULL == es ) {
222 /* Oh, well. */
223 return;
224 }
225
226 if (es->header.count < es->header.space) {
227 es->stack[ es->header.count++ ] = error;
228 } else {
229 memmove(es->stack, es->stack + 1,
230 (es->header.space - 1) * (sizeof es->stack[0]));
231 es->stack[ es->header.space - 1 ] = error;
232 }
233 return;
234 }
235
236 /*
237 * nss_ClearErrorStack
238 *
239 * This routine clears the calling thread's error stack.
240 */
241
242 NSS_IMPLEMENT void
243 nss_ClearErrorStack ( void)
244 {
245 error_stack *es = error_get_my_stack();
246 if( (error_stack *)NULL == es ) {
247 /* Oh, well. */
248 return;
249 }
250
251 es->header.count = 0;
252 es->stack[0] = 0;
253 return;
254 }
255
256 /*
257 * nss_DestroyErrorStack
258 *
259 * This routine frees the calling thread's error stack.
260 */
261
262 NSS_IMPLEMENT void
263 nss_DestroyErrorStack ( void)
264 {
265 if( INVALID_TPD_INDEX != error_stack_index ) {
266 PR_SetThreadPrivate(error_stack_index, NULL);
267 }
268 return;
269 }
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)