|
[Sbcl-commits] master: In x86 arch_os_get_current_thread(),
do not load from %fs
From: David Lichteblau <lichteblau@us...> - 2012-12-17 14:23
|
The branch "master" has been updated in SBCL:
via 9644b3bcfc539ab201da9d3251a3cc3ebc24d457 (commit)
from f21d139cd90695962174882c27585c02511c3027 (commit)
- Log -----------------------------------------------------------------
commit 9644b3bcfc539ab201da9d3251a3cc3ebc24d457
Author: David Lichteblau <david@...>
Date: Wed Dec 12 14:12:50 2012 +0100
In x86 arch_os_get_current_thread(), do not load from %fs
Simplify arch_os_get_current_thread() such that %fs is not being
loaded directly even on platforms which preserve it reliably (in
particular, Linux/x86 and Solaris/x86).
Aside from a code simplification and reduction of cross-platform
differences, this change is an improvement in the following way:
If arch_os_get_current_thread() gets called in a non-Lisp pthread,
it now returns NULL cleanly even on the platforms mentioned above.
On the other platforms, keep the support for restoring %fs, but
refactor to remove code duplication with arch_os_thread_init().
Coalesce the two differently-spelled Lisp features for this case
into one.
---
base-target-features.lisp-expr | 2 +-
make-config.sh | 2 +-
src/runtime/arch.h | 3 ++
src/runtime/thread.h | 69 +++++++++++++++++-----------------------
src/runtime/x86-bsd-os.c | 20 +++++++++--
src/runtime/x86-darwin-os.c | 23 +++++++++----
6 files changed, 66 insertions(+), 53 deletions(-)
diff --git a/base-target-features.lisp-expr b/base-target-features.lisp-expr
index 22530df..9ba7b4d 100644
--- a/base-target-features.lisp-expr
+++ b/base-target-features.lisp-expr
@@ -238,7 +238,7 @@
;; 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
diff --git a/make-config.sh b/make-config.sh
index 3897191..1b86204 100644
--- a/make-config.sh
+++ b/make-config.sh
@@ -478,7 +478,7 @@ case "$sbcl_os" in
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
;;
diff --git a/src/runtime/arch.h b/src/runtime/arch.h
index 1a8cf69..c8ef480 100644
--- a/src/runtime/arch.h
+++ b/src/runtime/arch.h
@@ -35,6 +35,9 @@ extern void arch_do_displaced_inst(os_context_t *context,
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);
diff --git a/src/runtime/thread.h b/src/runtime/thread.h
index ec295fc..6de8f89 100644
--- a/src/runtime/thread.h
+++ b/src/runtime/thread.h
@@ -294,51 +294,40 @@ static inline struct thread* arch_os_get_current_thread()
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
}
diff --git a/src/runtime/x86-bsd-os.c b/src/runtime/x86-bsd-os.c
index 8b62584..fe75566 100644
--- a/src/runtime/x86-bsd-os.c
+++ b/src/runtime/x86-bsd-os.c
@@ -157,11 +157,24 @@ void set_data_desc_addr(struct segment_descriptor* desc, void* addr)
#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 };
@@ -175,10 +188,9 @@ int arch_os_thread_init(struct thread *thread) {
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
diff --git a/src/runtime/x86-darwin-os.c b/src/runtime/x86-darwin-os.c
index 323e549..8489322 100644
--- a/src/runtime/x86-darwin-os.c
+++ b/src/runtime/x86-darwin-os.c
@@ -44,10 +44,23 @@ void set_data_desc_addr(data_desc_t* desc, void* addr)
#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 };
@@ -65,13 +78,9 @@ int arch_os_thread_init(struct thread *thread) {
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
-----------------------------------------------------------------------
hooks/post-receive
--
SBCL
|
| Thread | Author | Date |
|---|---|---|
| [Sbcl-commits] master: In x86 arch_os_get_current_thread(), do not load from %fs | David Lichteblau <lichteblau@us...> |