1 #if !defined(_INCLUDE_THREAD_H_)
2 #define _INCLUDE_THREAD_H_
3 
4 #include <sys/types.h>
5 #include <unistd.h>
6 #include <stddef.h>
7 #include "sbcl.h"
8 #include "globals.h"
9 #include "runtime.h"
10 #include "os.h"
11 #ifdef LISP_FEATURE_GENCGC
12 #include "gencgc-alloc-region.h"
13 #endif
14 #ifdef LISP_FEATURE_WIN32
15 #include "win32-thread-private-events.h"
16 #endif
17 #include "genesis/symbol.h"
18 #include "genesis/static-symbols.h"
19 
20 #include "genesis/thread.h"
21 #include "genesis/fdefn.h"
22 #include "interrupt.h"
23 #include "validate.h"           /* for BINDING_STACK_SIZE etc */
24 
25 #define STATE_RUNNING MAKE_FIXNUM(1)
26 #define STATE_STOPPED MAKE_FIXNUM(2)
27 #define STATE_DEAD MAKE_FIXNUM(3)
28 #if defined(LISP_FEATURE_SB_SAFEPOINT)
29 # define STATE_SUSPENDED_BRIEFLY MAKE_FIXNUM(4)
30 # define STATE_GC_BLOCKER MAKE_FIXNUM(5)
31 # define STATE_PHASE1_BLOCKER MAKE_FIXNUM(5)
32 # define STATE_PHASE2_BLOCKER MAKE_FIXNUM(6)
33 # define STATE_INTERRUPT_BLOCKER MAKE_FIXNUM(7)
34 #endif
35 
36 #ifdef LISP_FEATURE_SB_THREAD
37 lispobj thread_state(struct thread *thread);
38 void set_thread_state(struct thread *thread, lispobj state);
39 void wait_for_thread_state_change(struct thread *thread, lispobj state);
40 
41 #if defined(LISP_FEATURE_SB_SAFEPOINT)
42 enum threads_suspend_reason {
43     SUSPEND_REASON_NONE,
44     SUSPEND_REASON_GC,
45     SUSPEND_REASON_INTERRUPT,
46     SUSPEND_REASON_GCING
47 };
48 
49 struct threads_suspend_info {
50     int suspend;
51     pthread_mutex_t world_lock;
52     pthread_mutex_t lock;
53     enum threads_suspend_reason reason;
54     int phase;
55     struct thread * gc_thread;
56     struct thread * interrupted_thread;
57     int blockers;
58     int used_gc_page;
59 };
60 
61 struct suspend_phase {
62     int suspend;
63     enum threads_suspend_reason reason;
64     int phase;
65     struct suspend_phase *next;
66 };
67 
68 extern struct threads_suspend_info suspend_info;
69 
70 struct gcing_safety {
71     lispobj csp_around_foreign_call;
72 #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
73     lispobj* pc_around_foreign_call;
74 #endif
75 };
76 
77 int handle_safepoint_violation(os_context_t *context, os_vm_address_t addr);
78 void** os_get_csp(struct thread* th);
79 void alloc_gc_page();
80 void assert_on_stack(struct thread *th, void *esp);
81 #endif /* defined(LISP_FEATURE_SB_SAFEPOINT) */
82 
83 extern pthread_key_t lisp_thread;
84 #endif
85 
86 extern int kill_safely(os_thread_t os_thread, int signal);
87 
88 #define THREAD_SLOT_OFFSET_WORDS(c) \
89  (offsetof(struct thread,c)/(sizeof (struct thread *)))
90 
91 union per_thread_data {
92     struct thread thread;
93     lispobj dynamic_values[1];  /* actually more like 4000 or so */
94 };
95 
96 /* The thread struct is generated from lisp during genesis and it
97  * needs to know the sizes of all its members, but some types may have
98  * arbitrary lengths, thus the pointers are stored instead. This
99  * structure is used to help allocation of those types, so that the
100  * pointers can be later shoved into the thread struct. */
101 struct nonpointer_thread_data
102 {
103 #ifdef LISP_FEATURE_SB_THREAD
104     pthread_attr_t os_attr;
105 #ifndef LISP_FEATURE_SB_SAFEPOINT
106     os_sem_t state_sem;
107     os_sem_t state_not_running_sem;
108     os_sem_t state_not_stopped_sem;
109 #endif
110 #endif
111     struct interrupt_data interrupt_data;
112 };
113 
114 extern struct thread *all_threads;
115 extern int dynamic_values_bytes;
116 
117 #if defined(LISP_FEATURE_DARWIN)
118 #define CONTROL_STACK_ALIGNMENT_BYTES 8192 /* darwin wants page-aligned stacks */
119 #define THREAD_ALIGNMENT_BYTES CONTROL_STACK_ALIGNMENT_BYTES
120 #else
121 #define THREAD_ALIGNMENT_BYTES BACKEND_PAGE_BYTES
122 #define CONTROL_STACK_ALIGNMENT_BYTES 16
123 #endif
124 
125 
126 #ifdef LISP_FEATURE_SB_THREAD
127 #define for_each_thread(th) for(th=all_threads;th;th=th->next)
128 #else
129 /* there's some possibility a SSC could notice this never actually
130  * loops  */
131 #define for_each_thread(th) for(th=all_threads;th;th=0)
132 #endif
133 
134 #ifndef LISP_FEATURE_SB_THREAD
135 /* no threads: every symbol's tls_index is statically zero */
136 #  define tls_index_of(x) 0
137 #  define per_thread_value(sym, thread) sym->value
138 #else
139 #ifdef LISP_FEATURE_64_BIT
140 static inline int
tls_index_of(struct symbol * symbol)141 tls_index_of(struct symbol *symbol) // untagged pointer
142 {
143   return symbol->header >> 32;
144 }
145 #else
146 #  define tls_index_of(x) (x->tls_index)
147 #endif
148 #define per_thread_value(sym,th) \
149   ((union per_thread_data *)th)->dynamic_values[tls_index_of(sym)>>WORD_SHIFT]
150 #endif
151 
152 static inline lispobj *
SymbolValueAddress(u64 tagged_symbol_pointer,void * thread)153 SymbolValueAddress(u64 tagged_symbol_pointer, void *thread)
154 {
155     struct symbol *sym= SYMBOL(tagged_symbol_pointer);
156     if(thread && tls_index_of(sym)) {
157         lispobj *r = &per_thread_value(sym, thread);
158         if((*r)!=NO_TLS_VALUE_MARKER_WIDETAG) return r;
159     }
160     return &sym->value;
161 }
162 
163 static inline lispobj
SymbolValue(u64 tagged_symbol_pointer,void * thread)164 SymbolValue(u64 tagged_symbol_pointer, void *thread)
165 {
166     struct symbol *sym= SYMBOL(tagged_symbol_pointer);
167     if(thread && tls_index_of(sym)) {
168         lispobj r = per_thread_value(sym, thread);
169         if(r!=NO_TLS_VALUE_MARKER_WIDETAG) return r;
170     }
171     return sym->value;
172 }
173 
174 static inline void
SetSymbolValue(u64 tagged_symbol_pointer,lispobj val,void * thread)175 SetSymbolValue(u64 tagged_symbol_pointer,lispobj val, void *thread)
176 {
177     struct symbol *sym= SYMBOL(tagged_symbol_pointer);
178     if(thread && tls_index_of(sym)) {
179         if (per_thread_value(sym, thread) != NO_TLS_VALUE_MARKER_WIDETAG) {
180             per_thread_value(sym, thread) = val;
181             return;
182         }
183     }
184     sym->value = val;
185 }
186 
187 static inline lispobj
SymbolTlValue(u64 tagged_symbol_pointer,void * thread)188 SymbolTlValue(u64 tagged_symbol_pointer, void *thread)
189 {
190     struct symbol *sym= SYMBOL(tagged_symbol_pointer);
191     return per_thread_value(sym, thread);
192 }
193 
194 static inline void
SetTlSymbolValue(u64 tagged_symbol_pointer,lispobj val,void * thread)195 SetTlSymbolValue(u64 tagged_symbol_pointer,lispobj val, void *thread)
196 {
197     struct symbol *sym= SYMBOL(tagged_symbol_pointer);
198     // dynbind asserts that there is a tls_index in multithread runtime
199     per_thread_value(sym, thread) = val;
200 }
201 
202 /* This only works for static symbols. */
203 static inline lispobj
StaticSymbolFunction(lispobj sym)204 StaticSymbolFunction(lispobj sym)
205 {
206     return ((struct fdefn *)native_pointer(SymbolValue(sym, 0)))->fun;
207 }
208 
209 /* These are for use during GC, on the current thread, or on prenatal
210  * threads only. */
211 #if defined(LISP_FEATURE_SB_THREAD)
212 #define get_binding_stack_pointer(thread)       \
213     ((thread)->binding_stack_pointer)
214 #define set_binding_stack_pointer(thread,value) \
215     ((thread)->binding_stack_pointer = (lispobj *)(value))
216 #define access_control_stack_pointer(thread) \
217     ((thread)->control_stack_pointer)
218 #  if !defined(LISP_FEATURE_X86) && !defined(LISP_FEATURE_X86_64)
219 #define access_control_frame_pointer(thread) \
220     ((thread)->control_frame_pointer)
221 #  endif
222 #else
223 #  if defined(BINDING_STACK_POINTER)
224 #define get_binding_stack_pointer(thread)       \
225     SymbolValue(BINDING_STACK_POINTER, thread)
226 #define set_binding_stack_pointer(thread,value) \
227     SetSymbolValue(BINDING_STACK_POINTER, (lispobj)(value), thread)
228 #  else
229 #define get_binding_stack_pointer(thread)       \
230     (current_binding_stack_pointer)
231 #define set_binding_stack_pointer(thread,value) \
232     (current_binding_stack_pointer = (lispobj *)(value))
233 #  endif
234 #define access_control_stack_pointer(thread)    \
235     (current_control_stack_pointer)
236 #  if !defined(LISP_FEATURE_X86) && !defined(LISP_FEATURE_X86_64)
237 #define access_control_frame_pointer(thread) \
238     (current_control_frame_pointer)
239 #  endif
240 #endif
241 
242 #if defined(LISP_FEATURE_SB_THREAD) && defined(LISP_FEATURE_GCC_TLS)
243 extern __thread struct thread *current_thread;
244 #endif
245 
246 #ifndef LISP_FEATURE_SB_SAFEPOINT
247 # define THREAD_CSP_PAGE_SIZE 0
248 #elif defined(LISP_FEATURE_PPC)
249   /* BACKEND_PAGE_BYTES is nice and large on this platform, but therefore
250    * does not fit into an immediate, making it awkward to access the page
251    * relative to the thread-tn... */
252 # define THREAD_CSP_PAGE_SIZE 4096
253 #else
254 # define THREAD_CSP_PAGE_SIZE BACKEND_PAGE_BYTES
255 #endif
256 
257 #ifdef LISP_FEATURE_WIN32
258 /*
259  * Win32 doesn't have SIGSTKSZ, and we're not switching stacks anyway,
260  * so define it arbitrarily
261  */
262 #define SIGSTKSZ 1024
263 #endif
264 
265 #define THREAD_STRUCT_SIZE (thread_control_stack_size + BINDING_STACK_SIZE + \
266                             ALIEN_STACK_SIZE +                          \
267                             sizeof(struct nonpointer_thread_data) +     \
268                             dynamic_values_bytes +                      \
269                             32 * SIGSTKSZ +                             \
270                             THREAD_ALIGNMENT_BYTES +                    \
271                             THREAD_CSP_PAGE_SIZE)
272 
273 #if defined(LISP_FEATURE_WIN32)
274 static inline struct thread* arch_os_get_current_thread()
275     __attribute__((__const__));
276 #endif
277 
278 /* This is clearly per-arch and possibly even per-OS code, but we can't
279  * put it somewhere sensible like x86-linux-os.c because it needs too
280  * much stuff like struct thread and all_threads to be defined, which
281  * usually aren't by that time.  So, it's here instead.  Sorry */
282 
arch_os_get_current_thread(void)283 static inline struct thread *arch_os_get_current_thread(void)
284 {
285 #if !defined(LISP_FEATURE_SB_THREAD)
286      return all_threads;
287 
288 #elif defined(LISP_FEATURE_X86) && defined(LISP_FEATURE_WIN32)
289     register struct thread *me=0;
290     __asm__ volatile ("movl %%fs:0xE10+(4*63), %0" : "=r"(me) :);
291     return me;
292 
293 #else
294 
295 # if defined(LISP_FEATURE_X86)
296     if (!all_threads) return 0;
297 #endif
298 
299     /* Otherwise, use pthreads to find the right value.  We do not load
300      * directly from %fs:this even on x86 platforms (like Linux and
301      * Solaris) with dependable %fs, because we want to return NULL if
302      * called by a non-Lisp thread, and %fs would not be initialized
303      * suitably in that case. */
304     struct thread *th;
305 # ifdef LISP_FEATURE_GCC_TLS
306     th = current_thread;
307 # else
308     th = pthread_getspecific(specials);
309 # endif
310 
311 # if defined(LISP_FEATURE_RESTORE_FS_SEGMENT_REGISTER_FROM_TLS)
312     /* If enabled by make-config (currently Darwin and FreeBSD only),
313      * re-setup %fs.  This is an out-of-line call, and potentially
314      * expensive.*/
315     if (th) {
316         void arch_os_load_ldt(struct thread*);
317         arch_os_load_ldt(th);
318     }
319 # endif
320 
321     return th;
322 #endif
323 }
324 
325 #if defined(LISP_FEATURE_MACH_EXCEPTION_HANDLER)
326 extern kern_return_t mach_lisp_thread_init(struct thread *thread);
327 extern void mach_lisp_thread_destroy(struct thread *thread);
328 #endif
329 
330 typedef struct init_thread_data {
331     sigset_t oldset;
332 #ifdef LISP_FEATURE_SB_SAFEPOINT
333     struct gcing_safety safety;
334 #endif
335 } init_thread_data;
336 
337 #ifdef LISP_FEATURE_SB_SAFEPOINT
338 void thread_in_safety_transition(os_context_t *ctx);
339 void thread_in_lisp_raised(os_context_t *ctx);
340 void thread_interrupted(os_context_t *ctx);
341 void thread_pitstop(os_context_t *ctxptr);
342 extern void thread_register_gc_trigger();
343 
344 # ifdef LISP_FEATURE_SB_THRUPTION
345 int wake_thread(os_thread_t os_thread);
346 #  ifdef LISP_FEATURE_WIN32
347 void wake_thread_win32(struct thread *thread);
348 #  else
349 int wake_thread_posix(os_thread_t os_thread);
350 #  endif
351 # endif
352 
353 static inline
push_gcing_safety(struct gcing_safety * into)354 void push_gcing_safety(struct gcing_safety *into)
355 {
356     struct thread* th = arch_os_get_current_thread();
357     asm volatile ("");
358     if ((into->csp_around_foreign_call =
359          *th->csp_around_foreign_call)) {
360         *th->csp_around_foreign_call = 0;
361         asm volatile ("");
362 #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
363         into->pc_around_foreign_call = th->pc_around_foreign_call;
364         th->pc_around_foreign_call = 0;
365         asm volatile ("");
366 #endif
367     } else {
368 #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
369         into->pc_around_foreign_call = 0;
370 #endif
371     }
372 }
373 
374 static inline
pop_gcing_safety(struct gcing_safety * from)375 void pop_gcing_safety(struct gcing_safety *from)
376 {
377     struct thread* th = arch_os_get_current_thread();
378     if (from->csp_around_foreign_call) {
379         asm volatile ("");
380         *th->csp_around_foreign_call = from->csp_around_foreign_call;
381         asm volatile ("");
382 #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
383         th->pc_around_foreign_call = from->pc_around_foreign_call;
384         asm volatile ("");
385 #endif
386     }
387 }
388 
389 /* Even with just -O1, gcc optimizes the jumps in this "loop" away
390  * entirely, giving the ability to define WITH-FOO-style macros. */
391 #define RUN_BODY_ONCE(prefix, finally_do)               \
392     int prefix##done = 0;                               \
393     for (; !prefix##done; finally_do, prefix##done = 1)
394 
395 #define WITH_GC_AT_SAFEPOINTS_ONLY_hygenic(var)        \
396     struct gcing_safety var;                    \
397     push_gcing_safety(&var);                    \
398     RUN_BODY_ONCE(var, pop_gcing_safety(&var))
399 
400 #define WITH_GC_AT_SAFEPOINTS_ONLY()                           \
401     WITH_GC_AT_SAFEPOINTS_ONLY_hygenic(sbcl__gc_safety)
402 
403 #define WITH_STATE_SEM_hygenic(var, thread)                             \
404     os_sem_wait((thread)->state_sem, "thread_state");                   \
405     RUN_BODY_ONCE(var, os_sem_post((thread)->state_sem, "thread_state"))
406 
407 #define WITH_STATE_SEM(thread)                                     \
408     WITH_STATE_SEM_hygenic(sbcl__state_sem, thread)
409 
410 int check_pending_thruptions(os_context_t *ctx);
411 
412 void attach_os_thread(init_thread_data *);
413 void detach_os_thread(init_thread_data *);
414 
415 # if defined(LISP_FEATURE_SB_SAFEPOINT_STRICTLY) && !defined(LISP_FEATURE_WIN32)
416 
417 void signal_handler_callback(lispobj, int, void *, void *);
418 # endif
419 
420 #endif
421 
422 extern void create_initial_thread(lispobj);
423 
424 #ifdef LISP_FEATURE_SB_THREAD
425 extern pthread_mutex_t all_threads_lock;
426 #endif
427 
428 #endif /* _INCLUDE_THREAD_H_ */
429