1 #if !defined(_INCLUDE_THREAD_H_)
2 #define _INCLUDE_THREAD_H_
11 #ifdef LISP_FEATURE_GENCGC
12 #include "gencgc-alloc-region.h"
14 #include "genesis/symbol.h"
15 #include "genesis/static-symbols.h"
17 #include "genesis/thread.h"
18 #include "genesis/fdefn.h"
19 #include "interrupt.h"
21 #define STATE_RUNNING MAKE_FIXNUM(1)
22 #define STATE_STOPPED MAKE_FIXNUM(2)
23 #define STATE_DEAD MAKE_FIXNUM(3)
25 #ifdef LISP_FEATURE_SB_THREAD
26 lispobj thread_state(struct thread *thread);
27 void set_thread_state(struct thread *thread, lispobj state);
28 void wait_for_thread_state_change(struct thread *thread, lispobj state);
29 extern pthread_key_t lisp_thread;
32 extern int kill_safely(os_thread_t os_thread, int signal);
34 #define THREAD_SLOT_OFFSET_WORDS(c) \
35 (offsetof(struct thread,c)/(sizeof (struct thread *)))
37 union per_thread_data {
39 lispobj dynamic_values[1]; /* actually more like 4000 or so */
42 extern struct thread *all_threads;
43 extern int dynamic_values_bytes;
45 #if defined(LISP_FEATURE_DARWIN)
46 #define CONTROL_STACK_ALIGNMENT_BYTES 8192 /* darwin wants page-aligned stacks */
47 #define THREAD_ALIGNMENT_BYTES CONTROL_STACK_ALIGNMENT_BYTES
49 #define THREAD_ALIGNMENT_BYTES BACKEND_PAGE_BYTES
50 #define CONTROL_STACK_ALIGNMENT_BYTES 16
54 #ifdef LISP_FEATURE_SB_THREAD
55 #define for_each_thread(th) for(th=all_threads;th;th=th->next)
57 /* there's some possibility a SSC could notice this never actually
59 #define for_each_thread(th) for(th=all_threads;th;th=0)
62 static inline lispobj *
63 SymbolValueAddress(u64 tagged_symbol_pointer, void *thread)
65 struct symbol *sym= (struct symbol *)
66 (pointer_sized_uint_t)(tagged_symbol_pointer-OTHER_POINTER_LOWTAG);
67 #ifdef LISP_FEATURE_SB_THREAD
68 if(thread && sym->tls_index) {
69 lispobj *r = &(((union per_thread_data *)thread)
70 ->dynamic_values[(sym->tls_index) >> WORD_SHIFT]);
71 if((*r)!=NO_TLS_VALUE_MARKER_WIDETAG) return r;
78 SymbolValue(u64 tagged_symbol_pointer, void *thread)
80 struct symbol *sym= (struct symbol *)
81 (pointer_sized_uint_t)(tagged_symbol_pointer-OTHER_POINTER_LOWTAG);
82 #ifdef LISP_FEATURE_SB_THREAD
83 if(thread && sym->tls_index) {
85 ((union per_thread_data *)thread)
86 ->dynamic_values[(sym->tls_index) >> WORD_SHIFT];
87 if(r!=NO_TLS_VALUE_MARKER_WIDETAG) return r;
94 SymbolTlValue(u64 tagged_symbol_pointer, void *thread)
96 struct symbol *sym= (struct symbol *)
97 (pointer_sized_uint_t)(tagged_symbol_pointer-OTHER_POINTER_LOWTAG);
98 #ifdef LISP_FEATURE_SB_THREAD
99 return ((union per_thread_data *)thread)
100 ->dynamic_values[(sym->tls_index) >> WORD_SHIFT];
107 SetSymbolValue(u64 tagged_symbol_pointer,lispobj val, void *thread)
109 struct symbol *sym= (struct symbol *)
110 (pointer_sized_uint_t)(tagged_symbol_pointer-OTHER_POINTER_LOWTAG);
111 #ifdef LISP_FEATURE_SB_THREAD
112 if(thread && sym->tls_index) {
113 lispobj *pr= &(((union per_thread_data *)thread)
114 ->dynamic_values[(sym->tls_index) >> WORD_SHIFT]);
115 if(*pr!=NO_TLS_VALUE_MARKER_WIDETAG) {
125 SetTlSymbolValue(u64 tagged_symbol_pointer,lispobj val, void *thread)
127 #ifdef LISP_FEATURE_SB_THREAD
128 struct symbol *sym= (struct symbol *)
129 (pointer_sized_uint_t)(tagged_symbol_pointer-OTHER_POINTER_LOWTAG);
130 ((union per_thread_data *)thread)
131 ->dynamic_values[(sym->tls_index) >> WORD_SHIFT]
134 SetSymbolValue(tagged_symbol_pointer,val,thread) ;
138 /* This only works for static symbols. */
139 static inline lispobj
140 StaticSymbolFunction(lispobj sym)
142 return ((struct fdefn *)native_pointer(SymbolValue(sym, 0)))->fun;
145 /* These are for use during GC, on the current thread, or on prenatal
147 #if defined(LISP_FEATURE_SB_THREAD)
148 #define get_binding_stack_pointer(thread) \
149 ((thread)->binding_stack_pointer)
150 #define set_binding_stack_pointer(thread,value) \
151 ((thread)->binding_stack_pointer = (lispobj *)(value))
152 #define access_control_stack_pointer(thread) \
153 ((thread)->control_stack_pointer)
154 # if !defined(LISP_FEATURE_X86) && !defined(LISP_FEATURE_X86_64)
155 #define access_control_frame_pointer(thread) \
156 ((thread)->control_frame_pointer)
158 #elif defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64)
159 #define get_binding_stack_pointer(thread) \
160 SymbolValue(BINDING_STACK_POINTER, thread)
161 #define set_binding_stack_pointer(thread,value) \
162 SetSymbolValue(BINDING_STACK_POINTER, (lispobj)(value), thread)
163 #define access_control_stack_pointer(thread) \
164 (current_control_stack_pointer)
166 #define get_binding_stack_pointer(thread) \
167 (current_binding_stack_pointer)
168 #define set_binding_stack_pointer(thread,value) \
169 (current_binding_stack_pointer = (lispobj *)(value))
170 #define access_control_stack_pointer(thread) \
171 (current_control_stack_pointer)
172 #define access_control_frame_pointer(thread) \
173 (current_control_frame_pointer)
176 #if defined(LISP_FEATURE_SB_THREAD) && defined(LISP_FEATURE_GCC_TLS)
177 extern __thread struct thread *current_thread;
180 /* This is clearly per-arch and possibly even per-OS code, but we can't
181 * put it somewhere sensible like x86-linux-os.c because it needs too
182 * much stuff like struct thread and all_threads to be defined, which
183 * usually aren't by that time. So, it's here instead. Sorry */
185 static inline struct thread *arch_os_get_current_thread(void)
187 #if defined(LISP_FEATURE_SB_THREAD)
188 #if defined(LISP_FEATURE_X86)
189 register struct thread *me=0;
191 #if defined(LISP_FEATURE_DARWIN) && defined(LISP_FEATURE_RESTORE_FS_SEGMENT_REGISTER_FROM_TLS)
193 struct thread *th = pthread_getspecific(specials);
194 sel.index = th->tls_cookie;
197 __asm__ __volatile__ ("movw %w0, %%fs" : : "r"(sel));
198 #elif defined(LISP_FEATURE_FREEBSD)
199 #ifdef LISP_FEATURE_GCC_TLS
200 struct thread *th = current_thread;
202 struct thread *th = pthread_getspecific(specials);
204 #ifdef LISP_FEATURE_RESTORE_TLS_SEGMENT_REGISTER_FROM_TLS
205 unsigned int sel = LSEL(th->tls_cookie, SEL_UPL);
206 unsigned int fs = rfs();
208 /* Load FS only if it's necessary. Modifying a selector
209 * causes privilege checking and it takes long time. */
215 __asm__ __volatile__ ("movl %%fs:%c1,%0" : "=r" (me)
216 : "i" (offsetof (struct thread,this)));
220 #ifdef LISP_FEATURE_GCC_TLS
221 return current_thread;
223 return pthread_getspecific(specials);
231 #if defined(LISP_FEATURE_MACH_EXCEPTION_HANDLER)
232 #define THREAD_STRUCT_TO_EXCEPTION_PORT(th) ((mach_port_t) th)
233 #define EXCEPTION_PORT_TO_THREAD_STRUCT(th) ((struct thread *) th)
236 extern void create_initial_thread(lispobj);
238 #endif /* _INCLUDE_THREAD_H_ */