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