imcplugin demo: Extend to support stat() call
[nativeclient.git] / service_runtime / nacl_app_thread.c
bloba9a24d5afe88b6a1372c36d2ef162f777eb722fb
1 /*
2 * Copyright 2008, Google Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
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
14 * distribution.
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.
35 #include <stdlib.h>
36 #include <string.h>
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
74 * shown.
76 WINDOWS_EXCEPTION_TRY;
77 NaClStartThreadInApp(natp, natp->user.eip);
78 WINDOWS_EXCEPTION_CATCH;
81 int NaClAppThreadCtor(struct NaClAppThread *natp,
82 struct NaClApp *nap,
83 int is_privileged,
84 uintptr_t usr_entry,
85 uintptr_t usr_esp,
86 uint16_t gs)
88 int rv;
89 uint16_t ldt_ix;
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);
107 effp = NULL;
109 if (!NaClMutexCtor(&natp->mu)) {
110 return 0;
112 if (!NaClCondVarCtor(&natp->cv)) {
113 goto cleanup_mutex;
116 natp->is_privileged = is_privileged;
117 natp->refcount = 1;
119 if (!NaClClosureResultCtor(&natp->result)) {
120 goto cleanup_cv;
122 natp->sysret = 0;
123 natp->nap = nap;
125 effp = (struct NaClDescEffectorLdr *) malloc(sizeof *effp);
126 if (NULL == effp) {
127 goto cleanup_cv;
130 if (!NaClDescEffectorLdrCtor(effp, natp)) {
131 goto cleanup_cv;
133 natp->effp = (struct NaClDescEffector *) effp;
134 effp = NULL;
136 natp->holding_sr_locks = 0;
137 natp->state = NACL_APP_THREAD_ALIVE;
139 natp->thread_num = -1; /* illegal index */
141 ldt_ix = gs >> 3;
143 nacl_thread[ldt_ix] = natp;
144 nacl_user[ldt_ix] = &natp->user;
145 nacl_sys[ldt_ix] = &natp->sys;
147 if(1)
148 NaClThreadLauncher((void *) natp);
149 else {
150 rv = NaClThreadCtor(&natp->thread,
151 NaClThreadLauncher,
152 (void *) natp,
153 NACL_KERN_STACK_SIZE);
154 if (rv != 0) {
155 return rv;
158 NaClClosureResultDtor(&natp->result);
159 cleanup_cv:
160 NaClCondVarDtor(&natp->cv);
161 cleanup_mutex:
162 NaClMutexDtor(&natp->mu);
163 free(effp);
164 natp->effp = NULL;
165 return 0;
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);
176 free(natp->effp);
177 natp->effp = NULL;
178 NaClLdtDeleteSelector(natp->user.gs);
179 NaClCondVarDtor(&natp->cv);
180 NaClMutexDtor(&natp->mu);
183 int NaClAppThreadAllocSegCtor(struct NaClAppThread *natp,
184 struct NaClApp *nap,
185 int is_privileged,
186 uintptr_t usr_entry,
187 uintptr_t usr_esp,
188 uintptr_t sys_tdb_base,
189 size_t tdb_size)
191 uint16_t gs;
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,
204 tdb_size);
206 NaClLog(4, "NaClAppThreadAllocSegCtor: esp 0x%08"PRIxPTR", gs 0x%02x\n",
207 usr_esp, gs);
209 if (0 == gs) {
210 NaClLog(LOG_ERROR, "No gs for thread, num_thread %d\n", nap->num_threads);
211 return 0;
214 return NaClAppThreadCtor(natp, nap, is_privileged, usr_entry, usr_esp, gs);
217 int NaClAppThreadIncRef(struct NaClAppThread *natp)
219 int refcount;
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);
231 return refcount;
234 int NaClAppThreadDecRef(struct NaClAppThread *natp)
236 int refcount;
238 NaClXMutexLock(&natp->mu);
239 refcount = --natp->refcount;
240 NaClXMutexUnlock(&natp->mu);
242 if (0 == refcount) {
243 NaClAppThreadDtor(natp);
244 free(natp);
246 return refcount;