fpostype=''
gidtype=''
groupstype=''
+d_sched_yield=''
+d_pthread_yield=''
h_fcntl=''
h_sysfile=''
db_hashtype=''
privlib=''
privlibexp=''
prototype=''
+pthreads_created_joinable=''
randbits=''
installscript=''
scriptdir=''
*) 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
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
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'
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'
privlib='$privlib'
privlibexp='$privlibexp'
prototype='$prototype'
+pthreads_created_joinable='$pthreads_created_joinable'
randbits='$randbits'
ranlib='$ranlib'
rd_nodata='$rd_nodata'
*/
#$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
*/
#$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.
*/
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;
};
#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> */
use ExtUtils::MakeMaker;
-WriteMakefile(NAME => "Thread");
+WriteMakefile(
+ NAME => 'Thread',
+ VERSION_FROM => 'Thread.pm'
+ );
+
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);
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(),
/*
* 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);
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
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;
# 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>
;;
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
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 **));
#ifdef USE_THREADS
int i;
#ifndef FAKE_THREADS
- struct thread *thr;
+ struct perl_thread *thr;
#endif /* FAKE_THREADS */
#endif /* USE_THREADS */
}
#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();
};
#ifdef USE_THREADS
-#define ARGSproto struct thread *thr
+#define ARGSproto struct perl_thread *thr
#else
#define ARGSproto void
#endif /* USE_THREADS */
/* 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 */
#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
#ifdef USE_THREADS
#define ARGS thr
-#define dARGS struct thread *thr;
+#define dARGS struct perl_thread *thr;
#else
#define ARGS
#define dARGS
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));
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;
#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
#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
# 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;
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 */
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
#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 */
* 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;
}
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
#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;
} \
} 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
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