| 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 "native_client/src/include/nacl_platform.h" | 7 #include "native_client/src/include/nacl_platform.h" |
| 8 #include "native_client/src/include/nacl_macros.h" | 8 #include "native_client/src/include/nacl_macros.h" |
| 9 #include "native_client/src/include/portability.h" | 9 #include "native_client/src/include/portability.h" |
| 10 #include "native_client/src/shared/platform/nacl_check.h" | 10 #include "native_client/src/shared/platform/nacl_check.h" |
| 11 #include "native_client/src/shared/platform/nacl_sync_checked.h" | 11 #include "native_client/src/shared/platform/nacl_sync_checked.h" |
| 12 #include "native_client/src/trusted/service_runtime/arch/arm/sel_ldr_arm.h" | 12 #include "native_client/src/trusted/service_runtime/arch/mips/sel_ldr_mips.h" |
| 13 #include "native_client/src/trusted/service_runtime/nacl_app_thread.h" | 13 #include "native_client/src/trusted/service_runtime/nacl_app_thread.h" |
| 14 #include "native_client/src/trusted/service_runtime/nacl_globals.h" | 14 #include "native_client/src/trusted/service_runtime/nacl_globals.h" |
| 15 #include "native_client/src/trusted/service_runtime/nacl_tls.h" | 15 #include "native_client/src/trusted/service_runtime/nacl_tls.h" |
| 16 #include "native_client/src/trusted/service_runtime/sel_ldr.h" | 16 #include "native_client/src/trusted/service_runtime/sel_ldr.h" |
| 17 #include "native_client/src/trusted/service_runtime/sel_memory.h" | 17 #include "native_client/src/trusted/service_runtime/sel_memory.h" |
| 18 | 18 |
| 19 static struct NaClMutex gNaClTlsMu; | 19 static struct NaClMutex gNaClTlsMu; |
| 20 static int gNaClThreadIdxInUse[NACL_THREAD_MAX]; /* bool */ | 20 static int gNaClThreadIdxInUse[NACL_THREAD_MAX]; /* bool */ |
| 21 static size_t const kNumThreads = NACL_ARRAY_SIZE_UNSAFE(gNaClThreadIdxInUse); | |
| 22 | 21 |
| 23 /* | 22 /* |
| 24 * This holds the index of the current thread. | 23 * This holds the index of the current thread. |
| 25 * This is also used directly in nacl_syscall.S (NaClSyscallSeg). | 24 * This is also used directly in nacl_syscall.S (NaClSyscallSeg). |
| 26 */ | 25 */ |
| 27 __thread uint32_t gNaClThreadIdx = NACL_TLS_INDEX_INVALID; | 26 __thread uint32_t gNaClThreadIdx = NACL_TLS_INDEX_INVALID; |
| 28 | 27 |
| 29 uint32_t NaClTlsGetIdx(void) { | 28 uint32_t NaClTlsGetIdx(void) { |
| 30 return gNaClThreadIdx; | 29 return gNaClThreadIdx; |
| 31 } | 30 } |
| 32 | 31 |
| 33 void NaClTlsSetIdx(uint32_t tls_idx) { | 32 void NaClTlsSetIdx(uint32_t tls_idx) { |
| 34 gNaClThreadIdx = tls_idx; | 33 gNaClThreadIdx = tls_idx; |
| 35 } | 34 } |
| 36 | 35 |
| 37 uint32_t NaClGetThreadIdx(struct NaClAppThread *natp) { | 36 uint32_t NaClGetThreadIdx(struct NaClAppThread *natp) { |
| 38 return natp->user.tls_idx; | 37 return natp->user.tls_idx; |
| 39 } | 38 } |
| 40 | 39 |
| 41 | 40 |
| 42 int NaClTlsInit() { | 41 int NaClTlsInit() { |
| 43 size_t i; | 42 size_t i; |
| 44 | 43 |
| 45 NaClLog(2, "NaClTlsInit\n"); | 44 NaClLog(2, "NaClTlsInit\n"); |
| 46 | 45 |
| 47 for (i = 0; i < kNumThreads; i++) { | 46 for (i = 0; i < NACL_ARRAY_SIZE(gNaClThreadIdxInUse); i++) { |
| 48 gNaClThreadIdxInUse[i] = 0; | 47 gNaClThreadIdxInUse[i] = 0; |
| 49 } | 48 } |
| 50 if (!NaClMutexCtor(&gNaClTlsMu)) { | 49 if (!NaClMutexCtor(&gNaClTlsMu)) { |
| 51 NaClLog(LOG_WARNING, | 50 NaClLog(LOG_WARNING, |
| 52 "NaClTlsInit: gNaClTlsMu initialization failed\n"); | 51 "NaClTlsInit: gNaClTlsMu initialization failed\n"); |
| 53 return 0; | 52 return 0; |
| 54 } | 53 } |
| 55 | 54 |
| 56 return 1; | 55 return 1; |
| 57 } | 56 } |
| 58 | 57 |
| 59 | 58 |
| 60 void NaClTlsFini() { | 59 void NaClTlsFini() { |
| 61 NaClLog(2, "NaClTlsFini\n"); | 60 NaClLog(2, "NaClTlsFini\n"); |
| 62 NaClMutexDtor(&gNaClTlsMu); | 61 NaClMutexDtor(&gNaClTlsMu); |
| 63 } | 62 } |
| 64 | 63 |
| 64 |
| 65 static int NaClThreadIdxAllocate() { | 65 static int NaClThreadIdxAllocate() { |
| 66 size_t i; | 66 int i; |
| 67 | 67 |
| 68 NaClXMutexLock(&gNaClTlsMu); | 68 NaClXMutexLock(&gNaClTlsMu); |
| 69 for (i = 1; i < kNumThreads; i++) { | 69 for (i = 0; i < NACL_THREAD_MAX; i++) { |
| 70 if (!gNaClThreadIdxInUse[i]) { | 70 if (!gNaClThreadIdxInUse[i]) { |
| 71 gNaClThreadIdxInUse[i] = 1; | 71 gNaClThreadIdxInUse[i] = 1; |
| 72 break; | 72 break; |
| 73 } | 73 } |
| 74 } | 74 } |
| 75 NaClXMutexUnlock(&gNaClTlsMu); | 75 NaClXMutexUnlock(&gNaClTlsMu); |
| 76 | 76 |
| 77 if (kNumThreads != i) { | 77 if (NACL_THREAD_MAX != i) { |
| 78 return i; | 78 return i; |
| 79 } | 79 } |
| 80 | 80 |
| 81 NaClLog(LOG_ERROR, "NaClThreadIdxAllocate: no more slots for a thread\n"); | 81 NaClLog(LOG_ERROR, "NaClThreadIdxAllocate: no more slots for a thread\n"); |
| 82 return NACL_TLS_INDEX_INVALID; | 82 return -1; |
| 83 } | 83 } |
| 84 | 84 |
| 85 | 85 |
| 86 /* | 86 /* |
| 87 * Allocation does not mean we can set gNaClThreadIdx, since we are not | 87 * Allocation does not mean we can set gNaClThreadIdx, since we are not |
| 88 * that thread. Setting it must wait until the thread actually launches. | 88 * that thread. Setting it must wait until the thread actually launches. |
| 89 */ | 89 */ |
| 90 uint32_t NaClTlsAllocate(struct NaClAppThread *natp) { | 90 uint32_t NaClTlsAllocate(struct NaClAppThread *natp) { |
| 91 int idx = NaClThreadIdxAllocate(); | 91 int idx = NaClThreadIdxAllocate(); |
| 92 | 92 |
| 93 NaClLog(2, "NaClTlsAllocate: $tp %x idx %d\n", natp->tls_values.tls1, idx); | 93 NaClLog(2, "NaClTlsAllocate: $tp %x idx %d\n", natp->tls_values.tls1, idx); |
| 94 if (NACL_TLS_INDEX_INVALID != idx) { | 94 if (-1 == idx) { |
| 95 natp->user.r9 = natp->tls_values.tls1; | 95 NaClLog(LOG_FATAL, |
| 96 "NaClTlsAllocate: thread limit reached\n"); |
| 97 return NACL_TLS_INDEX_INVALID; |
| 96 } | 98 } |
| 97 | 99 |
| 98 return idx; | 100 natp->user.t8 = natp->tls_values.tls1; |
| 101 |
| 102 /* |
| 103 * Bias by 1: successful return value is never 0. |
| 104 */ |
| 105 return idx + 1; |
| 99 } | 106 } |
| 100 | 107 |
| 101 | 108 |
| 102 void NaClTlsFree(struct NaClAppThread *natp) { | 109 void NaClTlsFree(struct NaClAppThread *natp) { |
| 103 uint32_t idx = NaClGetThreadIdx(natp); | 110 uint32_t idx = NaClGetThreadIdx(natp); |
| 104 NaClLog(2, | 111 NaClLog(2, |
| 105 "NaClTlsFree: old idx %d $tp %x\n", | 112 "NaClTlsFree: old idx %d $tp %x\n", |
| 106 idx, natp->user.r9); | 113 idx, natp->user.t8); |
| 107 | 114 |
| 108 NaClXMutexLock(&gNaClTlsMu); | 115 NaClXMutexLock(&gNaClTlsMu); |
| 109 gNaClThreadIdxInUse[idx] = 0; | 116 gNaClThreadIdxInUse[idx - 1] = 0; |
| 110 NaClXMutexUnlock(&gNaClTlsMu); | 117 NaClXMutexUnlock(&gNaClTlsMu); |
| 111 | 118 |
| 112 natp->user.r9 = 0; | 119 natp->user.t8 = 0; |
| 113 } | 120 } |
| 114 | 121 |
| 115 | 122 |
| 116 void NaClTlsChange(struct NaClAppThread *natp) { | 123 void NaClTlsChange(struct NaClAppThread *natp) { |
| 117 NaClLog(2, "NaClTlsChange: $tp %x\n", natp->tls_values.tls1); | 124 NaClLog(2, "NaClTlsChange: $tp %x\n", natp->tls_values.tls1); |
| 118 | 125 |
| 119 natp->user.r9 = natp->tls_values.tls1; | 126 natp->user.t8 = natp->tls_values.tls1; |
| 120 } | 127 } |
| OLD | NEW |