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
4 * found in the LICENSE file.
9 #include "native_client/src/nonsfi/linux/linux_syscall_defines.h"
10 #include "native_client/src/nonsfi/linux/linux_syscall_structs.h"
11 #include "native_client/src/nonsfi/linux/linux_syscall_wrappers.h"
12 #include "native_client/src/nonsfi/linux/linux_syscalls.h"
13 #include "native_client/src/untrusted/nacl/nacl_thread.h"
14 #include "native_client/src/untrusted/pthread/pthread_internal.h"
16 /* Convert a return value of a Linux syscall to the one of an IRT call. */
17 static uint32_t irt_return_call(uintptr_t result) {
18 if (linux_is_error_result(result))
23 static int nacl_irt_thread_create(void (*start_func)(void), void *stack,
26 * The prototype of clone(2) is
28 * clone(int flags, void *stack, pid_t *ptid, void *tls, pid_t *ctid);
30 * See linux_syscall_wrappers.h for syscalls' calling conventions.
34 * We do not use CLONE_CHILD_CLEARTID as we do not want any
35 * non-private futex signaling. Also, NaCl ABI does not require us
36 * to signal the futex on stack_flag.
38 int flags = (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
39 CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS);
41 * Make sure we can access stack[0] and align the stack address to a
44 static const int kStackAlignmentMask = ~15;
45 stack = (void *) (((uintptr_t) stack - sizeof(uintptr_t)) &
47 /* We pass start_func using the stack top. */
48 ((uintptr_t *) stack)[0] = (uintptr_t) start_func;
52 struct linux_user_desc desc = create_linux_user_desc(
53 0 /* allocate_new_entry */, thread_ptr);
54 __asm__ __volatile__("int $0x80\n"
56 * If the return value of clone is non-zero, we are
57 * in the parent thread of clone.
62 * In child thread. Clear the frame pointer to
63 * prevent debuggers from unwinding beyond this,
64 * pop the stack to get start_func and call it.
68 /* start_func never finishes. */
72 : "a"(__NR_clone), "b"(flags), "c"(stack),
73 /* We do not use CLONE_PARENT_SETTID. */
76 /* We do not use CLONE_CHILD_CLEARTID. */
79 #elif defined(__arm__)
80 register uint32_t result __asm__("r0");
81 register uint32_t sysno __asm__("r7") = __NR_clone;
82 register uint32_t a1 __asm__("r0") = flags;
83 register uint32_t a2 __asm__("r1") = (uint32_t) stack;
84 register uint32_t a3 __asm__("r2") = 0; /* No CLONE_PARENT_SETTID. */
85 register uint32_t a4 __asm__("r3") = (uint32_t) thread_ptr;
86 register uint32_t a5 __asm__("r4") = 0; /* No CLONE_CHILD_CLEARTID. */
87 __asm__ __volatile__("svc #0\n"
89 * If the return value of clone is non-zero, we are
90 * in the parent thread of clone.
95 * In child thread. Clear the frame pointer to
96 * prevent debuggers from unwinding beyond this,
97 * pop the stack to get start_func and call it.
102 /* start_func never finishes. */
107 "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5)
110 # error Unsupported architecture
112 return irt_return_call(result);
115 static void nacl_irt_thread_exit(int32_t *stack_flag) {
117 * We fill zero to stack_flag by ourselves instead of relying
118 * on CLONE_CHILD_CLEARTID. We do everything in the following inline
119 * assembly because we need to make sure we will never touch stack.
121 * We will set the stack pointer to zero at the beginning of the
122 * assembly code just in case an async signal arrives after setting
123 * *stack_flag=0 but before calling the syscall, so that any signal
124 * handler crashes rather than running on a stack that has been
125 * reallocated to another thread.
127 #if defined(__i386__)
128 __asm__ __volatile__("mov $0, %%esp\n"
129 "movl $0, (%[stack_flag])\n"
132 :: [stack_flag]"r"(stack_flag), "a"(__NR_exit));
133 #elif defined(__arm__)
134 __asm__ __volatile__("mov sp, #0\n"
136 "str r7, [%[stack_flag]]\n"
140 :: [stack_flag]"r"(stack_flag), [sysno]"i"(__NR_exit)
143 # error Unsupported architecture
147 static int nacl_irt_thread_nice(const int nice) {
151 void __nc_initialize_interfaces(struct nacl_irt_thread *irt_thread) {
152 const struct nacl_irt_thread init = {
153 nacl_irt_thread_create,
154 nacl_irt_thread_exit,
155 nacl_irt_thread_nice,