1 : /*
2 : * Copyright (c) 2011 The Native Client Authors. All rights reserved.
3 : * Use of this source code is governed by a BSD-style license that can be
4 : * found in the LICENSE file.
5 : */
6 :
7 : /*
8 : * NaCl Server Runtime threads implementation layer.
9 : */
10 :
11 : #include <process.h>
12 : #include <string.h>
13 : #include <sys/types.h>
14 : #include <signal.h>
15 :
16 : #include "native_client/src/shared/platform/nacl_log.h"
17 : #include "native_client/src/shared/platform/nacl_threads.h"
18 : #include "native_client/src/trusted/service_runtime/nacl_config.h"
19 :
20 : int NaClThreadCtor(struct NaClThread *ntp,
21 : void (WINAPI *start_fn)(void *),
22 : void *state,
23 9 : size_t stack_size) {
24 : HANDLE handle;
25 : DWORD actual_stack_size;
26 :
27 9 : if (stack_size > MAXDWORD) {
28 : NaClLog(LOG_ERROR,
29 : ("NaClThreadCtor: "
30 : "_beginthreadex failed, stack request out of range\n"),
31 0 : errno);
32 0 : return 0;
33 : } else {
34 9 : actual_stack_size = (DWORD)stack_size;
35 : }
36 :
37 : handle = (HANDLE) _beginthreadex(NULL, /* default security */
38 : actual_stack_size,
39 : (unsigned (WINAPI *)(void *)) start_fn,
40 : /* the argument for the thread function */
41 : state,
42 : CREATE_SUSPENDED , /* start suspended */
43 9 : NULL);
44 9 : if (0 == handle){ /* we don't need the thread id */
45 : NaClLog(LOG_ERROR,
46 : "NaClThreadCtor: _beginthreadex failed, errno %d\n",
47 0 : errno);
48 0 : return 0;
49 : }
50 9 : ntp->tid = handle; /* we need the handle to kill the thread etc. */
51 :
52 : /* Now that the structure is filled, the thread can start */
53 9 : ResumeThread(handle);
54 :
55 9 : return 1;
56 9 : }
57 :
58 : int NaClThreadCreateJoinable(struct NaClThread *ntp,
59 : void (WINAPI *start_fn)(void *),
60 : void *state,
61 6 : size_t stack_size) {
62 6 : return NaClThreadCtor(ntp, start_fn, state, stack_size);
63 6 : }
64 :
65 1 : void NaClThreadDtor(struct NaClThread *ntp) {
66 : /*
67 : * the handle is not closed when the thread exits because we are
68 : * using _beginthreadex and not _beginthread, so we must close it
69 : * manually
70 : */
71 1 : CloseHandle(ntp->tid);
72 1 : }
73 :
74 6 : void NaClThreadJoin(struct NaClThread *ntp) {
75 6 : DWORD result = WaitForSingleObject(ntp->tid, INFINITE);
76 6 : if (result != WAIT_OBJECT_0) {
77 0 : NaClLog(LOG_ERROR, "NaClThreadJoin: unexpected result of thread\n");
78 : }
79 6 : CloseHandle(ntp->tid);
80 6 : }
81 :
82 3 : void NaClThreadExit(void) {
83 : /*
84 : * On Windows, the exit status of a process is taken to be the exit
85 : * status of the last thread that exited. If a process is killed
86 : * with TerminateProcess(), the threads exit in a non-deterministic
87 : * order. In that case, the thread exit status we return here could
88 : * become the process's exit status. We return a magic number so
89 : * that we can identify when that happens.
90 : * See https://code.google.com/p/nativeclient/issues/detail?id=2870
91 : */
92 3 : _endthreadex(0xdecea5ed);
93 0 : }
94 :
95 7 : uint32_t NaClThreadId(void) {
96 7 : return GetCurrentThreadId();
97 7 : }
98 :
99 1 : void NaClThreadYield(void) {
100 1 : SwitchToThread();
101 1 : }
|