Mercurial > trustbridge > nss-cmake-static
comparison nss/lib/base/tracker.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 * tracker.c | |
7 * | |
8 * This file contains the code used by the pointer-tracking calls used | |
9 * in the debug builds to catch bad pointers. The entire contents are | |
10 * only available in debug builds (both internal and external builds). | |
11 */ | |
12 | |
13 #ifndef BASE_H | |
14 #include "base.h" | |
15 #endif /* BASE_H */ | |
16 | |
17 #ifdef DEBUG | |
18 /* | |
19 * identity_hash | |
20 * | |
21 * This static callback is a PLHashFunction as defined in plhash.h | |
22 * It merely returns the value of the object pointer as its hash. | |
23 * There are no possible errors. | |
24 */ | |
25 | |
26 static PLHashNumber PR_CALLBACK | |
27 identity_hash | |
28 ( | |
29 const void *key | |
30 ) | |
31 { | |
32 return (PLHashNumber)key; | |
33 } | |
34 | |
35 /* | |
36 * trackerOnceFunc | |
37 * | |
38 * This function is called once, using the nssCallOnce function above. | |
39 * It creates a new pointer tracker object; initialising its hash | |
40 * table and protective lock. | |
41 */ | |
42 | |
43 static PRStatus | |
44 trackerOnceFunc | |
45 ( | |
46 void *arg | |
47 ) | |
48 { | |
49 nssPointerTracker *tracker = (nssPointerTracker *)arg; | |
50 | |
51 tracker->lock = PZ_NewLock(nssILockOther); | |
52 if( (PZLock *)NULL == tracker->lock ) { | |
53 return PR_FAILURE; | |
54 } | |
55 | |
56 tracker->table = PL_NewHashTable(0, | |
57 identity_hash, | |
58 PL_CompareValues, | |
59 PL_CompareValues, | |
60 (PLHashAllocOps *)NULL, | |
61 (void *)NULL); | |
62 if( (PLHashTable *)NULL == tracker->table ) { | |
63 PZ_DestroyLock(tracker->lock); | |
64 tracker->lock = (PZLock *)NULL; | |
65 return PR_FAILURE; | |
66 } | |
67 | |
68 return PR_SUCCESS; | |
69 } | |
70 | |
71 /* | |
72 * nssPointerTracker_initialize | |
73 * | |
74 * This method is only present in debug builds. | |
75 * | |
76 * This routine initializes an nssPointerTracker object. Note that | |
77 * the object must have been declared *static* to guarantee that it | |
78 * is in a zeroed state initially. This routine is idempotent, and | |
79 * may even be safely called by multiple threads simultaneously with | |
80 * the same argument. This routine returns a PRStatus value; if | |
81 * successful, it will return PR_SUCCESS. On failure it will set an | |
82 * error on the error stack and return PR_FAILURE. | |
83 * | |
84 * The error may be one of the following values: | |
85 * NSS_ERROR_NO_MEMORY | |
86 * | |
87 * Return value: | |
88 * PR_SUCCESS | |
89 * PR_FAILURE | |
90 */ | |
91 | |
92 NSS_IMPLEMENT PRStatus | |
93 nssPointerTracker_initialize | |
94 ( | |
95 nssPointerTracker *tracker | |
96 ) | |
97 { | |
98 PRStatus rv = PR_CallOnceWithArg(&tracker->once, trackerOnceFunc, tracker); | |
99 if( PR_SUCCESS != rv ) { | |
100 nss_SetError(NSS_ERROR_NO_MEMORY); | |
101 } | |
102 | |
103 return rv; | |
104 } | |
105 | |
106 #ifdef DONT_DESTROY_EMPTY_TABLES | |
107 /* See same #ifdef below */ | |
108 /* | |
109 * count_entries | |
110 * | |
111 * This static routine is a PLHashEnumerator, as defined in plhash.h. | |
112 * It merely causes the enumeration function to count the number of | |
113 * entries. | |
114 */ | |
115 | |
116 static PRIntn PR_CALLBACK | |
117 count_entries | |
118 ( | |
119 PLHashEntry *he, | |
120 PRIntn index, | |
121 void *arg | |
122 ) | |
123 { | |
124 return HT_ENUMERATE_NEXT; | |
125 } | |
126 #endif /* DONT_DESTROY_EMPTY_TABLES */ | |
127 | |
128 /* | |
129 * zero_once | |
130 * | |
131 * This is a guaranteed zeroed once block. It's used to help clear | |
132 * the tracker. | |
133 */ | |
134 | |
135 static const PRCallOnceType zero_once; | |
136 | |
137 /* | |
138 * nssPointerTracker_finalize | |
139 * | |
140 * This method is only present in debug builds. | |
141 * | |
142 * This routine returns the nssPointerTracker object to the pre- | |
143 * initialized state, releasing all resources used by the object. | |
144 * It will *NOT* destroy the objects being tracked by the pointer | |
145 * (should any remain), and therefore cannot be used to "sweep up" | |
146 * remaining objects. This routine returns a PRStatus value; if | |
147 * successful, it will return PR_SUCCES. On failure it will set an | |
148 * error on the error stack and return PR_FAILURE. If any objects | |
149 * remain in the tracker when it is finalized, that will be treated | |
150 * as an error. | |
151 * | |
152 * The error may be one of the following values: | |
153 * NSS_ERROR_INVALID_POINTER | |
154 * NSS_ERROR_TRACKER_NOT_INITIALIZED | |
155 * NSS_ERROR_TRACKER_NOT_EMPTY | |
156 * | |
157 * Return value: | |
158 * PR_SUCCESS | |
159 * PR_FAILURE | |
160 */ | |
161 | |
162 NSS_IMPLEMENT PRStatus | |
163 nssPointerTracker_finalize | |
164 ( | |
165 nssPointerTracker *tracker | |
166 ) | |
167 { | |
168 PZLock *lock; | |
169 | |
170 if( (nssPointerTracker *)NULL == tracker ) { | |
171 nss_SetError(NSS_ERROR_INVALID_POINTER); | |
172 return PR_FAILURE; | |
173 } | |
174 | |
175 if( (PZLock *)NULL == tracker->lock ) { | |
176 nss_SetError(NSS_ERROR_TRACKER_NOT_INITIALIZED); | |
177 return PR_FAILURE; | |
178 } | |
179 | |
180 lock = tracker->lock; | |
181 PZ_Lock(lock); | |
182 | |
183 if( (PLHashTable *)NULL == tracker->table ) { | |
184 PZ_Unlock(lock); | |
185 nss_SetError(NSS_ERROR_TRACKER_NOT_INITIALIZED); | |
186 return PR_FAILURE; | |
187 } | |
188 | |
189 #ifdef DONT_DESTROY_EMPTY_TABLES | |
190 /* | |
191 * I changed my mind; I think we don't want this after all. | |
192 * Comments? | |
193 */ | |
194 count = PL_HashTableEnumerateEntries(tracker->table, | |
195 count_entries, | |
196 (void *)NULL); | |
197 | |
198 if( 0 != count ) { | |
199 PZ_Unlock(lock); | |
200 nss_SetError(NSS_ERROR_TRACKER_NOT_EMPTY); | |
201 return PR_FAILURE; | |
202 } | |
203 #endif /* DONT_DESTROY_EMPTY_TABLES */ | |
204 | |
205 PL_HashTableDestroy(tracker->table); | |
206 /* memset(tracker, 0, sizeof(nssPointerTracker)); */ | |
207 tracker->once = zero_once; | |
208 tracker->lock = (PZLock *)NULL; | |
209 tracker->table = (PLHashTable *)NULL; | |
210 | |
211 PZ_Unlock(lock); | |
212 PZ_DestroyLock(lock); | |
213 | |
214 return PR_SUCCESS; | |
215 } | |
216 | |
217 /* | |
218 * nssPointerTracker_add | |
219 * | |
220 * This method is only present in debug builds. | |
221 * | |
222 * This routine adds the specified pointer to the nssPointerTracker | |
223 * object. It should be called in constructor objects to register | |
224 * new valid objects. The nssPointerTracker is threadsafe, but this | |
225 * call is not idempotent. This routine returns a PRStatus value; | |
226 * if successful it will return PR_SUCCESS. On failure it will set | |
227 * an error on the error stack and return PR_FAILURE. | |
228 * | |
229 * The error may be one of the following values: | |
230 * NSS_ERROR_INVALID_POINTER | |
231 * NSS_ERROR_NO_MEMORY | |
232 * NSS_ERROR_TRACKER_NOT_INITIALIZED | |
233 * NSS_ERROR_DUPLICATE_POINTER | |
234 * | |
235 * Return value: | |
236 * PR_SUCCESS | |
237 * PR_FAILURE | |
238 */ | |
239 | |
240 NSS_IMPLEMENT PRStatus | |
241 nssPointerTracker_add | |
242 ( | |
243 nssPointerTracker *tracker, | |
244 const void *pointer | |
245 ) | |
246 { | |
247 void *check; | |
248 PLHashEntry *entry; | |
249 | |
250 if( (nssPointerTracker *)NULL == tracker ) { | |
251 nss_SetError(NSS_ERROR_INVALID_POINTER); | |
252 return PR_FAILURE; | |
253 } | |
254 | |
255 if( (PZLock *)NULL == tracker->lock ) { | |
256 nss_SetError(NSS_ERROR_TRACKER_NOT_INITIALIZED); | |
257 return PR_FAILURE; | |
258 } | |
259 | |
260 PZ_Lock(tracker->lock); | |
261 | |
262 if( (PLHashTable *)NULL == tracker->table ) { | |
263 PZ_Unlock(tracker->lock); | |
264 nss_SetError(NSS_ERROR_TRACKER_NOT_INITIALIZED); | |
265 return PR_FAILURE; | |
266 } | |
267 | |
268 check = PL_HashTableLookup(tracker->table, pointer); | |
269 if( (void *)NULL != check ) { | |
270 PZ_Unlock(tracker->lock); | |
271 nss_SetError(NSS_ERROR_DUPLICATE_POINTER); | |
272 return PR_FAILURE; | |
273 } | |
274 | |
275 entry = PL_HashTableAdd(tracker->table, pointer, (void *)pointer); | |
276 | |
277 PZ_Unlock(tracker->lock); | |
278 | |
279 if( (PLHashEntry *)NULL == entry ) { | |
280 nss_SetError(NSS_ERROR_NO_MEMORY); | |
281 return PR_FAILURE; | |
282 } | |
283 | |
284 return PR_SUCCESS; | |
285 } | |
286 | |
287 /* | |
288 * nssPointerTracker_remove | |
289 * | |
290 * This method is only present in debug builds. | |
291 * | |
292 * This routine removes the specified pointer from the | |
293 * nssPointerTracker object. It does not call any destructor for the | |
294 * object; rather, this should be called from the object's destructor. | |
295 * The nssPointerTracker is threadsafe, but this call is not | |
296 * idempotent. This routine returns a PRStatus value; if successful | |
297 * it will return PR_SUCCESS. On failure it will set an error on the | |
298 * error stack and return PR_FAILURE. | |
299 * | |
300 * The error may be one of the following values: | |
301 * NSS_ERROR_INVALID_POINTER | |
302 * NSS_ERROR_TRACKER_NOT_INITIALIZED | |
303 * NSS_ERROR_POINTER_NOT_REGISTERED | |
304 * | |
305 * Return value: | |
306 * PR_SUCCESS | |
307 * PR_FAILURE | |
308 */ | |
309 | |
310 NSS_IMPLEMENT PRStatus | |
311 nssPointerTracker_remove | |
312 ( | |
313 nssPointerTracker *tracker, | |
314 const void *pointer | |
315 ) | |
316 { | |
317 PRBool registered; | |
318 | |
319 if( (nssPointerTracker *)NULL == tracker ) { | |
320 nss_SetError(NSS_ERROR_INVALID_POINTER); | |
321 return PR_FAILURE; | |
322 } | |
323 | |
324 if( (PZLock *)NULL == tracker->lock ) { | |
325 nss_SetError(NSS_ERROR_TRACKER_NOT_INITIALIZED); | |
326 return PR_FAILURE; | |
327 } | |
328 | |
329 PZ_Lock(tracker->lock); | |
330 | |
331 if( (PLHashTable *)NULL == tracker->table ) { | |
332 PZ_Unlock(tracker->lock); | |
333 nss_SetError(NSS_ERROR_TRACKER_NOT_INITIALIZED); | |
334 return PR_FAILURE; | |
335 } | |
336 | |
337 registered = PL_HashTableRemove(tracker->table, pointer); | |
338 PZ_Unlock(tracker->lock); | |
339 | |
340 if( !registered ) { | |
341 nss_SetError(NSS_ERROR_POINTER_NOT_REGISTERED); | |
342 return PR_FAILURE; | |
343 } | |
344 | |
345 return PR_SUCCESS; | |
346 } | |
347 | |
348 /* | |
349 * nssPointerTracker_verify | |
350 * | |
351 * This method is only present in debug builds. | |
352 * | |
353 * This routine verifies that the specified pointer has been registered | |
354 * with the nssPointerTracker object. The nssPointerTracker object is | |
355 * threadsafe, and this call may be safely called from multiple threads | |
356 * simultaneously with the same arguments. This routine returns a | |
357 * PRStatus value; if the pointer is registered this will return | |
358 * PR_SUCCESS. Otherwise it will set an error on the error stack and | |
359 * return PR_FAILURE. Although the error is suitable for leaving on | |
360 * the stack, callers may wish to augment the information available by | |
361 * placing a more type-specific error on the stack. | |
362 * | |
363 * The error may be one of the following values: | |
364 * NSS_ERROR_INVALID_POINTER | |
365 * NSS_ERROR_TRACKER_NOT_INITIALIZED | |
366 * NSS_ERROR_POINTER_NOT_REGISTERED | |
367 * | |
368 * Return value: | |
369 * PR_SUCCESS | |
370 * PR_FAILRUE | |
371 */ | |
372 | |
373 NSS_IMPLEMENT PRStatus | |
374 nssPointerTracker_verify | |
375 ( | |
376 nssPointerTracker *tracker, | |
377 const void *pointer | |
378 ) | |
379 { | |
380 void *check; | |
381 | |
382 if( (nssPointerTracker *)NULL == tracker ) { | |
383 nss_SetError(NSS_ERROR_INVALID_POINTER); | |
384 return PR_FAILURE; | |
385 } | |
386 | |
387 if( (PZLock *)NULL == tracker->lock ) { | |
388 nss_SetError(NSS_ERROR_TRACKER_NOT_INITIALIZED); | |
389 return PR_FAILURE; | |
390 } | |
391 | |
392 PZ_Lock(tracker->lock); | |
393 | |
394 if( (PLHashTable *)NULL == tracker->table ) { | |
395 PZ_Unlock(tracker->lock); | |
396 nss_SetError(NSS_ERROR_TRACKER_NOT_INITIALIZED); | |
397 return PR_FAILURE; | |
398 } | |
399 | |
400 check = PL_HashTableLookup(tracker->table, pointer); | |
401 PZ_Unlock(tracker->lock); | |
402 | |
403 if( (void *)NULL == check ) { | |
404 nss_SetError(NSS_ERROR_POINTER_NOT_REGISTERED); | |
405 return PR_FAILURE; | |
406 } | |
407 | |
408 return PR_SUCCESS; | |
409 } | |
410 | |
411 #endif /* DEBUG */ |