mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-23 13:52:28 +00:00
Revert "Use %gs as TLS register when dlopen() is linked"
This reverts commit d71da7fc72
.
This commit is contained in:
parent
d71da7fc72
commit
956e68be59
13 changed files with 40 additions and 71 deletions
|
@ -28,8 +28,6 @@
|
||||||
#include "libc/sysv/consts/o.h"
|
#include "libc/sysv/consts/o.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
void sys_fcntl_nt_lock_cleanup(int);
|
|
||||||
|
|
||||||
textwindows int sys_close_nt(int fd, int fildes) {
|
textwindows int sys_close_nt(int fd, int fildes) {
|
||||||
if (fd + 0u >= g_fds.n) return ebadf();
|
if (fd + 0u >= g_fds.n) return ebadf();
|
||||||
struct Fd *f = g_fds.p + fd;
|
struct Fd *f = g_fds.p + fd;
|
||||||
|
@ -37,6 +35,7 @@ textwindows int sys_close_nt(int fd, int fildes) {
|
||||||
case kFdEmpty:
|
case kFdEmpty:
|
||||||
return ebadf();
|
return ebadf();
|
||||||
case kFdFile:
|
case kFdFile:
|
||||||
|
void sys_fcntl_nt_lock_cleanup(int);
|
||||||
if (_weaken(sys_fcntl_nt_lock_cleanup)) {
|
if (_weaken(sys_fcntl_nt_lock_cleanup)) {
|
||||||
_weaken(sys_fcntl_nt_lock_cleanup)(fildes);
|
_weaken(sys_fcntl_nt_lock_cleanup)(fildes);
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,11 +136,10 @@ static inline void InitProgramExecutableNameImpl(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// give up and just copy argv[0] into it
|
// give up and just copy argv[0] into it
|
||||||
char *p, *e;
|
|
||||||
if ((q = __argv[0])) {
|
if ((q = __argv[0])) {
|
||||||
CopyString:
|
CopyString:
|
||||||
p = g_prog.u.buf;
|
char *p = g_prog.u.buf;
|
||||||
e = p + sizeof(g_prog.u.buf);
|
char *e = p + sizeof(g_prog.u.buf);
|
||||||
while ((c = *q++)) {
|
while ((c = *q++)) {
|
||||||
if (p + 1 < e) {
|
if (p + 1 < e) {
|
||||||
*p++ = c;
|
*p++ = c;
|
||||||
|
|
|
@ -35,7 +35,6 @@ static textwindows int _park_thread(uint32_t msdelay, sigset_t waitmask,
|
||||||
if ((sig = __sig_get(waitmask))) goto HandleSignal;
|
if ((sig = __sig_get(waitmask))) goto HandleSignal;
|
||||||
int expect = 0;
|
int expect = 0;
|
||||||
atomic_int futex = 0;
|
atomic_int futex = 0;
|
||||||
int handler_was_called;
|
|
||||||
struct PosixThread *pt = _pthread_self();
|
struct PosixThread *pt = _pthread_self();
|
||||||
pt->pt_blkmask = waitmask;
|
pt->pt_blkmask = waitmask;
|
||||||
atomic_store_explicit(&pt->pt_blocker, &futex, memory_order_release);
|
atomic_store_explicit(&pt->pt_blocker, &futex, memory_order_release);
|
||||||
|
@ -43,7 +42,7 @@ static textwindows int _park_thread(uint32_t msdelay, sigset_t waitmask,
|
||||||
atomic_store_explicit(&pt->pt_blocker, 0, memory_order_release);
|
atomic_store_explicit(&pt->pt_blocker, 0, memory_order_release);
|
||||||
if (ok && (sig = __sig_get(waitmask))) {
|
if (ok && (sig = __sig_get(waitmask))) {
|
||||||
HandleSignal:
|
HandleSignal:
|
||||||
handler_was_called = __sig_relay(sig, SI_KERNEL, waitmask);
|
int handler_was_called = __sig_relay(sig, SI_KERNEL, waitmask);
|
||||||
if (_check_cancel() == -1) return -1;
|
if (_check_cancel() == -1) return -1;
|
||||||
if (!restartable || (handler_was_called & SIG_HANDLED_NO_RESTART)) {
|
if (!restartable || (handler_was_called & SIG_HANDLED_NO_RESTART)) {
|
||||||
return eintr();
|
return eintr();
|
||||||
|
|
|
@ -723,7 +723,6 @@ static textwindows int WaitForConsole(struct Fd *f, sigset_t waitmask) {
|
||||||
int sig;
|
int sig;
|
||||||
int64_t sem;
|
int64_t sem;
|
||||||
uint32_t wi, ms = -1;
|
uint32_t wi, ms = -1;
|
||||||
int handler_was_called;
|
|
||||||
if (!__ttyconf.vmin) {
|
if (!__ttyconf.vmin) {
|
||||||
if (!__ttyconf.vtime) {
|
if (!__ttyconf.vtime) {
|
||||||
return 0; // non-blocking w/o raising eagain
|
return 0; // non-blocking w/o raising eagain
|
||||||
|
@ -746,7 +745,7 @@ static textwindows int WaitForConsole(struct Fd *f, sigset_t waitmask) {
|
||||||
if (wi != 1) return __winerr(); // wait failed
|
if (wi != 1) return __winerr(); // wait failed
|
||||||
if (!(sig = __sig_get(waitmask))) return eintr();
|
if (!(sig = __sig_get(waitmask))) return eintr();
|
||||||
DeliverSignal:
|
DeliverSignal:
|
||||||
handler_was_called = __sig_relay(sig, SI_KERNEL, waitmask);
|
int handler_was_called = __sig_relay(sig, SI_KERNEL, waitmask);
|
||||||
if (_check_cancel() == -1) return -1;
|
if (_check_cancel() == -1) return -1;
|
||||||
if (!(handler_was_called & SIG_HANDLED_NO_RESTART)) return -2;
|
if (!(handler_was_called & SIG_HANDLED_NO_RESTART)) return -2;
|
||||||
return eintr();
|
return eintr();
|
||||||
|
|
|
@ -47,9 +47,7 @@ sys_readwrite_nt(int fd, void *data, size_t size, ssize_t offset,
|
||||||
bool32 ReadOrWriteFile(int64_t, void *, uint32_t, uint32_t *,
|
bool32 ReadOrWriteFile(int64_t, void *, uint32_t, uint32_t *,
|
||||||
struct NtOverlapped *)) {
|
struct NtOverlapped *)) {
|
||||||
int sig;
|
int sig;
|
||||||
bool eagained;
|
|
||||||
uint32_t exchanged;
|
uint32_t exchanged;
|
||||||
int handler_was_called;
|
|
||||||
struct Fd *f = g_fds.p + fd;
|
struct Fd *f = g_fds.p + fd;
|
||||||
|
|
||||||
// win32 i/o apis generally take 32-bit values thus we implicitly
|
// win32 i/o apis generally take 32-bit values thus we implicitly
|
||||||
|
@ -81,7 +79,7 @@ sys_readwrite_nt(int fd, void *data, size_t size, ssize_t offset,
|
||||||
}
|
}
|
||||||
|
|
||||||
RestartOperation:
|
RestartOperation:
|
||||||
eagained = false;
|
bool eagained = false;
|
||||||
// check for signals and cancelation
|
// check for signals and cancelation
|
||||||
if (_check_cancel() == -1) return -1; // ECANCELED
|
if (_check_cancel() == -1) return -1; // ECANCELED
|
||||||
if ((sig = __sig_get(waitmask))) goto HandleInterrupt;
|
if ((sig = __sig_get(waitmask))) goto HandleInterrupt;
|
||||||
|
@ -134,7 +132,7 @@ RestartOperation:
|
||||||
// otherwise it must be due to a kill() via __sig_cancel()
|
// otherwise it must be due to a kill() via __sig_cancel()
|
||||||
if ((sig = __sig_get(waitmask))) {
|
if ((sig = __sig_get(waitmask))) {
|
||||||
HandleInterrupt:
|
HandleInterrupt:
|
||||||
handler_was_called = __sig_relay(sig, SI_KERNEL, waitmask);
|
int handler_was_called = __sig_relay(sig, SI_KERNEL, waitmask);
|
||||||
if (_check_cancel() == -1) return -1; // possible if we SIGTHR'd
|
if (_check_cancel() == -1) return -1; // possible if we SIGTHR'd
|
||||||
// read() is @restartable unless non-SA_RESTART hands were called
|
// read() is @restartable unless non-SA_RESTART hands were called
|
||||||
if (!(handler_was_called & SIG_HANDLED_NO_RESTART)) {
|
if (!(handler_was_called & SIG_HANDLED_NO_RESTART)) {
|
||||||
|
|
|
@ -39,7 +39,6 @@
|
||||||
#include "libc/nt/errors.h"
|
#include "libc/nt/errors.h"
|
||||||
#include "libc/nt/memory.h"
|
#include "libc/nt/memory.h"
|
||||||
#include "libc/nt/runtime.h"
|
#include "libc/nt/runtime.h"
|
||||||
#include "libc/runtime/internal.h"
|
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/runtime/syslib.internal.h"
|
#include "libc/runtime/syslib.internal.h"
|
||||||
#include "libc/stdio/stdio.h"
|
#include "libc/stdio/stdio.h"
|
||||||
|
@ -76,6 +75,17 @@ __static_yoink(".dlopen.aarch64.glibc.elf");
|
||||||
#define XNU_RTLD_LOCAL 4
|
#define XNU_RTLD_LOCAL 4
|
||||||
#define XNU_RTLD_GLOBAL 8
|
#define XNU_RTLD_GLOBAL 8
|
||||||
|
|
||||||
|
#define BEGIN_FOREIGN \
|
||||||
|
{ \
|
||||||
|
struct CosmoTib *cosmo_tib = __get_tls(); \
|
||||||
|
pthread_mutex_lock(&foreign.lock); \
|
||||||
|
__set_tls(foreign.tib)
|
||||||
|
|
||||||
|
#define END_FOREIGN \
|
||||||
|
__set_tls(cosmo_tib); \
|
||||||
|
pthread_mutex_unlock(&foreign.lock); \
|
||||||
|
}
|
||||||
|
|
||||||
struct loaded {
|
struct loaded {
|
||||||
char *base;
|
char *base;
|
||||||
char *entry;
|
char *entry;
|
||||||
|
@ -86,6 +96,8 @@ struct loaded {
|
||||||
static struct {
|
static struct {
|
||||||
atomic_uint once;
|
atomic_uint once;
|
||||||
bool is_supported;
|
bool is_supported;
|
||||||
|
struct CosmoTib *tib;
|
||||||
|
pthread_mutex_t lock;
|
||||||
void *(*dlopen)(const char *, int);
|
void *(*dlopen)(const char *, int);
|
||||||
void *(*dlsym)(void *, const char *);
|
void *(*dlsym)(void *, const char *);
|
||||||
int (*dlclose)(void *);
|
int (*dlclose)(void *);
|
||||||
|
@ -300,6 +312,7 @@ static void foreign_setup(void) {
|
||||||
if (!dlopen_helper) {
|
if (!dlopen_helper) {
|
||||||
return; // this platform isn't supported yet
|
return; // this platform isn't supported yet
|
||||||
}
|
}
|
||||||
|
struct CosmoTib *cosmo_tib = __get_tls();
|
||||||
if (!setjmp(foreign.jb)) {
|
if (!setjmp(foreign.jb)) {
|
||||||
elf_exec(dlopen_helper, interp, 2,
|
elf_exec(dlopen_helper, interp, 2,
|
||||||
(char *[]){
|
(char *[]){
|
||||||
|
@ -310,6 +323,8 @@ static void foreign_setup(void) {
|
||||||
environ);
|
environ);
|
||||||
return; // if it returns then it failed
|
return; // if it returns then it failed
|
||||||
}
|
}
|
||||||
|
foreign.tib = __get_tls();
|
||||||
|
__set_tls(cosmo_tib);
|
||||||
foreign.is_supported = true;
|
foreign.is_supported = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,17 +391,15 @@ static char *dlsym_nt_alloc_rwx_block(void) {
|
||||||
static void *dlsym_nt_alloc_rwx(size_t n) {
|
static void *dlsym_nt_alloc_rwx(size_t n) {
|
||||||
void *res;
|
void *res;
|
||||||
static char *block;
|
static char *block;
|
||||||
static pthread_spinlock_t lock;
|
pthread_mutex_lock(&foreign.lock);
|
||||||
pthread_spin_lock(&lock);
|
|
||||||
if (!block || READ32LE(block) + n > 65536) {
|
if (!block || READ32LE(block) + n > 65536) {
|
||||||
if (!(block = dlsym_nt_alloc_rwx_block())) {
|
if (!(block = dlsym_nt_alloc_rwx_block())) {
|
||||||
pthread_spin_unlock(&lock);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res = block + READ32LE(block);
|
res = block + READ32LE(block);
|
||||||
WRITE32LE(block, READ32LE(block) + n);
|
WRITE32LE(block, READ32LE(block) + n);
|
||||||
pthread_spin_unlock(&lock);
|
pthread_mutex_unlock(&foreign.lock);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -482,7 +495,9 @@ void *dlopen(const char *path, int mode) {
|
||||||
last_dlerror = "dlopen() isn't supported on x86-64 MacOS";
|
last_dlerror = "dlopen() isn't supported on x86-64 MacOS";
|
||||||
res = 0;
|
res = 0;
|
||||||
} else if (foreign_init()) {
|
} else if (foreign_init()) {
|
||||||
|
BEGIN_FOREIGN;
|
||||||
res = foreign.dlopen(path, mode);
|
res = foreign.dlopen(path, mode);
|
||||||
|
END_FOREIGN;
|
||||||
} else {
|
} else {
|
||||||
res = 0;
|
res = 0;
|
||||||
}
|
}
|
||||||
|
@ -509,7 +524,9 @@ void *dlsym(void *handle, const char *name) {
|
||||||
last_dlerror = "dlopen() isn't supported on x86-64 MacOS";
|
last_dlerror = "dlopen() isn't supported on x86-64 MacOS";
|
||||||
res = 0;
|
res = 0;
|
||||||
} else if (foreign_init()) {
|
} else if (foreign_init()) {
|
||||||
|
BEGIN_FOREIGN;
|
||||||
res = foreign.dlsym(handle, name);
|
res = foreign.dlsym(handle, name);
|
||||||
|
END_FOREIGN;
|
||||||
} else {
|
} else {
|
||||||
res = 0;
|
res = 0;
|
||||||
}
|
}
|
||||||
|
@ -533,7 +550,9 @@ int dlclose(void *handle) {
|
||||||
last_dlerror = "dlopen() isn't supported on x86-64 MacOS";
|
last_dlerror = "dlopen() isn't supported on x86-64 MacOS";
|
||||||
res = -1;
|
res = -1;
|
||||||
} else if (foreign_init()) {
|
} else if (foreign_init()) {
|
||||||
|
BEGIN_FOREIGN;
|
||||||
res = foreign.dlclose(handle);
|
res = foreign.dlclose(handle);
|
||||||
|
END_FOREIGN;
|
||||||
} else {
|
} else {
|
||||||
res = -1;
|
res = -1;
|
||||||
}
|
}
|
||||||
|
@ -551,24 +570,12 @@ char *dlerror(void) {
|
||||||
} else if (IsWindows() || IsXnu()) {
|
} else if (IsWindows() || IsXnu()) {
|
||||||
res = (char *)last_dlerror;
|
res = (char *)last_dlerror;
|
||||||
} else if (foreign_init()) {
|
} else if (foreign_init()) {
|
||||||
|
BEGIN_FOREIGN;
|
||||||
res = foreign.dlerror();
|
res = foreign.dlerror();
|
||||||
|
END_FOREIGN;
|
||||||
} else {
|
} else {
|
||||||
res = (char *)last_dlerror;
|
res = (char *)last_dlerror;
|
||||||
}
|
}
|
||||||
STRACE("dlerror() → %#s", res);
|
STRACE("dlerror() → %#s", res);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __x86_64__
|
|
||||||
static textstartup void dlopen_init() {
|
|
||||||
if (IsLinux() || IsFreebsd() || IsNetbsd()) {
|
|
||||||
// switch from %fs to %gs for tls
|
|
||||||
struct CosmoTib *tib = __get_tls();
|
|
||||||
__morph_tls();
|
|
||||||
__set_tls(tib);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const void *const dlopen_ctor[] initarray = {
|
|
||||||
dlopen_init,
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
|
||||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
|
||||||
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
|
||||||
│ │
|
|
||||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
|
||||||
│ any purpose with or without fee is hereby granted, provided that the │
|
|
||||||
│ above copyright notice and this permission notice appear in all copies. │
|
|
||||||
│ │
|
|
||||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
|
||||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
|
||||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
|
||||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
|
||||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
|
||||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
|
||||||
#include "libc/runtime/internal.h"
|
|
||||||
|
|
||||||
bool __tls_morphed;
|
|
|
@ -72,7 +72,7 @@ static textwindows int __proc_wait(int pid, int *wstatus, int options,
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
|
||||||
// check for signals and cancelation
|
// check for signals and cancelation
|
||||||
int rc, sig, handler_was_called;
|
int sig, handler_was_called;
|
||||||
if (_check_cancel() == -1) {
|
if (_check_cancel() == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ static textwindows int __proc_wait(int pid, int *wstatus, int options,
|
||||||
// check for zombie to harvest
|
// check for zombie to harvest
|
||||||
__proc_lock();
|
__proc_lock();
|
||||||
CheckForZombies:
|
CheckForZombies:
|
||||||
rc = __proc_check(pid, wstatus, rusage);
|
int rc = __proc_check(pid, wstatus, rusage);
|
||||||
if (rc || (options & WNOHANG)) {
|
if (rc || (options & WNOHANG)) {
|
||||||
__proc_unlock();
|
__proc_unlock();
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -55,13 +55,11 @@ privileged void __morph_tls(void) {
|
||||||
// address 0x30 was promised to us, according to Go team
|
// address 0x30 was promised to us, according to Go team
|
||||||
// https://github.com/golang/go/issues/23617
|
// https://github.com/golang/go/issues/23617
|
||||||
dis = 0x30;
|
dis = 0x30;
|
||||||
} else if (IsWindows()) {
|
} else {
|
||||||
// MSVC __declspec(thread) generates binary code for this
|
// MSVC __declspec(thread) generates binary code for this
|
||||||
// %gs:0x1480 abi. So long as TlsAlloc() isn't called >64
|
// %gs:0x1480 abi. So long as TlsAlloc() isn't called >64
|
||||||
// times we should be good.
|
// times we should be good.
|
||||||
dis = 0x1480 + __tls_index * 8;
|
dis = 0x1480 + __tls_index * 8;
|
||||||
} else {
|
|
||||||
dis = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// iterate over modifiable code looking for 9 byte instruction
|
// iterate over modifiable code looking for 9 byte instruction
|
||||||
|
@ -114,7 +112,6 @@ privileged void __morph_tls(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__tls_morphed = true;
|
|
||||||
__morph_end();
|
__morph_end();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,9 +26,6 @@
|
||||||
#include "libc/thread/tls.h"
|
#include "libc/thread/tls.h"
|
||||||
#include "libc/thread/tls2.internal.h"
|
#include "libc/thread/tls2.internal.h"
|
||||||
|
|
||||||
#define AMD64_SET_FSBASE 129
|
|
||||||
#define AMD64_SET_GSBASE 131
|
|
||||||
|
|
||||||
int sys_set_tls();
|
int sys_set_tls();
|
||||||
|
|
||||||
textstartup void __set_tls(struct CosmoTib *tib) {
|
textstartup void __set_tls(struct CosmoTib *tib) {
|
||||||
|
@ -39,9 +36,9 @@ textstartup void __set_tls(struct CosmoTib *tib) {
|
||||||
npassert(0 <= __tls_index && __tls_index < 64);
|
npassert(0 <= __tls_index && __tls_index < 64);
|
||||||
asm("mov\t%1,%%gs:%0" : "=m"(*((long *)0x1480 + __tls_index)) : "r"(tib));
|
asm("mov\t%1,%%gs:%0" : "=m"(*((long *)0x1480 + __tls_index)) : "r"(tib));
|
||||||
} else if (IsFreebsd()) {
|
} else if (IsFreebsd()) {
|
||||||
sys_set_tls(__tls_morphed ? AMD64_SET_GSBASE : AMD64_SET_FSBASE, tib);
|
sys_set_tls(129 /*AMD64_SET_FSBASE*/, tib);
|
||||||
} else if (IsLinux()) {
|
} else if (IsLinux()) {
|
||||||
sys_set_tls(__tls_morphed ? ARCH_SET_GS : ARCH_SET_FS, tib);
|
sys_set_tls(ARCH_SET_FS, tib);
|
||||||
} else if (IsNetbsd()) {
|
} else if (IsNetbsd()) {
|
||||||
// netbsd has sysarch(X86_SET_FSBASE) but we can't use that because
|
// netbsd has sysarch(X86_SET_FSBASE) but we can't use that because
|
||||||
// signal handlers will cause it to be reset due to not setting the
|
// signal handlers will cause it to be reset due to not setting the
|
||||||
|
|
|
@ -705,7 +705,7 @@ haveinc:
|
||||||
return prec;
|
return prec;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __fmt_noop(const char *x, void *y, size_t z) {
|
static int __fmt_noop(const char *, void *, size_t) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,6 @@ struct CosmoTib {
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int __threaded;
|
extern int __threaded;
|
||||||
extern bool __tls_morphed;
|
|
||||||
extern unsigned __tls_index;
|
extern unsigned __tls_index;
|
||||||
|
|
||||||
char *_mktls(struct CosmoTib **);
|
char *_mktls(struct CosmoTib **);
|
||||||
|
|
|
@ -15,11 +15,7 @@ COSMOPOLITAN_C_START_
|
||||||
__funline struct CosmoTib *__get_tls_privileged(void) {
|
__funline struct CosmoTib *__get_tls_privileged(void) {
|
||||||
char *tib, *lin = (char *)0x30;
|
char *tib, *lin = (char *)0x30;
|
||||||
if (IsLinux() || IsFreebsd() || IsNetbsd() || IsOpenbsd() || IsMetal()) {
|
if (IsLinux() || IsFreebsd() || IsNetbsd() || IsOpenbsd() || IsMetal()) {
|
||||||
if (!__tls_morphed) {
|
|
||||||
asm("mov\t%%fs:(%1),%0" : "=a"(tib) : "r"(lin) : "memory");
|
asm("mov\t%%fs:(%1),%0" : "=a"(tib) : "r"(lin) : "memory");
|
||||||
} else {
|
|
||||||
asm("mov\t%%gs:(%1),%0" : "=a"(tib) : "r"(lin) : "memory");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
asm("mov\t%%gs:(%1),%0" : "=a"(tib) : "r"(lin) : "memory");
|
asm("mov\t%%gs:(%1),%0" : "=a"(tib) : "r"(lin) : "memory");
|
||||||
if (IsWindows()) {
|
if (IsWindows()) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue