mirror of
				https://github.com/jart/cosmopolitan.git
				synced 2025-10-26 11:10:58 +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