Win32 changes over 5.004_52:
[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 { \
f6ac99e2 115 if (CloseHandle((t)->Tself) == 0) { \
116 MUTEX_UNLOCK(&(t)->mutex); \
059e4e88 117 croak("panic: DETACH"); \
f6ac99e2 118 } \
059e4e88 119 } STMT_END
120
121#define THR ((struct thread *) TlsGetValue(thr_key))
122#define pthread_getspecific(k) TlsGetValue(k)
123#define pthread_setspecific(k,v) (TlsSetValue(k,v) == 0)
124
125#else /* !WIN32 */
126
12ca11f6 127/* POSIXish threads */
128typedef pthread_t perl_thread;
11343788 129#ifdef OLD_PTHREADS_API
130#define pthread_mutexattr_init(a) pthread_mutexattr_create(a)
131#define pthread_mutexattr_settype(a,t) pthread_mutexattr_setkind_np(a,t)
132#define pthread_key_create(k,d) pthread_keycreate(k,(pthread_destructor_t)(d))
133#else
134#define pthread_mutexattr_default NULL
b851de6c 135#define pthread_condattr_default NULL
11343788 136#endif /* OLD_PTHREADS_API */
137
138#define MUTEX_INIT(m) \
139 if (pthread_mutex_init((m), pthread_mutexattr_default)) \
140 croak("panic: MUTEX_INIT"); \
141 else 1
142#define MUTEX_LOCK(m) \
143 if (pthread_mutex_lock((m))) croak("panic: MUTEX_LOCK"); else 1
144#define MUTEX_UNLOCK(m) \
145 if (pthread_mutex_unlock((m))) croak("panic: MUTEX_UNLOCK"); else 1
146#define MUTEX_DESTROY(m) \
147 if (pthread_mutex_destroy((m))) croak("panic: MUTEX_DESTROY"); else 1
148#define COND_INIT(c) \
b851de6c 149 if (pthread_cond_init((c), pthread_condattr_default)) \
150 croak("panic: COND_INIT"); \
151 else 1
11343788 152#define COND_SIGNAL(c) \
153 if (pthread_cond_signal((c))) croak("panic: COND_SIGNAL"); else 1
154#define COND_BROADCAST(c) \
155 if (pthread_cond_broadcast((c))) croak("panic: COND_BROADCAST"); else 1
156#define COND_WAIT(c, m) \
157 if (pthread_cond_wait((c), (m))) croak("panic: COND_WAIT"); else 1
158#define COND_DESTROY(c) \
159 if (pthread_cond_destroy((c))) croak("panic: COND_DESTROY"); else 1
33f46ff6 160
f826a10b 161/* DETACH(t) must only be called while holding t->mutex */
162#define DETACH(t) \
163 if (pthread_detach((t)->Tself)) { \
164 MUTEX_UNLOCK(&(t)->mutex); \
165 croak("panic: DETACH"); \
166 } else 1
33f46ff6 167
11343788 168/* XXX Add "old" (?) POSIX draft interface too */
169#ifdef OLD_PTHREADS_API
170struct thread *getTHR _((void));
171#define THR getTHR()
172#else
173#define THR ((struct thread *) pthread_getspecific(thr_key))
174#endif /* OLD_PTHREADS_API */
059e4e88 175#endif /* WIN32 */
11343788 176#define dTHR struct thread *thr = THR
12ca11f6 177#endif /* FAKE_THREADS */
11343788 178
33f46ff6 179#ifndef INIT_THREADS
180# ifdef NEED_PTHREAD_INIT
181# define INIT_THREADS pthread_init()
182# else
183# define INIT_THREADS NOOP
184# endif
185#endif
11343788 186
33f46ff6 187struct thread {
11343788 188 /* The fields that used to be global */
33f46ff6 189 /* Important ones in the first cache line (if alignment is done right) */
11343788 190 SV ** Tstack_sp;
462e5cf6 191#ifdef OP_IN_REGISTER
192 OP * Topsave;
193#else
11343788 194 OP * Top;
462e5cf6 195#endif
33f46ff6 196 SV ** Tcurpad;
197 SV ** Tstack_base;
198
199 SV ** Tstack_max;
11343788 200
201 I32 * Tscopestack;
202 I32 Tscopestack_ix;
203 I32 Tscopestack_max;
204
205 ANY * Tsavestack;
206 I32 Tsavestack_ix;
207 I32 Tsavestack_max;
208
209 OP ** Tretstack;
210 I32 Tretstack_ix;
211 I32 Tretstack_max;
212
213 I32 * Tmarkstack;
214 I32 * Tmarkstack_ptr;
215 I32 * Tmarkstack_max;
216
11343788 217 SV * TSv;
218 XPV * TXpv;
11343788 219 struct stat Tstatbuf;
220 struct tms Ttimesbuf;
221
222 /* XXX What about regexp stuff? */
223
224 /* Now the fields that used to be "per interpreter" (even when global) */
225
226 /* XXX What about magic variables such as $/, $? and so on? */
227 HV * Tdefstash;
228 HV * Tcurstash;
11343788 229
230 SV ** Ttmps_stack;
231 I32 Ttmps_ix;
232 I32 Ttmps_floor;
233 I32 Ttmps_max;
234
235 int Tin_eval;
236 OP * Trestartop;
237 int Tdelaymagic;
238 bool Tdirty;
239 U8 Tlocalizing;
0f15f207 240 COP * Tcurcop;
11343788 241
242 CONTEXT * Tcxstack;
243 I32 Tcxstack_ix;
244 I32 Tcxstack_max;
245
0f15f207 246 AV * Tcurstack;
11343788 247 AV * Tmainstack;
e858de61 248 JMPENV * Ttop_env;
11343788 249 I32 Trunlevel;
250
251 /* XXX Sort stuff, firstgv, secongv and so on? */
252
33f46ff6 253 perl_thread Tself;
254 SV * Toursv;
11343788 255 HV * Tcvcache;
33f46ff6 256 U32 flags;
f826a10b 257 perl_mutex mutex; /* For the fields others can change */
33f46ff6 258 U32 tid;
259 struct thread *next, *prev; /* Circular linked list of threads */
12ca11f6 260
f826a10b 261#ifdef ADD_THREAD_INTERN
262 struct thread_intern i; /* Platform-dependent internals */
263#endif
11343788 264};
265
266typedef struct thread *Thread;
267
33f46ff6 268/* Values and macros for thr->flags */
605e5515 269#define THRf_STATE_MASK 7
270#define THRf_R_JOINABLE 0
271#define THRf_R_JOINED 1
272#define THRf_R_DETACHED 2
273#define THRf_ZOMBIE 3
274#define THRf_DEAD 4
f93b4edd 275
605e5515 276#define THRf_DIE_FATAL 8
07b73707 277
f826a10b 278/* ThrSTATE(t) and ThrSETSTATE(t) must only be called while holding t->mutex */
605e5515 279#define ThrSTATE(t) ((t)->flags)
f93b4edd 280#define ThrSETSTATE(t, s) STMT_START { \
605e5515 281 (t)->flags &= ~THRf_STATE_MASK; \
33f46ff6 282 (t)->flags |= (s); \
605e5515 283 DEBUG_L(PerlIO_printf(PerlIO_stderr(), \
284 "thread %p set to state %d\n", (t), (s))); \
f93b4edd 285 } STMT_END
286
287typedef struct condpair {
f826a10b 288 perl_mutex mutex; /* Protects all other fields */
289 perl_cond owner_cond; /* For when owner changes at all */
290 perl_cond cond; /* For cond_signal and cond_broadcast */
291 Thread owner; /* Currently owning thread */
f93b4edd 292} condpair_t;
293
294#define MgMUTEXP(mg) (&((condpair_t *)(mg->mg_ptr))->mutex)
295#define MgOWNERCONDP(mg) (&((condpair_t *)(mg->mg_ptr))->owner_cond)
296#define MgCONDP(mg) (&((condpair_t *)(mg->mg_ptr))->cond)
297#define MgOWNER(mg) ((condpair_t *)(mg->mg_ptr))->owner
298
11343788 299#undef stack_base
300#undef stack_sp
301#undef stack_max
0f15f207 302#undef curstack
11343788 303#undef mainstack
304#undef markstack
305#undef markstack_ptr
306#undef markstack_max
307#undef scopestack
308#undef scopestack_ix
309#undef scopestack_max
310#undef savestack
311#undef savestack_ix
312#undef savestack_max
313#undef retstack
314#undef retstack_ix
315#undef retstack_max
0f15f207 316#undef curcop
11343788 317#undef cxstack
318#undef cxstack_ix
319#undef cxstack_max
809a5acc 320#undef defstash
321#undef curstash
6d4ff0d2 322#undef tmps_stack
323#undef tmps_floor
324#undef tmps_ix
325#undef tmps_max
11343788 326#undef curpad
327#undef Sv
328#undef Xpv
96827780 329#undef statbuf
330#undef timesbuf
11343788 331#undef top_env
332#undef runlevel
333#undef in_eval
809a5acc 334#undef restartop
335#undef delaymagic
336#undef dirty
337#undef localizing
11343788 338
339#define self (thr->Tself)
07b73707 340#define oursv (thr->Toursv)
11343788 341#define stack_base (thr->Tstack_base)
342#define stack_sp (thr->Tstack_sp)
343#define stack_max (thr->Tstack_max)
462e5cf6 344#ifdef OP_IN_REGISTER
345#define opsave (thr->Topsave)
346#else
347#undef op
11343788 348#define op (thr->Top)
462e5cf6 349#endif
0f15f207 350#define curcop (thr->Tcurcop)
11343788 351#define stack (thr->Tstack)
809a5acc 352#define curstack (thr->Tcurstack)
11343788 353#define mainstack (thr->Tmainstack)
354#define markstack (thr->Tmarkstack)
355#define markstack_ptr (thr->Tmarkstack_ptr)
356#define markstack_max (thr->Tmarkstack_max)
357#define scopestack (thr->Tscopestack)
358#define scopestack_ix (thr->Tscopestack_ix)
359#define scopestack_max (thr->Tscopestack_max)
360
361#define savestack (thr->Tsavestack)
362#define savestack_ix (thr->Tsavestack_ix)
363#define savestack_max (thr->Tsavestack_max)
364
365#define retstack (thr->Tretstack)
366#define retstack_ix (thr->Tretstack_ix)
367#define retstack_max (thr->Tretstack_max)
368
369#define cxstack (thr->Tcxstack)
370#define cxstack_ix (thr->Tcxstack_ix)
371#define cxstack_max (thr->Tcxstack_max)
372
373#define curpad (thr->Tcurpad)
374#define Sv (thr->TSv)
375#define Xpv (thr->TXpv)
96827780 376#define statbuf (thr->Tstatbuf)
377#define timesbuf (thr->Ttimesbuf)
11343788 378#define defstash (thr->Tdefstash)
379#define curstash (thr->Tcurstash)
11343788 380
381#define tmps_stack (thr->Ttmps_stack)
382#define tmps_ix (thr->Ttmps_ix)
383#define tmps_floor (thr->Ttmps_floor)
384#define tmps_max (thr->Ttmps_max)
385
386#define in_eval (thr->Tin_eval)
387#define restartop (thr->Trestartop)
388#define delaymagic (thr->Tdelaymagic)
389#define dirty (thr->Tdirty)
390#define localizing (thr->Tlocalizing)
391
392#define top_env (thr->Ttop_env)
393#define runlevel (thr->Trunlevel)
394
f93b4edd 395#define cvcache (thr->Tcvcache)
11343788 396#endif /* USE_THREADS */