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
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)