don't stack-allocate specialized vectors on non-conservtive control stacks
[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 #else
14 struct alloc_region { };
15 #endif
16 #include "genesis/symbol.h"
17 #include "genesis/static-symbols.h"
18
19 #include "genesis/thread.h"
20 #include "genesis/fdefn.h"
21 #include "interrupt.h"
22
23 #define STATE_RUNNING MAKE_FIXNUM(1)
24 #define STATE_STOPPED MAKE_FIXNUM(2)
25 #define STATE_DEAD MAKE_FIXNUM(3)
26
27 #ifdef LISP_FEATURE_SB_THREAD
28 lispobj thread_state(struct thread *thread);
29 void set_thread_state(struct thread *thread, lispobj state);
30 void wait_for_thread_state_change(struct thread *thread, lispobj state);
31 extern pthread_key_t lisp_thread;
32 #endif
33
34 extern int kill_safely(os_thread_t os_thread, int signal);
35
36 #define THREAD_SLOT_OFFSET_WORDS(c) \
37  (offsetof(struct thread,c)/(sizeof (struct thread *)))
38
39 union per_thread_data {
40     struct thread thread;
41     lispobj dynamic_values[1];  /* actually more like 4000 or so */
42 };
43
44 extern struct thread *all_threads;
45 extern int dynamic_values_bytes;
46
47 #if defined(LISP_FEATURE_DARWIN)
48 #define CONTROL_STACK_ALIGNMENT_BYTES 8192 /* darwin wants page-aligned stacks */
49 #define THREAD_ALIGNMENT_BYTES CONTROL_STACK_ALIGNMENT_BYTES
50 #else
51 #define THREAD_ALIGNMENT_BYTES BACKEND_PAGE_BYTES
52 #define CONTROL_STACK_ALIGNMENT_BYTES 16
53 #endif
54
55
56 #ifdef LISP_FEATURE_SB_THREAD
57 #define for_each_thread(th) for(th=all_threads;th;th=th->next)
58 #else
59 /* there's some possibility a SSC could notice this never actually
60  * loops  */
61 #define for_each_thread(th) for(th=all_threads;th;th=0)
62 #endif
63
64 static inline lispobj *
65 SymbolValueAddress(u64 tagged_symbol_pointer, void *thread)
66 {
67     struct symbol *sym= (struct symbol *)
68         (pointer_sized_uint_t)(tagged_symbol_pointer-OTHER_POINTER_LOWTAG);
69 #ifdef LISP_FEATURE_SB_THREAD
70     if(thread && sym->tls_index) {
71         lispobj *r = &(((union per_thread_data *)thread)
72                        ->dynamic_values[(sym->tls_index) >> WORD_SHIFT]);
73         if((*r)!=NO_TLS_VALUE_MARKER_WIDETAG) return r;
74     }
75 #endif
76     return &sym->value;
77 }
78
79 static inline lispobj
80 SymbolValue(u64 tagged_symbol_pointer, void *thread)
81 {
82     struct symbol *sym= (struct symbol *)
83         (pointer_sized_uint_t)(tagged_symbol_pointer-OTHER_POINTER_LOWTAG);
84 #ifdef LISP_FEATURE_SB_THREAD
85     if(thread && sym->tls_index) {
86         lispobj r=
87             ((union per_thread_data *)thread)
88             ->dynamic_values[(sym->tls_index) >> WORD_SHIFT];
89         if(r!=NO_TLS_VALUE_MARKER_WIDETAG) return r;
90     }
91 #endif
92     return sym->value;
93 }
94
95 static inline lispobj
96 SymbolTlValue(u64 tagged_symbol_pointer, void *thread)
97 {
98     struct symbol *sym= (struct symbol *)
99         (pointer_sized_uint_t)(tagged_symbol_pointer-OTHER_POINTER_LOWTAG);
100 #ifdef LISP_FEATURE_SB_THREAD
101     return ((union per_thread_data *)thread)
102         ->dynamic_values[(sym->tls_index) >> WORD_SHIFT];
103 #else
104     return sym->value;
105 #endif
106 }
107
108 static inline void
109 SetSymbolValue(u64 tagged_symbol_pointer,lispobj val, void *thread)
110 {
111     struct symbol *sym= (struct symbol *)
112         (pointer_sized_uint_t)(tagged_symbol_pointer-OTHER_POINTER_LOWTAG);
113 #ifdef LISP_FEATURE_SB_THREAD
114     if(thread && sym->tls_index) {
115         lispobj *pr= &(((union per_thread_data *)thread)
116                        ->dynamic_values[(sym->tls_index) >> WORD_SHIFT]);
117         if(*pr!=NO_TLS_VALUE_MARKER_WIDETAG) {
118             *pr=val;
119             return;
120         }
121     }
122 #endif
123     sym->value = val;
124 }
125
126 static inline void
127 SetTlSymbolValue(u64 tagged_symbol_pointer,lispobj val, void *thread)
128 {
129 #ifdef LISP_FEATURE_SB_THREAD
130     struct symbol *sym= (struct symbol *)
131         (pointer_sized_uint_t)(tagged_symbol_pointer-OTHER_POINTER_LOWTAG);
132     ((union per_thread_data *)thread)
133         ->dynamic_values[(sym->tls_index) >> WORD_SHIFT]
134         =val;
135 #else
136     SetSymbolValue(tagged_symbol_pointer,val,thread) ;
137 #endif
138 }
139
140 /* This only works for static symbols. */
141 static inline lispobj
142 StaticSymbolFunction(lispobj sym)
143 {
144     return ((struct fdefn *)native_pointer(SymbolValue(sym, 0)))->fun;
145 }
146
147 /* These are for use during GC, on the current thread, or on prenatal
148  * threads only. */
149 #if defined(LISP_FEATURE_SB_THREAD)
150 #define get_binding_stack_pointer(thread)       \
151     ((thread)->binding_stack_pointer)
152 #define set_binding_stack_pointer(thread,value) \
153     ((thread)->binding_stack_pointer = (lispobj *)(value))
154 #define access_control_stack_pointer(thread) \
155     ((thread)->control_stack_pointer)
156 #  if !defined(LISP_FEATURE_X86) && !defined(LISP_FEATURE_X86_64)
157 #define access_control_frame_pointer(thread) \
158     ((thread)->control_frame_pointer)
159 #  endif
160 #elif defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64)
161 #define get_binding_stack_pointer(thread)       \
162     SymbolValue(BINDING_STACK_POINTER, thread)
163 #define set_binding_stack_pointer(thread,value) \
164     SetSymbolValue(BINDING_STACK_POINTER, (lispobj)(value), thread)
165 #define access_control_stack_pointer(thread)    \
166     (current_control_stack_pointer)
167 #else
168 #define get_binding_stack_pointer(thread)       \
169     (current_binding_stack_pointer)
170 #define set_binding_stack_pointer(thread,value) \
171     (current_binding_stack_pointer = (lispobj *)(value))
172 #define access_control_stack_pointer(thread) \
173     (current_control_stack_pointer)
174 #define access_control_frame_pointer(thread) \
175     (current_control_frame_pointer)
176 #endif
177
178 #if defined(LISP_FEATURE_SB_THREAD) && defined(LISP_FEATURE_GCC_TLS)
179 extern __thread struct thread *current_thread;
180 #endif
181
182 /* This is clearly per-arch and possibly even per-OS code, but we can't
183  * put it somewhere sensible like x86-linux-os.c because it needs too
184  * much stuff like struct thread and all_threads to be defined, which
185  * usually aren't by that time.  So, it's here instead.  Sorry */
186
187 static inline struct thread *arch_os_get_current_thread(void)
188 {
189 #if defined(LISP_FEATURE_SB_THREAD)
190 #if defined(LISP_FEATURE_X86)
191     register struct thread *me=0;
192     if(all_threads) {
193 #if defined(LISP_FEATURE_DARWIN) && defined(LISP_FEATURE_RESTORE_FS_SEGMENT_REGISTER_FROM_TLS)
194         sel_t sel;
195         struct thread *th = pthread_getspecific(specials);
196         sel.index = th->tls_cookie;
197         sel.rpl = USER_PRIV;
198         sel.ti = SEL_LDT;
199         __asm__ __volatile__ ("movw %w0, %%fs" : : "r"(sel));
200 #elif defined(LISP_FEATURE_FREEBSD)
201 #ifdef LISP_FEATURE_GCC_TLS
202         struct thread *th = current_thread;
203 #else
204         struct thread *th = pthread_getspecific(specials);
205 #endif
206 #ifdef LISP_FEATURE_RESTORE_TLS_SEGMENT_REGISTER_FROM_TLS
207         unsigned int sel = LSEL(th->tls_cookie, SEL_UPL);
208         unsigned int fs = rfs();
209
210         /* Load FS only if it's necessary.  Modifying a selector
211          * causes privilege checking and it takes long time. */
212         if (fs != sel)
213             load_fs(sel);
214 #endif
215         return th;
216 #endif
217         __asm__ __volatile__ ("movl %%fs:%c1,%0" : "=r" (me)
218                  : "i" (offsetof (struct thread,this)));
219     }
220     return me;
221 #else
222 #ifdef LISP_FEATURE_GCC_TLS
223     return current_thread;
224 #else
225     return pthread_getspecific(specials);
226 #endif
227 #endif /* x86 */
228 #else
229      return all_threads;
230 #endif
231 }
232
233 #if defined(LISP_FEATURE_MACH_EXCEPTION_HANDLER)
234 #define THREAD_STRUCT_TO_EXCEPTION_PORT(th) ((mach_port_t) th)
235 #define EXCEPTION_PORT_TO_THREAD_STRUCT(th) ((struct thread *) th)
236 #endif
237
238 extern void create_initial_thread(lispobj);
239
240 #endif /* _INCLUDE_THREAD_H_ */