| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #ifndef TLS_H__ | |
| 6 #define TLS_H__ | |
| 7 | |
| 8 #include <asm/ldt.h> | |
| 9 #include <stdlib.h> | |
| 10 #include <sys/mman.h> | |
| 11 #include <sys/prctl.h> | |
| 12 | |
| 13 namespace playground { | |
| 14 | |
| 15 class TLS { | |
| 16 private: | |
| 17 class SysCalls { | |
| 18 public: | |
| 19 #define SYS_CPLUSPLUS | |
| 20 #define SYS_ERRNO my_errno | |
| 21 #define SYS_INLINE inline | |
| 22 #define SYS_PREFIX -1 | |
| 23 #undef SYS_LINUX_SYSCALL_SUPPORT_H | |
| 24 #include "linux_syscall_support.h" | |
| 25 SysCalls() : my_errno(0) { } | |
| 26 int my_errno; | |
| 27 }; | |
| 28 | |
| 29 public: | |
| 30 static void *allocateTLS() { | |
| 31 SysCalls sys; | |
| 32 #if defined(__x86_64__) | |
| 33 void *addr = sys.mmap(0, 4096, PROT_READ|PROT_WRITE, | |
| 34 MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); | |
| 35 if (sys.arch_prctl(ARCH_SET_GS, addr) < 0) { | |
| 36 return NULL; | |
| 37 } | |
| 38 #elif defined(__i386__) | |
| 39 void *addr = sys.mmap2(0, 4096, PROT_READ|PROT_WRITE, | |
| 40 MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); | |
| 41 struct user_desc u; | |
| 42 u.entry_number = (typeof u.entry_number)-1; | |
| 43 u.base_addr = (int)addr; | |
| 44 u.limit = 0xfffff; | |
| 45 u.seg_32bit = 1; | |
| 46 u.contents = 0; | |
| 47 u.read_exec_only = 0; | |
| 48 u.limit_in_pages = 1; | |
| 49 u.seg_not_present = 0; | |
| 50 u.useable = 1; | |
| 51 if (sys.set_thread_area(&u) < 0) { | |
| 52 return NULL; | |
| 53 } | |
| 54 asm volatile( | |
| 55 "movw %w0, %%fs" | |
| 56 : | |
| 57 : "q"(8*u.entry_number+3)); | |
| 58 #else | |
| 59 #error Unsupported target platform | |
| 60 #endif | |
| 61 return addr; | |
| 62 } | |
| 63 | |
| 64 static void freeTLS() { | |
| 65 SysCalls sys; | |
| 66 void *addr; | |
| 67 #if defined(__x86_64__) | |
| 68 sys.arch_prctl(ARCH_GET_GS, &addr); | |
| 69 #elif defined(__i386__) | |
| 70 struct user_desc u; | |
| 71 sys.get_thread_area(&u); | |
| 72 addr = (void *)u.base_addr; | |
| 73 #else | |
| 74 #error Unsupported target platform | |
| 75 #endif | |
| 76 sys.munmap(addr, 4096); | |
| 77 } | |
| 78 | |
| 79 template<class T> static inline bool setTLSValue(int idx, T val) { | |
| 80 #if defined(__x86_64__) | |
| 81 if (idx < 0 || idx >= 4096/8) { | |
| 82 return false; | |
| 83 } | |
| 84 asm volatile( | |
| 85 "movq %0, %%gs:(%1)\n" | |
| 86 : | |
| 87 : "q"((void *)val), "q"(8ll * idx)); | |
| 88 #elif defined(__i386__) | |
| 89 if (idx < 0 || idx >= 4096/8) { | |
| 90 return false; | |
| 91 } | |
| 92 if (sizeof(T) == 8) { | |
| 93 asm volatile( | |
| 94 "movl %0, %%fs:(%1)\n" | |
| 95 : | |
| 96 : "r"((unsigned)val), "r"(8 * idx)); | |
| 97 asm volatile( | |
| 98 "movl %0, %%fs:(%1)\n" | |
| 99 : | |
| 100 : "r"((unsigned)((unsigned long long)val >> 32)), "r"(8 * idx + 4)); | |
| 101 } else { | |
| 102 asm volatile( | |
| 103 "movl %0, %%fs:(%1)\n" | |
| 104 : | |
| 105 : "r"(val), "r"(8 * idx)); | |
| 106 } | |
| 107 #else | |
| 108 #error Unsupported target platform | |
| 109 #endif | |
| 110 return true; | |
| 111 } | |
| 112 | |
| 113 template<class T> static inline T getTLSValue(int idx) { | |
| 114 #if defined(__x86_64__) | |
| 115 long long rc; | |
| 116 if (idx < 0 || idx >= 4096/8) { | |
| 117 return 0; | |
| 118 } | |
| 119 asm volatile( | |
| 120 "movq %%gs:(%1), %0\n" | |
| 121 : "=q"(rc) | |
| 122 : "q"(8ll * idx)); | |
| 123 return (T)rc; | |
| 124 #elif defined(__i386__) | |
| 125 if (idx < 0 || idx >= 4096/8) { | |
| 126 return 0; | |
| 127 } | |
| 128 if (sizeof(T) == 8) { | |
| 129 unsigned lo, hi; | |
| 130 asm volatile( | |
| 131 "movl %%fs:(%1), %0\n" | |
| 132 : "=r"(lo) | |
| 133 : "r"(8 * idx)); | |
| 134 asm volatile( | |
| 135 "movl %%fs:(%1), %0\n" | |
| 136 : "=r"(hi) | |
| 137 : "r"(8 * idx + 4)); | |
| 138 return (T)((unsigned long long)lo + ((unsigned long long)hi << 32)); | |
| 139 } else { | |
| 140 long rc; | |
| 141 asm volatile( | |
| 142 "movl %%fs:(%1), %0\n" | |
| 143 : "=r"(rc) | |
| 144 : "r"(8 * idx)); | |
| 145 return (T)rc; | |
| 146 } | |
| 147 #else | |
| 148 #error Unsupported target platform | |
| 149 #endif | |
| 150 } | |
| 151 | |
| 152 }; | |
| 153 | |
| 154 } // namespace | |
| 155 #endif | |
| OLD | NEW |