# DB_File.pm -- Perl 5 interface to Berkeley DB
#
# written by Paul Marquess (pmarquess@bfsec.bt.co.uk)
-# last modified 30th Apr 1997
-# version 1.14
+# last modified 31st May 1997
+# version 1.15
#
# Copyright (c) 1995, 1996, 1997 Paul Marquess. All rights reserved.
# This program is free software; you can redistribute it and/or
use Carp;
-$VERSION = "1.14" ;
+$VERSION = "1.15" ;
#typedef enum { DB_BTREE, DB_HASH, DB_RECNO } DBTYPE;
$DB_BTREE = new DB_File::BTREEINFO ;
Made it illegal to tie an associative array to a RECNO database and an
ordinary array to a HASH or BTREE database.
+=item 1.15
+
+Minor changes to DB_File.xs to support multithreaded perl.
+
=back
=head1 BUGS
DB_File.xs -- Perl 5 interface to Berkeley DB
written by Paul Marquess (pmarquess@bfsec.bt.co.uk)
- last modified 30th Apr 1997
- version 1.14
+ last modified 31st May 1997
+ version 1.15
All comments/suggestions/problems are welcome
1.13 - Tidied up a few casts.
1.14 - Made it illegal to tie an associative array to a RECNO
database and an ordinary array to a HASH or BTREE database.
+ 1.15 - Minor additions to DB_File.xs to support multithreaded perl.
*/
const DBT * key1 ;
const DBT * key2 ;
{
+ dTHR ;
dSP ;
void * data1, * data2 ;
int retval ;
const DBT * key1 ;
const DBT * key2 ;
{
+ dTHR ;
dSP ;
void * data1, * data2 ;
int retval ;
const void * data ;
size_t size ;
{
+ dTHR ;
dSP ;
int retval ;
int count ;
NAME => 'Opcode',
MAN3PODS => ' ',
VERSION_FROM => 'Opcode.pm',
- XS_VERSION => '1.02'
+ XS_VERSION => '1.03'
);
use vars qw($VERSION $XS_VERSION @ISA @EXPORT_OK);
$VERSION = "1.04";
-$XS_VERSION = "1.02";
+$XS_VERSION = "1.03";
use strict;
use Carp;
op_named_bits = newHV();
for(i=0; i < maxo; ++i) {
- hv_store(op_named_bits, op_name[i],strlen(op_name[i]),
- Sv=newSViv(i), 0);
- SvREADONLY_on(Sv);
+ SV *sv;
+ sv = newSViv(i);
+ SvREADONLY_on(sv);
+ hv_store(op_named_bits, op_name[i], strlen(op_name[i]), sv, 0);
}
put_op_bitspec(":none",0, sv_2mortal(new_opset(Nullsv)));
gv_fetchfile(name)
char *name;
{
+ dTHR;
char smallbuf[256];
char *tmpbuf;
STRLEN tmplen;
basestash = gv_stashpvn(packname, packlen, TRUE);
gvp = (GV**)hv_fetch(basestash, "ISA", 3, FALSE);
if (gvp && (gv = *gvp) != (GV*)&sv_undef && (av = GvAV(gv))) {
+ dTHR; /* just for SvREFCNT_dec */
gvp = (GV**)hv_fetch(stash, "ISA", 3, TRUE);
if (!gvp || !(gv = *gvp))
croak("Cannot create %s::ISA", HvNAME(stash));
(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));
if (SvRMAGICAL(hv)) {
if (mg_find((SV*)hv,'P')) {
+ dTHR; /* just for SvTRUE */
sv = sv_newmortal();
keysv = sv_2mortal(newSVsv(keysv));
mg_copy((SV*)hv, sv, (char*)keysv, HEf_SVKEY);
}
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 */
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 */
targ = AvARRAY(av)[LvTARGOFF(sv)];
}
if (targ && targ != &sv_undef) {
+ dTHR; /* just for SvREFCNT_dec */
/* somebody else defined it for us */
SvREFCNT_dec(LvTARG(sv));
LvTARG(sv) = SvREFCNT_inc(targ);
vivify_defelem(sv)
SV* sv;
{
+ dTHR; /* just for SvREFCNT_inc and SvREFCNT_dec*/
MAGIC* mg;
SV* value;
{
dTHR;
#ifdef USE_THREADS
- MUTEX_DESTROY(CvMUTEXP(cv));
- Safefree(CvMUTEXP(cv));
+ if (CvMUTEXP(cv)) {
+ MUTEX_DESTROY(CvMUTEXP(cv));
+ Safefree(CvMUTEXP(cv));
+ CvMUTEXP(cv) = 0;
+ }
if (CvCONDP(cv)) {
COND_DESTROY(CvCONDP(cv));
Safefree(CvCONDP(cv));
+ CvCONDP(cv) = 0;
}
#endif /* USE_THREADS */
if (type == OP_CONST)
sv = cSVOPo->op_sv;
else if (type == OP_PADSV) {
- AV* pad = (AV*)(AvARRAY(CvPADLIST(cv))[1]);
- sv = pad ? AvARRAY(pad)[o->op_targ] : Nullsv;
+ AV* padav = (AV*)(AvARRAY(CvPADLIST(cv))[1]);
+ sv = padav ? AvARRAY(padav)[o->op_targ] : Nullsv;
if (!sv || (!SvREADONLY(sv) && SvREFCNT(sv) > 1))
return Nullsv;
}
o2 = newUNOP(OP_REFGEN, 0, kid);
o2->op_sibling = kid->op_sibling;
kid->op_sibling = 0;
- prev->op_sibling = o;
+ prev->op_sibling = o2;
}
break;
default: goto oops;
OP* pop = o->op_next->op_next;
IV i;
if (pop->op_type == OP_CONST &&
- (o = pop->op_next) &&
+ (op = pop->op_next) &&
pop->op_next->op_type == OP_AELEM &&
!(pop->op_next->op_private &
(OPpLVAL_INTRO|OPpLVAL_DEFER|OPpDEREF)) &&
main_cv = compcv = (CV*)NEWSV(1104,0);
sv_upgrade((SV *)compcv, SVt_PVCV);
CvUNIQUE_on(compcv);
-#ifdef USE_THREADS
- CvOWNER(compcv) = 0;
- New(666, CvMUTEXP(compcv), 1, pthread_mutex_t);
- MUTEX_INIT(CvMUTEXP(compcv));
- New(666, CvCONDP(compcv), 1, pthread_cond_t);
- COND_INIT(CvCONDP(compcv));
-#endif /* USE_THREADS */
comppad = newAV();
av_push(comppad, Nullsv);
curpad = AvARRAY(comppad);
comppad_name = newAV();
comppad_name_fill = 0;
+ min_intro_pending = 0;
+ padix = 0;
#ifdef USE_THREADS
av_store(comppad_name, 0, newSVpv("@_", 2));
+ curpad[0] = (SV*)newAV();
+ CvOWNER(compcv) = 0;
+ New(666, CvMUTEXP(compcv), 1, pthread_mutex_t);
+ MUTEX_INIT(CvMUTEXP(compcv));
+ New(666, CvCONDP(compcv), 1, pthread_cond_t);
+ COND_INIT(CvCONDP(compcv));
#endif /* USE_THREADS */
- min_intro_pending = 0;
- padix = 0;
comppadlist = newAV();
AvREAL_off(comppadlist);
char* p;
I32 croak_on_error;
{
+ dTHR;
dSP;
SV* sv = newSVpv(p, 0);
static void
nuke_stacks()
{
+ dTHR;
Safefree(cxstack);
Safefree(tmps_stack);
DEBUG( {
static void
my_exit_jump()
{
+ dTHR;
register CONTEXT *cx;
I32 gimme;
SV **newsp;
break;
case 56:
#line 291 "perly.y"
-{ char *name = SvPVx(((SVOP*)yyvsp[0].opval)->op_sv, na);
- if (strEQ(name, "BEGIN") || strEQ(name, "END"))
+{ char *name = SvPV(((SVOP*)yyvsp[0].opval)->op_sv, na);
+ if (strEQ(name, "BEGIN") || strEQ(name, "END")
+ || strEQ(name, "RESTART"))
CvUNIQUE_on(compcv);
yyval.opval = yyvsp[0].opval; }
break;
{ $$ = start_subparse(TRUE, 0); }
;
-subname : WORD { char *name = SvPVx(((SVOP*)$1)->op_sv, na);
- if (strEQ(name, "BEGIN") || strEQ(name, "END"))
+subname : WORD { char *name = SvPV(((SVOP*)$1)->op_sv, na);
+ if (strEQ(name, "BEGIN") || strEQ(name, "END")
+ || strEQ(name, "RESTART"))
CvUNIQUE_on(compcv);
$$ = $1; }
;
else if (SvPADTMP(sv))
sv = newSVsv(sv);
else {
+ dTHR; /* just for SvREFCNT_inc */
SvTEMP_off(sv);
(void)SvREFCNT_inc(sv);
}
#define SEED_C3 269
#define SEED_C5 26107
+ dTHR;
U32 u;
#ifdef VMS
# include <starlet.h>
docatch(o)
OP *o;
{
+ dTHR;
int ret;
I32 oldrunlevel = runlevel;
OP *oldop = op;
DEBUG_s(debstack());
DEBUG_t(debop(op));
DEBUG_P(debprof(op));
-#ifdef USE_THREADS
- DEBUG_L(YIELD()); /* shake up scheduling a bit */
-#endif /* USE_THREADS */
}
} while ( op = (*op->op_ppaddr)(ARGS) );
GV *gv;
I32 empty;
{
+ dTHR;
SSCHECK(3);
SSPUSHPTR(SvREFCNT_inc(gv));
SSPUSHPTR(GvGP(gv));
save_I16(intp)
I16 *intp;
{
+ dTHR;
SSCHECK(3);
SSPUSHINT(*intp);
SSPUSHPTR(intp);
if (SvPOKp(sv) && SvLEN(sv))
return asIV(sv);
if (!SvROK(sv)) {
+ dTHR; /* just for localizing */
if (dowarn && !localizing && !(SvFLAGS(sv) & SVs_PADTMP))
warn(warn_uninit);
return 0;
if (SvPOKp(sv) && SvLEN(sv))
return asUV(sv);
if (!SvROK(sv)) {
+ dTHR; /* just for localizing */
if (dowarn && !localizing && !(SvFLAGS(sv) & SVs_PADTMP))
warn(warn_uninit);
return 0;
SvUVX(sv) = asUV(sv);
}
else {
+ dTHR; /* just for localizing */
if (dowarn && !localizing && !(SvFLAGS(sv) & SVs_PADTMP))
warn(warn_uninit);
return 0;
if (SvIOKp(sv))
return (double)SvIVX(sv);
if (!SvROK(sv)) {
+ dTHR; /* just for localizing */
if (dowarn && !localizing && !(SvFLAGS(sv) & SVs_PADTMP))
warn(warn_uninit);
return 0;
goto tokensave;
}
if (!SvROK(sv)) {
+ dTHR; /* just for localizing */
if (dowarn && !localizing && !(SvFLAGS(sv) & SVs_PADTMP))
warn(warn_uninit);
*lp = 0;
if (name)
if (namlen >= 0)
mg->mg_ptr = savepvn(name, namlen);
- else if (namlen == HEf_SVKEY)
+ else if (namlen == HEf_SVKEY) {
+ dTHR; /* just for SvREFCNT_inc */
mg->mg_ptr = (char*)SvREFCNT_inc((SV*)name);
+ }
switch (how) {
case 0:
assert(SvREFCNT(sv) == 0);
if (SvOBJECT(sv)) {
+ dTHR;
if (defstash) { /* Still have a symbol table? */
dTHR;
dSP;
I32 svmax;
bool *used_locale;
{
+ dTHR;
char *p;
char *q;
char *patend;
long xcv_depth; /* >= 2 indicates recursive call */
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 */
+#endif /* USE_THREADS */
U8 xcv_flags;
I32 xfm_lines;
AV * Tstack;
AV * Tmainstack;
- Sigjmp_buf Ttop_env;
+ JMPENV * Ttop_env;
I32 Trunlevel;
/* XXX Sort stuff, firstgv, secongv and so on? */
nextval[nexttoke].opval = o;
force_next(WORD);
if (kind) {
+ dTHR; /* just for in_eval */
o->op_private = OPpCONST_ENTERED;
/* XXX see note in pp_entereval() for why we forgo typo
warnings if the symbol must be introduced in an eval.
sv = mess_sv;
sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*));
if (!SvCUR(sv) || *(SvEND(sv) - 1) != '\n') {
+ dTHR;
if (dirty)
sv_catpv(sv, dgd);
else {