1 #if !defined(_INCLUDE_THREAD_H_)
2 #define _INCLUDE_THREAD_H_
11 #ifdef LISP_FEATURE_GENCGC
12 #include "gencgc-alloc-region.h"
14 #ifdef LISP_FEATURE_WIN32
15 #include "win32-thread-private-events.h"
17 #include "genesis/symbol.h"
18 #include "genesis/static-symbols.h"
20 #include "genesis/thread.h"
21 #include "genesis/fdefn.h"
22 #include "interrupt.h"
23 #include "validate.h" /* for BINDING_STACK_SIZE etc */
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)
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);
41 #if defined(LISP_FEATURE_SB_SAFEPOINT)
42 enum threads_suspend_reason {
45 SUSPEND_REASON_INTERRUPT,
49 struct threads_suspend_info {
51 pthread_mutex_t world_lock;
53 enum threads_suspend_reason reason;
55 struct thread * gc_thread;
56 struct thread * interrupted_thread;
61 struct suspend_phase {
63 enum threads_suspend_reason reason;
65 struct suspend_phase *next;
68 extern struct threads_suspend_info suspend_info;
71 lispobj csp_around_foreign_call;
72 #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
73 lispobj* pc_around_foreign_call;
77 int handle_safepoint_violation(os_context_t *context, os_vm_address_t addr);
78 void** os_get_csp(struct thread* th);
80 void assert_on_stack(struct thread *th, void *esp);
81 #endif /* defined(LISP_FEATURE_SB_SAFEPOINT) */
83 extern pthread_key_t lisp_thread;
86 extern int kill_safely(os_thread_t os_thread, int signal);
88 #define THREAD_SLOT_OFFSET_WORDS(c) \
89 (offsetof(struct thread,c)/(sizeof (struct thread *)))
91 union per_thread_data {
93 lispobj dynamic_values[1]; /* actually more like 4000 or so */
96 /* A helper structure for data local to a thread, which is not pointer-sized.
98 * Originally, all layouting of these fields was done manually in C code
99 * with pointer arithmetic. We let the C compiler figure it out now.
101 * (Why is this not part of `struct thread'? Because that structure is
102 * declared using genesis, and we would run into issues with fields that
103 * are of unknown length.)
105 struct nonpointer_thread_data
107 #if defined(LISP_FEATURE_SB_THREAD) && !defined(LISP_FEATURE_SB_SAFEPOINT)
109 os_sem_t state_not_running_sem;
110 os_sem_t state_not_stopped_sem;
112 /* An unused field follows, to ensure that the struct is non-empty
113 * for non-GCC compilers. */
118 extern struct thread *all_threads;
119 extern int dynamic_values_bytes;
121 #if defined(LISP_FEATURE_DARWIN)
122 #define CONTROL_STACK_ALIGNMENT_BYTES 8192 /* darwin wants page-aligned stacks */
123 #define THREAD_ALIGNMENT_BYTES CONTROL_STACK_ALIGNMENT_BYTES
125 #define THREAD_ALIGNMENT_BYTES BACKEND_PAGE_BYTES
126 #define CONTROL_STACK_ALIGNMENT_BYTES 16
130 #ifdef LISP_FEATURE_SB_THREAD
131 #define for_each_thread(th) for(th=all_threads;th;th=th->next)
133 /* there's some possibility a SSC could notice this never actually
135 #define for_each_thread(th) for(th=all_threads;th;th=0)
138 static inline lispobj *
139 SymbolValueAddress(u64 tagged_symbol_pointer, void *thread)
141 struct symbol *sym= (struct symbol *)
142 (pointer_sized_uint_t)(tagged_symbol_pointer-OTHER_POINTER_LOWTAG);
143 #ifdef LISP_FEATURE_SB_THREAD
144 if(thread && sym->tls_index) {
145 lispobj *r = &(((union per_thread_data *)thread)
146 ->dynamic_values[(sym->tls_index) >> WORD_SHIFT]);
147 if((*r)!=NO_TLS_VALUE_MARKER_WIDETAG) return r;
153 static inline lispobj
154 SymbolValue(u64 tagged_symbol_pointer, void *thread)
156 struct symbol *sym= (struct symbol *)
157 (pointer_sized_uint_t)(tagged_symbol_pointer-OTHER_POINTER_LOWTAG);
158 #ifdef LISP_FEATURE_SB_THREAD
159 if(thread && sym->tls_index) {
161 ((union per_thread_data *)thread)
162 ->dynamic_values[(sym->tls_index) >> WORD_SHIFT];
163 if(r!=NO_TLS_VALUE_MARKER_WIDETAG) return r;
169 static inline lispobj
170 SymbolTlValue(u64 tagged_symbol_pointer, void *thread)
172 struct symbol *sym= (struct symbol *)
173 (pointer_sized_uint_t)(tagged_symbol_pointer-OTHER_POINTER_LOWTAG);
174 #ifdef LISP_FEATURE_SB_THREAD
175 return ((union per_thread_data *)thread)
176 ->dynamic_values[(sym->tls_index) >> WORD_SHIFT];
183 SetSymbolValue(u64 tagged_symbol_pointer,lispobj val, void *thread)
185 struct symbol *sym= (struct symbol *)
186 (pointer_sized_uint_t)(tagged_symbol_pointer-OTHER_POINTER_LOWTAG);
187 #ifdef LISP_FEATURE_SB_THREAD
188 if(thread && sym->tls_index) {
189 lispobj *pr= &(((union per_thread_data *)thread)
190 ->dynamic_values[(sym->tls_index) >> WORD_SHIFT]);
191 if(*pr!=NO_TLS_VALUE_MARKER_WIDETAG) {
201 SetTlSymbolValue(u64 tagged_symbol_pointer,lispobj val, void *thread)
203 #ifdef LISP_FEATURE_SB_THREAD
204 struct symbol *sym= (struct symbol *)
205 (pointer_sized_uint_t)(tagged_symbol_pointer-OTHER_POINTER_LOWTAG);
206 ((union per_thread_data *)thread)
207 ->dynamic_values[(sym->tls_index) >> WORD_SHIFT]
210 SetSymbolValue(tagged_symbol_pointer,val,thread) ;
214 /* This only works for static symbols. */
215 static inline lispobj
216 StaticSymbolFunction(lispobj sym)
218 return ((struct fdefn *)native_pointer(SymbolValue(sym, 0)))->fun;
221 /* These are for use during GC, on the current thread, or on prenatal
223 #if defined(LISP_FEATURE_SB_THREAD)
224 #define get_binding_stack_pointer(thread) \
225 ((thread)->binding_stack_pointer)
226 #define set_binding_stack_pointer(thread,value) \
227 ((thread)->binding_stack_pointer = (lispobj *)(value))
228 #define access_control_stack_pointer(thread) \
229 ((thread)->control_stack_pointer)
230 # if !defined(LISP_FEATURE_X86) && !defined(LISP_FEATURE_X86_64)
231 #define access_control_frame_pointer(thread) \
232 ((thread)->control_frame_pointer)
235 # if defined(BINDING_STACK_POINTER)
236 #define get_binding_stack_pointer(thread) \
237 SymbolValue(BINDING_STACK_POINTER, thread)
238 #define set_binding_stack_pointer(thread,value) \
239 SetSymbolValue(BINDING_STACK_POINTER, (lispobj)(value), thread)
241 #define get_binding_stack_pointer(thread) \
242 (current_binding_stack_pointer)
243 #define set_binding_stack_pointer(thread,value) \
244 (current_binding_stack_pointer = (lispobj *)(value))
246 #define access_control_stack_pointer(thread) \
247 (current_control_stack_pointer)
248 # if !defined(LISP_FEATURE_X86) && !defined(LISP_FEATURE_X86_64)
249 #define access_control_frame_pointer(thread) \
250 (current_control_frame_pointer)
254 #if defined(LISP_FEATURE_SB_THREAD) && defined(LISP_FEATURE_GCC_TLS)
255 extern __thread struct thread *current_thread;
258 #ifndef LISP_FEATURE_SB_SAFEPOINT
259 # define THREAD_CSP_PAGE_SIZE 0
260 #elif defined(LISP_FEATURE_PPC)
261 /* BACKEND_PAGE_BYTES is nice and large on this platform, but therefore
262 * does not fit into an immediate, making it awkward to access the page
263 * relative to the thread-tn... */
264 # define THREAD_CSP_PAGE_SIZE 4096
266 # define THREAD_CSP_PAGE_SIZE BACKEND_PAGE_BYTES
269 #ifdef LISP_FEATURE_WIN32
271 * Win32 doesn't have SIGSTKSZ, and we're not switching stacks anyway,
272 * so define it arbitrarily
274 #define SIGSTKSZ 1024
277 #define THREAD_STRUCT_SIZE (thread_control_stack_size + BINDING_STACK_SIZE + \
279 sizeof(struct nonpointer_thread_data) + \
280 dynamic_values_bytes + \
282 THREAD_ALIGNMENT_BYTES + \
283 THREAD_CSP_PAGE_SIZE)
285 #if defined(LISP_FEATURE_WIN32)
286 static inline struct thread* arch_os_get_current_thread()
287 __attribute__((__const__));
290 /* This is clearly per-arch and possibly even per-OS code, but we can't
291 * put it somewhere sensible like x86-linux-os.c because it needs too
292 * much stuff like struct thread and all_threads to be defined, which
293 * usually aren't by that time. So, it's here instead. Sorry */
295 static inline struct thread *arch_os_get_current_thread(void)
297 #if !defined(LISP_FEATURE_SB_THREAD)
300 #elif defined(LISP_FEATURE_X86) && defined(LISP_FEATURE_WIN32)
301 register struct thread *me=0;
302 __asm__ ("movl %%fs:0xE10+(4*63), %0" : "=r"(me) :);
307 # if defined(LISP_FEATURE_X86)
308 if (!all_threads) return 0;
311 /* Otherwise, use pthreads to find the right value. We do not load
312 * directly from %fs:this even on x86 platforms (like Linux and
313 * Solaris) with dependable %fs, because we want to return NULL if
314 * called by a non-Lisp thread, and %fs would not be initialized
315 * suitably in that case. */
317 # ifdef LISP_FEATURE_GCC_TLS
320 th = pthread_getspecific(specials);
323 # if defined(LISP_FEATURE_RESTORE_FS_SEGMENT_REGISTER_FROM_TLS)
324 /* If enabled by make-config (currently Darwin and FreeBSD only),
325 * re-setup %fs. This is an out-of-line call, and potentially
328 arch_os_load_ldt(th);
335 #if defined(LISP_FEATURE_MACH_EXCEPTION_HANDLER)
336 extern kern_return_t mach_lisp_thread_init(struct thread *thread);
337 extern kern_return_t mach_lisp_thread_destroy(struct thread *thread);
340 typedef struct init_thread_data {
341 #ifdef LISP_FEATURE_SB_SAFEPOINT
342 struct gcing_safety safety;
347 #ifdef LISP_FEATURE_SB_SAFEPOINT
348 void thread_in_safety_transition(os_context_t *ctx);
349 void thread_in_lisp_raised(os_context_t *ctx);
350 void thread_interrupted(os_context_t *ctx);
351 void thread_pitstop(os_context_t *ctxptr);
352 extern void thread_register_gc_trigger();
354 # ifdef LISP_FEATURE_SB_THRUPTION
355 int wake_thread(os_thread_t os_thread);
356 # ifdef LISP_FEATURE_WIN32
357 void wake_thread_win32(struct thread *thread);
359 int wake_thread_posix(os_thread_t os_thread);
364 void push_gcing_safety(struct gcing_safety *into)
366 struct thread* th = arch_os_get_current_thread();
368 if ((into->csp_around_foreign_call =
369 *th->csp_around_foreign_call)) {
370 *th->csp_around_foreign_call = 0;
372 #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
373 into->pc_around_foreign_call = th->pc_around_foreign_call;
374 th->pc_around_foreign_call = 0;
378 #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
379 into->pc_around_foreign_call = 0;
385 void pop_gcing_safety(struct gcing_safety *from)
387 struct thread* th = arch_os_get_current_thread();
388 if (from->csp_around_foreign_call) {
390 *th->csp_around_foreign_call = from->csp_around_foreign_call;
392 #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
393 th->pc_around_foreign_call = from->pc_around_foreign_call;
399 /* Even with just -O1, gcc optimizes the jumps in this "loop" away
400 * entirely, giving the ability to define WITH-FOO-style macros. */
401 #define RUN_BODY_ONCE(prefix, finally_do) \
402 int prefix##done = 0; \
403 for (; !prefix##done; finally_do, prefix##done = 1)
405 #define WITH_GC_AT_SAFEPOINTS_ONLY_hygenic(var) \
406 struct gcing_safety var; \
407 push_gcing_safety(&var); \
408 RUN_BODY_ONCE(var, pop_gcing_safety(&var))
410 #define WITH_GC_AT_SAFEPOINTS_ONLY() \
411 WITH_GC_AT_SAFEPOINTS_ONLY_hygenic(sbcl__gc_safety)
413 #define WITH_STATE_SEM_hygenic(var, thread) \
414 os_sem_wait((thread)->state_sem, "thread_state"); \
415 RUN_BODY_ONCE(var, os_sem_post((thread)->state_sem, "thread_state"))
417 #define WITH_STATE_SEM(thread) \
418 WITH_STATE_SEM_hygenic(sbcl__state_sem, thread)
420 int check_pending_thruptions(os_context_t *ctx);
424 extern void create_initial_thread(lispobj);
426 #ifdef LISP_FEATURE_SB_THREAD
427 extern pthread_mutex_t all_threads_lock;
430 #endif /* _INCLUDE_THREAD_H_ */