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 */
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)