Miscellaneous cleanups for threaded darwin platforms
[sbcl.git] / src / runtime / thread.h
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 #include "genesis/symbol.h"
15 #include "genesis/static-symbols.h"
16
17 #include "genesis/thread.h"
18 #include "genesis/fdefn.h"
19 #include "interrupt.h"
20
21 #define STATE_RUNNING MAKE_FIXNUM(1)
22 #define STATE_STOPPED MAKE_FIXNUM(2)
23 #define STATE_DEAD MAKE_FIXNUM(3)
24
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;
30 #endif
31
32 extern int kill_safely(os_thread_t os_thread, int signal);
33
34 #define THREAD_SLOT_OFFSET_WORDS(c) \
35  (offsetof(struct thread,c)/(sizeof (struct thread *)))
36
37 union per_thread_data {
38     struct thread thread;
39     lispobj dynamic_values[1];  /* actually more like 4000 or so */
40 };
41
42 extern struct thread *all_threads;
43 extern int dynamic_values_bytes;
44
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
48 #else
49 #define THREAD_ALIGNMENT_BYTES BACKEND_PAGE_BYTES
50 #define CONTROL_STACK_ALIGNMENT_BYTES 16
51 #endif
52
53
54 #ifdef LISP_FEATURE_SB_THREAD
55 #define for_each_thread(th) for(th=all_threads;th;th=th->next)
56 #else
57 /* there's some possibility a SSC could notice this never actually
58  * loops  */
59 #define for_each_thread(th) for(th=all_threads;th;th=0)
60 #endif
61
62 static inline lispobj *
63 SymbolValueAddress(u64 tagged_symbol_pointer, void *thread)
64 {
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;
72     }
73 #endif
74     return &sym->value;
75 }
76
77 static inline lispobj
78 SymbolValue(u64 tagged_symbol_pointer, void *thread)
79 {
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) {
84         lispobj r=
85             ((union per_thread_data *)thread)
86             ->dynamic_values[(sym->tls_index) >> WORD_SHIFT];
87         if(r!=NO_TLS_VALUE_MARKER_WIDETAG) return r;
88     }
89 #endif
90     return sym->value;
91 }
92
93 static inline lispobj
94 SymbolTlValue(u64 tagged_symbol_pointer, void *thread)
95 {
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];
101 #else
102     return sym->value;
103 #endif
104 }
105
106 static inline void
107 SetSymbolValue(u64 tagged_symbol_pointer,lispobj val, void *thread)
108 {
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) {
116             *pr=val;
117             return;
118         }
119     }
120 #endif
121     sym->value = val;
122 }
123
124 static inline void
125 SetTlSymbolValue(u64 tagged_symbol_pointer,lispobj val, void *thread)
126 {
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]
132         =val;
133 #else
134     SetSymbolValue(tagged_symbol_pointer,val,thread) ;
135 #endif
136 }
137
138 /* This only works for static symbols. */
139 static inline lispobj
140 StaticSymbolFunction(lispobj sym)
141 {
142     return ((struct fdefn *)native_pointer(SymbolValue(sym, 0)))->fun;
143 }
144
145 /* These are for use during GC, on the current thread, or on prenatal
146  * threads only. */
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)
157 #  endif
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)
165 #else
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)
174 #endif
175
176 #if defined(LISP_FEATURE_SB_THREAD) && defined(LISP_FEATURE_GCC_TLS)
177 extern __thread struct thread *current_thread;
178 #endif
179
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 */
184
185 static inline struct thread *arch_os_get_current_thread(void)
186 {
187 #if defined(LISP_FEATURE_SB_THREAD)
188 #if defined(LISP_FEATURE_X86)
189     register struct thread *me=0;
190     if(all_threads) {
191 #if defined(LISP_FEATURE_DARWIN) && defined(LISP_FEATURE_RESTORE_FS_SEGMENT_REGISTER_FROM_TLS)
192         sel_t sel;
193         struct thread *th = pthread_getspecific(specials);
194         sel.index = th->tls_cookie;
195         sel.rpl = USER_PRIV;
196         sel.ti = SEL_LDT;
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;
201 #else
202         struct thread *th = pthread_getspecific(specials);
203 #endif
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();
207
208         /* Load FS only if it's necessary.  Modifying a selector
209          * causes privilege checking and it takes long time. */
210         if (fs != sel)
211             load_fs(sel);
212 #endif
213         return th;
214 #endif
215         __asm__ __volatile__ ("movl %%fs:%c1,%0" : "=r" (me)
216                  : "i" (offsetof (struct thread,this)));
217     }
218     return me;
219 #else
220 #ifdef LISP_FEATURE_GCC_TLS
221     return current_thread;
222 #else
223     return pthread_getspecific(specials);
224 #endif
225 #endif /* x86 */
226 #else
227      return all_threads;
228 #endif
229 }
230
231 #if defined(LISP_FEATURE_MACH_EXCEPTION_HANDLER)
232 extern kern_return_t mach_lisp_thread_init(struct thread *thread);
233 extern kern_return_t mach_lisp_thread_destroy(struct thread *thread);
234 #endif
235
236 extern void create_initial_thread(lispobj);
237
238 #endif /* _INCLUDE_THREAD_H_ */