Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(444)

Side by Side Diff: src/trusted/service_runtime/osx/thread_suspension.c

Issue 11543028: Allow creating a NaClAppThread without creating a new host OS thread (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client
Patch Set: Review: Add NACL_WUR Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/trusted/service_runtime/nacl_app_thread.c ('k') | src/trusted/service_runtime/sel_ldr.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be 3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file. 4 * found in the LICENSE file.
5 */ 5 */
6 6
7 #include <mach/mach.h> 7 #include <mach/mach.h>
8 #include <mach/thread_status.h> 8 #include <mach/thread_status.h>
9 9
10 #include "native_client/src/shared/platform/nacl_check.h" 10 #include "native_client/src/shared/platform/nacl_check.h"
11 #include "native_client/src/shared/platform/nacl_sync_checked.h" 11 #include "native_client/src/shared/platform/nacl_sync_checked.h"
12 #include "native_client/src/trusted/service_runtime/nacl_app_thread.h" 12 #include "native_client/src/trusted/service_runtime/nacl_app_thread.h"
13 #include "native_client/src/trusted/service_runtime/nacl_switch_to_app.h" 13 #include "native_client/src/trusted/service_runtime/nacl_switch_to_app.h"
14 #include "native_client/src/trusted/service_runtime/sel_ldr.h" 14 #include "native_client/src/trusted/service_runtime/sel_ldr.h"
15 #include "native_client/src/trusted/service_runtime/thread_suspension.h" 15 #include "native_client/src/trusted/service_runtime/thread_suspension.h"
16 16
17 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32 17 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
18 # include "native_client/src/trusted/service_runtime/arch/x86_32/nacl_switch_all _regs_32.h" 18 # include "native_client/src/trusted/service_runtime/arch/x86_32/nacl_switch_all _regs_32.h"
19 #endif 19 #endif
20 20
21 21
22 struct NaClAppThreadSuspendedRegisters { 22 struct NaClAppThreadSuspendedRegisters {
23 x86_thread_state_t context; 23 x86_thread_state_t context;
24 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32 24 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
25 struct NaClSwitchRemainingRegsState switch_state; 25 struct NaClSwitchRemainingRegsState switch_state;
26 #endif 26 #endif
27 }; 27 };
28 28
29 static mach_port_t GetHostThreadPort(struct NaClAppThread *natp) {
30 CHECK(natp->host_thread_is_defined);
31 return pthread_mach_thread_np(natp->host_thread.tid);
32 }
33
29 void NaClAppThreadSetSuspendState(struct NaClAppThread *natp, 34 void NaClAppThreadSetSuspendState(struct NaClAppThread *natp,
30 enum NaClSuspendState old_state, 35 enum NaClSuspendState old_state,
31 enum NaClSuspendState new_state) { 36 enum NaClSuspendState new_state) {
32 /* 37 /*
33 * Claiming suspend_mu here blocks a trusted/untrusted context 38 * Claiming suspend_mu here blocks a trusted/untrusted context
34 * switch while the thread is suspended or a suspension is in 39 * switch while the thread is suspended or a suspension is in
35 * progress. 40 * progress.
36 */ 41 */
37 NaClXMutexLock(&natp->suspend_mu); 42 NaClXMutexLock(&natp->suspend_mu);
38 DCHECK(natp->suspend_state == (Atomic32) old_state); 43 DCHECK(natp->suspend_state == (Atomic32) old_state);
39 natp->suspend_state = new_state; 44 natp->suspend_state = new_state;
40 NaClXMutexUnlock(&natp->suspend_mu); 45 NaClXMutexUnlock(&natp->suspend_mu);
41 } 46 }
42 47
43 void NaClUntrustedThreadSuspend(struct NaClAppThread *natp, 48 void NaClUntrustedThreadSuspend(struct NaClAppThread *natp,
44 int save_registers) { 49 int save_registers) {
45 /* 50 /*
46 * We claim suspend_mu here to block trusted/untrusted context 51 * We claim suspend_mu here to block trusted/untrusted context
47 * switches by blocking NaClAppThreadSetSuspendState(). This blocks 52 * switches by blocking NaClAppThreadSetSuspendState(). This blocks
48 * any untrusted->trusted context switch that might happen before 53 * any untrusted->trusted context switch that might happen before
49 * SuspendThread() takes effect. It blocks any trusted->untrusted 54 * SuspendThread() takes effect. It blocks any trusted->untrusted
50 * context switch that might happen if the syscall running in the 55 * context switch that might happen if the syscall running in the
51 * target thread returns. 56 * target thread returns.
52 */ 57 */
53 NaClXMutexLock(&natp->suspend_mu); 58 NaClXMutexLock(&natp->suspend_mu);
54 if (natp->suspend_state == NACL_APP_THREAD_UNTRUSTED) { 59 if (natp->suspend_state == NACL_APP_THREAD_UNTRUSTED) {
55 kern_return_t result; 60 kern_return_t result;
56 mach_msg_type_number_t size; 61 mach_msg_type_number_t size;
57 mach_port_t thread_port = pthread_mach_thread_np(natp->thread.tid); 62 mach_port_t thread_port = GetHostThreadPort(natp);
58 63
59 result = thread_suspend(thread_port); 64 result = thread_suspend(thread_port);
60 if (result != KERN_SUCCESS) { 65 if (result != KERN_SUCCESS) {
61 NaClLog(LOG_FATAL, "NaClUntrustedThreadSuspend: " 66 NaClLog(LOG_FATAL, "NaClUntrustedThreadSuspend: "
62 "thread_suspend() call failed: error %d\n", (int) result); 67 "thread_suspend() call failed: error %d\n", (int) result);
63 } 68 }
64 69
65 if (save_registers) { 70 if (save_registers) {
66 if (natp->suspended_registers == NULL) { 71 if (natp->suspended_registers == NULL) {
67 natp->suspended_registers = malloc(sizeof(*natp->suspended_registers)); 72 natp->suspended_registers = malloc(sizeof(*natp->suspended_registers));
(...skipping 13 matching lines...) Expand all
81 } 86 }
82 } 87 }
83 /* 88 /*
84 * We leave suspend_mu held so that NaClAppThreadSetSuspendState() 89 * We leave suspend_mu held so that NaClAppThreadSetSuspendState()
85 * will block. 90 * will block.
86 */ 91 */
87 } 92 }
88 93
89 void NaClUntrustedThreadResume(struct NaClAppThread *natp) { 94 void NaClUntrustedThreadResume(struct NaClAppThread *natp) {
90 if (natp->suspend_state == NACL_APP_THREAD_UNTRUSTED) { 95 if (natp->suspend_state == NACL_APP_THREAD_UNTRUSTED) {
91 mach_port_t thread_port = pthread_mach_thread_np(natp->thread.tid); 96 kern_return_t result = thread_resume(GetHostThreadPort(natp));
92 kern_return_t result = thread_resume(thread_port);
93 if (result != KERN_SUCCESS) { 97 if (result != KERN_SUCCESS) {
94 NaClLog(LOG_FATAL, "NaClUntrustedThreadResume: " 98 NaClLog(LOG_FATAL, "NaClUntrustedThreadResume: "
95 "thread_resume() call failed: error %d\n", (int) result); 99 "thread_resume() call failed: error %d\n", (int) result);
96 } 100 }
97 } 101 }
98 NaClXMutexUnlock(&natp->suspend_mu); 102 NaClXMutexUnlock(&natp->suspend_mu);
99 } 103 }
100 104
101 void NaClAppThreadGetSuspendedRegistersInternal( 105 void NaClAppThreadGetSuspendedRegistersInternal(
102 struct NaClAppThread *natp, struct NaClSignalContext *regs) { 106 struct NaClAppThread *natp, struct NaClSignalContext *regs) {
(...skipping 28 matching lines...) Expand all
131 state->context.uts.ts32.__ss = natp->user.ss; 135 state->context.uts.ts32.__ss = natp->user.ss;
132 } 136 }
133 #endif 137 #endif
134 138
135 NaClSignalContextFromMacThreadState(regs, 139 NaClSignalContextFromMacThreadState(regs,
136 &natp->suspended_registers->context); 140 &natp->suspended_registers->context);
137 } 141 }
138 142
139 void NaClAppThreadSetSuspendedRegistersInternal( 143 void NaClAppThreadSetSuspendedRegistersInternal(
140 struct NaClAppThread *natp, const struct NaClSignalContext *regs) { 144 struct NaClAppThread *natp, const struct NaClSignalContext *regs) {
141 mach_port_t thread_port = pthread_mach_thread_np(natp->thread.tid);
142 kern_return_t result; 145 kern_return_t result;
143 mach_msg_type_number_t size; 146 mach_msg_type_number_t size;
144 struct NaClAppThreadSuspendedRegisters *state = natp->suspended_registers; 147 struct NaClAppThreadSuspendedRegisters *state = natp->suspended_registers;
145 x86_thread_state_t context_copy; 148 x86_thread_state_t context_copy;
146 149
147 NaClSignalContextToMacThreadState(&state->context, regs); 150 NaClSignalContextToMacThreadState(&state->context, regs);
148 context_copy = state->context; 151 context_copy = state->context;
149 152
150 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32 153 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
151 /* 154 /*
152 * thread_set_state() ignores the %cs value we supply and always 155 * thread_set_state() ignores the %cs value we supply and always
153 * resets %cs back to the trusted-code value. This means we must 156 * resets %cs back to the trusted-code value. This means we must
154 * set up the new untrusted register state via a trusted code 157 * set up the new untrusted register state via a trusted code
155 * routine which returns to untrusted code via a springboard. 158 * routine which returns to untrusted code via a springboard.
156 * 159 *
157 * We reset %cs here in case the Mac kernel is ever fixed to not 160 * We reset %cs here in case the Mac kernel is ever fixed to not
158 * ignore the supplied %cs value. 161 * ignore the supplied %cs value.
159 */ 162 */
160 context_copy.uts.ts32.__cs = NaClGetGlobalCs(); 163 context_copy.uts.ts32.__cs = NaClGetGlobalCs();
161 context_copy.uts.ts32.__ds = NaClGetGlobalDs(); 164 context_copy.uts.ts32.__ds = NaClGetGlobalDs();
162 /* Reset these too just in case. */ 165 /* Reset these too just in case. */
163 context_copy.uts.ts32.__es = NaClGetGlobalDs(); 166 context_copy.uts.ts32.__es = NaClGetGlobalDs();
164 context_copy.uts.ts32.__ss = NaClGetGlobalDs(); 167 context_copy.uts.ts32.__ss = NaClGetGlobalDs();
165 context_copy.uts.ts32.__ecx = (uintptr_t) &state->switch_state; 168 context_copy.uts.ts32.__ecx = (uintptr_t) &state->switch_state;
166 context_copy.uts.ts32.__eip = (uintptr_t) NaClSwitchRemainingRegsViaECX; 169 context_copy.uts.ts32.__eip = (uintptr_t) NaClSwitchRemainingRegsViaECX;
167 NaClSwitchRemainingRegsSetup(&state->switch_state, natp, regs); 170 NaClSwitchRemainingRegsSetup(&state->switch_state, natp, regs);
168 #endif 171 #endif
169 172
170 size = sizeof(context_copy) / sizeof(natural_t); 173 size = sizeof(context_copy) / sizeof(natural_t);
171 result = thread_set_state(thread_port, x86_THREAD_STATE, 174 result = thread_set_state(GetHostThreadPort(natp), x86_THREAD_STATE,
172 (void *) &context_copy, size); 175 (void *) &context_copy, size);
173 if (result != KERN_SUCCESS) { 176 if (result != KERN_SUCCESS) {
174 NaClLog(LOG_FATAL, "NaClAppThreadSetSuspendedRegistersInternal: " 177 NaClLog(LOG_FATAL, "NaClAppThreadSetSuspendedRegistersInternal: "
175 "thread_set_state() call failed: error %d\n", result); 178 "thread_set_state() call failed: error %d\n", result);
176 } 179 }
177 } 180 }
178 181
179 int NaClAppThreadUnblockIfFaulted(struct NaClAppThread *natp, int *signal) { 182 int NaClAppThreadUnblockIfFaulted(struct NaClAppThread *natp, int *signal) {
180 mach_port_t thread_port;
181 kern_return_t result; 183 kern_return_t result;
182 if (natp->fault_signal == 0) { 184 if (natp->fault_signal == 0) {
183 return 0; 185 return 0;
184 } 186 }
185 *signal = natp->fault_signal; 187 *signal = natp->fault_signal;
186 natp->fault_signal = 0; 188 natp->fault_signal = 0;
187 AtomicIncrement(&natp->nap->faulted_thread_count, -1); 189 AtomicIncrement(&natp->nap->faulted_thread_count, -1);
188 /* 190 /*
189 * Decrement the kernel's suspension count for the thread. This 191 * Decrement the kernel's suspension count for the thread. This
190 * undoes the effect of mach_exception_handler.c's thread_suspend() 192 * undoes the effect of mach_exception_handler.c's thread_suspend()
191 * call. 193 * call.
192 */ 194 */
193 thread_port = pthread_mach_thread_np(natp->thread.tid); 195 result = thread_resume(GetHostThreadPort(natp));
194 result = thread_resume(thread_port);
195 if (result != KERN_SUCCESS) { 196 if (result != KERN_SUCCESS) {
196 NaClLog(LOG_FATAL, "NaClAppThreadUnblockIfFaulted: " 197 NaClLog(LOG_FATAL, "NaClAppThreadUnblockIfFaulted: "
197 "thread_resume() call failed: error %d\n", (int) result); 198 "thread_resume() call failed: error %d\n", (int) result);
198 } 199 }
199 return 1; 200 return 1;
200 } 201 }
OLDNEW
« no previous file with comments | « src/trusted/service_runtime/nacl_app_thread.c ('k') | src/trusted/service_runtime/sel_ldr.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698