OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2014 The Native Client Authors. All rights reserved. | 2 * Copyright 2014 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 <assert.h> | 7 #include <assert.h> |
8 #include <errno.h> | 8 #include <errno.h> |
9 | 9 |
10 #include "native_client/src/nonsfi/linux/linux_pthread_private.h" | 10 #include "native_client/src/nonsfi/linux/linux_pthread_private.h" |
11 #include "native_client/src/nonsfi/linux/linux_syscall_defines.h" | 11 #include "native_client/src/nonsfi/linux/linux_syscall_defines.h" |
12 #include "native_client/src/nonsfi/linux/linux_syscall_structs.h" | 12 #include "native_client/src/nonsfi/linux/linux_syscall_structs.h" |
13 #include "native_client/src/nonsfi/linux/linux_syscall_wrappers.h" | 13 #include "native_client/src/nonsfi/linux/linux_syscall_wrappers.h" |
14 #include "native_client/src/nonsfi/linux/linux_sys_private.h" | 14 #include "native_client/src/nonsfi/linux/linux_sys_private.h" |
15 #include "native_client/src/public/linux_syscalls/sched.h" | 15 #include "native_client/src/public/linux_syscalls/sched.h" |
16 #include "native_client/src/public/linux_syscalls/sys/syscall.h" | 16 #include "native_client/src/public/linux_syscalls/sys/syscall.h" |
17 #include "native_client/src/untrusted/nacl/nacl_irt.h" | 17 #include "native_client/src/untrusted/nacl/nacl_irt.h" |
18 #include "native_client/src/untrusted/nacl/nacl_thread.h" | 18 #include "native_client/src/untrusted/nacl/nacl_thread.h" |
19 #include "native_client/src/untrusted/pthread/pthread_internal.h" | 19 #include "native_client/src/untrusted/pthread/pthread_internal.h" |
20 | 20 |
21 struct nacl_irt_thread_v0_2 __libnacl_irt_thread_v0_2; | |
Mark Seaborn
2015/08/12 01:43:07
I don't think you need this, or the assignment to
Luis Héctor Chávez
2015/08/12 22:14:26
Done.
| |
22 | |
21 /* Convert a return value of a Linux syscall to the one of an IRT call. */ | 23 /* Convert a return value of a Linux syscall to the one of an IRT call. */ |
22 static uint32_t irt_return_call(uintptr_t result) { | 24 static uint32_t irt_return_call(uintptr_t result) { |
23 if (linux_is_error_result(result)) | 25 if (linux_is_error_result(result)) |
24 return -result; | 26 return -result; |
25 return 0; | 27 return 0; |
26 } | 28 } |
27 | 29 |
28 static int nacl_irt_thread_create(void (*start_func)(void), void *stack, | 30 static int nacl_irt_thread_create_v0_2(void (*start_func)(void), void *stack, |
29 void *thread_ptr) { | 31 void *thread_ptr, |
32 nacl_irt_tid_t *child_tid) { | |
30 /* | 33 /* |
31 * We do not use CLONE_CHILD_CLEARTID as we do not want any | 34 * We do not use CLONE_CHILD_CLEARTID as we do not want any |
32 * non-private futex signaling. Also, NaCl ABI does not require us | 35 * non-private futex signaling. Also, NaCl ABI does not require us |
33 * to signal the futex on stack_flag. | 36 * to signal the futex on stack_flag. |
34 */ | 37 */ |
35 int flags = (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | | 38 int flags = (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | |
36 CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS); | 39 CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS | |
40 CLONE_PARENT_SETTID); | |
41 /* | |
42 * In order to avoid allowing clone with and without CLONE_PARENT_SETTID, if | |
43 * |child_tid| is NULL, we provide a valid pointer whose value will be | |
44 * ignored. | |
45 */ | |
46 nacl_irt_tid_t ignored; | |
47 void *ptid = (child_tid != NULL) ? child_tid : &ignored; | |
48 | |
37 /* | 49 /* |
38 * linux_clone_wrapper expects start_func's type is "int (*)(void *)". | 50 * linux_clone_wrapper expects start_func's type is "int (*)(void *)". |
39 * Although |start_func| has type "void (*)(void)", the type mismatching | 51 * Although |start_func| has type "void (*)(void)", the type mismatching |
40 * will not cause a problem. Passing a dummy |arg| (= 0) does nothing there. | 52 * will not cause a problem. Passing a dummy |arg| (= 0) does nothing there. |
41 * Also, start_func will never return. | 53 * Also, start_func will never return. |
42 */ | 54 */ |
43 return irt_return_call(linux_clone_wrapper( | 55 return irt_return_call(linux_clone_wrapper( |
44 (uintptr_t) start_func, /* arg */ 0, flags, stack, | 56 (uintptr_t) start_func, /* arg */ 0, flags, stack, |
45 /* ptid */ NULL, thread_ptr, /* ctid */ NULL)); | 57 ptid, thread_ptr, /* ctid */ NULL)); |
58 } | |
59 | |
60 static int nacl_irt_thread_create(void (*start_func)(void), void *stack, | |
61 void *thread_ptr) { | |
62 nacl_irt_tid_t child_tid; | |
63 return nacl_irt_thread_create_v0_2(start_func, stack, thread_ptr, &child_tid); | |
46 } | 64 } |
47 | 65 |
48 static void nacl_irt_thread_exit(int32_t *stack_flag) { | 66 static void nacl_irt_thread_exit(int32_t *stack_flag) { |
49 /* | 67 /* |
50 * We fill zero to stack_flag by ourselves instead of relying | 68 * We fill zero to stack_flag by ourselves instead of relying |
51 * on CLONE_CHILD_CLEARTID. We do everything in the following inline | 69 * on CLONE_CHILD_CLEARTID. We do everything in the following inline |
52 * assembly because we need to make sure we will never touch stack. | 70 * assembly because we need to make sure we will never touch stack. |
53 * | 71 * |
54 * We will set the stack pointer to zero at the beginning of the | 72 * We will set the stack pointer to zero at the beginning of the |
55 * assembly code just in case an async signal arrives after setting | 73 * assembly code just in case an async signal arrives after setting |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
113 * That should never return. Crash hard if it does. | 131 * That should never return. Crash hard if it does. |
114 */ | 132 */ |
115 __builtin_trap(); | 133 __builtin_trap(); |
116 } | 134 } |
117 | 135 |
118 /* | 136 /* |
119 * Creates a thread and initializes the IRT-private TLS area. | 137 * Creates a thread and initializes the IRT-private TLS area. |
120 * Based on code from src/untrusted/irt/irt_thread.c | 138 * Based on code from src/untrusted/irt/irt_thread.c |
121 */ | 139 */ |
122 int nacl_user_thread_create(void *(*start_func)(void *), void *stack, | 140 int nacl_user_thread_create(void *(*start_func)(void *), void *stack, |
123 void *thread_ptr) { | 141 void *thread_ptr, nacl_irt_tid_t *child_tid) { |
124 struct nc_combined_tdb *tdb; | 142 struct nc_combined_tdb *tdb; |
125 | 143 |
126 /* | 144 /* |
127 * Before we start the thread, allocate the IRT-private TLS area for it. | 145 * Before we start the thread, allocate the IRT-private TLS area for it. |
128 */ | 146 */ |
129 size_t combined_size = __nacl_tls_combined_size(sizeof(*tdb)); | 147 size_t combined_size = __nacl_tls_combined_size(sizeof(*tdb)); |
130 void *combined_area = malloc(combined_size); | 148 void *combined_area = malloc(combined_size); |
131 if (combined_area == NULL) | 149 if (combined_area == NULL) |
132 return EAGAIN; | 150 return EAGAIN; |
133 | 151 |
134 /* | 152 /* |
135 * Note that __nacl_tls_initialize_memory() is not reversible, | 153 * Note that __nacl_tls_initialize_memory() is not reversible, |
136 * because it takes a pointer that need not be aligned and can | 154 * because it takes a pointer that need not be aligned and can |
137 * return a pointer that is aligned. In order to | 155 * return a pointer that is aligned. In order to |
138 * free(combined_area) later, we must save the value of | 156 * free(combined_area) later, we must save the value of |
139 * combined_area. | 157 * combined_area. |
140 */ | 158 */ |
141 void *irt_tp = __nacl_tls_initialize_memory(combined_area, sizeof(*tdb)); | 159 void *irt_tp = __nacl_tls_initialize_memory(combined_area, sizeof(*tdb)); |
142 tdb = get_irt_tdb(irt_tp); | 160 tdb = get_irt_tdb(irt_tp); |
143 __nc_initialize_unjoinable_thread(tdb); | 161 __nc_initialize_unjoinable_thread(tdb); |
144 tdb->tdb.irt_thread_data = combined_area; | 162 tdb->tdb.irt_thread_data = combined_area; |
145 tdb->tdb.start_func = start_func; | 163 tdb->tdb.start_func = start_func; |
146 tdb->tdb.state = thread_ptr; | 164 tdb->tdb.state = thread_ptr; |
147 | 165 |
148 return nacl_irt_thread_create(irt_start_thread, stack, irt_tp); | 166 return nacl_irt_thread_create_v0_2(irt_start_thread, stack, irt_tp, |
167 child_tid); | |
149 } | 168 } |
150 | 169 |
151 /* | 170 /* |
152 * Destroys a thread created by nacl_user_thread_create. | 171 * Destroys a thread created by nacl_user_thread_create. |
153 * Based on code from src/untrusted/irt/irt_thread.c | 172 * Based on code from src/untrusted/irt/irt_thread.c |
154 */ | 173 */ |
155 void nacl_user_thread_exit(int32_t *stack_flag) { | 174 void nacl_user_thread_exit(int32_t *stack_flag) { |
156 struct nc_combined_tdb *tdb = get_irt_tdb(__nacl_read_tp()); | 175 struct nc_combined_tdb *tdb = get_irt_tdb(__nacl_read_tp()); |
157 | 176 |
158 __nc_tsd_exit(); | 177 __nc_tsd_exit(); |
(...skipping 10 matching lines...) Expand all Loading... | |
169 nacl_irt_thread_exit(stack_flag); | 188 nacl_irt_thread_exit(stack_flag); |
170 } | 189 } |
171 | 190 |
172 void __nc_initialize_interfaces(void) { | 191 void __nc_initialize_interfaces(void) { |
173 const struct nacl_irt_thread init = { | 192 const struct nacl_irt_thread init = { |
174 nacl_irt_thread_create, | 193 nacl_irt_thread_create, |
175 nacl_irt_thread_exit, | 194 nacl_irt_thread_exit, |
176 nacl_irt_thread_nice, | 195 nacl_irt_thread_nice, |
177 }; | 196 }; |
178 __libnacl_irt_thread = init; | 197 __libnacl_irt_thread = init; |
198 const struct nacl_irt_thread_v0_2 init_v0_2 = { | |
199 nacl_irt_thread_create_v0_2, | |
200 nacl_irt_thread_exit, | |
201 nacl_irt_thread_nice, | |
202 }; | |
203 __libnacl_irt_thread_v0_2 = init_v0_2; | |
179 } | 204 } |
OLD | NEW |