;; thread local storage) is not reliably preserved in signal
;; handlers, so we need to restore its value from the pthread thread
;; local storage.
- ; :restore-tls-segment-register-from-tls
+ ; :restore-fs-segment-register-from-tls
;; On some x86oid operating systems (darwin) SIGTRAP is not reliably
;; delivered for the INT3 instruction, so we use the UD2 instruction
printf ' :freebsd' >> $ltf
printf ' :gcc-tls' >> $ltf
if [ $sbcl_arch = "x86" ]; then
- printf ' :restore-tls-segment-register-from-context' >> $ltf
+ printf ' :restore-fs-segment-register-from-tls' >> $ltf
fi
link_or_copy Config.$sbcl_arch-freebsd Config
;;
unsigned int orig_inst);
extern int arch_os_thread_init(struct thread *thread);
+#if defined(LISP_FEATURE_X86) && defined(LISP_FEATURE_SB_THREAD)
+extern void arch_os_load_ldt(struct thread *thread);
+#endif
extern int arch_os_thread_cleanup(struct thread *thread);
extern lispobj funcall0(lispobj function);
static inline struct thread *arch_os_get_current_thread(void)
{
-#if defined(LISP_FEATURE_SB_THREAD)
-#if defined(LISP_FEATURE_X86)
+#if !defined(LISP_FEATURE_SB_THREAD)
+ return all_threads;
+
+#elif defined(LISP_FEATURE_X86) && defined(LISP_FEATURE_WIN32)
register struct thread *me=0;
-#if defined(LISP_FEATURE_WIN32) && defined(LISP_FEATURE_SB_THREAD)
__asm__ ("movl %%fs:0xE10+(4*63), %0" : "=r"(me) :);
return me;
-#endif
- if(all_threads) {
-#if defined(LISP_FEATURE_DARWIN) && defined(LISP_FEATURE_RESTORE_FS_SEGMENT_REGISTER_FROM_TLS)
- sel_t sel;
- struct thread *th = pthread_getspecific(specials);
- sel.index = th->tls_cookie;
- sel.rpl = USER_PRIV;
- sel.ti = SEL_LDT;
- __asm__ __volatile__ ("movw %w0, %%fs" : : "r"(sel));
-#elif defined(LISP_FEATURE_FREEBSD)
-#ifdef LISP_FEATURE_GCC_TLS
- struct thread *th = current_thread;
-#else
- struct thread *th = pthread_getspecific(specials);
-#endif
-#ifdef LISP_FEATURE_RESTORE_TLS_SEGMENT_REGISTER_FROM_TLS
- unsigned int sel = LSEL(th->tls_cookie, SEL_UPL);
- unsigned int fs = rfs();
-
- /* Load FS only if it's necessary. Modifying a selector
- * causes privilege checking and it takes long time. */
- if (fs != sel)
- load_fs(sel);
-#endif
- return th;
-#endif
- __asm__ ("movl %%fs:%c1,%0" : "=r" (me)
- : "i" (offsetof (struct thread,this)));
- }
- return me;
-#else
-#ifdef LISP_FEATURE_GCC_TLS
- return current_thread;
-#else
- return pthread_getspecific(specials);
-#endif
-#endif /* x86 */
+
#else
- return all_threads;
+ if (!all_threads)
+ /* no need to bother */
+ return 0;
+
+ /* Otherwise, use pthreads to find the right value. We do not load
+ * directly from %fs:this even on x86 platforms (like Linux and
+ * Solaris) with dependable %fs, because we want to return NULL if
+ * called by a non-Lisp thread, and %fs would not be initialized
+ * suitably in that case. */
+ struct thread *th;
+# ifdef LISP_FEATURE_GCC_TLS
+ th = current_thread;
+# else
+ th = pthread_getspecific(specials);
+# endif
+
+# if defined(LISP_FEATURE_RESTORE_FS_SEGMENT_REGISTER_FROM_TLS)
+ /* If enabled by make-config (currently Darwin and FreeBSD only),
+ * re-setup %fs. This is an out-of-line call, and potentially
+ * expensive.*/
+ if (th)
+ arch_os_load_ldt(th);
+# endif
+
+ return th;
#endif
}
#endif
+#ifdef LISP_FEATURE_SB_THREAD
+void
+arch_os_load_ldt(struct thread *thread)
+{
+ int sel = LSEL(thread->tls_cookie, SEL_UPL);
+ unsigned int fs = rfs();
+
+ /* Load FS only if it's necessary. Modifying a selector
+ * causes privilege checking and it takes long time. */
+ if (fs != sel)
+ load_fs(sel);
+}
+#endif
+
int arch_os_thread_init(struct thread *thread) {
#ifdef LISP_FEATURE_SB_THREAD
int n;
- int sel;
struct segment_descriptor ldt_entry = { 0, 0, SDT_MEMRW, SEL_UPL, 1,
0, 0, 1, 0, 0 };
lose("unexpected i386_set_ldt(..) failure\n");
}
FSHOW_SIGNAL((stderr, "/ TLS: Allocated LDT %x\n", n));
- sel = LSEL(n, SEL_UPL);
- load_fs(sel);
-
thread->tls_cookie=n;
+ arch_os_load_ldt(thread);
+
#ifdef LISP_FEATURE_GCC_TLS
current_thread = thread;
#else
#endif
+#ifdef LISP_FEATURE_SB_THREAD
+void
+arch_os_load_ldt(struct thread *thread)
+{
+ sel_t sel;
+
+ sel.index = thread->tls_cookie;
+ sel.rpl = USER_PRIV;
+ sel.ti = SEL_LDT;
+
+ __asm__ __volatile__ ("mov %0, %%fs" : : "r"(sel));
+}
+#endif
+
int arch_os_thread_init(struct thread *thread) {
#ifdef LISP_FEATURE_SB_THREAD
int n;
- sel_t sel;
data_desc_t ldt_entry = { 0, 0, 0, DESC_DATA_WRITE,
3, 1, 0, DESC_DATA_32B, DESC_GRAN_BYTE, 0 };
thread_mutex_unlock(&modify_ldt_lock);
FSHOW_SIGNAL((stderr, "/ TLS: Allocated LDT %x\n", n));
- sel.index = n;
- sel.rpl = USER_PRIV;
- sel.ti = SEL_LDT;
-
- __asm__ __volatile__ ("mov %0, %%fs" : : "r"(sel));
-
thread->tls_cookie=n;
+ arch_os_load_ldt(thread);
+
pthread_setspecific(specials,thread);
#endif
#ifdef LISP_FEATURE_MACH_EXCEPTION_HANDLER