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 /* 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
103 #ifdef LISP_FEATURE_SB_THREAD
104 pthread_attr_t os_attr
;
105 #ifndef LISP_FEATURE_SB_SAFEPOINT
107 os_sem_t state_not_running_sem
;
108 os_sem_t state_not_stopped_sem
;
111 struct interrupt_data interrupt_data
;
114 extern struct thread
*all_threads
;
115 extern int dynamic_values_bytes
;
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
121 #define THREAD_ALIGNMENT_BYTES BACKEND_PAGE_BYTES
122 #define CONTROL_STACK_ALIGNMENT_BYTES 16
126 #ifdef LISP_FEATURE_SB_THREAD
127 #define for_each_thread(th) for(th=all_threads;th;th=th->next)
129 /* there's some possibility a SSC could notice this never actually
131 #define for_each_thread(th) for(th=all_threads;th;th=0)
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
139 #ifdef LISP_FEATURE_64_BIT
140 static inline unsigned int
141 tls_index_of(struct symbol
*symbol
) // untagged pointer
143 return symbol
->header
>> 32;
146 # define tls_index_of(x) (x->tls_index)
148 #define per_thread_value(sym,th) \
149 ((union per_thread_data *)th)->dynamic_values[tls_index_of(sym)>>WORD_SHIFT]
152 static inline lispobj
153 SymbolValue(u64 tagged_symbol_pointer
, void *thread
)
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
;
164 SetSymbolValue(u64 tagged_symbol_pointer
,lispobj val
, void *thread
)
166 struct symbol
*sym
= SYMBOL(tagged_symbol_pointer
);
167 if(thread
&& tls_index_of(sym
)) {
168 if (per_thread_value(sym
, thread
) != NO_TLS_VALUE_MARKER_WIDETAG
) {
169 per_thread_value(sym
, thread
) = val
;
176 #ifdef LISP_FEATURE_SB_THREAD
177 /* write_TLS assigns directly into TLS causing the symbol to
178 * be thread-local without saving a prior value on the binding stack. */
179 # define write_TLS(sym, val, thread) write_TLS_index(sym##_tlsindex, val, thread, _ignored_)
180 # define write_TLS_index(index, val, thread, sym) \
181 *(lispobj*)(index + (char*)((union per_thread_data*)thread)->dynamic_values) = val
182 # define read_TLS(sym, thread) \
183 *(lispobj*)(sym##_tlsindex + (char*)((union per_thread_data*)thread)->dynamic_values)
185 # define write_TLS(sym, val, thread) SYMBOL(sym)->value = val
186 # define write_TLS_index(index, val, thread, sym) sym->value = val
187 # define read_TLS(sym, thread) SYMBOL(sym)->value
190 #define StaticSymbolFunction(x) FdefnFun(x##_FDEFN)
191 /* Return 'fun' given a tagged pointer to an fdefn. */
192 static inline lispobj
FdefnFun(lispobj fdefn
)
194 return FDEFN(fdefn
)->fun
;
197 /* These are for use during GC, on the current thread, or on prenatal
199 #if defined(LISP_FEATURE_SB_THREAD)
200 #define get_binding_stack_pointer(thread) \
201 ((thread)->binding_stack_pointer)
202 #define set_binding_stack_pointer(thread,value) \
203 ((thread)->binding_stack_pointer = (lispobj *)(value))
204 #define access_control_stack_pointer(thread) \
205 ((thread)->control_stack_pointer)
206 # if !defined(LISP_FEATURE_X86) && !defined(LISP_FEATURE_X86_64)
207 #define access_control_frame_pointer(thread) \
208 ((thread)->control_frame_pointer)
211 # if defined(BINDING_STACK_POINTER)
212 #define get_binding_stack_pointer(thread) \
213 SymbolValue(BINDING_STACK_POINTER, thread)
214 #define set_binding_stack_pointer(thread,value) \
215 SetSymbolValue(BINDING_STACK_POINTER, (lispobj)(value), thread)
217 #define get_binding_stack_pointer(thread) \
218 (current_binding_stack_pointer)
219 #define set_binding_stack_pointer(thread,value) \
220 (current_binding_stack_pointer = (lispobj *)(value))
222 #define access_control_stack_pointer(thread) \
223 (current_control_stack_pointer)
224 # if !defined(LISP_FEATURE_X86) && !defined(LISP_FEATURE_X86_64)
225 #define access_control_frame_pointer(thread) \
226 (current_control_frame_pointer)
230 #if defined(LISP_FEATURE_SB_THREAD) && defined(LISP_FEATURE_GCC_TLS)
231 extern __thread
struct thread
*current_thread
;
234 #ifndef LISP_FEATURE_SB_SAFEPOINT
235 # define THREAD_CSP_PAGE_SIZE 0
236 #elif defined(LISP_FEATURE_PPC)
237 /* BACKEND_PAGE_BYTES is nice and large on this platform, but therefore
238 * does not fit into an immediate, making it awkward to access the page
239 * relative to the thread-tn... */
240 # define THREAD_CSP_PAGE_SIZE 4096
242 # define THREAD_CSP_PAGE_SIZE BACKEND_PAGE_BYTES
245 #ifdef LISP_FEATURE_WIN32
247 * Win32 doesn't have SIGSTKSZ, and we're not switching stacks anyway,
248 * so define it arbitrarily
250 #define SIGSTKSZ 1024
253 #define THREAD_STRUCT_SIZE (thread_control_stack_size + BINDING_STACK_SIZE + \
255 sizeof(struct nonpointer_thread_data) + \
256 dynamic_values_bytes + \
258 THREAD_ALIGNMENT_BYTES + \
259 THREAD_CSP_PAGE_SIZE)
261 #if defined(LISP_FEATURE_WIN32)
262 static inline struct thread
* arch_os_get_current_thread()
263 __attribute__((__const__
));
266 /* This is clearly per-arch and possibly even per-OS code, but we can't
267 * put it somewhere sensible like x86-linux-os.c because it needs too
268 * much stuff like struct thread and all_threads to be defined, which
269 * usually aren't by that time. So, it's here instead. Sorry */
271 static inline struct thread
*arch_os_get_current_thread(void)
273 #if !defined(LISP_FEATURE_SB_THREAD)
276 #elif defined(LISP_FEATURE_X86) && defined(LISP_FEATURE_WIN32)
277 register struct thread
*me
=0;
278 __asm__
volatile ("movl %%fs:0xE10+(4*63), %0" : "=r"(me
) :);
283 # if defined(LISP_FEATURE_X86)
284 if (!all_threads
) return 0;
287 /* Otherwise, use pthreads to find the right value. We do not load
288 * directly from %fs:this even on x86 platforms (like Linux and
289 * Solaris) with dependable %fs, because we want to return NULL if
290 * called by a non-Lisp thread, and %fs would not be initialized
291 * suitably in that case. */
293 # ifdef LISP_FEATURE_GCC_TLS
296 th
= pthread_getspecific(specials
);
299 # if defined(LISP_FEATURE_RESTORE_FS_SEGMENT_REGISTER_FROM_TLS)
300 /* If enabled by make-config (currently Darwin and FreeBSD only),
301 * re-setup %fs. This is an out-of-line call, and potentially
304 void arch_os_load_ldt(struct thread
*);
305 arch_os_load_ldt(th
);
313 inline static int lisp_thread_p(os_context_t
*context
) {
314 #ifdef LISP_FEATURE_SB_THREAD
315 return pthread_getspecific(lisp_thread
) != NULL
;
316 #elif defined(LISP_FEATURE_C_STACK_IS_CONTROL_STACK)
317 char *csp
= (char *)*os_context_sp_addr(context
);
318 return (char *)all_threads
->control_stack_start
< csp
&&
319 (char *)all_threads
->control_stack_end
> (char *) csp
;
321 /* Can't really tell since pthreads are required to get the
322 dimensions of the C stack. */
327 #if defined(LISP_FEATURE_MACH_EXCEPTION_HANDLER)
328 extern kern_return_t
mach_lisp_thread_init(struct thread
*thread
);
329 extern void mach_lisp_thread_destroy(struct thread
*thread
);
332 typedef struct init_thread_data
{
334 #ifdef LISP_FEATURE_SB_SAFEPOINT
335 struct gcing_safety safety
;
339 #ifdef LISP_FEATURE_SB_SAFEPOINT
340 void thread_in_safety_transition(os_context_t
*ctx
);
341 void thread_in_lisp_raised(os_context_t
*ctx
);
342 void thread_interrupted(os_context_t
*ctx
);
343 void thread_pitstop(os_context_t
*ctxptr
);
344 extern void thread_register_gc_trigger();
346 # ifdef LISP_FEATURE_SB_THRUPTION
347 int wake_thread(os_thread_t os_thread
);
348 # ifdef LISP_FEATURE_WIN32
349 void wake_thread_win32(struct thread
*thread
);
351 int wake_thread_posix(os_thread_t os_thread
);
356 void push_gcing_safety(struct gcing_safety
*into
)
358 struct thread
* th
= arch_os_get_current_thread();
360 if ((into
->csp_around_foreign_call
=
361 *th
->csp_around_foreign_call
)) {
362 *th
->csp_around_foreign_call
= 0;
364 #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
365 into
->pc_around_foreign_call
= th
->pc_around_foreign_call
;
366 th
->pc_around_foreign_call
= 0;
370 #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
371 into
->pc_around_foreign_call
= 0;
377 void pop_gcing_safety(struct gcing_safety
*from
)
379 struct thread
* th
= arch_os_get_current_thread();
380 if (from
->csp_around_foreign_call
) {
382 *th
->csp_around_foreign_call
= from
->csp_around_foreign_call
;
384 #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
385 th
->pc_around_foreign_call
= from
->pc_around_foreign_call
;
391 #define WITH_GC_AT_SAFEPOINTS_ONLY_hygenic(var) \
392 struct gcing_safety var; \
393 push_gcing_safety(&var); \
394 RUN_BODY_ONCE(var, pop_gcing_safety(&var))
396 #define WITH_GC_AT_SAFEPOINTS_ONLY() \
397 WITH_GC_AT_SAFEPOINTS_ONLY_hygenic(sbcl__gc_safety)
399 #define WITH_STATE_SEM_hygenic(var, thread) \
400 os_sem_wait((thread)->state_sem, "thread_state"); \
401 RUN_BODY_ONCE(var, os_sem_post((thread)->state_sem, "thread_state"))
403 #define WITH_STATE_SEM(thread) \
404 WITH_STATE_SEM_hygenic(sbcl__state_sem, thread)
406 int check_pending_thruptions(os_context_t
*ctx
);
408 void attach_os_thread(init_thread_data
*);
409 void detach_os_thread(init_thread_data
*);
411 # if defined(LISP_FEATURE_SB_SAFEPOINT_STRICTLY) && !defined(LISP_FEATURE_WIN32)
413 void signal_handler_callback(lispobj
, int, void *, void *);
418 extern void create_initial_thread(lispobj
);
420 #ifdef LISP_FEATURE_SB_THREAD
421 extern pthread_mutex_t all_threads_lock
;
424 #endif /* _INCLUDE_THREAD_H_ */