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 <errno.h> | 8 #include <errno.h> |
8 | 9 |
| 10 #include "native_client/src/nonsfi/linux/linux_pthread_private.h" |
9 #include "native_client/src/nonsfi/linux/linux_syscall_defines.h" | 11 #include "native_client/src/nonsfi/linux/linux_syscall_defines.h" |
10 #include "native_client/src/nonsfi/linux/linux_syscall_structs.h" | 12 #include "native_client/src/nonsfi/linux/linux_syscall_structs.h" |
11 #include "native_client/src/nonsfi/linux/linux_syscall_wrappers.h" | 13 #include "native_client/src/nonsfi/linux/linux_syscall_wrappers.h" |
12 #include "native_client/src/nonsfi/linux/linux_sys_private.h" | 14 #include "native_client/src/nonsfi/linux/linux_sys_private.h" |
13 #include "native_client/src/public/linux_syscalls/sched.h" | 15 #include "native_client/src/public/linux_syscalls/sched.h" |
14 #include "native_client/src/public/linux_syscalls/sys/syscall.h" | 16 #include "native_client/src/public/linux_syscalls/sys/syscall.h" |
15 #include "native_client/src/untrusted/nacl/nacl_irt.h" | 17 #include "native_client/src/untrusted/nacl/nacl_irt.h" |
16 #include "native_client/src/untrusted/nacl/nacl_thread.h" | 18 #include "native_client/src/untrusted/nacl/nacl_thread.h" |
17 #include "native_client/src/untrusted/pthread/pthread_internal.h" | 19 #include "native_client/src/untrusted/pthread/pthread_internal.h" |
18 | 20 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
72 : "r7"); | 74 : "r7"); |
73 #else | 75 #else |
74 # error Unsupported architecture | 76 # error Unsupported architecture |
75 #endif | 77 #endif |
76 } | 78 } |
77 | 79 |
78 static int nacl_irt_thread_nice(const int nice) { | 80 static int nacl_irt_thread_nice(const int nice) { |
79 return 0; | 81 return 0; |
80 } | 82 } |
81 | 83 |
| 84 static struct nc_combined_tdb *get_irt_tdb(void *thread_ptr) { |
| 85 struct nc_combined_tdb *tdb = (void *) ((uintptr_t) thread_ptr + |
| 86 __nacl_tp_tdb_offset(sizeof(*tdb))); |
| 87 return tdb; |
| 88 } |
| 89 |
| 90 /* |
| 91 * This is the real first entry point for new threads. |
| 92 * Based on code from src/untrusted/irt/irt_thread.c |
| 93 */ |
| 94 static void irt_start_thread() { |
| 95 struct nc_combined_tdb *tdb = get_irt_tdb(__nacl_read_tp()); |
| 96 |
| 97 /* |
| 98 * Fetch the user's start routine. |
| 99 */ |
| 100 void *(*user_start)(void *) = tdb->tdb.start_func; |
| 101 |
| 102 /* |
| 103 * Now do per-thread initialization for the IRT-private C library state. |
| 104 */ |
| 105 __newlib_thread_init(); |
| 106 |
| 107 /* |
| 108 * Finally, run the user code. |
| 109 */ |
| 110 (*user_start)(tdb->tdb.state); |
| 111 |
| 112 /* |
| 113 * That should never return. Crash hard if it does. |
| 114 */ |
| 115 __builtin_trap(); |
| 116 } |
| 117 |
| 118 /* |
| 119 * Creates a thread and initializes the IRT-private TLS area. |
| 120 * Based on code from src/untrusted/irt/irt_thread.c |
| 121 */ |
| 122 int nacl_user_thread_create(void *(*start_func)(void *), void *stack, |
| 123 void *thread_ptr) { |
| 124 struct nc_combined_tdb *tdb; |
| 125 |
| 126 /* |
| 127 * Before we start the thread, allocate the IRT-private TLS area for it. |
| 128 */ |
| 129 size_t combined_size = __nacl_tls_combined_size(sizeof(*tdb)); |
| 130 void *combined_area = malloc(combined_size); |
| 131 if (combined_area == NULL) |
| 132 return EAGAIN; |
| 133 |
| 134 /* |
| 135 * Note that __nacl_tls_initialize_memory() is not reversible, |
| 136 * because it takes a pointer that need not be aligned and can |
| 137 * return a pointer that is aligned. In order to |
| 138 * free(combined_area) later, we must save the value of |
| 139 * combined_area. |
| 140 */ |
| 141 void *irt_tp = __nacl_tls_initialize_memory(combined_area, sizeof(*tdb)); |
| 142 tdb = get_irt_tdb(irt_tp); |
| 143 __nc_initialize_unjoinable_thread(tdb); |
| 144 tdb->tdb.irt_thread_data = combined_area; |
| 145 tdb->tdb.start_func = start_func; |
| 146 tdb->tdb.state = thread_ptr; |
| 147 |
| 148 return nacl_irt_thread_create(irt_start_thread, stack, irt_tp); |
| 149 } |
| 150 |
| 151 /* |
| 152 * Destroys a thread created by nacl_user_thread_create. |
| 153 * Based on code from src/untrusted/irt/irt_thread.c |
| 154 */ |
| 155 void nacl_user_thread_exit(int32_t *stack_flag) { |
| 156 struct nc_combined_tdb *tdb = get_irt_tdb(__nacl_read_tp()); |
| 157 |
| 158 __nc_tsd_exit(); |
| 159 |
| 160 /* |
| 161 * Sanity check: Check that this function was not called on a thread |
| 162 * created by the IRT's internal pthread_create(). For such |
| 163 * threads, irt_thread_data == NULL. |
| 164 */ |
| 165 assert(tdb->tdb.irt_thread_data != NULL); |
| 166 |
| 167 free(tdb->tdb.irt_thread_data); |
| 168 |
| 169 nacl_irt_thread_exit(stack_flag); |
| 170 } |
| 171 |
82 void __nc_initialize_interfaces(void) { | 172 void __nc_initialize_interfaces(void) { |
83 const struct nacl_irt_thread init = { | 173 const struct nacl_irt_thread init = { |
84 nacl_irt_thread_create, | 174 nacl_irt_thread_create, |
85 nacl_irt_thread_exit, | 175 nacl_irt_thread_exit, |
86 nacl_irt_thread_nice, | 176 nacl_irt_thread_nice, |
87 }; | 177 }; |
88 __libnacl_irt_thread = init; | 178 __libnacl_irt_thread = init; |
89 } | 179 } |
OLD | NEW |