diff nspr/pr/src/threads/prtpd.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/nspr/pr/src/threads/prtpd.c	Mon Jul 28 10:47:06 2014 +0200
@@ -0,0 +1,248 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+/*
+** Thread Private Data
+**
+** There is an aribitrary limit on the number of keys that will be allocated
+** by the runtime. It's largish, so it is intended to be a sanity check, not
+** an impediment.
+**
+** There is a counter, initialized to zero and incremented every time a
+** client asks for a new key, that holds the high water mark for keys. All
+** threads logically have the same high water mark and are permitted to
+** ask for TPD up to that key value.
+**
+** The vector to hold the TPD are allocated when PR_SetThreadPrivate() is
+** called. The size of the vector will be some value greater than or equal
+** to the current high water mark. Each thread has its own TPD length and
+** vector.
+**
+** Threads that get private data for keys they have not set (or perhaps
+** don't even exist for that thread) get a NULL return. If the key is
+** beyond the high water mark, an error will be returned.
+*/
+
+/*
+** As of this time, BeOS has its own TPD implementation.  Integrating
+** this standard one is a TODO for anyone with a bit of spare time on
+** their hand.  For now, we just #ifdef out this whole file and use
+** the routines in pr/src/btthreads/
+*/
+
+#ifndef XP_BEOS
+
+#include "primpl.h"
+
+#include <string.h>
+
+#if defined(WIN95)
+/*
+** Some local variables report warnings on Win95 because the code paths 
+** using them are conditioned on HAVE_CUSTOME_USER_THREADS.
+** The pragma suppresses the warning.
+** 
+*/
+#pragma warning(disable : 4101)
+#endif
+
+#define _PR_TPD_LIMIT 128               /* arbitary limit on the TPD slots */
+static PRInt32 _pr_tpd_length = 0;      /* current length of destructor vector */
+static PRInt32 _pr_tpd_highwater = 0;   /* next TPD key to be assigned */
+static PRThreadPrivateDTOR *_pr_tpd_destructors = NULL;
+                                        /* the destructors are associated with
+                                            the keys, therefore asserting that
+                                            the TPD key depicts the data's 'type' */
+
+/*
+** Initialize the thread private data manipulation
+*/
+void _PR_InitTPD(void)
+{
+    _pr_tpd_destructors = (PRThreadPrivateDTOR*)
+        PR_CALLOC(_PR_TPD_LIMIT * sizeof(PRThreadPrivateDTOR*));
+    PR_ASSERT(NULL != _pr_tpd_destructors);
+    _pr_tpd_length = _PR_TPD_LIMIT;
+}
+
+/*
+** Clean up the thread private data manipulation
+*/
+void _PR_CleanupTPD(void)
+{
+}  /* _PR_CleanupTPD */
+
+/*
+** This routine returns a new index for per-thread-private data table. 
+** The index is visible to all threads within a process. This index can 
+** be used with the PR_SetThreadPrivate() and PR_GetThreadPrivate() routines 
+** to save and retrieve data associated with the index for a thread.
+**
+** The index independently maintains specific values for each binding thread. 
+** A thread can only get access to its own thread-specific-data.
+**
+** Upon a new index return the value associated with the index for all threads
+** is NULL, and upon thread creation the value associated with all indices for 
+** that thread is NULL. 
+**
+**     "dtor" is the destructor function to invoke when the private
+**       data is set or destroyed
+**
+** Returns PR_FAILURE if the total number of indices will exceed the maximun 
+** allowed.
+*/
+
+PR_IMPLEMENT(PRStatus) PR_NewThreadPrivateIndex(
+    PRUintn *newIndex, PRThreadPrivateDTOR dtor)
+{
+    PRStatus rv;
+    PRInt32 index;
+
+    if (!_pr_initialized) _PR_ImplicitInitialization();
+
+    PR_ASSERT(NULL != newIndex);
+    PR_ASSERT(NULL != _pr_tpd_destructors);
+
+    index = PR_ATOMIC_INCREMENT(&_pr_tpd_highwater) - 1;  /* allocate index */
+    if (_PR_TPD_LIMIT <= index)
+    {
+        PR_SetError(PR_TPD_RANGE_ERROR, 0);
+        rv = PR_FAILURE;  /* that's just wrong */
+    }
+    else
+    {
+        _pr_tpd_destructors[index] = dtor;  /* record destructor @index */
+        *newIndex = (PRUintn)index;  /* copy into client's location */
+        rv = PR_SUCCESS;  /* that's okay */
+    }
+
+    return rv;
+}
+
+/*
+** Define some per-thread-private data.
+**     "index" is an index into the per-thread private data table
+**     "priv" is the per-thread-private data 
+**
+** If the per-thread private data table has a previously registered
+** destructor function and a non-NULL per-thread-private data value,
+** the destructor function is invoked.
+**
+** This can return PR_FAILURE if index is invalid (ie., beyond the current
+** high water mark) or memory is insufficient to allocate an exanded vector.
+*/
+
+PR_IMPLEMENT(PRStatus) PR_SetThreadPrivate(PRUintn index, void *priv)
+{
+    PRThread *self = PR_GetCurrentThread();
+
+    /*
+    ** The index being set might not have a sufficient vector in this
+    ** thread. But if the index has been allocated, it's okay to go
+    ** ahead and extend this one now.
+    */
+    if ((index >= _PR_TPD_LIMIT) || (index >= _pr_tpd_highwater))
+    {
+        PR_SetError(PR_TPD_RANGE_ERROR, 0);
+        return PR_FAILURE;
+    }
+
+    PR_ASSERT(((NULL == self->privateData) && (0 == self->tpdLength))
+        || ((NULL != self->privateData) && (0 != self->tpdLength)));
+
+    if ((NULL == self->privateData) || (self->tpdLength <= index))
+    {
+        void *extension = PR_CALLOC(_pr_tpd_length * sizeof(void*));
+        if (NULL == extension)
+        {
+            PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+            return PR_FAILURE;
+        }
+        if (self->privateData) {
+            (void)memcpy(
+                extension, self->privateData,
+                self->tpdLength * sizeof(void*));
+            PR_DELETE(self->privateData);
+        }
+        self->tpdLength = _pr_tpd_length;
+        self->privateData = (void**)extension;
+    }
+    /*
+    ** There wasn't much chance of having to call the destructor
+    ** unless the slot already existed.
+    */
+    else if (self->privateData[index] && _pr_tpd_destructors[index])
+    {
+        void *data = self->privateData[index];
+        self->privateData[index] = NULL;
+        (*_pr_tpd_destructors[index])(data);
+    }
+
+    PR_ASSERT(index < self->tpdLength);
+    self->privateData[index] = priv;
+
+    return PR_SUCCESS;
+}
+
+/*
+** Recover the per-thread-private data for the current thread. "index" is
+** the index into the per-thread private data table. 
+**
+** The returned value may be NULL which is indistinguishable from an error 
+** condition.
+**
+*/
+
+PR_IMPLEMENT(void*) PR_GetThreadPrivate(PRUintn index)
+{
+    PRThread *self = PR_GetCurrentThread();
+    void *tpd = ((NULL == self->privateData) || (index >= self->tpdLength)) ?
+        NULL : self->privateData[index];
+
+    return tpd;
+}
+
+/*
+** Destroy the thread's private data, if any exists. This is called at
+** thread termination time only. There should be no threading issues
+** since this is being called by the thread itself.
+*/
+void _PR_DestroyThreadPrivate(PRThread* self)
+{
+#define _PR_TPD_DESTRUCTOR_ITERATIONS 4
+
+    if (NULL != self->privateData)  /* we have some */
+    {
+        PRBool clean;
+        PRUint32 index;
+        PRInt32 passes = _PR_TPD_DESTRUCTOR_ITERATIONS;
+        PR_ASSERT(0 != self->tpdLength);
+        do
+        {
+            clean = PR_TRUE;
+            for (index = 0; index < self->tpdLength; ++index)
+            {
+                void *priv = self->privateData[index];  /* extract */
+                if (NULL != priv)  /* we have data at this index */
+                {
+                    if (NULL != _pr_tpd_destructors[index])
+                    {
+                        self->privateData[index] = NULL;  /* precondition */
+                        (*_pr_tpd_destructors[index])(priv);  /* destroy */
+                        clean = PR_FALSE;  /* unknown side effects */
+                    }
+                }
+            }
+        } while ((--passes > 0) && !clean);  /* limit # of passes */
+        /*
+        ** We give up after a fixed number of passes. Any non-NULL
+        ** thread-private data value with a registered destructor
+        ** function is not destroyed.
+        */
+        memset(self->privateData, 0, self->tpdLength * sizeof(void*));
+    }
+}  /* _PR_DestroyThreadPrivate */
+
+#endif /* !XP_BEOS */
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)