Mercurial > trustbridge > nss-cmake-static
comparison nspr/pr/src/md/windows/w95thred.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 #include <process.h> /* for _beginthreadex() */ | |
8 | |
9 #if defined(_MSC_VER) && _MSC_VER <= 1200 | |
10 /* | |
11 * VC++ 6.0 doesn't have DWORD_PTR. | |
12 */ | |
13 | |
14 typedef DWORD DWORD_PTR; | |
15 #endif /* _MSC_VER <= 1200 */ | |
16 | |
17 /* --- globals ------------------------------------------------ */ | |
18 #ifdef _PR_USE_STATIC_TLS | |
19 __declspec(thread) struct PRThread *_pr_thread_last_run; | |
20 __declspec(thread) struct PRThread *_pr_currentThread; | |
21 __declspec(thread) struct _PRCPU *_pr_currentCPU; | |
22 #else | |
23 DWORD _pr_currentThreadIndex; | |
24 DWORD _pr_lastThreadIndex; | |
25 DWORD _pr_currentCPUIndex; | |
26 #endif | |
27 int _pr_intsOff = 0; | |
28 _PRInterruptTable _pr_interruptTable[] = { { 0 } }; | |
29 | |
30 void | |
31 _PR_MD_EARLY_INIT() | |
32 { | |
33 #ifndef _PR_USE_STATIC_TLS | |
34 _pr_currentThreadIndex = TlsAlloc(); | |
35 _pr_lastThreadIndex = TlsAlloc(); | |
36 _pr_currentCPUIndex = TlsAlloc(); | |
37 #endif | |
38 } | |
39 | |
40 void _PR_MD_CLEANUP_BEFORE_EXIT(void) | |
41 { | |
42 _PR_NT_FreeSids(); | |
43 | |
44 _PR_MD_CleanupSockets(); | |
45 | |
46 WSACleanup(); | |
47 | |
48 #ifndef _PR_USE_STATIC_TLS | |
49 TlsFree(_pr_currentThreadIndex); | |
50 TlsFree(_pr_lastThreadIndex); | |
51 TlsFree(_pr_currentCPUIndex); | |
52 #endif | |
53 } | |
54 | |
55 PRStatus | |
56 _PR_MD_INIT_THREAD(PRThread *thread) | |
57 { | |
58 if (thread->flags & (_PR_PRIMORDIAL | _PR_ATTACHED)) { | |
59 /* | |
60 ** Warning: | |
61 ** -------- | |
62 ** NSPR requires a real handle to every thread. | |
63 ** GetCurrentThread() returns a pseudo-handle which | |
64 ** is not suitable for some thread operations (e.g., | |
65 ** suspending). Therefore, get a real handle from | |
66 ** the pseudo handle via DuplicateHandle(...) | |
67 */ | |
68 DuplicateHandle( | |
69 GetCurrentProcess(), /* Process of source handle */ | |
70 GetCurrentThread(), /* Pseudo Handle to dup */ | |
71 GetCurrentProcess(), /* Process of handle */ | |
72 &(thread->md.handle), /* resulting handle */ | |
73 0L, /* access flags */ | |
74 FALSE, /* Inheritable */ | |
75 DUPLICATE_SAME_ACCESS); /* Options */ | |
76 } | |
77 | |
78 /* Create the blocking IO semaphore */ | |
79 thread->md.blocked_sema = CreateSemaphore(NULL, 0, 1, NULL); | |
80 if (thread->md.blocked_sema == NULL) | |
81 return PR_FAILURE; | |
82 else | |
83 return PR_SUCCESS; | |
84 } | |
85 | |
86 static unsigned __stdcall | |
87 pr_root(void *arg) | |
88 { | |
89 PRThread *thread = (PRThread *)arg; | |
90 thread->md.start(thread); | |
91 return 0; | |
92 } | |
93 | |
94 PRStatus | |
95 _PR_MD_CREATE_THREAD(PRThread *thread, | |
96 void (*start)(void *), | |
97 PRThreadPriority priority, | |
98 PRThreadScope scope, | |
99 PRThreadState state, | |
100 PRUint32 stackSize) | |
101 { | |
102 | |
103 thread->md.start = start; | |
104 thread->md.handle = (HANDLE) _beginthreadex( | |
105 NULL, | |
106 thread->stack->stackSize, | |
107 pr_root, | |
108 (void *)thread, | |
109 CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION, | |
110 &(thread->id)); | |
111 if(!thread->md.handle) { | |
112 return PR_FAILURE; | |
113 } | |
114 | |
115 thread->md.id = thread->id; | |
116 /* | |
117 * On windows, a thread is created with a thread priority of | |
118 * THREAD_PRIORITY_NORMAL. | |
119 */ | |
120 if (priority != PR_PRIORITY_NORMAL) { | |
121 _PR_MD_SET_PRIORITY(&(thread->md), priority); | |
122 } | |
123 | |
124 /* Activate the thread */ | |
125 if ( ResumeThread( thread->md.handle ) != -1) | |
126 return PR_SUCCESS; | |
127 | |
128 return PR_FAILURE; | |
129 } | |
130 | |
131 void | |
132 _PR_MD_YIELD(void) | |
133 { | |
134 /* Can NT really yield at all? */ | |
135 Sleep(0); | |
136 } | |
137 | |
138 void | |
139 _PR_MD_SET_PRIORITY(_MDThread *thread, PRThreadPriority newPri) | |
140 { | |
141 int nativePri; | |
142 BOOL rv; | |
143 | |
144 if (newPri < PR_PRIORITY_FIRST) { | |
145 newPri = PR_PRIORITY_FIRST; | |
146 } else if (newPri > PR_PRIORITY_LAST) { | |
147 newPri = PR_PRIORITY_LAST; | |
148 } | |
149 switch (newPri) { | |
150 case PR_PRIORITY_LOW: | |
151 nativePri = THREAD_PRIORITY_BELOW_NORMAL; | |
152 break; | |
153 case PR_PRIORITY_NORMAL: | |
154 nativePri = THREAD_PRIORITY_NORMAL; | |
155 break; | |
156 case PR_PRIORITY_HIGH: | |
157 nativePri = THREAD_PRIORITY_ABOVE_NORMAL; | |
158 break; | |
159 case PR_PRIORITY_URGENT: | |
160 nativePri = THREAD_PRIORITY_HIGHEST; | |
161 } | |
162 rv = SetThreadPriority(thread->handle, nativePri); | |
163 PR_ASSERT(rv); | |
164 if (!rv) { | |
165 PR_LOG(_pr_thread_lm, PR_LOG_MIN, | |
166 ("PR_SetThreadPriority: can't set thread priority\n")); | |
167 } | |
168 return; | |
169 } | |
170 | |
171 const DWORD MS_VC_EXCEPTION = 0x406D1388; | |
172 | |
173 #pragma pack(push,8) | |
174 typedef struct tagTHREADNAME_INFO | |
175 { | |
176 DWORD dwType; // Must be 0x1000. | |
177 LPCSTR szName; // Pointer to name (in user addr space). | |
178 DWORD dwThreadID; // Thread ID (-1=caller thread). | |
179 DWORD dwFlags; // Reserved for future use, must be zero. | |
180 } THREADNAME_INFO; | |
181 #pragma pack(pop) | |
182 | |
183 void | |
184 _PR_MD_SET_CURRENT_THREAD_NAME(const char *name) | |
185 { | |
186 #ifdef _MSC_VER | |
187 THREADNAME_INFO info; | |
188 | |
189 if (!IsDebuggerPresent()) | |
190 return; | |
191 | |
192 info.dwType = 0x1000; | |
193 info.szName = (char*) name; | |
194 info.dwThreadID = -1; | |
195 info.dwFlags = 0; | |
196 | |
197 __try { | |
198 RaiseException(MS_VC_EXCEPTION, | |
199 0, | |
200 sizeof(info) / sizeof(ULONG_PTR), | |
201 (ULONG_PTR*)&info); | |
202 } __except(EXCEPTION_CONTINUE_EXECUTION) { | |
203 } | |
204 #endif | |
205 } | |
206 | |
207 void | |
208 _PR_MD_CLEAN_THREAD(PRThread *thread) | |
209 { | |
210 BOOL rv; | |
211 | |
212 if (thread->md.blocked_sema) { | |
213 rv = CloseHandle(thread->md.blocked_sema); | |
214 PR_ASSERT(rv); | |
215 thread->md.blocked_sema = 0; | |
216 } | |
217 | |
218 if (thread->md.handle) { | |
219 rv = CloseHandle(thread->md.handle); | |
220 PR_ASSERT(rv); | |
221 thread->md.handle = 0; | |
222 } | |
223 } | |
224 | |
225 void | |
226 _PR_MD_EXIT_THREAD(PRThread *thread) | |
227 { | |
228 _PR_MD_CLEAN_THREAD(thread); | |
229 _PR_MD_SET_CURRENT_THREAD(NULL); | |
230 } | |
231 | |
232 | |
233 void | |
234 _PR_MD_EXIT(PRIntn status) | |
235 { | |
236 _exit(status); | |
237 } | |
238 | |
239 PRInt32 _PR_MD_SETTHREADAFFINITYMASK(PRThread *thread, PRUint32 mask ) | |
240 { | |
241 #ifdef WINCE | |
242 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | |
243 return -1; | |
244 #else | |
245 DWORD_PTR rv; | |
246 | |
247 rv = SetThreadAffinityMask(thread->md.handle, mask); | |
248 | |
249 return rv?0:-1; | |
250 #endif | |
251 } | |
252 | |
253 PRInt32 _PR_MD_GETTHREADAFFINITYMASK(PRThread *thread, PRUint32 *mask) | |
254 { | |
255 #ifdef WINCE | |
256 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | |
257 return -1; | |
258 #else | |
259 BOOL rv; | |
260 DWORD_PTR process_mask; | |
261 DWORD_PTR system_mask; | |
262 | |
263 rv = GetProcessAffinityMask(GetCurrentProcess(), | |
264 &process_mask, &system_mask); | |
265 if (rv) | |
266 *mask = (PRUint32)process_mask; | |
267 | |
268 return rv?0:-1; | |
269 #endif | |
270 } | |
271 | |
272 void | |
273 _PR_MD_SUSPEND_CPU(_PRCPU *cpu) | |
274 { | |
275 _PR_MD_SUSPEND_THREAD(cpu->thread); | |
276 } | |
277 | |
278 void | |
279 _PR_MD_RESUME_CPU(_PRCPU *cpu) | |
280 { | |
281 _PR_MD_RESUME_THREAD(cpu->thread); | |
282 } | |
283 | |
284 void | |
285 _PR_MD_SUSPEND_THREAD(PRThread *thread) | |
286 { | |
287 if (_PR_IS_NATIVE_THREAD(thread)) { | |
288 DWORD previousSuspendCount; | |
289 /* XXXMB - SuspendThread() is not a blocking call; how do we | |
290 * know when the thread is *REALLY* suspended? | |
291 */ | |
292 previousSuspendCount = SuspendThread(thread->md.handle); | |
293 PR_ASSERT(previousSuspendCount == 0); | |
294 } | |
295 } | |
296 | |
297 void | |
298 _PR_MD_RESUME_THREAD(PRThread *thread) | |
299 { | |
300 if (_PR_IS_NATIVE_THREAD(thread)) { | |
301 DWORD previousSuspendCount; | |
302 previousSuspendCount = ResumeThread(thread->md.handle); | |
303 PR_ASSERT(previousSuspendCount == 1); | |
304 } | |
305 } | |
306 | |
307 PRThread* | |
308 _MD_CURRENT_THREAD(void) | |
309 { | |
310 PRThread *thread; | |
311 | |
312 thread = _MD_GET_ATTACHED_THREAD(); | |
313 | |
314 if (NULL == thread) { | |
315 thread = _PRI_AttachThread( | |
316 PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, NULL, 0); | |
317 } | |
318 PR_ASSERT(thread != NULL); | |
319 return thread; | |
320 } | |
321 | |
322 #ifdef NSPR_STATIC | |
323 | |
324 // The following code is from Chromium src/base/thread_local_storage_win.cc, | |
325 // r11329. | |
326 | |
327 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | |
328 // | |
329 // Redistribution and use in source and binary forms, with or without | |
330 // modification, are permitted provided that the following conditions are | |
331 // met: | |
332 // | |
333 // * Redistributions of source code must retain the above copyright | |
334 // notice, this list of conditions and the following disclaimer. | |
335 // * Redistributions in binary form must reproduce the above | |
336 // copyright notice, this list of conditions and the following disclaimer | |
337 // in the documentation and/or other materials provided with the | |
338 // distribution. | |
339 // * Neither the name of Google Inc. nor the names of its | |
340 // contributors may be used to endorse or promote products derived from | |
341 // this software without specific prior written permission. | |
342 // | |
343 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
344 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
345 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
346 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
347 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
348 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
349 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
350 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
351 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
352 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
353 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
354 | |
355 // Thread Termination Callbacks. | |
356 // Windows doesn't support a per-thread destructor with its | |
357 // TLS primitives. So, we build it manually by inserting a | |
358 // function to be called on each thread's exit. | |
359 // This magic is from http://www.codeproject.com/threads/tls.asp | |
360 // and it works for VC++ 7.0 and later. | |
361 | |
362 // Force a reference to _tls_used to make the linker create the TLS directory | |
363 // if it's not already there. (e.g. if __declspec(thread) is not used). | |
364 // Force a reference to p_thread_callback_nspr to prevent whole program | |
365 // optimization from discarding the variable. | |
366 #ifdef _WIN64 | |
367 | |
368 #pragma comment(linker, "/INCLUDE:_tls_used") | |
369 #pragma comment(linker, "/INCLUDE:p_thread_callback_nspr") | |
370 | |
371 #else // _WIN64 | |
372 | |
373 #pragma comment(linker, "/INCLUDE:__tls_used") | |
374 #pragma comment(linker, "/INCLUDE:_p_thread_callback_nspr") | |
375 | |
376 #endif // _WIN64 | |
377 | |
378 // Static callback function to call with each thread termination. | |
379 static void NTAPI PR_OnThreadExit(PVOID module, DWORD reason, PVOID reserved) | |
380 { | |
381 PRThread *me; | |
382 | |
383 switch (reason) { | |
384 case DLL_PROCESS_ATTACH: | |
385 break; | |
386 case DLL_THREAD_ATTACH: | |
387 break; | |
388 case DLL_THREAD_DETACH: | |
389 if (_pr_initialized) { | |
390 me = _MD_GET_ATTACHED_THREAD(); | |
391 if ((me != NULL) && (me->flags & _PR_ATTACHED)) | |
392 _PRI_DetachThread(); | |
393 } | |
394 break; | |
395 case DLL_PROCESS_DETACH: | |
396 break; | |
397 } | |
398 } | |
399 | |
400 // .CRT$XLA to .CRT$XLZ is an array of PIMAGE_TLS_CALLBACK pointers that are | |
401 // called automatically by the OS loader code (not the CRT) when the module is | |
402 // loaded and on thread creation. They are NOT called if the module has been | |
403 // loaded by a LoadLibrary() call. It must have implicitly been loaded at | |
404 // process startup. | |
405 // By implicitly loaded, I mean that it is directly referenced by the main EXE | |
406 // or by one of its dependent DLLs. Delay-loaded DLL doesn't count as being | |
407 // implicitly loaded. | |
408 // | |
409 // See VC\crt\src\tlssup.c for reference. | |
410 | |
411 // The linker must not discard p_thread_callback_nspr. (We force a reference | |
412 // to this variable with a linker /INCLUDE:symbol pragma to ensure that.) If | |
413 // this variable is discarded, the PR_OnThreadExit function will never be | |
414 // called. | |
415 #ifdef _WIN64 | |
416 | |
417 // .CRT section is merged with .rdata on x64 so it must be constant data. | |
418 #pragma const_seg(".CRT$XLB") | |
419 // When defining a const variable, it must have external linkage to be sure the | |
420 // linker doesn't discard it. | |
421 extern const PIMAGE_TLS_CALLBACK p_thread_callback_nspr; | |
422 const PIMAGE_TLS_CALLBACK p_thread_callback_nspr = PR_OnThreadExit; | |
423 | |
424 // Reset the default section. | |
425 #pragma const_seg() | |
426 | |
427 #else // _WIN64 | |
428 | |
429 #pragma data_seg(".CRT$XLB") | |
430 PIMAGE_TLS_CALLBACK p_thread_callback_nspr = PR_OnThreadExit; | |
431 | |
432 // Reset the default section. | |
433 #pragma data_seg() | |
434 | |
435 #endif // _WIN64 | |
436 | |
437 #endif // NSPR_STATIC |