AIX patch (including Configure support for {sched,pthread}_yield,
Jarkko Hietaniemi [Thu, 20 Nov 1997 06:10:51 +0000 (22:10 -0800)]
pthread initial detach state, renaming perl_thread to perl_os_thread
and struct thread to struct perl_thread):
Subject: Re: _54 on AIX

p4raw-id: //depot/perl@290

18 files changed:
Configure
config_h.SH
cv.h
ext/DB_File/DB_File.xs
ext/Thread/Makefile.PL
ext/Thread/Thread.pm
ext/Thread/Thread.xs
fakethr.h
hints/aix.sh
perl.c
perl.h
pp.h
proto.h
sv.h
thread.h
util.c
win32/win32thread.c
win32/win32thread.h

index 1fce22d..b8618cb 100755 (executable)
--- a/Configure
+++ b/Configure
@@ -465,6 +465,8 @@ usedl=''
 fpostype=''
 gidtype=''
 groupstype=''
+d_sched_yield=''
+d_pthread_yield=''
 h_fcntl=''
 h_sysfile=''
 db_hashtype=''
@@ -601,6 +603,7 @@ installprivlib=''
 privlib=''
 privlibexp=''
 prototype=''
+pthreads_created_joinable=''
 randbits=''
 installscript=''
 scriptdir=''
@@ -8549,6 +8552,24 @@ EOM
 *)  groupstype="$gidtype";;
 esac
 
+case "$usethreads" in
+$define)
+
+    : see if sched_yield exists
+    set sched_yield d_sched_yield
+    eval $inlibc
+    
+    : see if pthread_yield exists
+    set pthread_yield d_pthread_yield
+    eval $inlibc
+
+    ;;
+*)
+    d_sched_yield=$undef
+    d_pthread_yield=$undef
+    ;;
+esac
+
 : see what type lseek is declared as in the kernel
 set off_t lseektype long stdio.h sys/types.h
 eval $typedef
@@ -9896,6 +9917,53 @@ val="$t_gdbm"
 set i_gdbm
 eval $setvar
 
+: test whether pthreads are created in joinable -- aka undetached -- state
+if test "X$usethreads" != X; then
+echo " "
+echo 'Checking whether pthreads are created joinable.' >&4
+       $cat >try.c <<EOCP
+/* Note: this program returns 1 if detached, 0 if not.
+ * Easier this way because the PTHREAD_CREATE_DETACHED is more
+ * portable than the obsolete PTHREAD_CREATE_UNDETACHED.
+ * Testing for joinable (aka undetached) as opposed to detached
+ * is then again logically more sensible because that's
+ * the more modern default state in the pthreads implementations. */
+#include <pthread.h>
+#include <stdio.h>
+int main() {
+    pthread_attr_t attr;
+    int detachstate;
+    pthread_attr_init(&attr);
+    pthread_attr_getdetachstate(&attr, &detachstate);
+    printf("%s\n",
+           detachstate == PTHREAD_CREATE_DETACHED ?
+           "detached" : "joinable");
+    exit(0);
+}
+EOCP
+    if $cc $ccflags $ldflags -o try try.c $libs >/dev/null 2>&1; then
+       yyy=`./try`
+    else
+       echo "(I can't seem to compile the test program--assuming they are.)"
+       yyy=joinable
+    fi
+    case "$yyy" in
+    joinable)
+      val="$define"
+      echo "Yup, they are."
+      ;;
+    *)
+      val="$undef"
+      echo "Nope, they aren't."
+      ;;
+    esac
+    set d_pthreads_created_joinable
+    eval $setvar
+    $rm -f try try.*
+else
+    d_pthreads_created_joinable=$undef
+fi
+
 echo " "
 echo "Looking for extensions..." >&4
 cd ../ext
@@ -10271,6 +10339,7 @@ d_phostname='$d_phostname'
 d_pipe='$d_pipe'
 d_poll='$d_poll'
 d_portable='$d_portable'
+d_pthread_yield='$d_pthread_yield'
 d_pwage='$d_pwage'
 d_pwchange='$d_pwchange'
 d_pwclass='$d_pwclass'
@@ -10285,6 +10354,7 @@ d_rmdir='$d_rmdir'
 d_safebcpy='$d_safebcpy'
 d_safemcpy='$d_safemcpy'
 d_sanemcmp='$d_sanemcmp'
+d_sched_yield='$d_sched_yield'
 d_seekdir='$d_seekdir'
 d_select='$d_select'
 d_sem='$d_sem'
@@ -10538,6 +10608,7 @@ prefixexp='$prefixexp'
 privlib='$privlib'
 privlibexp='$privlibexp'
 prototype='$prototype'
+pthreads_created_joinable='$pthreads_created_joinable'
 randbits='$randbits'
 ranlib='$ranlib'
 rd_nodata='$rd_nodata'
index 7575143..7b625e3 100644 (file)
@@ -566,6 +566,18 @@ sed <<!GROK!THIS! >config.h -e 's!^#undef\(.*/\)\*!/\*#define\1 \*!' -e 's!^#un-
  */
 #$d_poll HAS_POLL              /**/
 
+/* HAS_PTHREAD_YIELD:
+ *     This symbol, if defined, indicates that the pthread_yield routine is
+ *     available to yield the execution of the current thread.
+ */
+#$d_pthread_yield HAS_PTHREAD_YIELD
+
+/* HAS_SCHED_YIELD:
+ *     This symbol, if defined, indicates that the sched_yield routine is
+ *     available to yield the execution of the current thread.
+ */
+#$d_sched_yield HAS_SCHED_YIELD
+
 /* HAS_READDIR:
  *     This symbol, if defined, indicates that the readdir routine is
  *     available to read directory entries. You may have to include
@@ -1624,6 +1636,12 @@ sed <<!GROK!THIS! >config.h -e 's!^#undef\(.*/\)\*!/\*#define\1 \*!' -e 's!^#un-
  */
 #$d_sfio       USE_SFIO                /**/
 
+/* PTHREADS_CREATED_JOINABLE:
+ *     This symbol, if defined, indicates that pthreads are created
+ *     in the joinable (aka undetached) state.
+ */
+#$d_pthreads_created_joinable  PTHREADS_CREATED_JOINABLE               /**/
+
 /* Sigjmp_buf:
  *     This is the buffer type to be used with Sigsetjmp and Siglongjmp.
  */
diff --git a/cv.h b/cv.h
index d5ffdc2..0eeedfd 100644 (file)
--- a/cv.h
+++ b/cv.h
@@ -30,7 +30,7 @@ struct xpvcv {
     CV *       xcv_outside;
 #ifdef USE_THREADS
     perl_mutex *xcv_mutexp;
-    struct thread *xcv_owner;  /* current owner thread */
+    struct perl_thread *xcv_owner;     /* current owner thread */
 #endif /* USE_THREADS */
     cv_flags_t xcv_flags;
 };
index 959f342..b6e8a03 100644 (file)
 #include "perl.h"
 #include "XSUB.h"
 
+/* Being the Berkeley DB we prefer the <sys/cdefs.h> (which will be
+ * shortly #included by the <db.h>) __attribute__ to the possibly
+ * already defined __attribute__, for example by GNUC or by Perl. */
+#undef __attribute__
+
 #include <db.h>
 /* #ifdef DB_VERSION_MAJOR */
 /* #include <db_185.h> */
index d699091..bed0db4 100644 (file)
@@ -1,2 +1,6 @@
 use ExtUtils::MakeMaker;
-WriteMakefile(NAME => "Thread");
+WriteMakefile(
+       NAME => 'Thread',
+       VERSION_FROM => 'Thread.pm'
+       );
+
index 1936142..48ca304 100644 (file)
@@ -1,6 +1,10 @@
 package Thread;
 require Exporter;
 require DynaLoader;
+use vars qw($VERSION @ISA @EXPORT);
+
+$VERSION = "1.0";
+
 @ISA = qw(Exporter DynaLoader);
 @EXPORT_OK = qw(yield cond_signal cond_broadcast cond_wait async);
 
index 0844312..17c724a 100644 (file)
@@ -16,13 +16,13 @@ static U32 threadnum = 0;
 static int sig_pipe[2];
             
 #ifndef THREAD_RET_TYPE
-typedef struct thread *Thread;
+typedef struct perl_thread *Thread;
 #define THREAD_RET_TYPE void *
 #define THREAD_RET_CAST(x) ((THREAD_RET_TYPE) x)
 #endif
 
 static void
-remove_thread(struct thread *t)
+remove_thread(struct perl_thread *t)
 {
 #ifdef USE_THREADS
     DEBUG_L(WITH_THR(PerlIO_printf(PerlIO_stderr(),
@@ -106,8 +106,8 @@ threadstart(void *arg)
 
     /*
      * It's safe to wait until now to set the thread-specific pointer
-     * from our pthread_t structure to our struct thread, since we're
-     * the only thread who can get at it anyway.
+     * from our pthread_t structure to our struct perl_thread, since
+     * we're the only thread who can get at it anyway.
      */
     SET_THR(thr);
 
@@ -234,8 +234,27 @@ newthread (SV *startsv, AV *initargs, char *classname)
     sigfillset(&fullmask);
     if (sigprocmask(SIG_SETMASK, &fullmask, &oldmask) == -1)
        croak("panic: sigprocmask");
+#ifdef PTHREADS_CREATED_JOINABLE
     err = pthread_create(&thr->self, pthread_attr_default,
                         threadstart, (void*) thr);
+#else
+    {
+       pthread_attr_t attr;
+
+       err = pthread_attr_init(&attr);
+       if (err == 0) {
+#ifdef PTHREAD_CREATE_UNDETACHED
+         err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_UNDETACHED);
+#else
+         croak("panic: pthread_attr_setdetachstate");
+#endif
+         if (err == 0) 
+           err = pthread_create(&thr->self, &attr,
+                                threadstart, (void*) thr);
+       }
+       pthread_attr_destroy(&attr);
+    }
+#endif
     /* Go */
     MUTEX_UNLOCK(&thr->mutex);
 #endif
index 596e8a9..8b1e76f 100644 (file)
--- a/fakethr.h
+++ b/fakethr.h
@@ -1,12 +1,12 @@
 typedef int perl_mutex;
 typedef int perl_key;
 
-typedef struct thread *perl_os_thread;
+typedef struct perl_thread *perl_os_thread;
 /* With fake threads, thr is global(ish) so we don't need dTHR */
 #define dTHR extern int errno
 
 struct perl_wait_queue {
-    struct thread *            thread;
+    struct perl_thread *       thread;
     struct perl_wait_queue *   next;
 };
 typedef struct perl_wait_queue *perl_cond;
index 2c42151..8869a23 100644 (file)
@@ -1,6 +1,8 @@
 # hints/aix.sh
 # AIX 3.x.x hints thanks to Wayne Scott <wscott@ichips.intel.com>
 # AIX 4.1 hints thanks to Christopher Chan-Nui <channui@austin.ibm.com>.
+# AIX 4.1 pthreading by Christopher Chan-Nui <channui@austin.ibm.com> and
+#         Jarkko Hietaniemi <jhi@iki.fi>.
 # Merged on Mon Feb  6 10:22:35 EST 1995 by
 #   Andy Dougherty  <doughera@lafcol.lafayette.edu>
 
@@ -74,3 +76,32 @@ lddlflags='-H512 -T512 -bhalt:4 -bM:SRE -bI:$(PERL_INC)/perl.exp -bE:$(BASEEXT).
 
 ;;
 esac
+
+if [ "X$usethreads" != "X" ]; then
+    ccflags="-DUSE_THREADS $ccflags"
+    cppflags="-DUSE_THREADS $cppflags"
+    case "$cc" in
+    xlc_r)
+       ;;
+    cc | '') 
+       cc=xlc_r
+        ;;
+    *)
+       case "$cc" in
+       gcc)
+           echo >&4 "You cannot use POSIX threads from GNU cc in AIX."
+           ;;
+       *)
+           echo >&4 "Unknown C compiler."
+           ;;
+       esac
+       echo >&4 "You should use the AIX C compiler called xlc_r."
+       echo >&4 "Cannot continue, aborting."
+       exit 1
+       ;;
+    esac
+
+    # Add the POSIX threads library and use the re-entrant libc.
+
+    lddlflags=`echo $lddlflags | sed 's/ -lc$/ -lpthreads -lc_r/'`
+fi
diff --git a/perl.c b/perl.c
index 0ff9f4e..923eea5 100644 (file)
--- a/perl.c
+++ b/perl.c
@@ -70,7 +70,7 @@ static void init_debugger _((void));
 static void init_lexer _((void));
 static void init_main_stash _((void));
 #ifdef USE_THREADS
-static struct thread * init_main_thread _((void));
+static struct perl_thread * init_main_thread _((void));
 #endif /* USE_THREADS */
 static void init_perllib _((void));
 static void init_postdump_symbols _((int, char **, char **));
@@ -112,7 +112,7 @@ perl_construct(register PerlInterpreter *sv_interp)
 #ifdef USE_THREADS
     int i;
 #ifndef FAKE_THREADS
-    struct thread *thr;
+    struct perl_thread *thr;
 #endif /* FAKE_THREADS */
 #endif /* USE_THREADS */
     
@@ -2777,13 +2777,13 @@ incpush(char *p, int addsubdirs)
 }
 
 #ifdef USE_THREADS
-static struct thread *
+static struct perl_thread *
 init_main_thread()
 {
-    struct thread *thr;
+    struct perl_thread *thr;
     XPV *xpv;
 
-    Newz(53, thr, 1, struct thread);
+    Newz(53, thr, 1, struct perl_thread);
     curcop = &compiling;
     thr->cvcache = newHV();
     thr->threadsv = newAV();
diff --git a/perl.h b/perl.h
index b4e8865..ddeff99 100644 (file)
--- a/perl.h
+++ b/perl.h
@@ -1058,7 +1058,7 @@ union any {
 };
 
 #ifdef USE_THREADS
-#define ARGSproto struct thread *thr
+#define ARGSproto struct perl_thread *thr
 #else
 #define ARGSproto void
 #endif /* USE_THREADS */
@@ -1362,18 +1362,18 @@ int runops_debug _((void));
 /* global state */
 EXT PerlInterpreter *  curinterp;      /* currently running interpreter */
 #ifdef USE_THREADS
-EXT perl_key           thr_key;        /* For per-thread struct thread ptr */
+EXT perl_key           thr_key;        /* For per-thread struct perl_thread* */
 EXT perl_mutex         sv_mutex;       /* Mutex for allocating SVs in sv.c */
 EXT perl_mutex         malloc_mutex;   /* Mutex for malloc */
 EXT perl_mutex         eval_mutex;     /* Mutex for doeval */
 EXT perl_cond          eval_cond;      /* Condition variable for doeval */
-EXT struct thread *    eval_owner;     /* Owner thread for doeval */
+EXT struct perl_thread *       eval_owner;     /* Owner thread for doeval */
 EXT int                        nthreads;       /* Number of threads currently */
 EXT perl_mutex         threads_mutex;  /* Mutex for nthreads and thread list */
 EXT perl_cond          nthreads_cond;  /* Condition variable for nthreads */
 EXT char *             threadsv_names INIT(THREADSV_NAMES);
 #ifdef FAKE_THREADS
-EXT struct thread *    thr;            /* Currently executing (fake) thread */
+EXT struct perl_thread *       thr;    /* Currently executing (fake) thread */
 #endif
 #endif /* USE_THREADS */
 
@@ -1959,7 +1959,7 @@ IEXT SV * Imess_sv;
 
 #ifdef USE_THREADS
 /* threads stuff */
-IEXT SV *      Ithrsv;         /* holds struct thread for main thread */
+IEXT SV *      Ithrsv;         /* holds struct perl_thread for main thread */
 #endif /* USE_THREADS */
 
 #undef IEXT
diff --git a/pp.h b/pp.h
index bc39f80..1914fcc 100644 (file)
--- a/pp.h
+++ b/pp.h
@@ -9,7 +9,7 @@
 
 #ifdef USE_THREADS
 #define ARGS thr
-#define dARGS struct thread *thr;
+#define dARGS struct perl_thread *thr;
 #else
 #define ARGS
 #define dARGS
diff --git a/proto.h b/proto.h
index 35ef574..202331b 100644 (file)
--- a/proto.h
+++ b/proto.h
@@ -341,7 +341,7 @@ OP* newUNOP _((I32 type, I32 flags, OP* first));
 OP*    newWHILEOP _((I32 flags, I32 debuggable, LOOP* loop,
                      I32 whileline, OP* expr, OP* block, OP* cont));
 #ifdef USE_THREADS
-struct thread *        new_struct_thread _((struct thread *t));
+struct perl_thread *   new_struct_thread _((struct perl_thread *t));
 #endif
 PerlIO*        nextargv _((GV* gv));
 char*  ninstr _((char* big, char* bigend, char* little, char* lend));
diff --git a/sv.h b/sv.h
index fcf9297..2c47399 100644 (file)
--- a/sv.h
+++ b/sv.h
@@ -246,7 +246,7 @@ struct xpvfm {
     CV *       xcv_outside;
 #ifdef USE_THREADS
     perl_mutex *xcv_mutexp;    /* protects xcv_owner */
-    struct thread *xcv_owner;  /* current owner thread */
+    struct perl_thread *xcv_owner;     /* current owner thread */
 #endif /* USE_THREADS */
     cv_flags_t xcv_flags;
 
index 5c78e7d..656a693 100644 (file)
--- a/thread.h
+++ b/thread.h
@@ -26,7 +26,11 @@ typedef pthread_t perl_os_thread;
 #endif
 
 #ifndef YIELD
-#  define YIELD sched_yield()
+#  ifdef HAS_PTHREAD_YIELD
+#    define YIELD pthread_yield()
+#  else
+#    define YIELD sched_yield()
+#  endif
 #endif
 
 #ifndef MUTEX_INIT
@@ -109,15 +113,15 @@ typedef pthread_t perl_os_thread;
 
 #ifndef THR
 #  ifdef OLD_PTHREADS_API
-struct thread *getTHR _((void));
+struct perl_thread *getTHR _((void));
 #    define THR getTHR()
 #  else
-#    define THR ((struct thread *) pthread_getspecific(thr_key))
+#    define THR ((struct perl_thread *) pthread_getspecific(thr_key))
 #  endif /* OLD_PTHREADS_API */
 #endif /* THR */
 
 #ifndef dTHR
-#  define dTHR struct thread *thr = THR
+#  define dTHR struct perl_thread *thr = THR
 #endif /* dTHR */
 
 #ifndef INIT_THREADS
@@ -134,7 +138,7 @@ struct thread *getTHR _((void));
 #  define THREAD_RET_CAST(p)   ((void *)(p))
 #endif /* THREAD_RET */
 
-struct thread {
+struct perl_thread {
     /* The fields that used to be global */
     /* Important ones in the first cache line (if alignment is done right) */
     SV **      Tstack_sp;
@@ -224,7 +228,7 @@ struct thread {
     HV *       errhv;                  /* HV for what was %@ in pp_ctl.c */
     perl_mutex mutex;                  /* For the fields others can change */
     U32                tid;
-    struct thread *next, *prev;                /* Circular linked list of threads */
+    struct perl_thread *next, *prev;           /* Circular linked list of threads */
     JMPENV     Tstart_env;             /* Top of top_env longjmp() chain */ 
 #ifdef HAVE_THREAD_INTERN
     struct thread_intern i;            /* Platform-dependent internals */
@@ -232,7 +236,7 @@ struct thread {
     char       trailing_nul;           /* For the sake of thrsv and oursv */
 };
 
-typedef struct thread *Thread;
+typedef struct perl_thread *Thread;
 
 /* Values and macros for thr->flags */
 #define THRf_STATE_MASK        7
diff --git a/util.c b/util.c
index 9bdea38..b86f6f5 100644 (file)
--- a/util.c
+++ b/util.c
@@ -2382,14 +2382,14 @@ perl_cond *cp;
 #endif /* FAKE_THREADS */
 
 #ifdef OLD_PTHREADS_API
-struct thread *
+struct perl_thread *
 getTHR _((void))
 {
     pthread_addr_t t;
 
     if (pthread_getspecific(thr_key, &t))
        croak("panic: pthread_getspecific");
-    return (struct thread *) t;
+    return (struct perl_thread *) t;
 }
 #endif /* OLD_PTHREADS_API */
 
@@ -2438,20 +2438,20 @@ condpair_magic(SV *sv)
  * called. The use by ext/Thread/Thread.xs in core perl (where t is the
  * thread calling new_struct_thread) clearly satisfies this constraint.
  */
-struct thread *
-new_struct_thread(struct thread *t)
+struct perl_thread *
+new_struct_thread(struct perl_thread *t)
 {
-    struct thread *thr;
+    struct perl_thread *thr;
     SV *sv;
     SV **svp;
     I32 i;
 
     sv = newSVpv("", 0);
-    SvGROW(sv, sizeof(struct thread) + 1);
-    SvCUR_set(sv, sizeof(struct thread));
+    SvGROW(sv, sizeof(struct perl_thread) + 1);
+    SvCUR_set(sv, sizeof(struct perl_thread));
     thr = (Thread) SvPVX(sv);
     /* debug */
-    memset(thr, 0xab, sizeof(struct thread));
+    memset(thr, 0xab, sizeof(struct perl_thread));
     markstack = 0;
     scopestack = 0;
     savestack = 0;
index 4dbc750..922bef4 100644 (file)
@@ -15,7 +15,7 @@ Perl_alloc_thread_key(void)
 }
 
 void
-Perl_set_thread_self(struct thread *thr)
+Perl_set_thread_self(struct perl_thread *thr)
 {
 #ifdef USE_THREADS
     /* Set thr->self.  GetCurrentThread() retrurns a pseudo handle, need
@@ -33,7 +33,7 @@ Perl_set_thread_self(struct thread *thr)
 
 #ifdef USE_THREADS
 int
-Perl_thread_create(struct thread *thr, thread_func_t *fn)
+Perl_thread_create(struct perl_thread *thr, thread_func_t *fn)
 {
     DWORD junk;
 
index 76392cf..d2dfe42 100644 (file)
@@ -97,7 +97,7 @@ typedef HANDLE perl_mutex;
        }                                                       \
     } STMT_END
 
-#define THR ((struct thread *) TlsGetValue(thr_key))
+#define THR ((struct perl_thread *) TlsGetValue(thr_key))
 #define THREAD_CREATE(t, f)    Perl_thread_create(t, f)
 #define THREAD_POST_CREATE(t)  NOOP
 #define THREAD_RET_TYPE                DWORD WINAPI
@@ -107,8 +107,8 @@ typedef THREAD_RET_TYPE thread_func_t(void *);
 
 START_EXTERN_C
 void Perl_alloc_thread_key _((void));
-int Perl_thread_create _((struct thread *thr, thread_func_t *fn));
-void Perl_set_thread_self _((struct thread *thr));
+int Perl_thread_create _((struct perl_thread *thr, thread_func_t *fn));
+void Perl_set_thread_self _((struct perl_thread *thr));
 END_EXTERN_C
 
 #define INIT_THREADS NOOP