2 * Copyright 2008, Google Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
15 * * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * NaCl Server Runtime user thread state.
38 #include "native_client/include/nacl_platform.h"
40 #include "native_client/service_runtime/sel_ldr.h"
41 #include "native_client/service_runtime/nacl_app_thread.h"
42 #include "native_client/service_runtime/nacl_desc_effector_ldr.h"
43 #include "native_client/service_runtime/nacl_bottom_half.h"
44 #include "native_client/service_runtime/nacl_globals.h"
45 #include "native_client/service_runtime/nacl_ldt.h"
46 #include "native_client/service_runtime/nacl_log.h"
47 #include "native_client/service_runtime/nacl_switch_to_app.h"
48 #include "native_client/service_runtime/nacl_sync_checked.h"
49 #include "native_client/service_runtime/sel_memory.h"
51 void WINAPI
NaClThreadLauncher(void *state
) {
52 struct NaClAppThread
*natp
;
54 NaClLog(4, "NaClThreadLauncher: entered\n");
55 natp
= (struct NaClAppThread
*) state
;
56 NaClLog(4, "natp = 0x%08"PRIxPTR
"\n", (uintptr_t) natp
);
57 NaClLog(4,"eip = 0x%08"PRIx32
"\n", natp
->user
.eip
);
59 NaClLog(4, "Obtaining thread_num\n");
61 * We have to hold the threads_mu lock until after thread_num field
62 * in this thread has been initialized. All other threads can only
63 * find and examine this natp through the threads table, so the fact
64 * that natp is not consistent (no thread_num) will not be visible.
66 NaClXMutexLock(&natp
->nap
->threads_mu
);
67 natp
->thread_num
= NaClAddThreadMu(natp
->nap
, natp
);
68 NaClXMutexUnlock(&natp
->nap
->threads_mu
);
69 NaClLog(4, "thread num %d\n", natp
->thread_num
);
72 * We need to set an exception handler in every thread we start,
73 * otherwise the system's default handler is called and a message box is
76 WINDOWS_EXCEPTION_TRY
;
77 NaClStartThreadInApp(natp
, natp
->user
.eip
);
78 WINDOWS_EXCEPTION_CATCH
;
81 int NaClAppThreadCtor(struct NaClAppThread
*natp
,
90 struct NaClDescEffectorLdr
*effp
;
92 NaClLog(4, "natp = 0x%08"PRIxPTR
"\n", (uintptr_t) natp
);
93 NaClLog(4, "nap = 0x%08"PRIxPTR
"\n", (uintptr_t) nap
);
94 NaClLog(4, "&nap->code_seg_sel = 0x%08"PRIxPTR
"\n",
95 (uintptr_t) &nap
->code_seg_sel
);
96 NaClLog(4, "&nap->data_seg_sel = 0x%08"PRIxPTR
"\n",
97 (uintptr_t) &nap
->data_seg_sel
);
98 NaClLog(4, "nap->code_seg_sel = 0x%02x\n", nap
->code_seg_sel
);
99 NaClLog(4, "nap->data_seg_sel = 0x%02x\n", nap
->data_seg_sel
);
100 NaClThreadContextCtor(&natp
->user
, usr_entry
, usr_esp
,
101 nap
->data_seg_sel
, gs
, nap
->code_seg_sel
);
102 NaClLog(4, "natp->user.cs: 0x%02x\n", natp
->user
.cs
);
103 NaClLog(4, "natp->user.fs: 0x%02x\n", natp
->user
.fs
);
104 NaClLog(4, "natp->user.gs: 0x%02x\n", natp
->user
.gs
);
105 NaClLog(4, "natp->user.ss: 0x%02x\n", natp
->user
.ss
);
109 if (!NaClMutexCtor(&natp
->mu
)) {
112 if (!NaClCondVarCtor(&natp
->cv
)) {
116 natp
->is_privileged
= is_privileged
;
119 if (!NaClClosureResultCtor(&natp
->result
)) {
125 effp
= (struct NaClDescEffectorLdr
*) malloc(sizeof *effp
);
130 if (!NaClDescEffectorLdrCtor(effp
, natp
)) {
133 natp
->effp
= (struct NaClDescEffector
*) effp
;
136 natp
->holding_sr_locks
= 0;
137 natp
->state
= NACL_APP_THREAD_ALIVE
;
139 natp
->thread_num
= -1; /* illegal index */
143 nacl_thread
[ldt_ix
] = natp
;
144 nacl_user
[ldt_ix
] = &natp
->user
;
145 nacl_sys
[ldt_ix
] = &natp
->sys
;
148 NaClThreadLauncher((void *) natp
);
150 rv
= NaClThreadCtor(&natp
->thread
,
153 NACL_KERN_STACK_SIZE
);
158 NaClClosureResultDtor(&natp
->result
);
160 NaClCondVarDtor(&natp
->cv
);
162 NaClMutexDtor(&natp
->mu
);
168 void NaClAppThreadDtor(struct NaClAppThread
*natp
)
171 * the thread must not be still running, else this crashes the system
173 NaClThreadDtor(&natp
->thread
);
174 NaClClosureResultDtor(&natp
->result
);
175 (*natp
->effp
->vtbl
->Dtor
)(natp
->effp
);
178 NaClLdtDeleteSelector(natp
->user
.gs
);
179 NaClCondVarDtor(&natp
->cv
);
180 NaClMutexDtor(&natp
->mu
);
183 int NaClAppThreadAllocSegCtor(struct NaClAppThread
*natp
,
188 uintptr_t sys_tdb_base
,
194 * Even though we don't know what segment base/range should gs
195 * select, we still need one, since gs identifies the thread when we
196 * context switch back. This use of a dummy %gs is only needed for
197 * the main thread, which is expected to invoke the tls_init syscall
198 * from its crt code (before main or much of libc can run). Other
199 * threads are spawned with the tdb address and size as a parameter.
201 gs
= NaClLdtAllocateByteSelector(NACL_LDT_DESCRIPTOR_DATA
,
203 (void *) sys_tdb_base
,
206 NaClLog(4, "NaClAppThreadAllocSegCtor: esp 0x%08"PRIxPTR
", gs 0x%02x\n",
210 NaClLog(LOG_ERROR
, "No gs for thread, num_thread %d\n", nap
->num_threads
);
214 return NaClAppThreadCtor(natp
, nap
, is_privileged
, usr_entry
, usr_esp
, gs
);
217 int NaClAppThreadIncRef(struct NaClAppThread
*natp
)
221 NaClXMutexLock(&natp
->mu
);
222 if (natp
->refcount
== 0) {
223 NaClLog(LOG_FATAL
, "NaClAppThreadIncRef: count was already 0!\n");
225 if (++natp
->refcount
== 0) {
226 NaClLog(LOG_FATAL
, "NaClAppThreadIncRef: refcount overflow\n");
228 refcount
= natp
->refcount
;
229 NaClXMutexUnlock(&natp
->mu
);
234 int NaClAppThreadDecRef(struct NaClAppThread
*natp
)
238 NaClXMutexLock(&natp
->mu
);
239 refcount
= --natp
->refcount
;
240 NaClXMutexUnlock(&natp
->mu
);
243 NaClAppThreadDtor(natp
);