summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doop.c2
-rw-r--r--embed.h11
-rw-r--r--ext/Thread/Thread.xs17
-rw-r--r--global.sym3
-rw-r--r--gv.c1
-rw-r--r--hv.c2
-rw-r--r--interp.sym3
-rw-r--r--mg.c20
-rw-r--r--op.c61
-rw-r--r--opcode.h15
-rwxr-xr-xopcode.pl12
-rw-r--r--patchlevel.h2
-rw-r--r--perl.c52
-rw-r--r--perl.h4
-rw-r--r--pp.c3
-rw-r--r--pp_ctl.c22
-rw-r--r--pp_sys.c18
-rw-r--r--proto.h8
-rw-r--r--sv.c13
-rw-r--r--sv.h32
-rw-r--r--taint.c5
-rw-r--r--thread.h42
-rw-r--r--toke.c21
-rw-r--r--util.c7
-rw-r--r--win32/makefile.mk4
25 files changed, 252 insertions, 128 deletions
diff --git a/doop.c b/doop.c
index 7209e1dc64..277f46ef7a 100644
--- a/doop.c
+++ b/doop.c
@@ -244,6 +244,7 @@ do_chop(register SV *astr, register SV *sv)
I32
do_chomp(register SV *sv)
{
+ dTHR;
register I32 count;
STRLEN len;
char *s;
@@ -317,6 +318,7 @@ do_chomp(register SV *sv)
void
do_vop(I32 optype, SV *sv, SV *left, SV *right)
{
+ dTHR; /* just for taint */
#ifdef LIBERAL
register long *dl;
register long *ll;
diff --git a/embed.h b/embed.h
index c5cb02c231..46709be1c1 100644
--- a/embed.h
+++ b/embed.h
@@ -460,6 +460,7 @@
#define newWHILEOP Perl_newWHILEOP
#define newXS Perl_newXS
#define newXSUB Perl_newXSUB
+#define new_struct_thread Perl_new_struct_thread
#define nextargv Perl_nextargv
#define nexttoke Perl_nexttoke
#define nexttype Perl_nexttype
@@ -514,6 +515,7 @@
#define padix Perl_padix
#define patleave Perl_patleave
#define peep Perl_peep
+#define per_thread_magicals Perl_per_thread_magicals
#define pidgone Perl_pidgone
#define pidstatus Perl_pidstatus
#define pmflag Perl_pmflag
@@ -1265,7 +1267,8 @@
#define e_tmpname (curinterp->Ie_tmpname)
#define endav (curinterp->Iendav)
#define envgv (curinterp->Ienvgv)
-#define errgv (curinterp->Ierrgv)
+#define errhv (curinterp->Ierrhv)
+#define errsv (curinterp->Ierrsv)
#define eval_root (curinterp->Ieval_root)
#define eval_start (curinterp->Ieval_start)
#define fdpid (curinterp->Ifdpid)
@@ -1417,7 +1420,8 @@
#define Ie_tmpname e_tmpname
#define Iendav endav
#define Ienvgv envgv
-#define Ierrgv errgv
+#define Ierrhv errhv
+#define Ierrsv errsv
#define Ieval_root eval_root
#define Ieval_start eval_start
#define Ifdpid fdpid
@@ -1578,7 +1582,8 @@
#define e_fp Perl_e_fp
#define e_tmpname Perl_e_tmpname
#define endav Perl_endav
-#define errgv Perl_errgv
+#define errhv Perl_errhv
+#define errsv Perl_errsv
#define eval_root Perl_eval_root
#define eval_start Perl_eval_start
#define fdpid Perl_fdpid
diff --git a/ext/Thread/Thread.xs b/ext/Thread/Thread.xs
index d132394689..3a204b25b3 100644
--- a/ext/Thread/Thread.xs
+++ b/ext/Thread/Thread.xs
@@ -225,23 +225,6 @@ newthread (SV *startsv, AV *initargs, char *Class)
savethread = thr;
thr = new_struct_thread(thr);
SPAGAIN;
- defstash = savethread->Tdefstash; /* XXX maybe these should */
- curstash = savethread->Tcurstash; /* always be set to main? */
- /* top_env? */
- /* runlevel */
- cvcache = newHV();
- thr->flags = THRf_R_JOINABLE;
- MUTEX_INIT(&thr->mutex);
- thr->tid = ++threadnum;
- /* Insert new thread into the circular linked list and bump nthreads */
- MUTEX_LOCK(&threads_mutex);
- thr->next = savethread->next;
- thr->prev = savethread;
- savethread->next = thr;
- thr->next->prev = thr;
- nthreads++;
- MUTEX_UNLOCK(&threads_mutex);
-
DEBUG_L(PerlIO_printf(PerlIO_stderr(),
"%p: newthread, tid is %u, preparing stack\n",
savethread, thr->tid));
diff --git a/global.sym b/global.sym
index 5702556528..c2c8b0b18e 100644
--- a/global.sym
+++ b/global.sym
@@ -120,6 +120,7 @@ na
ncmp_amg
ne_amg
neg_amg
+new_struct_thread
nexttoke
nexttype
nextval
@@ -162,6 +163,7 @@ pad_reset_pending
padix
padix_floor
patleave
+per_thread_magicals
pidstatus
pow_amg
pow_ass_amg
@@ -956,6 +958,7 @@ pp_snetent
pp_socket
pp_sockpair
pp_sort
+pp_specific
pp_splice
pp_split
pp_sprintf
diff --git a/gv.c b/gv.c
index 25f8cb135f..7d8df6cd17 100644
--- a/gv.c
+++ b/gv.c
@@ -219,7 +219,6 @@ gv_fetchmeth(HV *stash, char *name, STRLEN len, I32 level)
(cv = GvCV(gv)) &&
(CvROOT(cv) || CvXSUB(cv)))
{
- dTHR; /* just for SvREFCNT_inc */
if (cv = GvCV(topgv))
SvREFCNT_dec(cv);
GvCV(topgv) = (CV*)SvREFCNT_inc(GvCV(gv));
diff --git a/hv.c b/hv.c
index 2ef9ae3496..f3ab6ccbb9 100644
--- a/hv.c
+++ b/hv.c
@@ -294,6 +294,7 @@ hv_store_ent(HV *hv, SV *keysv, SV *val, register U32 hash)
xhv = (XPVHV*)SvANY(hv);
if (SvMAGICAL(hv)) {
+ dTHR;
bool save_taint = tainted;
if (tainting)
tainted = SvTAINTED(keysv);
@@ -877,7 +878,6 @@ hv_iternext(HV *hv)
}
magic_nextpack((SV*) hv,mg,key);
if (SvOK(key)) {
- dTHR; /* just for SvREFCNT_inc */
/* force key to stay around until next time */
HeSVKEY_set(entry, SvREFCNT_inc(key));
return entry; /* beware, hent_val is not set */
diff --git a/interp.sym b/interp.sym
index 1583ea217e..ae064a8031 100644
--- a/interp.sym
+++ b/interp.sym
@@ -47,7 +47,8 @@ e_fp
e_tmpname
endav
envgv
-errgv
+errhv
+errsv
eval_root
eval_start
fdpid
diff --git a/mg.c b/mg.c
index 5d2702675c..893b5aaba1 100644
--- a/mg.c
+++ b/mg.c
@@ -247,6 +247,7 @@ mg_free(SV *sv)
U32
magic_len(SV *sv, MAGIC *mg)
{
+ dTHR;
register I32 paren;
register char *s;
register I32 i;
@@ -310,6 +311,7 @@ magic_len(SV *sv, MAGIC *mg)
int
magic_get(SV *sv, MAGIC *mg)
{
+ dTHR;
register I32 paren;
register char *s;
register I32 i;
@@ -396,7 +398,11 @@ magic_get(SV *sv, MAGIC *mg)
case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': case '&':
if (curpm && (rx = curpm->op_pmregexp)) {
- paren = atoi(GvENAME((GV*)mg->mg_obj));
+ /*
+ * Pre-threads, this was paren = atoi(GvENAME((GV*)mg->mg_obj));
+ * XXX Does the new way break anything?
+ */
+ paren = atoi(mg->mg_ptr);
getparen:
if (paren <= rx->nparens &&
(s = rx->startp[paren]) &&
@@ -553,6 +559,11 @@ magic_get(SV *sv, MAGIC *mg)
break;
case '0':
break;
+#ifdef USE_THREADS
+ case '@':
+ sv_setsv(sv, errsv);
+ break;
+#endif /* USE_THREADS */
}
return 0;
}
@@ -718,7 +729,6 @@ magic_getsig(SV *sv, MAGIC *mg)
if(psig_ptr[i])
sv_setsv(sv,psig_ptr[i]);
else {
- dTHR; /* just for SvREFCNT_inc */
Sighandler_t sigstate = rsignal_state(i);
/* cache state so we don't fetch it again */
@@ -1098,6 +1108,7 @@ magic_setsubstr(SV *sv, MAGIC *mg)
int
magic_gettaint(SV *sv, MAGIC *mg)
{
+ dTHR;
TAINT_IF((mg->mg_len & 1) ||
(mg->mg_len & 2) && mg->mg_obj == sv); /* kludge */
return 0;
@@ -1604,6 +1615,11 @@ magic_set(SV *sv, MAGIC *mg)
origargv[i] = Nullch;
}
break;
+#ifdef USE_THREADS
+ case '@':
+ sv_setsv(errsv, sv);
+ break;
+#endif /* USE_THREADS */
}
return 0;
}
diff --git a/op.c b/op.c
index 513a6507a5..2f79a6f924 100644
--- a/op.c
+++ b/op.c
@@ -523,7 +523,7 @@ find_thread_magical(char *name)
sv_setpv(sv, "\034");
break;
}
- sv_magic(sv, 0, 0, name, 1);
+ sv_magic(sv, 0, 0, name, 1);
DEBUG_L(PerlIO_printf(PerlIO_stderr(),
"find_thread_magical: new SV %p for $%s%c\n",
sv, (*name < 32) ? "^" : "",
@@ -1147,7 +1147,7 @@ mod(OP *o, I32 type)
case OP_RV2SV:
if (!type && cUNOPo->op_first->op_type != OP_GV)
croak("Can't localize through a reference");
- ref(cUNOPo->op_first, o->op_type);
+ ref(cUNOPo->op_first, o->op_type);
/* FALL THROUGH */
case OP_GV:
case OP_AV2ARYLEN:
@@ -1175,7 +1175,7 @@ mod(OP *o, I32 type)
case OP_SPECIFIC:
modcount++; /* XXX ??? */
#if 0
- if (!type)
+ if (!type)
croak("Can't localize thread-specific variable");
#endif
break;
@@ -1314,7 +1314,7 @@ ref(OP *o, I32 type)
o->op_flags |= OPf_SPECIAL;
}
break;
-
+
case OP_COND_EXPR:
for (kid = cUNOPo->op_first->op_sibling; kid; kid = kid->op_sibling)
ref(kid, type);
@@ -1330,10 +1330,14 @@ ref(OP *o, I32 type)
o->op_flags |= OPf_MOD;
}
break;
-
+
+ case OP_SPECIFIC:
+ o->op_flags |= OPf_MOD; /* XXX ??? */
+ break;
+
case OP_RV2AV:
case OP_RV2HV:
- o->op_flags |= OPf_REF;
+ o->op_flags |= OPf_REF;
/* FALL THROUGH */
case OP_RV2GV:
ref(cUNOPo->op_first, o->op_type);
@@ -1341,9 +1345,9 @@ ref(OP *o, I32 type)
case OP_PADAV:
case OP_PADHV:
- o->op_flags |= OPf_REF;
+ o->op_flags |= OPf_REF;
break;
-
+
case OP_SCALAR:
case OP_NULL:
if (!(o->op_flags & OPf_KIDS))
@@ -1664,7 +1668,7 @@ fold_constants(register OP *o)
}
return newSVOP(OP_CONST, 0, sv);
}
-
+
nope:
if (!(opargs[type] & OA_OTHERINT))
return o;
@@ -1904,7 +1908,7 @@ newUNOP(I32 type, I32 flags, OP *first)
UNOP *unop;
if (!first)
- first = newOP(OP_STUB, 0);
+ first = newOP(OP_STUB, 0);
if (opargs[type] & OA_MARK)
first = force_list(first);
@@ -2063,7 +2067,7 @@ pmruntime(OP *o, OP *expr, OP *repl)
pm->op_pmflags |= PMf_SKIPWHITE;
}
pm->op_pmregexp = pregcomp(p, p + plen, pm);
- if (strEQ("\\s+", pm->op_pmregexp->precomp))
+ if (strEQ("\\s+", pm->op_pmregexp->precomp))
pm->op_pmflags |= PMf_WHITE;
hoistmust(pm);
op_free(expr);
@@ -2287,7 +2291,7 @@ utilize(int aver, I32 floor, OP *version, OP *id, OP *arg)
newUNOP(OP_METHOD, 0, meth)));
}
}
-
+
/* Fake up an import/unimport */
if (arg && arg->op_type == OP_STUB)
imop = arg; /* no import on explicit () */
@@ -2845,7 +2849,7 @@ newWHILEOP(I32 flags, I32 debuggable, LOOP *loop, I32 whileline, OP *expr, OP *b
op_free((OP*)loop);
return Nullop; /* (listop already freed by newLOGOP) */
}
- ((LISTOP*)listop)->op_last->op_next = condop =
+ ((LISTOP*)listop)->op_last->op_next = condop =
(o == listop ? redo : LINKLIST(o));
if (!next)
next = condop;
@@ -3218,7 +3222,7 @@ cv_const_sv(CV *cv)
{
OP *o;
SV *sv;
-
+
if (!cv || !SvPOK(cv) || SvCUR(cv))
return Nullsv;
@@ -3334,8 +3338,8 @@ newSUB(I32 floor, OP *o, OP *proto, OP *block)
croak(not_safe);
else {
/* force display of errors found but not reported */
- sv_catpv(GvSV(errgv), not_safe);
- croak("%s", SvPVx(GvSV(errgv), na));
+ sv_catpv(errsv, not_safe);
+ croak("%s", SvPV(errsv, na));
}
}
}
@@ -3462,8 +3466,9 @@ newSUB(I32 floor, OP *o, OP *proto, OP *block)
return cv;
}
+
CV *
-newXS(char *name, void (*subaddr) _((CV *)), char *filename)
+newXS(char *name, void (*subaddr) (CV *), char *filename)
{
dTHR;
GV *gv = gv_fetchpv(name ? name : "__ANON__", GV_ADDMULTI, SVt_PVCV);
@@ -3702,6 +3707,8 @@ newSVREF(OP *o)
o->op_ppaddr = ppaddr[OP_PADSV];
return o;
}
+ else if (o->op_type == OP_SPECIFIC)
+ return o;
return newUNOP(OP_RV2SV, 0, scalar(o));
}
@@ -3757,7 +3764,7 @@ ck_spair(OP *o)
!(opargs[newop->op_type] & OA_RETSCALAR) ||
newop->op_type == OP_PADAV || newop->op_type == OP_PADHV ||
newop->op_type == OP_RV2AV || newop->op_type == OP_RV2HV)) {
-
+
return o;
}
op_free(kUNOP->op_first);
@@ -3978,7 +3985,7 @@ ck_fun(OP *o)
I32 numargs = 0;
int type = o->op_type;
register I32 oa = opargs[type] >> OASHIFT;
-
+
if (o->op_flags & OPf_STACKED) {
if ((oa & OA_OPTIONAL) && (oa >> 4) && !((oa >> 4) & OA_OPTIONAL))
oa &= ~OA_OPTIONAL;
@@ -4127,7 +4134,7 @@ ck_glob(OP *o)
cLISTOPo->op_first->op_type = OP_PUSHMARK;
cLISTOPo->op_first->op_ppaddr = ppaddr[OP_PUSHMARK];
o = newUNOP(OP_ENTERSUB, OPf_STACKED,
- append_elem(OP_LIST, o,
+ append_elem(OP_LIST, o,
scalar(newUNOP(OP_RV2CV, 0,
newGVOP(OP_GV, 0, gv)))));
o = newUNOP(OP_NULL, 0, ck_subr(o));
@@ -4150,7 +4157,7 @@ ck_grep(OP *o)
o->op_ppaddr = ppaddr[OP_GREPSTART];
Newz(1101, gwop, 1, LOGOP);
-
+
if (o->op_flags & OPf_STACKED) {
OP* k;
o = ck_sort(o);
@@ -4169,7 +4176,7 @@ ck_grep(OP *o)
o = ck_fun(o);
if (error_count)
return o;
- kid = cLISTOPo->op_first->op_sibling;
+ kid = cLISTOPo->op_first->op_sibling;
if (kid->op_type != OP_NULL)
croak("panic: ck_grep");
kid = kUNOP->op_first;
@@ -4228,7 +4235,7 @@ OP *
ck_listiob(OP *o)
{
register OP *kid;
-
+
kid = cLISTOPo->op_first;
if (!kid) {
o = force_list(o);
@@ -4445,7 +4452,7 @@ ck_split(OP *o)
{
register OP *kid;
PMOP* pm;
-
+
if (o->op_flags & OPf_STACKED)
return no_fh_allowed(o);
@@ -4747,7 +4754,7 @@ peep(register OP *o)
o->op_next = o->op_next->op_next;
}
break;
-
+
case OP_PADHV:
if (o->op_next->op_type == OP_RV2HV
&& (o->op_next->op_flags && OPf_REF))
@@ -4798,7 +4805,7 @@ peep(register OP *o)
}
}
break;
-
+
case OP_HELEM: {
UNOP *rop;
SV *lexname;
@@ -4807,7 +4814,7 @@ peep(register OP *o)
I32 ind;
char *key;
STRLEN keylen;
-
+
if (o->op_private & (OPpDEREF_HV|OPpDEREF_AV|OPpLVAL_INTRO)
|| ((BINOP*)o)->op_last->op_type != OP_CONST)
break;
diff --git a/opcode.h b/opcode.h
index 7ac38950f3..dedc5ca953 100644
--- a/opcode.h
+++ b/opcode.h
@@ -349,10 +349,11 @@ typedef enum {
OP_GETLOGIN, /* 342 */
OP_SYSCALL, /* 343 */
OP_LOCK, /* 344 */
+ OP_SPECIFIC, /* 345 */
OP_max
} opcode;
-#define MAXO 345
+#define MAXO 346
#ifndef DOINIT
EXT char *op_name[];
@@ -703,6 +704,7 @@ EXT char *op_name[] = {
"getlogin",
"syscall",
"lock",
+ "specific",
};
#endif
@@ -1055,6 +1057,7 @@ EXT char *op_desc[] = {
"getlogin",
"syscall",
"lock",
+ "thread-specific",
};
#endif
@@ -1438,14 +1441,14 @@ OP * pp_egrent _((ARGSproto));
OP * pp_getlogin _((ARGSproto));
OP * pp_syscall _((ARGSproto));
OP * pp_lock _((ARGSproto));
-
+OP * pp_specific _((ARGSproto));
END_EXTERN_C
#ifndef DOINIT
-EXT OP * (*ppaddr[])_((ARGSproto));
+EXT OP * (*ppaddr[])(ARGSproto);
#else
-EXT OP * (*ppaddr[])_((ARGSproto)) = {
+EXT OP * (*ppaddr[])(ARGSproto) = {
pp_null,
pp_stub,
pp_scalar,
@@ -1791,6 +1794,7 @@ EXT OP * (*ppaddr[])_((ARGSproto)) = {
pp_getlogin,
pp_syscall,
pp_lock,
+ pp_specific,
};
#endif
@@ -2143,6 +2147,7 @@ EXT OP * (*check[]) _((OP *op)) = {
ck_null, /* getlogin */
ck_fun, /* syscall */
ck_rfun, /* lock */
+ ck_null, /* specific */
};
#endif
@@ -2495,6 +2500,6 @@ EXT U32 opargs[] = {
0x0000000c, /* getlogin */
0x0002151d, /* syscall */
0x00001c04, /* lock */
+ 0x00000044, /* specific */
};
#endif
-
diff --git a/opcode.pl b/opcode.pl
index 1ef36f2fad..b3405b7b71 100755
--- a/opcode.pl
+++ b/opcode.pl
@@ -77,6 +77,8 @@ print <<END;
};
#endif
+START_EXTERN_C
+
END
# Emit function declarations.
@@ -95,10 +97,12 @@ for (@ops) {
print <<END;
+END_EXTERN_C
+
#ifndef DOINIT
-EXT OP * (*ppaddr[])();
+EXT OP * (*ppaddr[])(ARGSproto);
#else
-EXT OP * (*ppaddr[])() = {
+EXT OP * (*ppaddr[])(ARGSproto) = {
END
for (@ops) {
@@ -180,8 +184,6 @@ for (@ops) {
$argsum |= 128 if $flags =~ /u/; # defaults to $_
$flags =~ /([^a-zA-Z])/ or die qq[Opcode "$_" has no class indicator];
- printf STDERR "op $_, class $1 => 0x%x, argsum 0x%x",
- $opclass{$1}, $argsum; # debug
$argsum |= $opclass{$1} << 8;
$mul = 4096; # 2 ^ OASHIFT
for $arg (split(' ',$args{$_})) {
@@ -190,7 +192,6 @@ for (@ops) {
$argsum += $argnum * $mul;
$mul <<= 4;
}
- printf STDERR ", argsum now 0x%x\n", $argsum; # debug
$argsum = sprintf("0x%08x", $argsum);
print "\t", &tab(3, "$argsum,"), "/* $_ */\n";
}
@@ -680,3 +681,4 @@ syscall syscall ck_fun imst@ S L
# For multi-threading
lock lock ck_rfun s% S
+specific thread-specific ck_null ds0
diff --git a/patchlevel.h b/patchlevel.h
index d8da982693..c5dff601ed 100644
--- a/patchlevel.h
+++ b/patchlevel.h
@@ -1,5 +1,5 @@
#define PATCHLEVEL 4
-#define SUBVERSION 52
+#define SUBVERSION 54
/*
local_patches -- list of locally applied less-than-subversion patches.
diff --git a/perl.c b/perl.c
index cca10d3614..591ec832b1 100644
--- a/perl.c
+++ b/perl.c
@@ -109,9 +109,12 @@ perl_alloc(void)
void
perl_construct(register PerlInterpreter *sv_interp)
{
-#if defined(USE_THREADS) && !defined(FAKE_THREADS)
+#ifdef USE_THREADS
+ int i;
+#ifndef FAKE_THREADS
struct thread *thr;
-#endif
+#endif /* FAKE_THREADS */
+#endif /* USE_THREADS */
if (!(curinterp = sv_interp))
return;
@@ -123,13 +126,18 @@ perl_construct(register PerlInterpreter *sv_interp)
/* Init the real globals (and main thread)? */
if (!linestr) {
#ifdef USE_THREADS
- XPV *xpv;
INIT_THREADS;
- Newz(53, thr, 1, struct thread);
+#ifndef WIN32
+ if (pthread_key_create(&thr_key, 0))
+ croak("panic: pthread_key_create");
+#endif
MUTEX_INIT(&malloc_mutex);
MUTEX_INIT(&sv_mutex);
- /* Safe to use SVs from now on */
+ /*
+ * Safe to use basic SV functions from now on (though
+ * not things like mortals or tainting yet).
+ */
MUTEX_INIT(&eval_mutex);
COND_INIT(&eval_cond);
MUTEX_INIT(&threads_mutex);
@@ -462,7 +470,8 @@ perl_destruct(register PerlInterpreter *sv_interp)
envgv = Nullgv;
siggv = Nullgv;
incgv = Nullgv;
- errgv = Nullgv;
+ errhv = Nullhv;
+ errsv = Nullsv;
argvgv = Nullgv;
argvoutgv = Nullgv;
stdingv = Nullgv;
@@ -960,7 +969,7 @@ print \" \\@INC:\\n @INC\\n\";");
sv_setsv(*av_fetch(thr->magicals, find_thread_magical("/"), FALSE), rs);
#else
sv_setsv(GvSV(gv_fetchpv("/", TRUE, SVt_PV)), rs);
-
+#endif /* USE_THREADS */
if (do_undump)
my_unexec();
@@ -1221,7 +1230,7 @@ perl_call_sv(SV *sv, I32 flags)
if (flags & G_KEEPERR)
in_eval |= 4;
else
- sv_setpv(GvSV(errgv),"");
+ sv_setpv(errsv,"");
}
markstack_ptr++;
@@ -1266,7 +1275,7 @@ perl_call_sv(SV *sv, I32 flags)
runops();
retval = stack_sp - (stack_base + oldmark);
if ((flags & G_EVAL) && !(flags & G_KEEPERR))
- sv_setpv(GvSV(errgv),"");
+ sv_setpv(errsv,"");
cleanup:
if (flags & G_EVAL) {
@@ -1375,7 +1384,7 @@ perl_eval_sv(SV *sv, I32 flags)
runops();
retval = stack_sp - (stack_base + oldmark);
if (!(flags & G_KEEPERR))
- sv_setpv(GvSV(errgv),"");
+ sv_setpv(errsv,"");
cleanup:
JMPENV_POP;
@@ -1403,8 +1412,8 @@ perl_eval_pv(char *p, I32 croak_on_error)
sv = POPs;
PUTBACK;
- if (croak_on_error && SvTRUE(GvSV(errgv)))
- croak(SvPVx(GvSV(errgv), na));
+ if (croak_on_error && SvTRUE(errsv))
+ croak(SvPV(errsv, na));
return sv;
}
@@ -1481,6 +1490,8 @@ moreswitches(char *s)
switch (*s) {
case '0':
+ {
+ dTHR;
rschar = scan_oct(s, 4, &numlen);
SvREFCNT_dec(nrs);
if (rschar & ~((U8)~0))
@@ -1492,6 +1503,7 @@ moreswitches(char *s)
nrs = newSVpv(&ch, 1);
}
return s + numlen;
+ }
case 'F':
minus_F = TRUE;
splitstr = savepv(s + 1);
@@ -1578,6 +1590,7 @@ moreswitches(char *s)
s += numlen;
}
else {
+ dTHR;
if (RsPARA(nrs)) {
ors = "\n\n";
orslen = 2;
@@ -1766,11 +1779,11 @@ init_main_stash(void)
incgv = gv_HVadd(gv_AVadd(gv_fetchpv("INC",TRUE, SVt_PVAV)));
GvMULTI_on(incgv);
defgv = gv_fetchpv("_",TRUE, SVt_PVAV);
- errgv = gv_HVadd(gv_fetchpv("@", TRUE, SVt_PV));
- GvMULTI_on(errgv);
+ errsv = newSVpv("", 0);
+ errhv = newHV();
(void)form("%240s",""); /* Preallocate temp - for immediate signals. */
- sv_grow(GvSV(errgv), 240); /* Preallocate - for immediate signals. */
- sv_setpvn(GvSV(errgv), "", 0);
+ sv_grow(errsv, 240); /* Preallocate - for immediate signals. */
+ sv_setpvn(errsv, "", 0);
curstash = defstash;
compiling.cop_stash = defstash;
debstash = GvHV(gv_fetchpv("DB::", GV_ADDMULTI, SVt_PVHV));
@@ -2506,6 +2519,7 @@ init_predump_symbols(void)
sv_setpvn(*av_fetch(thr->magicals,find_thread_magical("\""),FALSE)," ", 1);
#else
sv_setpvn(GvSV(gv_fetchpv("\"", TRUE, SVt_PV)), " ", 1);
+#endif /* USE_THREADS */
stdingv = gv_fetchpv("STDIN",TRUE, SVt_PVIO);
GvMULTI_on(stdingv);
@@ -2538,6 +2552,7 @@ init_predump_symbols(void)
static void
init_postdump_symbols(register int argc, register char **argv, register char **env)
{
+ dTHR;
char *s;
SV *sv;
GV* tmpgv;
@@ -2913,8 +2928,8 @@ my_exit(U32 status)
dTHR;
#ifdef USE_THREADS
- DEBUG_L(PerlIO_printf(Perl_debug_log, "my_exit: thread 0x%lx, status %lu\n",
- (unsigned long) thr, (unsigned long) status));
+ DEBUG_L(PerlIO_printf(Perl_debug_log, "my_exit: thread %p, status %lu\n",
+ thr, (unsigned long) status));
#endif /* USE_THREADS */
switch (status) {
case 0:
@@ -2981,3 +2996,4 @@ my_exit_jump(void)
JMPENV_JUMP(2);
}
+
diff --git a/perl.h b/perl.h
index fb1775570e..8e82d2d56c 100644
--- a/perl.h
+++ b/perl.h
@@ -1367,6 +1367,7 @@ EXT struct 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 * per_thread_magicals INIT(PER_THREAD_MAGICALS);
#ifdef FAKE_THREADS
EXT struct thread * thr; /* Currently executing (fake) thread */
#endif
@@ -1869,7 +1870,8 @@ IEXT I32 Imaxscream IINIT(-1);
IEXT SV * Ilastscream;
/* shortcuts to misc objects */
-IEXT GV * Ierrgv;
+IEXT HV * Ierrhv;
+IEXT SV * Ierrsv;
/* shortcuts to debugging objects */
IEXT GV * IDBgv;
diff --git a/pp.c b/pp.c
index 86dd10f379..3df534008e 100644
--- a/pp.c
+++ b/pp.c
@@ -403,7 +403,6 @@ refto(SV *sv)
else if (SvPADTMP(sv))
sv = newSVsv(sv);
else {
- dTHR; /* just for SvREFCNT_inc */
SvTEMP_off(sv);
(void)SvREFCNT_inc(sv);
}
@@ -4313,3 +4312,5 @@ PP(pp_specific)
#endif /* USE_THREADS */
RETURN;
}
+
+
diff --git a/pp_ctl.c b/pp_ctl.c
index ee60c41937..36baae5599 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -1029,21 +1029,21 @@ die_where(char *message)
SV **svp;
STRLEN klen = strlen(message);
- svp = hv_fetch(GvHV(errgv), message, klen, TRUE);
+ svp = hv_fetch(errhv, message, klen, TRUE);
if (svp) {
if (!SvIOK(*svp)) {
static char prefix[] = "\t(in cleanup) ";
sv_upgrade(*svp, SVt_IV);
(void)SvIOK_only(*svp);
- SvGROW(GvSV(errgv), SvCUR(GvSV(errgv))+sizeof(prefix)+klen);
- sv_catpvn(GvSV(errgv), prefix, sizeof(prefix)-1);
- sv_catpvn(GvSV(errgv), message, klen);
+ SvGROW(errsv, SvCUR(errsv)+sizeof(prefix)+klen);
+ sv_catpvn(errsv, prefix, sizeof(prefix)-1);
+ sv_catpvn(errsv, message, klen);
}
sv_inc(*svp);
}
}
else
- sv_setpv(GvSV(errgv), message);
+ sv_setpv(errsv, message);
cxix = dopoptoeval(cxstack_ix);
if (cxix >= 0) {
@@ -1066,7 +1066,7 @@ die_where(char *message)
LEAVE;
if (optype == OP_REQUIRE) {
- char* msg = SvPVx(GvSV(errgv), na);
+ char* msg = SvPV(errsv, na);
DIE("%s", *msg ? msg : "Compilation failed in require");
}
return pop_return();
@@ -2171,7 +2171,7 @@ doeval(int gimme)
if (saveop->op_flags & OPf_SPECIAL)
in_eval |= 4;
else
- sv_setpv(GvSV(errgv),"");
+ sv_setpv(errsv,"");
if (yyparse() || error_count || !eval_root) {
SV **newsp;
I32 gimme;
@@ -2190,7 +2190,7 @@ doeval(int gimme)
lex_end();
LEAVE;
if (optype == OP_REQUIRE) {
- char* msg = SvPVx(GvSV(errgv), na);
+ char* msg = SvPV(errsv, na);
DIE("%s", *msg ? msg : "Compilation failed in require");
}
SvREFCNT_dec(rs);
@@ -2544,7 +2544,7 @@ PP(pp_leaveeval)
LEAVE;
if (!(save_flags & OPf_SPECIAL))
- sv_setpv(GvSV(errgv),"");
+ sv_setpv(errsv,"");
RETURNOP(retop);
}
@@ -2564,7 +2564,7 @@ PP(pp_entertry)
eval_root = op; /* Only needed so that goto works right. */
in_eval = 1;
- sv_setpv(GvSV(errgv),"");
+ sv_setpv(errsv,"");
PUTBACK;
return DOCATCH(op->op_next);
}
@@ -2612,7 +2612,7 @@ PP(pp_leavetry)
curpm = newpm; /* Don't pop $1 et al till now */
LEAVE;
- sv_setpv(GvSV(errgv),"");
+ sv_setpv(errsv,"");
RETURN;
}
diff --git a/pp_sys.c b/pp_sys.c
index 9a96f7a9d3..34a175ae03 100644
--- a/pp_sys.c
+++ b/pp_sys.c
@@ -284,11 +284,10 @@ PP(pp_warn)
tmps = SvPV(TOPs, na);
}
if (!tmps || !*tmps) {
- SV *error = GvSV(errgv);
- (void)SvUPGRADE(error, SVt_PV);
- if (SvPOK(error) && SvCUR(error))
- sv_catpv(error, "\t...caught");
- tmps = SvPV(error, na);
+ (void)SvUPGRADE(errsv, SVt_PV);
+ if (SvPOK(errsv) && SvCUR(errsv))
+ sv_catpv(errsv, "\t...caught");
+ tmps = SvPV(errsv, na);
}
if (!tmps || !*tmps)
tmps = "Warning: something's wrong";
@@ -310,11 +309,10 @@ PP(pp_die)
tmps = SvPV(TOPs, na);
}
if (!tmps || !*tmps) {
- SV *error = GvSV(errgv);
- (void)SvUPGRADE(error, SVt_PV);
- if (SvPOK(error) && SvCUR(error))
- sv_catpv(error, "\t...propagated");
- tmps = SvPV(error, na);
+ (void)SvUPGRADE(errsv, SVt_PV);
+ if (SvPOK(errsv) && SvCUR(errsv))
+ sv_catpv(errsv, "\t...propagated");
+ tmps = SvPV(errsv, na);
}
if (!tmps || !*tmps)
tmps = "Died";
diff --git a/proto.h b/proto.h
index 9926977569..b5d60f6cb1 100644
--- a/proto.h
+++ b/proto.h
@@ -4,7 +4,7 @@
#undef __attribute__
#endif
#define __attribute__(attr)
-#endif
+#endif
#endif
#ifdef OVERLOAD
SV* amagic_call _((SV* left,SV* right,int method,int dir));
@@ -134,6 +134,9 @@ void dump_packsubs _((HV* stash));
void dump_sub _((GV* gv));
void fbm_compile _((SV* sv));
char* fbm_instr _((unsigned char* big, unsigned char* bigend, SV* littlesv));
+#ifdef USE_THREADS
+PADOFFSET find_thread_magical _((char *name));
+#endif
OP* force_list _((OP* arg));
OP* fold_constants _((OP* arg));
char* form _((const char* pat, ...));
@@ -336,6 +339,9 @@ SV* newSVsv _((SV* old));
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));
+#endif
PerlIO* nextargv _((GV* gv));
char* ninstr _((char* big, char* bigend, char* little, char* lend));
OP* oopsCV _((OP* o));
diff --git a/sv.c b/sv.c
index 97cba87e8b..aeb205542d 100644
--- a/sv.c
+++ b/sv.c
@@ -1084,6 +1084,7 @@ sv_grow(SV* sv, unsigned long newlen)
void
sv_setiv(register SV *sv, IV i)
{
+ dTHR; /* just for taint */
sv_check_thinkfirst(sv);
switch (SvTYPE(sv)) {
case SVt_NULL:
@@ -1131,6 +1132,7 @@ sv_setuv(register SV *sv, UV u)
void
sv_setnv(register SV *sv, double num)
{
+ dTHR; /* just for taint */
sv_check_thinkfirst(sv);
switch (SvTYPE(sv)) {
case SVt_NULL:
@@ -2146,6 +2148,7 @@ sv_setsv(SV *dstr, register SV *sstr)
void
sv_setpvn(register SV *sv, register const char *ptr, register STRLEN len)
{
+ dTHR; /* just for taint */
assert(len >= 0); /* STRLEN is probably unsigned, so this may
elicit a warning, but it won't hurt. */
sv_check_thinkfirst(sv);
@@ -2170,6 +2173,7 @@ sv_setpvn(register SV *sv, register const char *ptr, register STRLEN len)
void
sv_setpv(register SV *sv, register const char *ptr)
{
+ dTHR; /* just for taint */
register STRLEN len;
sv_check_thinkfirst(sv);
@@ -2194,6 +2198,7 @@ sv_setpv(register SV *sv, register const char *ptr)
void
sv_usepvn(register SV *sv, register char *ptr, register STRLEN len)
{
+ dTHR; /* just for taint */
sv_check_thinkfirst(sv);
if (!SvUPGRADE(sv, SVt_PV))
return;
@@ -2254,6 +2259,7 @@ sv_chop(register SV *sv, register char *ptr) /* like set but assuming ptr is in
void
sv_catpvn(register SV *sv, register char *ptr, register STRLEN len)
{
+ dTHR; /* just for taint */
STRLEN tlen;
char *junk;
@@ -2282,6 +2288,7 @@ sv_catsv(SV *dstr, register SV *sstr)
void
sv_catpv(register SV *sv, register char *ptr)
{
+ dTHR; /* just for taint */
register STRLEN len;
STRLEN tlen;
char *junk;
@@ -2977,6 +2984,7 @@ sv_collxfrm(SV *sv, STRLEN *nxp)
char *
sv_gets(register SV *sv, register FILE *fp, I32 append)
{
+ dTHR;
char *rsptr;
STRLEN rslen;
register STDCHAR rslast;
@@ -3490,8 +3498,9 @@ newRV(SV *ref)
}
+
SV *
-newRV_noinc(SV *ref)
+Perl_newRV_noinc(SV *ref)
{
register SV *sv;
@@ -3570,6 +3579,7 @@ sv_reset(register char *s, HV *stash)
sv = GvSV(gv);
(void)SvOK_off(sv);
if (SvTYPE(sv) >= SVt_PV) {
+ dTHR; /* just for taint */
SvCUR_set(sv, 0);
if (SvPVX(sv) != Nullch)
*SvPVX(sv) = '\0';
@@ -3788,6 +3798,7 @@ sv_pvn_force(SV *sv, STRLEN *lp)
*SvEND(sv) = '\0';
}
if (!SvPOK(sv)) {
+ dTHR; /* just for taint */
SvPOK_on(sv); /* validate pointer */
SvTAINT(sv);
DEBUG_c(PerlIO_printf(Perl_debug_log, "0x%lx 2pv(%s)\n",
diff --git a/sv.h b/sv.h
index c888d8fcac..fcf92975f4 100644
--- a/sv.h
+++ b/sv.h
@@ -70,6 +70,7 @@ struct io {
#define SvANY(sv) (sv)->sv_any
#define SvFLAGS(sv) (sv)->sv_flags
+#define SvREFCNT(sv) (sv)->sv_refcnt
#ifdef __GNUC__
# define SvREFCNT_inc(sv) ({SV* nsv=(SV*)(sv); if(nsv) ++SvREFCNT(nsv); nsv;})
@@ -82,7 +83,6 @@ struct io {
#endif
#define SvREFCNT_dec(sv) sv_free((SV*)sv)
-#endif
#define SVTYPEMASK 0xff
#define SvTYPE(sv) ((sv)->sv_flags & SVTYPEMASK)
@@ -546,19 +546,33 @@ struct xpvio {
? SvNVX(sv) != 0.0 \
: sv_2bool(sv) )
-#define SvIVx(sv) ((Sv = (sv)), SvIV(Sv))
-#define SvUVx(sv) ((Sv = (sv)), SvUV(Sv))
-#define SvNVx(sv) ((Sv = (sv)), SvNV(Sv))
-#define SvPVx(sv, lp) ((Sv = (sv)), SvPV(Sv, lp))
+#ifdef __GNUC__
+# define SvIVx(sv) ({SV *nsv = (SV*)(sv); SvIV(nsv); })
+# define SvUVx(sv) ({SV *nsv = (SV*)(sv); SvUV(nsv); })
+# define SvNVx(sv) ({SV *nsv = (SV*)(sv); SvNV(nsv); })
+# define SvPVx(sv, lp) ({SV *nsv = (sv); SvPV(nsv, lp); })
+#else
+# define SvIVx(sv) ((Sv = (sv)), SvIV(Sv))
+# define SvUVx(sv) ((Sv = (sv)), SvUV(Sv))
+# define SvNVx(sv) ((Sv = (sv)), SvNV(Sv))
+# define SvPVx(sv, lp) ((Sv = (sv)), SvPV(Sv, lp))
+#endif /* __GNUC__ */
+
#define SvTRUEx(sv) ((Sv = (sv)), SvTRUE(Sv))
#endif /* CRIPPLED_CC */
#define newRV_inc(sv) newRV(sv)
-#ifndef CRIPPLED_CC
-#undef newRV_noinc
-#define newRV_noinc(sv) ((Sv = newRV(sv)), --SvREFCNT(SvRV(Sv)), Sv)
-#endif
+#ifdef __GNUC__
+# undef newRV_noinc
+# define newRV_noinc(sv) ({SV *nsv=newRV((sv)); --SvREFCNT(SvRV(nsv)); nsv;})
+#else
+# if defined(CRIPPLED_CC) || defined(USE_THREADS)
+# else
+# undef newRV_noinc
+# define newRV_noinc(sv) ((Sv = newRV(sv)), --SvREFCNT(SvRV(Sv)), Sv)
+# endif
+#endif /* __GNUC__ */
/* the following macro updates any magic values this sv is associated with */
diff --git a/taint.c b/taint.c
index c8c6800c46..2dc43a4ab4 100644
--- a/taint.c
+++ b/taint.c
@@ -10,6 +10,7 @@
void
taint_proper(const char *f, char *s)
{
+ dTHR; /* just for taint */
char *ug;
DEBUG_u(PerlIO_printf(Perl_debug_log,
@@ -68,10 +69,12 @@ taint_env(void)
svp = hv_fetch(GvHVn(envgv),"PATH",4,FALSE);
if (svp && *svp) {
if (SvTAINTED(*svp)) {
+ dTHR;
TAINT;
taint_proper("Insecure %s%s", "$ENV{PATH}");
}
if ((mg = mg_find(*svp, 'e')) && MgTAINTEDDIR(mg)) {
+ dTHR;
TAINT;
taint_proper("Insecure directory in %s%s", "$ENV{PATH}");
}
@@ -81,6 +84,7 @@ taint_env(void)
/* tainted $TERM is okay if it contains no metachars */
svp = hv_fetch(GvHVn(envgv),"TERM",4,FALSE);
if (svp && *svp && SvTAINTED(*svp)) {
+ dTHR; /* just for taint */
bool was_tainted = tainted;
char *t = SvPV(*svp, na);
char *e = t + na;
@@ -99,6 +103,7 @@ taint_env(void)
for (e = misc_env; *e; e++) {
svp = hv_fetch(GvHVn(envgv), *e, strlen(*e), FALSE);
if (svp && *svp != &sv_undef && SvTAINTED(*svp)) {
+ dTHR; /* just for taint */
TAINT;
taint_proper("Insecure $ENV{%s}%s", *e);
}
diff --git a/thread.h b/thread.h
index 76cd7d9623..2ee4f518f6 100644
--- a/thread.h
+++ b/thread.h
@@ -172,10 +172,25 @@ struct thread {
/* Now the fields that used to be "per interpreter" (even when global) */
- /* XXX What about magic variables such as $/, $? and so on? */
+ /* Fields used by magic variables such as $@, $/ and so on */
+ bool Ttainted;
+ PMOP * Tcurpm;
+ SV * Tnrs;
+ SV * Trs;
+ GV * Tlast_in_gv;
+ char * Tofs;
+ STRLEN Tofslen;
+ GV * Tdefoutgv;
+ char * Tchopset;
+ SV * Tformtarget;
+ SV * Tbodytarget;
+ SV * Ttoptarget;
+
+ /* Stashes */
HV * Tdefstash;
HV * Tcurstash;
+ /* Stacks */
SV ** Ttmps_stack;
I32 Ttmps_ix;
I32 Ttmps_floor;
@@ -280,6 +295,18 @@ typedef struct condpair {
#undef Xpv
#undef statbuf
#undef timesbuf
+#undef tainted
+#undef curpm
+#undef nrs
+#undef rs
+#undef last_in_gv
+#undef ofs
+#undef ofslen
+#undef defoutgv
+#undef chopset
+#undef formtarget
+#undef bodytarget
+#undef toptarget
#undef top_env
#undef runlevel
#undef in_eval
@@ -325,6 +352,19 @@ typedef struct condpair {
#define Xpv (thr->TXpv)
#define statbuf (thr->Tstatbuf)
#define timesbuf (thr->Ttimesbuf)
+#define tainted (thr->Ttainted)
+#define tainted (thr->Ttainted)
+#define curpm (thr->Tcurpm)
+#define nrs (thr->Tnrs)
+#define rs (thr->Trs)
+#define last_in_gv (thr->Tlast_in_gv)
+#define ofs (thr->Tofs)
+#define ofslen (thr->Tofslen)
+#define defoutgv (thr->Tdefoutgv)
+#define chopset (thr->Tchopset)
+#define formtarget (thr->Tformtarget)
+#define bodytarget (thr->Tbodytarget)
+#define toptarget (thr->Ttoptarget)
#define defstash (thr->Tdefstash)
#define curstash (thr->Tcurstash)
diff --git a/toke.c b/toke.c
index f1b59003c7..b92edd3285 100644
--- a/toke.c
+++ b/toke.c
@@ -1243,16 +1243,21 @@ yylex(void)
(tokenbuf[1] == 'a' || tokenbuf[1] == 'b')
&& !tokenbuf[2])
{
- if (strnEQ(d,"<=>",3) || strnEQ(d,"cmp",3)) {
- croak("Can't use \"my %s\" in sort comparison",
- tokenbuf);
+ for (d = in_eval ? oldoldbufptr : linestart;
+ d < bufend && *d != '\n';
+ d++)
+ {
+ if (strnEQ(d,"<=>",3) || strnEQ(d,"cmp",3)) {
+ croak("Can't use \"my %s\" in sort comparison",
+ tokenbuf);
+ }
}
}
- }
- yylval.opval = newOP(OP_PADANY, 0);
- yylval.opval->op_targ = tmp;
- return PRIVATEREF;
+ yylval.opval = newOP(OP_PADANY, 0);
+ yylval.opval->op_targ = tmp;
+ return PRIVATEREF;
+ }
}
/* Force them to make up their mind on "@foo". */
@@ -5365,7 +5370,7 @@ yyerror(char *s)
if (in_eval & 2)
warn("%_", msg);
else if (in_eval)
- sv_catsv(GvSV(errgv), msg);
+ sv_catsv(errsv, msg);
else
PerlIO_write(PerlIO_stderr(), SvPVX(msg), SvCUR(msg));
if (++error_count >= 10)
diff --git a/util.c b/util.c
index 93f5620e2e..4ece7f1224 100644
--- a/util.c
+++ b/util.c
@@ -56,6 +56,10 @@
static void xstat _((void));
#endif
+#ifdef USE_THREADS
+static U32 threadnum = 0;
+#endif /* USE_THREADS */
+
#ifndef MYMALLOC
/* paranoid version of malloc */
@@ -2397,8 +2401,7 @@ condpair_magic(SV *sv)
* thread calling new_struct_thread) clearly satisfies this constraint.
*/
struct thread *
-new_struct_thread(t)
-struct thread *t;
+new_struct_thread(struct thread *t)
{
struct thread *thr;
SV *sv;
diff --git a/win32/makefile.mk b/win32/makefile.mk
index bad3e775ab..7f5dad30e3 100644
--- a/win32/makefile.mk
+++ b/win32/makefile.mk
@@ -11,7 +11,7 @@
# newly built perl.
INST_DRV=c:
INST_TOP=$(INST_DRV)\perl\perl5004.5X
-BUILDOPT=-DUSE_THREADS
+BUILDOPT=-DUSE_THREADS -P
# -DUSE_PERLIO -D__STDC__=1 -DUSE_SFIO -DI_SFIO -I\sfio97\include
@@ -63,7 +63,7 @@ IMPLIB = implib
RUNTIME = -D_RTLDLL
INCLUDES = -I.\include -I. -I.. -I$(CCINCDIR)
#PCHFLAGS = -H -H$(INTDIR)\bcmoduls.pch
-DEFINES = -DWIN32 $(BUILDOPT) -D_WIN32_WINNT=0x400
+DEFINES = -DWIN32 $(BUILDOPT)
LOCDEFS = -DPERLDLL
SUBSYS = console
LIBC = cw32mti.lib