Initial merge of win32 threads patch.
[p5sagit/p5-mst-13.2.git] / thread.h
CommitLineData
11343788 1#ifndef USE_THREADS
2#define MUTEX_LOCK(m)
3#define MUTEX_UNLOCK(m)
4#define MUTEX_INIT(m)
5#define MUTEX_DESTROY(m)
6#define COND_INIT(c)
7#define COND_SIGNAL(c)
8#define COND_BROADCAST(c)
9#define COND_WAIT(c, m)
10#define COND_DESTROY(c)
11
12#define THR
13/* Rats: if dTHR is just blank then the subsequent ";" throws an error */
14#define dTHR extern int errno
15#else
11343788 16
12ca11f6 17#ifdef FAKE_THREADS
18typedef struct thread *perl_thread;
19/* With fake threads, thr is global(ish) so we don't need dTHR */
20#define dTHR extern int errno
21
22/*
23 * Note that SCHEDULE() is only callable from pp code (which
24 * must be expecting to be restarted). We'll have to do
25 * something a bit different for XS code.
26 */
27#define SCHEDULE() return schedule(), op
28
29#define MUTEX_LOCK(m)
30#define MUTEX_UNLOCK(m)
31#define MUTEX_INIT(m)
32#define MUTEX_DESTROY(m)
33#define COND_INIT(c) perl_cond_init(c)
34#define COND_SIGNAL(c) perl_cond_signal(c)
35#define COND_BROADCAST(c) perl_cond_broadcast(c)
36#define COND_WAIT(c, m) STMT_START { \
37 perl_cond_wait(c); \
38 SCHEDULE(); \
39 } STMT_END
40#define COND_DESTROY(c)
12ca11f6 41#else
059e4e88 42
43#ifdef WIN32
44
45typedef HANDLE perl_thread;
46
47/* XXX Critical Sections used instead of mutexes: lightweight,
48 * but can't be communicated to child processes, and can't get
49 * HANDLE to it for use elsewhere
50 */
51/*
52#define MUTEX_INIT(m) InitializeCriticalSection(m)
53#define MUTEX_LOCK(m) EnterCriticalSection(m)
54#define MUTEX_UNLOCK(m) LeaveCriticalSection(m)
55#define MUTEX_DESTROY(m) DeleteCriticalSection(m)
56*/
57
58#define MUTEX_INIT(m) \
59 STMT_START { \
60 if ((*(m) = CreateMutex(NULL,FALSE,NULL)) == NULL) \
61 croak("panic: MUTEX_INIT"); \
62 } STMT_END
63#define MUTEX_LOCK(m) \
64 STMT_START { \
65 if (WaitForSingleObject(*(m),INFINITE) == WAIT_FAILED) \
66 croak("panic: MUTEX_LOCK"); \
67 } STMT_END
68#define MUTEX_UNLOCK(m) \
69 STMT_START { \
70 if (ReleaseMutex(*(m)) == 0) \
71 croak("panic: MUTEX_UNLOCK"); \
72 } STMT_END
73#define MUTEX_DESTROY(m) \
74 STMT_START { \
75 if (CloseHandle(*(m)) == 0) \
76 croak("panic: MUTEX_DESTROY"); \
77 } STMT_END
78
79#define COND_INIT(c) \
80 STMT_START { \
81 if ((*(c) = CreateEvent(NULL,TRUE,FALSE,NULL)) == NULL) \
82 croak("panic: COND_INIT"); \
83 } STMT_END
84#define COND_SIGNAL(c) \
85 STMT_START { \
86 if (PulseEvent(*(c)) == 0) \
87 croak("panic: COND_SIGNAL (%ld)",GetLastError()); \
88 } STMT_END
89#define COND_BROADCAST(c) \
90 STMT_START { \
91 if (PulseEvent(*(c)) == 0) \
92 croak("panic: COND_BROADCAST"); \
93 } STMT_END
94/* #define COND_WAIT(c, m) \
95 STMT_START { \
96 if (WaitForSingleObject(*(c),INFINITE) == WAIT_FAILED) \
97 croak("panic: COND_WAIT"); \
98 } STMT_END
99*/
100#define COND_WAIT(c, m) \
101 STMT_START { \
102 if (SignalObjectAndWait(*(m),*(c),INFINITE,FALSE) == WAIT_FAILED)\
103 croak("panic: COND_WAIT"); \
104 else \
105 MUTEX_LOCK(m); \
106 } STMT_END
107#define COND_DESTROY(c) \
108 STMT_START { \
109 if (CloseHandle(*(c)) == 0) \
110 croak("panic: COND_DESTROY"); \
111 } STMT_END
112
113#define DETACH(t) \
114 STMT_START { \
115 if (CloseHandle((t)->Tself) == 0) \
116 croak("panic: DETACH"); \
117 } STMT_END
118
119#define THR ((struct thread *) TlsGetValue(thr_key))
120#define pthread_getspecific(k) TlsGetValue(k)
121#define pthread_setspecific(k,v) (TlsSetValue(k,v) == 0)
122
123#else /* !WIN32 */
124
12ca11f6 125/* POSIXish threads */
126typedef pthread_t perl_thread;
11343788 127#ifdef OLD_PTHREADS_API
128#define pthread_mutexattr_init(a) pthread_mutexattr_create(a)
129#define pthread_mutexattr_settype(a,t) pthread_mutexattr_setkind_np(a,t)
130#define pthread_key_create(k,d) pthread_keycreate(k,(pthread_destructor_t)(d))
131#else
132#define pthread_mutexattr_default NULL
133#endif /* OLD_PTHREADS_API */
134
135#define MUTEX_INIT(m) \
136 if (pthread_mutex_init((m), pthread_mutexattr_default)) \
137 croak("panic: MUTEX_INIT"); \
138 else 1
139#define MUTEX_LOCK(m) \
140 if (pthread_mutex_lock((m))) croak("panic: MUTEX_LOCK"); else 1
141#define MUTEX_UNLOCK(m) \
142 if (pthread_mutex_unlock((m))) croak("panic: MUTEX_UNLOCK"); else 1
143#define MUTEX_DESTROY(m) \
144 if (pthread_mutex_destroy((m))) croak("panic: MUTEX_DESTROY"); else 1
145#define COND_INIT(c) \
146 if (pthread_cond_init((c), NULL)) croak("panic: COND_INIT"); else 1
147#define COND_SIGNAL(c) \
148 if (pthread_cond_signal((c))) croak("panic: COND_SIGNAL"); else 1
149#define COND_BROADCAST(c) \
150 if (pthread_cond_broadcast((c))) croak("panic: COND_BROADCAST"); else 1
151#define COND_WAIT(c, m) \
152 if (pthread_cond_wait((c), (m))) croak("panic: COND_WAIT"); else 1
153#define COND_DESTROY(c) \
154 if (pthread_cond_destroy((c))) croak("panic: COND_DESTROY"); else 1
33f46ff6 155
156#define DETACH(t) \
157 if (pthread_detach((t)->Tself)) croak("panic: DETACH"); else 1
158
11343788 159/* XXX Add "old" (?) POSIX draft interface too */
160#ifdef OLD_PTHREADS_API
161struct thread *getTHR _((void));
162#define THR getTHR()
163#else
164#define THR ((struct thread *) pthread_getspecific(thr_key))
165#endif /* OLD_PTHREADS_API */
059e4e88 166#endif /* WIN32 */
11343788 167#define dTHR struct thread *thr = THR
12ca11f6 168#endif /* FAKE_THREADS */
11343788 169
33f46ff6 170#ifndef INIT_THREADS
171# ifdef NEED_PTHREAD_INIT
172# define INIT_THREADS pthread_init()
173# else
174# define INIT_THREADS NOOP
175# endif
176#endif
11343788 177
33f46ff6 178struct thread {
11343788 179 /* The fields that used to be global */
33f46ff6 180 /* Important ones in the first cache line (if alignment is done right) */
11343788 181 SV ** Tstack_sp;
462e5cf6 182#ifdef OP_IN_REGISTER
183 OP * Topsave;
184#else
11343788 185 OP * Top;
462e5cf6 186#endif
33f46ff6 187 SV ** Tcurpad;
188 SV ** Tstack_base;
189
190 SV ** Tstack_max;
11343788 191
192 I32 * Tscopestack;
193 I32 Tscopestack_ix;
194 I32 Tscopestack_max;
195
196 ANY * Tsavestack;
197 I32 Tsavestack_ix;
198 I32 Tsavestack_max;
199
200 OP ** Tretstack;
201 I32 Tretstack_ix;
202 I32 Tretstack_max;
203
204 I32 * Tmarkstack;
205 I32 * Tmarkstack_ptr;
206 I32 * Tmarkstack_max;
207
11343788 208 SV * TSv;
209 XPV * TXpv;
11343788 210 struct stat Tstatbuf;
211 struct tms Ttimesbuf;
212
213 /* XXX What about regexp stuff? */
214
215 /* Now the fields that used to be "per interpreter" (even when global) */
216
217 /* XXX What about magic variables such as $/, $? and so on? */
218 HV * Tdefstash;
219 HV * Tcurstash;
11343788 220
221 SV ** Ttmps_stack;
222 I32 Ttmps_ix;
223 I32 Ttmps_floor;
224 I32 Ttmps_max;
225
226 int Tin_eval;
227 OP * Trestartop;
228 int Tdelaymagic;
229 bool Tdirty;
230 U8 Tlocalizing;
0f15f207 231 COP * Tcurcop;
11343788 232
233 CONTEXT * Tcxstack;
234 I32 Tcxstack_ix;
235 I32 Tcxstack_max;
236
0f15f207 237 AV * Tcurstack;
11343788 238 AV * Tmainstack;
e858de61 239 JMPENV * Ttop_env;
11343788 240 I32 Trunlevel;
241
242 /* XXX Sort stuff, firstgv, secongv and so on? */
243
33f46ff6 244 perl_thread Tself;
245 SV * Toursv;
12ca11f6 246 perl_mutex *Tthreadstart_mutexp;
11343788 247 HV * Tcvcache;
33f46ff6 248 U32 flags;
249 U32 tid;
250 struct thread *next, *prev; /* Circular linked list of threads */
12ca11f6 251
252#ifdef FAKE_THREADS
12ca11f6 253 perl_thread next_run, prev_run; /* Linked list of runnable threads */
254 perl_cond wait_queue; /* Wait queue that we are waiting on */
255 IV private; /* Holds data across time slices */
0f15f207 256 I32 savemark; /* Holds MARK for thread join values */
12ca11f6 257#endif /* FAKE_THREADS */
11343788 258};
259
260typedef struct thread *Thread;
261
33f46ff6 262/* Values and macros for thr->flags */
07b73707 263#define THRf_STATE_MASK 3
264#define THRf_NORMAL 0
265#define THRf_DETACHED 1
266#define THRf_JOINED 2
267#define THRf_DEAD 3
f93b4edd 268
07b73707 269#define THRf_DIE_FATAL 4
270
33f46ff6 271#define ThrSTATE(t) (t->flags & THRf_STATE_MASK)
f93b4edd 272#define ThrSETSTATE(t, s) STMT_START { \
33f46ff6 273 (t)->flags &= ~THRf_STATE_MASK; \
274 (t)->flags |= (s); \
f93b4edd 275 DEBUG_L(fprintf(stderr, "thread 0x%lx set to state %d\n", \
276 (unsigned long)(t), (s))); \
277 } STMT_END
278
279typedef struct condpair {
12ca11f6 280 perl_mutex mutex;
281 perl_cond owner_cond;
282 perl_cond cond;
283 Thread owner;
f93b4edd 284} condpair_t;
285
286#define MgMUTEXP(mg) (&((condpair_t *)(mg->mg_ptr))->mutex)
287#define MgOWNERCONDP(mg) (&((condpair_t *)(mg->mg_ptr))->owner_cond)
288#define MgCONDP(mg) (&((condpair_t *)(mg->mg_ptr))->cond)
289#define MgOWNER(mg) ((condpair_t *)(mg->mg_ptr))->owner
290
11343788 291#undef stack_base
292#undef stack_sp
293#undef stack_max
0f15f207 294#undef curstack
11343788 295#undef mainstack
296#undef markstack
297#undef markstack_ptr
298#undef markstack_max
299#undef scopestack
300#undef scopestack_ix
301#undef scopestack_max
302#undef savestack
303#undef savestack_ix
304#undef savestack_max
305#undef retstack
306#undef retstack_ix
307#undef retstack_max
0f15f207 308#undef curcop
11343788 309#undef cxstack
310#undef cxstack_ix
311#undef cxstack_max
809a5acc 312#undef defstash
313#undef curstash
6d4ff0d2 314#undef tmps_stack
315#undef tmps_floor
316#undef tmps_ix
317#undef tmps_max
11343788 318#undef curpad
319#undef Sv
320#undef Xpv
96827780 321#undef statbuf
322#undef timesbuf
11343788 323#undef top_env
324#undef runlevel
325#undef in_eval
809a5acc 326#undef restartop
327#undef delaymagic
328#undef dirty
329#undef localizing
11343788 330
331#define self (thr->Tself)
07b73707 332#define oursv (thr->Toursv)
11343788 333#define stack_base (thr->Tstack_base)
334#define stack_sp (thr->Tstack_sp)
335#define stack_max (thr->Tstack_max)
462e5cf6 336#ifdef OP_IN_REGISTER
337#define opsave (thr->Topsave)
338#else
339#undef op
11343788 340#define op (thr->Top)
462e5cf6 341#endif
0f15f207 342#define curcop (thr->Tcurcop)
11343788 343#define stack (thr->Tstack)
809a5acc 344#define curstack (thr->Tcurstack)
11343788 345#define mainstack (thr->Tmainstack)
346#define markstack (thr->Tmarkstack)
347#define markstack_ptr (thr->Tmarkstack_ptr)
348#define markstack_max (thr->Tmarkstack_max)
349#define scopestack (thr->Tscopestack)
350#define scopestack_ix (thr->Tscopestack_ix)
351#define scopestack_max (thr->Tscopestack_max)
352
353#define savestack (thr->Tsavestack)
354#define savestack_ix (thr->Tsavestack_ix)
355#define savestack_max (thr->Tsavestack_max)
356
357#define retstack (thr->Tretstack)
358#define retstack_ix (thr->Tretstack_ix)
359#define retstack_max (thr->Tretstack_max)
360
361#define cxstack (thr->Tcxstack)
362#define cxstack_ix (thr->Tcxstack_ix)
363#define cxstack_max (thr->Tcxstack_max)
364
365#define curpad (thr->Tcurpad)
366#define Sv (thr->TSv)
367#define Xpv (thr->TXpv)
96827780 368#define statbuf (thr->Tstatbuf)
369#define timesbuf (thr->Ttimesbuf)
11343788 370#define defstash (thr->Tdefstash)
371#define curstash (thr->Tcurstash)
11343788 372
373#define tmps_stack (thr->Ttmps_stack)
374#define tmps_ix (thr->Ttmps_ix)
375#define tmps_floor (thr->Ttmps_floor)
376#define tmps_max (thr->Ttmps_max)
377
378#define in_eval (thr->Tin_eval)
379#define restartop (thr->Trestartop)
380#define delaymagic (thr->Tdelaymagic)
381#define dirty (thr->Tdirty)
382#define localizing (thr->Tlocalizing)
383
384#define top_env (thr->Ttop_env)
385#define runlevel (thr->Trunlevel)
386
387#define threadstart_mutexp (thr->Tthreadstart_mutexp)
f93b4edd 388#define cvcache (thr->Tcvcache)
11343788 389#endif /* USE_THREADS */