comparison 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
comparison
equal deleted inserted replaced
-1:000000000000 0:1e5118fa0cb1
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 /*
7 ** Thread Private Data
8 **
9 ** There is an aribitrary limit on the number of keys that will be allocated
10 ** by the runtime. It's largish, so it is intended to be a sanity check, not
11 ** an impediment.
12 **
13 ** There is a counter, initialized to zero and incremented every time a
14 ** client asks for a new key, that holds the high water mark for keys. All
15 ** threads logically have the same high water mark and are permitted to
16 ** ask for TPD up to that key value.
17 **
18 ** The vector to hold the TPD are allocated when PR_SetThreadPrivate() is
19 ** called. The size of the vector will be some value greater than or equal
20 ** to the current high water mark. Each thread has its own TPD length and
21 ** vector.
22 **
23 ** Threads that get private data for keys they have not set (or perhaps
24 ** don't even exist for that thread) get a NULL return. If the key is
25 ** beyond the high water mark, an error will be returned.
26 */
27
28 /*
29 ** As of this time, BeOS has its own TPD implementation. Integrating
30 ** this standard one is a TODO for anyone with a bit of spare time on
31 ** their hand. For now, we just #ifdef out this whole file and use
32 ** the routines in pr/src/btthreads/
33 */
34
35 #ifndef XP_BEOS
36
37 #include "primpl.h"
38
39 #include <string.h>
40
41 #if defined(WIN95)
42 /*
43 ** Some local variables report warnings on Win95 because the code paths
44 ** using them are conditioned on HAVE_CUSTOME_USER_THREADS.
45 ** The pragma suppresses the warning.
46 **
47 */
48 #pragma warning(disable : 4101)
49 #endif
50
51 #define _PR_TPD_LIMIT 128 /* arbitary limit on the TPD slots */
52 static PRInt32 _pr_tpd_length = 0; /* current length of destructor vector */
53 static PRInt32 _pr_tpd_highwater = 0; /* next TPD key to be assigned */
54 static PRThreadPrivateDTOR *_pr_tpd_destructors = NULL;
55 /* the destructors are associated with
56 the keys, therefore asserting that
57 the TPD key depicts the data's 'type' */
58
59 /*
60 ** Initialize the thread private data manipulation
61 */
62 void _PR_InitTPD(void)
63 {
64 _pr_tpd_destructors = (PRThreadPrivateDTOR*)
65 PR_CALLOC(_PR_TPD_LIMIT * sizeof(PRThreadPrivateDTOR*));
66 PR_ASSERT(NULL != _pr_tpd_destructors);
67 _pr_tpd_length = _PR_TPD_LIMIT;
68 }
69
70 /*
71 ** Clean up the thread private data manipulation
72 */
73 void _PR_CleanupTPD(void)
74 {
75 } /* _PR_CleanupTPD */
76
77 /*
78 ** This routine returns a new index for per-thread-private data table.
79 ** The index is visible to all threads within a process. This index can
80 ** be used with the PR_SetThreadPrivate() and PR_GetThreadPrivate() routines
81 ** to save and retrieve data associated with the index for a thread.
82 **
83 ** The index independently maintains specific values for each binding thread.
84 ** A thread can only get access to its own thread-specific-data.
85 **
86 ** Upon a new index return the value associated with the index for all threads
87 ** is NULL, and upon thread creation the value associated with all indices for
88 ** that thread is NULL.
89 **
90 ** "dtor" is the destructor function to invoke when the private
91 ** data is set or destroyed
92 **
93 ** Returns PR_FAILURE if the total number of indices will exceed the maximun
94 ** allowed.
95 */
96
97 PR_IMPLEMENT(PRStatus) PR_NewThreadPrivateIndex(
98 PRUintn *newIndex, PRThreadPrivateDTOR dtor)
99 {
100 PRStatus rv;
101 PRInt32 index;
102
103 if (!_pr_initialized) _PR_ImplicitInitialization();
104
105 PR_ASSERT(NULL != newIndex);
106 PR_ASSERT(NULL != _pr_tpd_destructors);
107
108 index = PR_ATOMIC_INCREMENT(&_pr_tpd_highwater) - 1; /* allocate index */
109 if (_PR_TPD_LIMIT <= index)
110 {
111 PR_SetError(PR_TPD_RANGE_ERROR, 0);
112 rv = PR_FAILURE; /* that's just wrong */
113 }
114 else
115 {
116 _pr_tpd_destructors[index] = dtor; /* record destructor @index */
117 *newIndex = (PRUintn)index; /* copy into client's location */
118 rv = PR_SUCCESS; /* that's okay */
119 }
120
121 return rv;
122 }
123
124 /*
125 ** Define some per-thread-private data.
126 ** "index" is an index into the per-thread private data table
127 ** "priv" is the per-thread-private data
128 **
129 ** If the per-thread private data table has a previously registered
130 ** destructor function and a non-NULL per-thread-private data value,
131 ** the destructor function is invoked.
132 **
133 ** This can return PR_FAILURE if index is invalid (ie., beyond the current
134 ** high water mark) or memory is insufficient to allocate an exanded vector.
135 */
136
137 PR_IMPLEMENT(PRStatus) PR_SetThreadPrivate(PRUintn index, void *priv)
138 {
139 PRThread *self = PR_GetCurrentThread();
140
141 /*
142 ** The index being set might not have a sufficient vector in this
143 ** thread. But if the index has been allocated, it's okay to go
144 ** ahead and extend this one now.
145 */
146 if ((index >= _PR_TPD_LIMIT) || (index >= _pr_tpd_highwater))
147 {
148 PR_SetError(PR_TPD_RANGE_ERROR, 0);
149 return PR_FAILURE;
150 }
151
152 PR_ASSERT(((NULL == self->privateData) && (0 == self->tpdLength))
153 || ((NULL != self->privateData) && (0 != self->tpdLength)));
154
155 if ((NULL == self->privateData) || (self->tpdLength <= index))
156 {
157 void *extension = PR_CALLOC(_pr_tpd_length * sizeof(void*));
158 if (NULL == extension)
159 {
160 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
161 return PR_FAILURE;
162 }
163 if (self->privateData) {
164 (void)memcpy(
165 extension, self->privateData,
166 self->tpdLength * sizeof(void*));
167 PR_DELETE(self->privateData);
168 }
169 self->tpdLength = _pr_tpd_length;
170 self->privateData = (void**)extension;
171 }
172 /*
173 ** There wasn't much chance of having to call the destructor
174 ** unless the slot already existed.
175 */
176 else if (self->privateData[index] && _pr_tpd_destructors[index])
177 {
178 void *data = self->privateData[index];
179 self->privateData[index] = NULL;
180 (*_pr_tpd_destructors[index])(data);
181 }
182
183 PR_ASSERT(index < self->tpdLength);
184 self->privateData[index] = priv;
185
186 return PR_SUCCESS;
187 }
188
189 /*
190 ** Recover the per-thread-private data for the current thread. "index" is
191 ** the index into the per-thread private data table.
192 **
193 ** The returned value may be NULL which is indistinguishable from an error
194 ** condition.
195 **
196 */
197
198 PR_IMPLEMENT(void*) PR_GetThreadPrivate(PRUintn index)
199 {
200 PRThread *self = PR_GetCurrentThread();
201 void *tpd = ((NULL == self->privateData) || (index >= self->tpdLength)) ?
202 NULL : self->privateData[index];
203
204 return tpd;
205 }
206
207 /*
208 ** Destroy the thread's private data, if any exists. This is called at
209 ** thread termination time only. There should be no threading issues
210 ** since this is being called by the thread itself.
211 */
212 void _PR_DestroyThreadPrivate(PRThread* self)
213 {
214 #define _PR_TPD_DESTRUCTOR_ITERATIONS 4
215
216 if (NULL != self->privateData) /* we have some */
217 {
218 PRBool clean;
219 PRUint32 index;
220 PRInt32 passes = _PR_TPD_DESTRUCTOR_ITERATIONS;
221 PR_ASSERT(0 != self->tpdLength);
222 do
223 {
224 clean = PR_TRUE;
225 for (index = 0; index < self->tpdLength; ++index)
226 {
227 void *priv = self->privateData[index]; /* extract */
228 if (NULL != priv) /* we have data at this index */
229 {
230 if (NULL != _pr_tpd_destructors[index])
231 {
232 self->privateData[index] = NULL; /* precondition */
233 (*_pr_tpd_destructors[index])(priv); /* destroy */
234 clean = PR_FALSE; /* unknown side effects */
235 }
236 }
237 }
238 } while ((--passes > 0) && !clean); /* limit # of passes */
239 /*
240 ** We give up after a fixed number of passes. Any non-NULL
241 ** thread-private data value with a registered destructor
242 ** function is not destroyed.
243 */
244 memset(self->privateData, 0, self->tpdLength * sizeof(void*));
245 }
246 } /* _PR_DestroyThreadPrivate */
247
248 #endif /* !XP_BEOS */
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)