OLD | NEW |
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 <windows.h> | 7 #include <windows.h> |
8 | 8 |
9 #include "native_client/src/shared/platform/nacl_check.h" | 9 #include "native_client/src/shared/platform/nacl_check.h" |
10 #include "native_client/src/shared/platform/nacl_sync_checked.h" | 10 #include "native_client/src/shared/platform/nacl_sync_checked.h" |
11 #include "native_client/src/trusted/service_runtime/nacl_app_thread.h" | 11 #include "native_client/src/trusted/service_runtime/nacl_app_thread.h" |
12 #include "native_client/src/trusted/service_runtime/sel_ldr.h" | 12 #include "native_client/src/trusted/service_runtime/sel_ldr.h" |
13 #include "native_client/src/trusted/service_runtime/thread_suspension.h" | 13 #include "native_client/src/trusted/service_runtime/thread_suspension.h" |
14 | 14 |
15 | 15 |
16 struct NaClAppThreadSuspendedRegisters { | 16 struct NaClAppThreadSuspendedRegisters { |
17 CONTEXT context; | 17 CONTEXT context; |
18 }; | 18 }; |
19 | 19 |
| 20 static HANDLE GetHostThreadHandle(struct NaClAppThread *natp) { |
| 21 CHECK(natp->host_thread_is_defined); |
| 22 return natp->host_thread.tid; |
| 23 } |
| 24 |
20 void NaClAppThreadSetSuspendState(struct NaClAppThread *natp, | 25 void NaClAppThreadSetSuspendState(struct NaClAppThread *natp, |
21 enum NaClSuspendState old_state, | 26 enum NaClSuspendState old_state, |
22 enum NaClSuspendState new_state) { | 27 enum NaClSuspendState new_state) { |
23 /* | 28 /* |
24 * Claiming suspend_mu here blocks a trusted/untrusted context | 29 * Claiming suspend_mu here blocks a trusted/untrusted context |
25 * switch while the thread is suspended or a suspension is in | 30 * switch while the thread is suspended or a suspension is in |
26 * progress. | 31 * progress. |
27 */ | 32 */ |
28 NaClXMutexLock(&natp->suspend_mu); | 33 NaClXMutexLock(&natp->suspend_mu); |
29 DCHECK(natp->suspend_state == old_state); | 34 DCHECK(natp->suspend_state == old_state); |
30 natp->suspend_state = new_state; | 35 natp->suspend_state = new_state; |
31 NaClXMutexUnlock(&natp->suspend_mu); | 36 NaClXMutexUnlock(&natp->suspend_mu); |
32 } | 37 } |
33 | 38 |
34 void NaClUntrustedThreadSuspend(struct NaClAppThread *natp, | 39 void NaClUntrustedThreadSuspend(struct NaClAppThread *natp, |
35 int save_registers) { | 40 int save_registers) { |
36 /* | 41 /* |
37 * We claim suspend_mu here to block trusted/untrusted context | 42 * We claim suspend_mu here to block trusted/untrusted context |
38 * switches by blocking NaClAppThreadSetSuspendState(). This blocks | 43 * switches by blocking NaClAppThreadSetSuspendState(). This blocks |
39 * any untrusted->trusted context switch that might happen before | 44 * any untrusted->trusted context switch that might happen before |
40 * SuspendThread() takes effect. It blocks any trusted->untrusted | 45 * SuspendThread() takes effect. It blocks any trusted->untrusted |
41 * context switch that might happen if the syscall running in the | 46 * context switch that might happen if the syscall running in the |
42 * target thread returns. | 47 * target thread returns. |
43 */ | 48 */ |
44 NaClXMutexLock(&natp->suspend_mu); | 49 NaClXMutexLock(&natp->suspend_mu); |
45 if (natp->suspend_state == NACL_APP_THREAD_UNTRUSTED) { | 50 if (natp->suspend_state == NACL_APP_THREAD_UNTRUSTED) { |
46 CONTEXT temp_context; | 51 CONTEXT temp_context; |
47 CONTEXT *context; | 52 CONTEXT *context; |
| 53 HANDLE thread_handle = GetHostThreadHandle(natp); |
48 | 54 |
49 if (SuspendThread(natp->thread.tid) == (DWORD) -1) { | 55 if (SuspendThread(thread_handle) == (DWORD) -1) { |
50 NaClLog(LOG_FATAL, "NaClUntrustedThreadSuspend: " | 56 NaClLog(LOG_FATAL, "NaClUntrustedThreadSuspend: " |
51 "SuspendThread() call failed\n"); | 57 "SuspendThread() call failed\n"); |
52 } | 58 } |
53 | 59 |
54 if (save_registers) { | 60 if (save_registers) { |
55 if (natp->suspended_registers == NULL) { | 61 if (natp->suspended_registers == NULL) { |
56 natp->suspended_registers = malloc(sizeof(*natp->suspended_registers)); | 62 natp->suspended_registers = malloc(sizeof(*natp->suspended_registers)); |
57 if (natp->suspended_registers == NULL) { | 63 if (natp->suspended_registers == NULL) { |
58 NaClLog(LOG_FATAL, "NaClUntrustedThreadSuspend: malloc() failed\n"); | 64 NaClLog(LOG_FATAL, "NaClUntrustedThreadSuspend: malloc() failed\n"); |
59 } | 65 } |
(...skipping 12 matching lines...) Expand all Loading... |
72 * able to return a snapshot of the register state once the | 78 * able to return a snapshot of the register state once the |
73 * thread has actually suspended. | 79 * thread has actually suspended. |
74 * | 80 * |
75 * If save_registers=0, the set of registers we request via | 81 * If save_registers=0, the set of registers we request via |
76 * ContextFlags is unimportant as long as it is non-empty. | 82 * ContextFlags is unimportant as long as it is non-empty. |
77 */ | 83 */ |
78 context = &temp_context; | 84 context = &temp_context; |
79 context->ContextFlags = CONTEXT_CONTROL; | 85 context->ContextFlags = CONTEXT_CONTROL; |
80 } | 86 } |
81 | 87 |
82 if (!GetThreadContext(natp->thread.tid, context)) { | 88 if (!GetThreadContext(thread_handle, context)) { |
83 NaClLog(LOG_FATAL, "NaClUntrustedThreadSuspend: " | 89 NaClLog(LOG_FATAL, "NaClUntrustedThreadSuspend: " |
84 "GetThreadContext() failed\n"); | 90 "GetThreadContext() failed\n"); |
85 } | 91 } |
86 } | 92 } |
87 /* | 93 /* |
88 * We leave suspend_mu held so that NaClAppThreadSetSuspendState() | 94 * We leave suspend_mu held so that NaClAppThreadSetSuspendState() |
89 * will block. | 95 * will block. |
90 */ | 96 */ |
91 } | 97 } |
92 | 98 |
93 void NaClUntrustedThreadResume(struct NaClAppThread *natp) { | 99 void NaClUntrustedThreadResume(struct NaClAppThread *natp) { |
94 if (natp->suspend_state == NACL_APP_THREAD_UNTRUSTED) { | 100 if (natp->suspend_state == NACL_APP_THREAD_UNTRUSTED) { |
95 if (ResumeThread(natp->thread.tid) == (DWORD) -1) { | 101 if (ResumeThread(GetHostThreadHandle(natp)) == (DWORD) -1) { |
96 NaClLog(LOG_FATAL, "NaClUntrustedThreadResume: " | 102 NaClLog(LOG_FATAL, "NaClUntrustedThreadResume: " |
97 "ResumeThread() call failed\n"); | 103 "ResumeThread() call failed\n"); |
98 } | 104 } |
99 } | 105 } |
100 NaClXMutexUnlock(&natp->suspend_mu); | 106 NaClXMutexUnlock(&natp->suspend_mu); |
101 } | 107 } |
102 | 108 |
103 void NaClAppThreadGetSuspendedRegistersInternal( | 109 void NaClAppThreadGetSuspendedRegistersInternal( |
104 struct NaClAppThread *natp, struct NaClSignalContext *regs) { | 110 struct NaClAppThread *natp, struct NaClSignalContext *regs) { |
105 NaClSignalContextFromHandler(regs, natp->suspended_registers); | 111 NaClSignalContextFromHandler(regs, natp->suspended_registers); |
106 } | 112 } |
107 | 113 |
108 void NaClAppThreadSetSuspendedRegistersInternal( | 114 void NaClAppThreadSetSuspendedRegistersInternal( |
109 struct NaClAppThread *natp, const struct NaClSignalContext *regs) { | 115 struct NaClAppThread *natp, const struct NaClSignalContext *regs) { |
110 NaClSignalContextToHandler(natp->suspended_registers, regs); | 116 NaClSignalContextToHandler(natp->suspended_registers, regs); |
111 if (!SetThreadContext(natp->thread.tid, | 117 if (!SetThreadContext(GetHostThreadHandle(natp), |
112 &natp->suspended_registers->context)) { | 118 &natp->suspended_registers->context)) { |
113 NaClLog(LOG_FATAL, "NaClAppThreadSetSuspendedRegistersInternal: " | 119 NaClLog(LOG_FATAL, "NaClAppThreadSetSuspendedRegistersInternal: " |
114 "SetThreadContext() failed\n"); | 120 "SetThreadContext() failed\n"); |
115 } | 121 } |
116 } | 122 } |
117 | 123 |
118 int NaClAppThreadUnblockIfFaulted(struct NaClAppThread *natp, int *signal) { | 124 int NaClAppThreadUnblockIfFaulted(struct NaClAppThread *natp, int *signal) { |
119 DWORD previous_suspend_count; | 125 DWORD previous_suspend_count; |
120 | 126 |
121 if (natp->fault_signal == 0) { | 127 if (natp->fault_signal == 0) { |
122 return 0; | 128 return 0; |
123 } | 129 } |
124 *signal = natp->fault_signal; | 130 *signal = natp->fault_signal; |
125 natp->fault_signal = 0; | 131 natp->fault_signal = 0; |
126 AtomicIncrement(&natp->nap->faulted_thread_count, -1); | 132 AtomicIncrement(&natp->nap->faulted_thread_count, -1); |
127 /* | 133 /* |
128 * Decrement Windows' suspension count for the thread. This undoes | 134 * Decrement Windows' suspension count for the thread. This undoes |
129 * the effect of debug_exception_handler.c's SuspendThread() call. | 135 * the effect of debug_exception_handler.c's SuspendThread() call. |
130 */ | 136 */ |
131 previous_suspend_count = ResumeThread(natp->thread.tid); | 137 previous_suspend_count = ResumeThread(GetHostThreadHandle(natp)); |
132 if (previous_suspend_count == (DWORD) -1) { | 138 if (previous_suspend_count == (DWORD) -1) { |
133 NaClLog(LOG_FATAL, "NaClAppThreadUnblockIfFaulted: " | 139 NaClLog(LOG_FATAL, "NaClAppThreadUnblockIfFaulted: " |
134 "ResumeThread() call failed\n"); | 140 "ResumeThread() call failed\n"); |
135 } | 141 } |
136 /* | 142 /* |
137 * This thread should already have been suspended using | 143 * This thread should already have been suspended using |
138 * NaClUntrustedThreadSuspend(), so the thread will not actually | 144 * NaClUntrustedThreadSuspend(), so the thread will not actually |
139 * resume until NaClUntrustedThreadResume() is called. | 145 * resume until NaClUntrustedThreadResume() is called. |
140 */ | 146 */ |
141 DCHECK(previous_suspend_count >= 2); | 147 DCHECK(previous_suspend_count >= 2); |
142 return 1; | 148 return 1; |
143 } | 149 } |
OLD | NEW |