Mercurial > trustbridge > nss-cmake-static
comparison nspr/pr/src/threads/prcthr.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 #include "primpl.h" | |
7 | |
8 #if defined(WIN95) | |
9 /* | |
10 ** Some local variables report warnings on Win95 because the code paths | |
11 ** using them are conditioned on HAVE_CUSTOME_USER_THREADS. | |
12 ** The pragma suppresses the warning. | |
13 ** | |
14 */ | |
15 #pragma warning(disable : 4101) | |
16 #endif | |
17 | |
18 | |
19 extern PRLock *_pr_sleeplock; /* allocated and initialized in prinit */ | |
20 /* | |
21 ** Routines common to both native and user threads. | |
22 ** | |
23 ** | |
24 ** Clean up a thread object, releasing all of the attached data. Do not | |
25 ** free the object itself (it may not have been malloc'd) | |
26 */ | |
27 void _PR_CleanupThread(PRThread *thread) | |
28 { | |
29 /* Free up per-thread-data */ | |
30 _PR_DestroyThreadPrivate(thread); | |
31 | |
32 /* Free any thread dump procs */ | |
33 if (thread->dumpArg) { | |
34 PR_DELETE(thread->dumpArg); | |
35 } | |
36 thread->dump = 0; | |
37 | |
38 PR_DELETE(thread->name); | |
39 PR_DELETE(thread->errorString); | |
40 thread->errorStringSize = 0; | |
41 thread->errorStringLength = 0; | |
42 thread->environment = NULL; | |
43 } | |
44 | |
45 PR_IMPLEMENT(PRStatus) PR_Yield() | |
46 { | |
47 static PRBool warning = PR_TRUE; | |
48 if (warning) warning = _PR_Obsolete( | |
49 "PR_Yield()", "PR_Sleep(PR_INTERVAL_NO_WAIT)"); | |
50 return (PR_Sleep(PR_INTERVAL_NO_WAIT)); | |
51 } | |
52 | |
53 /* | |
54 ** Make the current thread sleep until "timeout" ticks amount of time | |
55 ** has expired. If "timeout" is PR_INTERVAL_NO_WAIT then the call is | |
56 ** equivalent to a yield. Waiting for an infinite amount of time is | |
57 ** allowed in the expectation that another thread will interrupt(). | |
58 ** | |
59 ** A single lock is used for all threads calling sleep. Each caller | |
60 ** does get its own condition variable since each is expected to have | |
61 ** a unique 'timeout'. | |
62 */ | |
63 PR_IMPLEMENT(PRStatus) PR_Sleep(PRIntervalTime timeout) | |
64 { | |
65 PRStatus rv = PR_SUCCESS; | |
66 | |
67 if (!_pr_initialized) _PR_ImplicitInitialization(); | |
68 | |
69 if (PR_INTERVAL_NO_WAIT == timeout) | |
70 { | |
71 /* | |
72 ** This is a simple yield, nothing more, nothing less. | |
73 */ | |
74 PRIntn is; | |
75 PRThread *me = PR_GetCurrentThread(); | |
76 PRUintn pri = me->priority; | |
77 _PRCPU *cpu = _PR_MD_CURRENT_CPU(); | |
78 | |
79 if ( _PR_IS_NATIVE_THREAD(me) ) _PR_MD_YIELD(); | |
80 else | |
81 { | |
82 _PR_INTSOFF(is); | |
83 _PR_RUNQ_LOCK(cpu); | |
84 if (_PR_RUNQREADYMASK(cpu) >> pri) { | |
85 me->cpu = cpu; | |
86 me->state = _PR_RUNNABLE; | |
87 _PR_ADD_RUNQ(me, cpu, pri); | |
88 _PR_RUNQ_UNLOCK(cpu); | |
89 | |
90 PR_LOG(_pr_sched_lm, PR_LOG_MIN, ("PR_Yield: yielding")); | |
91 _PR_MD_SWITCH_CONTEXT(me); | |
92 PR_LOG(_pr_sched_lm, PR_LOG_MIN, ("PR_Yield: done")); | |
93 | |
94 _PR_FAST_INTSON(is); | |
95 } | |
96 else | |
97 { | |
98 _PR_RUNQ_UNLOCK(cpu); | |
99 _PR_INTSON(is); | |
100 } | |
101 } | |
102 } | |
103 else | |
104 { | |
105 /* | |
106 ** This is waiting for some finite period of time. | |
107 ** A thread in this state is interruptible (PR_Interrupt()), | |
108 ** but the lock and cvar used are local to the implementation | |
109 ** and not visible to the caller, therefore not notifiable. | |
110 */ | |
111 PRCondVar *cv; | |
112 PRIntervalTime timein; | |
113 | |
114 timein = PR_IntervalNow(); | |
115 cv = PR_NewCondVar(_pr_sleeplock); | |
116 PR_ASSERT(cv != NULL); | |
117 PR_Lock(_pr_sleeplock); | |
118 do | |
119 { | |
120 PRIntervalTime delta = PR_IntervalNow() - timein; | |
121 if (delta > timeout) break; | |
122 rv = PR_WaitCondVar(cv, timeout - delta); | |
123 } while (rv == PR_SUCCESS); | |
124 PR_Unlock(_pr_sleeplock); | |
125 PR_DestroyCondVar(cv); | |
126 } | |
127 return rv; | |
128 } | |
129 | |
130 PR_IMPLEMENT(PRUint32) PR_GetThreadID(PRThread *thread) | |
131 { | |
132 return thread->id; | |
133 } | |
134 | |
135 PR_IMPLEMENT(PRThreadPriority) PR_GetThreadPriority(const PRThread *thread) | |
136 { | |
137 return (PRThreadPriority) thread->priority; | |
138 } | |
139 | |
140 PR_IMPLEMENT(PRThread *) PR_GetCurrentThread() | |
141 { | |
142 if (!_pr_initialized) _PR_ImplicitInitialization(); | |
143 return _PR_MD_CURRENT_THREAD(); | |
144 } | |
145 | |
146 /* | |
147 ** Set the interrupt flag for a thread. The thread will be unable to | |
148 ** block in i/o functions when this happens. Also, any PR_Wait's in | |
149 ** progress will be undone. The interrupt remains in force until | |
150 ** PR_ClearInterrupt is called. | |
151 */ | |
152 PR_IMPLEMENT(PRStatus) PR_Interrupt(PRThread *thread) | |
153 { | |
154 #ifdef _PR_GLOBAL_THREADS_ONLY | |
155 PRCondVar *victim; | |
156 | |
157 _PR_THREAD_LOCK(thread); | |
158 thread->flags |= _PR_INTERRUPT; | |
159 victim = thread->wait.cvar; | |
160 _PR_THREAD_UNLOCK(thread); | |
161 if ((NULL != victim) && (!(thread->flags & _PR_INTERRUPT_BLOCKED))) { | |
162 int haveLock = (victim->lock->owner == _PR_MD_CURRENT_THREAD()); | |
163 | |
164 if (!haveLock) PR_Lock(victim->lock); | |
165 PR_NotifyAllCondVar(victim); | |
166 if (!haveLock) PR_Unlock(victim->lock); | |
167 } | |
168 return PR_SUCCESS; | |
169 #else /* ! _PR_GLOBAL_THREADS_ONLY */ | |
170 PRIntn is; | |
171 PRThread *me = _PR_MD_CURRENT_THREAD(); | |
172 | |
173 if (!_PR_IS_NATIVE_THREAD(me)) | |
174 _PR_INTSOFF(is); | |
175 | |
176 _PR_THREAD_LOCK(thread); | |
177 thread->flags |= _PR_INTERRUPT; | |
178 switch (thread->state) { | |
179 case _PR_COND_WAIT: | |
180 /* | |
181 * call is made with thread locked; | |
182 * on return lock is released | |
183 */ | |
184 if (!(thread->flags & _PR_INTERRUPT_BLOCKED)) | |
185 _PR_NotifyLockedThread(thread); | |
186 break; | |
187 case _PR_IO_WAIT: | |
188 /* | |
189 * Need to hold the thread lock when calling | |
190 * _PR_Unblock_IO_Wait(). On return lock is | |
191 * released. | |
192 */ | |
193 #if defined(XP_UNIX) || defined(WINNT) || defined(WIN16) | |
194 if (!(thread->flags & _PR_INTERRUPT_BLOCKED)) | |
195 _PR_Unblock_IO_Wait(thread); | |
196 #else | |
197 _PR_THREAD_UNLOCK(thread); | |
198 #endif | |
199 break; | |
200 case _PR_RUNNING: | |
201 case _PR_RUNNABLE: | |
202 case _PR_LOCK_WAIT: | |
203 default: | |
204 _PR_THREAD_UNLOCK(thread); | |
205 break; | |
206 } | |
207 if (!_PR_IS_NATIVE_THREAD(me)) | |
208 _PR_INTSON(is); | |
209 return PR_SUCCESS; | |
210 #endif /* _PR_GLOBAL_THREADS_ONLY */ | |
211 } | |
212 | |
213 /* | |
214 ** Clear the interrupt flag for self. | |
215 */ | |
216 PR_IMPLEMENT(void) PR_ClearInterrupt() | |
217 { | |
218 PRIntn is; | |
219 PRThread *me = _PR_MD_CURRENT_THREAD(); | |
220 | |
221 if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is); | |
222 _PR_THREAD_LOCK(me); | |
223 me->flags &= ~_PR_INTERRUPT; | |
224 _PR_THREAD_UNLOCK(me); | |
225 if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is); | |
226 } | |
227 | |
228 PR_IMPLEMENT(void) PR_BlockInterrupt() | |
229 { | |
230 PRIntn is; | |
231 PRThread *me = _PR_MD_CURRENT_THREAD(); | |
232 | |
233 if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is); | |
234 _PR_THREAD_LOCK(me); | |
235 _PR_THREAD_BLOCK_INTERRUPT(me); | |
236 _PR_THREAD_UNLOCK(me); | |
237 if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is); | |
238 } /* PR_BlockInterrupt */ | |
239 | |
240 PR_IMPLEMENT(void) PR_UnblockInterrupt() | |
241 { | |
242 PRIntn is; | |
243 PRThread *me = _PR_MD_CURRENT_THREAD(); | |
244 | |
245 if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is); | |
246 _PR_THREAD_LOCK(me); | |
247 _PR_THREAD_UNBLOCK_INTERRUPT(me); | |
248 _PR_THREAD_UNLOCK(me); | |
249 if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is); | |
250 } /* PR_UnblockInterrupt */ | |
251 | |
252 /* | |
253 ** Return the thread stack pointer of the given thread. | |
254 */ | |
255 PR_IMPLEMENT(void *) PR_GetSP(PRThread *thread) | |
256 { | |
257 return (void *)_PR_MD_GET_SP(thread); | |
258 } | |
259 | |
260 PR_IMPLEMENT(void*) GetExecutionEnvironment(PRThread *thread) | |
261 { | |
262 return thread->environment; | |
263 } | |
264 | |
265 PR_IMPLEMENT(void) SetExecutionEnvironment(PRThread *thread, void *env) | |
266 { | |
267 thread->environment = env; | |
268 } | |
269 | |
270 | |
271 PR_IMPLEMENT(PRInt32) PR_GetThreadAffinityMask(PRThread *thread, PRUint32 *mask) | |
272 { | |
273 #ifdef HAVE_THREAD_AFFINITY | |
274 return _PR_MD_GETTHREADAFFINITYMASK(thread, mask); | |
275 #else | |
276 return 0; | |
277 #endif | |
278 } | |
279 | |
280 PR_IMPLEMENT(PRInt32) PR_SetThreadAffinityMask(PRThread *thread, PRUint32 mask ) | |
281 { | |
282 #ifdef HAVE_THREAD_AFFINITY | |
283 #ifndef IRIX | |
284 return _PR_MD_SETTHREADAFFINITYMASK(thread, mask); | |
285 #else | |
286 return 0; | |
287 #endif | |
288 #else | |
289 return 0; | |
290 #endif | |
291 } | |
292 | |
293 /* This call is thread unsafe if another thread is calling SetConcurrency() | |
294 */ | |
295 PR_IMPLEMENT(PRInt32) PR_SetCPUAffinityMask(PRUint32 mask) | |
296 { | |
297 #ifdef HAVE_THREAD_AFFINITY | |
298 PRCList *qp; | |
299 extern PRUint32 _pr_cpu_affinity_mask; | |
300 | |
301 if (!_pr_initialized) _PR_ImplicitInitialization(); | |
302 | |
303 _pr_cpu_affinity_mask = mask; | |
304 | |
305 qp = _PR_CPUQ().next; | |
306 while(qp != &_PR_CPUQ()) { | |
307 _PRCPU *cpu; | |
308 | |
309 cpu = _PR_CPU_PTR(qp); | |
310 PR_SetThreadAffinityMask(cpu->thread, mask); | |
311 | |
312 qp = qp->next; | |
313 } | |
314 #endif | |
315 | |
316 return 0; | |
317 } | |
318 | |
319 PRUint32 _pr_recycleThreads = 0; | |
320 PR_IMPLEMENT(void) PR_SetThreadRecycleMode(PRUint32 count) | |
321 { | |
322 _pr_recycleThreads = count; | |
323 } | |
324 | |
325 PR_IMPLEMENT(PRThread*) PR_CreateThreadGCAble(PRThreadType type, | |
326 void (*start)(void *arg), | |
327 void *arg, | |
328 PRThreadPriority priority, | |
329 PRThreadScope scope, | |
330 PRThreadState state, | |
331 PRUint32 stackSize) | |
332 { | |
333 return _PR_CreateThread(type, start, arg, priority, scope, state, | |
334 stackSize, _PR_GCABLE_THREAD); | |
335 } | |
336 | |
337 #ifdef SOLARIS | |
338 PR_IMPLEMENT(PRThread*) PR_CreateThreadBound(PRThreadType type, | |
339 void (*start)(void *arg), | |
340 void *arg, | |
341 PRUintn priority, | |
342 PRThreadScope scope, | |
343 PRThreadState state, | |
344 PRUint32 stackSize) | |
345 { | |
346 return _PR_CreateThread(type, start, arg, priority, scope, state, | |
347 stackSize, _PR_BOUND_THREAD); | |
348 } | |
349 #endif | |
350 | |
351 | |
352 PR_IMPLEMENT(PRThread*) PR_AttachThreadGCAble( | |
353 PRThreadType type, PRThreadPriority priority, PRThreadStack *stack) | |
354 { | |
355 /* $$$$ not sure how to finese this one */ | |
356 PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); | |
357 return NULL; | |
358 } | |
359 | |
360 PR_IMPLEMENT(void) PR_SetThreadGCAble() | |
361 { | |
362 if (!_pr_initialized) _PR_ImplicitInitialization(); | |
363 PR_Lock(_pr_activeLock); | |
364 _PR_MD_CURRENT_THREAD()->flags |= _PR_GCABLE_THREAD; | |
365 PR_Unlock(_pr_activeLock); | |
366 } | |
367 | |
368 PR_IMPLEMENT(void) PR_ClearThreadGCAble() | |
369 { | |
370 if (!_pr_initialized) _PR_ImplicitInitialization(); | |
371 PR_Lock(_pr_activeLock); | |
372 _PR_MD_CURRENT_THREAD()->flags &= (~_PR_GCABLE_THREAD); | |
373 PR_Unlock(_pr_activeLock); | |
374 } | |
375 | |
376 PR_IMPLEMENT(PRThreadScope) PR_GetThreadScope(const PRThread *thread) | |
377 { | |
378 if (!_pr_initialized) _PR_ImplicitInitialization(); | |
379 | |
380 if (_PR_IS_NATIVE_THREAD(thread)) { | |
381 return (thread->flags & _PR_BOUND_THREAD) ? PR_GLOBAL_BOUND_THREAD : | |
382 PR_GLOBAL_THREAD; | |
383 } else | |
384 return PR_LOCAL_THREAD; | |
385 } | |
386 | |
387 PR_IMPLEMENT(PRThreadType) PR_GetThreadType(const PRThread *thread) | |
388 { | |
389 return (thread->flags & _PR_SYSTEM) ? PR_SYSTEM_THREAD : PR_USER_THREAD; | |
390 } | |
391 | |
392 PR_IMPLEMENT(PRThreadState) PR_GetThreadState(const PRThread *thread) | |
393 { | |
394 return (NULL == thread->term) ? PR_UNJOINABLE_THREAD : PR_JOINABLE_THREAD; | |
395 } /* PR_GetThreadState */ |