2 * Copyright (C) 2001-2007, Parrot Foundation.
6 * This is the api header for the thread primitives
7 * Data Structure and Algorithms:
13 #ifndef PARROT_THREAD_H_GUARD
14 #define PARROT_THREAD_H_GUARD
16 # include "parrot/parrot.h"
17 # include "parrot/atomic.h"
19 #ifndef PARROT_HAS_THREADS
23 # define COND_WAIT(c, m)
24 # define COND_TIMED_WAIT(c, m, t)
25 # define COND_SIGNAL(c)
26 # define COND_BROADCAST(c)
28 # define MUTEX_INIT(m)
29 # define MUTEX_DESTROY(m)
32 # define COND_DESTROY(c)
34 # define THREAD_CREATE_DETACHED(t, func, arg)
35 # define THREAD_CREATE_JOINABLE(t, func, arg)
40 # define CLEANUP_PUSH(f, a)
41 # define CLEANUP_POP(a)
43 # define Parrot_mutex int
44 # define Parrot_cond int
45 # define Parrot_thread int
47 typedef void (*Cleanup_Handler
)(void *);
49 # ifndef __timespec_defined
50 # define __timespec_defined
55 # endif /* __timespec_defined */
57 #endif /* PARROT_HAS_THREADS */
64 THREAD_STATE_JOINABLE
, /* default */
65 THREAD_STATE_DETACHED
= 0x01, /* i.e. non-joinable */
66 THREAD_STATE_JOINED
= 0x02, /* JOIN was issued */
67 THREAD_STATE_FINISHED
= 0x04, /* the thread function has ended */
68 THREAD_STATE_NOT_STARTED
= 0x08, /* the thread wasn't started */
69 THREAD_STATE_SUSPENDED_GC
= 0x10, /* suspended for GC on request */
70 THREAD_STATE_GC_WAKEUP
= 0x20, /* the thread is waiting on its condition
71 variable, and will do a GC run if
72 it is woken up and marked as suspended
74 THREAD_STATE_SUSPEND_GC_REQUESTED
= 0x40 /* the thread's event queue
75 contains a suspend-for-GC event */
80 * per interpreter thread data structure
82 typedef struct _Thread_data
{
83 Parrot_thread thread
; /* pthread_t or such */
85 int wants_shared_gc
; /* therad is trying to
87 UINTVAL tid
; /* 0.. n-1 idx in interp array */
89 Parrot_Interp joiner
; /* thread that is trying to join this */
91 /* for wr access to interpreter e.g. for GC
92 * if only used for GC the lock could be in the arena
93 * instead here, or in the interpreter, with negative size impact
94 * for the non-threaded case
96 Parrot_mutex interp_lock
;
98 /* for waking up the interpreter from various sorts
101 Parrot_cond interp_cond
;
103 /* COW'd constant tables */
107 # define LOCK_INTERPRETER(interp) \
108 if ((interp)->thread_data) \
109 LOCK((interp)->thread_data->interp_lock)
110 # define UNLOCK_INTERPRETER(interp) \
111 if ((interp)->thread_data) \
112 UNLOCK((interp)->thread_data->interp_lock)
114 # define INTERPRETER_LOCK_INIT(interp) \
116 MUTEX_INIT((interp)->thread_data->interp_lock); \
117 COND_INIT((interp)->thread_data->interp_cond); \
119 # define INTERPRETER_LOCK_DESTROY(interp) \
121 MUTEX_DESTROY((interp)->thread_data->interp_lock); \
122 COND_DESTROY((interp)->thread_data->interp_cond); \
127 * this global mutex protects the list of interpreters
129 VAR_SCOPE Parrot_mutex interpreter_array_mutex
;
130 VAR_SCOPE Interp
** interpreter_array
;
131 VAR_SCOPE
size_t n_interpreters
;
134 THREAD_GC_STAGE_NONE
,
135 THREAD_GC_STAGE_MARK
,
136 THREAD_GC_STAGE_SWEEP
= THREAD_GC_STAGE_NONE
137 } thread_gc_stage_enum
;
139 typedef struct _Shared_gc_info
{
140 thread_gc_stage_enum gc_stage
;
144 Parrot_atomic_integer gc_block_level
;
147 /* TODO use thread pools instead */
148 VAR_SCOPE Shared_gc_info
*shared_gc_info
;
150 typedef struct _Sync
{
151 Parrot_Interp owner
; /* that interpreter, that owns
152 the arena, where the PMC is in */
153 Parrot_mutex pmc_lock
; /* for wr access to PMCs content */
156 /* HEADERIZER BEGIN: src/thread.c */
157 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
160 void Parrot_shared_gc_block(PARROT_INTERP
)
161 __attribute__nonnull__(1);
164 void Parrot_shared_gc_unblock(PARROT_INTERP
)
165 __attribute__nonnull__(1);
167 void pt_add_to_interpreters(PARROT_INTERP
,
168 ARGIN_NULLOK(Parrot_Interp new_interp
))
169 __attribute__nonnull__(1);
171 void pt_clone_code(Parrot_Interp d
, Parrot_Interp s
);
172 void pt_clone_globals(Parrot_Interp d
, Parrot_Interp s
);
173 void pt_free_pool(PARROT_INTERP
)
174 __attribute__nonnull__(1);
176 void pt_gc_mark_root_finished(PARROT_INTERP
)
177 __attribute__nonnull__(1);
179 void pt_gc_start_mark(PARROT_INTERP
)
180 __attribute__nonnull__(1);
182 void pt_gc_stop_mark(PARROT_INTERP
)
183 __attribute__nonnull__(1);
185 void pt_join_threads(PARROT_INTERP
)
186 __attribute__nonnull__(1);
188 PARROT_CAN_RETURN_NULL
189 PMC
* pt_shared_fixup(PARROT_INTERP
, ARGMOD(PMC
*pmc
))
190 __attribute__nonnull__(1)
191 __attribute__nonnull__(2)
194 void pt_suspend_self_for_gc(PARROT_INTERP
)
195 __attribute__nonnull__(1);
197 void pt_thread_detach(UINTVAL tid
);
198 PARROT_CAN_RETURN_NULL
199 PMC
* pt_thread_join(NOTNULL(Parrot_Interp parent
), UINTVAL tid
)
200 __attribute__nonnull__(1);
202 void pt_thread_kill(UINTVAL tid
);
203 void pt_thread_prepare_for_run(Parrot_Interp d
, NULLOK(Parrot_Interp s
));
204 int pt_thread_run(PARROT_INTERP
,
205 ARGOUT(PMC
*dest_interp
),
207 ARGIN_NULLOK(PMC
*arg
))
208 __attribute__nonnull__(1)
209 __attribute__nonnull__(2)
210 __attribute__nonnull__(3)
211 FUNC_MODIFIES(*dest_interp
);
213 int pt_thread_run_1(PARROT_INTERP
,
214 ARGOUT(PMC
* dest_interp
),
217 __attribute__nonnull__(1)
218 __attribute__nonnull__(2)
219 __attribute__nonnull__(3)
220 __attribute__nonnull__(4)
221 FUNC_MODIFIES(* dest_interp
);
223 int pt_thread_run_2(PARROT_INTERP
,
224 ARGOUT(PMC
* dest_interp
),
227 __attribute__nonnull__(1)
228 __attribute__nonnull__(2)
229 __attribute__nonnull__(3)
230 __attribute__nonnull__(4)
231 FUNC_MODIFIES(* dest_interp
);
233 int pt_thread_run_3(PARROT_INTERP
,
234 ARGOUT(PMC
* dest_interp
),
237 __attribute__nonnull__(1)
238 __attribute__nonnull__(2)
239 __attribute__nonnull__(3)
240 __attribute__nonnull__(4)
241 FUNC_MODIFIES(* dest_interp
);
243 void pt_thread_wait_with(PARROT_INTERP
, ARGMOD(Parrot_mutex
*mutex
))
244 __attribute__nonnull__(1)
245 __attribute__nonnull__(2)
246 FUNC_MODIFIES(*mutex
);
248 void pt_thread_yield(void);
249 PARROT_CAN_RETURN_NULL
250 PMC
* pt_transfer_sub(
251 ARGOUT(Parrot_Interp d
),
252 ARGIN(Parrot_Interp s
),
254 __attribute__nonnull__(1)
255 __attribute__nonnull__(2)
256 __attribute__nonnull__(3)
259 #define ASSERT_ARGS_Parrot_shared_gc_block __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
260 PARROT_ASSERT_ARG(interp))
261 #define ASSERT_ARGS_Parrot_shared_gc_unblock __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
262 PARROT_ASSERT_ARG(interp))
263 #define ASSERT_ARGS_pt_add_to_interpreters __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
264 PARROT_ASSERT_ARG(interp))
265 #define ASSERT_ARGS_pt_clone_code __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
266 #define ASSERT_ARGS_pt_clone_globals __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
267 #define ASSERT_ARGS_pt_free_pool __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
268 PARROT_ASSERT_ARG(interp))
269 #define ASSERT_ARGS_pt_gc_mark_root_finished __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
270 PARROT_ASSERT_ARG(interp))
271 #define ASSERT_ARGS_pt_gc_start_mark __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
272 PARROT_ASSERT_ARG(interp))
273 #define ASSERT_ARGS_pt_gc_stop_mark __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
274 PARROT_ASSERT_ARG(interp))
275 #define ASSERT_ARGS_pt_join_threads __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
276 PARROT_ASSERT_ARG(interp))
277 #define ASSERT_ARGS_pt_shared_fixup __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
278 PARROT_ASSERT_ARG(interp) \
279 , PARROT_ASSERT_ARG(pmc))
280 #define ASSERT_ARGS_pt_suspend_self_for_gc __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
281 PARROT_ASSERT_ARG(interp))
282 #define ASSERT_ARGS_pt_thread_detach __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
283 #define ASSERT_ARGS_pt_thread_join __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
284 PARROT_ASSERT_ARG(parent))
285 #define ASSERT_ARGS_pt_thread_kill __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
286 #define ASSERT_ARGS_pt_thread_prepare_for_run __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
287 #define ASSERT_ARGS_pt_thread_run __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
288 PARROT_ASSERT_ARG(interp) \
289 , PARROT_ASSERT_ARG(dest_interp) \
290 , PARROT_ASSERT_ARG(sub))
291 #define ASSERT_ARGS_pt_thread_run_1 __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
292 PARROT_ASSERT_ARG(interp) \
293 , PARROT_ASSERT_ARG(dest_interp) \
294 , PARROT_ASSERT_ARG(sub) \
295 , PARROT_ASSERT_ARG(arg))
296 #define ASSERT_ARGS_pt_thread_run_2 __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
297 PARROT_ASSERT_ARG(interp) \
298 , PARROT_ASSERT_ARG(dest_interp) \
299 , PARROT_ASSERT_ARG(sub) \
300 , PARROT_ASSERT_ARG(arg))
301 #define ASSERT_ARGS_pt_thread_run_3 __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
302 PARROT_ASSERT_ARG(interp) \
303 , PARROT_ASSERT_ARG(dest_interp) \
304 , PARROT_ASSERT_ARG(sub) \
305 , PARROT_ASSERT_ARG(arg))
306 #define ASSERT_ARGS_pt_thread_wait_with __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
307 PARROT_ASSERT_ARG(interp) \
308 , PARROT_ASSERT_ARG(mutex))
309 #define ASSERT_ARGS_pt_thread_yield __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
310 #define ASSERT_ARGS_pt_transfer_sub __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
311 PARROT_ASSERT_ARG(d) \
312 , PARROT_ASSERT_ARG(s) \
313 , PARROT_ASSERT_ARG(sub))
314 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
315 /* HEADERIZER END: src/thread.c */
317 #endif /* PARROT_THREAD_H_GUARD */
321 * c-file-style: "parrot"
323 * vim: expandtab shiftwidth=4: