1.1.13: will be tagged as "sbcl-1.1.13"
[sbcl.git] / src / runtime / thread.h
index 3c2d5bc..1a004c0 100644 (file)
@@ -69,7 +69,9 @@ extern struct threads_suspend_info suspend_info;
 
 struct gcing_safety {
     lispobj csp_around_foreign_call;
+#ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
     lispobj* pc_around_foreign_call;
+#endif
 };
 
 int handle_safepoint_violation(os_context_t *context, os_vm_address_t addr);
@@ -229,32 +231,39 @@ StaticSymbolFunction(lispobj sym)
 #define access_control_frame_pointer(thread) \
     ((thread)->control_frame_pointer)
 #  endif
-#elif defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64)
+#else
+#  if defined(BINDING_STACK_POINTER)
 #define get_binding_stack_pointer(thread)       \
     SymbolValue(BINDING_STACK_POINTER, thread)
 #define set_binding_stack_pointer(thread,value) \
     SetSymbolValue(BINDING_STACK_POINTER, (lispobj)(value), thread)
-#define access_control_stack_pointer(thread)    \
-    (current_control_stack_pointer)
-#else
+#  else
 #define get_binding_stack_pointer(thread)       \
     (current_binding_stack_pointer)
 #define set_binding_stack_pointer(thread,value) \
     (current_binding_stack_pointer = (lispobj *)(value))
-#define access_control_stack_pointer(thread) \
+#  endif
+#define access_control_stack_pointer(thread)    \
     (current_control_stack_pointer)
+#  if !defined(LISP_FEATURE_X86) && !defined(LISP_FEATURE_X86_64)
 #define access_control_frame_pointer(thread) \
     (current_control_frame_pointer)
+#  endif
 #endif
 
 #if defined(LISP_FEATURE_SB_THREAD) && defined(LISP_FEATURE_GCC_TLS)
 extern __thread struct thread *current_thread;
 #endif
 
-#ifdef LISP_FEATURE_SB_SAFEPOINT
-# define THREAD_CSP_PAGE_SIZE BACKEND_PAGE_BYTES
-#else
+#ifndef LISP_FEATURE_SB_SAFEPOINT
 # define THREAD_CSP_PAGE_SIZE 0
+#elif defined(LISP_FEATURE_PPC)
+  /* BACKEND_PAGE_BYTES is nice and large on this platform, but therefore
+   * does not fit into an immediate, making it awkward to access the page
+   * relative to the thread-tn... */
+# define THREAD_CSP_PAGE_SIZE 4096
+#else
+# define THREAD_CSP_PAGE_SIZE BACKEND_PAGE_BYTES
 #endif
 
 #ifdef LISP_FEATURE_WIN32
@@ -285,51 +294,41 @@ 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);
+
+# if defined(LISP_FEATURE_X86)
+    if (!all_threads) return 0;
 #endif
-#endif /* x86 */
-#else
-     return all_threads;
+
+    /* 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
 }
 
@@ -338,6 +337,13 @@ extern kern_return_t mach_lisp_thread_init(struct thread *thread);
 extern kern_return_t mach_lisp_thread_destroy(struct thread *thread);
 #endif
 
+typedef struct init_thread_data {
+    sigset_t oldset;
+#ifdef LISP_FEATURE_SB_SAFEPOINT
+    struct gcing_safety safety;
+#endif
+} init_thread_data;
+
 #ifdef LISP_FEATURE_SB_SAFEPOINT
 void thread_in_safety_transition(os_context_t *ctx);
 void thread_in_lisp_raised(os_context_t *ctx);
@@ -363,11 +369,15 @@ void push_gcing_safety(struct gcing_safety *into)
          *th->csp_around_foreign_call)) {
         *th->csp_around_foreign_call = 0;
         asm volatile ("");
+#ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
         into->pc_around_foreign_call = th->pc_around_foreign_call;
         th->pc_around_foreign_call = 0;
         asm volatile ("");
+#endif
     } else {
+#ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
         into->pc_around_foreign_call = 0;
+#endif
     }
 }
 
@@ -379,8 +389,10 @@ void pop_gcing_safety(struct gcing_safety *from)
         asm volatile ("");
         *th->csp_around_foreign_call = from->csp_around_foreign_call;
         asm volatile ("");
+#ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
         th->pc_around_foreign_call = from->pc_around_foreign_call;
         asm volatile ("");
+#endif
     }
 }
 
@@ -407,6 +419,14 @@ void pop_gcing_safety(struct gcing_safety *from)
 
 int check_pending_thruptions(os_context_t *ctx);
 
+void attach_os_thread(init_thread_data *);
+void detach_os_thread(init_thread_data *);
+
+# if defined(LISP_FEATURE_SB_SAFEPOINT_STRICTLY) && !defined(LISP_FEATURE_WIN32)
+
+void signal_handler_callback(lispobj, int, void *, void *);
+# endif
+
 #endif
 
 extern void create_initial_thread(lispobj);