diff options
author | Malcolm Beattie <mbeattie@sable.ox.ac.uk> | 1997-07-24 14:57:53 +0000 |
---|---|---|
committer | Malcolm Beattie <mbeattie@sable.ox.ac.uk> | 1997-07-24 14:57:53 +0000 |
commit | 12ca11f6c16e7b63e13bbf5bc251f214e8de5211 (patch) | |
tree | 2ad63340b2a0d6974dbb2bbf088695113f3c49b4 | |
parent | f2134d958aef4e3c1a25fdd268452df90105e99b (diff) | |
download | perl-12ca11f6c16e7b63e13bbf5bc251f214e8de5211.tar.gz |
Start support for fake threads.
pp_lock now returns its argument.
p4raw-id: //depot/perl@41
-rw-r--r-- | MANIFEST | 1 | ||||
-rw-r--r-- | Makefile.SH | 2 | ||||
-rw-r--r-- | cv.h | 6 | ||||
-rw-r--r-- | op.c | 12 | ||||
-rw-r--r-- | opcode.h | 2 | ||||
-rwxr-xr-x | opcode.pl | 2 | ||||
-rw-r--r-- | perl.c | 4 | ||||
-rw-r--r-- | perl.h | 20 | ||||
-rw-r--r-- | pp.c | 1 | ||||
-rw-r--r-- | pp_ctl.c | 4 | ||||
-rw-r--r-- | pp_hot.c | 14 | ||||
-rw-r--r-- | proto.h | 3 | ||||
-rw-r--r-- | sv.h | 6 | ||||
-rw-r--r-- | thread.h | 49 | ||||
-rw-r--r-- | toke.c | 8 | ||||
-rw-r--r-- | util.c | 78 |
16 files changed, 157 insertions, 55 deletions
@@ -762,6 +762,7 @@ t/pragma/subs.t See if subroutine pseudo-importation works t/pragma/warn-1global Tests of global warnings for warning.t t/pragma/warning.t See if warning controls work taint.c Tainting code +thread.h Threading header toke.c The tokener universal.c The default UNIVERSAL package methods unixish.h Defines that are assumed on Unix diff --git a/Makefile.SH b/Makefile.SH index ec99d02e5c..dc5111a7b6 100644 --- a/Makefile.SH +++ b/Makefile.SH @@ -176,7 +176,7 @@ addedbyconf = UU $(shextract) $(plextract) pstruct h1 = EXTERN.h INTERN.h XSUB.h av.h config.h cop.h cv.h dosish.h h2 = embed.h form.h gv.h handy.h hv.h keywords.h mg.h op.h h3 = opcode.h patchlevel.h perl.h perly.h pp.h proto.h regcomp.h -h4 = regexp.h scope.h sv.h unixish.h util.h perlio.h +h4 = regexp.h scope.h sv.h unixish.h util.h perlio.h thread.h h = $(h1) $(h2) $(h3) $(h4) c1 = $(mallocsrc) av.c scope.c op.c doop.c doio.c dump.c hv.c mg.c @@ -29,9 +29,9 @@ struct xpvcv { AV * xcv_padlist; CV * xcv_outside; #ifdef USE_THREADS - pthread_mutex_t * xcv_mutexp; - pthread_cond_t * xcv_condp; /* signalled when owner leaves CV */ - struct thread * xcv_owner; /* current owner thread */ + perl_mutex *xcv_mutexp; + perl_cond * xcv_condp; /* signalled when owner leaves CV */ + struct thread *xcv_owner; /* current owner thread */ #endif /* USE_THREADS */ U8 xcv_flags; }; @@ -3129,9 +3129,9 @@ CV* outside; CvANON_on(cv); #ifdef USE_THREADS - New(666, CvMUTEXP(cv), 1, pthread_mutex_t); + New(666, CvMUTEXP(cv), 1, perl_mutex); MUTEX_INIT(CvMUTEXP(cv)); - New(666, CvCONDP(cv), 1, pthread_cond_t); + New(666, CvCONDP(cv), 1, perl_cond); COND_INIT(CvCONDP(cv)); CvOWNER(cv) = 0; #endif /* USE_THREADS */ @@ -3371,9 +3371,9 @@ OP *block; CvSTASH(cv) = curstash; #ifdef USE_THREADS CvOWNER(cv) = 0; - New(666, CvMUTEXP(cv), 1, pthread_mutex_t); + New(666, CvMUTEXP(cv), 1, perl_mutex); MUTEX_INIT(CvMUTEXP(cv)); - New(666, CvCONDP(cv), 1, pthread_cond_t); + New(666, CvCONDP(cv), 1, perl_cond); COND_INIT(CvCONDP(cv)); #endif /* USE_THREADS */ @@ -3578,9 +3578,9 @@ char *filename; } CvGV(cv) = (GV*)SvREFCNT_inc(gv); #ifdef USE_THREADS - New(666, CvMUTEXP(cv), 1, pthread_mutex_t); + New(666, CvMUTEXP(cv), 1, perl_mutex); MUTEX_INIT(CvMUTEXP(cv)); - New(666, CvCONDP(cv), 1, pthread_cond_t); + New(666, CvCONDP(cv), 1, perl_cond); COND_INIT(CvCONDP(cv)); CvOWNER(cv) = 0; #endif /* USE_THREADS */ @@ -2489,6 +2489,6 @@ EXT U32 opargs[] = { 0x00000014, /* egrent */ 0x0000000c, /* getlogin */ 0x0000211d, /* syscall */ - 0x00000114, /* lock */ + 0x00000104, /* lock */ }; #endif @@ -654,4 +654,4 @@ getlogin getlogin ck_null st syscall syscall ck_fun imst S L # For multi-threading -lock lock ck_null is S +lock lock ck_null s S @@ -843,9 +843,9 @@ print \" \\@INC:\\n @INC\\n\";"); curpad[0] = (SV*)newAV(); SvPADMY_on(curpad[0]); /* XXX Needed? */ CvOWNER(compcv) = 0; - New(666, CvMUTEXP(compcv), 1, pthread_mutex_t); + New(666, CvMUTEXP(compcv), 1, perl_mutex); MUTEX_INIT(CvMUTEXP(compcv)); - New(666, CvCONDP(compcv), 1, pthread_cond_t); + New(666, CvCONDP(compcv), 1, perl_cond); COND_INIT(CvCONDP(compcv)); #endif /* USE_THREADS */ @@ -63,8 +63,14 @@ register struct op *op asm(stringify(OP_IN_REGISTER)); #define NOOP (void)0 #ifdef USE_THREADS +#ifdef FAKE_THREADS +#include "fakethr.h" +#else #include <pthread.h> -#endif +typedef pthread_mutex_t perl_mutex; +typedef pthread_cond_t perl_cond; +#endif /* FAKE_THREADS */ +#endif /* USE_THREADS */ /* * SOFT_CAST can be used for args to prototyped functions to retain some @@ -1318,14 +1324,14 @@ typedef Sighandler_t Sigsave_t; EXT PerlInterpreter * curinterp; /* currently running interpreter */ #ifdef USE_THREADS EXT pthread_key_t thr_key; /* For per-thread struct thread ptr */ -EXT pthread_mutex_t sv_mutex; /* Mutex for allocating SVs in sv.c */ -EXT pthread_mutex_t malloc_mutex; /* Mutex for malloc */ -EXT pthread_mutex_t eval_mutex; /* Mutex for doeval */ -EXT pthread_cond_t eval_cond; /* Condition variable for doeval */ +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 int nthreads; /* Number of threads currently */ -EXT pthread_mutex_t nthreads_mutex; /* Mutex for nthreads */ -EXT pthread_cond_t nthreads_cond; /* Condition variable for nthreads */ +EXT perl_mutex nthreads_mutex; /* Mutex for nthreads */ +EXT perl_cond nthreads_cond; /* Condition variable for nthreads */ #endif /* USE_THREADS */ /* VMS doesn't use environ array and NeXT has problems with crt0.o globals */ @@ -4157,6 +4157,5 @@ PP(pp_lock) save_destructor(unlock_condpair, sv); } #endif /* USE_THREADS */ - PUSHs(&sv_yes); RETURN; } @@ -2163,9 +2163,9 @@ int gimme; CvUNIQUE_on(compcv); #ifdef USE_THREADS CvOWNER(compcv) = 0; - New(666, CvMUTEXP(compcv), 1, pthread_mutex_t); + New(666, CvMUTEXP(compcv), 1, perl_mutex); MUTEX_INIT(CvMUTEXP(compcv)); - New(666, CvCONDP(compcv), 1, pthread_cond_t); + New(666, CvCONDP(compcv), 1, perl_cond); COND_INIT(CvCONDP(compcv)); #endif /* USE_THREADS */ @@ -41,20 +41,6 @@ void *cvarg; MUTEX_UNLOCK(CvMUTEXP(cv)); SvREFCNT_dec(cv); } - -#if 0 -void -mutex_unlock(m) -void *m; -{ -#ifdef DEBUGGING - dTHR; - DEBUG_L((fprintf(stderr, "0x%lx unlocking mutex 0x%lx\n", - (unsigned long) thr, (unsigned long) m))); -#endif /* DEBUGGING */ - MUTEX_UNLOCK((pthread_mutex_t *) m); -} -#endif #endif /* USE_THREADS */ PP(pp_const) @@ -258,9 +258,6 @@ void mg_magical _((SV* sv)); int mg_set _((SV* sv)); OP* mod _((OP* o, I32 type)); char* moreswitches _((char* s)); -#ifdef USE_THREADS -void mutex_unlock _((void *m)); -#endif /* USE_THREADS */ OP* my _((OP* o)); #if !defined(HAS_BCOPY) || !defined(HAS_SAFE_BCOPY) char* my_bcopy _((char* from, char* to, I32 len)); @@ -244,9 +244,9 @@ struct xpvfm { AV * xcv_padlist; CV * xcv_outside; #ifdef USE_THREADS - pthread_mutex_t * xcv_mutexp; - pthread_cond_t * xcv_condp; /* signalled when owner leaves CV */ - struct thread * xcv_owner; /* current owner thread */ + perl_mutex *xcv_mutexp; + perl_cond * xcv_condp; /* signalled when owner leaves CV */ + struct thread *xcv_owner; /* current owner thread */ #endif /* USE_THREADS */ U8 xcv_flags; @@ -13,8 +13,35 @@ /* Rats: if dTHR is just blank then the subsequent ";" throws an error */ #define dTHR extern int errno #else -#include <pthread.h> +#ifdef FAKE_THREADS +typedef struct thread *perl_thread; +/* With fake threads, thr is global(ish) so we don't need dTHR */ +#define dTHR extern int errno + +/* + * Note that SCHEDULE() is only callable from pp code (which + * must be expecting to be restarted). We'll have to do + * something a bit different for XS code. + */ +#define SCHEDULE() return schedule(), op + +#define MUTEX_LOCK(m) +#define MUTEX_UNLOCK(m) +#define MUTEX_INIT(m) +#define MUTEX_DESTROY(m) +#define COND_INIT(c) perl_cond_init(c) +#define COND_SIGNAL(c) perl_cond_signal(c) +#define COND_BROADCAST(c) perl_cond_broadcast(c) +#define COND_WAIT(c, m) STMT_START { \ + perl_cond_wait(c); \ + SCHEDULE(); \ + } STMT_END +#define COND_DESTROY(c) + +#else +/* 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) @@ -51,9 +78,10 @@ struct thread *getTHR _((void)); #define THR ((struct thread *) pthread_getspecific(thr_key)) #endif /* OLD_PTHREADS_API */ #define dTHR struct thread *thr = THR +#endif /* FAKE_THREADS */ struct thread { - pthread_t Tself; + perl_thread Tself; /* The fields that used to be global */ SV ** Tstack_base; @@ -123,9 +151,16 @@ struct thread { /* XXX Sort stuff, firstgv, secongv and so on? */ - pthread_mutex_t * Tthreadstart_mutexp; + perl_mutex *Tthreadstart_mutexp; HV * Tcvcache; U32 Tthrflags; + +#ifdef FAKE_THREADS + perl_thread next, prev; /* Linked list of all threads */ + perl_thread next_run, prev_run; /* Linked list of runnable threads */ + perl_cond wait_queue; /* Wait queue that we are waiting on */ + IV private; /* Holds data across time slices */ +#endif /* FAKE_THREADS */ }; typedef struct thread *Thread; @@ -146,10 +181,10 @@ typedef struct thread *Thread; } STMT_END typedef struct condpair { - pthread_mutex_t mutex; - pthread_cond_t owner_cond; - pthread_cond_t cond; - Thread owner; + perl_mutex mutex; + perl_cond owner_cond; + perl_cond cond; + Thread owner; } condpair_t; #define MgMUTEXP(mg) (&((condpair_t *)(mg->mg_ptr))->mutex) @@ -5237,9 +5237,9 @@ U32 flags; curpad[0] = (SV*)newAV(); SvPADMY_on(curpad[0]); /* XXX Needed? */ CvOWNER(compcv) = 0; - New(666, CvMUTEXP(compcv), 1, pthread_mutex_t); + New(666, CvMUTEXP(compcv), 1, perl_mutex); MUTEX_INIT(CvMUTEXP(compcv)); - New(666, CvCONDP(compcv), 1, pthread_cond_t); + New(666, CvCONDP(compcv), 1, perl_cond); COND_INIT(CvCONDP(compcv)); #endif /* USE_THREADS */ @@ -5252,9 +5252,9 @@ U32 flags; CvOUTSIDE(compcv) = (CV*)SvREFCNT_inc((SV*)outsidecv); #ifdef USE_THREADS CvOWNER(compcv) = 0; - New(666, CvMUTEXP(compcv), 1, pthread_mutex_t); + New(666, CvMUTEXP(compcv), 1, perl_mutex); MUTEX_INIT(CvMUTEXP(compcv)); - New(666, CvCONDP(compcv), 1, pthread_cond_t); + New(666, CvCONDP(compcv), 1, perl_cond); COND_INIT(CvCONDP(compcv)); #endif /* USE_THREADS */ @@ -2293,6 +2293,84 @@ I32 *retlen; } #ifdef USE_THREADS +#ifdef FAKE_THREADS +/* Very simplistic scheduler for now */ +void +schedule(void) +{ + thr = thr->next_run; +} + +void +perl_cond_init(cp) +perl_cond *cp; +{ + *cp = 0; +} + +void +perl_cond_signal(cp) +perl_cond *cp; +{ + perl_thread t; + perl_cond cond = *cp; + + if (!cond) + return; + t = cond->thread; + /* Insert t in the runnable queue just ahead of us */ + t->next_run = thr->next_run; + thr->next_run->prev_run = t; + t->prev_run = thr; + thr->next_run = t; + thr->wait_queue = 0; + /* Remove from the wait queue */ + *cp = cond->next; + Safefree(cond); +} + +void +perl_cond_broadcast(cp) +perl_cond *cp; +{ + perl_thread t; + perl_cond cond, cond_next; + + for (cond = *cp; cond; cond = cond_next) { + t = cond->thread; + /* Insert t in the runnable queue just ahead of us */ + t->next_run = thr->next_run; + thr->next_run->prev_run = t; + t->prev_run = thr; + thr->next_run = t; + thr->wait_queue = 0; + /* Remove from the wait queue */ + cond_next = cond->next; + Safefree(cond); + } + *cp = 0; +} + +void +perl_cond_wait(cp) +perl_cond *cp; +{ + perl_cond cond; + + if (thr->next_run == thr) + croak("panic: perl_cond_wait called by last runnable thread"); + + New(666, cond, 1, perl_wait_queue); + cond->thread = thr; + cond->next = *cp; + *cp = cond; + thr->wait_queue = cond; + /* Remove ourselves from runnable queue */ + thr->next_run->prev_run = thr->prev_run; + thr->prev_run->next_run = thr->next_run; +} +#endif /* FAKE_THREADS */ + #ifdef OLD_PTHREADS_API struct thread * getTHR _((void)) |