This is a bad patch.

 a) Out of order: we are executed (and use timeslice!) in the order as for
    time-critical thread.

 b) longjmp() will live the applicaiton in time-critical priority.

--- ./makedef.pl-pre	Sun Nov  2 11:54:06 2003
+++ ./makedef.pl	Wed Dec 10 22:46:12 2003
@@ -401,6 +401,8 @@ elsif ($PLATFORM eq 'os2') {
 		    nthreads_cond
 		    os2_cond_wait
 		    os2_stat
+		    os2_execname
+		    async_mssleep
 		    pthread_join
 		    pthread_create
 		    pthread_detach
--- ./os2/os2ish.h-pre	Sun Nov  2 11:54:12 2003
+++ ./os2/os2ish.h	Wed Dec 10 23:21:52 2003
@@ -320,6 +320,8 @@ void my_setpwent (void);
 void my_endpwent (void);
 char *gcvt_os2(double value, int digits, char *buffer);
 
+extern int async_mssleep(unsigned long ms, int switch_priority);
+
 #define MAX_SLEEP	(((1<30) / (1000/4))-1)	/* 1<32 msec */
 
 static __inline__ unsigned
@@ -360,7 +362,7 @@ struct passwd *my_getpwnam (__const__ ch
 #define strtoll	_strtoll
 #define strtoull	_strtoull
 
-#define usleep(usec)	((void)_sleep2(((usec)+500)/1000))
+#define usleep(usec)	((void)async_mssleep(((usec)+500)/1000, 500))
 
 
 /*
@@ -761,7 +763,7 @@ static __inline__ int
 my_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
 {
   if (nfds == 0 && timeout && (_emx_env & 0x200)) {
-    if (DosSleep(1000 * timeout->tv_sec	+ (timeout->tv_usec + 500)/1000) == 0)
+    if (async_mssleep(1000 * timeout->tv_sec + (timeout->tv_usec + 500)/1000, 500))
       return 0;
     errno = EINTR;
     return -1;
@@ -783,6 +785,18 @@ int setpriority(int which, int pid, int 
 int getpriority(int which /* ignored */, int pid);
 
 void croak_with_os2error(char *s) __attribute__((noreturn));
+
+/* void return value */
+#define os2cp_croak(rc,msg)	(CheckOSError(rc) && (croak_with_os2error(msg),0))
+
+/* propagates rc */
+#define os2win_croak(rc,msg)						\
+	SaveCroakWinError((expr), 1 /* die */, /* no prefix */, (msg))
+
+/* propagates rc; use with functions which may return 0 on success */
+#define os2win_croak_0OK(rc,msg)					\
+	SaveCroakWinError((ResetWinError, (expr)),			\
+			  1 /* die */, /* no prefix */, (msg))
 
 #ifdef PERL_CORE
 int os2_do_spawn(pTHX_ char *cmd);
--- ./os2/os2.c-pre	Sun Nov  2 11:54:10 2003
+++ ./os2/os2.c	Thu Dec 11 01:52:16 2003
@@ -12,6 +12,7 @@
 #include <os2.h>
 #include "dlfcn.h"
 #include <emx/syscalls.h>
+#include <sys/emxload.h>
 
 #include <sys/uflags.h>
 
@@ -32,6 +33,14 @@
 #include "EXTERN.h"
 #include "perl.h"
 
+enum module_name_how { mod_name_handle, mod_name_shortname, mod_name_full,
+  mod_name_C_function = 0x100, mod_name_HMODULE = 0x200};
+
+/* Find module name to which *this* subroutine is compiled */
+#define module_name(how)	module_name_at(&module_name_at, how)
+
+static SV* module_name_at(void *pp, enum module_name_how how);
+
 void
 croak_with_os2error(char *s)
 {
@@ -2100,20 +2109,31 @@ void
 CroakWinError(int die, char *name)
 {
   FillWinError;
-  if (die && Perl_rc) {
-    dTHX;
-
-    Perl_croak(aTHX_ "%s: %s", (name ? name : "Win* API call"), os2error(Perl_rc));
-  }
+  if (die && Perl_rc)
+    croak_with_os2error(name ? name : "Win* API call");
 }
 
-char *
-os2_execname(pTHX)
+static char *
+execname2buffer(pTHX_ char *buf, STRLEN l, int is_dll)
 {
-  char buf[300], *p, *o = PL_origargv[0], ok = 1;
+  char *p, *o = PL_origargv[0], ok = 1;
+
+  if (is_dll) {
+    STRLEN ll;
+    SV *dll = Nullsv;
 
-  if (_execname(buf, sizeof buf) != 0)
-	return o;
+    dll = module_name(mod_name_full);
+    o = SvPV(dll, ll);
+    if (ll < l)
+       memcpy(buf,o,ll);
+    SvREFCNT_dec(dll);
+    return (ll >= l ? "???" : buf);
+  }
+  if (_execname(buf, l) != 0) {
+    if (strlen(o) >= l)
+      return o;
+    strcpy(buf, o);
+  }
   p = buf;
   while (*p) {
     if (*p == '\\')
@@ -2135,7 +2155,15 @@ os2_execname(pTHX)
        p++;
      }     
   }
-  p = savepv(buf);
+  return buf;
+}
+
+char *
+os2_execname(pTHX)
+{
+  char buf[300], *p = execname2buffer(aTHX_ buf, sizeof buf, 0);
+
+  p = savepv(p);
   SAVEFREEPV(p);
   return p;
 }
@@ -2143,30 +2171,81 @@ os2_execname(pTHX)
 char *
 perllib_mangle(char *s, unsigned int l)
 {
+    char *name;
     if (!newp && !notfound) {
-	newp = getenv("PERLLIB_" STRINGIFY(PERL_REVISION)
+	newp = getenv(name = "PERLLIB_" STRINGIFY(PERL_REVISION)
 		      STRINGIFY(PERL_VERSION) STRINGIFY(PERL_SUBVERSION)
 		      "_PREFIX");
 	if (!newp)
-	    newp = getenv("PERLLIB_" STRINGIFY(PERL_REVISION)
+	    newp = getenv(name = "PERLLIB_" STRINGIFY(PERL_REVISION)
 			  STRINGIFY(PERL_VERSION) "_PREFIX");
 	if (!newp)
-	    newp = getenv("PERLLIB_" STRINGIFY(PERL_REVISION) "_PREFIX");
+	    newp = getenv(name = "PERLLIB_" STRINGIFY(PERL_REVISION) "_PREFIX");
 	if (!newp)
-	    newp = getenv("PERLLIB_PREFIX");
+	    newp = getenv(name = "PERLLIB_PREFIX");
 	if (newp) {
 	    char *s;
+	    const char * const from = "~installprefix";
+	    STRLEN froml = strlen(from);
 	    
 	    oldp = newp;
 	    while (*newp && !isSPACE(*newp) && *newp != ';') {
-		newp++; oldl++;		/* Skip digits. */
+		newp++;			/* Skip old name. */
+	    }
+	    oldl = newp - oldp;
+	    if ( oldl >= froml && oldp[0] == '~' 
+		 && strnicmp(oldp+1, from + 1, froml - 1) == 0 ) {
+		if (oldl == froml) {
+		    oldp = INSTALL_PREFIX;
+		    oldl = strlen(oldp);
+		} else {
+		    char b[300];
+		    STRLEN l = strlen(INSTALL_PREFIX);
+
+		    if (oldl - froml + l >= sizeof b)
+			Perl_croak_nocontext("%s: name `%s%s' too long", name,
+					     INSTALL_PREFIX, oldp + froml);
+		    memcpy(b, INSTALL_PREFIX, l);
+		    memcpy(b + l, oldp + froml, oldl - froml);
+		    oldl += l - froml;
+		    b[oldl] = 0;
+		    oldp = savepv(b);
+		}
 	    }
 	    while (*newp && (isSPACE(*newp) || *newp == ';')) {
 		newp++;			/* Skip whitespace. */
 	    }
 	    newl = strlen(newp);
+	    if (newl >= 4 && newp[0] == '~'
+		&& (strnicmp(newp+1,"exe",3) == 0 || strnicmp(newp+1,"dll",3) == 0)) {
+		/* Base on the exe name */
+		char b[300], *e;
+		char *p = execname2buffer(aTHX_ b, sizeof b, 
+					  newp[1] == 'd' || newp[1] == 'D');
+
+		e = strrchr(p, '/');
+		if (p != b || !e)
+		    Perl_croak_nocontext("Can't parse EXE/DLL name: '%s'", p);
+		*e = 0;
+		newl -= 4; newp += 4;
+		while (newl >= 3 && (newp[0] == '/' || newp[0] == '\\')
+		       && newp[1] == '.' && newp[2] == '.') {
+		    e = strrchr(b, '/');
+		    if (!e)
+			Perl_croak_nocontext("%s: Error stripping dirs from EXE name", name);
+		    *e = 0;
+		    newl -= 3; newp += 3;
+		}
+		if (newp[0] && newp[0] != '/' && newp[0] != '\\')
+		    *e++ = '/';
+		if (e + newl >= p + sizeof b)
+		    Perl_croak_nocontext("%s: name `%s%s' too long", name, b, newp);
+		memcpy(e, newp, newl + 1);
+		newl += e - b;
+		newp = savepv(b);
+	    }
 	    if (newl == 0 || oldl == 0) {
-		Perl_croak_nocontext("Malformed PERLLIB_PREFIX");
+		Perl_croak_nocontext("Malformed %s", name);
 	    }
 	    strcpy(mangle_ret, newp);
 	    s = mangle_ret;
@@ -2394,6 +2473,85 @@ XS(XS_OS2_Errors2Drive)
     XSRETURN(1);
 }
 
+int
+async_mssleep(ULONG ms, int switch_priority) {
+  /* This is similar to DosSleep(), but has 8ms granularity in time-critical
+     threads even on Warp3. */
+  HEV     hevEvent1     = 0;                   /* Event semaphore handle    */
+  HTIMER  htimerEvent1  = 0;                   /* Timer handle              */
+  APIRET  rc            = NO_ERROR;            /* Return code               */
+  int ret = 1;
+  ULONG priority;
+  PPIB pib;
+  PTIB tib;
+  char *e = NULL;
+  APIRET badrc;
+
+  if (!(_emx_env & 0x200))	/* DOS */
+    return !_sleep2(ms);
+
+  os2cp_croak(DosCreateEventSem(NULL,	     /* Unnamed */
+				&hevEvent1,  /* Handle of semaphore returned */
+				DC_SEM_SHARED, /* Shared needed for DosAsyncTimer */
+				FALSE),      /* Semaphore is in RESET state  */
+	      "DosCreateEventSem");
+
+  /* On Warp3fp42 it is the priority at the time of DosAsyncTimer() which matters... */
+  if (ms >= switch_priority)
+    switch_priority = 0;
+  if (switch_priority) {
+    if (CheckOSError(DosGetInfoBlocks(&tib, &pib))) 
+	switch_priority = 0;
+    else {
+	priority = (tib->tib_ptib2->tib2_ulpri);
+	if ((priority & 0xFF00) == 0x0300) /* already time-critical */
+	    switch_priority = 0;
+	/* tib->tib_ptib2->tib2_ulpri = 0x0300;*/	/* Make us time-critical */
+	DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0);
+    }
+  }
+
+  if ((badrc = DosAsyncTimer(ms,
+			     (HSEM) hevEvent1,	/* Semaphore to post        */
+			     &htimerEvent1))) {	/* Timer handler (returned) */
+     DosCloseEventSem(hevEvent1);		/* Ignore error */
+     e = "DosAsyncTimer";
+  }
+
+  if (!e)					/* Wait for AsyncTimer event */
+      badrc = DosWaitEventSem(hevEvent1, SEM_INDEFINITE_WAIT);
+
+  if (switch_priority && tib->tib_ptib2->tib2_ulpri == 0x0300) {
+	/* Nobody switched priority while we slept... */
+	/* tib->tib_ptib2->tib2_ulpri = priority; */	/* Get back... */
+	DosSetPriority(PRTYS_THREAD, (priority>>8) & 0xFF, 0, 0);
+	DosSetPriority(PRTYS_THREAD, 0, priority & 0xFF, 0);
+  }
+
+  if (e) ;				/* Do nothing */
+  else if (badrc == ERROR_INTERRUPT)
+     ret = 0;
+  else if (badrc)
+     e = "DosWaitEventSem";
+  if ((rc = DosCloseEventSem(hevEvent1)) && !e) { /* Get rid of semaphore */
+     e = "DosCloseEventSem";
+     badrc = rc;
+  }
+  if (e)
+     os2cp_croak(badrc, e);
+  return ret;
+}
+
+XS(XS_OS2_hr_sleep)		/* for testing only... */
+{
+    dXSARGS;
+
+    if (items != 2)
+	Perl_croak_nocontext("Usage: OS2::timer2hr(wait_ms, high_priority_limit)");
+    async_mssleep(SvUV(ST(0)), SvIV(ST(1)));
+    XSRETURN_EMPTY;
+}
+
 ULONG (*pDosTmrQueryFreq) (PULONG);
 ULONG (*pDosTmrQueryTime) (unsigned long long *);
 
@@ -3243,7 +3401,7 @@ XS(XS_Cwd_extLibpath)
 {
     dXSARGS;
     if (items < 0 || items > 1)
-	Perl_croak_nocontext("Usage: Cwd::extLibpath(type = 0)");
+	Perl_croak_nocontext("Usage: OS2::extLibpath(type = 0)");
     {
 	IV	type;
 	char	to[1024];
@@ -3260,7 +3418,7 @@ XS(XS_Cwd_extLibpath)
 	to[0] = 1; to[1] = 0;		/* Sometimes no error reported */
 	RETVAL = extLibpath(to, type);
 	if (RETVAL && RETVAL[0] == 1 && RETVAL[1] == 0)
-	    Perl_croak_nocontext("panic Cwd::extLibpath parameter");
+	    Perl_croak_nocontext("panic OS2::extLibpath parameter");
 	sv_setpv(TARG, RETVAL);
 	XSprePUSH; PUSHTARG;
     }
@@ -3271,7 +3429,7 @@ XS(XS_Cwd_extLibpath_set)
 {
     dXSARGS;
     if (items < 1 || items > 2)
-	Perl_croak_nocontext("Usage: Cwd::extLibpath_set(s, type = 0)");
+	Perl_croak_nocontext("Usage: OS2::extLibpath_set(s, type = 0)");
     {
 	STRLEN n_a;
 	char *	s = (char *)SvPV(ST(0),n_a);
@@ -3303,9 +3461,6 @@ DeclOSFuncByORD(APIRET, _DosQueryModFrom
 			ULONG * Offset, ULONG Address),
 			(hmod, obj, BufLen, Buf, Offset, Address))
 
-enum module_name_how { mod_name_handle, mod_name_shortname, mod_name_full,
-  mod_name_C_function = 0x100, mod_name_HMODULE = 0x200};
-
 static SV*
 module_name_at(void *pp, enum module_name_how how)
 {
@@ -3351,9 +3506,6 @@ module_name_of_cv(SV *cv, enum module_na
     return module_name_at(CvXSUB(SvRV(cv)), how);
 }
 
-/* Find module name to which *this* subroutine is compiled */
-#define module_name(how)	module_name_at(&module_name_at, how)
-
 XS(XS_OS2_DLLname)
 {
     dXSARGS;
@@ -3589,6 +3741,8 @@ Xs_OS2_init(pTHX)
             newXS("File::Copy::syscopy", XS_File__Copy_syscopy, file);
             newXS("Cwd::extLibpath", XS_Cwd_extLibpath, file);
             newXS("Cwd::extLibpath_set", XS_Cwd_extLibpath_set, file);
+            newXS("OS2::extLibpath", XS_Cwd_extLibpath, file);
+            newXS("OS2::extLibpath_set", XS_Cwd_extLibpath_set, file);
 	}
         newXS("OS2::Error", XS_OS2_Error, file);
         newXS("OS2::Errors2Drive", XS_OS2_Errors2Drive, file);
@@ -3620,6 +3774,7 @@ Xs_OS2_init(pTHX)
         newXSproto("OS2::_headerInfo", XS_OS2__headerInfo, file, "$$;$$");
         newXSproto("OS2::libPath", XS_OS2_libPath, file, "");
         newXSproto("OS2::Timer", XS_OS2_Timer, file, "");
+        newXSproto("OS2::hr_sleep", XS_OS2_hr_sleep, file, "$$");
         newXSproto("OS2::incrMaxFHandles", XS_OS2_incrMaxFHandles, file, ";$");
         newXSproto("OS2::SysValues", XS_OS2_SysValues, file, ";$$");
         newXSproto("OS2::SysValues_set", XS_OS2_SysValues_set, file, "$$;$");
@@ -4032,6 +4187,7 @@ Perl_OS2_init3(char **env, void **preg, 
     os2_mytype = my_type();		/* Do it before morphing.  Needed? */
     os2_mytype_ini = os2_mytype;
     Perl_os2_initial_mode = -1;		/* Uninit */
+    _emxload_env("PERL_EMXLOAD_SECS");
     /* Some DLLs reset FP flags on load.  We may have been linked with them */
     _control87(MCW_EM, MCW_EM);
 }
