Test changes
[p5sagit/p5-mst-13.2.git] / thread.h
index 45e47c3..5cb4b28 100644 (file)
--- a/thread.h
+++ b/thread.h
-#ifndef USE_THREADS
-#define MUTEX_LOCK(m)
-#define MUTEX_UNLOCK(m)
-#define MUTEX_INIT(m)
-#define MUTEX_DESTROY(m)
-#define COND_INIT(c)
-#define COND_SIGNAL(c)
-#define COND_BROADCAST(c)
-#define COND_WAIT(c, m)
-#define COND_DESTROY(c)
+#ifdef USE_THREADS
 
-#define THR
-/* Rats: if dTHR is just blank then the subsequent ";" throws an error */
-#define dTHR extern int errno
+#ifdef WIN32
+#  include <win32thread.h>
 #else
-#include <pthread.h>
 
+/* POSIXish threads */
+typedef pthread_t perl_thread;
 #ifdef OLD_PTHREADS_API
-#define pthread_mutexattr_init(a) pthread_mutexattr_create(a)
-#define pthread_mutexattr_settype(a,t) pthread_mutexattr_setkind_np(a,t)
-#define pthread_key_create(k,d) pthread_keycreate(k,(pthread_destructor_t)(d))
+#  define pthread_mutexattr_init(a) pthread_mutexattr_create(a)
+#  define pthread_mutexattr_settype(a,t) pthread_mutexattr_setkind_np(a,t)
+#  define pthread_key_create(k,d) pthread_keycreate(k,(pthread_destructor_t)(d))
+#  define YIELD pthread_yield()
+#  define DETACH(t)                            \
+    STMT_START {                               \
+       if (pthread_detach(&(t)->self)) {       \
+           MUTEX_UNLOCK(&(t)->mutex);          \
+           croak("panic: DETACH");             \
+       }                                       \
+    } STMT_END
 #else
-#define pthread_mutexattr_default NULL
+#  define pthread_mutexattr_default NULL
+#  define pthread_condattr_default NULL
+#  define pthread_attr_default NULL
 #endif /* OLD_PTHREADS_API */
+#endif
 
-#define MUTEX_INIT(m) \
-    if (pthread_mutex_init((m), pthread_mutexattr_default)) \
-       croak("panic: MUTEX_INIT"); \
-    else 1
-#define MUTEX_LOCK(m) \
-    if (pthread_mutex_lock((m))) croak("panic: MUTEX_LOCK"); else 1
-#define MUTEX_UNLOCK(m) \
-    if (pthread_mutex_unlock((m))) croak("panic: MUTEX_UNLOCK"); else 1
-#define MUTEX_DESTROY(m) \
-    if (pthread_mutex_destroy((m))) croak("panic: MUTEX_DESTROY"); else 1
-#define COND_INIT(c) \
-    if (pthread_cond_init((c), NULL)) croak("panic: COND_INIT"); else 1
-#define COND_SIGNAL(c) \
-    if (pthread_cond_signal((c))) croak("panic: COND_SIGNAL"); else 1
-#define COND_BROADCAST(c) \
-    if (pthread_cond_broadcast((c))) croak("panic: COND_BROADCAST"); else 1
-#define COND_WAIT(c, m) \
-    if (pthread_cond_wait((c), (m))) croak("panic: COND_WAIT"); else 1
-#define COND_DESTROY(c) \
-    if (pthread_cond_destroy((c))) croak("panic: COND_DESTROY"); else 1
-/* XXX Add "old" (?) POSIX draft interface too */
-#ifdef OLD_PTHREADS_API
+#ifndef YIELD
+#  define YIELD sched_yield()
+#endif
+
+#ifndef MUTEX_INIT
+#define MUTEX_INIT(m)                                          \
+    STMT_START {                                               \
+       if (pthread_mutex_init((m), pthread_mutexattr_default)) \
+           croak("panic: MUTEX_INIT");                         \
+    } STMT_END
+#define MUTEX_LOCK(m)                          \
+    STMT_START {                               \
+       if (pthread_mutex_lock((m)))            \
+           croak("panic: MUTEX_LOCK");         \
+    } STMT_END
+#define MUTEX_UNLOCK(m)                                \
+    STMT_START {                               \
+       if (pthread_mutex_unlock((m)))          \
+           croak("panic: MUTEX_UNLOCK");       \
+    } STMT_END
+#define MUTEX_DESTROY(m)                       \
+    STMT_START {                               \
+       if (pthread_mutex_destroy((m)))         \
+           croak("panic: MUTEX_DESTROY");      \
+    } STMT_END
+#endif /* MUTEX_INIT */
+
+#ifndef COND_INIT
+#define COND_INIT(c)                                           \
+    STMT_START {                                               \
+       if (pthread_cond_init((c), pthread_condattr_default))   \
+           croak("panic: COND_INIT");                          \
+    } STMT_END
+#define COND_SIGNAL(c)                         \
+    STMT_START {                               \
+       if (pthread_cond_signal((c)))           \
+           croak("panic: COND_SIGNAL");        \
+    } STMT_END
+#define COND_BROADCAST(c)                      \
+    STMT_START {                               \
+       if (pthread_cond_broadcast((c)))        \
+           croak("panic: COND_BROADCAST");     \
+    } STMT_END
+#define COND_WAIT(c, m)                                \
+    STMT_START {                               \
+       if (pthread_cond_wait((c), (m)))        \
+           croak("panic: COND_WAIT");          \
+    } STMT_END
+#define COND_DESTROY(c)                                \
+    STMT_START {                               \
+       if (pthread_cond_destroy((c)))          \
+           croak("panic: COND_DESTROY");       \
+    } STMT_END
+#endif /* COND_INIT */
+
+/* DETACH(t) must only be called while holding t->mutex */
+#ifndef DETACH
+#define DETACH(t)                              \
+    STMT_START {                               \
+       if (pthread_detach((t)->self)) {        \
+           MUTEX_UNLOCK(&(t)->mutex);          \
+           croak("panic: DETACH");             \
+       }                                       \
+    } STMT_END
+#endif /* DETACH */
+
+#ifndef JOIN
+#define JOIN(t, avp)                                   \
+    STMT_START {                                       \
+       if (pthread_join((t)->self, (void**)(avp)))     \
+           croak("panic: pthread_join");               \
+    } STMT_END
+#endif /* JOIN */
+
+#ifndef SET_THR
+#define SET_THR(t)                                     \
+    STMT_START {                                       \
+       if (pthread_setspecific(thr_key, (void *) (t))) \
+           croak("panic: pthread_setspecific");        \
+    } STMT_END
+#endif /* SET_THR */
+
+#ifndef THR
+#  ifdef OLD_PTHREADS_API
 struct thread *getTHR _((void));
-#define THR getTHR()
-#else
-#define THR ((struct thread *) pthread_getspecific(thr_key))
-#endif /* OLD_PTHREADS_API */
-#define dTHR struct thread *thr = THR
+#    define THR getTHR()
+#  else
+#    define THR ((struct thread *) pthread_getspecific(thr_key))
+#  endif /* OLD_PTHREADS_API */
+#endif /* THR */
+
+#ifndef dTHR
+#  define dTHR struct thread *thr = THR
+#endif /* dTHR */
+
+#ifndef INIT_THREADS
+#  ifdef NEED_PTHREAD_INIT
+#    define INIT_THREADS pthread_init()
+#  else
+#    define INIT_THREADS NOOP
+#  endif
+#endif
 
-struct thread {
-    pthread_t  Tself;
+#ifndef THREAD_RET_TYPE
+#  define THREAD_RET_TYPE      void *
+#  define THREAD_RET_CAST(p)   ((void *)(p))
+#endif /* THREAD_RET */
 
+struct thread {
     /* The fields that used to be global */
-    SV **      Tstack_base;
+    /* Important ones in the first cache line (if alignment is done right) */
     SV **      Tstack_sp;
-    SV **      Tstack_max;
-
 #ifdef OP_IN_REGISTER
     OP *       Topsave;
 #else
     OP *       Top;
 #endif
+    SV **      Tcurpad;
+    SV **      Tstack_base;
+
+    SV **      Tstack_max;
 
     I32 *      Tscopestack;
     I32                Tscopestack_ix;
@@ -82,12 +163,8 @@ struct thread {
     I32 *      Tmarkstack_ptr;
     I32 *      Tmarkstack_max;
 
-    SV **      Tcurpad;
-
     SV *       TSv;
     XPV *      TXpv;
-    char       Tbuf[2048];     /* should be a global locked by a mutex */
-    char       Ttokenbuf[256]; /* should be a global locked by a mutex */
     struct stat        Tstatbuf;
     struct tms Ttimesbuf;
     
@@ -98,8 +175,6 @@ struct thread {
     /* XXX What about magic variables such as $/, $? and so on? */
     HV *       Tdefstash;
     HV *       Tcurstash;
-    AV *       Tpad;
-    AV *       Tpadname;
 
     SV **      Ttmps_stack;
     I32                Ttmps_ix;
@@ -111,45 +186,59 @@ struct thread {
     int                Tdelaymagic;
     bool       Tdirty;
     U8         Tlocalizing;
+    COP *      Tcurcop;
 
     CONTEXT *  Tcxstack;
     I32                Tcxstack_ix;
     I32                Tcxstack_max;
 
-    AV *       Tstack;
+    AV *       Tcurstack;
     AV *       Tmainstack;
     JMPENV *   Ttop_env;
     I32                Trunlevel;
 
     /* XXX Sort stuff, firstgv, secongv and so on? */
 
-    pthread_mutex_t *  Tthreadstart_mutexp;
+    SV *       Toursv;
     HV *       Tcvcache;
-    U32                Tthrflags;
+    perl_thread        self;                   /* Underlying thread object */
+    U32                flags;
+    perl_mutex mutex;                  /* For the fields others can change */
+    U32                tid;
+    struct thread *next, *prev;                /* Circular linked list of threads */
+
+#ifdef ADD_THREAD_INTERN
+    struct thread_intern i;            /* Platform-dependent internals */
+#endif
+    char       trailing_nul;           /* For the sake of thrsv, t->Toursv */
 };
 
 typedef struct thread *Thread;
 
-/* Values and macros for thrflags */
-#define THR_STATE_MASK 3
-#define THR_NORMAL     0
-#define THR_DETACHED   1
-#define THR_JOINED     2
-#define THR_DEAD       3
+/* Values and macros for thr->flags */
+#define THRf_STATE_MASK        7
+#define THRf_R_JOINABLE        0
+#define THRf_R_JOINED  1
+#define THRf_R_DETACHED        2
+#define THRf_ZOMBIE    3
+#define THRf_DEAD      4
 
-#define ThrSTATE(t)    (t->Tthrflags & THR_STATE_MASK)
+#define THRf_DIE_FATAL 8
+
+/* ThrSTATE(t) and ThrSETSTATE(t) must only be called while holding t->mutex */
+#define ThrSTATE(t) ((t)->flags)
 #define ThrSETSTATE(t, s) STMT_START {         \
-       (t)->Tthrflags &= ~THR_STATE_MASK;      \
-       (t)->Tthrflags |= (s);                  \
-       DEBUG_L(fprintf(stderr, "thread 0x%lx set to state %d\n", \
-                       (unsigned long)(t), (s))); \
+       (t)->flags &= ~THRf_STATE_MASK;         \
+       (t)->flags |= (s);                      \
+       DEBUG_L(PerlIO_printf(PerlIO_stderr(),  \
+                             "thread %p set to state %d\n", (t), (s))); \
     } STMT_END
 
 typedef struct condpair {
-    pthread_mutex_t    mutex;
-    pthread_cond_t     owner_cond;
-    pthread_cond_t     cond;
-    Thread             owner;
+    perl_mutex mutex;          /* Protects all other fields */
+    perl_cond  owner_cond;     /* For when owner changes at all */
+    perl_cond  cond;           /* For cond_signal and cond_broadcast */
+    Thread     owner;          /* Currently owning thread */
 } condpair_t;
 
 #define MgMUTEXP(mg) (&((condpair_t *)(mg->mg_ptr))->mutex)
@@ -160,7 +249,7 @@ typedef struct condpair {
 #undef stack_base
 #undef stack_sp
 #undef stack_max
-#undef stack
+#undef curstack
 #undef mainstack
 #undef markstack
 #undef markstack_ptr
@@ -174,9 +263,12 @@ typedef struct condpair {
 #undef retstack
 #undef retstack_ix
 #undef retstack_max
+#undef curcop
 #undef cxstack
 #undef cxstack_ix
 #undef cxstack_max
+#undef defstash
+#undef curstash
 #undef tmps_stack
 #undef tmps_floor
 #undef tmps_ix
@@ -184,11 +276,17 @@ typedef struct condpair {
 #undef curpad
 #undef Sv
 #undef Xpv
+#undef statbuf
+#undef timesbuf
 #undef top_env
 #undef runlevel
 #undef in_eval
+#undef restartop
+#undef delaymagic
+#undef dirty
+#undef localizing
 
-#define self           (thr->Tself)
+#define oursv          (thr->Toursv)
 #define stack_base     (thr->Tstack_base)
 #define stack_sp       (thr->Tstack_sp)
 #define stack_max      (thr->Tstack_max)
@@ -198,7 +296,9 @@ typedef struct condpair {
 #undef op
 #define op             (thr->Top)
 #endif
+#define        curcop          (thr->Tcurcop)
 #define        stack           (thr->Tstack)
+#define curstack       (thr->Tcurstack)
 #define        mainstack       (thr->Tmainstack)
 #define        markstack       (thr->Tmarkstack)
 #define        markstack_ptr   (thr->Tmarkstack_ptr)
@@ -222,10 +322,10 @@ typedef struct condpair {
 #define curpad         (thr->Tcurpad)
 #define Sv             (thr->TSv)
 #define Xpv            (thr->TXpv)
+#define statbuf                (thr->Tstatbuf)
+#define timesbuf       (thr->Ttimesbuf)
 #define defstash       (thr->Tdefstash)
 #define curstash       (thr->Tcurstash)
-#define pad            (thr->Tpad)
-#define padname                (thr->Tpadname)
 
 #define tmps_stack     (thr->Ttmps_stack)
 #define tmps_ix                (thr->Ttmps_ix)
@@ -241,7 +341,20 @@ typedef struct condpair {
 #define        top_env         (thr->Ttop_env)
 #define        runlevel        (thr->Trunlevel)
 
-#define        threadstart_mutexp      (thr->Tthreadstart_mutexp)
 #define        cvcache         (thr->Tcvcache)
-#define        thrflags        (thr->Tthrflags)
+#else
+/* USE_THREADS is not defined */
+#define MUTEX_LOCK(m)
+#define MUTEX_UNLOCK(m)
+#define MUTEX_INIT(m)
+#define MUTEX_DESTROY(m)
+#define COND_INIT(c)
+#define COND_SIGNAL(c)
+#define COND_BROADCAST(c)
+#define COND_WAIT(c, m)
+#define COND_DESTROY(c)
+
+#define THR
+/* Rats: if dTHR is just blank then the subsequent ";" throws an error */
+#define dTHR extern int errno
 #endif /* USE_THREADS */