]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 | 1 | /* |
d8f41ccd | 2 | * Copyright (c) 2003-2006,2008,2010-2012 Apple Inc. All Rights Reserved. |
b1ab9ed8 A |
3 | * |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * This file contains Original Code and/or Modifications of Original Code | |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. Please obtain a copy of the License at | |
10 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
11 | * file. | |
12 | * | |
13 | * The Original Code and all software distributed under the License are | |
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
18 | * Please see the License for the specific language governing rights and | |
19 | * limitations under the License. | |
20 | * | |
21 | * @APPLE_LICENSE_HEADER_END@ | |
22 | * | |
23 | * nsprPortX.c - minimal platform dependent NSPR functions to enable | |
24 | * use of DER libraries | |
25 | */ | |
26 | ||
27 | #ifndef _NSPR_PORT_X_H_ | |
28 | #define _NSPR_PORT_X_H_ | |
29 | ||
30 | #include "prmem.h" | |
31 | #include "prlock.h" | |
32 | #include "prerror.h" | |
33 | #include "prinit.h" | |
34 | #include "prbit.h" | |
35 | ||
36 | #include <stdlib.h> | |
37 | #include <pthread.h> | |
38 | #include <string.h> | |
39 | ||
427c49bc | 40 | // MARK: *** Memory *** |
b1ab9ed8 A |
41 | |
42 | NSPR_API(void *) PR_Malloc(PRSize size) | |
43 | { | |
44 | return malloc(size ? size : 1); | |
45 | } | |
46 | NSPR_API(void *) PR_Calloc(PRSize nelem, PRSize elsize) | |
47 | { | |
48 | return calloc(nelem, elsize); | |
49 | } | |
50 | NSPR_API(void *) PR_Realloc(void *ptr, PRSize size) | |
51 | { | |
52 | return realloc(ptr, size); | |
53 | } | |
54 | NSPR_API(void) PR_Free(void *ptr) | |
55 | { | |
56 | return free(ptr); | |
57 | } | |
58 | ||
427c49bc | 59 | // MARK: *** locks *** |
b1ab9ed8 A |
60 | |
61 | NSPR_API(PRLock*) PR_NewLock(void) | |
62 | { | |
63 | pthread_mutex_t *pm = PR_Malloc(sizeof(pthread_mutex_t)); | |
64 | if(pm == NULL) { | |
65 | return NULL; | |
66 | } | |
67 | if(pthread_mutex_init(pm, NULL)) { | |
68 | PR_Free(pm); | |
69 | return NULL; | |
70 | } | |
71 | return (PRLock*)pm; | |
72 | } | |
73 | ||
74 | NSPR_API(void) PR_DestroyLock(PRLock *lock) | |
75 | { | |
76 | if(lock == NULL) { | |
77 | return; | |
78 | } | |
79 | pthread_mutex_destroy((pthread_mutex_t *)lock); | |
80 | PR_Free(lock); | |
81 | } | |
82 | ||
83 | NSPR_API(void) PR_Lock(PRLock *lock) | |
84 | { | |
85 | if(lock == NULL) { | |
86 | return; | |
87 | } | |
88 | pthread_mutex_lock((pthread_mutex_t *)lock); | |
89 | } | |
90 | ||
91 | NSPR_API(PRStatus) PR_Unlock(PRLock *lock) | |
92 | { | |
93 | if(lock == NULL) { | |
94 | return PR_FAILURE; | |
95 | } | |
96 | pthread_mutex_unlock((pthread_mutex_t *)lock); | |
97 | return PR_SUCCESS; | |
98 | } | |
99 | ||
427c49bc | 100 | // MARK: *** get/set error *** |
b1ab9ed8 A |
101 | |
102 | /* | |
103 | * key for pthread_{set,get}specific and a lock to ensure it gets | |
104 | * created once | |
105 | */ | |
106 | static pthread_key_t PR_threadKey; | |
107 | static int PR_threadKeyInitFlag; // we have a PR_threadKey | |
108 | static int PR_threadKeyErrorFlag; // unable to create PR_threadKey | |
109 | static pthread_mutex_t PR_threadKeyLock = PTHREAD_MUTEX_INITIALIZER; | |
110 | ||
111 | /* | |
112 | * The thing that gets stored on a per-thread basis. A pointer to | |
113 | * this is associated with key PR_threadKey. Mallocd in | |
114 | * PR_getThreadErrInfo(); freed directly by free() as | |
115 | * PR_threadKey's destructor. | |
116 | */ | |
117 | typedef struct { | |
118 | PRInt32 osError; | |
119 | PRErrorCode prError; | |
120 | } PR_threadErrInfo; | |
121 | ||
122 | /* | |
123 | * One-time init of PR_threadKey, returns nonzero on error. | |
124 | * Does not attempt to init PR_threadKey if doCreate is false and | |
125 | * a previous call to this routine resulted in error (i.e., this | |
126 | * is the GetXError() following a failed SetError()). | |
127 | */ | |
128 | static PRInt32 PR_initThreadKey( | |
129 | int doCreate) | |
130 | { | |
131 | PRInt32 prtn = 0; | |
132 | if(PR_threadKeyInitFlag) { | |
133 | /* thread safe since we never clear this flag; we're ready to go */ | |
134 | return 0; | |
135 | } | |
136 | pthread_mutex_lock(&PR_threadKeyLock); | |
137 | if(PR_threadKeyErrorFlag && !doCreate) { | |
138 | /* no error to get because the last SetXError failed */ | |
139 | prtn = PR_IO_ERROR; | |
140 | } | |
141 | else if(!PR_threadKeyInitFlag) { | |
142 | prtn = pthread_key_create(&PR_threadKey, free); | |
143 | if(prtn) { | |
144 | /* out of pthread_key_t's */ | |
145 | PR_threadKeyErrorFlag = 1; | |
146 | } | |
147 | else { | |
148 | PR_threadKeyErrorFlag = 0; // in case of retry */ | |
149 | PR_threadKeyInitFlag = 1; // success | |
150 | } | |
151 | } | |
152 | pthread_mutex_unlock(&PR_threadKeyLock); | |
153 | return prtn; | |
154 | } | |
155 | ||
156 | /* | |
157 | * Get current thread's PR_threadErrInfo. Create one if doCreate is | |
158 | * true and one does not exist. | |
159 | * | |
160 | * -- A nonzero *threadKeyError on return indicates that we can | |
161 | * not create a pthread_key_t; in this case we return NULL. | |
162 | * -- Note that NULL return with zero threadKeyError and zero | |
163 | * doCreate indicates "no per-thread error set yet", which is | |
164 | * not an error. | |
165 | */ | |
166 | static PR_threadErrInfo *PR_getThreadErrInfo( | |
167 | int doCreate, | |
168 | PRInt32 *threadKeyError) // RETURNED, an OSStatus | |
169 | { | |
170 | *threadKeyError = PR_initThreadKey(doCreate); | |
171 | if(*threadKeyError) { | |
172 | return NULL; | |
173 | } | |
174 | PR_threadErrInfo *errInfo = pthread_getspecific(PR_threadKey); | |
175 | if((errInfo == NULL) && doCreate) { | |
176 | errInfo = (PR_threadErrInfo *)malloc(sizeof(*errInfo)); | |
177 | if(errInfo == NULL) { | |
178 | /* | |
179 | * malloc failure, retriable failure of this routine (not | |
180 | * a PR_threadKeyErrorFlag style error). | |
181 | * Note that this is *not* detected in a subsequent | |
182 | * GetXError() call, but it will allow for somewhat | |
183 | * graceful recovery in case some memory gets freed | |
184 | * up. | |
185 | */ | |
186 | *threadKeyError = PR_OUT_OF_MEMORY_ERROR; | |
187 | } | |
188 | else { | |
189 | memset(errInfo, 0, sizeof(*errInfo)); | |
190 | pthread_setspecific(PR_threadKey, errInfo); | |
191 | } | |
192 | } | |
193 | return errInfo; | |
194 | } | |
195 | ||
196 | PR_IMPLEMENT(PRErrorCode) PR_GetError(void) | |
197 | { | |
198 | PRInt32 prtn; | |
199 | PR_threadErrInfo *errInfo = PR_getThreadErrInfo(0, &prtn); | |
200 | if(errInfo == NULL) { | |
201 | /* no error set or per-thread logic uninitialized */ | |
202 | if(prtn) { | |
203 | return PR_INSUFFICIENT_RESOURCES_ERROR; | |
204 | } | |
205 | else { | |
206 | return 0; | |
207 | } | |
208 | } | |
209 | else { | |
210 | return errInfo->prError; | |
211 | } | |
212 | } | |
213 | ||
214 | PR_IMPLEMENT(PRInt32) PR_GetOSError(void) | |
215 | { | |
216 | PRInt32 prtn; | |
217 | PR_threadErrInfo *errInfo = PR_getThreadErrInfo(0, &prtn); | |
218 | if(errInfo == NULL) { | |
219 | /* no error set or per-thread logic uninitialized */ | |
220 | return prtn; | |
221 | } | |
222 | else { | |
223 | return errInfo->osError; | |
224 | } | |
225 | } | |
226 | ||
227 | PR_IMPLEMENT(void) PR_SetError(PRErrorCode code, PRInt32 osErr) | |
228 | { | |
229 | PRInt32 prtn; | |
230 | PR_threadErrInfo *errInfo = PR_getThreadErrInfo(1, &prtn); | |
231 | if(errInfo != NULL) { | |
232 | errInfo->osError = osErr; | |
233 | errInfo->prError = code; | |
234 | } | |
235 | /* else per-thread logic uninitialized */ | |
236 | } | |
237 | ||
427c49bc | 238 | // MARK: *** misc. *** |
b1ab9ed8 A |
239 | |
240 | /* | |
241 | ** Compute the log of the least power of 2 greater than or equal to n | |
242 | */ | |
243 | NSPR_API(PRIntn) PR_CeilingLog2(PRUint32 i) | |
244 | { | |
245 | PRIntn r; | |
246 | PR_CEILING_LOG2(r,i); | |
247 | return r; | |
248 | } | |
249 | ||
250 | #endif /* _NSPR_PORT_X_H_ */ |