Mercurial > trustbridge > nss-cmake-static
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nss/lib/base/tracker.c Mon Jul 28 10:47:06 2014 +0200 @@ -0,0 +1,411 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * tracker.c + * + * This file contains the code used by the pointer-tracking calls used + * in the debug builds to catch bad pointers. The entire contents are + * only available in debug builds (both internal and external builds). + */ + +#ifndef BASE_H +#include "base.h" +#endif /* BASE_H */ + +#ifdef DEBUG +/* + * identity_hash + * + * This static callback is a PLHashFunction as defined in plhash.h + * It merely returns the value of the object pointer as its hash. + * There are no possible errors. + */ + +static PLHashNumber PR_CALLBACK +identity_hash +( + const void *key +) +{ + return (PLHashNumber)key; +} + +/* + * trackerOnceFunc + * + * This function is called once, using the nssCallOnce function above. + * It creates a new pointer tracker object; initialising its hash + * table and protective lock. + */ + +static PRStatus +trackerOnceFunc +( + void *arg +) +{ + nssPointerTracker *tracker = (nssPointerTracker *)arg; + + tracker->lock = PZ_NewLock(nssILockOther); + if( (PZLock *)NULL == tracker->lock ) { + return PR_FAILURE; + } + + tracker->table = PL_NewHashTable(0, + identity_hash, + PL_CompareValues, + PL_CompareValues, + (PLHashAllocOps *)NULL, + (void *)NULL); + if( (PLHashTable *)NULL == tracker->table ) { + PZ_DestroyLock(tracker->lock); + tracker->lock = (PZLock *)NULL; + return PR_FAILURE; + } + + return PR_SUCCESS; +} + +/* + * nssPointerTracker_initialize + * + * This method is only present in debug builds. + * + * This routine initializes an nssPointerTracker object. Note that + * the object must have been declared *static* to guarantee that it + * is in a zeroed state initially. This routine is idempotent, and + * may even be safely called by multiple threads simultaneously with + * the same argument. This routine returns a PRStatus value; if + * successful, it will return PR_SUCCESS. On failure it will set an + * error on the error stack and return PR_FAILURE. + * + * The error may be one of the following values: + * NSS_ERROR_NO_MEMORY + * + * Return value: + * PR_SUCCESS + * PR_FAILURE + */ + +NSS_IMPLEMENT PRStatus +nssPointerTracker_initialize +( + nssPointerTracker *tracker +) +{ + PRStatus rv = PR_CallOnceWithArg(&tracker->once, trackerOnceFunc, tracker); + if( PR_SUCCESS != rv ) { + nss_SetError(NSS_ERROR_NO_MEMORY); + } + + return rv; +} + +#ifdef DONT_DESTROY_EMPTY_TABLES +/* See same #ifdef below */ +/* + * count_entries + * + * This static routine is a PLHashEnumerator, as defined in plhash.h. + * It merely causes the enumeration function to count the number of + * entries. + */ + +static PRIntn PR_CALLBACK +count_entries +( + PLHashEntry *he, + PRIntn index, + void *arg +) +{ + return HT_ENUMERATE_NEXT; +} +#endif /* DONT_DESTROY_EMPTY_TABLES */ + +/* + * zero_once + * + * This is a guaranteed zeroed once block. It's used to help clear + * the tracker. + */ + +static const PRCallOnceType zero_once; + +/* + * nssPointerTracker_finalize + * + * This method is only present in debug builds. + * + * This routine returns the nssPointerTracker object to the pre- + * initialized state, releasing all resources used by the object. + * It will *NOT* destroy the objects being tracked by the pointer + * (should any remain), and therefore cannot be used to "sweep up" + * remaining objects. This routine returns a PRStatus value; if + * successful, it will return PR_SUCCES. On failure it will set an + * error on the error stack and return PR_FAILURE. If any objects + * remain in the tracker when it is finalized, that will be treated + * as an error. + * + * The error may be one of the following values: + * NSS_ERROR_INVALID_POINTER + * NSS_ERROR_TRACKER_NOT_INITIALIZED + * NSS_ERROR_TRACKER_NOT_EMPTY + * + * Return value: + * PR_SUCCESS + * PR_FAILURE + */ + +NSS_IMPLEMENT PRStatus +nssPointerTracker_finalize +( + nssPointerTracker *tracker +) +{ + PZLock *lock; + + if( (nssPointerTracker *)NULL == tracker ) { + nss_SetError(NSS_ERROR_INVALID_POINTER); + return PR_FAILURE; + } + + if( (PZLock *)NULL == tracker->lock ) { + nss_SetError(NSS_ERROR_TRACKER_NOT_INITIALIZED); + return PR_FAILURE; + } + + lock = tracker->lock; + PZ_Lock(lock); + + if( (PLHashTable *)NULL == tracker->table ) { + PZ_Unlock(lock); + nss_SetError(NSS_ERROR_TRACKER_NOT_INITIALIZED); + return PR_FAILURE; + } + +#ifdef DONT_DESTROY_EMPTY_TABLES + /* + * I changed my mind; I think we don't want this after all. + * Comments? + */ + count = PL_HashTableEnumerateEntries(tracker->table, + count_entries, + (void *)NULL); + + if( 0 != count ) { + PZ_Unlock(lock); + nss_SetError(NSS_ERROR_TRACKER_NOT_EMPTY); + return PR_FAILURE; + } +#endif /* DONT_DESTROY_EMPTY_TABLES */ + + PL_HashTableDestroy(tracker->table); + /* memset(tracker, 0, sizeof(nssPointerTracker)); */ + tracker->once = zero_once; + tracker->lock = (PZLock *)NULL; + tracker->table = (PLHashTable *)NULL; + + PZ_Unlock(lock); + PZ_DestroyLock(lock); + + return PR_SUCCESS; +} + +/* + * nssPointerTracker_add + * + * This method is only present in debug builds. + * + * This routine adds the specified pointer to the nssPointerTracker + * object. It should be called in constructor objects to register + * new valid objects. The nssPointerTracker is threadsafe, but this + * call is not idempotent. This routine returns a PRStatus value; + * if successful it will return PR_SUCCESS. On failure it will set + * an error on the error stack and return PR_FAILURE. + * + * The error may be one of the following values: + * NSS_ERROR_INVALID_POINTER + * NSS_ERROR_NO_MEMORY + * NSS_ERROR_TRACKER_NOT_INITIALIZED + * NSS_ERROR_DUPLICATE_POINTER + * + * Return value: + * PR_SUCCESS + * PR_FAILURE + */ + +NSS_IMPLEMENT PRStatus +nssPointerTracker_add +( + nssPointerTracker *tracker, + const void *pointer +) +{ + void *check; + PLHashEntry *entry; + + if( (nssPointerTracker *)NULL == tracker ) { + nss_SetError(NSS_ERROR_INVALID_POINTER); + return PR_FAILURE; + } + + if( (PZLock *)NULL == tracker->lock ) { + nss_SetError(NSS_ERROR_TRACKER_NOT_INITIALIZED); + return PR_FAILURE; + } + + PZ_Lock(tracker->lock); + + if( (PLHashTable *)NULL == tracker->table ) { + PZ_Unlock(tracker->lock); + nss_SetError(NSS_ERROR_TRACKER_NOT_INITIALIZED); + return PR_FAILURE; + } + + check = PL_HashTableLookup(tracker->table, pointer); + if( (void *)NULL != check ) { + PZ_Unlock(tracker->lock); + nss_SetError(NSS_ERROR_DUPLICATE_POINTER); + return PR_FAILURE; + } + + entry = PL_HashTableAdd(tracker->table, pointer, (void *)pointer); + + PZ_Unlock(tracker->lock); + + if( (PLHashEntry *)NULL == entry ) { + nss_SetError(NSS_ERROR_NO_MEMORY); + return PR_FAILURE; + } + + return PR_SUCCESS; +} + +/* + * nssPointerTracker_remove + * + * This method is only present in debug builds. + * + * This routine removes the specified pointer from the + * nssPointerTracker object. It does not call any destructor for the + * object; rather, this should be called from the object's destructor. + * The nssPointerTracker is threadsafe, but this call is not + * idempotent. This routine returns a PRStatus value; if successful + * it will return PR_SUCCESS. On failure it will set an error on the + * error stack and return PR_FAILURE. + * + * The error may be one of the following values: + * NSS_ERROR_INVALID_POINTER + * NSS_ERROR_TRACKER_NOT_INITIALIZED + * NSS_ERROR_POINTER_NOT_REGISTERED + * + * Return value: + * PR_SUCCESS + * PR_FAILURE + */ + +NSS_IMPLEMENT PRStatus +nssPointerTracker_remove +( + nssPointerTracker *tracker, + const void *pointer +) +{ + PRBool registered; + + if( (nssPointerTracker *)NULL == tracker ) { + nss_SetError(NSS_ERROR_INVALID_POINTER); + return PR_FAILURE; + } + + if( (PZLock *)NULL == tracker->lock ) { + nss_SetError(NSS_ERROR_TRACKER_NOT_INITIALIZED); + return PR_FAILURE; + } + + PZ_Lock(tracker->lock); + + if( (PLHashTable *)NULL == tracker->table ) { + PZ_Unlock(tracker->lock); + nss_SetError(NSS_ERROR_TRACKER_NOT_INITIALIZED); + return PR_FAILURE; + } + + registered = PL_HashTableRemove(tracker->table, pointer); + PZ_Unlock(tracker->lock); + + if( !registered ) { + nss_SetError(NSS_ERROR_POINTER_NOT_REGISTERED); + return PR_FAILURE; + } + + return PR_SUCCESS; +} + +/* + * nssPointerTracker_verify + * + * This method is only present in debug builds. + * + * This routine verifies that the specified pointer has been registered + * with the nssPointerTracker object. The nssPointerTracker object is + * threadsafe, and this call may be safely called from multiple threads + * simultaneously with the same arguments. This routine returns a + * PRStatus value; if the pointer is registered this will return + * PR_SUCCESS. Otherwise it will set an error on the error stack and + * return PR_FAILURE. Although the error is suitable for leaving on + * the stack, callers may wish to augment the information available by + * placing a more type-specific error on the stack. + * + * The error may be one of the following values: + * NSS_ERROR_INVALID_POINTER + * NSS_ERROR_TRACKER_NOT_INITIALIZED + * NSS_ERROR_POINTER_NOT_REGISTERED + * + * Return value: + * PR_SUCCESS + * PR_FAILRUE + */ + +NSS_IMPLEMENT PRStatus +nssPointerTracker_verify +( + nssPointerTracker *tracker, + const void *pointer +) +{ + void *check; + + if( (nssPointerTracker *)NULL == tracker ) { + nss_SetError(NSS_ERROR_INVALID_POINTER); + return PR_FAILURE; + } + + if( (PZLock *)NULL == tracker->lock ) { + nss_SetError(NSS_ERROR_TRACKER_NOT_INITIALIZED); + return PR_FAILURE; + } + + PZ_Lock(tracker->lock); + + if( (PLHashTable *)NULL == tracker->table ) { + PZ_Unlock(tracker->lock); + nss_SetError(NSS_ERROR_TRACKER_NOT_INITIALIZED); + return PR_FAILURE; + } + + check = PL_HashTableLookup(tracker->table, pointer); + PZ_Unlock(tracker->lock); + + if( (void *)NULL == check ) { + nss_SetError(NSS_ERROR_POINTER_NOT_REGISTERED); + return PR_FAILURE; + } + + return PR_SUCCESS; +} + +#endif /* DEBUG */