* Use GCC's Thread-Local Storage to store current thread.
(Tested on Linux x86 and x86-64, too)
* Restore lisp level TLS segment register at interrupt handler.
printf ' :elf' >> $ltf
printf ' :freebsd' >> $ltf
printf ' :sb-pthread-futex' >> $ltf
+ printf ' :gcc-tls' >> $ltf
if [ $sbcl_arch = "x86" ]; then
- printf ' :restore-tls-segment-register-from-tls' >> $ltf
+ printf ' :restore-tls-segment-register-from-context' >> $ltf
fi
link_or_copy Config.$sbcl_arch-freebsd Config
;;
* is done). For the GENCGC, it always points to DYNAMIC_SPACE_START. */
lispobj *current_dynamic_space;
-#if defined(LISP_FEATURE_SB_THREAD)
+#if defined(LISP_FEATURE_SB_THREAD) && !defined(LISP_FEATURE_GCC_TLS)
pthread_key_t specials=0;
#endif
foreign_function_call_active = 1;
#endif
-#ifdef LISP_FEATURE_SB_THREAD
+#if defined(LISP_FEATURE_SB_THREAD) && !defined(LISP_FEATURE_GCC_TLS)
pthread_key_create(&specials,0);
#endif
}
#endif
extern char **ENVIRON;
-#if defined(LISP_FEATURE_SB_THREAD)
+#if defined(LISP_FEATURE_SB_THREAD) && !defined(LISP_FEATURE_GCC_TLS)
extern pthread_key_t specials;
#endif
#ifdef LOCK_CREATE_THREAD
static pthread_mutex_t create_thread_lock = PTHREAD_MUTEX_INITIALIZER;
#endif
+#ifdef LISP_FEATURE_GCC_TLS
+__thread struct thread *current_thread;
+#endif
#endif
#if defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64)
[fixnum_value(SymbolValue(FREE_INTERRUPT_CONTEXT_INDEX,th)-1)];
}
+#if defined(LISP_FEATURE_SB_THREAD) && defined(LISP_FEATURE_GCC_TLS)
+extern __thread struct thread *current_thread;
+#endif
+
/* This is clearly per-arch and possibly even per-OS code, but we can't
* put it somewhere sensible like x86-linux-os.c because it needs too
* much stuff like struct thread and all_threads to be defined, which
sel.rpl = USER_PRIV;
sel.ti = SEL_LDT;
__asm__ __volatile__ ("movw %w0, %%fs" : : "r"(sel));
-#elif defined(LISP_FEATURE_FREEBSD) && defined(LISP_FEATURE_RESTORE_TLS_SEGMENT_REGISTER_FROM_TLS)
+#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();
* causes privilege checking and it takes long time. */
if (fs != sel)
load_fs(sel);
+#endif
return th;
#endif
__asm__ __volatile__ ("movl %%fs:%c1,%0" : "=r" (me)
}
return me;
#else
+#ifdef LISP_FEATURE_GCC_TLS
+ return current_thread;
+#else
return pthread_getspecific(specials);
+#endif
#endif /* x86 */
#else
return all_threads;
push %rsi #
push %rdx #
#ifdef LISP_FEATURE_SB_THREAD
+#ifdef LISP_FEATURE_GCC_TLS
+ movq %fs:0, %rax
+ movq GNAME(current_thread)@TPOFF(%rax), %r12
+#else
#ifdef LISP_FEATURE_DARWIN
mov GSYM(GNAME(specials)),%rdi
#else
call GNAME(pthread_getspecific)
mov %rax,%r12
#endif
+#endif
pop %rcx # num args
pop %rbx # arg vector
pop %rax # function ptr/lexenv
int arch_os_thread_init(struct thread *thread) {
stack_t sigstack;
#ifdef LISP_FEATURE_SB_THREAD
+#ifdef LISP_FEATURE_GCC_TLS
+ current_thread = thread;
+#else
pthread_setspecific(specials,thread);
#endif
+#endif
#ifdef LISP_FEATURE_MACH_EXCEPTION_HANDLER
mach_thread_init(THREAD_STRUCT_TO_EXCEPTION_PORT(thread));
int arch_os_thread_init(struct thread *thread) {
stack_t sigstack;
#ifdef LISP_FEATURE_SB_THREAD
+#ifdef LISP_FEATURE_GCC_TLS
+ current_thread = thread;
+#else
pthread_setspecific(specials,thread);
#endif
+#endif
#ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
/* Signal handlers are run on the control stack, so if it is exhausted
* we had better use an alternate stack for whatever signal tells us
load_fs(sel);
thread->tls_cookie=n;
+#ifdef LISP_FEATURE_GCC_TLS
+ current_thread = thread;
+#else
pthread_setspecific(specials,thread);
#endif
+#endif
#ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
stack_t sigstack;
#endif /* !LISP_FEATURE_DARWIN */
#if defined(LISP_FEATURE_FREEBSD)
+#if defined(LISP_FEATURE_RESTORE_TLS_SEGMENT_REGISTER_FROM_CONTEXT)
+void
+os_restore_tls_segment_register(os_context_t *context)
+{
+ load_fs(context->uc_mcontext.mc_fs);
+}
+#endif
+
void
os_restore_fp_control(os_context_t *context)
{
struct envxmm *ex = (struct envxmm*)(&context->uc_mcontext.mc_fpstate);
asm ("fldcw %0" : : "m" (ex->en_cw));
#endif
+#if defined(LISP_FEATURE_RESTORE_TLS_SEGMENT_REGISTER_FROM_CONTEXT)
+ /* Calling this function here may not be good idea. Or rename
+ * function name os_restore_fp_control to os_restore_context or
+ * so, to match the behavior? */
+ os_restore_tls_segment_register(context);
+#endif
}
#endif
pthread_mutex_unlock(&modify_ldt_lock);
if(n<0) return 0;
+#ifdef LISP_FEATURE_GCC_TLS
+ current_thread = thread;
+#else
pthread_setspecific(specials,thread);
#endif
+#endif
#ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
/* Signal handlers are run on the control stack, so if it is exhausted
* we had better use an alternate stack for whatever signal tells us
;;; checkins which aren't released. (And occasionally for internal
;;; versions, especially for internal versions off the main CVS
;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"1.0.9.61"
+"1.0.9.62"