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