2 * Copyright (c) 2003-2006,2008,2010-2012 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
23 * nsprPortX.c - minimal platform dependent NSPR functions to enable
24 * use of DER libraries
27 #ifndef _NSPR_PORT_X_H_
28 #define _NSPR_PORT_X_H_
40 // MARK: *** Memory ***
42 NSPR_API(void *) PR_Malloc(PRSize size
)
44 return malloc(size
? size
: 1);
46 NSPR_API(void *) PR_Calloc(PRSize nelem
, PRSize elsize
)
48 return calloc(nelem
, elsize
);
50 NSPR_API(void *) PR_Realloc(void *ptr
, PRSize size
)
52 return realloc(ptr
, size
);
54 NSPR_API(void) PR_Free(void *ptr
)
59 // MARK: *** locks ***
61 NSPR_API(PRLock
*) PR_NewLock(void)
63 pthread_mutex_t
*pm
= PR_Malloc(sizeof(pthread_mutex_t
));
67 if(pthread_mutex_init(pm
, NULL
)) {
74 NSPR_API(void) PR_DestroyLock(PRLock
*lock
)
79 pthread_mutex_destroy((pthread_mutex_t
*)lock
);
83 NSPR_API(void) PR_Lock(PRLock
*lock
)
88 pthread_mutex_lock((pthread_mutex_t
*)lock
);
91 NSPR_API(PRStatus
) PR_Unlock(PRLock
*lock
)
96 pthread_mutex_unlock((pthread_mutex_t
*)lock
);
100 // MARK: *** get/set error ***
103 * key for pthread_{set,get}specific and a lock to ensure it gets
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
;
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.
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()).
128 static PRInt32
PR_initThreadKey(
132 if(PR_threadKeyInitFlag
) {
133 /* thread safe since we never clear this flag; we're ready to go */
136 pthread_mutex_lock(&PR_threadKeyLock
);
137 if(PR_threadKeyErrorFlag
&& !doCreate
) {
138 /* no error to get because the last SetXError failed */
141 else if(!PR_threadKeyInitFlag
) {
142 prtn
= pthread_key_create(&PR_threadKey
, free
);
144 /* out of pthread_key_t's */
145 PR_threadKeyErrorFlag
= 1;
148 PR_threadKeyErrorFlag
= 0; // in case of retry */
149 PR_threadKeyInitFlag
= 1; // success
152 pthread_mutex_unlock(&PR_threadKeyLock
);
157 * Get current thread's PR_threadErrInfo. Create one if doCreate is
158 * true and one does not exist.
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
166 static PR_threadErrInfo
*PR_getThreadErrInfo(
168 PRInt32
*threadKeyError
) // RETURNED, an OSStatus
170 *threadKeyError
= PR_initThreadKey(doCreate
);
171 if(*threadKeyError
) {
174 PR_threadErrInfo
*errInfo
= pthread_getspecific(PR_threadKey
);
175 if((errInfo
== NULL
) && doCreate
) {
176 errInfo
= (PR_threadErrInfo
*)malloc(sizeof(*errInfo
));
177 if(errInfo
== NULL
) {
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
186 *threadKeyError
= PR_OUT_OF_MEMORY_ERROR
;
189 memset(errInfo
, 0, sizeof(*errInfo
));
190 pthread_setspecific(PR_threadKey
, errInfo
);
196 PR_IMPLEMENT(PRErrorCode
) PR_GetError(void)
199 PR_threadErrInfo
*errInfo
= PR_getThreadErrInfo(0, &prtn
);
200 if(errInfo
== NULL
) {
201 /* no error set or per-thread logic uninitialized */
203 return PR_INSUFFICIENT_RESOURCES_ERROR
;
210 return errInfo
->prError
;
214 PR_IMPLEMENT(PRInt32
) PR_GetOSError(void)
217 PR_threadErrInfo
*errInfo
= PR_getThreadErrInfo(0, &prtn
);
218 if(errInfo
== NULL
) {
219 /* no error set or per-thread logic uninitialized */
223 return errInfo
->osError
;
227 PR_IMPLEMENT(void) PR_SetError(PRErrorCode code
, PRInt32 osErr
)
230 PR_threadErrInfo
*errInfo
= PR_getThreadErrInfo(1, &prtn
);
231 if(errInfo
!= NULL
) {
232 errInfo
->osError
= osErr
;
233 errInfo
->prError
= code
;
235 /* else per-thread logic uninitialized */
238 // MARK: *** misc. ***
241 ** Compute the log of the least power of 2 greater than or equal to n
243 NSPR_API(PRIntn
) PR_CeilingLog2(PRUint32 i
)
246 PR_CEILING_LOG2(r
,i
);
250 #endif /* _NSPR_PORT_X_H_ */