--- ./Configure-pre	Thu Mar 20 22:13:56 2003
+++ ./Configure	Mon Mar 24 19:31:02 2003
@@ -71,11 +71,12 @@ esac
 : Proper separator for the PATH environment variable
 p_=:
 : On OS/2 this directory should exist if this is not floppy only system :-]
-if test -d c:/. ; then
+if test -d c:/. || ( uname -a | grep -i 'os\(/\|\)2' ) 2>&1 >/dev/null ; then
     if test -n "$OS2_SHELL"; then
 		p_=\;
 		PATH=`cmd /c "echo %PATH%" | tr '\\\\' / `
 		OS2_SHELL=`cmd /c "echo %OS2_SHELL%" | tr '\\\\' / | tr '[A-Z]' '[a-z]'`
+		is_os2=yes
 	elif test -n "$DJGPP"; then
 		case "X${MACHTYPE:-nonesuchmach}" in
 		*cygwin) ;;
@@ -1195,7 +1196,7 @@ elif test -f "/system/gnu_library/bin/ar
 elif test -n "$DJGPP"; then
 : DOS DJGPP
     _exe=".exe"
-elif test -d c:/. ; then
+elif test -d c:/. -o -n "$is_os2" ; then
 : OS/2 or cygwin
     _exe=".exe"
 fi
@@ -3137,6 +3138,9 @@ EOM
 		openbsd) osname=openbsd
                 	osvers="$3"
                 	;;
+		os2)	osname=os2
+			osvers="$4"
+			;;
 		POSIX-BC | posix-bc ) osname=posix-bc
 			osvers="$3"
 			;;
@@ -3255,7 +3259,7 @@ EOM
 				osname=news_os
 			fi
 			$rm -f UU/kernel.what
-		elif test -d c:/.; then
+		elif test -d c:/. -o -n "$is_os2" ; then
 			set X $myuname
 			osname=os2
 			osvers="$5"
@@ -4978,6 +4982,7 @@ echo "Your cpp writes the filename in th
 
 case "$osname" in
 vos) cppfilter="tr '\\\\>' '/' |" ;; # path component separator is >
+os2) cppfilter="sed -e 's|\\\\\\\\|/|g' |" ;; # path component separator is \
 *)   cppfilter='' ;;
 esac
 : locate header file
--- ./intrpvar.h-pre	Tue Mar 11 11:04:22 2003
+++ ./intrpvar.h	Mon Mar 24 18:54:10 2003
@@ -248,7 +248,10 @@ PERLVAR(Iorigalen,	U32)
 PERLVAR(Ipidstatus,	HV *)		/* pid-to-status mappings for waitpid */
 PERLVARI(Imaxo,	int,	MAXO)		/* maximum number of ops */
 PERLVAR(Iosname,	char *)		/* operating system */
-PERLVARI(Ish_path,	char *,	SH_PATH)/* full path of shell */
+
+/* For binary compatibility with older versions only */
+PERLVARI(Ish_path_compat,	char *,	SH_PATH)/* full path of shell */
+
 PERLVAR(Isighandlerp,	Sighandler_t)
 
 PERLVAR(Ixiv_arenaroot,	XPV*)		/* list of allocated xiv areas */
--- ./makedef.pl-pre	Mon Mar 10 14:11:18 2003
+++ ./makedef.pl	Wed Mar 26 18:13:28 2003
@@ -6,13 +6,20 @@
 # and by MacOS Classic.
 #
 # reads global.sym, pp.sym, perlvars.h, intrpvar.h, thrdvar.h, config.h
-# On OS/2 reads miniperl.map as well
+# On OS/2 reads miniperl.map and the previous version of perl5.def as well
 
 my $PLATFORM;
 my $CCTYPE;
 
 while (@ARGV) {
     my $flag = shift;
+    if ($flag =~ s/^CC_FLAGS=/ /) {
+	for my $fflag ($flag =~ /(?:^|\s)-D(\S+)/g) {
+	    $fflag     .= '=1' unless $fflag =~ /^(\w+)=/;
+	    $define{$1} = $2   if $fflag =~ /^(\w+)=(.+)$/;
+	}
+	next;
+    }
     $define{$1} = 1 if ($flag =~ /^-D(\w+)$/);
     $define{$1} = $2 if ($flag =~ /^-D(\w+)=(.+)$/);
     $CCTYPE   = $1 if ($flag =~ /^CCTYPE=(\w+)$/);
@@ -418,7 +425,14 @@ elsif ($PLATFORM eq 'os2') {
 		    os2error
 		    ResetWinError
 		    CroakWinError
+		    PL_do_undump
 		    )]);
+    emit_symbols([qw(os2_cond_wait
+		     pthread_join
+		     pthread_create
+		     pthread_detach
+		    )])
+      if $define{'USE_5005THREADS'} or $define{'USE_ITHREADS'};
 }
 elsif ($PLATFORM eq 'MacOS') {
     skip_symbols [qw(
@@ -526,7 +540,7 @@ elsif ($PLATFORM eq 'netware') {
 			)];
 }
 
-unless ($define{'DEBUGGING'}) {
+unless ($define{'DEBUGGING'} or $ENV{DO_DEBUGGING}) {
     skip_symbols [qw(
 		    Perl_deb_growlevel
 		    Perl_debop
@@ -947,7 +961,7 @@ if ($define{'MULTIPLICITY'}) {
 	emit_symbols $glob;
     }
     # XXX AIX seems to want the perlvars.h symbols, for some reason
-    if ($PLATFORM eq 'aix') {
+    if ($PLATFORM eq 'aix' or $PLATFORM eq 'os2') {	# OS/2 needs PL_thr_key
 	my $glob = readvar($perlvars_h);
 	emit_symbols $glob;
     }
--- ./Makefile.SH-pre	Sun Mar  9 07:13:12 2003
+++ ./Makefile.SH	Wed Mar 26 17:35:22 2003
@@ -450,7 +450,7 @@ PERLEXPORT		= perl.exp
 	esac
 	$spitshell >>Makefile <<'!NO!SUBS!'
 perl.exp: $(MINIPERLEXP) makedef.pl config.sh $(SYM) $(SYMH)
-	./$(MINIPERLEXP) makedef.pl PLATFORM=aix | sort -u | sort -f > perl.exp.tmp
+	./$(MINIPERLEXP) makedef.pl PLATFORM=aix CC_FLAGS="$(OPTIMIZE)" | sort -u | sort -f > perl.exp.tmp
 	sh mv-if-diff perl.exp.tmp perl.exp
 
 !NO!SUBS!
@@ -460,7 +460,7 @@ os2)
 MINIPERLEXP		= miniperl
 
 perl5.def: $(MINIPERLEXP) makedef.pl config.sh $(SYM) $(SYMH) miniperl.map
-	./$(MINIPERLEXP) makedef.pl PLATFORM=os2 -DPERL_DLL=$(PERL_DLL) > perl.exp.tmp
+	./$(MINIPERLEXP) makedef.pl PLATFORM=os2 -DPERL_DLL=$(PERL_DLL) CC_FLAGS="$(OPTIMIZE)" > perl.exp.tmp
 	sh mv-if-diff perl.exp.tmp perl5.def
 
 !NO!SUBS!
--- ./malloc.c-pre	Sun Nov  3 22:34:38 2002
+++ ./malloc.c	Sat Mar 29 20:18:52 2003
@@ -27,9 +27,12 @@
   options take a precise value, while the others are just boolean.
   The boolean ones are listed first.
 
+    # Read configuration settings from malloc_cfg.h
+    HAVE_MALLOC_CFG_H		undef
+
     # Enable code for an emergency memory pool in $^M.  See perlvar.pod
     # for a description of $^M.
-    PERL_EMERGENCY_SBRK		(!PLAIN_MALLOC && PERL_CORE)
+    PERL_EMERGENCY_SBRK		(!PLAIN_MALLOC && (PERL_CORE || !NO_MALLOC_DYNAMIC_CFG))
 
     # Enable code for printing memory statistics.
     DEBUGGING_MSTATS		(!PLAIN_MALLOC && PERL_CORE)
@@ -78,6 +81,22 @@
     # pessimization, error reporting optimization
     RCHECK			(DEBUGGING && !NO_RCHECK)
 
+    # Do not overwrite uninit areas with DEBUGGING.  Speed
+    # optimization, error reporting pessimization
+    NO_MFILL			undef
+
+    # Overwrite uninit areas with DEBUGGING.  Speed
+    # pessimization, error reporting optimization
+    MALLOC_FILL			(DEBUGGING && !NO_RCHECK && !NO_MFILL)
+
+    # Do not check overwritten uninit areas with DEBUGGING.  Speed
+    # optimization, error reporting pessimization
+    NO_FILL_CHECK		undef
+
+    # Check overwritten uninit areas with DEBUGGING.  Speed
+    # pessimization, error reporting optimization
+    MALLOC_FILL_CHECK		(DEBUGGING && !NO_RCHECK && !NO_FILL_CHECK)
+
     # Failed allocations bigger than this size croak (if
     # PERL_EMERGENCY_SBRK is enabled) without touching $^M.  See
     # perlvar.pod for a description of $^M.
@@ -98,6 +117,9 @@
     # Round up sbrk()s to multiples of this percent of footprint.
     MIN_SBRK_FRAC 		3
 
+    # Round up sbrk()s to multiples of this multiple of 1/1000 of footprint.
+    MIN_SBRK_FRAC1000 		(10 * MIN_SBRK_FRAC)
+
     # Add this much memory to big powers of two to get the bucket size.
     PERL_PAGESIZE 		4096
 
@@ -114,6 +136,12 @@
     # define this to disable 12-byte bucket (will increase memory footprint)
     STRICT_ALIGNMENT		undef
 
+    # Do not allow configuration of runtime options at runtime
+    NO_MALLOC_DYNAMIC_CFG	undef
+
+    # Do not allow configuration of runtime options via $ENV{PERL_MALLOC_OPT}
+    NO_PERL_MALLOC_ENV		undef
+
   This implementation assumes that calling PerlIO_printf() does not
   result in any memory allocation calls (used during a panic).
 
@@ -168,6 +196,10 @@
      MUTEX_UNLOCK(l)			void
  */
 
+#ifdef HAVE_MALLOC_CFG_H
+#  include "malloc_cfg.h"
+#endif
+
 #ifndef NO_FANCY_MALLOC
 #  ifndef SMALL_BUCKET_VIA_TABLE
 #    define SMALL_BUCKET_VIA_TABLE
@@ -187,7 +219,7 @@
 #  ifndef TWO_POT_OPTIMIZE
 #    define TWO_POT_OPTIMIZE
 #  endif 
-#  if defined(PERL_CORE) && !defined(PERL_EMERGENCY_SBRK)
+#  if (defined(PERL_CORE) || !defined(NO_MALLOC_DYNAMIC_CFG)) && !defined(PERL_EMERGENCY_SBRK)
 #    define PERL_EMERGENCY_SBRK
 #  endif 
 #  if defined(PERL_CORE) && !defined(DEBUGGING_MSTATS)
@@ -211,6 +243,12 @@
 #  if defined(DEBUGGING) && !defined(NO_RCHECK)
 #    define RCHECK
 #  endif
+#  if defined(DEBUGGING) && !defined(NO_RCHECK) && !defined(NO_MFILL) && !defined(MALLOC_FILL)
+#    define MALLOC_FILL
+#  endif
+#  if defined(DEBUGGING) && !defined(NO_RCHECK) && !defined(NO_FILL_CHECK) && !defined(MALLOC_FILL_CHECK)
+#    define MALLOC_FILL_CHECK
+#  endif
 #  if defined(RCHECK) && defined(IGNORE_SMALL_BAD_FREE)
 #    undef IGNORE_SMALL_BAD_FREE
 #  endif 
@@ -251,6 +289,11 @@
 #    define croak2	croak
 #    define warn2	warn
 #  endif
+#  if defined(USE_5005THREADS) || defined(USE_ITHREADS)
+#     define PERL_MAYBE_ALIVE	PL_thr_key
+#  else
+#     define PERL_MAYBE_ALIVE	1
+#  endif
 #else
 #  ifdef PERL_FOR_X2P
 #    include "../EXTERN.h"
@@ -317,6 +360,7 @@
 #  ifndef PERL_GET_INTERP
 #     define PERL_GET_INTERP	PL_curinterp
 #  endif
+#  define PERL_MAYBE_ALIVE	1
 #  ifndef Perl_malloc
 #     define Perl_malloc malloc
 #  endif
@@ -358,7 +402,7 @@
 #  undef DEBUG_m
 #  define DEBUG_m(a) 							\
     STMT_START {							\
-	if (PERL_GET_INTERP) {						\
+	if (PERL_MAYBE_ALIVE && PERL_GET_THX) {						\
 	    dTHX;							\
 	    if (DEBUG_m_TEST) {						\
 		PL_debug &= ~DEBUG_m_FLAG;				\
@@ -480,7 +524,7 @@ union	overhead {
 		u_char	ovu_index;	/* bucket # */
 		u_char	ovu_magic;	/* magic number */
 #ifdef RCHECK
-		u_short	ovu_size;	/* actual block size */
+		u_short	ovu_size;	/* block size (requested + overhead - 1) */
 		u_int	ovu_rmagic;	/* range magic number */
 #endif
 	} ovu;
@@ -497,7 +541,7 @@ union	overhead {
 #ifdef RCHECK
 #  define	RSLOP		sizeof (u_int)
 #  ifdef TWO_POT_OPTIMIZE
-#    define MAX_SHORT_BUCKET (12 * BUCKETS_PER_POW2)
+#    define MAX_SHORT_BUCKET (12 * BUCKETS_PER_POW2) /* size-1 fits in short */
 #  else
 #    define MAX_SHORT_BUCKET (13 * BUCKETS_PER_POW2)
 #  endif 
@@ -908,6 +952,87 @@ extern	Malloc_t sbrk(int);
 # endif
 #endif
 
+#ifndef MIN_SBRK_FRAC1000	/* Backward compatibility */
+#  define MIN_SBRK_FRAC1000	(MIN_SBRK_FRAC * 10)
+#endif
+
+#ifndef NO_MALLOC_DYNAMIC_CFG
+#define PERL_MALLOC_OPT_CHARS "FMfAPGdac"
+enum {
+  MallocCfg_FIRST_SBRK,
+  MallocCfg_MIN_SBRK,
+  MallocCfg_MIN_SBRK_FRAC1000,
+  MallocCfg_SBRK_ALLOW_FAILURES,
+  MallocCfg_SBRK_FAILURE_PRICE,
+  MallocCfg_sbrk_goodness,
+
+  MallocCfg_filldead,
+  MallocCfg_fillalive,
+  MallocCfg_fillcheck,
+
+  MallocCfg_emergency_buffer,
+  MallocCfg_emergency_buffer_size,
+  MallocCfg_emergency_buffer_last_req,
+
+  MallocCfg_emergency_buffer_prepared,
+  MallocCfg_emergency_buffer_prepared_size,
+
+  MallocCfg_last
+};
+
+IV MallocCfg[MallocCfg_last] = {
+  FIRST_SBRK,
+  MIN_SBRK,
+  MIN_SBRK_FRAC,
+  SBRK_ALLOW_FAILURES,
+  SBRK_FAILURE_PRICE,
+  SBRK_ALLOW_FAILURES * SBRK_FAILURE_PRICE,	/* sbrk_goodness */
+  1,			/* FILL_DEAD */
+  1,			/* FILL_ALIVE */
+  1,			/* FILL_CHECK */
+  0,			/* MallocCfg_emergency_buffer */
+  0,			/* MallocCfg_emergency_buffer_prepared */
+  0,			/* MallocCfg_emergency_buffer_size */
+  0,			/* MallocCfg_emergency_buffer_prepared_size */
+  0			/* MallocCfg_emergency_buffer_last_req */
+};
+extern IV *MallocCfg_ptr;
+IV *MallocCfg_ptr = MallocCfg;
+
+#  undef MIN_SBRK
+#  undef FIRST_SBRK
+#  undef MIN_SBRK_FRAC1000
+#  undef SBRK_ALLOW_FAILURES
+#  undef SBRK_FAILURE_PRICE
+
+#  define MIN_SBRK		MallocCfg[MallocCfg_MIN_SBRK]
+#  define FIRST_SBRK		MallocCfg[MallocCfg_FIRST_SBRK]
+#  define MIN_SBRK_FRAC1000	MallocCfg[MallocCfg_MIN_SBRK_FRAC1000]
+#  define SBRK_ALLOW_FAILURES	MallocCfg[MallocCfg_SBRK_ALLOW_FAILURES]
+#  define SBRK_FAILURE_PRICE	MallocCfg[MallocCfg_SBRK_FAILURE_PRICE]
+
+#  define sbrk_goodness		MallocCfg[MallocCfg_sbrk_goodness]
+
+#  define emergency_buffer	((char*)MallocCfg[MallocCfg_emergency_buffer])
+#  define emergency_buffer_size	MallocCfg[MallocCfg_emergency_buffer_size]
+#  define emergency_buffer_last_req	MallocCfg[MallocCfg_emergency_buffer_last_req]
+
+#  define FILL_DEAD		MallocCfg[MallocCfg_filldead]
+#  define FILL_ALIVE		MallocCfg[MallocCfg_fillalive]
+#  define FILL_CHECK_		MallocCfg[MallocCfg_fillcheck]
+#  define FILL_CHECK		(FILL_DEAD && FILL_CHECK_)
+
+#else	/* defined(NO_MALLOC_DYNAMIC_CFG) */
+
+#  define FILL_DEAD	1
+#  define FILL_ALIVE	1
+#  define FILL_CHECK	1
+static int sbrk_goodness = SBRK_ALLOW_FAILURES * SBRK_FAILURE_PRICE;
+
+#  define NO_PERL_MALLOC_ENV
+
+#endif
+
 #ifdef DEBUGGING_MSTATS
 /*
  * nmalloc[i] is the difference between the number of mallocs and frees
@@ -928,21 +1053,99 @@ static	u_int goodsbrk;
 #    define BIG_SIZE (1<<16)		/* 64K */
 #  endif
 
+#  ifdef NO_MALLOC_DYNAMIC_CFG
 static char *emergency_buffer;
 static MEM_SIZE emergency_buffer_size;
-static MEM_SIZE no_mem;	/* 0 if the last request for more memory succeeded.
-			   Otherwise the size of the failing request. */
+	/* 0 if the last request for more memory succeeded.
+	   Otherwise the size of the failing request. */
+static MEM_SIZE emergency_buffer_last_req;
+#  endif
+
+#  ifndef emergency_sbrk_croak
+#    define emergency_sbrk_croak	croak2
+#  endif
+
+#  ifdef PERL_CORE
+static char *
+perl_get_emergency_buffer(IV *size)
+{
+    dTHX;
+    /* First offense, give a possibility to recover by dieing. */
+    /* No malloc involved here: */
+    GV **gvp = (GV**)hv_fetch(PL_defstash, "^M", 2, 0);
+    SV *sv;
+    char *pv;
+    STRLEN n_a;
+
+    if (!gvp) gvp = (GV**)hv_fetch(PL_defstash, "\015", 1, 0);
+    if (!gvp || !(sv = GvSV(*gvp)) || !SvPOK(sv) 
+        || (SvLEN(sv) < (1<<LOG_OF_MIN_ARENA) - M_OVERHEAD))
+        return NULL;		/* Now die die die... */
+    /* Got it, now detach SvPV: */
+    pv = SvPV(sv, n_a);
+    /* Check alignment: */
+    if ((PTR2UV(pv) - sizeof(union overhead)) & (NEEDED_ALIGNMENT - 1)) {
+        PerlIO_puts(PerlIO_stderr(),"Bad alignment of $^M!\n");
+        return NULL;		/* die die die */
+    }
+
+    SvPOK_off(sv);
+    SvPVX(sv) = Nullch;
+    SvCUR(sv) = SvLEN(sv) = 0;
+    *size = malloced_size(pv) + M_OVERHEAD;
+    return pv - sizeof(union overhead);
+}
+#    define PERL_GET_EMERGENCY_BUFFER(p)	perl_get_emergency_buffer(p)
+#  else
+#    define PERL_GET_EMERGENCY_BUFFER(p)	NULL
+#  endif
+
+#  ifndef NO_MALLOC_DYNAMIC_CFG
+static char *
+get_emergency_buffer(IV *size)
+{
+    char *pv = (char*)MallocCfg[MallocCfg_emergency_buffer_prepared];
+
+    *size = MallocCfg[MallocCfg_emergency_buffer_prepared_size];
+    MallocCfg[MallocCfg_emergency_buffer_prepared] = 0;
+    MallocCfg[MallocCfg_emergency_buffer_prepared_size] = 0;
+    return pv;
+}
+
+/* Returns 0 on success, -1 on bad alignment, -2 if not implemented */
+int
+set_emergency_buffer(char *b, IV size)
+{
+    if (PTR2UV(b) & (NEEDED_ALIGNMENT - 1))
+	return -1;
+    if (MallocCfg[MallocCfg_emergency_buffer_prepared_size])
+	add_to_chain((void*)MallocCfg[MallocCfg_emergency_buffer_prepared],
+		     MallocCfg[MallocCfg_emergency_buffer_prepared_size], 0);
+    MallocCfg[MallocCfg_emergency_buffer_prepared] = PTR2UV(b);
+    MallocCfg[MallocCfg_emergency_buffer_prepared_size] = size;
+    return 0;
+}
+#    define GET_EMERGENCY_BUFFER(p)	get_emergency_buffer(p)
+#  else		/* NO_MALLOC_DYNAMIC_CFG */
+#    define GET_EMERGENCY_BUFFER(p)	NULL
+int
+set_emergency_buffer(char *b, IV size)
+{
+    return -1;
+}
+#  endif
 
 static Malloc_t
 emergency_sbrk(MEM_SIZE size)
 {
     MEM_SIZE rsize = (((size - 1)>>LOG_OF_MIN_ARENA) + 1)<<LOG_OF_MIN_ARENA;
 
-    if (size >= BIG_SIZE && (!no_mem || (size < no_mem))) {
+    if (size >= BIG_SIZE
+	&& (!emergency_buffer_last_req || (size < emergency_buffer_last_req))) {
 	/* Give the possibility to recover, but avoid an infinite cycle. */
 	MALLOC_UNLOCK;
-	no_mem = size;
-	croak2("Out of memory during \"large\" request for %"UVuf" bytes, total sbrk() is %"UVuf" bytes", (UV)size, (UV)(goodsbrk + sbrk_slack));
+	emergency_buffer_last_req = size;
+	emergency_sbrk_croak("Out of memory during \"large\" request for %"UVuf" bytes, total sbrk() is %"UVuf" bytes", (UV)size, (UV)(goodsbrk + sbrk_slack));
     }
 
     if (emergency_buffer_size >= rsize) {
@@ -952,14 +1155,11 @@ emergency_sbrk(MEM_SIZE size)
 	emergency_buffer += rsize;
 	return old;
     } else {		
-	dTHX;
 	/* First offense, give a possibility to recover by dieing. */
 	/* No malloc involved here: */
-	GV **gvp = (GV**)hv_fetch(PL_defstash, "^M", 2, 0);
-	SV *sv;
-	char *pv;
+	IV Size;
+	char *pv = GET_EMERGENCY_BUFFER(&Size);
 	int have = 0;
-	STRLEN n_a;
 
 	if (emergency_buffer_size) {
 	    add_to_chain(emergency_buffer, emergency_buffer_size, 0);
@@ -967,30 +1167,29 @@ emergency_sbrk(MEM_SIZE size)
 	    emergency_buffer = Nullch;
 	    have = 1;
 	}
-	if (!gvp) gvp = (GV**)hv_fetch(PL_defstash, "\015", 1, 0);
-	if (!gvp || !(sv = GvSV(*gvp)) || !SvPOK(sv) 
-	    || (SvLEN(sv) < (1<<LOG_OF_MIN_ARENA) - M_OVERHEAD)) {
+
+	if (!pv)
+	    pv = PERL_GET_EMERGENCY_BUFFER(&Size);
+	if (!pv) {
 	    if (have)
 		goto do_croak;
 	    return (char *)-1;		/* Now die die die... */
 	}
-	/* Got it, now detach SvPV: */
-	pv = SvPV(sv, n_a);
+
 	/* Check alignment: */
-	if ((PTR2UV(pv) - sizeof(union overhead)) & (NEEDED_ALIGNMENT - 1)) {
+	if (PTR2UV(pv) & (NEEDED_ALIGNMENT - 1)) {
+	    dTHX;
+
 	    PerlIO_puts(PerlIO_stderr(),"Bad alignment of $^M!\n");
 	    return (char *)-1;		/* die die die */
 	}
 
-	emergency_buffer = pv - sizeof(union overhead);
-	emergency_buffer_size = malloced_size(pv) + M_OVERHEAD;
-	SvPOK_off(sv);
-	SvPVX(sv) = Nullch;
-	SvCUR(sv) = SvLEN(sv) = 0;
+	emergency_buffer = pv;
+	emergency_buffer_size = Size;
     }
   do_croak:
     MALLOC_UNLOCK;
-    croak("Out of memory during request for %"UVuf" bytes, total sbrk() is %"UVuf" bytes", (UV)size, (UV)(goodsbrk + sbrk_slack));
+    emergency_sbrk_croak("Out of memory during request for %"UVuf" bytes, total sbrk() is %"UVuf" bytes", (UV)size, (UV)(goodsbrk + sbrk_slack));
     /* NOTREACHED */
     return Nullch;
 }
@@ -1000,20 +1199,115 @@ emergency_sbrk(MEM_SIZE size)
 # endif
 #endif /* ifdef PERL_CORE */
 
+static void
+write2(char *mess)
+{
+  write(2, mess, strlen(mess));
+}
+
 #ifdef DEBUGGING
 #undef ASSERT
 #define	ASSERT(p,diag)   if (!(p)) botch(diag,STRINGIFY(p));  else
 static void
 botch(char *diag, char *s)
 {
+    if (!(PERL_MAYBE_ALIVE && PERL_GET_THX))
+	goto do_write;
+    else {
 	dTHX;
-	PerlIO_printf(PerlIO_stderr(), "assertion botched (%s?): %s\n", diag, s);
+
+	if (PerlIO_printf(PerlIO_stderr(),
+			  "assertion botched (%s?): %s\n", diag, s) != 0) {
+	 do_write:		/* Can be initializing interpreter */
+	    write2("assertion botched (");
+	    write2(diag);
+	    write2("?): ");
+	    write2(s);
+	    write2("\n");
+	}
 	PerlProc_abort();
+    }
 }
 #else
 #define	ASSERT(p, diag)
 #endif
 
+#ifdef MALLOC_FILL
+/* Fill should be long enough to cover long */
+static void
+fill_pat_4bytes(unsigned char *s, size_t nbytes, const unsigned char *fill)
+{
+    unsigned char *e = s + nbytes;
+    long *lp;
+    long lfill = *(long*)fill;
+
+    if (PTR2UV(s) & (sizeof(long)-1)) {		/* Align the pattern */
+	int shift = sizeof(long) - (PTR2UV(s) & (sizeof(long)-1));
+	unsigned const char *f = fill + sizeof(long) - shift;
+	unsigned char *e1 = s + shift;
+
+	while (s < e1)
+	    *s++ = *f++;
+    }
+    lp = (long*)s;
+    while ((unsigned char*)(lp + 1) <= e)
+	*lp++ = lfill;
+    s = (unsigned char*)lp;
+    while (s < e)
+	*s++ = *fill++;
+}
+/* Just malloc()ed */
+static const unsigned char fill_feedadad[] =
+ {0xFE, 0xED, 0xAD, 0xAD, 0xFE, 0xED, 0xAD, 0xAD,
+  0xFE, 0xED, 0xAD, 0xAD, 0xFE, 0xED, 0xAD, 0xAD};
+/* Just free()ed */
+static const unsigned char fill_deadbeef[] =
+ {0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF,
+  0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF};
+#  define FILL_DEADBEEF(s, n)	\
+	(void)(FILL_DEAD?  (fill_pat_4bytes((s), (n), fill_deadbeef), 0) : 0)
+#  define FILL_FEEDADAD(s, n)	\
+	(void)(FILL_ALIVE? (fill_pat_4bytes((s), (n), fill_feedadad), 0) : 0)
+#else
+#  define FILL_DEADBEEF(s, n)	((void)0)
+#  define FILL_FEEDADAD(s, n)	((void)0)
+#  undef MALLOC_FILL_CHECK
+#endif
+
+#ifdef MALLOC_FILL_CHECK
+static int
+cmp_pat_4bytes(unsigned char *s, size_t nbytes, const unsigned char *fill)
+{
+    unsigned char *e = s + nbytes;
+    long *lp;
+    long lfill = *(long*)fill;
+
+    if (PTR2UV(s) & (sizeof(long)-1)) {		/* Align the pattern */
+	int shift = sizeof(long) - (PTR2UV(s) & (sizeof(long)-1));
+	unsigned const char *f = fill + sizeof(long) - shift;
+	unsigned char *e1 = s + shift;
+
+	while (s < e1)
+	    if (*s++ != *f++)
+		return 1;
+    }
+    lp = (long*)s;
+    while ((unsigned char*)(lp + 1) <= e)
+	if (*lp++ != lfill)
+	    return 1;
+    s = (unsigned char*)lp;
+    while (s < e)
+	if (*s++ != *fill++)
+	    return 1;
+    return 0;
+}
+#  define FILLCHECK_DEADBEEF(s, n)					\
+	ASSERT(!FILL_CHECK || !cmp_pat_4bytes(s, n, fill_deadbeef),	\
+	       "free()ed/realloc()ed-away memory was overwritten")
+#else
+#  define FILLCHECK_DEADBEEF(s, n)	((void)0)
+#endif
+
 Malloc_t
 Perl_malloc(register size_t nbytes)
 {
@@ -1135,6 +1429,9 @@ Perl_malloc(register size_t nbytes)
 			      PTR2UV((Malloc_t)(p + CHUNK_SHIFT)), (unsigned long)(PL_an++),
 			      (long)size));
 
+	FILLCHECK_DEADBEEF((unsigned char*)(p + CHUNK_SHIFT),
+			   BUCKET_SIZE_REAL(bucket));
+
 #ifdef IGNORE_SMALL_BAD_FREE
 	if (bucket >= FIRST_BUCKET_WITH_CHECK)
 #endif 
@@ -1161,6 +1458,7 @@ Perl_malloc(register size_t nbytes)
 	    nbytes = (nbytes + 3) &~ 3; 
 	    *((u_int *)((caddr_t)p + nbytes - RSLOP)) = RMAGIC;
 	}
+	FILL_FEEDADAD((unsigned char *)(p + CHUNK_SHIFT), size);
 #endif
   	return ((Malloc_t)(p + CHUNK_SHIFT));
 }
@@ -1168,7 +1466,6 @@ Perl_malloc(register size_t nbytes)
 static char *last_sbrk_top;
 static char *last_op;			/* This arena can be easily extended. */
 static MEM_SIZE sbrked_remains;
-static int sbrk_good = SBRK_ALLOW_FAILURES * SBRK_FAILURE_PRICE;
 
 #ifdef DEBUGGING_MSTATS
 static int sbrks;
@@ -1274,13 +1571,13 @@ getpages(MEM_SIZE needed, int *nblksp, i
     union overhead *ovp;
     MEM_SIZE slack = 0;
 
-    if (sbrk_good > 0) {
+    if (sbrk_goodness > 0) {
 	if (!last_sbrk_top && require < FIRST_SBRK) 
 	    require = FIRST_SBRK;
 	else if (require < MIN_SBRK) require = MIN_SBRK;
 
-	if (require < goodsbrk * MIN_SBRK_FRAC / 100)
-	    require = goodsbrk * MIN_SBRK_FRAC / 100;
+	if (require < goodsbrk * MIN_SBRK_FRAC1000 / 1000)
+	    require = goodsbrk * MIN_SBRK_FRAC1000 / 1000;
 	require = ((require - 1 + MIN_SBRK) / MIN_SBRK) * MIN_SBRK;
     } else {
 	require = needed;
@@ -1297,7 +1594,7 @@ getpages(MEM_SIZE needed, int *nblksp, i
 #endif 
     if (cp == last_sbrk_top) {
 	/* Common case, anything is fine. */
-	sbrk_good++;
+	sbrk_goodness++;
 	ovp = (union overhead *) (cp - sbrked_remains);
 	last_op = cp - sbrked_remains;
 	sbrked_remains = require - (needed - sbrked_remains);
@@ -1369,7 +1666,7 @@ getpages(MEM_SIZE needed, int *nblksp, i
 		    if (cp == (char *)-1)
 			return 0;
 		}
-		sbrk_good = -1;	/* Disable optimization!
+		sbrk_goodness = -1;	/* Disable optimization!
 				   Continue with not-aligned... */
 	    } else {
 		cp += slack;
@@ -1378,7 +1675,7 @@ getpages(MEM_SIZE needed, int *nblksp, i
 	}
 
 	if (last_sbrk_top) {
-	    sbrk_good -= SBRK_FAILURE_PRICE;
+	    sbrk_goodness -= SBRK_FAILURE_PRICE;
 	}
 
 	ovp = (union overhead *) cp;
@@ -1411,7 +1708,7 @@ getpages(MEM_SIZE needed, int *nblksp, i
 	last_op = cp;
     }
 #if !defined(PLAIN_MALLOC) && !defined(NO_FANCY_MALLOC)
-    no_mem = 0;
+    emergency_buffer_last_req = 0;
 #endif
     last_sbrk_top = cp + require;
 #ifdef DEBUGGING_MSTATS
@@ -1450,7 +1747,7 @@ getpages_adjacent(MEM_SIZE require)
 		add_to_chain((void*)(last_sbrk_top - sbrked_remains),
 			     sbrked_remains, 0);
 	    add_to_chain((void*)cp, require, 0);
-	    sbrk_good -= SBRK_FAILURE_PRICE;
+	    sbrk_goodness -= SBRK_FAILURE_PRICE;
 	    sbrked_remains = 0;
 	    last_sbrk_top = 0;
 	    last_op = 0;
@@ -1471,9 +1768,39 @@ morecore(register int bucket)
   	register int rnu;       /* 2^rnu bytes will be requested */
   	int nblks;		/* become nblks blocks of the desired size */
 	register MEM_SIZE siz, needed;
+	static int were_called = 0;
 
   	if (nextf[bucket])
   		return;
+#ifndef NO_PERL_MALLOC_ENV
+	if (!were_called) {
+	    /* It's the our first time.  Initialize ourselves */
+	    were_called = 1;	/* Avoid a loop */
+	    {
+		char *s = getenv("PERL_MALLOC_OPT"), *t = s, *off;
+		const char *opts = PERL_MALLOC_OPT_CHARS;
+
+		while ( t && t[0] && t[1] == '='
+			&& ((off = strchr(opts, *t))) ) {
+		    IV val = 0;
+
+		    t += 2;
+		    while (*t <= '9' && *t >= '0')
+			val = 10*val + *t++ - '0';
+		    if (!*t || *t == ';') {
+			MallocCfg[off - opts] = val;
+			if (*t)
+			    t++;
+		    }
+		}
+		if (t && *t) {
+		    write2("Unrecognized part of PERL_MALLOC_OPT: `");
+		    write2(t);
+		    write2("'\n");
+		}
+	    }
+	}
+#endif
 	if (bucket == sizeof(MEM_SIZE)*8*BUCKETS_PER_POW2) {
 	    MALLOC_UNLOCK;
 	    croak("%s", "Out of memory during ridiculously large request");
@@ -1518,6 +1845,7 @@ morecore(register int bucket)
 
 	if (!ovp)
 	    return;
+	FILL_DEADBEEF((unsigned char*)ovp, needed);
 
 	/*
 	 * Add new memory allocated to that on
@@ -1544,6 +1872,7 @@ morecore(register int bucket)
 	    start_slack += M_OVERHEAD * nblks;
 	}
 #endif 
+
   	while (--nblks > 0) {
 		ovp->ov_next = (union overhead *)((caddr_t)ovp + siz);
 		ovp = (union overhead *)((caddr_t)ovp + siz);
@@ -1638,7 +1967,10 @@ Perl_mfree(void *mp)
 	    }
 	    nbytes = (nbytes + 3) &~ 3; 
 	    ASSERT(*(u_int *)((caddr_t)ovp + nbytes - RSLOP) == RMAGIC, "chunk's tail overwrite");	    
+	    FILLCHECK_DEADBEEF((unsigned char*)((caddr_t)ovp + nbytes - RSLOP + sizeof(u_int)),
+			       BUCKET_SIZE_REAL(OV_INDEX(ovp)) - (nbytes - RSLOP + sizeof(u_int)));
 	}
+	FILL_DEADBEEF((unsigned char*)(ovp+1), BUCKET_SIZE_REAL(OV_INDEX(ovp)));
 	ovp->ov_rmagic = RMAGIC - 1;
 #endif
   	ASSERT(OV_INDEX(ovp) < NBUCKETS, "chunk's head overwrite");
@@ -1776,6 +2108,14 @@ Perl_realloc(void *mp, size_t nbytes)
 		       }
 		       nb = (nb + 3) &~ 3; 
 		       ASSERT(*(u_int *)((caddr_t)ovp + nb - RSLOP) == RMAGIC, "chunk's tail overwrite");
+		       FILLCHECK_DEADBEEF((unsigned char*)((caddr_t)ovp + nb - RSLOP + sizeof(u_int)),
+			       BUCKET_SIZE_REAL(OV_INDEX(ovp)) - (nb - RSLOP + sizeof(u_int)));
+		       if (nbytes > ovp->ov_size + 1 - M_OVERHEAD)
+			   FILL_FEEDADAD((unsigned char*)cp + ovp->ov_size + 1 - M_OVERHEAD,
+				     nbytes - (ovp->ov_size + 1 - M_OVERHEAD));
+		       else
+			   FILL_DEADBEEF((unsigned char*)cp + nbytes,
+					 nb - M_OVERHEAD + RSLOP - nbytes);
 			/*
 			 * Convert amount of memory requested into
 			 * closest block size stored in hash buckets
@@ -1954,7 +2294,7 @@ Perl_get_mstats(pTHX_ perl_mstats_t *buf
 	}
 	buf->total_sbrk = goodsbrk + sbrk_slack;
 	buf->sbrks = sbrks;
-	buf->sbrk_good = sbrk_good;
+	buf->sbrk_good = sbrk_goodness;
 	buf->sbrk_slack = sbrk_slack;
 	buf->start_slack = start_slack;
 	buf->sbrked_remains = sbrked_remains;
--- ./mg.c-pre	Fri Mar 14 06:59:28 2003
+++ ./mg.c	Mon Mar 24 18:56:04 2003
@@ -589,7 +589,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
 			    Perl_rc = tmp;
 		  }
 		  sv_setnv(sv, (NV)Perl_rc);
-		  sv_setpv(sv, os2error(Perl_rc));
+		  sv_setpv(sv, os2error(aTHX_ Perl_rc));
 	     }
 #else
 #ifdef WIN32
@@ -840,7 +840,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
 	sv_setnv(sv, (NV)errno);
 #ifdef OS2
 	if (errno == errno_isOS2 || errno == errno_isOS2_set)
-	    sv_setpv(sv, os2error(Perl_rc));
+	    sv_setpv(sv, os2error(aTHX_ Perl_rc));
 	else
 #endif
 	sv_setpv(sv, errno ? Strerror(errno) : "");
--- ./perlio.c-pre	Tue Mar 11 23:31:14 2003
+++ ./perlio.c	Mon Mar 24 17:58:48 2003
@@ -3343,7 +3343,7 @@ PerlIOBuf_open(pTHX_ PerlIO_funcs *self,
 #ifdef PERLIO_USING_CRLF
 #  ifdef PERLIO_IS_BINMODE_FD
 		if (PERLIO_IS_BINMODE_FD(fd))
-		    PerlIO_binmode(f,  '<'/*not used*/, O_BINARY, Nullch);
+		    PerlIO_binmode(aTHX_ f,  '<'/*not used*/, O_BINARY, Nullch);
 		else
 #  endif
 		/*
--- ./perlvars.h-pre	Sun Mar  2 14:40:14 2003
+++ ./perlvars.h	Mon Mar 24 19:06:04 2003
@@ -67,3 +67,6 @@ PERLVARI(Gppid,		IV,		0)
 PERLVAR(Gdollarzero_mutex, perl_mutex)	/* Modifying $0 */
 #endif
 
+/* This is constant on most architectures, a global on OS/2 */
+PERLVARI(Gsh_path,	char *,	SH_PATH)/* full path of shell */
+
--- ./reentr.pl-pre	Tue Mar 11 11:34:34 2003
+++ ./reentr.pl	Sat Mar 29 18:49:14 2003
@@ -457,7 +457,7 @@ EOF
 #endif
 EOF
     	    push @init, <<EOF;
-#ifdef __GLIBC__
+#if defined(__GLIBC__) || defined(__EMX__)
 	PL_reentrant_buffer->_${func}_struct.initialized = 0;
 	/* work around glibc-2.2.5 bug */
 	PL_reentrant_buffer->_${func}_struct.current_saltbits = 0;
--- ./sv.c-pre	Thu Mar 13 13:22:36 2003
+++ ./sv.c	Fri Mar 28 16:49:26 2003
@@ -10402,6 +10402,8 @@ perl_clone_using(PerlInterpreter *proto_
     PL_markstack = 0;
     PL_scopestack = 0;
     PL_savestack = 0;
+    PL_savestack_ix = 0;
+    PL_savestack_max = -1;
     PL_retstack = 0;
     PL_sig_pending = 0;
     Zero(&PL_debug_pad, 1, struct perl_debug_pad);
@@ -10433,6 +10435,8 @@ perl_clone_using(PerlInterpreter *proto_
     PL_markstack = 0;
     PL_scopestack = 0;
     PL_savestack = 0;
+    PL_savestack_ix = 0;
+    PL_savestack_max = -1;
     PL_retstack = 0;
     PL_sig_pending = 0;
     Zero(&PL_debug_pad, 1, struct perl_debug_pad);
@@ -10736,7 +10740,7 @@ perl_clone_using(PerlInterpreter *proto_
     PL_origalen		= proto_perl->Iorigalen;
     PL_pidstatus	= newHV();			/* XXX flag for cloning? */
     PL_osname		= SAVEPV(proto_perl->Iosname);
-    PL_sh_path		= proto_perl->Ish_path; /* XXX never deallocated */
+    PL_sh_path_compat	= proto_perl->Ish_path_compat; /* XXX never deallocated */
     PL_sighandlerp	= proto_perl->Isighandlerp;
 
 
--- ./pod/perlembed.pod-pre	Mon Mar 10 00:34:36 2003
+++ ./pod/perlembed.pod	Wed Mar 26 19:47:26 2003
@@ -183,6 +183,7 @@ version of I<miniperlmain.c> containing 
 
     int main(int argc, char **argv, char **env)
     {
+	PERL_SYS_INIT3(&argc,&argv,&env);
         my_perl = perl_alloc();
         perl_construct(my_perl);
 	PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
@@ -190,11 +191,16 @@ version of I<miniperlmain.c> containing 
         perl_run(my_perl);
         perl_destruct(my_perl);
         perl_free(my_perl);
+	PERL_SYS_TERM();
     }
 
 Notice that we don't use the C<env> pointer.  Normally handed to
 C<perl_parse> as its final argument, C<env> here is replaced by
-C<NULL>, which means that the current environment will be used.
+C<NULL>, which means that the current environment will be used.  The macros
+PERL_SYS_INIT3() and PERL_SYS_TERM() provide system-specific tune up 
+of the C runtime environment necessary to run Perl interpreters; since
+PERL_SYS_INIT3() may change C<env>, it may be more appropriate to provide
+C<env> as an argument to perl_parse().
 
 Now compile this program (I'll call it I<interp.c>) into an executable:
 
@@ -235,6 +241,7 @@ That's shown below, in a program I'll ca
     int main(int argc, char **argv, char **env)
     {
         char *args[] = { NULL };
+	PERL_SYS_INIT3(&argc,&argv,&env);
         my_perl = perl_alloc();
         perl_construct(my_perl);
 
@@ -247,6 +254,7 @@ That's shown below, in a program I'll ca
 
         perl_destruct(my_perl);
         perl_free(my_perl);
+	PERL_SYS_TERM();
     }
 
 where I<showtime> is a Perl subroutine that takes no arguments (that's the
@@ -308,6 +316,7 @@ the first, a C<float> from the second, a
        STRLEN n_a;
        char *embedding[] = { "", "-e", "0" };
 
+       PERL_SYS_INIT3(&argc,&argv,&env);
        my_perl = perl_alloc();
        perl_construct( my_perl );
 
@@ -329,6 +338,7 @@ the first, a C<float> from the second, a
 
        perl_destruct(my_perl);
        perl_free(my_perl);
+       PERL_SYS_TERM();
    }
 
 All of those strange functions with I<sv> in their names help convert Perl scalars to C types.  They're described in L<perlguts> and L<perlapi>.
@@ -489,6 +499,7 @@ been wrapped here):
      SV *text;
      STRLEN n_a;
 
+     PERL_SYS_INIT3(&argc,&argv,&env);
      my_perl = perl_alloc();
      perl_construct(my_perl);
      perl_parse(my_perl, NULL, 3, embedding, NULL);
@@ -532,6 +543,7 @@ been wrapped here):
      PL_perl_destruct_level = 1;
      perl_destruct(my_perl);
      perl_free(my_perl);
+     PERL_SYS_TERM();
  }
 
 which produces the output (again, long lines have been wrapped here)
@@ -614,6 +626,7 @@ deep breath...
     {
       char *my_argv[] = { "", "power.pl" };
 
+      PERL_SYS_INIT3(&argc,&argv,&env);
       my_perl = perl_alloc();
       perl_construct( my_perl );
 
@@ -625,6 +638,7 @@ deep breath...
 
       perl_destruct(my_perl);
       perl_free(my_perl);
+      PERL_SYS_TERM();
     }
 
 
@@ -763,6 +777,7 @@ with L<perlfunc/my> whenever possible.
      int exitstatus = 0;
      STRLEN n_a;
 
+     PERL_SYS_INIT3(&argc,&argv,&env);
      if((my_perl = perl_alloc()) == NULL) {
         fprintf(stderr, "no memory!");
         exit(1);
@@ -792,6 +807,7 @@ with L<perlfunc/my> whenever possible.
      PL_perl_destruct_level = 0;
      perl_destruct(my_perl);
      perl_free(my_perl);
+     PERL_SYS_TERM();
      exit(exitstatus);
  }
 
@@ -884,12 +900,14 @@ Let's give it a try:
 
  int main(int argc, char **argv, char **env)
  {
-     PerlInterpreter
-         *one_perl = perl_alloc(),
-         *two_perl = perl_alloc();
+     PerlInterpreter *one_perl, *two_perl;
      char *one_args[] = { "one_perl", SAY_HELLO };
      char *two_args[] = { "two_perl", SAY_HELLO };
 
+     PERL_SYS_INIT3(&argc,&argv,&env);
+     one_perl = perl_alloc();
+     two_perl = perl_alloc();
+
      PERL_SET_CONTEXT(one_perl);
      perl_construct(one_perl);
      PERL_SET_CONTEXT(two_perl);
@@ -914,6 +932,7 @@ Let's give it a try:
      perl_free(one_perl);
      PERL_SET_CONTEXT(two_perl);
      perl_free(two_perl);
+     PERL_SYS_TERM();
  }
 
 Note the calls to PERL_SET_CONTEXT().  These are necessary to initialize
--- ./os2/dl_os2.c-pre	Fri Jul 19 16:50:02 2002
+++ ./os2/dl_os2.c	Tue Mar 25 17:13:46 2003
@@ -8,13 +8,20 @@
 static ULONG retcode;
 static char fail[300];
 
+#ifdef PERL_CORE
+#include "EXTERN.h"
+#include "perl.h"
+#else
+#define aTHX_
 char *os2error(int rc);
+#endif
 
 void *
 dlopen(const char *path, int mode)
 {
 	HMODULE handle;
-	char tmp[260], *beg, *dot;
+	char tmp[260];
+	const char *beg, *dot;
 	ULONG rc;
 
 	fail[0] = 0;
@@ -66,13 +73,16 @@ dlsym(void *handle, const char *symbol)
 char *
 dlerror(void)
 {
+#ifdef PERL_CORE
+	dTHX;
+#endif
 	static char buf[700];
 	ULONG len;
 	char *err;
 
 	if (retcode == 0)
 		return NULL;
-	err = os2error(retcode);
+	err = os2error(aTHX_ retcode);
 	len = strlen(err);
 	if (len > sizeof(buf) - 1)
 	    len = sizeof(buf) - 1;
--- ./os2/Makefile.SHs-pre	Tue Mar 25 13:06:08 2003
+++ ./os2/Makefile.SHs	Tue Mar 25 13:04:28 2003
@@ -27,7 +27,6 @@ $spitshell >>Makefile <<!GROK!THIS!
 
 PERL_FULLVERSION = $perl_fullversion
 
-OPTIMIZE	= $optimize
 AOUT_OPTIMIZE	= \$(OPTIMIZE)
 AOUT_CCCMD	= \$(CC) -DPERL_CORE $aout_ccflags \$(AOUT_OPTIMIZE)
 AOUT_AR		= $aout_ar
--- ./os2/os2.c-pre	Sun Dec 22 23:48:34 2002
+++ ./os2/os2.c	Fri Mar 28 18:23:54 2003
@@ -9,6 +9,7 @@
 #define SPU_ENABLESUPPRESSION           1
 #include <os2.h>
 #include "dlfcn.h"
+#include <emx/syscalls.h>
 
 #include <sys/uflags.h>
 
@@ -29,7 +30,7 @@
 #include "EXTERN.h"
 #include "perl.h"
 
-#ifdef USE_5005THREADS
+#if defined(USE_5005THREADS) || defined(USE_ITHREADS)
 
 typedef void (*emx_startroutine)(void *);
 typedef void* (*pthreads_startroutine)(void *);
@@ -40,6 +41,8 @@ enum pthreads_state {
     pthreads_st_exited, 
     pthreads_st_detached, 
     pthreads_st_waited,
+    pthreads_st_norun,
+    pthreads_st_exited_waited,
 };
 const char *pthreads_states[] = {
     "uninit",
@@ -47,8 +50,24 @@ const char *pthreads_states[] = {
     "exited",
     "detached",
     "waited for",
+    "could not start",
+    "exited, then waited on",
 };
 
+enum pthread_exists { pthread_not_existant = -0xff };
+
+static const char*
+pthreads_state_string(enum pthreads_state state)
+{
+  if (state < 0 || state >= sizeof(pthreads_states)/sizeof(*pthreads_states)) {
+    static char buf[80];
+
+    snprintf(buf, sizeof(buf), "unknown thread state %d", (int)state);
+    return buf;
+  }
+  return pthreads_states[state];
+}
+
 typedef struct {
     void *status;
     perl_cond cond;
@@ -63,43 +82,90 @@ int
 pthread_join(perl_os_thread tid, void **status)
 {
     MUTEX_LOCK(&start_thread_mutex);
+    if (tid < 1 || tid >= thread_join_count) {
+	MUTEX_UNLOCK(&start_thread_mutex);
+	if (tid != pthread_not_existant)
+	    Perl_croak_nocontext("panic: join with a thread with strange ordinal %d", (int)tid);
+	Perl_warn_nocontext("panic: join with a thread which could not start");
+	*status = 0;
+	return 0;
+    }
     switch (thread_join_data[tid].state) {
     case pthreads_st_exited:
-	thread_join_data[tid].state = pthreads_st_none;	/* Ready to reuse */
-	MUTEX_UNLOCK(&start_thread_mutex);
+	thread_join_data[tid].state = pthreads_st_exited_waited;
 	*status = thread_join_data[tid].status;
+	MUTEX_UNLOCK(&start_thread_mutex);
+	COND_SIGNAL(&thread_join_data[tid].cond);    
 	break;
     case pthreads_st_waited:
 	MUTEX_UNLOCK(&start_thread_mutex);
 	Perl_croak_nocontext("join with a thread with a waiter");
 	break;
+    case pthreads_st_norun:
+    {
+	int state = (int)thread_join_data[tid].status;
+
+	thread_join_data[tid].state = pthreads_st_none;
+	MUTEX_UNLOCK(&start_thread_mutex);
+	Perl_croak_nocontext("panic: join with a thread which could not run"
+			     " due to attempt of tid reuse (state='%s')",
+			     pthreads_state_string(state));
+	break;
+    }
     case pthreads_st_run:
+    {
+	perl_cond cond;
+
 	thread_join_data[tid].state = pthreads_st_waited;
+	thread_join_data[tid].status = (void *)status;
 	COND_INIT(&thread_join_data[tid].cond);
+	cond = thread_join_data[tid].cond;
+	COND_WAIT(&thread_join_data[tid].cond, &start_thread_mutex);
+	COND_DESTROY(&cond);
 	MUTEX_UNLOCK(&start_thread_mutex);
-	COND_WAIT(&thread_join_data[tid].cond, NULL);    
-	COND_DESTROY(&thread_join_data[tid].cond);
-	thread_join_data[tid].state = pthreads_st_none;	/* Ready to reuse */
-	*status = thread_join_data[tid].status;
 	break;
+    }
     default:
 	MUTEX_UNLOCK(&start_thread_mutex);
-	Perl_croak_nocontext("join: unknown thread state: '%s'", 
-	      pthreads_states[thread_join_data[tid].state]);
+	Perl_croak_nocontext("panic: join with thread in unknown thread state: '%s'", 
+	      pthreads_state_string(thread_join_data[tid].state));
 	break;
     }
     return 0;
 }
 
+typedef struct {
+  pthreads_startroutine sub;
+  void *arg;
+  void *ctx;
+} pthr_startit;
+
+/* The lock is used:
+	a) Since we temporarily usurp the caller interp, so malloc() may
+	   use it to decide on debugging the call;
+	b) Since *args is on the caller's stack.
+ */
 void
-pthread_startit(void *arg)
+pthread_startit(void *arg1)
 {
     /* Thread is already started, we need to transfer control only */
-    pthreads_startroutine start_routine = *((pthreads_startroutine*)arg);
+    pthr_startit args = *(pthr_startit *)arg1;
     int tid = pthread_self();
-    void *retval;
-    
-    arg = ((void**)arg)[1];
+    void *rc;
+    int state;
+
+    if (tid <= 1) {
+	/* Can't croak, the setjmp() is not in scope... */
+	char buf[80];
+
+	snprintf(buf, sizeof(buf),
+		 "panic: thread with strange ordinal %d created\n\r", tid);
+	write(2,buf,strlen(buf));
+	MUTEX_UNLOCK(&start_thread_mutex);
+	return;
+    }
+    /* Until args.sub resets it, makes debugging Perl_malloc() work: */
+    PERL_SET_CONTEXT(0);
     if (tid >= thread_join_count) {
 	int oc = thread_join_count;
 	
@@ -111,43 +177,89 @@ pthread_startit(void *arg)
 	    Newz(1323, thread_join_data, thread_join_count, thread_join_t);
 	}
     }
-    if (thread_join_data[tid].state != pthreads_st_none)
-	Perl_croak_nocontext("attempt to reuse thread id %i", tid);
+    if (thread_join_data[tid].state != pthreads_st_none) {
+	/* Can't croak, the setjmp() is not in scope... */
+	char buf[80];
+
+	snprintf(buf, sizeof(buf),
+		 "panic: attempt to reuse thread id %d (state='%s')\n\r",
+		 tid, pthreads_state_string(thread_join_data[tid].state));
+	write(2,buf,strlen(buf));
+	thread_join_data[tid].status = (void*)thread_join_data[tid].state;
+	thread_join_data[tid].state = pthreads_st_norun;
+	MUTEX_UNLOCK(&start_thread_mutex);
+	return;
+    }
     thread_join_data[tid].state = pthreads_st_run;
     /* Now that we copied/updated the guys, we may release the caller... */
     MUTEX_UNLOCK(&start_thread_mutex);
-    thread_join_data[tid].status = (*start_routine)(arg);
+    rc = (*args.sub)(args.arg);
+    MUTEX_LOCK(&start_thread_mutex);
     switch (thread_join_data[tid].state) {
     case pthreads_st_waited:
-	COND_SIGNAL(&thread_join_data[tid].cond);    
+	COND_SIGNAL(&thread_join_data[tid].cond);
+	thread_join_data[tid].state = pthreads_st_none;
+	*((void**)thread_join_data[tid].status) = rc;
 	break;
-    default:
+    case pthreads_st_detached:
+	thread_join_data[tid].state = pthreads_st_none;
+	break;
+    case pthreads_st_run:
+	/* Somebody can wait on us; cannot exit, since OS can reuse the tid
+	   and our waiter will get somebody else's status. */
 	thread_join_data[tid].state = pthreads_st_exited;
+	thread_join_data[tid].status = rc;
+	COND_INIT(&thread_join_data[tid].cond);
+	COND_WAIT(&thread_join_data[tid].cond, &start_thread_mutex);
+	COND_DESTROY(&thread_join_data[tid].cond);
+	thread_join_data[tid].state = pthreads_st_none;	/* Ready to reuse */
 	break;
+    default:
+	state = thread_join_data[tid].state;
+	MUTEX_UNLOCK(&start_thread_mutex);
+	Perl_croak_nocontext("panic: unexpected thread state on exit: '%s'",
+			     pthreads_state_string(state));
     }
+    MUTEX_UNLOCK(&start_thread_mutex);
 }
 
 int
-pthread_create(perl_os_thread *tid, const pthread_attr_t *attr, 
+pthread_create(perl_os_thread *tidp, const pthread_attr_t *attr, 
 	       void *(*start_routine)(void*), void *arg)
 {
-    void *args[2];
+    dTHX;
+    pthr_startit args;
 
-    args[0] = (void*)start_routine;
-    args[1] = arg;
+    args.sub = (void*)start_routine;
+    args.arg = arg;
+    args.ctx = PERL_GET_CONTEXT;
 
     MUTEX_LOCK(&start_thread_mutex);
-    *tid = _beginthread(pthread_startit, /*stack*/ NULL, 
-			/*stacksize*/ 10*1024*1024, (void*)args);
-    MUTEX_LOCK(&start_thread_mutex);
+    /* Test suite creates 31 extra threads;
+       on machine without shared-memory-hogs this stack sizeis OK with 31: */
+    *tidp = _beginthread(pthread_startit, /*stack*/ NULL, 
+			 /*stacksize*/ 4*1024*1024, (void*)&args);
+    if (*tidp == -1) {
+	*tidp = pthread_not_existant;
+	MUTEX_UNLOCK(&start_thread_mutex);
+	return EINVAL;
+    }
+    MUTEX_LOCK(&start_thread_mutex);		/* Wait for init to proceed */
     MUTEX_UNLOCK(&start_thread_mutex);
-    return *tid ? 0 : EINVAL;
+    return 0;
 }
 
 int 
 pthread_detach(perl_os_thread tid)
 {
     MUTEX_LOCK(&start_thread_mutex);
+    if (tid < 1 || tid >= thread_join_count) {
+	MUTEX_UNLOCK(&start_thread_mutex);
+	if (tid != pthread_not_existant)
+	    Perl_croak_nocontext("panic: detach of a thread with strange ordinal %d", (int)tid);
+	Perl_warn_nocontext("detach of a thread which could not start");
+	return 0;
+    }
     switch (thread_join_data[tid].state) {
     case pthreads_st_waited:
 	MUTEX_UNLOCK(&start_thread_mutex);
@@ -157,16 +269,35 @@ pthread_detach(perl_os_thread tid)
 	thread_join_data[tid].state = pthreads_st_detached;
 	MUTEX_UNLOCK(&start_thread_mutex);
 	break;
+    case pthreads_st_exited:
+	MUTEX_UNLOCK(&start_thread_mutex);
+	COND_SIGNAL(&thread_join_data[tid].cond);    
+	break;
+    case pthreads_st_detached:
+	MUTEX_UNLOCK(&start_thread_mutex);
+	Perl_warn_nocontext("detach on an already detached thread");
+	break;
+    case pthreads_st_norun:
+    {
+	int state = (int)thread_join_data[tid].status;
+
+	thread_join_data[tid].state = pthreads_st_none;
+	MUTEX_UNLOCK(&start_thread_mutex);
+	Perl_croak_nocontext("panic: detaching thread which could not run"
+			     " due to attempt of tid reuse (state='%s')",
+			     pthreads_state_string(state));
+	break;
+    }
     default:
 	MUTEX_UNLOCK(&start_thread_mutex);
-	Perl_croak_nocontext("detach: unknown thread state: '%s'", 
-	      pthreads_states[thread_join_data[tid].state]);
+	Perl_croak_nocontext("panic: detach of a thread with unknown thread state: '%s'", 
+	      pthreads_state_string(thread_join_data[tid].state));
 	break;
     }
     return 0;
 }
 
-/* This is a very bastardized version: */
+/* This is a very bastardized version; may be OK due to edge trigger of Wait */
 int
 os2_cond_wait(perl_cond *c, perl_mutex *m)
 {						
@@ -180,9 +311,10 @@ os2_cond_wait(perl_cond *c, perl_mutex *
 	Perl_croak_nocontext("panic: COND_WAIT: rc=%i", rc);		
     if (rc == ERROR_INTERRUPT)
 	errno = EINTR;
-    if (m) MUTEX_LOCK(m);					
+    if (m) MUTEX_LOCK(m);
+    return 0;
 } 
-#endif 
+#endif
 
 static int exe_is_aout(void);
 
@@ -1280,17 +1412,51 @@ int	setgid(x)	{ errno = EINVAL; return -
 
 #if OS2_STAT_HACK
 
+enum os2_stat_extra {	/* EMX 0.9d fix 4 defines up to 0100000 */
+  os2_stat_archived	= 0x1000000,	/* 0100000000 */
+  os2_stat_hidden	= 0x2000000,	/* 0200000000 */
+  os2_stat_system	= 0x4000000,	/* 0400000000 */
+  os2_stat_force	= 0x8000000,	/* Do not ignore flags on chmod */
+};
+
+#define OS2_STAT_SPECIAL (os2_stat_system | os2_stat_archived | os2_stat_hidden)
+
+static void
+massage_os2_attr(struct stat *st)
+{
+    if ( ((st->st_mode & S_IFMT) != S_IFREG
+	  && (st->st_mode & S_IFMT) != S_IFDIR)
+         || !(st->st_attr & (FILE_ARCHIVED | FILE_HIDDEN | FILE_SYSTEM)))
+	return;
+
+    if ( st->st_attr & FILE_ARCHIVED )
+	st->st_mode |= (os2_stat_archived | os2_stat_force);
+    if ( st->st_attr & FILE_HIDDEN )
+	st->st_mode |= (os2_stat_hidden | os2_stat_force);
+    if ( st->st_attr & FILE_SYSTEM )
+	st->st_mode |= (os2_stat_system | os2_stat_force);
+}
+
     /* First attempt used DosQueryFSAttach which crashed the system when
        used with 5.001. Now just look for /dev/. */
-
 int
 os2_stat(const char *name, struct stat *st)
 {
     static int ino = SHRT_MAX;
+    STRLEN l = strlen(name);
 
-    if (stricmp(name, "/dev/con") != 0
-     && stricmp(name, "/dev/tty") != 0)
-	return stat(name, st);
+    if ( ( l < 8 || l > 9) || strnicmp(name, "/dev/", 5) != 0
+         || (    stricmp(name + 5, "con") != 0
+	      && stricmp(name + 5, "tty") != 0
+	      && stricmp(name + 5, "nul") != 0
+	      && stricmp(name + 5, "null") != 0) ) {
+	int s = stat(name, st);
+
+	if (s)
+	    return s;
+	massage_os2_attr(st);
+	return 0;
+    }
 
     memset(st, 0, sizeof *st);
     st->st_mode = S_IFCHR|0666;
@@ -1299,6 +1465,48 @@ os2_stat(const char *name, struct stat *
     return 0;
 }
 
+int
+os2_fstat(int handle, struct stat *st)
+{
+    int s = fstat(handle, st);
+
+    if (s)
+	return s;
+    massage_os2_attr(st);
+    return 0;
+}
+
+#undef chmod
+int
+os2_chmod (const char *name, int pmode)	/* Modelled after EMX src/lib/io/chmod.c */
+{
+    int attr, rc;
+
+    if (!(pmode & os2_stat_force))
+	return chmod(name, pmode);
+
+    attr = __chmod (name, 0, 0);           /* Get attributes */
+    if (attr < 0)
+	return -1;
+    if (pmode & S_IWRITE)
+	attr &= ~FILE_READONLY;
+    else
+	attr |= FILE_READONLY;
+    /* New logic */
+    attr &= ~(FILE_ARCHIVED | FILE_HIDDEN | FILE_SYSTEM);
+
+    if ( pmode & os2_stat_archived )
+        attr |= FILE_ARCHIVED;
+    if ( pmode & os2_stat_hidden )
+        attr |= FILE_HIDDEN;
+    if ( pmode & os2_stat_system )
+        attr |= FILE_SYSTEM;
+
+    rc = __chmod (name, 1, attr);
+    if (rc >= 0) rc = 0;
+    return rc;
+}
+
 #endif
 
 #ifdef USE_PERL_SBRK
@@ -1406,9 +1614,6 @@ mod2fname(pTHX_ SV *sv)
 	}
 	avlen --;
     }
-#ifdef USE_5005THREADS
-    sum++;				/* Avoid conflict of DLLs in memory. */
-#endif 
    /* We always load modules as *specific* DLLs, and with the full name.
       When loading a specific DLL by its full name, one cannot get a
       different DLL, even if a DLL with the same basename is loaded already.
@@ -1444,7 +1649,7 @@ XS(XS_DynaLoader_mod2fname)
 }
 
 char *
-os2error(int rc)
+os2error(pTHX_ int rc)
 {
 	static char buf[300];
 	ULONG len;
@@ -1489,11 +1694,11 @@ ResetWinError(void)
 }
 
 void
-CroakWinError(int die, char *name)
+CroakWinError(pTHX_ int die, char *name)
 {
   FillWinError;
   if (die && Perl_rc)
-    croak("%s: %s", (name ? name : "Win* API call"), os2error(Perl_rc));
+    Perl_croak(aTHX_ "%s: %s", (name ? name : "Win* API call"), os2error(aTHX_ Perl_rc));
 }
 
 char *
@@ -1585,7 +1790,7 @@ Perl_hab_GET()			/* Needed if perl.h can
 }
 
 HMQ
-Perl_Register_MQ(int serve)
+Perl_Register_MQ(pTHX_ int serve)
 {
   if (Perl_hmq_refcnt <= 0) {
     PPIB pib;
@@ -2238,7 +2443,7 @@ DeclOSFuncByORD(APIRET, _DosQueryModFrom
 enum module_name_how { mod_name_handle, mod_name_shortname, mod_name_full};
 
 static SV*
-module_name_at(void *pp, enum module_name_how how)
+module_name_at(pTHX_ void *pp, enum module_name_how how)
 {
     char buf[MAXPATHLEN];
     char *p = buf;
@@ -2262,15 +2467,15 @@ module_name_at(void *pp, enum module_nam
 }
 
 static SV*
-module_name_of_cv(SV *cv, enum module_name_how how)
+module_name_of_cv(pTHX_ SV *cv, enum module_name_how how)
 {
     if (!cv || !SvROK(cv) || SvTYPE(SvRV(cv)) != SVt_PVCV || !CvXSUB(SvRV(cv)))
-	croak("Not an XSUB reference");
-    return module_name_at(CvXSUB(SvRV(cv)), how);
+	Perl_croak(aTHX_ "Not an XSUB reference");
+    return module_name_at(aTHX_ CvXSUB(SvRV(cv)), how);
 }
 
 /* Find module name to which *this* subroutine is compiled */
-#define module_name(how)	module_name_at(&module_name_at, how)
+#define module_name(how)	module_name_at(aTHX_ &module_name_at, how)
 
 XS(XS_OS2_DLLname)
 {
@@ -2289,7 +2494,7 @@ XS(XS_OS2_DLLname)
 	if (items < 2)
 	    RETVAL = module_name(how);
 	else
-	    RETVAL = module_name_of_cv(ST(1), how);
+	    RETVAL = module_name_of_cv(aTHX_ ST(1), how);
 	ST(0) = RETVAL;
 	sv_2mortal(ST(0));
     }
@@ -2303,7 +2508,7 @@ XS(XS_OS2__control87)
 {
     dXSARGS;
     if (items != 2)
-	croak("Usage: OS2::_control87(new,mask)");
+	Perl_croak(aTHX_ "Usage: OS2::_control87(new,mask)");
     {
 	unsigned	new = (unsigned)SvIV(ST(0));
 	unsigned	mask = (unsigned)SvIV(ST(1));
@@ -2320,7 +2525,7 @@ XS(XS_OS2_get_control87)
 {
     dXSARGS;
     if (items != 0)
-	croak("Usage: OS2::get_control87()");
+	Perl_croak(aTHX_ "Usage: OS2::get_control87()");
     {
 	unsigned	RETVAL;
 
@@ -2336,7 +2541,7 @@ XS(XS_OS2_set_control87)
 {
     dXSARGS;
     if (items < 0 || items > 2)
-	croak("Usage: OS2::set_control87(new=MCW_EM, mask=MCW_EM)");
+	Perl_croak(aTHX_ "Usage: OS2::set_control87(new=MCW_EM, mask=MCW_EM)");
     {
 	unsigned	new;
 	unsigned	mask;
@@ -2757,7 +2962,9 @@ Perl_OS2_init3(char **env, void **preg, 
 	    if (PL_sh_path[i] == '\\') PL_sh_path[i] = '/';
 	}
     }
+#if defined(USE_5005THREADS) || defined(USE_ITHREADS)
     MUTEX_INIT(&start_thread_mutex);
+#endif
     os2_mytype = my_type();		/* Do it before morphing.  Needed? */
     /* Some DLLs reset FP flags on load.  We may have been linked with them */
     _control87(MCW_EM, MCW_EM);
@@ -3068,4 +3275,23 @@ char *
 gcvt_os2 (double value, int digits, char *buffer)
 {
   return gcvt (value, digits, buffer);
+}
+
+#undef fork
+int fork_with_resources()
+{
+#if (defined(USE_5005THREADS) || defined(USE_ITHREADS)) && !defined(USE_SLOW_THREAD_SPECIFIC)
+  dTHX;
+  void *ctx = PERL_GET_CONTEXT;
+#endif
+
+  int rc = fork();
+
+#if (defined(USE_5005THREADS) || defined(USE_ITHREADS)) && !defined(USE_SLOW_THREAD_SPECIFIC)
+  if (rc == 0) {			/* child */
+    ALLOC_THREAD_KEY;			/* Acquire the thread-local memory */
+    PERL_SET_CONTEXT(ctx);		/* Reinit the thread-local memory */
+  }
+#endif
+  return rc;
 }
--- ./os2/os2ish.h-pre	Fri Jul 19 16:50:02 2002
+++ ./os2/os2ish.h	Wed Mar 26 01:35:20 2003
@@ -99,7 +99,7 @@
 # undef I_SYS_UN
 #endif 
 
-#ifdef USE_5005THREADS
+#if defined(USE_5005THREADS) || defined(USE_ITHREADS)
 
 #define do_spawn(a)      os2_do_spawn(aTHX_ (a))
 #define do_aspawn(a,b,c) os2_do_aspawn(aTHX_ (a),(b),(c))
@@ -184,7 +184,7 @@ extern int rc;
 #  define pthread_getspecific(k)	(*(k))
 #  define pthread_setspecific(k,v)	(*(k)=(v),0)
 #  define pthread_key_create(keyp,flag)			\
-	( DosAllocThreadLocalMemory(1,(U32*)keyp)	\
+	( DosAllocThreadLocalMemory(1,(unsigned long**)keyp)	\
 	  ? Perl_croak_nocontext("LocalMemory"),1	\
 	  : 0						\
 	)
@@ -401,15 +401,19 @@ char *ctermid(char *s);
 #if OS2_STAT_HACK
 
 #define Stat(fname,bufptr) os2_stat((fname),(bufptr))
-#define Fstat(fd,bufptr)   fstat((fd),(bufptr))
+#define Fstat(fd,bufptr)   os2_fstat((fd),(bufptr))
 #define Fflush(fp)         fflush(fp)
 #define Mkdir(path,mode)   mkdir((path),(mode))
+#define chmod(path,mode)   os2_chmod((path),(mode))
 
 #undef S_IFBLK
 #undef S_ISBLK
-#define S_IFBLK		0120000
+#define S_IFBLK		0120000		/* Hacks to make things compile... */
 #define S_ISBLK(mode)	(((mode) & S_IFMT) == S_IFBLK)
 
+int os2_chmod(const char *name, int pmode);
+int os2_fstat(int handle, struct stat *st);
+
 #else
 
 #define Stat(fname,bufptr) stat((fname),(bufptr))
@@ -461,7 +465,7 @@ extern OS2_Perl_data_t OS2_Perl_data;
 #define Perl_os2_initial_mode	(OS2_Perl_data.initial_mode)
 
 unsigned long Perl_hab_GET();
-unsigned long Perl_Register_MQ(int serve);
+unsigned long Perl_Register_MQ(pTHX_ int serve);
 void	Perl_Deregister_MQ(int serve);
 int	Perl_Serve_Messages(int force);
 /* Cannot prototype with I32 at this point. */
@@ -486,7 +490,7 @@ struct PMWIN_entries_t {
 extern struct PMWIN_entries_t PMWIN_entries;
 void init_PMWIN_entries(void);
 
-#define perl_hmq_GET(serve)	Perl_Register_MQ(serve)
+#define perl_hmq_GET(serve)	Perl_Register_MQ(aTHX_ serve)
 #define perl_hmq_UNSET(serve)	Perl_Deregister_MQ(serve)
 
 #define OS2_XS_init() (*OS2_Perl_data.xs_init)(aTHX)
@@ -509,7 +513,7 @@ void init_PMWIN_entries(void);
 
 /* This form propagates the return value, dieing with $^E if needed */
 #define SaveCroakWinError(expr,die,name1,name2)		\
-  ((expr) ? : (CroakWinError(die,name1 name2), 0))
+  ((expr) ? : (CroakWinError(aTHX_ die,name1 name2), 0))
 
 #define FillOSError(rc) (os2_setsyserrno(rc),				\
 			Perl_severity = SEVERITY_ERROR) 
@@ -665,16 +669,19 @@ enum entries_ordinals {
 	DeclWinFuncByORD_CACHE_resetError_survive(ret,name,CAT2(ORD_Win,name),at,args)
 
 void ResetWinError(void);
-void CroakWinError(int die, char *name);
+void CroakWinError(pTHX_ int die, char *name);
 
 #define PERLLIB_MANGLE(s, n) perllib_mangle((s), (n))
 char *perllib_mangle(char *, unsigned int);
 
+#define fork	fork_with_resources
+
 typedef int (*Perl_PFN)();
 Perl_PFN loadByOrdinal(enum entries_ordinals ord, int fail);
 extern const Perl_PFN * const pExtFCN;
-char *os2error(int rc);
+char *os2error(pTHX_ int rc);
 int os2_stat(const char *name, struct stat *st);
+int fork_with_resources();
 int setpriority(int which, int pid, int val);
 int getpriority(int which /* ignored */, int pid);
 
--- ./os2/os2thread.h-pre	Fri Jul 19 16:50:02 2002
+++ ./os2/os2thread.h	Tue Mar 25 16:03:12 2003
@@ -7,6 +7,7 @@ typedef _rmutex perl_mutex;
 
 /*typedef HEV perl_cond;*/	/* Will include os2.h into all C files.  */
 typedef unsigned long perl_cond;
+int os2_cond_wait(perl_cond *c, perl_mutex *m);
 
 #ifdef USE_SLOW_THREAD_SPECIFIC
 typedef int perl_key;
--- ./os2/OS2/REXX/REXX.pm-pre	Fri Jul 19 16:50:02 2002
+++ ./os2/OS2/REXX/REXX.pm	Wed Mar 26 14:53:40 2003
@@ -1,18 +1,17 @@
 package OS2::REXX;
 
-use Carp;
 require Exporter;
-require DynaLoader;
+use XSLoader;
 require OS2::DLL;
 
-@ISA = qw(Exporter DynaLoader);
+@ISA = qw(Exporter);
 # Items to export into callers namespace by default
 # (move infrequently used names to @EXPORT_OK below)
 @EXPORT = qw(REXX_call REXX_eval REXX_eval_with);
 # Other items we are prepared to export if requested
 @EXPORT_OK = qw(drop register);
 
-$VERSION = '1.01';
+$VERSION = '1.02';
 
 # We cannot just put OS2::DLL in @ISA, since some scripts would use
 # function interface, not method interface...
@@ -21,7 +20,7 @@ $VERSION = '1.01';
 *load = \&OS2::DLL::load;
 *find = \&OS2::DLL::find;
 
-bootstrap OS2::REXX;
+XSLoader::load 'OS2::REXX';
 
 # Preloaded methods go here.  Autoload methods go after __END__, and are
 # processed by the autosplit program.
--- ./os2/OS2/REXX/DLL/DLL.pm-pre	Fri Jul 19 16:50:02 2002
+++ ./os2/OS2/REXX/DLL/DLL.pm	Wed Mar 26 14:51:44 2003
@@ -3,9 +3,7 @@ package OS2::DLL;
 our $VERSION = '1.00';
 
 use Carp;
-use DynaLoader;
-
-@ISA = qw(DynaLoader);
+use XSLoader;
 
 sub AUTOLOAD {
     $AUTOLOAD =~ /^OS2::DLL::.+::(.+)$/
@@ -86,7 +84,7 @@ EOE
 	return 1;
 }
 
-bootstrap OS2::DLL;
+XSLoader::load 'OS2::DLL';
 
 1;
 __END__
--- ./os2/OS2/Process/Process.xs-pre	Fri Jul 19 16:50:02 2002
+++ ./os2/OS2/Process/Process.xs	Mon Mar 24 19:38:24 2003
@@ -232,7 +232,7 @@ file_type(char *path)
     ULONG apptype;
     
     if (!(_emx_env & 0x200)) 
-	croak("file_type not implemented on DOS"); /* not OS/2. */
+	Perl_croak_nocontext("file_type not implemented on DOS"); /* not OS/2. */
     if (CheckOSError(DosQueryAppType(path, &apptype))) {
 	if (rc == ERROR_INVALID_EXE_SIGNATURE) 
 	    croak("Invalid EXE signature"); 
@@ -420,8 +420,11 @@ fill_swentry(SWENTRY *swentryp, HWND hwn
 	 if (!(_emx_env & 0x200)) 
 	     croak("switch_entry not implemented on DOS"); /* not OS/2. */
 	 if (CheckWinError(hSwitch = 
-			   myWinQuerySwitchHandle(hwnd, pid)))
-	     croak("WinQuerySwitchHandle: %s", os2error(Perl_rc));
+			   myWinQuerySwitchHandle(hwnd, pid))) {
+	     dTHX;
+
+	     croak("WinQuerySwitchHandle: %s", os2error(aTHX_ Perl_rc));
+	 }
 	 swentryp->hswitch = hSwitch;
 	 if (CheckOSError(myWinQuerySwitchEntry(hSwitch, &swentryp->swctl)))
 	     croak("WinQuerySwitchEntry err %ld", rc);
--- ./os2/OS2/PrfDB/Changes-pre	Fri Jul 19 16:50:02 2002
+++ ./os2/OS2/PrfDB/Changes	Wed Mar 26 15:04:40 2003
@@ -3,3 +3,4 @@ Revision history for Perl extension OS2:
 0.01  Tue Mar 26 19:35:27 1996
 	- original version; created by h2xs 1.16
 0.02:  Field do-not-close added to OS2::Prf::Hini.
+0.03:  Update to XSLoader and 'our'.
--- ./os2/OS2/PrfDB/PrfDB.pm-pre	Fri Jul 19 16:50:02 2002
+++ ./os2/OS2/PrfDB/PrfDB.pm	Wed Mar 26 15:03:34 2003
@@ -1,21 +1,22 @@
 package OS2::PrfDB;
 
 use strict;
-use vars qw($VERSION @ISA @EXPORT);
 
 require Exporter;
-require DynaLoader;
+use XSLoader;
+use Tie::Hash;
 
-@ISA = qw(Exporter DynaLoader);
+our $debug;
+our @ISA = qw(Exporter Tie::Hash);
 # Items to export into callers namespace by default. Note: do not export
 # names by default without a very good reason. Use EXPORT_OK instead.
 # Do not simply export all your public functions/methods/constants.
-@EXPORT = qw(
-	     AnyIni UserIni SystemIni
-	    );
-$VERSION = '0.02';
+our @EXPORT = qw(
+		 AnyIni UserIni SystemIni
+		);
+our $VERSION = '0.03';
 
-bootstrap OS2::PrfDB $VERSION;
+XSLoader::load 'OS2::PrfDB', $VERSION;
 
 # Preloaded methods go here.
 
@@ -32,10 +33,6 @@ sub SystemIni {
   new_from_int OS2::PrfDB::Hini OS2::Prf::System(2),'System settings database',1;
 }
 
-use vars qw{$debug @ISA};
-use Tie::Hash;
-push @ISA, qw{Tie::Hash};
-
 # Internal structure 0 => HINI, 1 => array of entries, 2 => iterator.
 
 sub TIEHASH {
@@ -127,9 +124,10 @@ sub DESTROY {
 }
 
 package OS2::PrfDB::Sub;
-use vars qw{$debug @ISA};
 use Tie::Hash;
-@ISA = qw{Tie::Hash};
+
+our $debug;
+our @ISA = qw{Tie::Hash};
 
 # Internal structure 0 => HINI, 1 => array of entries, 2 => iterator,
 # 3 => appname.
--- ./os2/OS2/ExtAttr/Changes-pre	Fri Jul 19 16:50:02 2002
+++ ./os2/OS2/ExtAttr/Changes	Wed Mar 26 15:07:10 2003
@@ -3,3 +3,5 @@ Revision history for Perl extension OS2:
 0.01  Sun Apr 21 11:07:04 1996
 	- original version; created by h2xs 1.16
 
+0.02  Update to XSLoader and 'our'.
+      Remove Exporter.
--- ./os2/OS2/ExtAttr/ExtAttr.pm-pre	Fri Jul 19 16:50:02 2002
+++ ./os2/OS2/ExtAttr/ExtAttr.pm	Wed Mar 26 15:05:58 2003
@@ -1,21 +1,10 @@
 package OS2::ExtAttr;
 
 use strict;
-use vars qw($VERSION @ISA @EXPORT);
+use XSLoader;
 
-require Exporter;
-require DynaLoader;
-
-@ISA = qw(Exporter DynaLoader);
-# Items to export into callers namespace by default. Note: do not export
-# names by default without a very good reason. Use EXPORT_OK instead.
-# Do not simply export all your public functions/methods/constants.
-@EXPORT = qw(
-	
-);
-$VERSION = '0.01';
-
-bootstrap OS2::ExtAttr $VERSION;
+our $VERSION = '0.02';
+XSLoader::load 'OS2::ExtAttr', $VERSION;
 
 # Preloaded methods go here.
 
--- ./lib/Net/Ping/t/190_alarm.t-pre	Tue Mar 11 00:13:06 2003
+++ ./lib/Net/Ping/t/190_alarm.t	Thu Mar 27 00:04:50 2003
@@ -22,6 +22,21 @@ use strict;
 use Test;
 use Net::Ping;
 
+BEGIN {
+  unless (eval "require Socket") {
+    print "1..0 \# Skip: no Socket\n";
+    exit;
+  }
+  unless (eval {alarm 0; 1;}) {
+    print "1..0 \# Skip: alarm borks on $^O $^X $] ?\n";
+    exit;
+  }
+  unless (getservbyname('echo', 'tcp')) {
+    print "1..0 \# Skip: no echo port\n";
+    exit;
+  }
+}
+
 plan tests => 6;
 
 # Everything compiled
@@ -49,6 +64,6 @@ eval {
 ok 1;
 
 # Make sure it died for a good excuse
-ok $@ =~ /alarm works/ or die $@;
+ok $@ =~ /alarm works|Network\s.*unreachable/i or die $@;
 
 alarm 0; # Reset alarm
--- ./lib/ExtUtils/MM_OS2.pm-pre	Fri Jul 19 16:49:46 2002
+++ ./lib/ExtUtils/MM_OS2.pm	Wed Mar 26 16:07:08 2003
@@ -38,7 +38,7 @@ sub dist {
     my($self, %attribs) = @_;
 
     $attribs{TO_UNIX} ||= sprintf <<'MAKE_TEXT', $self->{NOECHO};
-%s$(TEST_F) tmp.zip && $(RM) tmp.zip; $(ZIP) -ll -mr tmp.zip $(DISTVNAME) && unzip -o tmp.zip && $(RM) tmp.zip
+%s$(TEST_F) tmp.zip && $(RM_F) tmp.zip; $(ZIP) -ll -mr tmp.zip $(DISTVNAME) && unzip -o tmp.zip && $(RM_F) tmp.zip
 MAKE_TEXT
 
     return $self->SUPER::dist(%attribs);
--- ./lib/ExtUtils/MM_Unix.pm-pre	Sun Nov  3 22:34:38 2002
+++ ./lib/ExtUtils/MM_Unix.pm	Thu Mar 27 01:55:14 2003
@@ -976,12 +976,15 @@ sub dynamic_lib {
     $armaybe = 'ar' if ($^O eq 'dec_osf' and $armaybe eq ':');
     my(@m);
     my $ld_opt = $Is_OS2 ? '$(OPTIMIZE) ' : '';	# Useful on other systems too?
+    # Linker doesn't remove file on failure, only marks EXE header as invalid
+    my $ld_fix = $Is_OS2 ? '|| ( $(RM_F) $@ && sh -c false )' : '';	# Useful on other systems too?
     push(@m,'
 # This section creates the dynamically loadable $(INST_DYNAMIC)
 # from $(OBJECT) and possibly $(MYEXTLIB).
 ARMAYBE = '.$armaybe.'
 OTHERLDFLAGS = '.$ld_opt.$otherldflags.'
 INST_DYNAMIC_DEP = '.$inst_dynamic_dep.'
+INST_DYNAMIC_FIX = '.$ld_fix.'
 
 $(INST_DYNAMIC): $(OBJECT) $(MYEXTLIB) $(BOOTSTRAP) $(INST_ARCHAUTODIR)/.exists $(EXPORT_LIST) $(PERL_ARCHIVE) $(PERL_ARCHIVE_AFTER) $(INST_DYNAMIC_DEP)
 ');
@@ -1022,7 +1025,7 @@ $(INST_DYNAMIC): $(OBJECT) $(MYEXTLIB) $
 
     push(@m,
 '	LD_RUN_PATH="$(LD_RUN_PATH)" $(LD) '.$ldrun.' $(LDDLFLAGS) '.$ldfrom.
-' $(OTHERLDFLAGS) -o $@ $(MYEXTLIB) $(PERL_ARCHIVE) '.$libs.' $(PERL_ARCHIVE_AFTER) $(EXPORT_LIST)');
+' $(OTHERLDFLAGS) -o $@ $(MYEXTLIB) $(PERL_ARCHIVE) '.$libs.' $(PERL_ARCHIVE_AFTER) $(EXPORT_LIST) $(INST_DYNAMIC_FIX)');
     push @m, '
 	$(CHMOD) $(PERM_RWX) $@
 ';
@@ -1198,6 +1201,8 @@ eval 'exec $interpreter $arg -S \$0 \${1
 	close FIXIN;
 	close FIXOUT;
 
+	chmod 0666, "$file.bak";
+	unlink "$file.bak";
 	unless ( rename($file, "$file.bak") ) {	
 	    warn "Can't rename $file to $file.bak: $!";
 	    next;
--- ./lib/ExtUtils/t/Embed.t-pre	Wed Jan  8 12:54:52 2003
+++ ./lib/ExtUtils/t/Embed.t	Wed Mar 26 19:48:08 2003
@@ -155,7 +155,11 @@ static char *cmds[] = { "perl","-e", "pr
 
 int main(int argc, char **argv, char **env)
 {
-    PerlInterpreter *my_perl = perl_alloc();
+    PerlInterpreter *my_perl;
+
+    PERL_SYS_INIT3(&argc,&argv,&env);
+
+    my_perl = perl_alloc();
 
     my_puts("ok 2");
 
@@ -180,6 +184,8 @@ int main(int argc, char **argv, char **e
     perl_free(my_perl);
 
     my_puts("ok 8");
+
+    PERL_SYS_TERM();
 
     return 0;
 }
--- ./ext/Time/HiRes/HiRes.t-pre	Sun Nov  3 22:34:36 2002
+++ ./ext/Time/HiRes/HiRes.t	Thu Mar 27 00:08:02 2003
@@ -30,7 +30,7 @@ import Time::HiRes 'ualarm'		if $have_ua
 
 use Config;
 
-my $xdefine; 
+my $xdefine = '';
 
 if (open(XDEFINE, "xdefine")) {
     chomp($xdefine = <XDEFINE>);
--- ./ext/threads/threads.xs-pre	Sat Feb  1 14:28:04 2003
+++ ./ext/threads/threads.xs	Tue Mar 25 15:41:06 2003
@@ -18,7 +18,11 @@ STMT_START {\
   }\
 } STMT_END
 #else
+#ifdef OS2
+typedef perl_os_thread pthread_t;
+#else
 #include <pthread.h>
+#endif
 #include <thread.h>
 
 #define PERL_THREAD_SETSPECIFIC(k,v) pthread_setspecific(k,v)
@@ -78,7 +82,9 @@ ithread *threads;
 #define ithread_tid(thread)		((thread)->tid)
 #define ithread_yield(thread)		(YIELD);
 
-static perl_mutex create_destruct_mutex;  /* protects the creation and destruction of threads*/
+/* protects thread->next/prev, threads, known_threads, active_threads */
+static perl_mutex create_destruct_mutex;
+static int create_aborted = 0;
 
 I32 tid_counter = 0;
 I32 known_threads = 0;
@@ -154,7 +160,8 @@ int
 Perl_ithread_hook(pTHX)
 {
     int veto_cleanup = 0;
-    MUTEX_LOCK(&create_destruct_mutex);
+    if (!create_aborted)
+	MUTEX_LOCK(&create_destruct_mutex);
     if (aTHX == PL_curinterp && active_threads != 1) {
 	Perl_warn(aTHX_ "A thread exited while %" IVdf " other threads were still running",
 						(IV)active_threads);
@@ -372,8 +379,9 @@ Perl_ithread_create(pTHX_ SV *obj, char*
 	SV**            tmps_tmp = PL_tmps_stack;
 	I32             tmps_ix  = PL_tmps_ix;
 
-	PERL_THREAD_GETSPECIFIC(self_key,current_thread);
 	MUTEX_LOCK(&create_destruct_mutex);
+	create_aborted = 1;
+	PERL_THREAD_GETSPECIFIC(self_key,current_thread);
 	thread = PerlMemShared_malloc(sizeof(ithread));
 	Zero(thread,1,ithread);
 	thread->next = threads;
@@ -496,6 +504,7 @@ Perl_ithread_create(pTHX_ SV *obj, char*
 #endif
 	known_threads++;
 	active_threads++;
+	create_aborted = 0;
 	MUTEX_UNLOCK(&create_destruct_mutex);
 	sv_2mortal(params);
 
