1 #if !defined(_INCLUDE_THREAD_H_)
2 #define _INCLUDE_THREAD_H_
11 #ifdef LISP_FEATURE_GENCGC
12 #include "gencgc-alloc-region.h"
14 struct alloc_region
{ };
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"
22 #define STATE_RUNNING (make_fixnum(1))
23 #define STATE_SUSPENDED (make_fixnum(2))
24 #define STATE_DEAD (make_fixnum(3))
26 #ifdef LISP_FEATURE_SB_THREAD
28 /* Only access thread state with blockables blocked. */
30 thread_state(struct thread
*thread
)
33 pthread_mutex_lock(thread
->state_lock
);
34 state
= thread
->state
;
35 pthread_mutex_unlock(thread
->state_lock
);
40 set_thread_state(struct thread
*thread
, lispobj state
)
42 pthread_mutex_lock(thread
->state_lock
);
43 thread
->state
= state
;
44 pthread_cond_broadcast(thread
->state_cond
);
45 pthread_mutex_unlock(thread
->state_lock
);
49 wait_for_thread_state_change(struct thread
*thread
, lispobj state
)
51 pthread_mutex_lock(thread
->state_lock
);
52 while (thread
->state
== state
)
53 pthread_cond_wait(thread
->state_cond
, thread
->state_lock
);
54 pthread_mutex_unlock(thread
->state_lock
);
57 extern pthread_key_t lisp_thread
;
60 extern int kill_safely(os_thread_t os_thread
, int signal
);
62 #define THREAD_SLOT_OFFSET_WORDS(c) \
63 (offsetof(struct thread,c)/(sizeof (struct thread *)))
65 union per_thread_data
{
67 lispobj dynamic_values
[1]; /* actually more like 4000 or so */
70 extern struct thread
*all_threads
;
71 extern int dynamic_values_bytes
;
73 #if defined(LISP_FEATURE_DARWIN)
74 #define CONTROL_STACK_ALIGNMENT_BYTES 8192 /* darwin wants page-aligned stacks */
75 #define THREAD_ALIGNMENT_BYTES CONTROL_STACK_ALIGNMENT_BYTES
77 #define THREAD_ALIGNMENT_BYTES BACKEND_PAGE_BYTES
78 #define CONTROL_STACK_ALIGNMENT_BYTES 16
82 #ifdef LISP_FEATURE_SB_THREAD
83 #define for_each_thread(th) for(th=all_threads;th;th=th->next)
85 /* there's some possibility a SSC could notice this never actually
87 #define for_each_thread(th) for(th=all_threads;th;th=0)
90 static inline lispobj
*
91 SymbolValueAddress(u64 tagged_symbol_pointer
, void *thread
)
93 struct symbol
*sym
= (struct symbol
*)
94 (pointer_sized_uint_t
)(tagged_symbol_pointer
-OTHER_POINTER_LOWTAG
);
95 #ifdef LISP_FEATURE_SB_THREAD
96 if(thread
&& sym
->tls_index
) {
97 lispobj
*r
= &(((union per_thread_data
*)thread
)
98 ->dynamic_values
[fixnum_value(sym
->tls_index
)]);
99 if((*r
)!=NO_TLS_VALUE_MARKER_WIDETAG
) return r
;
105 static inline lispobj
106 SymbolValue(u64 tagged_symbol_pointer
, void *thread
)
108 struct symbol
*sym
= (struct symbol
*)
109 (pointer_sized_uint_t
)(tagged_symbol_pointer
-OTHER_POINTER_LOWTAG
);
110 #ifdef LISP_FEATURE_SB_THREAD
111 if(thread
&& sym
->tls_index
) {
113 ((union per_thread_data
*)thread
)
114 ->dynamic_values
[fixnum_value(sym
->tls_index
)];
115 if(r
!=NO_TLS_VALUE_MARKER_WIDETAG
) return r
;
121 static inline lispobj
122 SymbolTlValue(u64 tagged_symbol_pointer
, void *thread
)
124 struct symbol
*sym
= (struct symbol
*)
125 (pointer_sized_uint_t
)(tagged_symbol_pointer
-OTHER_POINTER_LOWTAG
);
126 #ifdef LISP_FEATURE_SB_THREAD
127 return ((union per_thread_data
*)thread
)
128 ->dynamic_values
[fixnum_value(sym
->tls_index
)];
135 SetSymbolValue(u64 tagged_symbol_pointer
,lispobj val
, void *thread
)
137 struct symbol
*sym
= (struct symbol
*)
138 (pointer_sized_uint_t
)(tagged_symbol_pointer
-OTHER_POINTER_LOWTAG
);
139 #ifdef LISP_FEATURE_SB_THREAD
140 if(thread
&& sym
->tls_index
) {
141 lispobj
*pr
= &(((union per_thread_data
*)thread
)
142 ->dynamic_values
[fixnum_value(sym
->tls_index
)]);
143 if(*pr
!=NO_TLS_VALUE_MARKER_WIDETAG
) {
153 SetTlSymbolValue(u64 tagged_symbol_pointer
,lispobj val
, void *thread
)
155 #ifdef LISP_FEATURE_SB_THREAD
156 struct symbol
*sym
= (struct symbol
*)
157 (pointer_sized_uint_t
)(tagged_symbol_pointer
-OTHER_POINTER_LOWTAG
);
158 ((union per_thread_data
*)thread
)
159 ->dynamic_values
[fixnum_value(sym
->tls_index
)]
162 SetSymbolValue(tagged_symbol_pointer
,val
,thread
) ;
166 /* This only works for static symbols. */
167 static inline lispobj
168 StaticSymbolFunction(lispobj sym
)
170 return ((struct fdefn
*)native_pointer(SymbolValue(sym
, 0)))->fun
;
173 #if defined(LISP_FEATURE_SB_THREAD) && defined(LISP_FEATURE_GCC_TLS)
174 extern __thread
struct thread
*current_thread
;
177 /* This is clearly per-arch and possibly even per-OS code, but we can't
178 * put it somewhere sensible like x86-linux-os.c because it needs too
179 * much stuff like struct thread and all_threads to be defined, which
180 * usually aren't by that time. So, it's here instead. Sorry */
182 static inline struct thread
*arch_os_get_current_thread(void)
184 #if defined(LISP_FEATURE_SB_THREAD)
185 #if defined(LISP_FEATURE_X86)
186 register struct thread
*me
=0;
188 #if defined(LISP_FEATURE_DARWIN) && defined(LISP_FEATURE_RESTORE_FS_SEGMENT_REGISTER_FROM_TLS)
190 struct thread
*th
= pthread_getspecific(specials
);
191 sel
.index
= th
->tls_cookie
;
194 __asm__
__volatile__ ("movw %w0, %%fs" : : "r"(sel
));
195 #elif defined(LISP_FEATURE_FREEBSD)
196 #ifdef LISP_FEATURE_GCC_TLS
197 struct thread
*th
= current_thread
;
199 struct thread
*th
= pthread_getspecific(specials
);
201 #ifdef LISP_FEATURE_RESTORE_TLS_SEGMENT_REGISTER_FROM_TLS
202 unsigned int sel
= LSEL(th
->tls_cookie
, SEL_UPL
);
203 unsigned int fs
= rfs();
205 /* Load FS only if it's necessary. Modifying a selector
206 * causes privilege checking and it takes long time. */
212 __asm__
__volatile__ ("movl %%fs:%c1,%0" : "=r" (me
)
213 : "i" (offsetof (struct thread
,this)));
217 #ifdef LISP_FEATURE_GCC_TLS
218 return current_thread
;
220 return pthread_getspecific(specials
);
228 #if defined(LISP_FEATURE_MACH_EXCEPTION_HANDLER)
229 #define THREAD_STRUCT_TO_EXCEPTION_PORT(th) ((mach_port_t) th)
230 #define EXCEPTION_PORT_TO_THREAD_STRUCT(th) ((struct thread *) th)
233 extern void create_initial_thread(lispobj
);
235 #endif /* _INCLUDE_THREAD_H_ */