Mercurial > trustbridge > nss-cmake-static
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 */ |