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

Side by Side Diff: src/nonsfi/linux/linux_pthread_private.c

Issue 1212613002: Non-SFI mode: Add Linux asynchronous signal support (Closed) Base URL: https://chromium.googlesource.com/native_client/src/native_client.git@master
Patch Set: Fixed a small window where signals could corrupt the stack Created 5 years, 5 months 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
OLDNEW
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;
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);
37 /* 41 /*
38 * linux_clone_wrapper expects start_func's type is "int (*)(void *)". 42 * linux_clone_wrapper expects start_func's type is "int (*)(void *)".
39 * Although |start_func| has type "void (*)(void)", the type mismatching 43 * Although |start_func| has type "void (*)(void)", the type mismatching
40 * will not cause a problem. Passing a dummy |arg| (= 0) does nothing there. 44 * will not cause a problem. Passing a dummy |arg| (= 0) does nothing there.
41 * Also, start_func will never return. 45 * Also, start_func will never return.
42 */ 46 */
43 return irt_return_call(linux_clone_wrapper( 47 return irt_return_call(linux_clone_wrapper(
44 (uintptr_t) start_func, /* arg */ 0, flags, stack, 48 (uintptr_t) start_func, /* arg */ 0, flags, stack,
45 /* ptid */ NULL, thread_ptr, /* ctid */ NULL)); 49 child_tid, thread_ptr, /* ctid */ NULL));
50 }
51
52 static int nacl_irt_thread_create(void (*start_func)(void), void *stack,
53 void *thread_ptr) {
54 nacl_irt_tid_t child_tid;
55 return nacl_irt_thread_create_v0_2(start_func, stack, thread_ptr, &child_tid);
46 } 56 }
47 57
48 static void nacl_irt_thread_exit(int32_t *stack_flag) { 58 static void nacl_irt_thread_exit(int32_t *stack_flag) {
49 /* 59 /*
50 * We fill zero to stack_flag by ourselves instead of relying 60 * We fill zero to stack_flag by ourselves instead of relying
51 * on CLONE_CHILD_CLEARTID. We do everything in the following inline 61 * on CLONE_CHILD_CLEARTID. We do everything in the following inline
52 * assembly because we need to make sure we will never touch stack. 62 * assembly because we need to make sure we will never touch stack.
53 * 63 *
54 * We will set the stack pointer to zero at the beginning of the 64 * 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 65 * assembly code just in case an async signal arrives after setting
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 * That should never return. Crash hard if it does. 123 * That should never return. Crash hard if it does.
114 */ 124 */
115 __builtin_trap(); 125 __builtin_trap();
116 } 126 }
117 127
118 /* 128 /*
119 * Creates a thread and initializes the IRT-private TLS area. 129 * Creates a thread and initializes the IRT-private TLS area.
120 * Based on code from src/untrusted/irt/irt_thread.c 130 * Based on code from src/untrusted/irt/irt_thread.c
121 */ 131 */
122 int nacl_user_thread_create(void *(*start_func)(void *), void *stack, 132 int nacl_user_thread_create(void *(*start_func)(void *), void *stack,
123 void *thread_ptr) { 133 void *thread_ptr, nacl_irt_tid_t *child_tid) {
124 struct nc_combined_tdb *tdb; 134 struct nc_combined_tdb *tdb;
125 135
126 /* 136 /*
127 * Before we start the thread, allocate the IRT-private TLS area for it. 137 * Before we start the thread, allocate the IRT-private TLS area for it.
128 */ 138 */
129 size_t combined_size = __nacl_tls_combined_size(sizeof(*tdb)); 139 size_t combined_size = __nacl_tls_combined_size(sizeof(*tdb));
130 void *combined_area = malloc(combined_size); 140 void *combined_area = malloc(combined_size);
131 if (combined_area == NULL) 141 if (combined_area == NULL)
132 return EAGAIN; 142 return EAGAIN;
133 143
134 /* 144 /*
135 * Note that __nacl_tls_initialize_memory() is not reversible, 145 * Note that __nacl_tls_initialize_memory() is not reversible,
136 * because it takes a pointer that need not be aligned and can 146 * because it takes a pointer that need not be aligned and can
137 * return a pointer that is aligned. In order to 147 * return a pointer that is aligned. In order to
138 * free(combined_area) later, we must save the value of 148 * free(combined_area) later, we must save the value of
139 * combined_area. 149 * combined_area.
140 */ 150 */
141 void *irt_tp = __nacl_tls_initialize_memory(combined_area, sizeof(*tdb)); 151 void *irt_tp = __nacl_tls_initialize_memory(combined_area, sizeof(*tdb));
142 tdb = get_irt_tdb(irt_tp); 152 tdb = get_irt_tdb(irt_tp);
143 __nc_initialize_unjoinable_thread(tdb); 153 __nc_initialize_unjoinable_thread(tdb);
144 tdb->tdb.irt_thread_data = combined_area; 154 tdb->tdb.irt_thread_data = combined_area;
145 tdb->tdb.start_func = start_func; 155 tdb->tdb.start_func = start_func;
146 tdb->tdb.state = thread_ptr; 156 tdb->tdb.state = thread_ptr;
147 157
148 return nacl_irt_thread_create(irt_start_thread, stack, irt_tp); 158 return nacl_irt_thread_create_v0_2(irt_start_thread, stack, irt_tp,
159 child_tid);
149 } 160 }
150 161
151 /* 162 /*
152 * Destroys a thread created by nacl_user_thread_create. 163 * Destroys a thread created by nacl_user_thread_create.
153 * Based on code from src/untrusted/irt/irt_thread.c 164 * Based on code from src/untrusted/irt/irt_thread.c
154 */ 165 */
155 void nacl_user_thread_exit(int32_t *stack_flag) { 166 void nacl_user_thread_exit(int32_t *stack_flag) {
156 struct nc_combined_tdb *tdb = get_irt_tdb(__nacl_read_tp()); 167 struct nc_combined_tdb *tdb = get_irt_tdb(__nacl_read_tp());
157 168
158 __nc_tsd_exit(); 169 __nc_tsd_exit();
(...skipping 10 matching lines...) Expand all
169 nacl_irt_thread_exit(stack_flag); 180 nacl_irt_thread_exit(stack_flag);
170 } 181 }
171 182
172 void __nc_initialize_interfaces(void) { 183 void __nc_initialize_interfaces(void) {
173 const struct nacl_irt_thread init = { 184 const struct nacl_irt_thread init = {
174 nacl_irt_thread_create, 185 nacl_irt_thread_create,
175 nacl_irt_thread_exit, 186 nacl_irt_thread_exit,
176 nacl_irt_thread_nice, 187 nacl_irt_thread_nice,
177 }; 188 };
178 __libnacl_irt_thread = init; 189 __libnacl_irt_thread = init;
190 const struct nacl_irt_thread_v0_2 init_v0_2 = {
191 nacl_irt_thread_create_v0_2,
192 nacl_irt_thread_exit,
193 nacl_irt_thread_nice,
194 };
195 __libnacl_irt_thread_v0_2 = init_v0_2;
179 } 196 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698