Copied the current tip of Netscape's internal development version of NSPRPUB_19980421_BRANCH
authorwtc
Tue, 21 Apr 1998 21:09:30 +0000
branchNSPRPUB_19980421_BRANCH
changeset 55 96763b5d836a4ec73a6081b2c300e2ed192ff8f5
parent 52 3c8688d587e5fe45d957986705be1e08a701747e
child 57 d5c6a396068890049f94b33c6d0ecffba2db9176
push idunknown
push userunknown
push dateunknown
Copied the current tip of Netscape's internal development version of NSPR to the NSPRPUB_19980421_BRANCH of the public ns/nsprpub at mozilla.org.
lib/ds/plevent.c
lib/ds/plevent.h
lib/msgc/src/prmsgc.c
lib/prstreams/prstrms.cpp
pr/include/md/_aix.h
pr/include/md/_freebsd.h
pr/include/md/_irix.cfg
pr/include/md/_irix.h
pr/include/md/_linux.h
pr/include/md/_macos.h
pr/include/md/_ncr.cfg
pr/include/md/_os2.cfg
pr/include/md/_os2.h
pr/include/md/_os2_errors.h
pr/include/md/_osf1.cfg
pr/include/md/_pcos.h
pr/include/md/_pth.h
pr/include/md/_reliantunix.cfg
pr/include/md/_scoos.cfg
pr/include/md/_unix_errors.h
pr/include/md/_unixos.h
pr/include/md/_unixware.cfg
pr/include/md/_win32_errors.h
pr/include/md/_win95.h
pr/include/md/_winnt.h
pr/include/obsolete/protypes.h
pr/include/prbit.h
pr/include/prdtoa.h
pr/include/prinet.h
pr/include/prio.h
pr/include/private/pprio.h
pr/include/private/primpl.h
pr/include/prmwait.h
pr/include/prtypes.h
pr/include/prwin16.h
pr/src/io/pprmwait.h
pr/src/io/prfile.c
pr/src/io/prio.c
pr/src/io/prlayer.c
pr/src/io/prmapopt.c
pr/src/io/prprf.c
pr/src/io/prscanf.c
pr/src/io/prsocket.c
pr/src/md/mac/macsockotpt.c
pr/src/md/os2/os2cv.c
pr/src/md/os2/os2gc.c
pr/src/md/os2/os2io.c
pr/src/md/os2/os2misc.c
pr/src/md/os2/os2thred.c
pr/src/md/unix/aix.c
pr/src/md/unix/freebsd.c
pr/src/md/unix/irix.c
pr/src/md/unix/linux.c
pr/src/md/unix/os_AIX.s
pr/src/md/unix/os_BSD_386_2.s
pr/src/md/unix/os_ReliantUNIX.s
pr/src/md/unix/os_SunOS_ultrasparc.s
pr/src/md/unix/unix.c
pr/src/md/unix/unix_errors.c
pr/src/md/windows/ntio.c
pr/src/md/windows/ntmisc.c
pr/src/md/windows/ntthread.c
pr/src/md/windows/w16null.c
pr/src/md/windows/w95thred.c
pr/src/md/windows/win32_errors.c
pr/src/misc/pratom.c
pr/src/misc/prdtoa.c
pr/src/misc/prinit.c
pr/src/misc/prnetdb.c
pr/src/misc/prtime.c
pr/src/pthreads/ptio.c
pr/src/pthreads/ptsynch.c
pr/src/pthreads/ptthread.c
pr/src/threads/combined/prucv.c
pr/src/threads/combined/prulock.c
pr/src/threads/combined/pruthr.c
pr/src/threads/prcthr.c
pr/src/threads/prdump.c
pr/tests/accept.c
pr/tests/alarm.c
pr/tests/atomic.c
pr/tests/attach.c
pr/tests/cltsrv.c
pr/tests/intrupt.c
pr/tests/io_timeout.c
pr/tests/ipv6.c
pr/tests/layer.c
pr/tests/many_cv.c
pr/tests/nonblock.c
pr/tests/poll_nm.c
pr/tests/poll_to.c
pr/tests/priotest.c
pr/tests/ranfile.c
pr/tests/sel_spd.c
pr/tests/selct_nm.c
pr/tests/selct_to.c
pr/tests/servr_kk.c
pr/tests/servr_ku.c
pr/tests/servr_uk.c
pr/tests/servr_uu.c
pr/tests/socket.c
pr/tests/suspend.c
pr/tests/testfile.c
pr/tests/thruput.c
pr/tests/tmocon.c
pr/tests/udpsrv.c
pr/tests/w16gui/poppad.rc
pr/tests/yield.c
tools/httpget.c
--- a/lib/ds/plevent.c
+++ b/lib/ds/plevent.c
@@ -10,19 +10,16 @@
  * for the specific language governing rights and limitations under the
  * NPL.
  * 
  * The Initial Developer of this code under the NPL is Netscape
  * Communications Corporation.  Portions created by Netscape are
  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  * Reserved.
  */
-#if defined(WIN16)
-#include <windows.h>
-#endif
 #include "plevent.h"
 #include "prmem.h"
 #include "prcmon.h"
 #include "prlog.h"
 #if !defined(WIN32)
 #include <errno.h>
 #include <stddef.h>
 #if !defined(OS2)
--- a/lib/ds/plevent.h
+++ b/lib/ds/plevent.h
@@ -165,16 +165,23 @@ and to ensure that no more events will b
 #ifndef prevent_h___
 #define prevent_h___
 
 #include "prtypes.h"
 #include "prclist.h"
 #include "prthread.h"
 #include "prmon.h"
 
+/* For HWND */
+#ifdef _WIN32
+#include <windef.h>
+#elif defined(WIN16)
+#include <windows.h>
+#endif
+
 PR_BEGIN_EXTERN_C
 
 /* Typedefs */
 
 typedef struct PLEvent PLEvent;
 typedef struct PLEventQueue PLEventQueue;
 
 /*******************************************************************************
--- a/lib/msgc/src/prmsgc.c
+++ b/lib/msgc/src/prmsgc.c
@@ -16,16 +16,21 @@
  * Reserved.
  */
 
 #include <string.h>
 #include <stddef.h>
 #include <stdarg.h>
 #include <time.h>
 
+#ifdef WIN32
+#include <windef.h>
+#include <winbase.h>
+#endif
+
 #include "prclist.h"
 #include "prbit.h"
 
 #include "prtypes.h"
 #include "prenv.h"
 #include "prgc.h"
 #include "prthread.h"
 #include "prlog.h"
@@ -2360,17 +2365,17 @@ PR_TraceRoot()
     */
     PR_DumpToFile("memory.out", "Tracing Roots", PR_TraceRoot1, PR_FALSE);
 }
 
 #endif /* GC_TRACEROOTS */
 
 /******************************************************************************/
 
-#if defined(DEBUG) && defined(_WIN32)
+#if defined(DEBUG) && defined(WIN32)
 static void DumpApplicationHeap(FILE *out, HANDLE heap)
 {
     PROCESS_HEAP_ENTRY entry;
     DWORD err;
 
     if (!HeapLock(heap))
     OutputDebugString("Can't lock the heap.\n");
     entry.lpData = 0;
--- a/lib/prstreams/prstrms.cpp
+++ b/lib/prstreams/prstrms.cpp
@@ -16,19 +16,17 @@
  * Reserved.
  */
 
 /*
  * Robin J. Maxwell 11-22-96
  */
 
 #include "prstrms.h"
-#ifdef SVR4
 #include <string.h> // memmove
-#endif
 
 //
 // Definition of macros _PRSTR_BP, _PRSTR_DELBUF, and _PRSTR_DELBUF_C.
 //
 // _PRSTR_BP is the protected member of class ios that is returned
 // by the public method rdbuf().
 //
 // _PRSTR_DELBUF is the method or data member of class ios, if available,
--- a/pr/include/md/_aix.h
+++ b/pr/include/md/_aix.h
@@ -33,36 +33,43 @@
 #include <sys/poll.h>
 #endif
 
 /*
  * Internal configuration macros
  */
 
 #define PR_LINKER_ARCH          "aix"
-#define _PR_SI_SYSNAME		"AIX"
-#define _PR_SI_ARCHITECTURE	"rs6000"
-#define PR_DLL_SUFFIX		".so"
+#define _PR_SI_SYSNAME		    "AIX"
+#define _PR_SI_ARCHITECTURE	    "rs6000"
+#define PR_DLL_SUFFIX		    ".so"
 
-#define _PR_VMBASE	 	0x30000000
-#define _PR_STACK_VMBASE	0x50000000
+#define _PR_VMBASE	 	        0x30000000
+#define _PR_STACK_VMBASE	    0x50000000
 #define _MD_DEFAULT_STACK_SIZE	65536L
-#define _MD_MMAP_FLAGS		MAP_PRIVATE
+#define _MD_MMAP_FLAGS		    MAP_PRIVATE
 
 #define NEED_TIME_R
 #undef  HAVE_STACK_GROWING_UP
 #undef	HAVE_WEAK_IO_SYMBOLS
 #undef	HAVE_WEAK_MALLOC_SYMBOLS
 #define	HAVE_DLL
 #define	USE_DLFCN
+#define _PR_HAVE_SOCKADDR_LEN
 
-#undef _PR_HAVE_ATOMIC_OPS
+#define _MD_GET_INTERVAL        _PR_UNIX_GetInterval
+#define _MD_INTERVAL_PER_SEC    _PR_UNIX_TicksPerSecond
 
-#define _MD_GET_INTERVAL                  _PR_UNIX_GetInterval
-#define _MD_INTERVAL_PER_SEC              _PR_UNIX_TicksPerSecond
+/* The atomic operations */
+#include <sys/atomic_op.h>
+#define _PR_HAVE_ATOMIC_OPS
+#define _MD_INIT_ATOMIC()
+#define _MD_ATOMIC_INCREMENT(val)   ((PRInt32)fetch_and_add((atomic_p)val, 1) + 1)
+#define _MD_ATOMIC_DECREMENT(val)   ((PRInt32)fetch_and_add((atomic_p)val, -1) - 1)
+#define _MD_ATOMIC_SET(val, newval) _AIX_AtomicSet(val, newval)
 
 #define USE_SETJMP
 
 #include <setjmp.h>
 
 #define _MD_GET_SP(_t)				(_t)->md.jb[3]
 #define _MD_SET_THR_SP(_t, _sp)		((_t)->md.jb[3] = (int) (_sp - 2 * 64))
 #define PR_NUM_GCREGS				_JBLEN
--- a/pr/include/md/_freebsd.h
+++ b/pr/include/md/_freebsd.h
@@ -31,16 +31,17 @@
 #define _PR_VMBASE              0x30000000
 #define _PR_STACK_VMBASE	0x50000000
 #define _MD_DEFAULT_STACK_SIZE	65536L
 #define _MD_MMAP_FLAGS          MAP_PRIVATE
 
 #undef  HAVE_STACK_GROWING_UP
 #define HAVE_DLL
 #define USE_DLFCN
+#define _PR_HAVE_SOCKADDR_LEN
 
 #define USE_SETJMP
 
 #ifndef _PR_PTHREADS
 #include <setjmp.h>
 
 #define PR_CONTEXT_TYPE	sigjmp_buf
 
@@ -151,51 +152,16 @@ extern PRIntervalTime _PR_UNIX_TicksPerS
 #define _MD_INTERVAL_PER_SEC              _PR_UNIX_TicksPerSecond
 
 /*
  * We wrapped the select() call.  _MD_SELECT refers to the built-in,
  * unwrapped version.
  */
 #define _MD_SELECT(nfds,r,w,e,tv) syscall(SYS_select,nfds,r,w,e,tv)
 
-#if defined(_PR_NEED_FAKE_POLL)
-
-/*
- * XXX: FreeBSD2 doesn't have poll(), but our pthreads code calls poll().
- * As a temporary measure, I implemented a fake poll() using select().
- * Here are the struct and macro definitions copied from sys/poll.h
- * on Solaris 2.5.
- */
-
-struct pollfd {
-    int fd;
-    short events;
-    short revents;
-};
-
-/* poll events */
-
-#define	POLLIN		0x0001		/* fd is readable */
-#define	POLLPRI		0x0002		/* high priority info at fd */
-#define	POLLOUT		0x0004		/* fd is writeable (won't block) */
-#define	POLLRDNORM	0x0040		/* normal data is readable */
-#define	POLLWRNORM	POLLOUT
-#define	POLLRDBAND	0x0080		/* out-of-band data is readable */
-#define	POLLWRBAND	0x0100		/* out-of-band data is writeable */
-
-#define	POLLNORM	POLLRDNORM
-
-#define	POLLERR		0x0008		/* fd has error condition */
-#define	POLLHUP		0x0010		/* fd has been hung up on */
-#define	POLLNVAL	0x0020		/* invalid pollfd entry */
-
-extern int poll(struct pollfd *, unsigned long, int);
-
-#endif /* _PR_NEED_FAKE_POLL */
-
 /* freebsd has INADDR_LOOPBACK defined, but in /usr/include/rpc/types.h, and I didn't
    want to be including that.. */
 #ifndef INADDR_LOOPBACK
 #define INADDR_LOOPBACK         (u_long)0x7F000001
 #endif
 
 /* For writev() */
 #include <sys/uio.h>
--- a/pr/include/md/_irix.cfg
+++ b/pr/include/md/_irix.cfg
@@ -73,16 +73,19 @@
 #define PR_ALIGN_OF_DOUBLE  8
 #define PR_ALIGN_OF_POINTER 4
 #define PR_ALIGN_OF_WORD    4
 
 #define HAVE_LONG_LONG
 #define HAVE_ALIGNED_DOUBLES
 #define HAVE_ALIGNED_LONGLONGS
 
+#define _PR_POLL_AVAILABLE
+#define _PR_USE_POLL
+
 #ifndef NO_NSPR_10_SUPPORT
 
 #define BYTES_PER_BYTE		PR_BYTES_PER_BYTE
 #define BYTES_PER_SHORT 	PR_BYTES_PER_SHORT
 #define BYTES_PER_INT 		PR_BYTES_PER_INT
 #define BYTES_PER_INT64		PR_BYTES_PER_INT64
 #define BYTES_PER_LONG		PR_BYTES_PER_LONG
 #define BYTES_PER_FLOAT		PR_BYTES_PER_FLOAT
--- a/pr/include/md/_irix.h
+++ b/pr/include/md/_irix.h
@@ -126,18 +126,18 @@ PR_EXTERN(struct PRThread*) _MD_get_atta
 		if (_pr_irix_exit_now) {			\
 			_PR_POST_SEM(_pr_irix_exit_sem);	\
 			exit(0);				\
 		}						\
 	}
 		
 #define _MD_ATTACH_THREAD(threadp)
 
-#define _MD_SAVE_ERRNO(_thread)
-#define _MD_RESTORE_ERRNO(_thread)
+#define _MD_SAVE_ERRNO(_thread)			(_thread)->md.errcode = errno;
+#define _MD_RESTORE_ERRNO(_thread)		errno = (_thread)->md.errcode;
 
 extern struct _PRCPU  *_pr_primordialCPU;
 extern usema_t *_pr_irix_exit_sem;
 extern PRInt32 _pr_irix_exit_now;
 
 /* Thread operations */
 #define _PR_LOCK_HEAP()	{						\
 			PRIntn _is;					\
@@ -211,16 +211,19 @@ struct _MDThread {
     usptr_t     *pollsem_arena;
     usema_t     *cvar_pollsem;
     PRInt32     cvar_pollsemfd;
     PRInt32     cvar_pollsem_select;    /* acquire sem by calling select */
     PRInt32     cvar_wait;              /* if 1, thread is waiting on cvar Q */
     PRInt32	id;
     PRInt32	suspending_id;
     int errcode;
+    PRStatus	*creation_status;	/* points to the variable in which
+					 * a newly created child thread is
+					 * to store its creation status */
 };
 
 struct _MDThreadStack {
     PRInt8 notused;
 };
 
 struct _MDSemaphore {
     usema_t *sem;
--- a/pr/include/md/_linux.h
+++ b/pr/include/md/_linux.h
@@ -51,24 +51,20 @@
 #if defined(LINUX1_2) || defined(LINUX2_0)
 #define HAVE_DLL
 #define USE_DLFCN
 #else
 #undef	HAVE_DLL
 #undef	USE_DLFCN
 #endif
 
-#if !defined(MACLINUX) && !defined(NEED_TIME_R)
+#if !defined(MKLINUX) && !defined(NEED_TIME_R)
 #define NEED_TIME_R
 #endif
 
-#if defined(_PR_PTHREADS) && !(defined(__GLIBC__) && __GLIBC__ >= 2)
-#define _PR_NEED_FAKE_POLL
-#endif
-
 #define USE_SETJMP
 
 #ifdef _PR_PTHREADS
 
 extern void _MD_CleanupBeforeExit(void);
 #define _MD_CLEANUP_BEFORE_EXIT _MD_CleanupBeforeExit
 
 #else  /* ! _PR_PTHREADS */
@@ -245,47 +241,19 @@ extern PRIntervalTime _PR_UNIX_TicksPerS
 #define _MD_INTERVAL_PER_SEC            _PR_UNIX_TicksPerSecond
 
 /*
  * We wrapped the select() call.  _MD_SELECT refers to the built-in,
  * unwrapped version.
  */
 #define _MD_SELECT __select
 
-#if defined(_PR_NEED_FAKE_POLL)
-
-/*
- * XXX: Linux doesn't have poll(), but our pthreads code calls poll().
- * As a temporary measure, I implemented a fake poll() using select().
- * Here are the struct and macro definitions copied from sys/poll.h
- * on Solaris 2.5.
- */
-
-struct pollfd {
-    int fd;
-    short events;
-    short revents;
-};
-
-/* poll events */
-
-#define	POLLIN		0x0001		/* fd is readable */
-#define	POLLPRI		0x0002		/* high priority info at fd */
-#define	POLLOUT		0x0004		/* fd is writeable (won't block) */
-#define	POLLRDNORM	0x0040		/* normal data is readable */
-#define	POLLWRNORM	POLLOUT
-#define	POLLRDBAND	0x0080		/* out-of-band data is readable */
-#define	POLLWRBAND	0x0100		/* out-of-band data is writeable */
-
-#define	POLLNORM	POLLRDNORM
-
-#define	POLLERR		0x0008		/* fd has error condition */
-#define	POLLHUP		0x0010		/* fd has been hung up on */
-#define	POLLNVAL	0x0020		/* invalid pollfd entry */
-
-extern int poll(struct pollfd *, unsigned long, int);
-
-#endif /* _PR_NEED_FAKE_POLL */
+#ifdef _PR_POLL_AVAILABLE
+#include <poll.h>
+extern int __syscall_poll(struct pollfd *ufds, unsigned long int nfds,
+	int timeout);
+#define _MD_POLL __syscall_poll
+#endif
 
 /* For writev() */
 #include <sys/uio.h>
 
 #endif /* nspr_linux_defs_h___ */
--- a/pr/include/md/_macos.h
+++ b/pr/include/md/_macos.h
@@ -325,21 +325,21 @@ typedef enum IOOperation {
 
 #define	_MD_GETFILEINFO 	_MD_GetFileInfo
 #define	_MD_GETOPENFILEINFO _MD_GetOpenFileInfo
 
 #define	_MD_STAT 			_MD_Stat
 
 #define	_MD_DELETE 			_MD_Delete
 
-PR_EXTERN(PRStatus) _MD_LockFile(PRInt32 osfd);
+extern PRStatus _MD_LockFile(PRInt32 osfd);
 #define	_MD_LOCKFILE 		_MD_LockFile
-PR_EXTERN(PRStatus) _MD_TLockFile(PRInt32 osfd);
+extern PRStatus _MD_TLockFile(PRInt32 osfd);
 #define	_MD_TLOCKFILE 		_MD_TLockFile
-PR_EXTERN(PRStatus) _MD_UnlockFile(PRInt32 osfd);
+extern PRStatus _MD_UnlockFile(PRInt32 osfd);
 #define	_MD_UNLOCKFILE		_MD_UnlockFile
 
 /* 
 ** Directory enumeration related definitions 
 */
 
 extern PRStatus _MD_OpenDir(struct _MDDir *md,const char *name);
 #define	_MD_OPEN_DIR 		_MD_OpenDir
@@ -379,17 +379,17 @@ extern PRStatus _MD_setsockopt(PRFileDes
 #define _MD_MAKE_NONBLOCK	_MD_makenonblock
 
 #define _MD_GET_SOCKET_ERROR() 		_PR_MD_CURRENT_THREAD()->md.osErrCode
 
 #define _PR_MD_MAP_SELECT_ERROR(x) 	(x)
 /*
 ** Netdb Related definitions
 */
-PR_EXTERN(PRStatus) _MD_gethostname(char *name, int namelen);
+extern PRStatus _MD_gethostname(char *name, int namelen);
 #define _MD_GETHOSTNAME		_MD_gethostname
 
 /* 
 	XXX _MD_WRITEV, _MD_SHUTDOWN & _MD_GETPEERNAME not done yet!!!
 */
 #define _MD_WRITEV			_MD_writev
 #define _MD_SHUTDOWN		_MD_shutdown
 #define _MD_GETPEERNAME		_MD_getpeername
--- a/pr/include/md/_ncr.cfg
+++ b/pr/include/md/_ncr.cfg
@@ -66,16 +66,17 @@
 #define PR_ALIGN_OF_SHORT   2
 #define PR_ALIGN_OF_INT     4
 #define PR_ALIGN_OF_LONG    4
 #define PR_ALIGN_OF_INT64   4
 #define PR_ALIGN_OF_FLOAT   4
 #define PR_ALIGN_OF_DOUBLE  4
 #define PR_ALIGN_OF_POINTER 4
 
+#define _PR_POLL_AVAILABLE
 #define _PR_USE_POLL
 
 #ifndef NO_NSPR_10_SUPPORT
 
 #define BYTES_PER_BYTE		PR_BYTES_PER_BYTE
 #define BYTES_PER_SHORT 	PR_BYTES_PER_SHORT
 #define BYTES_PER_INT 		PR_BYTES_PER_INT
 #define BYTES_PER_INT64		PR_BYTES_PER_INT64
--- a/pr/include/md/_os2.cfg
+++ b/pr/include/md/_os2.cfg
@@ -71,16 +71,19 @@
 #define PR_ALIGN_OF_LONG    4
 #define PR_ALIGN_OF_INT64   4
 #define PR_ALIGN_OF_FLOAT   4
 #define PR_ALIGN_OF_DOUBLE  4
 #define PR_ALIGN_OF_WORD	4
 #define PR_ALIGN_OF_DWORD	8
 #define PR_ALIGN_OF_POINTER 4
 
+#define PR_BYTES_PER_WORD_LOG2	2
+#define PR_BYTES_PER_DWORD_LOG2	2
+
 #ifndef NO_NSPR_10_SUPPORT
 
 #define BYTES_PER_BYTE      PR_BYTES_PER_BYTE
 #define BYTES_PER_SHORT     PR_BYTES_PER_SHORT
 #define BYTES_PER_INT       PR_BYTES_PER_INT
 #define BYTES_PER_INT64     PR_BYTES_PER_INT64
 #define BYTES_PER_LONG      PR_BYTES_PER_LONG
 #define BYTES_PER_FLOAT     PR_BYTES_PER_FLOAT
--- a/pr/include/md/_os2.h
+++ b/pr/include/md/_os2.h
@@ -18,17 +18,19 @@
 
 #ifndef nspr_os2_defs_h___
 #define nspr_os2_defs_h___
 
 #define INCL_DOS
 #define INCL_DOSERRORS
 #define INCL_WIN
 #define INCL_WPS
+#define TID OS2TID   /* global rename in OS2 H's!               */
 #include <os2.h>
+#undef TID           /* and restore                             */
 #include <sys/select.h>
 
 #include "prio.h"
 
 #include <errno.h>
 
 /*
  * Internal configuration macros
@@ -37,57 +39,64 @@
 #define PR_LINKER_ARCH      "os2"
 #define _PR_SI_SYSNAME        "OS2"
 #define _PR_SI_ARCHITECTURE   "x86"    /* XXXMB hardcode for now */
 
 #define HAVE_DLL
 #undef  HAVE_THREAD_AFFINITY
 #define HAVE_SOCKET_REUSEADDR
 #define HAVE_SOCKET_KEEPALIVE
-#define _PR_HAVE_ATOMIC_OPS
+
+/*********************************************                                                
+/* We don't have atomic ops on OS/2 natively */
+/* #define _PR_HAVE_ATOMIC_OPS               */
+/*********************************************/
 
 #define HANDLE unsigned long
 #define HINSTANCE HMODULE
 
 /* --- Common User-Thread/Native-Thread Definitions --------------------- */
 
 /* --- Globals --- */
 extern struct PRLock                      *_pr_schedLock;
 
 /* --- Typedefs --- */
 typedef void (*FiberFunc)(void *);
 
 #define PR_NUM_GCREGS           8
 typedef PRInt32	                PR_CONTEXT_TYPE[PR_NUM_GCREGS];
 #define GC_VMBASE               0x40000000
 #define GC_VMLIMIT              0x00FFFFFF
+typedef int (*FARPROC)();
 
 #define _MD_MAGIC_THREAD	0x22222222
 #define _MD_MAGIC_THREADSTACK	0x33333333
 #define _MD_MAGIC_SEGMENT	0x44444444
 #define _MD_MAGIC_DIR		0x55555555
 #define _MD_MAGIC_CV        0x66666666
 
+#define CALLBACK
+
 typedef struct _MDSemaphore
 {
    HEV sem;
 } MDSEM;
 
 struct _MDCPU {
     int              unused;
 }; 
 
 struct _MDThread {
     MDSEM            blocked_sema;       /* Threads block on this when waiting
                                          * for IO or CondVar.
                                          */
     PRBool           inCVWaitQueue;     /* PR_TRUE if the thread is in the
                                          * wait queue of some cond var.
                                          * PR_FALSE otherwise.  */
-    TID              handle;            /* OS/2 thread handle */
+    OS2TID           handle;            /* OS/2 thread handle */
     void            *sp;                /* only valid when suspended */
     PRUint32         magic;             /* for debugging */
     PR_CONTEXT_TYPE  gcContext;         /* Thread context for GC */
     struct PRThread *prev, *next;       /* used by the cvar wait queue to
                                          * chain the PRThread structures
                                          * together */
 };
 
@@ -128,17 +137,17 @@ struct _MDNotified {
         struct _MDCVar *cv;            /* the condition variable notified */
         PRIntn times;                  /* and the number of times notified */
         struct PRThread *notifyHead;   /* list of threads to wake up */
     } cv[_MD_CV_NOTIFIED_LENGTH];
     _MDNotified *link;                 /* link to another of these, or NULL */
 };
 
 struct _MDLock {
-    CRITICAL_SECTION mutex;          /* this is recursive on NT */
+    HMTX mutex;          /* this is recursive on NT */
 
     /*
      * When notifying cvars, there is no point in actually
      * waking up the threads waiting on the cvars until we've
      * released the lock.  So, we temporarily record the cvars.
      * When doing an unlock, we'll then wake up the waiting threads.
      */
     struct _MDNotified notified;     /* array of conditions notified */
@@ -184,16 +193,20 @@ extern PRInt32 _MD_CloseFile(PRInt32 osf
 #define _MD_DELETE                    _PR_MD_DELETE     
 #define _MD_MKDIR                     _PR_MD_MKDIR      
 #define _MD_RMDIR                     _PR_MD_RMDIR      
 #define _MD_LOCKFILE                  _PR_MD_LOCKFILE
 #define _MD_TLOCKFILE                 _PR_MD_TLOCKFILE
 #define _MD_UNLOCKFILE                _PR_MD_UNLOCKFILE
 
 /* --- Socket IO stuff --- */
+
+/* The ones that don't map directly may need to be re-visited... */
+#define EPIPE                     EBADF
+#define EIO                       ECONNREFUSED
 #define _MD_EACCES                EACCES
 #define _MD_EADDRINUSE            EADDRINUSE
 #define _MD_EADDRNOTAVAIL         EADDRNOTAVAIL
 #define _MD_EAFNOSUPPORT          EAFNOSUPPORT
 #define _MD_EAGAIN                EWOULDBLOCK
 #define _MD_EALREADY              EALREADY
 #define _MD_EBADF                 EBADF
 #define _MD_ECONNREFUSED          ECONNREFUSED
@@ -225,24 +238,20 @@ extern PRInt32 _MD_CloseSocket(PRInt32 o
 #define _MD_SOCKETPAIR(s, type, proto, sv) -1
 #define _MD_GETSOCKNAME               _PR_MD_GETSOCKNAME
 #define _MD_GETPEERNAME               _PR_MD_GETPEERNAME
 #define _MD_GETSOCKOPT                _PR_MD_GETSOCKOPT
 #define _MD_SETSOCKOPT                _PR_MD_SETSOCKOPT
 #define _MD_SELECT                    select
 #define _MD_FSYNC                     _PR_MD_FSYNC
 
-long _System InterlockedIncrement(PLONG);
-long _System InterlockedDecrement(PLONG);
-long _System InterlockedExchange(PLONG, LONG);
-
-#define _MD_INIT_ATOMIC()
-#define _MD_ATOMIC_INCREMENT(x)       InterlockedIncrement((PLONG)x)
-#define _MD_ATOMIC_DECREMENT(x)       InterlockedDecrement((PLONG)x)
-#define _MD_ATOMIC_SET(x,y)           InterlockedExchange((PLONG)x, (LONG)y)
+#define _MD_INIT_ATOMIC               _PR_MD_INIT_ATOMIC
+#define _MD_ATOMIC_INCREMENT(x)       _PR_MD_ATOMIC_INCREMENT(x)
+#define _MD_ATOMIC_DECREMENT(x)       _PR_MD_ATOMIC_DECREMENT(x)
+#define _MD_ATOMIC_SET(x,y)           _PR_MD_ATOMIC_SET(x, y)
 
 #define _MD_INIT_IO                   _PR_MD_INIT_IO
 #define _MD_TRANSMITFILE              _PR_MD_TRANSMITFILE
 
 
 /* win95 doesn't have async IO */
 #define _MD_SOCKET                    _PR_MD_SOCKET
 extern PRInt32 _MD_SocketAvailable(PRFileDesc *fd);
@@ -299,20 +308,20 @@ extern PRInt32 _MD_Accept(PRFileDesc *fd
 #define _MD_BEGIN_RESUME_ALL()
 #define _MD_END_SUSPEND_ALL()
 #define _MD_END_RESUME_ALL()
 
 /* --- Lock stuff --- */
 #define _PR_LOCK                      _MD_LOCK
 #define _PR_UNLOCK					  _MD_UNLOCK
 
-#define _MD_NEW_LOCK(lock)            (InitializeCriticalSection(&((lock)->mutex)),(lock)->notified.length=0,(lock)->notified.link=NULL,PR_SUCCESS)
-#define _MD_FREE_LOCK(lock)           DeleteCriticalSection(&((lock)->mutex))
-#define _MD_LOCK(lock)                EnterCriticalSection(&((lock)->mutex))
-#define _MD_TEST_AND_LOCK(lock)       (EnterCriticalSection(&((lock)->mutex)),PR_SUCCESS)
+#define _MD_NEW_LOCK(lock)            (DosCreateMutexSem(0, &((lock)->mutex), 0, 0),(lock)->notified.length=0,(lock)->notified.link=NULL,PR_SUCCESS)
+#define _MD_FREE_LOCK(lock)           DosCloseMutexSem(((lock)->mutex))
+#define _MD_LOCK(lock)                DosRequestMutexSem(((lock)->mutex), SEM_INDEFINITE_WAIT)
+#define _MD_TEST_AND_LOCK(lock)       (DosRequestMutexSem(((lock)->mutex), SEM_INDEFINITE_WAIT),PR_SUCCESS)
 #define _MD_UNLOCK                    _PR_MD_UNLOCK
 
 /* --- lock and cv waiting --- */
 #define _MD_WAIT                      _PR_MD_WAIT
 #define _MD_WAKEUP_WAITER             _PR_MD_WAKEUP_WAITER
 
 /* --- CVar ------------------- */
 #define _MD_WAIT_CV					  _PR_MD_WAIT_CV
@@ -371,18 +380,18 @@ extern PRStatus _PR_KillOS2Process(struc
 #define _MD_INTERVAL_PER_SEC              _PR_MD_INTERVAL_PER_SEC
 #define _MD_INTERVAL_PER_MILLISEC()       (_PR_MD_INTERVAL_PER_SEC() / 1000)
 #define _MD_INTERVAL_PER_MICROSEC()       (_PR_MD_INTERVAL_PER_SEC() / 1000000)
 
 /* --- Native-Thread Specific Definitions ------------------------------- */
 
 typedef struct __NSPR_TLS
 {
-    PRThread  *_pr_thread_last_run;
-    PRThread  *_pr_currentThread;
+    struct PRThread  *_pr_thread_last_run;
+    struct PRThread  *_pr_currentThread;
     struct _PRCPU    *_pr_currentCPU;
 } _NSPR_TLS;
 
 extern _NSPR_TLS*  pThreadLocalStorage;
 PR_IMPLEMENT(void) _PR_MD_ENSURE_TLS();
 
 #define _MD_CURRENT_THREAD() pThreadLocalStorage->_pr_currentThread
 #define _MD_SET_CURRENT_THREAD(_thread) _PR_MD_ENSURE_TLS(); pThreadLocalStorage->_pr_currentThread = (_thread)
@@ -426,17 +435,20 @@ extern void * _MD_MemMap(struct PRFileMa
 
 extern PRStatus _MD_MemUnmap(void *addr, PRUint32 size);
 #define _MD_MEM_UNMAP _MD_MemUnmap
 
 extern PRStatus _MD_CloseFileMap(struct PRFileMap *fmap);
 #define _MD_CLOSE_FILE_MAP _MD_CloseFileMap
 
 /* Some stuff for setting up thread contexts */
-typedef ULONG DWORD, *PDWORD;
+#undef DWORD
+#undef PDWORD
+typedef unsigned long DWORD;
+typedef unsigned long *PDWORD;
 
 /* The following definitions and two structures are new in OS/2 Warp 4.0.
  */
 #ifndef CONTEXT_CONTROL
 #define CONTEXT_CONTROL        0x00000001
 #define CONTEXT_INTEGER        0x00000002
 #define CONTEXT_SEGMENTS       0x00000004
 #define CONTEXT_FLOATING_POINT 0x00000008
@@ -467,22 +479,23 @@ typedef struct _CONTEXTRECORD {
     ULONG     ctx_SegCs;     /*  CS register. */
     ULONG     ctx_EFlags;    /*  EFLAGS register. */
     ULONG     ctx_RegEsp;    /*  ESP register. */
     ULONG     ctx_SegSs;     /*  SS register. */
 } CONTEXTRECORD, *PCONTEXTRECORD;
 #pragma pack()
 #endif
 
-extern APIRET (* APIENTRY QueryThreadContext)(TID, ULONG, PCONTEXTRECORD);
+extern APIRET (* APIENTRY QueryThreadContext)(OS2TID, ULONG, PCONTEXTRECORD);
 
 /*
 #define _pr_tid            (((PTIB2)_getTIBvalue(offsetof(TIB, tib_ptib2)))->tib2_ultid)
 #define _pr_current_Thread (_system_tls[_pr_tid-1].__pr_current_thread)
 */
 
 /* Some simple mappings of Windows API's to OS/2 API's to make our lives a
  * little bit easier.  Only add one here if it is a DIRECT mapping.  We are
  * not emulating anything.  Just mapping.
  */
 #define FreeLibrary(x) DosFreeModule(x)
+#define OutputDebugString(str) ;
                                
 #endif /* nspr_os2_defs_h___ */
--- a/pr/include/md/_os2_errors.h
+++ b/pr/include/md/_os2_errors.h
@@ -15,17 +15,19 @@
  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  * Reserved.
  */
 
 #ifndef nspr_os2_errors_h___
 #define nspr_os2_errors_h___
 
 #include "md/_os2.h"
-#include <assert.h>
+#ifndef assert
+  #include <assert.h>
+#endif  
 #include <nerrno.h>
 
 PR_EXTERN(void) _MD_os2_map_opendir_error(PRInt32 err);
 #define	_PR_MD_MAP_OPENDIR_ERROR	_MD_os2_map_opendir_error
 
 PR_EXTERN(void) _MD_os2_map_closedir_error(PRInt32 err);
 #define	_PR_MD_MAP_CLOSEDIR_ERROR	_MD_os2_map_closedir_error
 
--- a/pr/include/md/_osf1.cfg
+++ b/pr/include/md/_osf1.cfg
@@ -70,16 +70,17 @@
 #define PR_ALIGN_OF_SHORT   2
 #define PR_ALIGN_OF_INT     4
 #define PR_ALIGN_OF_LONG    8
 #define PR_ALIGN_OF_INT64   8
 #define PR_ALIGN_OF_FLOAT   4
 #define PR_ALIGN_OF_DOUBLE  8
 #define PR_ALIGN_OF_POINTER 8
 
+#define _PR_POLL_AVAILABLE
 #define _PR_USE_POLL
 
 #ifndef NO_NSPR_10_SUPPORT
 
 #define BYTES_PER_BYTE		PR_BYTES_PER_BYTE
 #define BYTES_PER_SHORT 	PR_BYTES_PER_SHORT
 #define BYTES_PER_INT 		PR_BYTES_PER_INT
 #define BYTES_PER_INT64		PR_BYTES_PER_INT64
--- a/pr/include/md/_pcos.h
+++ b/pr/include/md/_pcos.h
@@ -64,21 +64,23 @@ PR_END_EXTERN_C
 #include <io.h>
 #include <fcntl.h>          /* O_BINARY */
 
 typedef int PROSFD;
 
 /*
 ** Undo the macro define in the Microsoft header files...
 */
+#ifndef XP_OS2 /* Uh... this seems a bit insane in itself to we OS/2 folk */
 #ifdef _stat
 #undef _stat
 #endif
+#endif
 
 #ifdef OS2
-PR_EXTERN(PRStatus) _MD_OS2GetHostName(char *name, PRUint32 namelen);
+extern PRStatus _MD_OS2GetHostName(char *name, PRUint32 namelen);
 #define _MD_GETHOSTNAME _MD_OS2GetHostName
 #else
-PR_EXTERN(PRStatus) _MD_WindowsGetHostName(char *name, PRUint32 namelen);
+extern PRStatus _MD_WindowsGetHostName(char *name, PRUint32 namelen);
 #define _MD_GETHOSTNAME _MD_WindowsGetHostName
 #endif
 
 #endif /* prpcos_h___ */
--- a/pr/include/md/_pth.h
+++ b/pr/include/md/_pth.h
@@ -189,20 +189,23 @@ PR_EXTERN(PRIntn) pt_hpux_privcheck(void
 #define PT_PRIO_MAX            126
 #else
 #error "pthreads is not supported for this architecture"
 #endif
 
 /* Needed for garbage collection -- Look at PR_Suspend/PR_Resume implementation */
 #if defined(OSF1)
 #define PTHREAD_YIELD()            	pthread_yield_np()
-#elif defined(HPUX10_30) || defined(HPUX11) || defined(AIX4_3)
+#elif defined(HPUX10_30) || defined(HPUX11)
 #define PTHREAD_YIELD()            	sched_yield()
-#elif (defined(AIX) && !defined(AIX4_3)) || defined(HPUX)
+#elif defined(HPUX)
 #define PTHREAD_YIELD()            	pthread_yield()
+#elif defined(AIX)
+extern int (*_PT_aix_yield_fcn)();
+#define PTHREAD_YIELD()			(*_PT_aix_yield_fcn)()
 #elif defined(IRIX)
 #include <time.h>
 #define PTHREAD_YIELD() \
     PR_BEGIN_MACRO               				\
 		struct timespec onemillisec = {0};		\
 		onemillisec.tv_nsec = 1000000L;			\
         nanosleep(&onemillisec,NULL);			\
     PR_END_MACRO
--- a/pr/include/md/_reliantunix.cfg
+++ b/pr/include/md/_reliantunix.cfg
@@ -71,16 +71,17 @@
 #define PR_ALIGN_OF_INT     4
 #define PR_ALIGN_OF_LONG    4
 #define PR_ALIGN_OF_INT64   8
 #define PR_ALIGN_OF_FLOAT   4
 #define PR_ALIGN_OF_WORD    4
 #define PR_ALIGN_OF_DOUBLE  8
 #define PR_ALIGN_OF_POINTER 4
 
+#define _PR_POLL_AVAILABLE
 #define _PR_USE_POLL
 
 #ifndef NO_NSPR_10_SUPPORT
 
 #define BYTES_PER_BYTE		PR_BYTES_PER_BYTE
 #define BYTES_PER_SHORT 	PR_BYTES_PER_SHORT
 #define BYTES_PER_INT 		PR_BYTES_PER_INT
 #define BYTES_PER_INT64		PR_BYTES_PER_INT64
--- a/pr/include/md/_scoos.cfg
+++ b/pr/include/md/_scoos.cfg
@@ -66,16 +66,17 @@
 #define PR_ALIGN_OF_SHORT   2
 #define PR_ALIGN_OF_INT     4
 #define PR_ALIGN_OF_LONG    4
 #define PR_ALIGN_OF_INT64   4
 #define PR_ALIGN_OF_FLOAT   4
 #define PR_ALIGN_OF_DOUBLE  4
 #define PR_ALIGN_OF_POINTER 4
 
+#define _PR_POLL_AVAILABLE
 #define _PR_USE_POLL
 
 #ifndef NO_NSPR_10_SUPPORT
 
 #define BYTES_PER_BYTE		PR_BYTES_PER_BYTE
 #define BYTES_PER_SHORT 	PR_BYTES_PER_SHORT
 #define BYTES_PER_INT 		PR_BYTES_PER_INT
 #define BYTES_PER_INT64		PR_BYTES_PER_INT64
--- a/pr/include/md/_unix_errors.h
+++ b/pr/include/md/_unix_errors.h
@@ -130,16 +130,19 @@ PR_EXTERN(void) _MD_unix_map_mmap_error(
 #define	_PR_MD_MAP_MMAP_ERROR	_MD_unix_map_mmap_error
 
 PR_EXTERN(void) _MD_unix_map_gethostname_error(int err);
 #define	_PR_MD_MAP_GETHOSTNAME_ERROR	_MD_unix_map_gethostname_error
 
 PR_EXTERN(void) _MD_unix_map_select_error(int err);
 #define	_PR_MD_MAP_SELECT_ERROR	_MD_unix_map_select_error
 
+PR_EXTERN(void) _MD_unix_map_poll_error(int err);
+#define _PR_MD_MAP_POLL_ERROR _MD_unix_map_poll_error
+
 PR_EXTERN(void) _MD_unix_map_flock_error(int err);
 #define	_PR_MD_MAP_FLOCK_ERROR	_MD_unix_map_flock_error
 
 PR_EXTERN(void) _MD_unix_map_lockf_error(int err);
 #define	_PR_MD_MAP_LOCKF_ERROR	_MD_unix_map_lockf_error
 
 PR_END_EXTERN_C
 
--- a/pr/include/md/_unixos.h
+++ b/pr/include/md/_unixos.h
@@ -113,35 +113,46 @@ struct _MDDir {
 
 /*
  * md-specific cpu structure field, common to all Unix platforms
  */
 #define _PR_MD_MAX_OSFD FD_SETSIZE
 
 struct _MDCPU_Unix {
     PRCList ioQ;
+    PRUint32 ioq_timeout;
+    PRInt32 ioq_max_osfd;
+    PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
     fd_set fd_read_set, fd_write_set, fd_exception_set;
     PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
 				fd_exception_cnt[_PR_MD_MAX_OSFD];
-    PRUint32 ioq_timeout;
-    PRInt32 ioq_max_osfd;
+#else
+	struct pollfd *ioq_pollfds;
+	int ioq_pollfds_size;
+#endif	/* _PR_USE_POLL */
 };
 struct _PRCPU;
 extern void _MD_unix_init_running_cpu(struct _PRCPU *cpu);
 
 #define _PR_IOQ(_cpu)			((_cpu)->md.md_unix.ioQ)
 #define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
 #define _PR_FD_READ_SET(_cpu)		((_cpu)->md.md_unix.fd_read_set)
 #define _PR_FD_READ_CNT(_cpu)		((_cpu)->md.md_unix.fd_read_cnt)
 #define _PR_FD_WRITE_SET(_cpu)		((_cpu)->md.md_unix.fd_write_set)
 #define _PR_FD_WRITE_CNT(_cpu)		((_cpu)->md.md_unix.fd_write_cnt)
 #define _PR_FD_EXCEPTION_SET(_cpu)	((_cpu)->md.md_unix.fd_exception_set)
 #define _PR_FD_EXCEPTION_CNT(_cpu)	((_cpu)->md.md_unix.fd_exception_cnt)
 #define _PR_IOQ_TIMEOUT(_cpu)		((_cpu)->md.md_unix.ioq_timeout)
 #define _PR_IOQ_MAX_OSFD(_cpu)		((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu)		((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu)		((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu)	((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu)	32
 
 
 /*
 ** Make a redzone at both ends of the stack segment. Disallow access
 ** to those pages of memory. It's ok if the mprotect call's don't
 ** work - it just means that we don't really have a functional
 ** redzone.
 */
@@ -448,9 +459,48 @@ extern void * _MD_MemMap(struct PRFileMa
 #define _MD_MEM_MAP _MD_MemMap
 
 extern PRStatus _MD_MemUnmap(void *addr, PRUint32 size);
 #define _MD_MEM_UNMAP _MD_MemUnmap
 
 extern PRStatus _MD_CloseFileMap(struct PRFileMap *fmap);
 #define _MD_CLOSE_FILE_MAP _MD_CloseFileMap
 
+#if defined(LINUX) && defined(_PR_PTHREADS) && !(__GLIBC__ >= 2)
+#define _PR_NEED_FAKE_POLL
+#endif
+
+#if defined(_PR_NEED_FAKE_POLL)
+
+/*
+ * Some platforms don't have poll(), but our pthreads code calls poll().
+ * As a temporary measure, I implemented a fake poll() using select().
+ * Here are the struct and macro definitions copied from sys/poll.h
+ * on Solaris 2.5.
+ */
+
+struct pollfd {
+    int fd;
+    short events;
+    short revents;
+};
+
+/* poll events */
+
+#define	POLLIN		0x0001		/* fd is readable */
+#define	POLLPRI		0x0002		/* high priority info at fd */
+#define	POLLOUT		0x0004		/* fd is writeable (won't block) */
+#define	POLLRDNORM	0x0040		/* normal data is readable */
+#define	POLLWRNORM	POLLOUT
+#define	POLLRDBAND	0x0080		/* out-of-band data is readable */
+#define	POLLWRBAND	0x0100		/* out-of-band data is writeable */
+
+#define	POLLNORM	POLLRDNORM
+
+#define	POLLERR		0x0008		/* fd has error condition */
+#define	POLLHUP		0x0010		/* fd has been hung up on */
+#define	POLLNVAL	0x0020		/* invalid pollfd entry */
+
+extern int poll(struct pollfd *, unsigned long, int);
+
+#endif /* _PR_NEED_FAKE_POLL */
+
 #endif /* prunixos_h___ */
--- a/pr/include/md/_unixware.cfg
+++ b/pr/include/md/_unixware.cfg
@@ -67,16 +67,17 @@
 #define PR_ALIGN_OF_INT     4
 #define PR_ALIGN_OF_LONG    4
 #define PR_ALIGN_OF_INT64   4
 #define PR_ALIGN_OF_FLOAT   4
 #define PR_ALIGN_OF_DOUBLE  4
 #define PR_ALIGN_OF_POINTER 4
 
 #define _PR_USE_POLL
+#define _PR_POLL_AVAILABLE
 
 #ifndef NO_NSPR_10_SUPPORT
 
 #define BYTES_PER_BYTE		PR_BYTES_PER_BYTE
 #define BYTES_PER_SHORT 	PR_BYTES_PER_SHORT
 #define BYTES_PER_INT 		PR_BYTES_PER_INT
 #define BYTES_PER_INT64		PR_BYTES_PER_INT64
 #define BYTES_PER_LONG		PR_BYTES_PER_LONG
--- a/pr/include/md/_win32_errors.h
+++ b/pr/include/md/_win32_errors.h
@@ -19,114 +19,114 @@
 #ifndef nspr_win32_errors_h___
 #define nspr_win32_errors_h___
 
 #include <windows.h>
 #include <winsock.h>
 #include <errno.h>
 
 
-PR_EXTERN(void) _MD_win32_map_opendir_error(PRInt32 err);
+extern void _MD_win32_map_opendir_error(PRInt32 err);
 #define	_PR_MD_MAP_OPENDIR_ERROR	_MD_win32_map_opendir_error
 
-PR_EXTERN(void) _MD_win32_map_closedir_error(PRInt32 err);
+extern void _MD_win32_map_closedir_error(PRInt32 err);
 #define	_PR_MD_MAP_CLOSEDIR_ERROR	_MD_win32_map_closedir_error
 
-PR_EXTERN(void) _MD_unix_readdir_error(PRInt32 err);
+extern void _MD_unix_readdir_error(PRInt32 err);
 #define	_PR_MD_MAP_READDIR_ERROR	_MD_unix_readdir_error
 
-PR_EXTERN(void) _MD_win32_map_delete_error(PRInt32 err);
+extern void _MD_win32_map_delete_error(PRInt32 err);
 #define	_PR_MD_MAP_DELETE_ERROR	_MD_win32_map_delete_error
 
-PR_EXTERN(void) _MD_win32_map_stat_error(PRInt32 err);
+extern void _MD_win32_map_stat_error(PRInt32 err);
 #define	_PR_MD_MAP_STAT_ERROR	_MD_win32_map_stat_error
 
-PR_EXTERN(void) _MD_win32_map_fstat_error(PRInt32 err);
+extern void _MD_win32_map_fstat_error(PRInt32 err);
 #define	_PR_MD_MAP_FSTAT_ERROR	_MD_win32_map_fstat_error
 
-PR_EXTERN(void) _MD_win32_map_rename_error(PRInt32 err);
+extern void _MD_win32_map_rename_error(PRInt32 err);
 #define	_PR_MD_MAP_RENAME_ERROR	_MD_win32_map_rename_error
 
-PR_EXTERN(void) _MD_win32_map_access_error(PRInt32 err);
+extern void _MD_win32_map_access_error(PRInt32 err);
 #define	_PR_MD_MAP_ACCESS_ERROR	_MD_win32_map_access_error
 
-PR_EXTERN(void) _MD_win32_map_mkdir_error(PRInt32 err);
+extern void _MD_win32_map_mkdir_error(PRInt32 err);
 #define	_PR_MD_MAP_MKDIR_ERROR	_MD_win32_map_mkdir_error
 
-PR_EXTERN(void) _MD_win32_map_rmdir_error(PRInt32 err);
+extern void _MD_win32_map_rmdir_error(PRInt32 err);
 #define	_PR_MD_MAP_RMDIR_ERROR	_MD_win32_map_rmdir_error
 
-PR_EXTERN(void) _MD_win32_map_read_error(PRInt32 err);
+extern void _MD_win32_map_read_error(PRInt32 err);
 #define	_PR_MD_MAP_READ_ERROR	_MD_win32_map_read_error
 
-PR_EXTERN(void) _MD_win32_map_transmitfile_error(PRInt32 err);
+extern void _MD_win32_map_transmitfile_error(PRInt32 err);
 #define	_PR_MD_MAP_TRANSMITFILE_ERROR	_MD_win32_map_transmitfile_error
 
-PR_EXTERN(void) _MD_win32_map_write_error(PRInt32 err);
+extern void _MD_win32_map_write_error(PRInt32 err);
 #define	_PR_MD_MAP_WRITE_ERROR	_MD_win32_map_write_error
 
-PR_EXTERN(void) _MD_win32_map_lseek_error(PRInt32 err);
+extern void _MD_win32_map_lseek_error(PRInt32 err);
 #define	_PR_MD_MAP_LSEEK_ERROR	_MD_win32_map_lseek_error
 
-PR_EXTERN(void) _MD_win32_map_fsync_error(PRInt32 err);
+extern void _MD_win32_map_fsync_error(PRInt32 err);
 #define	_PR_MD_MAP_FSYNC_ERROR	_MD_win32_map_fsync_error
 
-PR_EXTERN(void) _MD_win32_map_close_error(PRInt32 err);
+extern void _MD_win32_map_close_error(PRInt32 err);
 #define	_PR_MD_MAP_CLOSE_ERROR	_MD_win32_map_close_error
 
-PR_EXTERN(void) _MD_win32_map_socket_error(PRInt32 err);
+extern void _MD_win32_map_socket_error(PRInt32 err);
 #define	_PR_MD_MAP_SOCKET_ERROR	_MD_win32_map_socket_error
 
-PR_EXTERN(void) _MD_win32_map_recv_error(PRInt32 err);
+extern void _MD_win32_map_recv_error(PRInt32 err);
 #define	_PR_MD_MAP_RECV_ERROR	_MD_win32_map_recv_error
 
-PR_EXTERN(void) _MD_win32_map_recvfrom_error(PRInt32 err);
+extern void _MD_win32_map_recvfrom_error(PRInt32 err);
 #define	_PR_MD_MAP_RECVFROM_ERROR	_MD_win32_map_recvfrom_error
 
-PR_EXTERN(void) _MD_win32_map_send_error(PRInt32 err);
+extern void _MD_win32_map_send_error(PRInt32 err);
 #define	_PR_MD_MAP_SEND_ERROR	_MD_win32_map_send_error
 
-PR_EXTERN(void) _MD_win32_map_sendto_error(PRInt32 err);
+extern void _MD_win32_map_sendto_error(PRInt32 err);
 #define	_PR_MD_MAP_SENDTO_ERROR	_MD_win32_map_sendto_error
 
-PR_EXTERN(void) _MD_win32_map_accept_error(PRInt32 err);
+extern void _MD_win32_map_accept_error(PRInt32 err);
 #define	_PR_MD_MAP_ACCEPT_ERROR	_MD_win32_map_accept_error
 
-PR_EXTERN(void) _MD_win32_map_acceptex_error(PRInt32 err);
+extern void _MD_win32_map_acceptex_error(PRInt32 err);
 #define	_PR_MD_MAP_ACCEPTEX_ERROR	_MD_win32_map_acceptex_error
 
-PR_EXTERN(PRInt32) _MD_win32_map_connect_error(PRInt32 err);
+extern PRInt32 _MD_win32_map_connect_error(PRInt32 err);
 #define	_PR_MD_MAP_CONNECT_ERROR	_MD_win32_map_connect_error
 
-PR_EXTERN(void) _MD_win32_map_bind_error(PRInt32 err);
+extern void _MD_win32_map_bind_error(PRInt32 err);
 #define	_PR_MD_MAP_BIND_ERROR	_MD_win32_map_bind_error
 
-PR_EXTERN(void) _MD_win32_map_listen_error(PRInt32 err);
+extern void _MD_win32_map_listen_error(PRInt32 err);
 #define	_PR_MD_MAP_LISTEN_ERROR	_MD_win32_map_listen_error
 
-PR_EXTERN(void) _MD_win32_map_shutdown_error(PRInt32 err);
+extern void _MD_win32_map_shutdown_error(PRInt32 err);
 #define	_PR_MD_MAP_SHUTDOWN_ERROR	_MD_win32_map_shutdown_error
 
-PR_EXTERN(void) _MD_win32_map_getsockname_error(PRInt32 err);
+extern void _MD_win32_map_getsockname_error(PRInt32 err);
 #define	_PR_MD_MAP_GETSOCKNAME_ERROR	_MD_win32_map_getsockname_error
 
-PR_EXTERN(void) _MD_win32_map_getpeername_error(PRInt32 err);
+extern void _MD_win32_map_getpeername_error(PRInt32 err);
 #define	_PR_MD_MAP_GETPEERNAME_ERROR	_MD_win32_map_getpeername_error
 
-PR_EXTERN(void) _MD_win32_map_getsockopt_error(PRInt32 err);
+extern void _MD_win32_map_getsockopt_error(PRInt32 err);
 #define	_PR_MD_MAP_GETSOCKOPT_ERROR	_MD_win32_map_getsockopt_error
 
-PR_EXTERN(void) _MD_win32_map_setsockopt_error(PRInt32 err);
+extern void _MD_win32_map_setsockopt_error(PRInt32 err);
 #define	_PR_MD_MAP_SETSOCKOPT_ERROR	_MD_win32_map_setsockopt_error
 
-PR_EXTERN(void) _MD_win32_map_open_error(PRInt32 err);
+extern void _MD_win32_map_open_error(PRInt32 err);
 #define	_PR_MD_MAP_OPEN_ERROR	_MD_win32_map_open_error
 
-PR_EXTERN(void) _MD_win32_map_gethostname_error(PRInt32 err);
+extern void _MD_win32_map_gethostname_error(PRInt32 err);
 #define	_PR_MD_MAP_GETHOSTNAME_ERROR	_MD_win32_map_gethostname_error
 
-PR_EXTERN(void) _MD_win32_map_select_error(PRInt32 err);
+extern void _MD_win32_map_select_error(PRInt32 err);
 #define	_PR_MD_MAP_SELECT_ERROR	_MD_win32_map_select_error
 
-PR_EXTERN(void) _MD_win32_map_lockf_error(int err);
+extern void _MD_win32_map_lockf_error(int err);
 #define _PR_MD_MAP_LOCKF_ERROR  _MD_win32_map_lockf_error
 
 #endif /* nspr_win32_errors_h___ */
--- a/pr/include/md/_win95.h
+++ b/pr/include/md/_win95.h
@@ -164,20 +164,23 @@ struct _MDProcess {
 
 /* --- IO stuff --- */
 
 #define _MD_OPEN                      _PR_MD_OPEN
 #define _MD_READ                      _PR_MD_READ
 #define _MD_WRITE                     _PR_MD_WRITE
 #define _MD_WRITEV                    _PR_MD_WRITEV
 #define _MD_LSEEK                     _PR_MD_LSEEK
+#define _MD_LSEEK64                   _PR_MD_LSEEK64
 extern PRInt32 _MD_CloseFile(PRInt32 osfd);
 #define _MD_CLOSE_FILE                _MD_CloseFile
 #define _MD_GETFILEINFO               _PR_MD_GETFILEINFO
+#define _MD_GETFILEINFO64             _PR_MD_GETFILEINFO64
 #define _MD_GETOPENFILEINFO           _PR_MD_GETOPENFILEINFO
+#define _MD_GETOPENFILEINFO64         _PR_MD_GETOPENFILEINFO64
 #define _MD_STAT                      _PR_MD_STAT
 #define _MD_RENAME                    _PR_MD_RENAME     
 #define _MD_ACCESS                    _PR_MD_ACCESS     
 #define _MD_DELETE                    _PR_MD_DELETE     
 #define _MD_MKDIR                     _PR_MD_MKDIR      
 #define _MD_RMDIR                     _PR_MD_RMDIR      
 #define _MD_LOCKFILE                  _PR_MD_LOCKFILE
 #define _MD_TLOCKFILE                 _PR_MD_TLOCKFILE
@@ -219,18 +222,23 @@ extern PRInt32 _MD_CloseSocket(PRInt32 o
 #define _MD_GETSOCKNAME               _PR_MD_GETSOCKNAME
 #define _MD_GETPEERNAME               _PR_MD_GETPEERNAME
 #define _MD_GETSOCKOPT                _PR_MD_GETSOCKOPT
 #define _MD_SETSOCKOPT                _PR_MD_SETSOCKOPT
 #define _MD_SELECT                    select
 #define _MD_FSYNC                     _PR_MD_FSYNC
 
 #define _MD_INIT_ATOMIC()
+#if defined(_M_IX86) || defined(_X86_)
+#define _MD_ATOMIC_INCREMENT          _PR_MD_ATOMIC_INCREMENT
+#define _MD_ATOMIC_DECREMENT          _PR_MD_ATOMIC_DECREMENT
+#else /* non-x86 processors */
 #define _MD_ATOMIC_INCREMENT(x)       InterlockedIncrement((PLONG)x)
 #define _MD_ATOMIC_DECREMENT(x)       InterlockedDecrement((PLONG)x)
+#endif /* x86 */
 #define _MD_ATOMIC_SET(x,y)           InterlockedExchange((PLONG)x, (LONG)y)
 
 #define _MD_INIT_IO                   _PR_MD_INIT_IO
 #define _MD_TRANSMITFILE              _PR_MD_TRANSMITFILE
 
 
 /* win95 doesn't have async IO */
 #define _MD_SOCKET                    _PR_MD_SOCKET
@@ -358,27 +366,41 @@ extern PRStatus _PR_KillWindowsProcess(s
 #define _MD_INTERVAL_INIT                 _PR_MD_INTERVAL_INIT
 #define _MD_GET_INTERVAL                  _PR_MD_GET_INTERVAL
 #define _MD_INTERVAL_PER_SEC              _PR_MD_INTERVAL_PER_SEC
 #define _MD_INTERVAL_PER_MILLISEC()       (_PR_MD_INTERVAL_PER_SEC() / 1000)
 #define _MD_INTERVAL_PER_MICROSEC()       (_PR_MD_INTERVAL_PER_SEC() / 1000000)
 
 /* --- Native-Thread Specific Definitions ------------------------------- */
 
+#ifdef _PR_USE_STATIC_TLS
 extern __declspec(thread) struct PRThread *_pr_currentThread;
 #define _MD_CURRENT_THREAD() _pr_currentThread
 #define _MD_SET_CURRENT_THREAD(_thread) (_pr_currentThread = (_thread))
 
 extern __declspec(thread) struct PRThread *_pr_thread_last_run;
 #define _MD_LAST_THREAD() _pr_thread_last_run
 #define _MD_SET_LAST_THREAD(_thread) (_pr_thread_last_run = (0))
 
 extern __declspec(thread) struct _PRCPU *_pr_currentCPU;
 #define _MD_CURRENT_CPU() _pr_currentCPU
 #define _MD_SET_CURRENT_CPU(_cpu) (_pr_currentCPU = (0))
+#else /* _PR_USE_STATIC_TLS */
+extern DWORD _pr_currentThreadIndex;
+#define _MD_CURRENT_THREAD() ((PRThread *) TlsGetValue(_pr_currentThreadIndex))
+#define _MD_SET_CURRENT_THREAD(_thread) TlsSetValue(_pr_currentThreadIndex, _thread)
+
+extern DWORD _pr_lastThreadIndex;
+#define _MD_LAST_THREAD() ((PRThread *) TlsGetValue(_pr_lastThreadIndex))
+#define _MD_SET_LAST_THREAD(_thread) TlsSetValue(_pr_lastThreadIndex, 0)
+
+extern DWORD _pr_currentCPUIndex;
+#define _MD_CURRENT_CPU() ((struct _PRCPU *) TlsGetValue(_pr_currentCPUIndex))
+#define _MD_SET_CURRENT_CPU(_cpu) TlsSetValue(_pr_currentCPUIndex, 0)
+#endif /* _PR_USE_STATIC_TLS */
 
 // wtc. extern __declspec(thread) PRUintn _pr_ints_off;
 // lth. #define _MD_SET_INTSOFF(_val) (_pr_ints_off = (_val))
 // lth. #define _MD_GET_INTSOFF() _pr_ints_off
 // lth. #define _MD_INCREMENT_INTSOFF() (_pr_ints_off++)
 // lth. #define _MD_DECREMENT_INTSOFF() (_pr_ints_off--)
 
 /* --- Scheduler stuff --- */
--- a/pr/include/md/_winnt.h
+++ b/pr/include/md/_winnt.h
@@ -174,19 +174,22 @@ struct _MDProcess {
 
 extern PRInt32 _PR_MD_CLOSE(PRInt32 osfd, PRBool socket);
 
 #define _MD_OPEN                      _PR_MD_OPEN
 #define _MD_READ                      _PR_MD_READ
 #define _MD_WRITE                     _PR_MD_WRITE
 #define _MD_WRITEV                    _PR_MD_WRITEV
 #define _MD_LSEEK                     _PR_MD_LSEEK
+#define _MD_LSEEK64                   _PR_MD_LSEEK64
 #define _MD_CLOSE_FILE(f)             _PR_MD_CLOSE(f, PR_FALSE)
 #define _MD_GETFILEINFO               _PR_MD_GETFILEINFO
+#define _MD_GETFILEINFO64             _PR_MD_GETFILEINFO64
 #define _MD_GETOPENFILEINFO           _PR_MD_GETOPENFILEINFO
+#define _MD_GETOPENFILEINFO64         _PR_MD_GETOPENFILEINFO64
 #define _MD_STAT                      _PR_MD_STAT
 #define _MD_RENAME                    _PR_MD_RENAME     
 #define _MD_ACCESS                    _PR_MD_ACCESS     
 #define _MD_DELETE                    _PR_MD_DELETE     
 #define _MD_MKDIR                     _PR_MD_MKDIR      
 #define _MD_RMDIR                     _PR_MD_RMDIR      
 #define _MD_LOCKFILE                  _PR_MD_LOCKFILE
 #define _MD_TLOCKFILE                 _PR_MD_TLOCKFILE
@@ -207,18 +210,23 @@ extern PRInt32 _PR_MD_CLOSE(PRInt32 osfd
 #define _MD_GETPEERNAME               _PR_MD_GETPEERNAME
 #define _MD_GETSOCKOPT                _PR_MD_GETSOCKOPT
 #define _MD_SETSOCKOPT                _PR_MD_SETSOCKOPT
 #define _MD_SELECT                    select
 #define _MD_FSYNC                     _PR_MD_FSYNC
 #define _MD_SOCKETAVAILABLE           _PR_MD_SOCKETAVAILABLE
 
 #define _MD_INIT_ATOMIC()
+#if defined(_M_IX86) || defined(_X86_)
+#define _MD_ATOMIC_INCREMENT          _PR_MD_ATOMIC_INCREMENT
+#define _MD_ATOMIC_DECREMENT          _PR_MD_ATOMIC_DECREMENT
+#else /* non-x86 processors */
 #define _MD_ATOMIC_INCREMENT(x)       InterlockedIncrement((PLONG)x)
 #define _MD_ATOMIC_DECREMENT(x)       InterlockedDecrement((PLONG)x)
+#endif /* x86 */
 #define _MD_ATOMIC_SET(x,y)           InterlockedExchange((PLONG)x, (LONG)y)
 
 #define _MD_INIT_IO                   _PR_MD_INIT_IO
 #define _MD_SOCKET                    _PR_MD_SOCKET
 #define _MD_CONNECT                   _PR_MD_CONNECT
 
 #define _MD_ACCEPT(s, a, l, to)       \
         _MD_FAST_ACCEPT(s, a, l, to, PR_FALSE, NULL, NULL)
--- a/pr/include/obsolete/protypes.h
+++ b/pr/include/obsolete/protypes.h
@@ -28,17 +28,17 @@
 
 /* SVR4 typedef of uint is commonly found on UNIX machines. */
 #ifndef XP_UNIX
 typedef PRUintn uint;
 #endif
 
 typedef PRUintn uintn;
 typedef PRUint64 uint64;
-#if !defined(XP_MAC) && !defined(_WIN32)
+#if !defined(XP_MAC) && !defined(_WIN32) && !defined(XP_OS2)
 typedef PRUint32 uint32;
 #else
 typedef unsigned long uint32;
 #endif
 typedef PRUint16 uint16;
 typedef PRUint8 uint8;
 
 #ifndef _XP_Core_
@@ -54,17 +54,17 @@ typedef PRIntn intn;
 #if defined(AIX4_3)
 #include <sys/inttypes.h>
 #else
 typedef PRInt64 int64;
 
 /* /usr/include/model.h on HP-UX defines int8, int16, and int32 */
 #if !defined(HPUX) || !defined(_MODEL_INCLUDED)
 #if !defined(WIN32) || !defined(_WINSOCK2API_)  /* defines its own "int32" */
-#if !defined(XP_MAC) && !defined(_WIN32)
+#if !defined(XP_MAC) && !defined(_WIN32) && !defined(XP_OS2)
 typedef PRInt32 int32;
 #else
 typedef long int32;
 #endif
 #endif
 typedef PRInt16 int16;
 typedef PRInt8 int8;
 #endif /* !defined(HPUX) || !defined(_MODEL_INCLUDED) */
--- a/pr/include/prbit.h
+++ b/pr/include/prbit.h
@@ -44,45 +44,47 @@ PR_EXTERN(PRIntn) PR_CeilingLog2(PRUint3
 PR_EXTERN(PRIntn) PR_FloorLog2(PRUint32 i); 
 
 /*
 ** Macro version of PR_CeilingLog2: Compute the log of the least power of
 ** 2 greater than or equal to _n. The result is returned in _log2.
 */
 #define PR_CEILING_LOG2(_log2,_n)   \
   PR_BEGIN_MACRO                    \
+    PRUint32 j_ = (PRUint32)(_n); 	\
     (_log2) = 0;                    \
-    if ((_n) & ((_n)-1))            \
+    if ((j_) & ((j_)-1))            \
 	(_log2) += 1;               \
-    if ((_n) >> 16)                 \
-	(_log2) += 16, (_n) >>= 16; \
-    if ((_n) >> 8)                  \
-	(_log2) += 8, (_n) >>= 8;   \
-    if ((_n) >> 4)                  \
-	(_log2) += 4, (_n) >>= 4;   \
-    if ((_n) >> 2)                  \
-	(_log2) += 2, (_n) >>= 2;   \
-    if ((_n) >> 1)                  \
+    if ((j_) >> 16)                 \
+	(_log2) += 16, (j_) >>= 16; \
+    if ((j_) >> 8)                  \
+	(_log2) += 8, (j_) >>= 8;   \
+    if ((j_) >> 4)                  \
+	(_log2) += 4, (j_) >>= 4;   \
+    if ((j_) >> 2)                  \
+	(_log2) += 2, (j_) >>= 2;   \
+    if ((j_) >> 1)                  \
 	(_log2) += 1;               \
   PR_END_MACRO
 
 /*
 ** Macro version of PR_FloorLog2: Compute the log of the greatest power of
 ** 2 less than or equal to _n. The result is returned in _log2.
 **
 ** This is equivalent to finding the highest set bit in the word.
 */
 #define PR_FLOOR_LOG2(_log2,_n)   \
   PR_BEGIN_MACRO                    \
+    PRUint32 j_ = (PRUint32)(_n); 	\
     (_log2) = 0;                    \
-    if ((_n) >> 16)                 \
-	(_log2) += 16, (_n) >>= 16; \
-    if ((_n) >> 8)                  \
-	(_log2) += 8, (_n) >>= 8;   \
-    if ((_n) >> 4)                  \
-	(_log2) += 4, (_n) >>= 4;   \
-    if ((_n) >> 2)                  \
-	(_log2) += 2, (_n) >>= 2;   \
-    if ((_n) >> 1)                  \
+    if ((j_) >> 16)                 \
+	(_log2) += 16, (j_) >>= 16; \
+    if ((j_) >> 8)                  \
+	(_log2) += 8, (j_) >>= 8;   \
+    if ((j_) >> 4)                  \
+	(_log2) += 4, (j_) >>= 4;   \
+    if ((j_) >> 2)                  \
+	(_log2) += 2, (j_) >>= 2;   \
+    if ((j_) >> 1)                  \
 	(_log2) += 1;               \
   PR_END_MACRO
 
 #endif /* prbit_h___ */
--- a/pr/include/prdtoa.h
+++ b/pr/include/prdtoa.h
@@ -64,22 +64,14 @@ PR_EXTERN(void) PR_cnvtf(char *buf, PRIn
 ** ARGUMENTS:
 ** If rve is not null, *rve is set to point to the end of the return value.
 ** If d is +-Infinity or NaN, then *decpt is set to 9999.
 **
 ** mode:
 **     0 ==> shortest string that yields d when read in
 **           and rounded to nearest.
 */
-PR_EXTERN(char *) PR_dtoa(PRFloat64 d, PRIntn mode, PRIntn ndigits,
-				     PRIntn *decpt, PRIntn *sign, char **rve);
-
-/*
-** PR_dtoa_r() is the reentrant version of PR_dtoa().
-*/
-
-PR_EXTERN(PRStatus)
-PR_dtoa_r(PRFloat64 d, PRIntn mode, PRIntn ndigits,
+PR_EXTERN(PRStatus) PR_dtoa(PRFloat64 d, PRIntn mode, PRIntn ndigits,
 	PRIntn *decpt, PRIntn *sign, char **rve, char *buf, PRSize bufsize);
 
 PR_END_EXTERN_C
 
 #endif /* prdtoa_h___ */
--- a/pr/include/prinet.h
+++ b/pr/include/prinet.h
@@ -69,23 +69,17 @@
  * on these platforms.
  */
 #if defined(BSDI) || defined(OSF1)
 #include <machine/endian.h>
 #endif
 
 #elif defined(WIN32)
 
-/*
- * On Win NT, windows.h includes either winsock.h or winsock2.h,
- * depending on the value of the _WIN32_WINNT macro.  One can't
- * include winsock2.h if winsock.h is already included.  So we
- * include windows.h to stay neutral.
- */
-#include <windows.h>
+/* Do not include any system header files. */
 
 #elif defined(WIN16)
 
 #include <winsock.h>
 
 #elif defined(XP_MAC)
 
 #include "macsocket.h"
--- a/pr/include/prio.h
+++ b/pr/include/prio.h
@@ -79,61 +79,114 @@ typedef enum PRTransmitFileFlags {
     PR_TRANSMITFILE_KEEP_OPEN = 0,    /* socket is left open after file
                                        * is transmitted. */
     PR_TRANSMITFILE_CLOSE_SOCKET = 1  /* socket is closed after file
                                        * is transmitted. */
 } PRTransmitFileFlags;
 
 /*
 **************************************************************************
+** Macros for PRNetAddr
+**
+** Address families: PR_AF_INET, PR_AF_INET6, PR_AF_LOCAL
+** IP addresses: PR_INADDR_ANY, PR_INADDR_LOOPBACK, PR_INADDR_BROADCAST
+**************************************************************************
+*/
+
+#ifdef WIN32
+
+#define PR_AF_INET 2
+#define PR_AF_LOCAL 1
+#define PR_INADDR_ANY (unsigned long)0x00000000
+#define PR_INADDR_LOOPBACK 0x7f000001
+#define PR_INADDR_BROADCAST (unsigned long)0xffffffff
+
+#else /* WIN32 */
+
+#define PR_AF_INET AF_INET
+#define PR_AF_LOCAL AF_UNIX
+#ifdef AF_INET6
+#define PR_AF_INET6 AF_INET6
+#endif
+#define PR_INADDR_ANY INADDR_ANY
+#define PR_INADDR_LOOPBACK INADDR_LOOPBACK
+#define PR_INADDR_BROADCAST INADDR_BROADCAST
+
+#endif /* WIN32 */
+
+/*
+**************************************************************************
 ** A network address
 **
 ** Only Internet Protocol (IPv4 and IPv6) addresses are supported.
 ** The address family must always represent IPv4 (AF_INET, probably == 2)
 ** or IPv6 (AF_INET6).
 **************************************************************************
 *************************************************************************/
 #if defined(_PR_INET6)
 
 #if !defined(AF_INET6)
 #error "AF_INET6 is not defined"
 #endif
 
 typedef struct in6_addr PRIPv6Addr;
 
-#define PR_NETADDR_SIZE(_addr) PR_NetAddrSize(_addr)
-
-#else
-
-#define PR_NETADDR_SIZE(_addr) sizeof(PRNetAddr)
-
 #endif /* defined(_PR_INET6) */
 
 union PRNetAddr {
     struct {
         PRUint16 family;                /* address family (0x00ff maskable) */
         char data[14];                  /* raw address data */
     } raw;
     struct {
         PRUint16 family;                /* address family (AF_INET) */
         PRUint16 port;                  /* port number */
         PRUint32 ip;                    /* The actual 32 bits of address */
         char pad[8];
     } inet;
 #if defined(_PR_INET6)
     struct {
-        PRUint16 family;                /* address family (AF_INET | AF_INET6) */
+        PRUint16 family;                /* address family (AF_INET6) */
         PRUint16 port;                  /* port number */
         PRUint32 flowinfo;              /* routing information */
         PRIPv6Addr ip;                  /* the actual 128 bits of address */
     } ipv6;
 #endif /* defined(_PR_INET6) */
+#if defined(XP_UNIX)
+    struct {                            /* Unix domain socket address */
+        PRUint16 family;                /* address family (AF_UNIX) */
+        char path[104];                 /* null-terminated pathname */
+    } local;
+#endif
 };
 
 /*
+** The PR_NETADDR_SIZE macro can only be called on a PRNetAddr union
+** whose 'family' field is set.  It returns the size of the union
+** member corresponding to the specified address family.
+*/
+
+#if defined(_PR_INET6)
+
+#define PR_NETADDR_SIZE(_addr) PR_NetAddrSize(_addr)
+
+#else
+
+#if defined(XP_UNIX)
+#define PR_NETADDR_SIZE(_addr) \
+        ((_addr)->raw.family == AF_UNIX \
+        ? sizeof((_addr)->local) \
+        : sizeof((_addr)->inet))
+#else
+#define PR_NETADDR_SIZE(_addr) sizeof((_addr)->inet)
+#endif /* defined(XP_UNIX) */
+
+#endif /* defined(_PR_INET6) */
+
+/*
 ***************************************************************************
 ** PRSockOption
 **
 ** The file descriptors can have predefined options set after they file
 ** descriptor is created to change their behavior. Only the options in
 ** the following enumeration are supported.
 ***************************************************************************
 */
@@ -270,17 +323,17 @@ typedef PRInt32 (PR_CALLBACK *PRSendFN) 
     PRIntn flags, PRIntervalTime timeout);
 typedef PRInt32 (PR_CALLBACK *PRRecvfromFN)(
     PRFileDesc *fd, void *buf, PRInt32 amount,
     PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout);
 typedef PRInt32 (PR_CALLBACK *PRSendtoFN)(
     PRFileDesc *fd, const void *buf, PRInt32 amount,
     PRIntn flags, const PRNetAddr *addr, PRIntervalTime timeout);
 typedef PRInt16 (PR_CALLBACK *PRPollFN)(
-    PRFileDesc *fd, PRInt16 how_flags);
+    PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags);
 typedef PRInt32 (PR_CALLBACK *PRAcceptreadFN)(
     PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr,
     void *buf, PRInt32 amount, PRIntervalTime t);
 typedef PRInt32 (PR_CALLBACK *PRTransmitfileFN)(
      PRFileDesc *sd, PRFileDesc *fd, const void *headers,
      PRInt32 hlen, PRTransmitFileFlags flags, PRIntervalTime t);
 typedef PRStatus (PR_CALLBACK *PRGetsocknameFN)(PRFileDesc *fd, PRNetAddr *addr);
 typedef PRStatus (PR_CALLBACK *PRGetpeernameFN)(PRFileDesc *fd, PRNetAddr *addr);
@@ -366,21 +419,23 @@ PR_EXTERN(PRFileDesc*) PR_GetSpecialFD(P
  *
  * File descriptors may be layered. Each layer has it's own identity.
  * Identities are allocated by the runtime and are to be associated
  * (by the layer implementor) with all layers that are of that type.
  * It is then possible to scan the chain of layers and find a layer
  * that one recongizes and therefore predict that it will implement
  * a desired protocol.
  *
- * There are two well-known identities:
+ * There are three well-known identities:
+ *      PR_INVALID_IO_LAYER => an invalid layer identity, for error return
  *      PR_TOP_IO_LAYER     => the identity of the top of the stack
  *      PR_NSPR_IO_LAYER    => the identity used by NSPR proper
- * The latter may be used as a shorthand for identifying the topmost layer
- * of an existing stack. Ie., the following two constructs are equivalent.
+ * PR_TOP_IO_LAYER may be used as a shorthand for identifying the topmost
+ * layer of an existing stack. Ie., the following two constructs are
+ * equivalent.
  *
  *      rv = PR_PushIOLayer(stack, PR_TOP_IO_LAYER, my_layer);
  *      rv = PR_PushIOLayer(stack, PR_GetLayersIdentity(stack), my_layer)
  *
  * A string may be associated with the creation of the identity. It
  * will be copied by the runtime. If queried the runtime will return
  * a reference to that copied string (not yet another copy). There
  * is no facility for deleting an identity.
@@ -399,29 +454,29 @@ PR_EXTERN(PRFileDesc*) PR_GetIdentitiesL
 /*
  **************************************************************************
  * PR_GetDefaultIOMethods: Accessing the default methods table.
  * You may get a pointer to the default methods table by calling this function.
  * You may then select any elements from that table with which to build your
  * layer's methods table. You may NOT modify the table directly.
  **************************************************************************
  */
-PR_EXTERN(PRIOMethods const*) PR_GetDefaultIOMethods(void);
+PR_EXTERN(const PRIOMethods *) PR_GetDefaultIOMethods(void);
 
 /*
  **************************************************************************
  * Creating a layer
  *
  * A new layer may be allocated by calling PR_CreateIOLayerStub(). The
  * file descriptor returned will contain the pointer to the methods table
  * provided. The runtime will not modify the table nor test its correctness.
  **************************************************************************
  */
 PR_EXTERN(PRFileDesc*) PR_CreateIOLayerStub(
-    PRDescIdentity ident, PRIOMethods const *methods);
+    PRDescIdentity ident, const PRIOMethods *methods);
 
 /*
  **************************************************************************
  * Pushing a layer
  *
  * A file descriptor (perhaps allocated using PR_CreateIOLayerStub()) may
  * be pushed into an existing stack of file descriptors at any point the
  * caller deems appropriate. The new layer will be inserted into the stack
@@ -1511,38 +1566,38 @@ struct PRPollDesc {
     PRInt16 in_flags;
     PRInt16 out_flags;
 };
 
 /*
 ** Bit values for PRPollDesc.in_flags or PRPollDesc.out_flags. Binary-or
 ** these together to produce the desired poll request.
 **
-** On Unix platforms where we use poll() to block the idle threads,
+** On Unix platforms where the poll() system call is available,
 ** the various PR_POLL_XXX flags are mapped to the native poll flags.
 */
 
-#if defined(XP_UNIX) && defined(_PR_USE_POLL)
+#if defined(XP_UNIX) && defined(_PR_POLL_AVAILABLE)
 
 #include <poll.h>
 #define PR_POLL_READ    POLLIN
 #define PR_POLL_WRITE   POLLOUT
 #define PR_POLL_EXCEPT  POLLPRI
 #define PR_POLL_ERR     POLLERR     /* only in out_flags */
 #define PR_POLL_NVAL    POLLNVAL    /* only in out_flags when fd is bad */
 
-#else  /* XP_UNIX, _PR_USE_POLL */
+#else  /* XP_UNIX, _PR_POLL_AVAILABLE */
 
 #define PR_POLL_READ    0x1
 #define PR_POLL_WRITE   0x2
 #define PR_POLL_EXCEPT  0x4
 #define PR_POLL_ERR     0x8         /* only in out_flags */
 #define PR_POLL_NVAL    0x10        /* only in out_flags when fd is bad */
 
-#endif  /* XP_UNIX, _PR_USE_POLL */
+#endif  /* XP_UNIX, _PR_POLL_AVAILABLE */
 
 /*
 *************************************************************************
 ** FUNCTION:    PR_Poll
 ** DESCRIPTION:
 **
 ** The call returns as soon as I/O is ready on one or more of the underlying
 ** file/socket objects. A count of the number of ready descriptors is
--- a/pr/include/private/pprio.h
+++ b/pr/include/private/pprio.h
@@ -34,36 +34,55 @@ NSPR_BEGIN_EXTERN_C
 #define _PR_FILEDESC_OPEN       0xaaaaaaaa    /* 1010101... */
 #define _PR_FILEDESC_CLOSED     0x55555555    /* 0101010... */
 #define _PR_FILEDESC_FREED      0x11111111
 
 /************************************************************************/
 /************************************************************************/
 
 /* Return the method tables for files, tcp sockets and udp sockets */
-PR_EXTERN(PRIOMethods*)    PR_GetFileMethods(void);
-PR_EXTERN(PRIOMethods*)    PR_GetTCPMethods(void);
-PR_EXTERN(PRIOMethods*)    PR_GetUDPMethods(void);
+PR_EXTERN(const PRIOMethods*)    PR_GetFileMethods(void);
+PR_EXTERN(const PRIOMethods*)    PR_GetTCPMethods(void);
+PR_EXTERN(const PRIOMethods*)    PR_GetUDPMethods(void);
 
 /*
 ** Convert a NSPR Socket Handle to a Native Socket handle.
 ** This function will be obsoleted with the next release; avoid using it.
 */
 PR_EXTERN(PRInt32)      PR_FileDesc2NativeHandle(PRFileDesc *);
 PR_EXTERN(void)         PR_ChangeFileDescNativeHandle(PRFileDesc *, PRInt32);
-PR_EXTERN(PRFileDesc*)  PR_AllocFileDesc(PRInt32 osfd, PRIOMethods *methods);
+PR_EXTERN(PRFileDesc*)  PR_AllocFileDesc(PRInt32 osfd,
+                                         const PRIOMethods *methods);
 PR_EXTERN(void)         PR_FreeFileDesc(PRFileDesc *fd);
 /*
 ** Import an existing OS file to NSPR. 
 */
 PR_EXTERN(PRFileDesc*)  PR_ImportFile(PRInt32 osfd);
 PR_EXTERN(PRFileDesc*)  PR_ImportTCPSocket(PRInt32 osfd);
 PR_EXTERN(PRFileDesc*)  PR_ImportUDPSocket(PRInt32 osfd);
 
 /*
+** Macros for PR_Socket
+**
+** Socket types: PR_SOCK_STREAM, PR_SOCK_DGRAM
+*/
+
+#ifdef WIN32
+
+#define PR_SOCK_STREAM 1
+#define PR_SOCK_DGRAM 2
+
+#else /* WIN32 */
+
+#define PR_SOCK_STREAM SOCK_STREAM
+#define PR_SOCK_DGRAM SOCK_DGRAM
+
+#endif /* WIN32 */
+
+/*
 ** Create a new Socket; this function is obsolete.
 */
 PR_EXTERN(PRFileDesc*)	PR_Socket(PRInt32 domain, PRInt32 type, PRInt32 proto);
 
 /* FUNCTION: PR_LockFile
 ** DESCRIPTION:
 **    Lock a file for exclusive access.
 ** RETURNS:
--- a/pr/include/private/primpl.h
+++ b/pr/include/private/primpl.h
@@ -23,24 +23,16 @@
  * HP-UX 10.10's pthread.h (DCE threads) includes dce/cma.h, which
  * has:
  *     #define sigaction _sigaction_sys
  * This macro causes chaos if signal.h gets included before pthread.h.
  * To be safe, we include pthread.h first.
  */
 
 #if defined(_PR_PTHREADS)
-/*
- * XXX: On Linux 2.0.27 (installed on tioman.mcom.com), sched.h uses
- * this _P macro that seems to be undefined.  I suspect that it is
- * a typo (should be __P).
- */
-#if defined(LINUX)
-#define _P(x) __P(x)
-#endif
 #include <pthread.h>
 #endif
 
 #ifdef WINNT
 /* Need to force service-pack 3 extensions to be defined by
 ** setting _WIN32_WINNT to NT 4.0 for winsock.h, winbase.h, winnt.h.
 */
 #ifndef  _WIN32_WINNT
@@ -186,19 +178,24 @@ struct _PT_Notified
 typedef struct PTDebug
 {
     PRTime timeStarted;
     PRUintn predictionsFoiled;
     PRUintn pollingListMax;
     PRUintn continuationsServed;
     PRUintn recyclesNeeded;
     PRUintn quiescentIO;
+    PRUintn locks_created, locks_destroyed;
+    PRUintn locks_acquired, locks_released;
+    PRUintn cvars_created, cvars_destroyed;
+    PRUintn cvars_notified, delayed_cv_deletes;
 } PTDebug;
 
 PR_EXTERN(PTDebug) PT_GetStats(void);
+PR_EXTERN(void) PT_FPrintStats(PRFileDesc *fd, const char *msg);
 
 #endif /* defined(DEBUG) */
 
 #else /* defined(_PR_PTHREADS) */
 
 /*
 ** This section is contains those parts needed to implement NSPR on
 ** platforms in general. One would assume that the pthreads implementation
@@ -519,43 +516,43 @@ PR_EXTERN(PRInt32)                      
 
 extern _PRInterruptTable _pr_interruptTable[];
 
 /* Bits for _pr_interruptState.u.missed[0,1] */
 #define _PR_MISSED_CLOCK    0x1
 #define _PR_MISSED_IO        0x2
 #define _PR_MISSED_CHILD    0x4
 
-PR_EXTERN(void) _PR_IntsOn(_PRCPU *cpu);
+extern void _PR_IntsOn(_PRCPU *cpu);
 
 PR_EXTERN(void) _PR_WakeupCPU(void);
 PR_EXTERN(void) _PR_PauseCPU(void);
 
 /************************************************************************/
 
 #define _PR_LOCK_LOCK(_lock) \
     _PR_MD_LOCK(&(_lock)->ilock);
 #define _PR_LOCK_UNLOCK(_lock) \
     _PR_MD_UNLOCK(&(_lock)->ilock);
     
-PR_EXTERN(PRThread *) _PR_AssignLock(PRLock *lock);
+extern PRThread * _PR_AssignLock(PRLock *lock);
 
 #define _PR_LOCK_PTR(_qp) \
     ((PRLock*) ((char*) (_qp) - offsetof(PRLock,links)))
 
 /************************************************************************/
 
 #define _PR_CVAR_LOCK(_cvar) \
     _PR_MD_LOCK(&(_cvar)->ilock); 
 #define _PR_CVAR_UNLOCK(_cvar) \
     _PR_MD_UNLOCK(&(_cvar)->ilock);
 
-PR_EXTERN(PRStatus) _PR_WaitCondVar(
+extern PRStatus _PR_WaitCondVar(
     PRThread *thread, PRCondVar *cvar, PRLock *lock, PRIntervalTime timeout);
-PR_EXTERN(PRUint32) _PR_CondVarToString(PRCondVar *cvar, char *buf, PRUint32 buflen);
+extern PRUint32 _PR_CondVarToString(PRCondVar *cvar, char *buf, PRUint32 buflen);
 
 PR_EXTERN(void) _PR_Notify(PRMonitor *mon, PRBool all, PRBool sticky);
 
 typedef struct _PRPerThreadExit {
     PRThreadExit func;
     void *arg;
 } _PRPerThreadExit;
 
@@ -684,47 +681,47 @@ extern PRUintn _pr_maxPTDs;
 
 extern PRLock *_pr_terminationCVLock;
 
 /*************************************************************************
 * Internal routines either called by PR itself or from machine-dependent *
 * code.                                                                  *
 *************************************************************************/
 
-PR_EXTERN(void) _PR_ClockInterrupt(void);
+extern void _PR_ClockInterrupt(void);
 
-PR_EXTERN(void) _PR_Schedule(void);
-PR_EXTERN(void) _PR_SetThreadPriority(
+extern void _PR_Schedule(void);
+extern void _PR_SetThreadPriority(
     PRThread* thread, PRThreadPriority priority);
 PR_EXTERN(void) _PR_Unlock(PRLock *lock);
 
 PR_EXTERN(void) _PR_SuspendThread(PRThread *t);
 PR_EXTERN(void) _PR_ResumeThread(PRThread *t);
 
-PR_EXTERN(PRThreadStack *)_PR_NewStack(PRUint32 stackSize);
-PR_EXTERN(void) _PR_FreeStack(PRThreadStack *stack);
-PR_EXTERN(PRBool) NotifyThread (PRThread *thread, PRThread *me);
-PR_EXTERN(void) _PR_NotifyLockedThread (PRThread *thread);
+extern PRThreadStack * _PR_NewStack(PRUint32 stackSize);
+extern void _PR_FreeStack(PRThreadStack *stack);
+extern PRBool _PR_NotifyThread (PRThread *thread, PRThread *me);
+extern void _PR_NotifyLockedThread (PRThread *thread);
 
 PR_EXTERN(void) _PR_AddSleepQ(PRThread *thread, PRIntervalTime timeout);
 PR_EXTERN(void) _PR_DelSleepQ(PRThread *thread, PRBool propogate_time);
 
 extern void _PR_AddThreadToRunQ(PRThread *me, PRThread *thread);
 
 PR_EXTERN(PRThread*) _PR_CreateThread(PRThreadType type,
                                      void (*start)(void *arg),
                                      void *arg,
                                      PRThreadPriority priority,
                                      PRThreadScope scope,
                                      PRThreadState state,
                                      PRUint32 stackSize,
                      PRUint32 flags);
 
-PR_EXTERN(void) _PR_NativeDestroyThread(PRThread *thread);
-PR_EXTERN(void) _PR_UserDestroyThread(PRThread *thread);
+extern void _PR_NativeDestroyThread(PRThread *thread);
+extern void _PR_UserDestroyThread(PRThread *thread);
 
 PR_EXTERN(PRThread*) _PRI_AttachThread(
     PRThreadType type, PRThreadPriority priority,
     PRThreadStack *stack, PRUint32 flags);
 
 #define _PR_IO_PENDING(_thread) ((_thread)->io_pending)
 
 PR_EXTERN(void) _PR_MD_INIT_CPUS();
@@ -745,20 +742,20 @@ PR_EXTERN(void) _PR_MD_BLOCK_CLOCK_INTER
 #define    _PR_MD_BLOCK_CLOCK_INTERRUPTS _MD_BLOCK_CLOCK_INTERRUPTS
 
 PR_EXTERN(void) _PR_MD_UNBLOCK_CLOCK_INTERRUPTS(void);
 #define    _PR_MD_UNBLOCK_CLOCK_INTERRUPTS _MD_UNBLOCK_CLOCK_INTERRUPTS
 
 /* The _PR_MD_WAIT_LOCK and _PR_MD_WAKEUP_WAITER functions put to sleep and
  * awaken a thread which is waiting on a lock or cvar.
  */
-PR_EXTERN(PRStatus) _PR_MD_WAIT(PRThread *, PRIntervalTime timeout);
+extern PRStatus _PR_MD_WAIT(PRThread *, PRIntervalTime timeout);
 #define    _PR_MD_WAIT _MD_WAIT
 
-PR_EXTERN(PRStatus) _PR_MD_WAKEUP_WAITER(PRThread *);
+extern PRStatus _PR_MD_WAKEUP_WAITER(PRThread *);
 #define    _PR_MD_WAKEUP_WAITER _MD_WAKEUP_WAITER
 
 #ifndef _PR_LOCAL_THREADS_ONLY /* not if only local threads supported */
 PR_EXTERN(void) _PR_MD_CLOCK_INTERRUPT(void);
 #define    _PR_MD_CLOCK_INTERRUPT _MD_CLOCK_INTERRUPT
 #endif
 
 /* Stack debugging */
@@ -782,23 +779,23 @@ PR_EXTERN(void) _PR_MD_SET_CURRENT_CPU(_
 #define    _PR_MD_SET_CURRENT_CPU _MD_SET_CURRENT_CPU
 
 PR_EXTERN(void) _PR_MD_INIT_RUNNING_CPU(_PRCPU *cpu);
 #define    _PR_MD_INIT_RUNNING_CPU _MD_INIT_RUNNING_CPU
 
 /*
  * Returns the number of threads awoken or 0 if a timeout occurred;
  */
-PR_EXTERN(PRInt32) _PR_MD_PAUSE_CPU(PRIntervalTime timeout);
+extern PRInt32 _PR_MD_PAUSE_CPU(PRIntervalTime timeout);
 #define    _PR_MD_PAUSE_CPU _MD_PAUSE_CPU
 
 extern void _PR_MD_CLEANUP_BEFORE_EXIT(void);
 #define _PR_MD_CLEANUP_BEFORE_EXIT _MD_CLEANUP_BEFORE_EXIT
 
-PR_EXTERN(void) _PR_MD_EXIT(PRIntn status);
+extern void _PR_MD_EXIT(PRIntn status);
 #define    _PR_MD_EXIT _MD_EXIT
 
 /* Locks related */
 
 PR_EXTERN(PRStatus) _PR_MD_NEW_LOCK(_MDLock *md);
 #define    _PR_MD_NEW_LOCK _MD_NEW_LOCK
 
 PR_EXTERN(void) _PR_MD_FREE_LOCK(_MDLock *md);
@@ -872,37 +869,37 @@ PR_EXTERN(PRThread*) _PR_MD_LAST_THREAD(
 #define    _PR_MD_LAST_THREAD _MD_LAST_THREAD
 
 PR_EXTERN(void) _PR_MD_SET_CURRENT_THREAD(PRThread *thread);
 #define    _PR_MD_SET_CURRENT_THREAD _MD_SET_CURRENT_THREAD
 
 PR_EXTERN(void) _PR_MD_SET_LAST_THREAD(PRThread *thread);
 #define    _PR_MD_SET_LAST_THREAD _MD_SET_LAST_THREAD
 
-PR_EXTERN(PRStatus) _PR_MD_INIT_THREAD(PRThread *thread);
+extern PRStatus _PR_MD_INIT_THREAD(PRThread *thread);
 #define    _PR_MD_INIT_THREAD _MD_INIT_THREAD
 
-PR_EXTERN(void) _PR_MD_EXIT_THREAD(PRThread *thread);
+extern void _PR_MD_EXIT_THREAD(PRThread *thread);
 #define    _PR_MD_EXIT_THREAD _MD_EXIT_THREAD
 
 #ifndef _PR_LOCAL_THREADS_ONLY /* not if only local threads supported */
 
 PR_EXTERN(PRStatus) _PR_MD_INIT_ATTACHED_THREAD(PRThread *thread);
 #define    _PR_MD_INIT_ATTACHED_THREAD _MD_INIT_ATTACHED_THREAD
 
-PR_EXTERN(void) _PR_MD_SUSPEND_THREAD(PRThread *thread);
+extern void _PR_MD_SUSPEND_THREAD(PRThread *thread);
 #define    _PR_MD_SUSPEND_THREAD _MD_SUSPEND_THREAD
 
-PR_EXTERN(void) _PR_MD_RESUME_THREAD(PRThread *thread);
+extern void _PR_MD_RESUME_THREAD(PRThread *thread);
 #define    _PR_MD_RESUME_THREAD _MD_RESUME_THREAD
 
-PR_EXTERN(void) _PR_MD_SUSPEND_CPU(_PRCPU  *cpu);
+extern void _PR_MD_SUSPEND_CPU(_PRCPU  *cpu);
 #define    _PR_MD_SUSPEND_CPU _MD_SUSPEND_CPU
 
-PR_EXTERN(void) _PR_MD_RESUME_CPU(_PRCPU  *cpu);
+extern void _PR_MD_RESUME_CPU(_PRCPU  *cpu);
 #define    _PR_MD_RESUME_CPU _MD_RESUME_CPU
 
 extern void _PR_MD_BEGIN_SUSPEND_ALL(void);
 #define    _PR_MD_BEGIN_SUSPEND_ALL _MD_BEGIN_SUSPEND_ALL
 
 extern void _PR_MD_END_SUSPEND_ALL(void);
 #define    _PR_MD_END_SUSPEND_ALL _MD_END_SUSPEND_ALL
 
@@ -913,62 +910,62 @@ extern void _PR_MD_END_RESUME_ALL(void);
 #define    _PR_MD_END_RESUME_ALL _MD_END_RESUME_ALL
 
 #if defined(IRIX) 
 PR_EXTERN(void) _PR_IRIX_CHILD_PROCESS(void);
 #endif        /* IRIX */
 
 #endif        /* !_PR_LOCAL_THREADS_ONLY */
 
-PR_EXTERN(void) _PR_MD_CLEAN_THREAD(PRThread *thread);
+extern void _PR_MD_CLEAN_THREAD(PRThread *thread);
 #define    _PR_MD_CLEAN_THREAD _MD_CLEAN_THREAD
 
 #ifdef HAVE_CUSTOM_USER_THREADS
-PR_EXTERN(void) _PR_MD_CREATE_PRIMORDIAL_USER_THREAD(PRThread *);
+extern void _PR_MD_CREATE_PRIMORDIAL_USER_THREAD(PRThread *);
 #define    _PR_MD_CREATE_PRIMORDIAL_USER_THREAD _MD_CREATE_PRIMORDIAL_USER_THREAD
 
-PR_EXTERN(PRThread*) _PR_MD_CREATE_USER_THREAD(
+extern PRThread* _PR_MD_CREATE_USER_THREAD(
                         PRUint32 stacksize,
                         void (*start)(void *),
                         void *arg);
 #define    _PR_MD_CREATE_USER_THREAD _MD_CREATE_USER_THREAD
 #endif
 
-PR_EXTERN(void) _PR_MD_INIT_PRIMORDIAL_THREAD(PRThread *thread);
+extern void _PR_MD_INIT_PRIMORDIAL_THREAD(PRThread *thread);
 #define _PR_MD_INIT_PRIMORDIAL_THREAD _MD_INIT_PRIMORDIAL_THREAD
 
-PR_EXTERN(PRStatus) _PR_MD_CREATE_THREAD(
+extern PRStatus _PR_MD_CREATE_THREAD(
                         PRThread *thread, 
                         void (*start) (void *), 
                         PRThreadPriority priority,                      
                         PRThreadScope scope,
                         PRThreadState state,
                         PRUint32 stackSize);
 #define    _PR_MD_CREATE_THREAD _MD_CREATE_THREAD
 
-PR_EXTERN(void) _PR_MD_YIELD(void);
+extern void _PR_MD_YIELD(void);
 #define    _PR_MD_YIELD _MD_YIELD
 
-PR_EXTERN(void) _PR_MD_SET_PRIORITY(_MDThread *md, PRThreadPriority newPri);
+extern void _PR_MD_SET_PRIORITY(_MDThread *md, PRThreadPriority newPri);
 #define    _PR_MD_SET_PRIORITY _MD_SET_PRIORITY
 
 PR_EXTERN(void) _PR_MD_SUSPENDALL(void);
 #define    _PR_MD_SUSPENDALL _MD_SUSPENDALL
 
 PR_EXTERN(void) _PR_MD_RESUMEALL(void);
 #define    _PR_MD_RESUMEALL _MD_RESUMEALL
 
-PR_EXTERN(void) _PR_MD_INIT_CONTEXT(
+extern void _PR_MD_INIT_CONTEXT(
     PRThread *thread, char *top, void (*start) (void), PRBool *status);
 #define    _PR_MD_INIT_CONTEXT _MD_INIT_CONTEXT
 
-PR_EXTERN(void) _PR_MD_SWITCH_CONTEXT(PRThread *thread);
+extern void _PR_MD_SWITCH_CONTEXT(PRThread *thread);
 #define    _PR_MD_SWITCH_CONTEXT _MD_SWITCH_CONTEXT
 
-PR_EXTERN(void) _PR_MD_RESTORE_CONTEXT(PRThread *thread);
+extern void _PR_MD_RESTORE_CONTEXT(PRThread *thread);
 #define    _PR_MD_RESTORE_CONTEXT _MD_RESTORE_CONTEXT
 
 /* Directory enumeration related */
 extern PRStatus _PR_MD_OPEN_DIR(_MDDir *md,const char *name);
 #define    _PR_MD_OPEN_DIR _MD_OPEN_DIR
 
 extern char * _PR_MD_READ_DIR(_MDDir *md, PRIntn flags);
 #define    _PR_MD_READ_DIR _MD_READ_DIR
@@ -1195,35 +1192,36 @@ extern void _PR_InitThreads(
 PR_EXTERN(void) _PR_MD_START_INTERRUPTS(void);
 #define    _PR_MD_START_INTERRUPTS _MD_START_INTERRUPTS
 
 PR_EXTERN(void) _PR_MD_INIT_LOCKS(void);
 #define    _PR_MD_INIT_LOCKS _MD_INIT_LOCKS
 
 struct PRLock {
 #if defined(_PR_PTHREADS)
-        pthread_mutex_t mutex;      /* the underlying lock */
-        _PT_Notified notified;      /* array of conditions notified */
+    pthread_mutex_t mutex;          /* the underlying lock */
+    _PT_Notified notified;          /* array of conditions notified */
     pthread_t owner;                /* current lock owner */
 #else  /* defined(_PR_PTHREADS) */
     PRCList links;                  /* linkage for PRThread.lockList */
     struct PRThread *owner;         /* current lock owner */
     PRCList waitQ;                  /* list of threads waiting for lock */
     PRThreadPriority priority;      /* priority of lock */ 
     PRThreadPriority boostPriority; /* boosted priority of lock owner */
     _MDLock ilock;                  /* Internal Lock to protect user-level fields */
 #endif /* defined(_PR_PTHREADS) */
 };
 
-PR_EXTERN(void) _PR_InitLocks(void);
+extern void _PR_InitLocks(void);
 
 struct PRCondVar {
     PRLock *lock;               /* associated lock that protects the condition */
 #if defined(_PR_PTHREADS)
-        pthread_cond_t cv;
+    pthread_cond_t cv;          /* underlying pthreads condition */
+    PRInt32 notify_pending;     /* CV has destroy pending notification */
 #else  /* defined(_PR_PTHREADS) */
     PRCList condQ;              /* Condition variable wait Q */
     _MDLock ilock;              /* Internal Lock to protect condQ */
     _MDCVar md;
 #endif /* defined(_PR_PTHREADS) */
 };
 
 /************************************************************************/
@@ -1292,22 +1290,23 @@ struct PRThread {
 
     PRThreadStack *stack;           /* info about thread's stack (for GC) */
     void *environment;              /* pointer to execution environment */
 
     PRThreadDumpProc dump;          /* dump thread info out */
     void *dumpArg;                  /* argument for the dump function */
 
 #if defined(_PR_PTHREADS)
-        pthread_t id;                   /* pthread identifier for the thread */
+    pthread_t id;                   /* pthread identifier for the thread */
     PRBool okToDelete;              /* ok to delete the PRThread struct? */
-        PRCondVar *waiting;             /* where the thread is waiting | NULL */
-        void *sp;                                                /* recorded sp for garbage collection */
-        PRThread *next, *prev;          /* simple linked list of all threads */
-        PRUint32 suspend;                        /* used to store suspend and resume flags */
+    PRCondVar *io_cv;               /* a condition used to run i/o */
+    PRCondVar *waiting;             /* where the thread is waiting | NULL */
+    void *sp;                       /* recorded sp for garbage collection */
+    PRThread *next, *prev;          /* simple linked list of all threads */
+    PRUint32 suspend;               /* used to store suspend and resume flags */
 #ifdef PT_NO_SIGTIMEDWAIT
     pthread_mutex_t suspendResumeMutex;
     pthread_cond_t suspendResumeCV;
 #endif
 #else /* defined(_PR_PTHREADS) */
     _MDLock threadLock;             /* Lock to protect thread state variables.
                                     * Protects the following fields:
                                     *     state
@@ -1476,20 +1475,20 @@ extern PRBool _pr_ipv6_enabled;  /* defi
 #define _PR_OVERRIDE_MALLOC
 #endif
 
 /*************************************************************************
 * External machine-dependent code provided by each OS.                     *                                                                     *
 *************************************************************************/
 
 /* Initialization related */
-PR_EXTERN(void) _PR_MD_EARLY_INIT(void);
+extern void _PR_MD_EARLY_INIT(void);
 #define    _PR_MD_EARLY_INIT _MD_EARLY_INIT
 
-PR_EXTERN(void) _PR_MD_INTERVAL_INIT(void);
+extern void _PR_MD_INTERVAL_INIT(void);
 #define    _PR_MD_INTERVAL_INIT _MD_INTERVAL_INIT
 
 PR_EXTERN(void) _PR_MD_INIT_SEGS(void);
 #define    _PR_MD_INIT_SEGS _MD_INIT_SEGS
 
 PR_EXTERN(void) _PR_MD_FINAL_INIT(void);
 #define    _PR_MD_FINAL_INIT _MD_FINAL_INIT
 
@@ -1511,34 +1510,34 @@ extern PRStatus _PR_MD_WAIT_PROCESS(PRPr
 extern PRStatus _PR_MD_KILL_PROCESS(PRProcess *process);
 #define    _PR_MD_KILL_PROCESS _MD_KILL_PROCESS        
 
 /* Current Time */
 PR_EXTERN(PRTime) _PR_MD_NOW(void);
 #define    _PR_MD_NOW _MD_NOW
 
 /* Environment related */
-PR_EXTERN(char*) _PR_MD_GET_ENV(const char *name);
+extern char* _PR_MD_GET_ENV(const char *name);
 #define    _PR_MD_GET_ENV _MD_GET_ENV
 
-PR_EXTERN(PRIntn) _PR_MD_PUT_ENV(const char *name);
+extern PRIntn _PR_MD_PUT_ENV(const char *name);
 #define    _PR_MD_PUT_ENV _MD_PUT_ENV
 
 /* Atomic operations */
 
-void _PR_MD_INIT_ATOMIC(void);
+extern void _PR_MD_INIT_ATOMIC(void);
 #define    _PR_MD_INIT_ATOMIC _MD_INIT_ATOMIC
 
-PR_EXTERN(PRInt32) _PR_MD_ATOMIC_INCREMENT(PRInt32 *);
+extern PRInt32 _PR_MD_ATOMIC_INCREMENT(PRInt32 *);
 #define    _PR_MD_ATOMIC_INCREMENT _MD_ATOMIC_INCREMENT
 
-PR_EXTERN(PRInt32) _PR_MD_ATOMIC_DECREMENT(PRInt32 *);
+extern PRInt32 _PR_MD_ATOMIC_DECREMENT(PRInt32 *);
 #define    _PR_MD_ATOMIC_DECREMENT _MD_ATOMIC_DECREMENT
 
-PR_EXTERN(PRInt32) _PR_MD_ATOMIC_SET(PRInt32 *, PRInt32);
+extern PRInt32 _PR_MD_ATOMIC_SET(PRInt32 *, PRInt32);
 #define    _PR_MD_ATOMIC_SET _MD_ATOMIC_SET
 
 /* Segment related */
 PR_EXTERN(PRStatus) _PR_MD_ALLOC_SEGMENT(PRSegment *seg, PRUint32 size, void *vaddr);
 #define    _PR_MD_ALLOC_SEGMENT _MD_ALLOC_SEGMENT
 
 PR_EXTERN(void) _PR_MD_FREE_SEGMENT(PRSegment *seg);
 #define    _PR_MD_FREE_SEGMENT _MD_FREE_SEGMENT
@@ -1555,39 +1554,39 @@ PR_EXTERN(void) _PR_MD_FREE_SEGMENT(PRSe
 ** If "isCurrent" is non-zero then it is allowed for the thread context
 ** area to be used as scratch storage to hold just the registers
 ** necessary for scanning.
 */
 extern PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np);
 
 /* Time intervals */
 
-PR_EXTERN(PRIntervalTime) _PR_MD_GET_INTERVAL(void);
+extern PRIntervalTime _PR_MD_GET_INTERVAL(void);
 #define _PR_MD_GET_INTERVAL _MD_GET_INTERVAL
 
-PR_EXTERN(PRIntervalTime) _PR_MD_INTERVAL_PER_SEC(void);
+extern PRIntervalTime _PR_MD_INTERVAL_PER_SEC(void);
 #define _PR_MD_INTERVAL_PER_SEC _MD_INTERVAL_PER_SEC
 
 /* Affinity masks */
 
-PR_EXTERN(PRInt32) _PR_MD_SETTHREADAFFINITYMASK(PRThread *thread, PRUint32 mask );
+extern PRInt32 _PR_MD_SETTHREADAFFINITYMASK(PRThread *thread, PRUint32 mask );
 #define _PR_MD_SETTHREADAFFINITYMASK _MD_SETTHREADAFFINITYMASK
 
-PR_EXTERN(PRInt32) _PR_MD_GETTHREADAFFINITYMASK(PRThread *thread, PRUint32 *mask);
+extern PRInt32 _PR_MD_GETTHREADAFFINITYMASK(PRThread *thread, PRUint32 *mask);
 #define _PR_MD_GETTHREADAFFINITYMASK _MD_GETTHREADAFFINITYMASK
 
 /* File locking */
 
-PR_EXTERN(PRStatus) _PR_MD_LOCKFILE(PRInt32 osfd);
+extern PRStatus _PR_MD_LOCKFILE(PRInt32 osfd);
 #define    _PR_MD_LOCKFILE _MD_LOCKFILE
 
-PR_EXTERN(PRStatus) _PR_MD_TLOCKFILE(PRInt32 osfd);
+extern PRStatus _PR_MD_TLOCKFILE(PRInt32 osfd);
 #define    _PR_MD_TLOCKFILE _MD_TLOCKFILE
 
-PR_EXTERN(PRStatus) _PR_MD_UNLOCKFILE(PRInt32 osfd);
+extern PRStatus _PR_MD_UNLOCKFILE(PRInt32 osfd);
 #define    _PR_MD_UNLOCKFILE _MD_UNLOCKFILE
 
 /* Memory-mapped files */
 
 extern PRStatus _PR_MD_CREATE_FILE_MAP(PRFileMap *fmap, PRInt64 size);
 #define _PR_MD_CREATE_FILE_MAP _MD_CREATE_FILE_MAP
 
 extern void * _PR_MD_MEM_MAP(
@@ -1603,14 +1602,14 @@ extern PRStatus _PR_MD_CLOSE_FILE_MAP(PR
 #define _PR_MD_CLOSE_FILE_MAP _MD_CLOSE_FILE_MAP
 
 /* Socket call error code */
 
 PR_EXTERN(PRInt32) _PR_MD_GET_SOCKET_ERROR(void);
 #define    _PR_MD_GET_SOCKET_ERROR _MD_GET_SOCKET_ERROR
 
 /* Get name of current host */
-PR_EXTERN(PRStatus) _PR_MD_GETHOSTNAME(char *name, PRUint32 namelen);
+extern PRStatus _PR_MD_GETHOSTNAME(char *name, PRUint32 namelen);
 #define    _PR_MD_GETHOSTNAME _MD_GETHOSTNAME
 
 PR_END_EXTERN_C
 
 #endif /* primpl_h___ */
--- a/pr/include/prmwait.h
+++ b/pr/include/prmwait.h
@@ -19,16 +19,18 @@
 #if defined(_PRMWAIT_H)
 #else
 #define _PRMWAIT_H
 
 #include "prio.h"
 #include "prtypes.h"
 #include "prclist.h"
 
+PR_BEGIN_EXTERN_C
+
 /********************************************************************************/
 /********************************************************************************/
 /********************************************************************************/
 /******************************       WARNING        ****************************/
 /********************************************************************************/
 /**************************** This is work in progress. *************************/
 /************************** Do not make any assumptions *************************/
 /************************** about the stability of this *************************/
@@ -294,11 +296,13 @@ PR_EXTERN(PRWaitGroup*) PR_CreateWaitGro
 **  ERRORS
 **      PR_INVALID_ARGUMENT_ERROR
                     The 'group' argument does not reference a known object.
 **      PR_INVALID_STATE_ERROR
 **                  The group still contains receive wait objects.
 */
 PR_EXTERN(PRStatus) PR_DestroyWaitGroup(PRWaitGroup *group);
 
+PR_END_EXTERN_C
+
 #endif /* defined(_PRMWAIT_H) */
 
 /* prmwait.h */
--- a/pr/include/prtypes.h
+++ b/pr/include/prtypes.h
@@ -95,22 +95,30 @@
 #define PR_IMPLEMENT(__type) __declspec(export) __type
 #define PR_EXTERN_DATA(__type) extern __declspec(export) __type
 #define PR_IMPLEMENT_DATA(__type) __declspec(export) __type
 
 #define PR_CALLBACK
 #define PR_CALLBACK_DECL
 #define PR_STATIC_CALLBACK(__x) static __x
 
-#else /* Unix or OS/2 */
+#elif defined(XP_OS2) 
 #define PR_EXTERN(__type) extern __type
 #define PR_IMPLEMENT(__type) __type
 #define PR_EXTERN_DATA(__type) extern __type
 #define PR_IMPLEMENT_DATA(__type) __type
+#define PR_CALLBACK
+#define PR_CALLBACK_DECL
+#define PR_STATIC_CALLBACK(__x) __x _Optlink
 
+#else /* Unix */
+#define PR_EXTERN(__type) extern __type
+#define PR_IMPLEMENT(__type) __type
+#define PR_EXTERN_DATA(__type) extern __type
+#define PR_IMPLEMENT_DATA(__type) __type
 #define PR_CALLBACK
 #define PR_CALLBACK_DECL
 #define PR_STATIC_CALLBACK(__x) static __x
 
 #endif
 
 #if !defined(NO_NSPR_10_SUPPORT)
 #define PR_PUBLIC_API		PR_IMPLEMENT
@@ -222,19 +230,18 @@ typedef long PRInt32;
 #ifdef HAVE_LONG_LONG
 #if PR_BYTES_PER_LONG == 8
 typedef long PRInt64;
 typedef unsigned long PRUint64;
 #elif defined(WIN16)
 typedef __int64 PRInt64;
 typedef unsigned __int64 PRUint64;
 #elif defined(WIN32)
-#include <windows.h>  /* For LONGLONG and DWORDLONG */
-typedef LONGLONG  PRInt64;
-typedef DWORDLONG PRUint64;
+typedef __int64  PRInt64;
+typedef unsigned __int64 PRUint64;
 #else
 typedef long long PRInt64;
 typedef unsigned long long PRUint64;
 #endif /* PR_BYTES_PER_LONG == 8 */
 #else  /* !HAVE_LONG_LONG */
 typedef struct {
 #ifdef IS_LITTLE_ENDIAN
     PRUint32 lo, hi;
@@ -294,17 +301,19 @@ typedef unsigned long PRUptrdiff;
 /************************************************************************
 ** TYPES:       PRBool
 ** DESCRIPTION:
 **  Use PRBool for variables and parameter types. Use PR_FALSE and PR_TRUE
 **      for clarity of target type in assignments and actual arguments. Use
 **      'if (bool)', 'while (!bool)', '(bool) ? x : y' etc., to test booleans
 **      juast as you would C int-valued conditions. 
 ************************************************************************/
-typedef enum { PR_FALSE = 0, PR_TRUE = 1 } PRBool;
+typedef PRIntn PRBool;
+#define PR_TRUE (PRIntn)1
+#define PR_FALSE (PRIntn)0
 
 /************************************************************************
 ** TYPES:       PRPackedBool
 ** DESCRIPTION:
 **  Use PRPackedBOol within structs where bitfields are not desireable
 **      but minimum and consistant overhead matters.
 ************************************************************************/
 typedef PRUint8 PRPackedBool;
--- a/pr/include/prwin16.h
+++ b/pr/include/prwin16.h
@@ -17,17 +17,17 @@
  */
 
 #ifndef prwin16_h___
 #define prwin16_h___
 
 /*
 ** Condition use of this header on platform.
 */
-#if (defined(XP_PC) && !defined(_WIN32) && defined(MOZILLA_CLIENT)) || defined(WIN16)
+#if (defined(XP_PC) && !defined(_WIN32) && !defined(XP_OS2) && defined(MOZILLA_CLIENT)) || defined(WIN16)
 #include <stdio.h>
 
 PR_BEGIN_EXTERN_C
 /* 
 ** Win16 stdio special case.
 ** To get stdio to work for Win16, all calls to printf() and related
 ** things must be called from the environment of the .EXE; calls to
 ** printf() from the .DLL send output to the bit-bucket.
--- a/pr/src/io/pprmwait.h
+++ b/pr/src/io/pprmwait.h
@@ -26,18 +26,18 @@
 #include "prthread.h"
 
 #define _PR_HASH_OFFSET 75013
 #define MAX_POLLING_INTERVAL 100
 #define _PR_POLL_COUNT_FUDGE 64
 #define MAX_POLLING_INTERVAL 100
 #define _PR_DEFAULT_HASH_LENGTH 59
 
-#define _MW_REHASH(a, i, m) _MW_HASH((PRUint32)(a) + (i) + _PR_HASH_OFFSET, m)
-#define _MW_HASH(a, m) ((((PRUint32)(a) >> 4) ^ ((PRUint32)(a) >> 10)) % (m))
+#define _MW_REHASH(a, i, m) _MW_HASH((PRUword)(a) + (i) + _PR_HASH_OFFSET, m)
+#define _MW_HASH(a, m) ((((PRUword)(a) >> 4) ^ ((PRUword)(a) >> 10)) % (m))
 #define _MW_ABORTED(_rv) \
     ((PR_FAILURE == (_rv)) && (PR_PENDING_INTERRUPT_ERROR == PR_GetError()))
 
 typedef enum {_prmw_success, _prmw_rehash, _prmw_error} _PR_HashStory;
 
 typedef struct _PRWaiterHash
 {
     PRUint16 count;             /* current number in hash table */
--- a/pr/src/io/prfile.c
+++ b/pr/src/io/prfile.c
@@ -195,16 +195,23 @@ static PRStatus PR_CALLBACK FileClose(PR
     PR_FreeFileDesc(fd);
     if (rv < 0) {
         return PR_FAILURE;
     } else {
         return PR_SUCCESS;
     }
 }
 
+static PRInt16 PR_CALLBACK FilePoll(
+    PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags)
+{
+    *out_flags = 0;
+    return in_flags;
+}  /* FilePoll */
+
 PRIOMethods _pr_fileMethods = {
     PR_DESC_FILE,
     FileClose,
     FileRead,
     FileWrite,
     FileAvailable,
     FileAvailable64,
     FileSync,
@@ -217,28 +224,28 @@ PRIOMethods _pr_fileMethods = {
     (PRAcceptFN)_PR_InvalidDesc,		
     (PRBindFN)_PR_InvalidStatus,		
     (PRListenFN)_PR_InvalidStatus,		
     (PRShutdownFN)_PR_InvalidStatus,	
     (PRRecvFN)_PR_InvalidInt,		
     (PRSendFN)_PR_InvalidInt,		
     (PRRecvfromFN)_PR_InvalidInt,	
     (PRSendtoFN)_PR_InvalidInt,		
-    (PRPollFN)0,         
+    FilePoll,         
     (PRAcceptreadFN)_PR_InvalidInt,   
     (PRTransmitfileFN)_PR_InvalidInt, 
     (PRGetsocknameFN)_PR_InvalidStatus,	
     (PRGetpeernameFN)_PR_InvalidStatus,	
     (PRGetsockoptFN)_PR_InvalidStatus,	
     (PRSetsockoptFN)_PR_InvalidStatus,	
     (PRGetsocketoptionFN)_PR_InvalidStatus,	
     (PRSetsocketoptionFN)_PR_InvalidStatus,	
 };
 
-PR_IMPLEMENT(PRIOMethods*) PR_GetFileMethods(void)
+PR_IMPLEMENT(const PRIOMethods*) PR_GetFileMethods(void)
 {
     return &_pr_fileMethods;
 }
 
 PR_IMPLEMENT(PRFileDesc*) PR_Open(const char *name, PRIntn flags, PRIntn mode)
 {
     PRInt32 osfd;
     PRFileDesc *fd = 0;
--- a/pr/src/io/prio.c
+++ b/pr/src/io/prio.c
@@ -25,17 +25,17 @@
 
 PRLock *_pr_flock_lock;
 
 PRFileDesc *_pr_filedesc_freelist;
 PRLock *_pr_filedesc_freelist_lock;
 
 void _PR_InitIO(void)
 {
-    PRIOMethods *methods = PR_GetFileMethods();
+    const PRIOMethods *methods = PR_GetFileMethods();
 
     _pr_filedesc_freelist = NULL;
     _pr_filedesc_freelist_lock = PR_NewLock();
     _pr_flock_lock = PR_NewLock();
 
 #ifdef WIN32
     _pr_stdin = PR_AllocFileDesc((PRInt32)GetStdHandle(STD_INPUT_HANDLE),
             methods);
@@ -70,17 +70,18 @@ PR_IMPLEMENT(PRFileDesc*) PR_GetSpecialF
         case PR_StandardOutput: result = _pr_stdout; break;
         case PR_StandardError: result = _pr_stderr; break;
         default:
             (void)PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
     }
     return result;
 }
 
-PR_IMPLEMENT(PRFileDesc*) PR_AllocFileDesc(PRInt32 osfd, PRIOMethods *methods)
+PR_IMPLEMENT(PRFileDesc*) PR_AllocFileDesc(
+    PRInt32 osfd, const PRIOMethods *methods)
 {
     PRFileDesc *fd;
 
 #ifdef XP_UNIX
 	/*
 	 * Assert that the file descriptor is small enough to fit in the
 	 * fd_set passed to select
 	 */
@@ -142,43 +143,43 @@ PR_IMPLEMENT(void) PR_FreeFileDesc(PRFil
 
 /*
 ** Wait for some i/o to finish on one or more more poll descriptors.
 */
 PR_IMPLEMENT(PRInt32) PR_Poll(PRPollDesc *pds, PRIntn npds,
 	PRIntervalTime timeout)
 {
     PRPollDesc *pd, *epd;
-    PRInt32 n;
+    PRInt32 ready;
     PRThread *me = _PR_MD_CURRENT_THREAD();
 
     if (_PR_PENDING_INTERRUPT(me)) {
         me->flags &= ~_PR_INTERRUPT;
 		PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
         return -1;
     }
     /*
     ** Before we do the poll operation, check each descriptor and see if
     ** it needs special poll handling. If it does, use the method poll
     ** proc to check for data before blocking.
     */
     pd = pds;
-    n = 0;
+    ready = 0;
     for (pd = pds, epd = pd + npds; pd < epd; pd++) {
         PRFileDesc *fd = pd->fd;
-        PRInt16 in_flags;
-        if (NULL == fd) {
-            continue;
-        }
-        in_flags = pd->in_flags;
-        if (in_flags && fd->methods->poll) {
-            PRInt16 out_flags = (*fd->methods->poll)(fd, in_flags);
-            if (out_flags) {
-                pd->out_flags = out_flags;
-                n++;
+        PRInt16 in_flags = pd->in_flags;
+        if (NULL != fd)
+        {
+            if (in_flags && fd->methods->poll) {
+                PRInt16 out_flags;
+                in_flags = (*fd->methods->poll)(fd, in_flags, &out_flags);
+                if (0 != (in_flags & out_flags)) {
+                    pd->out_flags = out_flags;  /* ready already */
+                    ready++;
+                }
             }
         }
     }
-    if (n != 0) {
-        return n;
+    if (ready != 0) {
+        return ready;  /* don't need to block */
     }
 	return(_PR_MD_PR_POLL(pds, npds, timeout));
 }
--- a/pr/src/io/prlayer.c
+++ b/pr/src/io/prlayer.c
@@ -143,34 +143,38 @@ static PRStatus PR_CALLBACK pl_DefConnec
     PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout)
 {
     PR_ASSERT(fd != NULL);
     PR_ASSERT(fd->lower != NULL);
 
     return (fd->lower->methods->connect)(fd->lower, addr, timeout);
 }
 
-static PRFileDesc * PR_CALLBACK pl_TopAccept (
+static PRFileDesc* PR_CALLBACK pl_TopAccept (
     PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout)
 {
+    PRStatus rv;
     PRFileDesc *newfd;
 
     PR_ASSERT(fd != NULL);
     PR_ASSERT(fd->lower != NULL);
 
     newfd = (fd->lower->methods->accept)(fd->lower, addr, timeout);
     if (newfd != NULL)
     {
-        if (PR_FAILURE == PR_PushIOLayer(fd, fd->identity, newfd))
+        PRFileDesc *newstack = PR_NEW(PRFileDesc);
+        if (NULL != newstack)
         {
-            PR_Close(newfd);
-            newfd = NULL;
+            *newstack = *fd;  /* make a copy of the accepting layer */
+            rv = PR_PushIOLayer(newfd, PR_TOP_IO_LAYER, newstack);
+            if (PR_SUCCESS == rv) return newfd;  /* that's it */
         }
+        PR_Close(newfd);  /* we failed for local reasons */
     }
-    return newfd;
+    return NULL;
 }
 
 static PRStatus PR_CALLBACK pl_DefBind (PRFileDesc *fd, const PRNetAddr *addr)
 {
     PR_ASSERT(fd != NULL);
     PR_ASSERT(fd->lower != NULL);
 
     return (fd->lower->methods->bind)(fd->lower, addr);
@@ -230,22 +234,23 @@ static PRInt32 PR_CALLBACK pl_DefSendto 
 {
     PR_ASSERT(fd != NULL);
     PR_ASSERT(fd->lower != NULL);
 
     return (fd->lower->methods->sendto)(
         fd->lower, buf, amount, flags, addr, timeout);
 }
 
-static PRInt16 PR_CALLBACK pl_DefPoll (PRFileDesc *fd, PRInt16 how_flags)
+static PRInt16 PR_CALLBACK pl_DefPoll (
+    PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags)
 {
     PR_ASSERT(fd != NULL);
     PR_ASSERT(fd->lower != NULL);
 
-    return (fd->lower->methods->poll)(fd->lower, how_flags);
+    return (fd->lower->methods->poll)(fd->lower, in_flags, out_flags);
 }
 
 static PRInt32 PR_CALLBACK pl_DefAcceptread (
     PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr, void *buf,
     PRInt32 amount, PRIntervalTime t)
 {
     PR_ASSERT(sd != NULL);
     PR_ASSERT(sd->lower != NULL);
@@ -312,17 +317,17 @@ static PRStatus PR_CALLBACK pl_DefSetsoc
 {
     PR_ASSERT(fd != NULL);
     PR_ASSERT(fd->lower != NULL);
 
     return (fd->lower->methods->setsocketoption)(fd->lower, data);
 }
 
 /* Methods for the top of the stack.  Just call down to the next fd. */
-static struct PRIOMethods pl_methods = {
+static PRIOMethods pl_methods = {
     PR_DESC_LAYERED,
     pl_TopClose,
     pl_DefRead,
     pl_DefWrite,
     pl_DefAvailable,
     pl_DefAvailable64,
     pl_DefFsync,
     pl_DefSeek,
@@ -345,23 +350,23 @@ static struct PRIOMethods pl_methods = {
     pl_DefGetsockname,
     pl_DefGetpeername,
     pl_DefGetsockopt,
     pl_DefSetsockopt,
     pl_DefGetsocketoption,
     pl_DefSetsocketoption
 };
 
-PR_IMPLEMENT(PRIOMethods const*) PR_GetDefaultIOMethods()
+PR_IMPLEMENT(const PRIOMethods*) PR_GetDefaultIOMethods()
 {
     return &pl_methods;
 }  /* PR_GetDefaultIOMethods */
 
 PR_IMPLEMENT(PRFileDesc*) PR_CreateIOLayerStub(
-    PRDescIdentity ident, PRIOMethods const *methods)
+    PRDescIdentity ident, const PRIOMethods *methods)
 {
     PRFileDesc *fd = NULL;
     PR_ASSERT((PR_NSPR_IO_LAYER != ident) && (PR_TOP_IO_LAYER != ident));
     if ((PR_NSPR_IO_LAYER == ident) || (PR_TOP_IO_LAYER == ident))
         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
     else
     {
         fd = PR_NEWZAP(PRFileDesc);
@@ -394,16 +399,17 @@ PR_IMPLEMENT(PRStatus) PR_PushIOLayer(
     if (stack == insert)
     {
         /* going on top of the stack */
         PRFileDesc copy = *stack;
         *stack = *fd;
         *fd = copy;
         fd->higher = stack;
         stack->lower = fd;
+        stack->higher = NULL;
     }
     else
     {
         /* going somewhere in the middle of the stack */
         fd->lower = insert;
         fd->higher = insert->higher;
 
         insert->higher = fd;
--- a/pr/src/io/prmapopt.c
+++ b/pr/src/io/prmapopt.c
@@ -35,116 +35,16 @@
 #endif
 
 #include "primpl.h"
 
 #if defined(XP_UNIX) || defined(OS2)
 #include <netinet/tcp.h>  /* TCP_NODELAY, TCP_MAXSEG */
 #endif
 
-/*
- * Not every platform has all the socket options we want to
- * support.  Some older operating systems such as SunOS 4.1.3
- * don't have the IP multicast socket options.  Win32 doesn't
- * have TCP_MAXSEG.
- *
- * To deal with this problem, we define the missing socket
- * options as _PR_NO_SUCH_SOCKOPT.  _PR_MapOptionName() fails with
- * PR_OPERATION_NOT_SUPPORTED_ERROR if a socket option not
- * available on the platform is requested.
- */
-
-/*
- * Sanity check.  SO_LINGER and TCP_NODELAY should be available
- * on all platforms.  Just to make sure we have included the
- * appropriate header files.  Then any undefined socket options
- * are really missing.
- */
-
-#if !defined(SO_LINGER)
-#error "SO_LINGER is not defined"
-#endif
-
-#if !defined(TCP_NODELAY)
-#error "TCP_NODELAY is not defined"
-#endif
-
-/*
- * Make sure the value of _PR_NO_SUCH_SOCKOPT is not
- * a valid socket option.
- */
-#define _PR_NO_SUCH_SOCKOPT -1
-
-#ifndef IP_MULTICAST_IF                 /* set/get IP multicast interface   */
-#define IP_MULTICAST_IF     _PR_NO_SUCH_SOCKOPT
-#endif
-
-#ifndef IP_MULTICAST_TTL                /* set/get IP multicast timetolive  */
-#define IP_MULTICAST_TTL    _PR_NO_SUCH_SOCKOPT
-#endif
-
-#ifndef IP_MULTICAST_LOOP               /* set/get IP multicast loopback    */
-#define IP_MULTICAST_LOOP   _PR_NO_SUCH_SOCKOPT
-#endif
-
-#ifndef IP_ADD_MEMBERSHIP               /* add  an IP group membership      */
-#define IP_ADD_MEMBERSHIP   _PR_NO_SUCH_SOCKOPT
-#endif
-
-#ifndef IP_DROP_MEMBERSHIP              /* drop an IP group membership      */
-#define IP_DROP_MEMBERSHIP  _PR_NO_SUCH_SOCKOPT
-#endif
-
-#ifndef IP_TTL                          /* set/get IP Time To Live          */
-#define IP_TTL              _PR_NO_SUCH_SOCKOPT
-#endif
-
-#ifndef IP_TOS                          /* set/get IP Type Of Service       */
-#define IP_TOS              _PR_NO_SUCH_SOCKOPT
-#endif
-
-#ifndef TCP_MAXSEG                      /* maxumum segment size for tcp     */
-#define TCP_MAXSEG          _PR_NO_SUCH_SOCKOPT
-#endif
-
-PRStatus _PR_MapOptionName(
-    PRSockOption optname, PRInt32 *level, PRInt32 *name)
-{
-    static PRInt32 socketOptions[PR_SockOpt_Last] =
-    {
-        0, SO_LINGER, SO_REUSEADDR, SO_KEEPALIVE, SO_RCVBUF, SO_SNDBUF,
-        IP_TTL, IP_TOS, IP_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP,
-        IP_MULTICAST_IF, IP_MULTICAST_TTL, IP_MULTICAST_LOOP,
-        TCP_NODELAY, TCP_MAXSEG
-    };
-    static PRInt32 socketLevels[PR_SockOpt_Last] =
-    {
-        0, SOL_SOCKET, SOL_SOCKET, SOL_SOCKET, SOL_SOCKET, SOL_SOCKET,
-        IPPROTO_IP, IPPROTO_IP, IPPROTO_IP, IPPROTO_IP,
-        IPPROTO_IP, IPPROTO_IP, IPPROTO_IP,
-        IPPROTO_TCP, IPPROTO_TCP
-    };
-
-    if ((optname < PR_SockOpt_Linger)
-    && (optname > PR_SockOpt_MaxSegment))
-    {
-        PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
-        return PR_FAILURE;
-    }
-
-    if (socketOptions[optname] == _PR_NO_SUCH_SOCKOPT)
-    {
-        PR_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR, 0);
-        return PR_FAILURE;
-    }
-    *name = socketOptions[optname];
-    *level = socketLevels[optname];
-    return PR_SUCCESS;
-}  /* _PR_MapOptionName */
-
 #ifndef _PR_PTHREADS
 
 PRStatus PR_CALLBACK _PR_SocketGetSocketOption(PRFileDesc *fd, PRSocketOptionData *data)
 {
     PRStatus rv;
     PRInt32 length;
     PRInt32 level, name;
 
@@ -239,32 +139,34 @@ PRStatus PR_CALLBACK _PR_SocketGetSocket
 #endif
                 length = sizeof(ttl);
                 rv = _PR_MD_GETSOCKOPT(
                     fd, level, name, (char*)&ttl, &length);
                 if (PR_SUCCESS == rv)
                     data->value.mcast_ttl = ttl;
                 break;
             }
+#ifdef IP_ADD_MEMBERSHIP
             case PR_SockOpt_AddMember:
             case PR_SockOpt_DropMember:
             {
                 struct ip_mreq mreq;
                 length = sizeof(mreq);
                 rv = _PR_MD_GETSOCKOPT(
                     fd, level, name, (char*)&mreq, &length);
                 if (PR_SUCCESS == rv)
                 {
                     data->value.add_member.mcaddr.inet.ip =
                         mreq.imr_multiaddr.s_addr;
                     data->value.add_member.ifaddr.inet.ip =
                         mreq.imr_interface.s_addr;
                 }
                 break;
             }
+#endif /* IP_ADD_MEMBERSHIP */
             case PR_SockOpt_McastInterface:
             {
                 /* This option is a struct in_addr. */
                 length = sizeof(data->value.mcast_if.inet.ip);
                 rv = _PR_MD_GETSOCKOPT(
                     fd, level, name,
                     (char*)&data->value.mcast_if.inet.ip, &length);
                 break;
@@ -372,28 +274,30 @@ PRStatus PR_CALLBACK _PR_SocketSetSocket
 #else
                 PRUint8 ttl;
 #endif
                 ttl = data->value.mcast_ttl;
                 rv = _PR_MD_SETSOCKOPT(
                     fd, level, name, (char*)&ttl, sizeof(ttl));
                 break;
             }
+#ifdef IP_ADD_MEMBERSHIP
             case PR_SockOpt_AddMember:
             case PR_SockOpt_DropMember:
             {
                 struct ip_mreq mreq;
                 mreq.imr_multiaddr.s_addr =
                     data->value.add_member.mcaddr.inet.ip;
                 mreq.imr_interface.s_addr =
                     data->value.add_member.ifaddr.inet.ip;
                 rv = _PR_MD_SETSOCKOPT(
                     fd, level, name, (char*)&mreq, sizeof(mreq));
                 break;
             }
+#endif /* IP_ADD_MEMBERSHIP */
             case PR_SockOpt_McastInterface:
             {
                 /* This option is a struct in_addr. */
                 rv = _PR_MD_SETSOCKOPT(
                     fd, level, name, (char*)&data->value.mcast_if.inet.ip,
                     sizeof(data->value.mcast_if.inet.ip));
                 break;
             }
@@ -401,8 +305,119 @@ PRStatus PR_CALLBACK _PR_SocketSetSocket
                 PR_NOT_REACHED("Unknown socket option");
                 break;
         }  
     }
     return rv;
 }  /* _PR_SocketSetSocketOption */
 
 #endif /* ! _PR_PTHREADS */
+
+/*
+ *********************************************************************
+ *********************************************************************
+ **
+ ** Make sure that the following is at the end of this file,
+ ** because we will be playing with macro redefines.
+ **
+ *********************************************************************
+ *********************************************************************
+ */
+
+/*
+ * Not every platform has all the socket options we want to
+ * support.  Some older operating systems such as SunOS 4.1.3
+ * don't have the IP multicast socket options.  Win32 doesn't
+ * have TCP_MAXSEG.
+ *
+ * To deal with this problem, we define the missing socket
+ * options as _PR_NO_SUCH_SOCKOPT.  _PR_MapOptionName() fails with
+ * PR_OPERATION_NOT_SUPPORTED_ERROR if a socket option not
+ * available on the platform is requested.
+ */
+
+/*
+ * Sanity check.  SO_LINGER and TCP_NODELAY should be available
+ * on all platforms.  Just to make sure we have included the
+ * appropriate header files.  Then any undefined socket options
+ * are really missing.
+ */
+
+#if !defined(SO_LINGER)
+#error "SO_LINGER is not defined"
+#endif
+
+#if !defined(TCP_NODELAY)
+#error "TCP_NODELAY is not defined"
+#endif
+
+/*
+ * Make sure the value of _PR_NO_SUCH_SOCKOPT is not
+ * a valid socket option.
+ */
+#define _PR_NO_SUCH_SOCKOPT -1
+
+#ifndef IP_MULTICAST_IF                 /* set/get IP multicast interface   */
+#define IP_MULTICAST_IF     _PR_NO_SUCH_SOCKOPT
+#endif
+
+#ifndef IP_MULTICAST_TTL                /* set/get IP multicast timetolive  */
+#define IP_MULTICAST_TTL    _PR_NO_SUCH_SOCKOPT
+#endif
+
+#ifndef IP_MULTICAST_LOOP               /* set/get IP multicast loopback    */
+#define IP_MULTICAST_LOOP   _PR_NO_SUCH_SOCKOPT
+#endif
+
+#ifndef IP_ADD_MEMBERSHIP               /* add  an IP group membership      */
+#define IP_ADD_MEMBERSHIP   _PR_NO_SUCH_SOCKOPT
+#endif
+
+#ifndef IP_DROP_MEMBERSHIP              /* drop an IP group membership      */
+#define IP_DROP_MEMBERSHIP  _PR_NO_SUCH_SOCKOPT
+#endif
+
+#ifndef IP_TTL                          /* set/get IP Time To Live          */
+#define IP_TTL              _PR_NO_SUCH_SOCKOPT
+#endif
+
+#ifndef IP_TOS                          /* set/get IP Type Of Service       */
+#define IP_TOS              _PR_NO_SUCH_SOCKOPT
+#endif
+
+#ifndef TCP_MAXSEG                      /* maxumum segment size for tcp     */
+#define TCP_MAXSEG          _PR_NO_SUCH_SOCKOPT
+#endif
+
+PRStatus _PR_MapOptionName(
+    PRSockOption optname, PRInt32 *level, PRInt32 *name)
+{
+    static PRInt32 socketOptions[PR_SockOpt_Last] =
+    {
+        0, SO_LINGER, SO_REUSEADDR, SO_KEEPALIVE, SO_RCVBUF, SO_SNDBUF,
+        IP_TTL, IP_TOS, IP_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP,
+        IP_MULTICAST_IF, IP_MULTICAST_TTL, IP_MULTICAST_LOOP,
+        TCP_NODELAY, TCP_MAXSEG
+    };
+    static PRInt32 socketLevels[PR_SockOpt_Last] =
+    {
+        0, SOL_SOCKET, SOL_SOCKET, SOL_SOCKET, SOL_SOCKET, SOL_SOCKET,
+        IPPROTO_IP, IPPROTO_IP, IPPROTO_IP, IPPROTO_IP,
+        IPPROTO_IP, IPPROTO_IP, IPPROTO_IP,
+        IPPROTO_TCP, IPPROTO_TCP
+    };
+
+    if ((optname < PR_SockOpt_Linger)
+    && (optname > PR_SockOpt_MaxSegment))
+    {
+        PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+        return PR_FAILURE;
+    }
+
+    if (socketOptions[optname] == _PR_NO_SUCH_SOCKOPT)
+    {
+        PR_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR, 0);
+        return PR_FAILURE;
+    }
+    *name = socketOptions[optname];
+    *level = socketLevels[optname];
+    return PR_SUCCESS;
+}  /* _PR_MapOptionName */
--- a/pr/src/io/prprf.c
+++ b/pr/src/io/prprf.c
@@ -30,21 +30,21 @@
 #include "prlong.h"
 #include "prlog.h"
 #include "prmem.h"
 
 /*
 ** Note: on some platforms va_list is defined as an array,
 ** and requires array notation.
 */
-#if defined(MACLINUX) || defined(WIN16)
+#if defined(MKLINUX) || defined(WIN16)
 #define VARARGS_ASSIGN(foo, bar) foo[0] = bar[0]
 #else
 #define VARARGS_ASSIGN(foo, bar) (foo) = (bar)
-#endif /*MACLINUX*/
+#endif /*MKLINUX*/
 
 /*
 ** WARNING: This code may *NOT* call PR_LOG (because PR_LOG calls it)
 */
 
 /*
 ** XXX This needs to be internationalized!
 */
--- a/pr/src/io/prscanf.c
+++ b/pr/src/io/prscanf.c
@@ -374,17 +374,17 @@ GetFloat(ScanfState *state)
             *va_arg(state->ap, PRFloat64 *) = dval;
         } else if (state->sizeSpec == _PR_size_L) {
 #if defined(OSF1) || defined(IRIX)
             *va_arg(state->ap, double *) = dval;
 #else
             *va_arg(state->ap, long double *) = dval;
 #endif
         } else {
-            *va_arg(state->ap, float *) = dval;
+            *va_arg(state->ap, float *) = (float) dval;
         }
     }
     return PR_SUCCESS;
 }
 
 /*
  * Convert, and return the end of the conversion spec.
  */
--- a/pr/src/io/prsocket.c
+++ b/pr/src/io/prsocket.c
@@ -25,97 +25,133 @@
 
 #if defined(SVR4) || defined(SUNOS4)
 /* To pick up FIONREAD */
 #include <sys/filio.h>
 #endif
 
 /************************************************************************/
 
+/* These two functions are only used in assertions. */
+#if defined(DEBUG)
+
+static PRBool IsValidNetAddr(const PRNetAddr *addr)
+{
+    if ((addr != NULL)
+#ifdef XP_UNIX
+	    && (addr->raw.family != AF_UNIX)
+#endif
+#ifdef _PR_INET6
+	    && (addr->raw.family != AF_INET6)
+#endif
+	    && (addr->raw.family != AF_INET)) {
+        return PR_FALSE;
+    }
+    return PR_TRUE;
+}
+
+static PRBool IsValidNetAddrLen(const PRNetAddr *addr, PRInt32 addr_len)
+{
+    /*
+     * The definition of the length of a Unix domain socket address
+     * is not uniform, so we don't check it.
+     */
+    if ((addr != NULL)
+#ifdef XP_UNIX
+            && (addr->raw.family != AF_UNIX)
+#endif
+            && (PR_NETADDR_SIZE(addr) != addr_len)) {
+        return PR_FALSE;
+    }
+    return PR_TRUE;
+}
+
+#endif /* DEBUG */
+
 static PRInt32 PR_CALLBACK SocketWritev(PRFileDesc *fd, PRIOVec *iov, PRInt32 iov_size,
 PRIntervalTime timeout)
 {
 	PRThread *me = _PR_MD_CURRENT_THREAD();
 	int w = 0;
 	PRIOVec *tmp_iov = NULL;
+#define LOCAL_MAXIOV    8
+	PRIOVec local_iov[LOCAL_MAXIOV];
 	int tmp_out;
 	int index, iov_cnt;
 	int count=0, sz = 0;    /* 'count' is the return value. */
-#if defined(XP_UNIX)
-	struct timeval tv, *tvp;
-	fd_set wd;
-
-	FD_ZERO(&wd);
-	if (timeout == PR_INTERVAL_NO_TIMEOUT)
-		tvp = NULL;
-	else if (timeout != PR_INTERVAL_NO_WAIT) {
-		tv.tv_sec = PR_IntervalToSeconds(timeout);
-		tv.tv_usec = PR_IntervalToMicroseconds(
-		    timeout - PR_SecondsToInterval(tv.tv_sec));
-		tvp = &tv;
-	}
-#endif
 
 	if (_PR_PENDING_INTERRUPT(me)) {
 		me->flags &= ~_PR_INTERRUPT;
 		PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
 		return -1;
 	}
 	if (_PR_IO_PENDING(me)) {
 		PR_SetError(PR_IO_PENDING_ERROR, 0);
 		return -1;
 	}
 
-	tmp_iov = (PRIOVec *)PR_CALLOC(iov_size * sizeof(PRIOVec));
-	if (!tmp_iov) {
-		PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
-		return -1;
-	}
+    /*
+     * Assume the first writev will succeed.  Copy iov's only on
+     * failure.
+     */
+    tmp_iov = iov;
+    for (index = 0; index < iov_size; index++)
+        sz += iov[index].iov_len;
 
-	for (index=0; index<iov_size; index++) {
-		sz += iov[index].iov_len;
-		tmp_iov[index].iov_base = iov[index].iov_base;
-		tmp_iov[index].iov_len = iov[index].iov_len;
-	}
 	iov_cnt = iov_size;
 
 	while (sz > 0) {
 
 		w = _PR_MD_WRITEV(fd, tmp_iov, iov_cnt, timeout);
 		if (w < 0) {
-					count = -1;
-					break;
+			count = -1;
+			break;
 		}
 		count += w;
 		if (fd->secret->nonblocking) {
 			break;
 		}
 		sz -= w;
 
 		if (sz > 0) {
 			/* find the next unwritten vector */
 			for ( index = 0, tmp_out = count;
-			    tmp_out >= iov[index].iov_len;
-			    tmp_out -= iov[index].iov_len, index++){;} /* nothing to execute */
+				tmp_out >= iov[index].iov_len;
+				tmp_out -= iov[index].iov_len, index++){;} /* nothing to execute */
 
+			if (tmp_iov == iov) {
+				/*
+				 * The first writev failed so we
+				 * must copy iov's around.
+				 * Avoid calloc/free if there
+				 * are few enough iov's.
+				 */
+				if (iov_size - index <= LOCAL_MAXIOV)
+					tmp_iov = local_iov;
+				else if ((tmp_iov = (PRIOVec *) PR_CALLOC((iov_size - index) *
+					sizeof *tmp_iov)) == NULL) {
+					PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+					return -1;
+				}
+			}
 
 			/* fill in the first partial read */
 			tmp_iov[0].iov_base = &(((char *)iov[index].iov_base)[tmp_out]);
 			tmp_iov[0].iov_len = iov[index].iov_len - tmp_out;
 			index++;
 
 			/* copy the remaining vectors */
 			for (iov_cnt=1; index<iov_size; iov_cnt++, index++) {
 				tmp_iov[iov_cnt].iov_base = iov[index].iov_base;
 				tmp_iov[iov_cnt].iov_len = iov[index].iov_len;
 			}
 		}
 	}
 
-	if (tmp_iov)
+	if (tmp_iov != iov && tmp_iov != local_iov)
 		PR_DELETE(tmp_iov);
 	return count;
 }
 
 /************************************************************************/
 
 PR_IMPLEMENT(PRFileDesc *) PR_ImportTCPSocket(PRInt32 osfd)
 {
@@ -302,23 +338,18 @@ PRIntervalTime timeout)
 	 * of the listening socket.  As an optimization, these
 	 * platforms can skip the following _PR_MD_MAKE_NONBLOCK
 	 * call.
 	 */
 #if !defined(SOLARIS) && !defined(IRIX) && !defined(WINNT)
 	_PR_MD_MAKE_NONBLOCK(fd2);
 #endif
 
-	PR_ASSERT((NULL == addr) || (PR_NETADDR_SIZE(addr) == al));
-#if defined(_PR_INET6)
-	PR_ASSERT((NULL == addr) || (addr->raw.family == AF_INET)
-		|| (addr->raw.family == AF_INET6));
-#else
-	PR_ASSERT((NULL == addr) || (addr->raw.family == AF_INET));
-#endif
+	PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
+	PR_ASSERT(IsValidNetAddrLen(addr, al) == PR_TRUE);
 
 	return fd2;
 }
 
 #ifdef WINNT
 PR_IMPLEMENT(PRFileDesc*) PR_NTFast_Accept(PRFileDesc *fd, PRNetAddr *addr,
 PRIntervalTime timeout)
 {
@@ -362,29 +393,39 @@ PRIntervalTime timeout)
 #endif /* WINNT */
 
 
 static PRStatus PR_CALLBACK SocketBind(PRFileDesc *fd, const PRNetAddr *addr)
 {
 	PRInt32 result;
 	int one = 1;
 
-#if defined(_PR_INET6)
-	PR_ASSERT(addr->raw.family == AF_INET || addr->raw.family == AF_INET6);
-#else
-	PR_ASSERT(addr->raw.family == AF_INET);
+	PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
+
+#ifdef XP_UNIX
+	if (addr->raw.family == AF_UNIX) {
+		/* Disallow relative pathnames */
+		if (addr->local.path[0] != '/') {
+			PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+			return PR_FAILURE;
+		}
+	} else {
 #endif
 
 #ifdef HAVE_SOCKET_REUSEADDR
 	if ( setsockopt (fd->secret->md.osfd, (int)SOL_SOCKET, SO_REUSEADDR, 
 	    (const void *)&one, sizeof(one) ) < 0) {
 		return PR_FAILURE;
 	}
 #endif
 
+#ifdef XP_UNIX
+	}
+#endif
+
 	result = _PR_MD_BIND(fd, addr, PR_NETADDR_SIZE(addr));
 	if (result < 0) {
 		return PR_FAILURE;
 	}
 	return PR_SUCCESS;
 }
 
 static PRStatus PR_CALLBACK SocketListen(PRFileDesc *fd, PRIntn backlog)
@@ -536,21 +577,17 @@ static PRInt32 PR_CALLBACK SocketSendTo(
 		PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
 		return -1;
 	}
 	if (_PR_IO_PENDING(me)) {
 		PR_SetError(PR_IO_PENDING_ERROR, 0);
 		return -1;
 	}
 
-#if defined(_PR_INET6)
-	PR_ASSERT(addr->raw.family == AF_INET || addr->raw.family == AF_INET6);
-#else
-	PR_ASSERT(addr->raw.family == AF_INET);
-#endif
+	PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
 
 	count = 0;
 	while (amount > 0) {
 		temp = _PR_MD_SENDTO(fd, buf, amount, flags,
 		    addr, PR_NETADDR_SIZE(addr), timeout);
 		if (temp < 0) {
 					count = -1;
 					break;
@@ -792,41 +829,33 @@ static PRStatus PR_CALLBACK SocketGetNam
 	PRInt32 result;
 	PRUint32 addrlen;
 
 	addrlen = sizeof(PRNetAddr);
 	result = _PR_MD_GETSOCKNAME(fd, addr, &addrlen);
 	if (result < 0) {
 		return PR_FAILURE;
 	}
-	PR_ASSERT(addrlen == PR_NETADDR_SIZE(addr));
-#if defined(_PR_INET6)
-	PR_ASSERT(addr->raw.family == AF_INET || addr->raw.family == AF_INET6);
-#else
-	PR_ASSERT(addr->raw.family == AF_INET);
-#endif
+	PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
+	PR_ASSERT(IsValidNetAddrLen(addr, addrlen) == PR_TRUE);
 	return PR_SUCCESS;
 }
 
 static PRStatus PR_CALLBACK SocketGetPeerName(PRFileDesc *fd, PRNetAddr *addr)
 {
 	PRInt32 result;
 	PRUint32 addrlen;
 
 	addrlen = sizeof(PRNetAddr);
 	result = _PR_MD_GETPEERNAME(fd, addr, &addrlen);
 	if (result < 0) {
 		return PR_FAILURE;
 	}
-	PR_ASSERT(addrlen == PR_NETADDR_SIZE(addr));
-#if defined(_PR_INET6)
-	PR_ASSERT(addr->raw.family == AF_INET || addr->raw.family == AF_INET6);
-#else
-	PR_ASSERT(addr->raw.family == AF_INET);
-#endif
+	PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
+	PR_ASSERT(IsValidNetAddrLen(addr, addrlen) == PR_TRUE);
 	return PR_SUCCESS;
 }
 
 static PRStatus PR_CALLBACK SocketGetSockOpt(
     PRFileDesc *fd, PRSockOption optname, void* optval, PRInt32* optlen)
 {
     PRInt32 level, name;
     PRStatus rv;
@@ -920,16 +949,23 @@ static PRStatus PR_CALLBACK SocketSetSoc
         {
             rv = _PR_MD_SETSOCKOPT(
                 fd, level, name, optval, optlen);
         }
     }
     return rv;
 }
 
+static PRInt16 PR_CALLBACK SocketPoll(
+    PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags)
+{
+    *out_flags = 0;
+    return in_flags;
+}  /* SocketPoll */
+
 static PRIOMethods tcpMethods = {
 	PR_DESC_SOCKET_TCP,
 	SocketClose,
 	SocketRead,
 	SocketWrite,
 	SocketAvailable,
 	SocketAvailable64,
 	SocketSync,
@@ -942,17 +978,17 @@ static PRIOMethods tcpMethods = {
 	SocketAccept,
 	SocketBind,
 	SocketListen,
 	SocketShutdown,
 	SocketRecv,
 	SocketSend,
 	(PRRecvfromFN)_PR_InvalidInt,
 	(PRSendtoFN)_PR_InvalidInt,
-	(PRPollFN)0,
+	SocketPoll,
 	SocketAcceptRead,
 	SocketTransmitFile,
 	SocketGetName,
 	SocketGetPeerName,
 	SocketGetSockOpt,
 	SocketSetSockOpt,
 	_PR_SocketGetSocketOption,
 	_PR_SocketSetSocketOption
@@ -975,48 +1011,51 @@ static PRIOMethods udpMethods = {
 	(PRAcceptFN)_PR_InvalidDesc,
 	SocketBind,
 	SocketListen,
 	SocketShutdown,
 	SocketRecv,
 	SocketSend,
 	SocketRecvFrom,
 	SocketSendTo,
-	(PRPollFN)0,
+	SocketPoll,
 	(PRAcceptreadFN)_PR_InvalidInt,
 	(PRTransmitfileFN)_PR_InvalidInt,
 	SocketGetName,
 	SocketGetPeerName,
 	SocketGetSockOpt,
 	SocketSetSockOpt,
 	_PR_SocketGetSocketOption,
 	_PR_SocketSetSocketOption
 };
 
-PR_IMPLEMENT(PRIOMethods*) PR_GetTCPMethods()
+PR_IMPLEMENT(const PRIOMethods*) PR_GetTCPMethods()
 {
 	return &tcpMethods;
 }
 
-PR_IMPLEMENT(PRIOMethods*) PR_GetUDPMethods()
+PR_IMPLEMENT(const PRIOMethods*) PR_GetUDPMethods()
 {
 	return &udpMethods;
 }
 
 PR_IMPLEMENT(PRFileDesc*) PR_Socket(PRInt32 domain, PRInt32 type, PRInt32 proto)
 {
 	PRInt32 osfd;
 	int one = 1;
 	PRFileDesc *fd;
 
 	if (!_pr_initialized) _PR_ImplicitInitialization();
 	if (AF_INET != domain
 #if defined(_PR_INET6)
 			&& AF_INET6 != domain
 #endif
+#if defined(XP_UNIX)
+			&& AF_UNIX != domain
+#endif
 			) {
 		PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0);
 		return NULL;
 	}
 	osfd = _PR_MD_SOCKET(domain, type, proto);
 	if (osfd == -1) {
 		return 0;
 	}
@@ -1238,41 +1277,39 @@ done:
  *	return number of bytes read or -1 on error
  *
  */
 PRInt32 _PR_EmulateAcceptRead(PRFileDesc *sd, PRFileDesc **nd, 
 PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime timeout)
 {
 	PRInt32 rv;
 	PRFileDesc *newsockfd;
-	PRNetAddr remote;
 	PRIntervalTime start, elapsed;
 
 	if (PR_INTERVAL_NO_TIMEOUT != timeout) {
 		start = PR_IntervalNow();
 	}
-	if ((newsockfd = PR_Accept(sd, &remote, timeout)) == NULL) {
+	*raddr = (PRNetAddr *) ((char *) buf + amount);
+	if ((newsockfd = PR_Accept(sd, *raddr, timeout)) == NULL) {
 		return -1;
 	}
 
 	if (PR_INTERVAL_NO_TIMEOUT != timeout) {
 		elapsed = (PRIntervalTime) (PR_IntervalNow() - start);
 		if (elapsed > timeout) {
 			PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
 			goto failed;
 		} else {
 			timeout = timeout - elapsed;
 		}
 	}
 
 	rv = PR_Recv(newsockfd, buf, amount, 0, timeout);
 	if (rv >= 0) {
 		*nd = newsockfd;
-		*raddr = (PRNetAddr *)((char *) buf + amount);
-		memcpy(*raddr, &remote, PR_NETADDR_SIZE(&remote));
 		return rv;
 	}
 
 failed:
 	PR_Close(newsockfd);
 	return -1;
 }
 
--- a/pr/src/md/mac/macsockotpt.c
+++ b/pr/src/md/mac/macsockotpt.c
@@ -1444,17 +1444,17 @@ PR_IMPLEMENT(struct hostent *) gethostby
 PR_IMPLEMENT(char *) inet_ntoa(struct in_addr addr)
 {
 	OTInetHostToString((InetHost)addr.s_addr, sHostInfo.name);
 	
 	return sHostInfo.name;
 }
 
 
-PR_IMPLEMENT(PRStatus) _MD_gethostname(char *name, int namelen)
+PRStatus _MD_gethostname(char *name, int namelen)
 {
 	OSStatus err;
 	InetInterfaceInfo info;
 
 	/*
 	 *	On a Macintosh, we donŐt have the concept of a local host name.
 	 *	We do though have an IP address & everyone should be happy with
 	 * 	a string version of that for a name.
--- a/pr/src/md/os2/os2cv.c
+++ b/pr/src/md/os2/os2cv.c
@@ -142,17 +142,17 @@ md_UnlockAndPostNotifies(
         notified = notified->link;
     } while (NULL != notified);
 
     if (waitThred) {
         AddThreadToCVWaitQueueInternal(waitThred, waitCV);
     }
 
     /* Release the lock before notifying */
-        LeaveCriticalSection(&lock->mutex);
+        DosReleaseMutexSem(lock->mutex);
 
     notified = &post;  /* this is where we start */
     do {
         for (index = 0; index < notified->length; ++index) {
             PRThread *thred;
             PRThread *next;
 
             thred = notified->cv[index].notifyHead;
@@ -249,24 +249,24 @@ PR_IMPLEMENT(void)
 
     /*
      * If we have pending notifies, post them now.
      */
     if (0 != lock->notified.length) {
         md_UnlockAndPostNotifies(lock, thred, cv);
     } else {
         AddThreadToCVWaitQueueInternal(thred, cv);
-        LeaveCriticalSection(&lock->mutex); 
+        DosReleaseMutexSem(lock->mutex); 
     }
 
     /* Wait for notification or timeout; don't really care which */
     rv = DosWaitEventSem(thred->md.blocked_sema.sem, msecs);
     DosResetEventSem(thred->md.blocked_sema.sem, &count);
 
-    EnterCriticalSection(&(lock->mutex));
+    _MD_LOCK(lock);
 
     PR_ASSERT(rv == NO_ERROR || rv == ERROR_TIMEOUT);
 
     if(rv == ERROR_TIMEOUT)
     {
        if (thred->md.inCVWaitQueue) {
            PR_ASSERT((cv->waitTail != NULL && cv->waitHead != NULL)
                    || (cv->waitTail == NULL && cv->waitHead == NULL));
@@ -321,12 +321,12 @@ PR_IMPLEMENT(void)
 }
 
 PR_IMPLEMENT(void)
 _PR_MD_UNLOCK(_MDLock *lock)
 {
     if (0 != lock->notified.length) {
         md_UnlockAndPostNotifies(lock, NULL, NULL);
     } else {
-        LeaveCriticalSection(&lock->mutex);
+        DosReleaseMutexSem(lock->mutex);
     }
     return;
 }
--- a/pr/src/md/os2/os2gc.c
+++ b/pr/src/md/os2/os2gc.c
@@ -17,17 +17,17 @@
  */
 
 /*
  * GC related routines
  *
  */
 #include "primpl.h"
 
-extern APIRET (* APIENTRY QueryThreadContext)(TID, ULONG, PCONTEXTRECORD);
+extern APIRET (* APIENTRY QueryThreadContext)(OS2TID, ULONG, PCONTEXTRECORD);
 
 PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np) 
 {
     CONTEXTRECORD context;
     context.ContextFlags = CONTEXT_INTEGER;
 
     if (_PR_IS_NATIVE_THREAD(t)) {
         context.ContextFlags |= CONTEXT_CONTROL;
--- a/pr/src/md/os2/os2io.c
+++ b/pr/src/md/os2/os2io.c
@@ -22,17 +22,17 @@
  *
  */
 
 #include "primpl.h"
 #include <direct.h>
 
 struct _MDLock               _pr_ioq_lock;
 
-PR_IMPLEMENT(PRStatus)
+PRStatus
 _PR_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
 {
     PRInt32 rv;
     ULONG count;
 
     PRUint32 msecs = (ticks == PR_INTERVAL_NO_TIMEOUT) ?
         SEM_INDEFINITE_WAIT : PR_IntervalToMilliseconds(ticks);
     rv = DosWaitEventSem(thread->md.blocked_sema.sem, msecs);
@@ -63,17 +63,17 @@ PR_IMPLEMENT(PRStatus)
             }
             return PR_SUCCESS;
             break;
         default:
             break;
     }
     return PR_FAILURE;
 }
-PR_IMPLEMENT(PRStatus)
+PRStatus
 _PR_MD_WAKEUP_WAITER(PRThread *thread)
 {
     if ( _PR_IS_NATIVE_THREAD(thread) ) 
     {
         if (DosPostEventSem(thread->md.blocked_sema.sem) != NO_ERROR)
             return PR_FAILURE;
         else
 			return PR_SUCCESS;
@@ -551,17 +551,17 @@ PRInt32
     if ( (rc = DosDeleteDir((char *)name)) == NO_ERROR) {
         return 0;
     } else {
 		_PR_MD_MAP_RMDIR_ERROR(rc);
         return -1;
     }
 }
 
-PR_IMPLEMENT(PRStatus)
+PRStatus
 _PR_MD_LOCKFILE(PRInt32 f)
 {
 	PRInt32   rv;
    FILELOCK lock, unlock;
 
    lock.lOffset = 0;
    lock.lRange = 0xffffffff;
    unlock.lOffset = 0;
@@ -581,24 +581,24 @@ PR_IMPLEMENT(PRStatus)
 		if ( rv != NO_ERROR )
         {
             DosSleep( 50 );  /* Sleep() a few milisecs and try again. */
         }            
     } /* end for() */
     return PR_SUCCESS;
 } /* end _PR_MD_LOCKFILE() */
 
-PR_IMPLEMENT(PRStatus)
+PRStatus
 _PR_MD_TLOCKFILE(PRInt32 f)
 {
     return _PR_MD_LOCKFILE(f);
 } /* end _PR_MD_TLOCKFILE() */
 
 
-PR_IMPLEMENT(PRStatus)
+PRStatus
 _PR_MD_UNLOCKFILE(PRInt32 f)
 {
 	PRInt32   rv;
    FILELOCK lock, unlock;
 
    lock.lOffset = 0;
    lock.lRange = 0;
    unlock.lOffset = 0;
--- a/pr/src/md/os2/os2misc.c
+++ b/pr/src/md/os2/os2misc.c
@@ -17,23 +17,23 @@
  */
 
 /*
  * os2misc.c
  *
  */
 #include "primpl.h"
 
-PR_IMPLEMENT(char *)
+char *
 _PR_MD_GET_ENV(const char *name)
 {
     return getenv(name);
 }
 
-PR_IMPLEMENT(PRIntn)
+PRIntn
 _PR_MD_PUT_ENV(const char *name)
 {
     return putenv(name);
 }
 
 
 /*
  **************************************************************************
@@ -447,17 +447,17 @@ PRStatus _PR_KillOS2Process(PRProcess *p
    ULONG ulRetVal;
     if ((ulRetVal = DosKillProcess(DKP_PROCESS, process->md.pid)) == NO_ERROR) {
 	return PR_SUCCESS;
     }
     PR_SetError(PR_UNKNOWN_ERROR, ulRetVal);
     return PR_FAILURE;
 }
 
-PR_IMPLEMENT(PRStatus) _MD_OS2GetHostName(char *name, PRUint32 namelen)
+PRStatus _MD_OS2GetHostName(char *name, PRUint32 namelen)
 {
     PRIntn rv;
     PRInt32 syserror;
 
     rv = gethostname(name, (PRInt32) namelen);
     if (0 == rv) {
         return PR_SUCCESS;
     }
--- a/pr/src/md/os2/os2thred.c
+++ b/pr/src/md/os2/os2thred.c
@@ -14,17 +14,17 @@
  * Communications Corporation.  Portions created by Netscape are
  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  * Reserved.
  */
 
 #include "primpl.h"
 #include <process.h>  /* for _beginthread() */
 
-APIRET (* APIENTRY QueryThreadContext)(TID, ULONG, PCONTEXTRECORD);
+APIRET (* APIENTRY QueryThreadContext)(OS2TID, ULONG, PCONTEXTRECORD);
 
 /* --- globals ------------------------------------------------ */
 _NSPR_TLS*        pThreadLocalStorage = 0;
 _PRInterruptTable             _pr_interruptTable[] = { { 0 } };
 
 PR_IMPLEMENT(void)
 _PR_MD_ENSURE_TLS()
 {
@@ -78,17 +78,17 @@ PR_IMPLEMENT(PRStatus)
 PR_IMPLEMENT(PRStatus) 
 _PR_MD_CREATE_THREAD(PRThread *thread, 
                   void (*start)(void *), 
                   PRThreadPriority priority, 
                   PRThreadScope scope, 
                   PRThreadState state, 
                   PRUint32 stackSize)
 {
-    thread->md.handle = thread->id = (TID) _beginthread(
+    thread->md.handle = thread->id = (OS2TID) _beginthread(
                     (void(* _Optlink)(void*))start,
                     NULL, 
                     thread->stack->stackSize,
                     thread);
     if(thread->md.handle == -1) {
         return PR_FAILURE;
     }
     _PR_MD_SET_PRIORITY(&(thread->md), priority);
--- a/pr/src/md/unix/aix.c
+++ b/pr/src/md/unix/aix.c
@@ -15,37 +15,50 @@
  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  * Reserved.
  */
 
 #include "primpl.h"
 
 /*
  * NSPR 2.0 overrides the system select() and poll() functions.
- * On AIX 4.2, we use dlopen("/unix", 0) and dlsym() to get to the
- * original system select() and poll() functions.
+ * On AIX 4.2, we use dlopen("/unix", RTLD_NOW) and dlsym() to get
+ * at the original system select() and poll() functions.
  */
 
 #ifndef AIX4_1
 
+#include <sys/atomic_op.h>
 #include <sys/select.h>
 #include <sys/poll.h>
 #include <dlfcn.h>
 
 static void *aix_handle = NULL;
 static int (*aix_select_fcn)() = NULL;
 static int (*aix_poll_fcn)() = NULL;
 
+PRInt32 _AIX_AtomicSet(PRInt32 *val, PRInt32 newval)
+{
+    PRIntn oldval;
+    boolean_t stored;
+    oldval = fetch_and_add((atomic_p)val, 0);
+    do
+    {
+        stored = compare_and_swap((atomic_p)val, &oldval, newval);
+    } while (!stored);
+    return oldval;
+}  /* _AIX_AtomicSet */
+
 int _MD_SELECT(int width, fd_set *r, fd_set *w, fd_set *e, struct timeval *t)
 {
     int rv;
 
     if (!aix_select_fcn) {
 	if (!aix_handle) {
-	    aix_handle = dlopen("/unix",0);
+	    aix_handle = dlopen("/unix", RTLD_NOW);
 	    if (!aix_handle) {
 	        PR_SetError(PR_UNKNOWN_ERROR, 0);
 	        return -1;
 	    }
 	}
 	aix_select_fcn = (int(*)())dlsym(aix_handle,"select");
 	if (!aix_select_fcn) {
 	    PR_SetError(PR_UNKNOWN_ERROR, 0);
@@ -57,17 +70,17 @@ int _MD_SELECT(int width, fd_set *r, fd_
 }
 
 int _MD_POLL(void *listptr, unsigned long nfds, long timeout)
 {
     int rv;
 
     if (!aix_poll_fcn) {
 	if (!aix_handle) {
-	    aix_handle = dlopen("/unix",0);
+	    aix_handle = dlopen("/unix", RTLD_NOW);
 	    if (!aix_handle) {
 	        PR_SetError(PR_UNKNOWN_ERROR, 0);
 	        return -1;
 	    }
 	}
 	aix_poll_fcn = (int(*)())dlsym(aix_handle,"poll");
 	if (!aix_poll_fcn) {
 	    PR_SetError(PR_UNKNOWN_ERROR, 0);
@@ -90,20 +103,48 @@ void _pr_aix_dummy()
 {
     poll(0,0,0);
 }
 
 #endif /* !AIX4_1 */
 
 #if !defined(PTHREADS_USER)
 
+#ifdef _PR_PTHREADS
+
+/*
+ * AIX 4.3 has sched_yield().  AIX 4.2 has pthread_yield().
+ * So we look up the appropriate function pointer at run time.
+ */
+
+int (*_PT_aix_yield_fcn)() = NULL;
+
+void _MD_EarlyInit(void)
+{
+    void *main_app_handle = NULL;
+
+    main_app_handle = dlopen(NULL, RTLD_NOW);
+    PR_ASSERT(NULL != main_app_handle);
+
+    _PT_aix_yield_fcn = (int(*)())dlsym(main_app_handle, "sched_yield");
+    if (!_PT_aix_yield_fcn) {
+        _PT_aix_yield_fcn = (int(*)())dlsym(main_app_handle,"pthread_yield");
+        PR_ASSERT(NULL != _PT_aix_yield_fcn);
+    }
+    dlclose(main_app_handle);
+}
+
+#else /* _PR_PTHREADS */
+
 void _MD_EarlyInit(void)
 {
 }
 
+#endif /* _PR_PTHREADS */
+
 PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
 {
 #ifndef _PR_PTHREADS
     if (isCurrent) {
 	(void) setjmp(CONTEXT(t));
     }
     *np = sizeof(CONTEXT(t)) / sizeof(PRWord);
     return (PRWord *) CONTEXT(t);
--- a/pr/src/md/unix/freebsd.c
+++ b/pr/src/md/unix/freebsd.c
@@ -93,140 +93,8 @@ PRStatus
     PRThreadScope scope,
     PRThreadState state,
     PRUint32 stackSize)
 {
     PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for OSF1.");
 	return PR_FAILURE;
 }
 #endif /* ! _PR_PTHREADS */
-
-#if defined(_PR_NEED_FAKE_POLL)
-
-#include <fcntl.h>
-
-int poll(struct pollfd *filedes, unsigned long nfds, int timeout)
-{
-    int i;
-    int rv;
-    int maxfd;
-    fd_set rd, wr, ex;
-    struct timeval tv, *tvp;
-
-    if (timeout < 0 && timeout != -1) {
-	errno = EINVAL;
-	return -1;
-    }
-
-    if (timeout == -1) {
-        tvp = NULL;
-    } else {
-	tv.tv_sec = timeout / 1000;
-	tv.tv_usec = (timeout % 1000) * 1000;
-        tvp = &tv;
-    }
-
-    maxfd = -1;
-    FD_ZERO(&rd);
-    FD_ZERO(&wr);
-    FD_ZERO(&ex);
-
-    for (i = 0; i < nfds; i++) {
-	int osfd = filedes[i].fd;
-	int events = filedes[i].events;
-	PRBool fdHasEvent = PR_FALSE;
-
-	if (osfd < 0) {
-            continue;  /* Skip this osfd. */
-	}
-
-	/*
-	 * Map the native poll flags to nspr poll flags.
-	 *     POLLIN, POLLRDNORM  ===> PR_POLL_READ
-	 *     POLLOUT, POLLWRNORM ===> PR_POLL_WRITE
-	 *     POLLPRI, POLLRDBAND ===> PR_POLL_EXCEPTION
-	 *     POLLNORM, POLLWRBAND (and POLLMSG on some platforms)
-	 *     are ignored.
-	 *
-	 * The output events POLLERR and POLLHUP are never turned on.
-	 * POLLNVAL may be turned on.
-	 */
-
-	if (events & (POLLIN | POLLRDNORM)) {
-	    FD_SET(osfd, &rd);
-	    fdHasEvent = PR_TRUE;
-	}
-	if (events & (POLLOUT | POLLWRNORM)) {
-	    FD_SET(osfd, &wr);
-	    fdHasEvent = PR_TRUE;
-	}
-	if (events & (POLLPRI | POLLRDBAND)) {
-	    FD_SET(osfd, &ex);
-	    fdHasEvent = PR_TRUE;
-	}
-	if (fdHasEvent && osfd > maxfd) {
-	    maxfd = osfd;
-	}
-    }
-
-    rv = select(maxfd + 1, &rd, &wr, &ex, tvp);
-
-    /* Compute poll results */
-    if (rv > 0) {
-	rv = 0;
-        for (i = 0; i < nfds; i++) {
-	    PRBool fdHasEvent = PR_FALSE;
-
-	    filedes[i].revents = 0;
-            if (filedes[i].fd < 0) {
-                continue;
-            }
-	    if (FD_ISSET(filedes[i].fd, &rd)) {
-		if (filedes[i].events & POLLIN) {
-		    filedes[i].revents |= POLLIN;
-		}
-		if (filedes[i].events & POLLRDNORM) {
-		    filedes[i].revents |= POLLRDNORM;
-		}
-		fdHasEvent = PR_TRUE;
-	    }
-	    if (FD_ISSET(filedes[i].fd, &wr)) {
-		if (filedes[i].events & POLLOUT) {
-		    filedes[i].revents |= POLLOUT;
-		}
-		if (filedes[i].events & POLLWRNORM) {
-		    filedes[i].revents |= POLLWRNORM;
-		}
-		fdHasEvent = PR_TRUE;
-	    }
-	    if (FD_ISSET(filedes[i].fd, &ex)) {
-		if (filedes[i].events & POLLPRI) {
-		    filedes[i].revents |= POLLPRI;
-		}
-		if (filedes[i].events & POLLRDBAND) {
-		    filedes[i].revents |= POLLRDBAND;
-		}
-		fdHasEvent = PR_TRUE;
-	    }
-	    if (fdHasEvent) {
-		rv++;
-            }
-        }
-	PR_ASSERT(rv > 0);
-    } else if (rv == -1 && errno == EBADF) {
-	rv = 0;
-        for (i = 0; i < nfds; i++) {
-	    filedes[i].revents = 0;
-            if (filedes[i].fd < 0) {
-                continue;
-            }
-	    if (fcntl(filedes[i].fd, F_GETFL, 0) == -1) {
-		filedes[i].revents = POLLNVAL;
-		rv++;
-	    }
-        }
-	PR_ASSERT(rv > 0);
-    }
-    PR_ASSERT(-1 != timeout || rv != 0);
-
-    return rv;
-}
-#endif /* _PR_NEED_FAKE_POLL */
--- a/pr/src/md/unix/irix.c
+++ b/pr/src/md/unix/irix.c
@@ -303,20 +303,21 @@ sigchld_handler(int sig)
     /*
      * If an sproc exited abnormally send a SIGKILL signal to all the
      * sprocs in the process to terminate the application
      */
     while ((pid = waitpid(0, &status, WNOHANG)) > 0) {
         if (WIFSIGNALED(status) && ((WTERMSIG(status) == SIGSEGV) ||
             (WTERMSIG(status) == SIGBUS) ||
             (WTERMSIG(status) == SIGABRT) ||
-            (WTERMSIG(status) == SIGILL)))
+            (WTERMSIG(status) == SIGILL))) {
 
-			prctl(PR_SETEXITSIG, SIGKILL);
-			exit(status);
+				prctl(PR_SETEXITSIG, SIGKILL);
+				exit(status);
+			}
     }
 }
 
 static void save_context_and_block(int sig)
 {
 PRThread *me = _PR_MD_CURRENT_THREAD();
 _PRCPU *cpu = _PR_MD_CURRENT_CPU();
 
@@ -432,42 +433,60 @@ void _PR_IRIX_CHILD_PROCESS()
     /*
      * save the new pid
      */
     _pr_primordialCPU->md.id = getpid();
 }
 
 static PRStatus pr_cvar_wait_sem(PRThread *thread, PRIntervalTime timeout)
 {
-    struct timeval tv, *tvp;
-    fd_set rd;
     int rv;
 
-    if(timeout == PR_INTERVAL_NO_TIMEOUT) tvp = NULL;
-    else {
-        tv.tv_sec = PR_IntervalToSeconds(timeout);
-        tv.tv_usec = PR_IntervalToMicroseconds(
-            timeout - PR_SecondsToInterval(tv.tv_sec));
-        tvp = &tv;
-    }
-    FD_ZERO(&rd);
-    FD_SET(thread->md.cvar_pollsemfd, &rd);
+#ifdef _PR_USE_POLL
+	struct pollfd pfd;
+	int msecs;
+
+	if (timeout == PR_INTERVAL_NO_TIMEOUT)
+		msecs = -1;
+	else
+		msecs  = PR_IntervalToMilliseconds(timeout);
+#else
+    struct timeval tv, *tvp;
+    fd_set rd;
+
+	if(timeout == PR_INTERVAL_NO_TIMEOUT)
+		tvp = NULL;
+	else {
+		tv.tv_sec = PR_IntervalToSeconds(timeout);
+		tv.tv_usec = PR_IntervalToMicroseconds(
+		timeout - PR_SecondsToInterval(tv.tv_sec));
+		tvp = &tv;
+	}
+	FD_ZERO(&rd);
+	FD_SET(thread->md.cvar_pollsemfd, &rd);
+#endif
+
     /*
      * call uspsema only if a previous select call on this semaphore
      * did not timeout
      */
     if (!thread->md.cvar_pollsem_select) {
         rv = _PR_WAIT_SEM(thread->md.cvar_pollsem);
 		PR_ASSERT(rv >= 0);
 	} else
         rv = 0;
 again:
     if(!rv) {
-        rv = _MD_SELECT(thread->md.cvar_pollsemfd + 1, &rd,
-            NULL,NULL,tvp);
+#ifdef _PR_USE_POLL
+		pfd.events = POLLIN;
+		pfd.fd = thread->md.cvar_pollsemfd;
+		rv = _MD_POLL(&pfd, 1, msecs);
+#else
+		rv = _MD_SELECT(thread->md.cvar_pollsemfd + 1, &rd, NULL,NULL,tvp);
+#endif
         if ((rv == -1) && (errno == EINTR)) {
 			rv = 0;
 			goto again;
 		}
 		PR_ASSERT(rv >= 0);
 	}
 
     if (rv > 0) {
@@ -554,37 +573,39 @@ PRThreadState state,
 PRUint32 stackSize)
 {
     typedef void (*SprocEntry) (void *, size_t);
     SprocEntry spentry = (SprocEntry)start;
     PRIntn is;
 	PRThread *me = _PR_MD_CURRENT_THREAD();	
 	PRInt32 pid;
 	PRStatus rv;
+    PRStatus creation_status;
 
 	if (!_PR_IS_NATIVE_THREAD(me))
 		_PR_INTSOFF(is);
     thread->md.cvar_pollsem_select = 0;
+    thread->md.creation_status = &creation_status;
     thread->flags |= _PR_GLOBAL_SCOPE;
     pid = sprocsp(
         			spentry,            /* startup func    */
     				PR_SALL,            /* attribute flags     */
     				(void *)thread,     /* thread param     */
     				NULL,               /* stack address    */
     				stackSize);         /* stack size     */
     if (pid > 0) {
 		/*
 		 * Wait for the sproc to signal me after it has initialized
 		 * itself
 		 */
 	    if (!_PR_IS_NATIVE_THREAD(me))
 		    blockproc(me->cpu->md.id);
         else
             blockproc(me->md.id);
-    	if (thread->md.cvar_pollsemfd < 0) {
+    	if (creation_status == PR_FAILURE) {
 			/*
 			 * the sproc failed to create a polled semaphore and exited
 			 */
         	_MD_ATOMIC_INCREMENT(&_pr_md_irix_sprocs_failed);
 			rv = PR_FAILURE;
 		} else {
         	_MD_ATOMIC_INCREMENT(&_pr_md_irix_sprocs_created);
         	_MD_ATOMIC_INCREMENT(&_pr_md_irix_sprocs);
@@ -676,27 +697,31 @@ PRStatus
 		 *
 		 * NOTE: On Irix there is a bug which requires the sproc that
 		 *		 created a polled semaphore to not exit for that semaphore
 		 *		 to be useable by other sprocs.
 		 */
 		thread->md.id = getpid();
 		thread->md.cvar_pollsemfd = -1;
 		if (new_poll_sem(&thread->md,0) == PR_FAILURE) {
-			if (wakeup_parent == PR_TRUE)
+			if (wakeup_parent == PR_TRUE) {
+				*thread->md.creation_status = PR_FAILURE;
 		 		unblockproc(getppid());
-			rv = PR_FAILURE;
+			}
+			return PR_FAILURE;
 		}
 		thread->md.cvar_pollsemfd =
 			_PR_OPEN_POLL_SEM(thread->md.cvar_pollsem);
 		if ((thread->md.cvar_pollsemfd < 0)) {
 			free_poll_sem(&thread->md);
-			if (wakeup_parent == PR_TRUE)
+			if (wakeup_parent == PR_TRUE) {
+				*thread->md.creation_status = PR_FAILURE;
 		 		unblockproc(getppid());
-			rv = PR_FAILURE;
+			}
+			return PR_FAILURE;
 		}
         setblockproccnt(thread->md.id, 0);
 		_MD_SET_SPROC_PID(getpid());	
 #ifndef IRIX5_3
 		/*
 		 * enable user-level processing of sigprocmask(); this is an
 		 * undocumented feature available in Irix 6.2, 6.3, 6.4 and 6.5
 		 */
@@ -739,18 +764,20 @@ PRStatus
 				sigact.sa_flags = SA_RESTART;
 				sigact.sa_mask = ints_off;
 				sigaction(SIGCLD, &sigact, NULL);
 			}
 		}
 		/*
 		 * unblock the parent sproc
 		 */
-		if (wakeup_parent == PR_TRUE)
+		if (wakeup_parent == PR_TRUE) {
+			*thread->md.creation_status = PR_SUCCESS;
 			unblockproc(getppid());
+		}
     }
 	return rv;
 }
 
 PR_EXTERN(void ) _MD_exit(PRIntn status)
 {
 	/*
 	 * Cause SIGKILL to be sent to other sprocs, if any, in the application
@@ -764,17 +791,19 @@ void
 {
     extern int _pr_md_pipefd[2];
 
     _MD_unix_init_running_cpu(cpu);
     cpu->md.id = getpid();
 	_MD_SET_SPROC_PID(getpid());	
 	if (_pr_md_pipefd[0] >= 0) {
     	_PR_IOQ_MAX_OSFD(cpu) = _pr_md_pipefd[0];
+#ifndef _PR_USE_POLL
     	FD_SET(_pr_md_pipefd[0], &_PR_FD_READ_SET(cpu));
+#endif
 	}
 }
 
 void
 _MD_ExitThread(PRThread *thread)
 {
     if (thread->flags & _PR_GLOBAL_SCOPE) {
         _MD_ATOMIC_DECREMENT(&_pr_md_irix_sprocs);
--- a/pr/src/md/unix/linux.c
+++ b/pr/src/md/unix/linux.c
@@ -91,140 +91,8 @@ PRStatus
     PRThreadScope scope,
     PRThreadState state,
     PRUint32 stackSize)
 {
     PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for OSF1.");
 	return PR_FAILURE;
 }
 #endif /* ! _PR_PTHREADS */
-
-#if defined(_PR_NEED_FAKE_POLL)
-
-#include <fcntl.h>
-
-int poll(struct pollfd *filedes, unsigned long nfds, int timeout)
-{
-    int i;
-    int rv;
-    int maxfd;
-    fd_set rd, wr, ex;
-    struct timeval tv, *tvp;
-
-    if (timeout < 0 && timeout != -1) {
-	errno = EINVAL;
-	return -1;
-    }
-
-    if (timeout == -1) {
-        tvp = NULL;
-    } else {
-	tv.tv_sec = timeout / 1000;
-	tv.tv_usec = (timeout % 1000) * 1000;
-        tvp = &tv;
-    }
-
-    maxfd = -1;
-    FD_ZERO(&rd);
-    FD_ZERO(&wr);
-    FD_ZERO(&ex);
-
-    for (i = 0; i < nfds; i++) {
-	int osfd = filedes[i].fd;
-	int events = filedes[i].events;
-	PRBool fdHasEvent = PR_FALSE;
-
-	if (osfd < 0) {
-            continue;  /* Skip this osfd. */
-	}
-
-	/*
-	 * Map the native poll flags to nspr poll flags.
-	 *     POLLIN, POLLRDNORM  ===> PR_POLL_READ
-	 *     POLLOUT, POLLWRNORM ===> PR_POLL_WRITE
-	 *     POLLPRI, POLLRDBAND ===> PR_POLL_EXCEPTION
-	 *     POLLNORM, POLLWRBAND (and POLLMSG on some platforms)
-	 *     are ignored.
-	 *
-	 * The output events POLLERR and POLLHUP are never turned on.
-	 * POLLNVAL may be turned on.
-	 */
-
-	if (events & (POLLIN | POLLRDNORM)) {
-	    FD_SET(osfd, &rd);
-	    fdHasEvent = PR_TRUE;
-	}
-	if (events & (POLLOUT | POLLWRNORM)) {
-	    FD_SET(osfd, &wr);
-	    fdHasEvent = PR_TRUE;
-	}
-	if (events & (POLLPRI | POLLRDBAND)) {
-	    FD_SET(osfd, &ex);
-	    fdHasEvent = PR_TRUE;
-	}
-	if (fdHasEvent && osfd > maxfd) {
-	    maxfd = osfd;
-	}
-    }
-
-    rv = select(maxfd + 1, &rd, &wr, &ex, tvp);
-
-    /* Compute poll results */
-    if (rv > 0) {
-	rv = 0;
-        for (i = 0; i < nfds; i++) {
-	    PRBool fdHasEvent = PR_FALSE;
-
-	    filedes[i].revents = 0;
-            if (filedes[i].fd < 0) {
-                continue;
-            }
-	    if (FD_ISSET(filedes[i].fd, &rd)) {
-		if (filedes[i].events & POLLIN) {
-		    filedes[i].revents |= POLLIN;
-		}
-		if (filedes[i].events & POLLRDNORM) {
-		    filedes[i].revents |= POLLRDNORM;
-		}
-		fdHasEvent = PR_TRUE;
-	    }
-	    if (FD_ISSET(filedes[i].fd, &wr)) {
-		if (filedes[i].events & POLLOUT) {
-		    filedes[i].revents |= POLLOUT;
-		}
-		if (filedes[i].events & POLLWRNORM) {
-		    filedes[i].revents |= POLLWRNORM;
-		}
-		fdHasEvent = PR_TRUE;
-	    }
-	    if (FD_ISSET(filedes[i].fd, &ex)) {
-		if (filedes[i].events & POLLPRI) {
-		    filedes[i].revents |= POLLPRI;
-		}
-		if (filedes[i].events & POLLRDBAND) {
-		    filedes[i].revents |= POLLRDBAND;
-		}
-		fdHasEvent = PR_TRUE;
-	    }
-	    if (fdHasEvent) {
-		rv++;
-            }
-        }
-	PR_ASSERT(rv > 0);
-    } else if (rv == -1 && errno == EBADF) {
-	rv = 0;
-        for (i = 0; i < nfds; i++) {
-	    filedes[i].revents = 0;
-            if (filedes[i].fd < 0) {
-                continue;
-            }
-	    if (fcntl(filedes[i].fd, F_GETFL, 0) == -1) {
-		filedes[i].revents = POLLNVAL;
-		rv++;
-	    }
-        }
-	PR_ASSERT(rv > 0);
-    }
-    PR_ASSERT(-1 != timeout || rv != 0);
-
-    return rv;
-}
-#endif /* _PR_NEED_FAKE_POLL */
--- a/pr/src/md/unix/os_AIX.s
+++ b/pr/src/md/unix/os_AIX.s
@@ -10,16 +10,17 @@
 # for the specific language governing rights and limitations under the
 # NPL.
 # 
 # The Initial Developer of this code under the NPL is Netscape
 # Communications Corporation.  Portions created by Netscape are
 # Copyright (C) 1998 Netscape Communications Corporation.  All Rights
 # Reserved.
 #
+
 .set r0,0; .set SP,1; .set RTOC,2; .set r3,3; .set r4,4
 .set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
 .set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
 .set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
 .set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
 .set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
 .set r30,30; .set r31,31
 
--- a/pr/src/md/unix/os_BSD_386_2.s
+++ b/pr/src/md/unix/os_BSD_386_2.s
@@ -10,16 +10,17 @@
  * for the specific language governing rights and limitations under the
  * NPL.
  * 
  * The Initial Developer of this code under the NPL is Netscape
  * Communications Corporation.  Portions created by Netscape are
  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  * Reserved.
  */
+
 /*
  * os_BSD_386_2.s
  * We need to define our own setjmp/longjmp on BSDI 2.x because libc's
  * implementation does some sanity checking that defeats user level threads.
  * This should no longer be necessary in BSDI 3.0.
  */
 
 .globl _setjmp
--- a/pr/src/md/unix/os_ReliantUNIX.s
+++ b/pr/src/md/unix/os_ReliantUNIX.s
@@ -10,16 +10,17 @@
  * for the specific language governing rights and limitations under the
  * NPL.
  * 
  * The Initial Developer of this code under the NPL is Netscape
  * Communications Corporation.  Portions created by Netscape are
  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  * Reserved.
  */
+
 /* We want position independent code */
 #define PIC
 
 #include <sys/asm.h>
 #include <sys/regdef.h>
 #include <sys/syscall.h>
 
 	.file 1 "os_ReliantUNIX.s"
--- a/pr/src/md/unix/os_SunOS_ultrasparc.s
+++ b/pr/src/md/unix/os_SunOS_ultrasparc.s
@@ -1,9 +1,9 @@
-! -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- 
+! -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 !
 ! The contents of this file are subject to the Netscape Public License
 ! Version 1.0 (the "NPL"); you may not use this file except in
 ! compliance with the NPL.  You may obtain a copy of the NPL at
 ! http://www.mozilla.org/NPL/
 ! 
 ! Software distributed under the NPL is distributed on an "AS IS" basis,
 ! WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
--- a/pr/src/md/unix/unix.c
+++ b/pr/src/md/unix/unix.c
@@ -23,30 +23,34 @@
 #include <memory.h>
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/time.h>
 #include <sys/ioctl.h>
 #include <sys/mman.h>
 
+#ifdef _PR_POLL_AVAILABLE
+#include <poll.h>
+#endif
+
 /* To get FIONREAD */
 #if defined(NCR) || defined(UNIXWARE) || defined(NEC) || defined(SNI) \
         || defined(SONY)
 #include <sys/filio.h>
 #endif
 
 /*
  * Make sure _PRSockLen_t is 32-bit, because we will cast a PRUint32* or
  * PRInt32* pointer to a _PRSockLen_t* pointer.
  */
 #if defined(IRIX) || defined(HPUX) || defined(OSF1) || defined(SOLARIS) \
     || defined(AIX4_1) || defined(LINUX) || defined(SONY) \
     || defined(BSDI) || defined(SCO) || defined(NEC) || defined(SNI) \
-    || defined(SUNOS4)
+    || defined(SUNOS4) || defined(NCR)
 #define _PRSockLen_t int
 #elif (defined(AIX) && !defined(AIX4_1)) || defined(FREEBSD) \
     || defined(UNIXWARE)
 #define _PRSockLen_t size_t
 #else
 #error "Cannot determine architecture"
 #endif
 
@@ -84,17 +88,17 @@ static sigset_t empty_set;
 
 #ifndef PROT_NONE
 #define PROT_NONE 0
 #endif
 
 /*
  * _nspr_noclock - if set clock interrupts are disabled
  */
-int _nspr_noclock = 0;
+int _nspr_noclock = 1;
 
 #ifdef IRIX
 extern PRInt32 _nspr_terminate_on_error;
 #endif
 
 /*
  * There is an assertion in this code that NSPR's definition of PRIOVec
  * is bit compatible with UNIX' definition of a struct iovec. This is
@@ -375,34 +379,50 @@ int rv, err;
 	}
 	return rv;
 }
 
 PRInt32 _MD_read(PRFileDesc *fd, void *buf, PRInt32 amount)
 {
 PRThread *me = _PR_MD_CURRENT_THREAD();
 PRInt32 rv, err;
+#ifndef _PR_USE_POLL
 fd_set rd;
+#else
+struct pollfd pfd;
+#endif /* _PR_USE_POLL */
 PRInt32 osfd = fd->secret->md.osfd;
 
+#ifndef _PR_USE_POLL
 	FD_ZERO(&rd);
 	FD_SET(osfd, &rd);
+#else
+	pfd.fd = osfd;
+	pfd.events = POLLIN;
+#endif /* _PR_USE_POLL */
 	while ((rv = read(osfd,buf,amount)) == -1) {
 		err = _MD_ERRNO();
 		if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
 			if (fd->secret->nonblocking) {
 				break;
 			}
 			if (!_PR_IS_NATIVE_THREAD(me)) {
 				_PR_WaitForFD(osfd, PR_POLL_READ, PR_INTERVAL_NO_TIMEOUT);
 			} else {
+#ifndef _PR_USE_POLL
 				while ((rv = _MD_SELECT(osfd + 1, &rd, NULL, NULL, NULL))
 						== -1 && (err = _MD_ERRNO()) == EINTR) {
 					/* retry _MD_SELECT() if it is interrupted */
 				}
+#else /* _PR_USE_POLL */
+				while ((rv = _MD_POLL(&pfd, 1, -1))
+						== -1 && (err = _MD_ERRNO()) == EINTR) {
+					/* retry _MD_POLL() if it is interrupted */
+				}
+#endif /* _PR_USE_POLL */
 				if (rv == -1) {
 					break;
 				}
 			}
 			if (_PR_PENDING_INTERRUPT(me))
 				break;
 		} else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
 			continue;
@@ -420,34 +440,50 @@ PRInt32 osfd = fd->secret->md.osfd;
 	}
 	return(rv);
 }
 
 PRInt32 _MD_write(PRFileDesc *fd, const void *buf, PRInt32 amount)
 {
 PRThread *me = _PR_MD_CURRENT_THREAD();
 PRInt32 rv, err;
+#ifndef _PR_USE_POLL
 fd_set wd;
+#else
+struct pollfd pfd;
+#endif /* _PR_USE_POLL */
 PRInt32 osfd = fd->secret->md.osfd;
 
+#ifndef _PR_USE_POLL
 	FD_ZERO(&wd);
 	FD_SET(osfd, &wd);
+#else
+	pfd.fd = osfd;
+	pfd.events = POLLOUT;
+#endif /* _PR_USE_POLL */
 	while ((rv = write(osfd,buf,amount)) == -1) {
 		err = _MD_ERRNO();
 		if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
 			if (fd->secret->nonblocking) {
 				break;
 			}
 			if (!_PR_IS_NATIVE_THREAD(me)) {
 				_PR_WaitForFD(osfd, PR_POLL_WRITE, PR_INTERVAL_NO_TIMEOUT);
 			} else {
+#ifndef _PR_USE_POLL
 				while ((rv = _MD_SELECT(osfd + 1, NULL, &wd, NULL, NULL))
 						== -1 && (err = _MD_ERRNO()) == EINTR) {
 					/* retry _MD_SELECT() if it is interrupted */
 				}
+#else /* _PR_USE_POLL */
+				while ((rv = _MD_POLL(&pfd, 1, -1))
+						== -1 && (err = _MD_ERRNO()) == EINTR) {
+					/* retry _MD_POLL() if it is interrupted */
+				}
+#endif /* _PR_USE_POLL */
 				if (rv == -1) {
 					break;
 				}
 			}
 			if (_PR_PENDING_INTERRUPT(me))
 				break;
 		} else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
 			continue;
@@ -565,21 +601,28 @@ PRInt64 _MD_socketavailable64(PRFileDesc
     LL_I2L(result, _MD_socketavailable(fd));
     return result;
 }  /* _MD_socketavailable64 */
 
 #define READ_FD		1
 #define WRITE_FD	2
 
 /*
+ * socket_io_wait --
+ *
  * wait for socket i/o, periodically checking for interrupt
+ *
+ * The first implementation uses select(), for platforms without
+ * poll().  The second (preferred) implementation uses poll().
  */
 
+#ifndef _PR_USE_POLL
+
 static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
-										PRIntervalTime timeout)
+    PRIntervalTime timeout)
 {
 	PRInt32 rv = -1;
 	struct timeval tv, *tvp;
 	PRThread *me = _PR_MD_CURRENT_THREAD();
 	PRIntervalTime epoch, now, elapsed, remaining;
 	PRInt32 syserror;
 	fd_set rd_wr;
 
@@ -687,16 +730,124 @@ static PRInt32 socket_io_wait(PRInt32 os
 					}
 				}
 			} while (rv == 0 || (rv == -1 && syserror == EINTR));
 			break;
 	}
 	return(rv);
 }
 
+#else /* _PR_USE_POLL */
+
+static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
+    PRIntervalTime timeout)
+{
+	PRInt32 rv = -1;
+	int msecs;
+	PRThread *me = _PR_MD_CURRENT_THREAD();
+	PRIntervalTime epoch, now, elapsed, remaining;
+	PRInt32 syserror;
+	struct pollfd pfd;
+
+	switch (timeout) {
+		case PR_INTERVAL_NO_WAIT:
+			PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+			break;
+		case PR_INTERVAL_NO_TIMEOUT:
+			/*
+			 * This is a special case of the 'default' case below.
+			 * Please see the comments there.
+			 */
+			msecs = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000;
+			pfd.fd = osfd;
+			if (fd_type == READ_FD) {
+				pfd.events = POLLIN;
+			} else {
+				pfd.events = POLLOUT;
+			}
+			do {
+				rv = _MD_POLL(&pfd, 1, msecs);
+				if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
+					_PR_MD_MAP_POLL_ERROR(syserror);
+					break;
+				}
+				if (_PR_PENDING_INTERRUPT(me)) {
+					me->flags &= ~_PR_INTERRUPT;
+					PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+					rv = -1;
+					break;
+				}
+			} while (rv == 0 || (rv == -1 && syserror == EINTR));
+			break;
+		default:
+			now = epoch = PR_IntervalNow();
+			remaining = timeout;
+			pfd.fd = osfd;
+			if (fd_type == READ_FD) {
+				pfd.events = POLLIN;
+			} else {
+				pfd.events = POLLOUT;
+			}
+			do {
+				/*
+				 * We block in _MD_POLL for at most
+				 * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds,
+				 * so that there is an upper limit on the delay
+				 * before the interrupt bit is checked.
+				 */
+				msecs = PR_IntervalToMilliseconds(remaining);
+				if (msecs > _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000) {
+					msecs = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000;
+				}
+				rv = _MD_POLL(&pfd, 1, msecs);
+				/*
+				 * we don't consider EINTR a real error
+				 */
+				if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
+					_PR_MD_MAP_POLL_ERROR(syserror);
+					break;
+				}
+				if (_PR_PENDING_INTERRUPT(me)) {
+					me->flags &= ~_PR_INTERRUPT;
+					PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+					rv = -1;
+					break;
+				}
+				/*
+				 * We loop again if _MD_POLL timed out or got interrupted
+				 * by a signal, and the timeout deadline has not passed yet.
+				 */
+				if (rv == 0 || (rv == -1 && syserror == EINTR)) {
+					/*
+					 * If _MD_POLL timed out, we know how much time
+					 * we spent in blocking, so we can avoid a
+					 * PR_IntervalNow() call.
+					 */
+					if (rv == 0) {
+						now += PR_MillisecondsToInterval(msecs);
+					} else {
+						now = PR_IntervalNow();
+					}
+					elapsed = (PRIntervalTime) (now - epoch);
+					if (elapsed >= timeout) {
+						PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+						rv = -1;
+						break;
+					} else {
+						remaining = timeout - elapsed;
+					}
+				}
+			} while (rv == 0 || (rv == -1 && syserror == EINTR));
+			break;
+	}
+	return(rv);
+}
+
+#endif /* _PR_USE_POLL */
+
 PRInt32 _MD_recv(PRFileDesc *fd, void *buf, PRInt32 amount,
 								PRInt32 flags, PRIntervalTime timeout)
 {
 	PRInt32 osfd = fd->secret->md.osfd;
 	PRInt32 rv, err;
 	PRThread *me = _PR_MD_CURRENT_THREAD();
 
 /*
@@ -789,24 +940,27 @@ PRInt32 _MD_recvfrom(PRFileDesc *fd, voi
 		} else {
 			break;
 		}
 	}
 	if (rv < 0) {
 		_PR_MD_MAP_RECVFROM_ERROR(err);
 	}
 done:
-#ifdef AIX
+#ifdef _PR_HAVE_SOCKADDR_LEN
     if (rv != -1) {
         /* mask off the first byte of struct sockaddr (the length field) */
         if (addr) {
-            addr->inet.family &= 0x00ff;
+            *((unsigned char *) addr) = 0;
+#ifdef IS_LITTLE_ENDIAN
+            addr->raw.family = ntohs(addr->raw.family);
+#endif
         }
     }
-#endif
+#endif /* _PR_HAVE_SOCKADDR_LEN */
 	return(rv);
 }
 
 PRInt32 _MD_send(PRFileDesc *fd, const void *buf, PRInt32 amount,
 							PRInt32 flags, PRIntervalTime timeout)
 {
 	PRInt32 osfd = fd->secret->md.osfd;
 	PRInt32 rv, err;
@@ -1038,24 +1192,27 @@ PRInt32 _MD_accept(PRFileDesc *fd, PRNet
 		} else {
 			break;
 		}
 	}
 	if (rv < 0) {
 		_PR_MD_MAP_ACCEPT_ERROR(err);
 	}
 done:
-#ifdef AIX
+#ifdef _PR_HAVE_SOCKADDR_LEN
     if (rv != -1) {
         /* mask off the first byte of struct sockaddr (the length field) */
         if (addr) {
-            addr->inet.family &= 0x00ff;
+            *((unsigned char *) addr) = 0;
+#ifdef IS_LITTLE_ENDIAN
+            addr->raw.family = ntohs(addr->raw.family);
+#endif
         }
     }
-#endif
+#endif /* _PR_HAVE_SOCKADDR_LEN */
 	return(rv);
 }
 
 extern int _connect (int s, const struct sockaddr *name, int namelen);
 PRInt32 _MD_connect(
     PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
 {
     PRInt32 rv, err;
@@ -1193,46 +1350,52 @@ PRInt32 _MD_socketpair(int af, int type,
 
 PRStatus _MD_getsockname(PRFileDesc *fd, PRNetAddr *addr,
 												PRUint32 *addrlen)
 {
     PRInt32 rv, err;
 
     rv = getsockname(fd->secret->md.osfd,
             (struct sockaddr *) addr, (_PRSockLen_t *)addrlen);
-#ifdef AIX
+#ifdef _PR_HAVE_SOCKADDR_LEN
     if (rv == 0) {
         /* mask off the first byte of struct sockaddr (the length field) */
         if (addr) {
-            addr->inet.family &= 0x00ff;
+            *((unsigned char *) addr) = 0;
+#ifdef IS_LITTLE_ENDIAN
+            addr->raw.family = ntohs(addr->raw.family);
+#endif
         }
     }
-#endif
+#endif /* _PR_HAVE_SOCKADDR_LEN */
     if (rv < 0) {
         err = _MD_ERRNO();
         _PR_MD_MAP_GETSOCKNAME_ERROR(err);
     }
     return rv==0?PR_SUCCESS:PR_FAILURE;
 }
 
 PRStatus _MD_getpeername(PRFileDesc *fd, PRNetAddr *addr,
 										PRUint32 *addrlen)
 {
     PRInt32 rv, err;
 
     rv = getpeername(fd->secret->md.osfd,
             (struct sockaddr *) addr, (_PRSockLen_t *)addrlen);
-#ifdef AIX
+#ifdef _PR_HAVE_SOCKADDR_LEN
     if (rv == 0) {
         /* mask off the first byte of struct sockaddr (the length field) */
         if (addr) {
-            addr->inet.family &= 0x00ff;
+            *((unsigned char *) addr) = 0;
+#ifdef IS_LITTLE_ENDIAN
+            addr->raw.family = ntohs(addr->raw.family);
+#endif
         }
     }
-#endif
+#endif /* _PR_HAVE_SOCKADDR_LEN */
     if (rv < 0) {
         err = _MD_ERRNO();
         _PR_MD_MAP_GETPEERNAME_ERROR(err);
     }
     return rv==0?PR_SUCCESS:PR_FAILURE;
 }
 
 PRStatus _MD_getsockopt(PRFileDesc *fd, PRInt32 level,
@@ -1267,17 +1430,26 @@ PR_IMPLEMENT(PRInt32) _MD_pr_poll(PRPoll
     PRPollDesc *pd, *epd;
     PRPollQueue pq;
     PRInt32 n, err, pdcnt;
     PRIntn is;
 	_PRUnixPollDesc *unixpds, *unixpd;
 	_PRCPU *io_cpu;
     PRThread *me = _PR_MD_CURRENT_THREAD();
 
+    if (0 == npds) {
+        PR_Sleep(timeout);
+        return 0;
+    }
+
     if (_PR_IS_NATIVE_THREAD(me)) {
+#ifndef _PR_USE_POLL
+        /*
+         * On platforms that don't have poll(), we call select().
+         */
 		fd_set rd, wt, ex;
 		struct timeval tv, *tvp = NULL;
 		int maxfd = -1;
 		/*
 		 * For restarting _MD_SELECT() if it is interrupted by a signal.
 		 * We use these variables to figure out how much time has elapsed
 		 * and how much of the timeout still remains.
 		 */
@@ -1393,16 +1565,115 @@ retry:
 				PR_ASSERT(n > 0);
 			} else {
 				PR_ASSERT(err != EINTR);  /* should have been handled above */
 				_PR_MD_MAP_SELECT_ERROR(err);
 			}
 		}
 
 		return n;
+#else /* _PR_USE_POLL */
+        /*
+         * For restarting _MD_POLL() if it is interrupted by a signal.
+         * We use these variables to figure out how much time has elapsed
+         * and how much of the timeout still remains.
+         */
+        PRIntervalTime start, elapsed, remaining;
+        int index, msecs;
+        struct pollfd *syspoll;
+
+        syspoll = (struct pollfd *) PR_MALLOC(npds * sizeof(struct pollfd));
+        if (NULL == syspoll) {
+            PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+            return -1;
+        }
+        for (index = 0; index < npds; index++) {
+            PRFileDesc *bottom = pds[index].fd;
+
+            if (NULL == bottom) {
+                /* make poll() ignore this entry */
+                syspoll[index].fd = -1;
+                continue;
+            }
+
+            while (bottom->lower != NULL) {
+                bottom = bottom->lower;
+            }
+            syspoll[index].fd = bottom->secret->md.osfd;
+
+            syspoll[index].events = 0;
+            if (pds[index].in_flags & PR_POLL_READ) {
+                syspoll[index].events |= POLLIN;
+            }
+            if (pds[index].in_flags & PR_POLL_WRITE) {
+                syspoll[index].events |= POLLOUT;
+            }
+            if (pds[index].in_flags & PR_POLL_EXCEPT) {
+                syspoll[index].events |= POLLPRI;
+            }
+            pds[index].out_flags = 0;  /* init the result */
+        }
+        if (timeout == PR_INTERVAL_NO_TIMEOUT) {
+            msecs = -1;
+        } else {
+            msecs = PR_IntervalToMilliseconds(timeout);
+            start = PR_IntervalNow();
+        }
+		
+retry:
+        n = _MD_POLL(syspoll, npds, msecs);
+        if (n == -1) {
+            err = _MD_ERRNO();
+            if (err == EINTR) {
+                if (timeout == PR_INTERVAL_NO_TIMEOUT) {
+                    goto retry;
+                } else if (timeout == PR_INTERVAL_NO_WAIT) {
+                    n = 0;  /* don't retry, just time out */
+                } else {
+                    elapsed = (PRIntervalTime) (PR_IntervalNow() - start);
+                    if (elapsed > timeout) {
+                        n = 0;  /* timed out */
+                    } else {
+                        remaining = timeout - elapsed;
+                        msecs = PR_IntervalToMilliseconds(remaining);
+                        goto retry;
+                    }
+                }
+            } else {
+                _PR_MD_MAP_POLL_ERROR(err);
+            }
+        } else if (n > 0) {
+            for (index = 0; index < npds; index++) {
+            	if (NULL == pds[index].fd) {
+                    continue;
+                }
+                PR_ASSERT(0 == pds[index].out_flags);
+                if (0 != syspoll[index].revents) {
+                    if (syspoll[index].revents & POLLIN)  {
+                        pds[index].out_flags |= PR_POLL_READ;
+                    }
+                    if (syspoll[index].revents & POLLOUT) {
+                        pds[index].out_flags |= PR_POLL_WRITE;
+                    }
+                    if (syspoll[index].revents & POLLPRI) {
+                        pds[index].out_flags |= PR_POLL_EXCEPT;
+                    }
+                    if (syspoll[index].revents & POLLERR) {
+                        pds[index].out_flags |= PR_POLL_ERR;
+                    }
+                    if (syspoll[index].revents & POLLNVAL) {
+                        pds[index].out_flags |= PR_POLL_NVAL;
+                    }
+                }
+            }
+        }
+
+        PR_DELETE(syspoll);
+        return n;
+#endif /* _PR_USE_POLL */
     }
 
 	/*
 	 * XXX
 	 *		PRPollDesc has a PRFileDesc field, fd, while the IOQ
 	 *		is a list of PRPollQueue structures, each of which contains
 	 *		a _PRUnixPollDesc. A _PRUnixPollDesc struct contains
 	 *		the OS file descriptor, osfd, and not a PRFileDesc.
@@ -1450,34 +1721,37 @@ retry:
 
 		PR_ASSERT(osfd >= 0 || in_flags == 0);
 
 		unixpd->osfd = osfd;
 		unixpd->in_flags = pd->in_flags;
 		unixpd++;
 		pdcnt++;
 
+#ifndef _PR_USE_POLL
 		if (in_flags & PR_POLL_READ)  {
 			FD_SET(osfd, &_PR_FD_READ_SET(me->cpu));
 			_PR_FD_READ_CNT(me->cpu)[osfd]++;
 		}
 		if (in_flags & PR_POLL_WRITE) {
 			FD_SET(osfd, &_PR_FD_WRITE_SET(me->cpu));
 			(_PR_FD_WRITE_CNT(me->cpu))[osfd]++;
 		}
 		if (in_flags & PR_POLL_EXCEPT) {
 			FD_SET(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
 			(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd]++;
 		}
+#endif	/* _PR_USE_POLL */
 		if (osfd > _PR_IOQ_MAX_OSFD(me->cpu))
 			_PR_IOQ_MAX_OSFD(me->cpu) = osfd;
 	}
 	if (timeout < _PR_IOQ_TIMEOUT(me->cpu))
 		_PR_IOQ_TIMEOUT(me->cpu) = timeout;
 
+	_PR_IOQ_OSFD_CNT(me->cpu) += pdcnt;
 
 	pq.pds = unixpds;
 	pq.npds = pdcnt;
 
     pq.thr = me;
 	io_cpu = me->cpu;
     pq.on_ioq = PR_TRUE;
     pq.timeout = timeout;
@@ -1536,29 +1810,33 @@ retry:
             	if ((NULL == bottom) || (in_flags == 0)) {
 					continue;
 				}
 				while (bottom->lower != NULL) {
 					bottom = bottom->lower;
 				}
 				osfd = bottom->secret->md.osfd;
 				PR_ASSERT(osfd >= 0 || in_flags == 0);
+#ifndef _PR_USE_POLL
 				if (in_flags & PR_POLL_READ)  {
 					if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0)
 						FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));
 				}
 				if (in_flags & PR_POLL_WRITE) {
 					if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0)
 							FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));
 				}
 				if (in_flags & PR_POLL_EXCEPT) {
 					if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0)
 							FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
 				}
+#endif
 			}
+			_PR_IOQ_OSFD_CNT(me->cpu) -= pdcnt;
+			PR_ASSERT(_PR_IOQ_OSFD_CNT(me->cpu) >= 0);
 		}
     	_PR_MD_IOQ_UNLOCK();
     }
 	_PR_INTSON(is);
     if (_PR_PENDING_INTERRUPT(me)) {
 		me->flags &= ~_PR_INTERRUPT;
 		PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
        	return -1;
@@ -1632,28 +1910,30 @@ static void FindBadFDs(void)
 	     * because this I/O request is being removed from the
 	     * ioq
 	     */
 			pds = pq->pds;
 			for (; pds < epds; pds++) {
 				PRInt32 osfd = pds->osfd;
 				PRInt16 in_flags = pds->in_flags;
 				PR_ASSERT(osfd >= 0 || in_flags == 0);
+#ifndef _PR_USE_POLL
 				if (in_flags & PR_POLL_READ) {
 					if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0)
 						FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));
 				}
 				if (in_flags & PR_POLL_WRITE) {
 					if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0)
 						FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));
 				}
 				if (in_flags & PR_POLL_EXCEPT) {
 					if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0)
 						FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
 				}
+#endif	/* !_PR_USE_POLL	*/
 			}
 
 			_PR_THREAD_LOCK(pq->thr);
 			if (pq->thr->flags & (_PR_ON_PAUSEQ|_PR_ON_SLEEPQ)) {
 				_PRCPU *cpu = pq->thr->cpu;
 				_PR_SLEEPQ_LOCK(pq->thr->cpu);
 				_PR_DEL_SLEEPQ(pq->thr, PR_TRUE);
 				_PR_SLEEPQ_UNLOCK(pq->thr->cpu);
@@ -1695,16 +1975,17 @@ static void FindBadFDs(void)
 void _MD_PauseCPU(PRIntervalTime ticks)
 {
 	PRThread *me = _MD_CURRENT_THREAD();
 #ifdef _PR_USE_POLL
 	int timeout;
 	struct pollfd *pollfds;    /* an array of pollfd structures */
 	struct pollfd *pollfdPtr;    /* a pointer that steps through the array */
 	unsigned long npollfds;     /* number of pollfd structures in array */
+	unsigned long pollfds_size;
 	int nfd;                    /* to hold the return value of poll() */
 #else
 	struct timeval timeout, *tvp;
 	fd_set r, w, e;
 	fd_set *rp, *wp, *ep;
 	PRInt32 max_osfd, nfd;
 #endif  /* _PR_USE_POLL */
 	PRInt32 rv;
@@ -1718,31 +1999,41 @@ extern sigset_t ints_off;
 	PR_ASSERT(_PR_MD_GET_INTSOFF() != 0);
 
 	_PR_MD_IOQ_LOCK();
 
 #ifdef _PR_USE_POLL
 	/* Build up the pollfd structure array to wait on */
 
 	/* Find out how many pollfd structures are needed */
-	npollfds = 0;
-	for (q = _PR_IOQ(me->cpu).next; q != &_PR_IOQ(me->cpu); q = q->next) {
-		PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
-
-		npollfds += pq->npds;
-	}
+	npollfds = _PR_IOQ_OSFD_CNT(me->cpu);
+	PR_ASSERT(npollfds >= 0);
+
 	/*
      * We use a pipe to wake up a native thread.  An fd is needed
      * for the pipe and we poll it for reading.
      */
 	if (_PR_IS_NATIVE_THREAD_SUPPORTED())
 		npollfds++;
 
-	pollfds = (struct pollfd *) PR_MALLOC(npollfds * sizeof(struct pollfd));
-	pollfdPtr = pollfds;
+	/*
+	 * if the cpu's pollfd array is not big enough, release it and allocate a new one
+	 */
+	if (npollfds > _PR_IOQ_POLLFDS_SIZE(me->cpu)) {
+		if (_PR_IOQ_POLLFDS(me->cpu) != NULL)
+			PR_DELETE(pollfds);
+		pollfds_size =  PR_MAX(_PR_IOQ_MIN_POLLFDS_SIZE(me->cpu), npollfds);
+		pollfds = (struct pollfd *) PR_MALLOC(pollfds_size * sizeof(struct pollfd));
+		_PR_IOQ_POLLFDS(me->cpu) = pollfds;
+		_PR_IOQ_POLLFDS_SIZE(me->cpu) = pollfds_size;
+		pollfdPtr = pollfds;
+	} else {
+		pollfds = _PR_IOQ_POLLFDS(me->cpu);
+		pollfdPtr = pollfds;
+	}
 
 	/*
      * If we need to poll the pipe for waking up a native thread,
      * the pipe's fd is the first element in the pollfds array.
      */
 	if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {
 		pollfdPtr->fd = _pr_md_pipefd[0];
 		pollfdPtr->events = PR_POLL_READ;
@@ -1764,16 +2055,17 @@ extern sigset_t ints_off;
 	     * beyond the end of the pollfds array
 	     */
 			PR_ASSERT(pollfdPtr < pollfds + npollfds);
 			pollfdPtr->fd = pds->osfd;
 			/* direct copy of poll flags */
 			pollfdPtr->events = pds->in_flags;
 		}
 	}
+	_PR_IOQ_TIMEOUT(me->cpu) = min_timeout;
 #else
 	/*
      * assigment of fd_sets
      */
 	r = _PR_FD_READ_SET(me->cpu);
 	w = _PR_FD_WRITE_SET(me->cpu);
 	e = _PR_FD_EXCEPTION_SET(me->cpu);
 
@@ -1892,46 +2184,41 @@ extern sigset_t ints_off;
 		for (q = _PR_IOQ(me->cpu).next; q != &_PR_IOQ(me->cpu); q = q->next) {
 			PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
 			PRBool notify = PR_FALSE;
 			_PRUnixPollDesc *pds = pq->pds;
 			_PRUnixPollDesc *epds = pds + pq->npds;
 
 			for (; pds < epds; pds++, pollfdPtr++) {
 				/*
-		 * Assert that the pollfdPtr pointer does not go beyond
-		 * the end of the pollfds array.
-		 */
+		 		 * Assert that the pollfdPtr pointer does not go beyond
+		 		 * the end of the pollfds array.
+		 		 */
 				PR_ASSERT(pollfdPtr < pollfds + npollfds);
 				/*
-		 * Assert that the fd's in the pollfds array (stepped
-		 * through by pollfdPtr) are in the same order as
-		 * the fd's in _PR_IOQ() (stepped through by q and pds).
-		 * This is how the pollfds array was created earlier.
-		 */
+				 * Assert that the fd's in the pollfds array (stepped
+				 * through by pollfdPtr) are in the same order as
+				 * the fd's in _PR_IOQ() (stepped through by q and pds).
+				 * This is how the pollfds array was created earlier.
+				 */
 				PR_ASSERT(pollfdPtr->fd == pds->osfd);
 				pds->out_flags = pollfdPtr->revents;
 				/* Negative fd's are ignored by poll() */
 				if (pds->osfd >= 0 && pds->out_flags) {
 					notify = PR_TRUE;
 				}
 			}
 			if (notify) {
 				PRIntn pri;
 				PRThread *thred;
 
 				PR_REMOVE_LINK(&pq->links);
 				pq->on_ioq = PR_FALSE;
 
-				/*
-				 * Because this thread can run on a different cpu right
-				 * after being added to the run queue, do not dereference
-				 * pq
-				 */
-				 thred = pq->thr;
+				thred = pq->thr;
                 _PR_THREAD_LOCK(thred);
 				if (pq->thr->flags & (_PR_ON_PAUSEQ|_PR_ON_SLEEPQ)) {
 					_PRCPU *cpu = pq->thr->cpu;
 					_PR_SLEEPQ_LOCK(pq->thr->cpu);
 					_PR_DEL_SLEEPQ(pq->thr, PR_TRUE);
 					_PR_SLEEPQ_UNLOCK(pq->thr->cpu);
 
 					pri = pq->thr->priority;
@@ -1939,24 +2226,24 @@ extern sigset_t ints_off;
 
 					_PR_RUNQ_LOCK(cpu);
 					_PR_ADD_RUNQ(pq->thr, cpu, pri);
 					_PR_RUNQ_UNLOCK(cpu);
 					if (_pr_md_idle_cpus > 1)
 						_PR_MD_WAKEUP_WAITER(thred);
 				}
 				_PR_THREAD_UNLOCK(thred);
+				_PR_IOQ_OSFD_CNT(me->cpu) -= pq->npds;
+				PR_ASSERT(_PR_IOQ_OSFD_CNT(me->cpu) >= 0);
 			}
 		}
 	} else if (nfd == -1) {
 		PR_LOG(_pr_io_lm, PR_LOG_MAX, ("poll() failed with errno %d", errno));
 	}
 
-	/* done with pollfds */
-	PR_DELETE(pollfds);
 #else
 	if (nfd > 0) {
 		q = _PR_IOQ(me->cpu).next;
 		_PR_IOQ_MAX_OSFD(me->cpu) = -1;
 		_PR_IOQ_TIMEOUT(me->cpu) = PR_INTERVAL_NO_TIMEOUT;
 		while (q != &_PR_IOQ(me->cpu)) {
 			PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
 			PRBool notify = PR_FALSE;
@@ -2131,17 +2418,19 @@ void _MD_Wakeup_CPUs()
 void _MD_InitCPUS()
 {
 	PRInt32 rv, flags;
 	PRThread *me = _MD_CURRENT_THREAD();
 
 	rv = pipe(_pr_md_pipefd);
 	PR_ASSERT(rv == 0);
 	_PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0];
+#ifndef _PR_USE_POLL
 	FD_SET(_pr_md_pipefd[0], &_PR_FD_READ_SET(me->cpu));
+#endif
 
 	flags = fcntl(_pr_md_pipefd[0], F_GETFL, 0);
 	fcntl(_pr_md_pipefd[0], F_SETFL, flags | O_NONBLOCK);
 	flags = fcntl(_pr_md_pipefd[1], F_GETFL, 0);
 	fcntl(_pr_md_pipefd[1], F_SETFL, flags | O_NONBLOCK);
 }
 
 /*
@@ -2337,17 +2626,17 @@ PRInt32 _MD_open(const char *name, PRInt
 		osflags = O_RDONLY;
 	}
 
 	if (flags & PR_APPEND)
 		osflags |= O_APPEND;
 	if (flags & PR_TRUNCATE)
 		osflags |= O_TRUNC;
 	if (flags & PR_SYNC) {
-#if defined(FREEBSD)
+#if defined(BSDI) || defined(FREEBSD)
 		osflags |= O_FSYNC;
 #else
 		osflags |= O_SYNC;
 #endif
 	}
 
     /*
     ** On creations we hold the 'create' lock in order to enforce
@@ -2890,32 +3179,37 @@ PRInt32 _PR_WaitForFD(PRInt32 osfd, PRUi
 		return 0;
 	}
 
     pq.thr = me;
 	io_cpu = me->cpu;
     pq.on_ioq = PR_TRUE;
     pq.timeout = timeout;
     _PR_ADD_TO_IOQ(pq, me->cpu);
+
+#ifndef _PR_USE_POLL
 	if (how == PR_POLL_READ) {
 		FD_SET(osfd, &_PR_FD_READ_SET(me->cpu));
 		(_PR_FD_READ_CNT(me->cpu))[osfd]++;
 	} else if (how == PR_POLL_WRITE) {
 		FD_SET(osfd, &_PR_FD_WRITE_SET(me->cpu));
 		(_PR_FD_WRITE_CNT(me->cpu))[osfd]++;
 	} else {
 		FD_SET(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
 		(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd]++;
 	}
+#endif	/* _PR_USE_POLL */
+
 	if (_PR_IOQ_MAX_OSFD(me->cpu) < osfd)
 		_PR_IOQ_MAX_OSFD(me->cpu) = osfd;
 	if (_PR_IOQ_TIMEOUT(me->cpu) > timeout)
 		_PR_IOQ_TIMEOUT(me->cpu) = timeout;
+
+	_PR_IOQ_OSFD_CNT(me->cpu) += 1;
 		
-
     _PR_SLEEPQ_LOCK(me->cpu);
     _PR_ADD_SLEEPQ(me, timeout);
     me->state = _PR_IO_WAIT;
     me->io_pending = PR_TRUE;
     me->io_suspended = PR_FALSE;
     _PR_SLEEPQ_UNLOCK(me->cpu);
     _PR_THREAD_UNLOCK(me);
     _PR_MD_IOQ_UNLOCK();
@@ -2937,27 +3231,31 @@ PRInt32 _PR_WaitForFD(PRInt32 osfd, PRUi
     */
     if (pq.on_ioq) {
     	_PR_MD_IOQ_LOCK();
 	/*
 	 * Need to check pq.on_ioq again
 	 */
         if (pq.on_ioq) {
             	PR_REMOVE_LINK(&pq.links);
-		if (how == PR_POLL_READ) {
-			if ((--(_PR_FD_READ_CNT(me->cpu))[osfd]) == 0)
-				FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));
-		
-		} else if (how == PR_POLL_WRITE) {
-			if ((--(_PR_FD_WRITE_CNT(me->cpu))[osfd]) == 0)
-				FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));
-		} else {
-			if ((--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd]) == 0)
-				FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
-		}
+#ifndef _PR_USE_POLL
+				if (how == PR_POLL_READ) {
+					if ((--(_PR_FD_READ_CNT(me->cpu))[osfd]) == 0)
+						FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));
+				
+				} else if (how == PR_POLL_WRITE) {
+						if ((--(_PR_FD_WRITE_CNT(me->cpu))[osfd]) == 0)
+							FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));
+				} else {
+						if ((--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd]) == 0)
+							FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
+				}
+#endif	/* _PR_USE_POLL */
+    		PR_ASSERT(pq.npds == 1);
+			_PR_IOQ_OSFD_CNT(me->cpu) -= 1;
         }
     	_PR_MD_IOQ_UNLOCK();
 		rv = 0;
     }
     _PR_FAST_INTSON(is);
    return(rv);
 }
 
@@ -3231,8 +3529,145 @@ PRStatus _MD_MemUnmap(void *addr, PRUint
     }
 }
 
 PRStatus _MD_CloseFileMap(PRFileMap *fmap)
 {
     PR_DELETE(fmap);
     return PR_SUCCESS;
 }
+
+#if defined(_PR_NEED_FAKE_POLL)
+
+/*
+ * Some platforms don't have poll().  For easier porting of code
+ * that calls poll(), we emulate poll() using select().
+ */
+
+#include <fcntl.h>
+
+int poll(struct pollfd *filedes, unsigned long nfds, int timeout)
+{
+    int i;
+    int rv;
+    int maxfd;
+    fd_set rd, wr, ex;
+    struct timeval tv, *tvp;
+
+    if (timeout < 0 && timeout != -1) {
+	errno = EINVAL;
+	return -1;
+    }
+
+    if (timeout == -1) {
+        tvp = NULL;
+    } else {
+	tv.tv_sec = timeout / 1000;
+	tv.tv_usec = (timeout % 1000) * 1000;
+        tvp = &tv;
+    }
+
+    maxfd = -1;
+    FD_ZERO(&rd);
+    FD_ZERO(&wr);
+    FD_ZERO(&ex);
+
+    for (i = 0; i < nfds; i++) {
+	int osfd = filedes[i].fd;
+	int events = filedes[i].events;
+	PRBool fdHasEvent = PR_FALSE;
+
+	if (osfd < 0) {
+            continue;  /* Skip this osfd. */
+	}
+
+	/*
+	 * Map the native poll flags to nspr poll flags.
+	 *     POLLIN, POLLRDNORM  ===> PR_POLL_READ
+	 *     POLLOUT, POLLWRNORM ===> PR_POLL_WRITE
+	 *     POLLPRI, POLLRDBAND ===> PR_POLL_EXCEPTION
+	 *     POLLNORM, POLLWRBAND (and POLLMSG on some platforms)
+	 *     are ignored.
+	 *
+	 * The output events POLLERR and POLLHUP are never turned on.
+	 * POLLNVAL may be turned on.
+	 */
+
+	if (events & (POLLIN | POLLRDNORM)) {
+	    FD_SET(osfd, &rd);
+	    fdHasEvent = PR_TRUE;
+	}
+	if (events & (POLLOUT | POLLWRNORM)) {
+	    FD_SET(osfd, &wr);
+	    fdHasEvent = PR_TRUE;
+	}
+	if (events & (POLLPRI | POLLRDBAND)) {
+	    FD_SET(osfd, &ex);
+	    fdHasEvent = PR_TRUE;
+	}
+	if (fdHasEvent && osfd > maxfd) {
+	    maxfd = osfd;
+	}
+    }
+
+    rv = select(maxfd + 1, &rd, &wr, &ex, tvp);
+
+    /* Compute poll results */
+    if (rv > 0) {
+	rv = 0;
+        for (i = 0; i < nfds; i++) {
+	    PRBool fdHasEvent = PR_FALSE;
+
+	    filedes[i].revents = 0;
+            if (filedes[i].fd < 0) {
+                continue;
+            }
+	    if (FD_ISSET(filedes[i].fd, &rd)) {
+		if (filedes[i].events & POLLIN) {
+		    filedes[i].revents |= POLLIN;
+		}
+		if (filedes[i].events & POLLRDNORM) {
+		    filedes[i].revents |= POLLRDNORM;
+		}
+		fdHasEvent = PR_TRUE;
+	    }
+	    if (FD_ISSET(filedes[i].fd, &wr)) {
+		if (filedes[i].events & POLLOUT) {
+		    filedes[i].revents |= POLLOUT;
+		}
+		if (filedes[i].events & POLLWRNORM) {
+		    filedes[i].revents |= POLLWRNORM;
+		}
+		fdHasEvent = PR_TRUE;
+	    }
+	    if (FD_ISSET(filedes[i].fd, &ex)) {
+		if (filedes[i].events & POLLPRI) {
+		    filedes[i].revents |= POLLPRI;
+		}
+		if (filedes[i].events & POLLRDBAND) {
+		    filedes[i].revents |= POLLRDBAND;
+		}
+		fdHasEvent = PR_TRUE;
+	    }
+	    if (fdHasEvent) {
+		rv++;
+            }
+        }
+	PR_ASSERT(rv > 0);
+    } else if (rv == -1 && errno == EBADF) {
+	rv = 0;
+        for (i = 0; i < nfds; i++) {
+	    filedes[i].revents = 0;
+            if (filedes[i].fd < 0) {
+                continue;
+            }
+	    if (fcntl(filedes[i].fd, F_GETFL, 0) == -1) {
+		filedes[i].revents = POLLNVAL;
+		rv++;
+	    }
+        }
+	PR_ASSERT(rv > 0);
+    }
+    PR_ASSERT(-1 != timeout || rv != 0);
+
+    return rv;
+}
+#endif /* _PR_NEED_FAKE_POLL */
--- a/pr/src/md/unix/unix_errors.c
+++ b/pr/src/md/unix/unix_errors.c
@@ -1407,16 +1407,36 @@ void _MD_unix_map_select_error(int err)
 			PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
 			break;
 		default:
 			PR_SetError(PR_UNKNOWN_ERROR, err);
 			break;
     }
 }
 
+void _MD_unix_map_poll_error(int err)
+{
+    PRErrorCode prerror;
+    switch (err) {
+        case EAGAIN:
+            prerror = PR_INSUFFICIENT_RESOURCES_ERROR;
+            break;
+        case EINVAL:
+            prerror = PR_INVALID_ARGUMENT_ERROR;
+            break;
+        case EFAULT:
+            prerror = PR_ACCESS_FAULT_ERROR;
+            break;
+        default:
+            prerror = PR_UNKNOWN_ERROR;
+            break;
+    }
+    PR_SetError(prerror, err);
+}
+
 void _MD_unix_map_flock_error(int err)
 {
     switch (err) {
 		case EBADF:
 		case EINVAL:
 			PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
 			break;
 		case EWOULDBLOCK:
--- a/pr/src/md/windows/ntio.c
+++ b/pr/src/md/windows/ntio.c
@@ -2940,17 +2940,17 @@ PRInt32 IsFileLocal(HANDLE hFile)
       dwIndex++;
       dwMask = dwMask >> 1;
    }
 
    return _PR_REMOTE_FILE;
 }
 #endif /* _NEED_351_FILE_LOCKING_HACK */
 
-void PR_NT_UseNonblock()
+PR_IMPLEMENT(void) PR_NT_UseNonblock()
 {
     _nt_use_async = 0;
 }
 
 
 PRInt32 _nt_nonblock_accept(PRFileDesc *fd, struct sockaddr_in *addr, int *len, PRIntervalTime timeout)
 {
     PRInt32 osfd = fd->secret->md.osfd;
--- a/pr/src/md/windows/ntmisc.c
+++ b/pr/src/md/windows/ntmisc.c
@@ -55,17 +55,17 @@ PRIntn _PR_MD_PUT_ENV(const char *name)
  *     The epoch is midnight January 1, 1970 GMT.
  *     The implementation is machine dependent.  This is the
  *     implementation for Windows.
  *     Cf. time_t time(time_t *tp)
  *
  *-----------------------------------------------------------------------
  */
 
-PRTime
+PR_IMPLEMENT(PRTime)
 PR_Now(void)
 {
     PRInt64 s, ms, ms2us, s2us;
     struct timeb b;
 
     ftime(&b);
     LL_I2L(ms2us, PR_USEC_PER_MSEC);
     LL_I2L(s2us, PR_USEC_PER_SEC);
@@ -596,8 +596,56 @@ PRStatus _MD_MemUnmap(void *addr, PRUint
 }
 
 PRStatus _MD_CloseFileMap(PRFileMap *fmap)
 {
     CloseHandle(fmap->md.hFileMap);
     PR_DELETE(fmap);
     return PR_SUCCESS;
 }
+
+/*
+ ***********************************************************************
+ *
+ * Atomic increment and decrement operations for x86 processors
+ *
+ * We don't use InterlockedIncrement and InterlockedDecrement
+ * because on NT 3.51 and Win95, they return a number with
+ * the same sign as the incremented/decremented result, rather
+ * than the result itself.  On NT 4.0 these functions do return
+ * the incremented/decremented result.
+ *
+ * The result is returned in the eax register by the inline
+ * assembly code.  We disable the harmless "no return value"
+ * warning (4035) for these two functions.
+ *
+ ***********************************************************************
+ */
+
+#if defined(_M_IX86) || defined(_X86_)
+
+#pragma warning(disable: 4035)
+PRInt32 _PR_MD_ATOMIC_INCREMENT(PRInt32 *val)
+{
+    __asm
+    {
+        mov ecx, val
+        mov eax, 1
+        xadd dword ptr [ecx], eax
+        inc eax
+    }
+}
+#pragma warning(default: 4035)
+
+#pragma warning(disable: 4035)
+PRInt32 _PR_MD_ATOMIC_DECREMENT(PRInt32 *val)
+{
+    __asm
+    {
+        mov ecx, val
+        mov eax, 0ffffffffh
+        xadd dword ptr [ecx], eax
+        dec eax
+    }
+}
+#pragma warning(default: 4035)
+
+#endif /* x86 processors */
--- a/pr/src/md/windows/ntthread.c
+++ b/pr/src/md/windows/ntthread.c
@@ -186,41 +186,43 @@ void
 {
     /* Can NT really yield at all? */
     Sleep(0);
 }
 
 void     
 _PR_MD_SET_PRIORITY(_MDThread *thread, PRThreadPriority newPri)
 {
-#if 0
-    /* XXXMB - does this work? Should we really set the priorities of
-     * native threads? */
-    if( newPri < 4 ) {
-        newPri = (PRUintn)THREAD_PRIORITY_IDLE;
-    } else if( newPri < 8 ) {
-        newPri = (PRUintn)THREAD_PRIORITY_LOWEST;
-    } else if( newPri < 12 ) {
-        newPri = (PRUintn)THREAD_PRIORITY_BELOW_NORMAL;
-    } else if( newPri < 16 ) {
-        newPri = (PRUintn)THREAD_PRIORITY_NORMAL;
-    } else if( newPri < 24 ) {
-        newPri = (PRUintn)THREAD_PRIORITY_ABOVE_NORMAL;
-    } else if( newPri < 28 ) {
-        newPri = (PRUintn)THREAD_PRIORITY_HIGHEST;
-    } else if( newPri < 32 ) {
-        newPri = (PRUintn)THREAD_PRIORITY_TIME_CRITICAL;
-    }        
+    int nativePri;
+    BOOL rv;
 
-    if( ! SetThreadPriority( thread->handle, newPri ) ) {
-        PR_LOG(_pr_thread_lm, PR_LOG_MIN,
-               ("PR_SetThreadPriority: can't set thread priority\n"));
+    if (newPri < PR_PRIORITY_FIRST) {
+        newPri = PR_PRIORITY_FIRST;
+    } else if (newPri > PR_PRIORITY_LAST) {
+        newPri = PR_PRIORITY_LAST;
     }
-#endif
-
+    switch (newPri) {
+        case PR_PRIORITY_LOW:
+            nativePri = THREAD_PRIORITY_BELOW_NORMAL;
+            break;
+        case PR_PRIORITY_NORMAL:
+            nativePri = THREAD_PRIORITY_NORMAL;
+            break;
+        case PR_PRIORITY_HIGH:
+            nativePri = THREAD_PRIORITY_ABOVE_NORMAL;
+            break;
+        case PR_PRIORITY_URGENT:
+            nativePri = THREAD_PRIORITY_HIGHEST;
+    }
+    rv = SetThreadPriority(thread->handle, nativePri);
+    PR_ASSERT(rv);
+    if (!rv) {
+	PR_LOG(_pr_thread_lm, PR_LOG_MIN,
+                ("PR_SetThreadPriority: can't set thread priority\n"));
+    }
     return;
 }
 
 void
 _PR_MD_CLEAN_THREAD(PRThread *thread)
 {
     if (thread->md.acceptex_buf) {
         PR_DELETE(thread->md.acceptex_buf);
--- a/pr/src/md/windows/w16null.c
+++ b/pr/src/md/windows/w16null.c
@@ -37,17 +37,17 @@ char *                  _pr_top_of_task_
  *     Cf. time_t time(time_t *tp)
  *
  *-----------------------------------------------------------------------
  */
 
 #if defined(HAVE_WATCOM_BUG_2)
 PRTime __pascal __export __loadds
 #else
-PRTime
+PR_IMPLEMENT(PRTime)
 #endif
 PR_Now(void)
 {
     PRInt64 s, ms, ms2us, s2us;
     struct timeb b;
 
     ftime(&b);
     LL_I2L(ms2us, PR_USEC_PER_MSEC);
--- a/pr/src/md/windows/w95thred.c
+++ b/pr/src/md/windows/w95thred.c
@@ -17,31 +17,49 @@
  */
 
 #include "primpl.h"
 #include <process.h>  /* for _beginthreadex() */
 
 extern void _PR_Win32InitTimeZone(void);  /* defined in ntmisc.c */
 
 /* --- globals ------------------------------------------------ */
+#ifdef _PR_USE_STATIC_TLS
 __declspec(thread) struct PRThread  *_pr_thread_last_run;
 __declspec(thread) struct PRThread  *_pr_currentThread;
 __declspec(thread) struct _PRCPU    *_pr_currentCPU;
+#else
+DWORD _pr_currentThreadIndex;
+DWORD _pr_lastThreadIndex;
+DWORD _pr_currentCPUIndex;
+#endif
 int                           _pr_intsOff = 0; 
 _PRInterruptTable             _pr_interruptTable[] = { { 0 } };
 
 void
 _PR_MD_EARLY_INIT()
 {
     _PR_Win32InitTimeZone();
+
+#ifndef _PR_USE_STATIC_TLS
+    _pr_currentThreadIndex = TlsAlloc();
+    _pr_lastThreadIndex = TlsAlloc();
+    _pr_currentCPUIndex = TlsAlloc();
+#endif
 }
 
 void _PR_MD_CLEANUP_BEFORE_EXIT(void)
 {
     WSACleanup();
+
+#ifndef _PR_USE_STATIC_TLS
+    TlsFree(_pr_currentThreadIndex);
+    TlsFree(_pr_lastThreadIndex);
+    TlsFree(_pr_currentCPUIndex);
+#endif
 }
 
 void
 _PR_MD_INIT_PRIMORDIAL_THREAD(PRThread *thread)
 {
     /*
     ** Warning:
     ** --------
--- a/pr/src/md/windows/win32_errors.c
+++ b/pr/src/md/windows/win32_errors.c
@@ -13,16 +13,17 @@
  * The Initial Developer of this code under the NPL is Netscape
  * Communications Corporation.  Portions created by Netscape are
  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  * Reserved.
  */
 
 #include "prerror.h"
 #include <errno.h>
+#include <windows.h>
 
 void _MD_win32_map_opendir_error(PRInt32 err)
 {
 	switch (err) {
 		case ERROR_FILE_NOT_FOUND:
 		case ERROR_PATH_NOT_FOUND:
 			PR_SetError(PR_FILE_NOT_FOUND_ERROR, err);
 			break;
--- a/pr/src/misc/pratom.c
+++ b/pr/src/misc/pratom.c
@@ -42,40 +42,52 @@
 static PRLock *monitor = NULL;
 void _PR_MD_INIT_ATOMIC()
 {
     if (monitor == NULL) {
         monitor = PR_NewLock();
     }
 }
 
-PR_IMPLEMENT(PRInt32)
+PRInt32
 _PR_MD_ATOMIC_INCREMENT(PRInt32 *val)
 {
     PRInt32 rv;
+
+    if (!_pr_initialized) {
+        _PR_ImplicitInitialization();
+    }
     PR_Lock(monitor);
     rv = ++(*val);
     PR_Unlock(monitor);
     return rv;
 }
 
-PR_IMPLEMENT(PRInt32)
+PRInt32
 _PR_MD_ATOMIC_DECREMENT(PRInt32 *val)
 {
     PRInt32 rv;
+
+    if (!_pr_initialized) {
+        _PR_ImplicitInitialization();
+    }
     PR_Lock(monitor);
     rv = --(*val);
     PR_Unlock(monitor);
     return rv;
 }
 
-PR_IMPLEMENT(PRInt32)
+PRInt32
 _PR_MD_ATOMIC_SET(PRInt32 *val, PRInt32 newval)
 {
     PRInt32 rv;
+
+    if (!_pr_initialized) {
+        _PR_ImplicitInitialization();
+    }
     PR_Lock(monitor);
     rv = *val;
     *val = newval;
     PR_Unlock(monitor);
     return rv;
 }
 
 #endif  /* !_PR_HAVE_ATOMIC_OPS */
--- a/pr/src/misc/prdtoa.c
+++ b/pr/src/misc/prdtoa.c
@@ -1,9 +1,25 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL.  You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ * 
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ * 
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation.  Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
+ * Reserved.
+ */
 
 #include "primpl.h"
 
 /****************************************************************
  *
  * The author of this software is David M. Gay.
  *
  * Copyright (c) 1991 by AT&T.
@@ -25,22 +41,22 @@
 	David M. Gay
 	AT&T Bell Laboratories, Room 2C-463
 	600 Mountain Avenue
 	Murray Hill, NJ 07974-2070
 	U.S.A.
 	dmg@research.att.com or research!dmg
  */
 
-/* strtod for IEEE-, VAX-, and IBM-arithmetic machines.
+/* PR_strtod for IEEE-, VAX-, and IBM-arithmetic machines.
  *
- * This strtod returns a nearest machine number to the input decimal
- * string (or sets errno to ERANGE).  With IEEE arithmetic, ties are
- * broken by the IEEE round-even rule.  Otherwise ties are broken by
- * biased rounding (add half and chop).
+ * This PR_strtod returns a nearest machine number to the input decimal
+ * string (or sets the error code to PR_RANGE_ERROR).  With IEEE
+ * arithmetic, ties are broken by the IEEE round-even rule.  Otherwise
+ * ties are broken by biased rounding (add half and chop).
  *
  * Inspired loosely by William D. Clinger's paper "How to Read Floating
  * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101].
  *
  * Modifications:
  *
  *	1. We only require IEEE, IBM, or VAX double-precision
  *		arithmetic (not IEEE double-extended).
@@ -119,17 +135,16 @@
 #include "string.h"
 
 #ifdef MALLOC
 extern void *MALLOC(size_t);
 #else
 #define MALLOC PR_MALLOC
 #endif
 
-#include "errno.h"
 #ifdef Bad_float_h
 #undef __STDC__
 #ifdef IEEE_MC68k
 #define IEEE_ARITHMETIC
 #endif
 #ifdef IEEE_8087
 #define IEEE_ARITHMETIC
 #endif
@@ -1346,17 +1361,17 @@ dig_done:
 	/* Get starting approximation = rv * 10**e1 */
 
 	if (e1 > 0) {
 		if ((i = e1 & 15) != 0)
 			rv *= tens[i];
 		if (e1 &= ~15) {
 			if (e1 > DBL_MAX_10_EXP) {
 			ovfl:
-				errno = ERANGE;
+				PR_SetError(PR_RANGE_ERROR, 0);
 #ifdef __STDC__
 				rv = HUGE_VAL;
 #else
 				/* Can't trust HUGE_VAL */
 #ifdef IEEE_Arith
 				word0(rv) = Exp_mask;
 				word1(rv) = 0;
 #else
@@ -1405,17 +1420,17 @@ dig_done:
 			rv0 = rv;
 			rv *= tinytens[j];
 			if (!rv) {
 				rv = 2.*rv0;
 				rv *= tinytens[j];
 				if (!rv) {
 				undfl:
 					rv = 0.;
-					errno = ERANGE;
+					PR_SetError(PR_RANGE_ERROR, 0);
 					if (bd0)
 						goto retfree;
 					goto ret;
 				}
 				word0(rv) = Tiny0;
 				word1(rv) = Tiny1;
 				/* The refinement below will clean
 				 * this approximation up.
@@ -1787,657 +1802,17 @@ quorem(Bigint *b, Bigint *S)
 			while(--bxe > bx && !*bxe)
 				--n;
 			b->wds = n;
 		}
 	}
 	return (int)q;
 }
 
-/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
- *
- * Inspired by "How to Print Floating-Point Numbers Accurately" by
- * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101].
- *
- * Modifications:
- *	1. Rather than iterating, we use a simple numeric overestimate
- *	   to determine k = floor(log10(d)).  We scale relevant
- *	   quantities using O(log2(k)) rather than O(k) multiplications.
- *	2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
- *	   try to generate digits strictly left to right.  Instead, we
- *	   compute with fewer bits and propagate the carry if necessary
- *	   when rounding the final digit up.  This is often faster.
- *	3. Under the assumption that input will be rounded nearest,
- *	   mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
- *	   That is, we allow equality in stopping tests when the
- *	   round-nearest rule will give the same floating-point value
- *	   as would satisfaction of the stopping test with strict
- *	   inequality.
- *	4. We remove common factors of powers of 2 from relevant
- *	   quantities.
- *	5. When converting floating-point integers less than 1e16,
- *	   we use floating-point arithmetic rather than resorting
- *	   to multiple-precision integers.
- *	6. When asked to produce fewer than 15 digits, we first try
- *	   to get by with floating-point arithmetic; we resort to
- *	   multiple-precision integer arithmetic only if we cannot
- *	   guarantee that the floating-point calculation has given
- *	   the correctly rounded result.  For k requested digits and
- *	   "uniformly" distributed input, the probability is
- *	   something like 10^(k-15) that we must resort to the Long
- *	   calculation.
- */
-
-PR_IMPLEMENT(char *)
-PR_dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve)
-{
-	/*	Arguments ndigits, decpt, sign are similar to those
-		of ecvt and fcvt; trailing zeros are suppressed from
-		the returned string.  If not null, *rve is set to point
-		to the end of the return value.  If d is +-Infinity or NaN,
-		then *decpt is set to 9999.
-
-		mode:
-		0 ==> shortest string that yields d when read in
-		and rounded to nearest.
-		1 ==> like 0, but with Steele & White stopping rule;
-		e.g. with IEEE P754 arithmetic , mode 0 gives
-		1e23 whereas mode 1 gives 9.999999999999999e22.
-		2 ==> max(1,ndigits) significant digits.  This gives a
-		return value similar to that of ecvt, except
-		that trailing zeros are suppressed.
-		3 ==> through ndigits past the decimal point.  This
-		gives a return value similar to that from fcvt,
-		except that trailing zeros are suppressed, and
-		ndigits can be negative.
-		4-9 should give the same return values as 2-3, i.e.,
-		4 <= mode <= 9 ==> same return as mode
-		2 + (mode & 1).  These modes are mainly for
-		debugging; often they run slower but sometimes
-		faster than modes 2-3.
-		4,5,8,9 ==> left-to-right digit generation.
-		6-9 ==> don't try fast floating-point estimate
-		(if applicable).
-
-		Values of mode other than 0-9 are treated as mode 0.
-
-		Sufficient space is allocated to the return value
-		to hold the suppressed trailing zeros.
-	*/
-
-	PRInt32 bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1,
-		j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,
-		spec_case, try_quick;
-	Long L;
-#ifndef Sudden_Underflow
-	PRInt32 denorm;
-	unsigned Long x;
-#endif
-	Bigint *b, *b1, *delta, *mlo, *mhi, *S;
-	double d2, ds, eps;
-	char *s, *s0;
-	static Bigint *result;
-	static PRInt32 result_k;
-
-	if (!_pr_initialized) _PR_ImplicitInitialization();
-
-	if (result) {
-		result->k = result_k;
-		result->maxwds = 1 << result_k;
-		Bfree(result);
-		result = 0;
-	}
-
-	if (word0(d) & Sign_bit) {
-		/* set sign for everything, including 0's and NaNs */
-		*sign = 1;
-		word0(d) &= ~Sign_bit;	/* clear sign bit */
-	}
-	else
-		*sign = 0;
-
-#if defined(IEEE_Arith) + defined(VAX)
-#ifdef IEEE_Arith
-	if ((word0(d) & Exp_mask) == Exp_mask)
-#else
-		if (word0(d)  == 0x8000)
-#endif
-			{
-				/* Infinity or NaN */
-				*decpt = 9999;
-				s =
-#ifdef IEEE_Arith
-					!word1(d) && !(word0(d) & 0xfffff) ? "Infinity" :
-#endif
-					"NaN";
-				if (rve)
-					*rve =
-#ifdef IEEE_Arith
-						s[3] ? s + 8 :
-#endif
-					s + 3;
-				return s;
-			}
-#endif
-#ifdef IBM
-	d += 0; /* normalize */
-#endif
-	if (!d) {
-		*decpt = 1;
-		s = "0";
-		if (rve)
-			*rve = s + 1;
-		return s;
-	}
-
-	b = d2b(d, &be, &bbits);
-#ifdef Sudden_Underflow
-	i = (PRInt32)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
-#else
-	if ((i = (PRInt32)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) != 0) {
-#endif
-		d2 = d;
-		word0(d2) &= Frac_mask1;
-		word0(d2) |= Exp_11;
-#ifdef IBM
-		if (j = 11 - hi0bits(word0(d2) & Frac_mask))
-			d2 /= 1 << j;
-#endif
-
-		/* log(x)	~=~ log(1.5) + (x-1.5)/1.5
-		 * log10(x)	 =  log(x) / log(10)
-		 *		~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
-		 * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
-		 *
-		 * This suggests computing an approximation k to log10(d) by
-		 *
-		 * k = (i - Bias)*0.301029995663981
-		 *	+ ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
-		 *
-		 * We want k to be too large rather than too small.
-		 * The error in the first-order Taylor series approximation
-		 * is in our favor, so we just round up the constant enough
-		 * to compensate for any error in the multiplication of
-		 * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
-		 * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
-		 * adding 1e-13 to the constant term more than suffices.
-		 * Hence we adjust the constant term to 0.1760912590558.
-		 * (We could get a more accurate k by invoking log10,
-		 *  but this is probably not worthwhile.)
-		 */
-
-		i -= Bias;
-#ifdef IBM
-		i <<= 2;
-		i += j;
-#endif
-#ifndef Sudden_Underflow
-		denorm = 0;
-	}
-	else {
-		/* d is denormalized */
-
-		i = bbits + be + (Bias + (P-1) - 1);
-		x = i > 32  ? word0(d) << (64 - i) | word1(d) >> (i - 32)
-			: word1(d) << (32 - i);
-		d2 = x;
-		word0(d2) -= 31*Exp_msk1; /* adjust exponent */
-		i -= (Bias + (P-1) - 1) + 1;
-		denorm = 1;
-	}
-#endif
-	ds = (d2-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
-	k = (PRInt32)ds;
-	if (ds < 0. && ds != k)
-		k--;	/* want k = floor(ds) */
-	k_check = 1;
-	if (k >= 0 && k <= Ten_pmax) {
-		if (d < tens[k])
-			k--;
-		k_check = 0;
-	}
-	j = bbits - i - 1;
-	if (j >= 0) {
-		b2 = 0;
-		s2 = j;
-	}
-	else {
-		b2 = -j;
-		s2 = 0;
-	}
-	if (k >= 0) {
-		b5 = 0;
-		s5 = k;
-		s2 += k;
-	}
-	else {
-		b2 -= k;
-		b5 = -k;
-		s5 = 0;
-	}
-	if (mode < 0 || mode > 9)
-		mode = 0;
-	try_quick = 1;
-	if (mode > 5) {
-		mode -= 4;
-		try_quick = 0;
-	}
-	leftright = 1;
-	switch(mode) {
-	case 0:
-	case 1:
-		ilim = ilim1 = -1;
-		i = 18;
-		ndigits = 0;
-		break;
-	case 2:
-		leftright = 0;
-		/* no break */
-	case 4:
-		if (ndigits <= 0)
-			ndigits = 1;
-		ilim = ilim1 = i = ndigits;
-		break;
-	case 3:
-		leftright = 0;
-		/* no break */
-	case 5:
-		i = ndigits + k + 1;
-		ilim = i;
-		ilim1 = i - 1;
-		if (i <= 0)
-			i = 1;
-	}
-	j = sizeof(unsigned Long);
-	for(result_k = 0; sizeof(Bigint) - sizeof(unsigned Long) <= i - j;
-		j <<= 1) result_k++;
-	result = Balloc(result_k);
-	s = s0 = (char *)result;
-
-	if (ilim >= 0 && ilim <= Quick_max && try_quick) {
-
-		/* Try to get by with floating-point arithmetic. */
-
-		i = 0;
-		d2 = d;
-		k0 = k;
-		ilim0 = ilim;
-		ieps = 2; /* conservative */
-		if (k > 0) {
-			ds = tens[k&0xf];
-			j = k >> 4;
-			if (j & Bletch) {
-				/* prevent overflows */
-				j &= Bletch - 1;
-				d /= bigtens[n_bigtens-1];
-				ieps++;
-			}
-			for(; j; j >>= 1, i++)
-				if (j & 1) {
-					ieps++;
-					ds *= bigtens[i];
-				}
-			d /= ds;
-		}
-		else if ((j1 = -k) != 0) {
-			d *= tens[j1 & 0xf];
-			for(j = j1 >> 4; j; j >>= 1, i++)
-				if (j & 1) {
-					ieps++;
-					d *= bigtens[i];
-				}
-		}
-		if (k_check && d < 1. && ilim > 0) {
-			if (ilim1 <= 0)
-				goto fast_failed;
-			ilim = ilim1;
-			k--;
-			d *= 10.;
-			ieps++;
-		}
-		eps = ieps*d + 7.;
-		word0(eps) -= (P-1)*Exp_msk1;
-		if (ilim == 0) {
-			S = mhi = 0;
-			d -= 5.;
-			if (d > eps)
-				goto one_digit;
-			if (d < -eps)
-				goto no_digits;
-			goto fast_failed;
-		}
-#ifndef No_leftright
-		if (leftright) {
-			/* Use Steele & White method of only
-			 * generating digits needed.
-			 */
-			eps = 0.5/tens[ilim-1] - eps;
-			for(i = 0;;) {
-				L = (Long) d;
-				d -= L;
-				*s++ = '0' + (PRInt32)L;
-				if (d < eps)
-					goto ret1;
-				if (1. - d < eps)
-					goto bump_up;
-				if (++i >= ilim)
-					break;
-				eps *= 10.;
-				d *= 10.;
-			}
-		}
-		else {
-#endif
-			/* Generate ilim digits, then fix them up. */
-			eps *= tens[ilim-1];
-			for(i = 1;; i++, d *= 10.) {
-				L = (Long) d;
-				d -= L;
-				*s++ = '0' + (PRInt32)L;
-				if (i == ilim) {
-					if (d > 0.5 + eps)
-						goto bump_up;
-					else if (d < 0.5 - eps) {
-						while(*--s == '0'){} /* just count -- nothing to execute */
-						s++;
-						goto ret1;
-					}
-					break;
-				}
-			}
-#ifndef No_leftright
-		}
-#endif
-	fast_failed:
-		s = s0;
-		d = d2;
-		k = k0;
-		ilim = ilim0;
-	}
-
-	/* Do we have a "small" integer? */
-
-	if (be >= 0 && k <= Int_max) {
-		/* Yes. */
-		ds = tens[k];
-		if (ndigits < 0 && ilim <= 0) {
-			S = mhi = 0;
-			if (ilim < 0 || d <= 5*ds)
-				goto no_digits;
-			goto one_digit;
-		}
-		for(i = 1;; i++) {
-			L = (Long) (d / ds);
-			d -= L*ds;
-#ifdef Check_FLT_ROUNDS
-			/* If FLT_ROUNDS == 2, L will usually be high by 1 */
-			if (d < 0) {
-				L--;
-				d += ds;
-			}
-#endif
-			*s++ = '0' + (PRInt32)L;
-			if (i == ilim) {
-				d += d;
-				if ((d > ds) || (d == ds && L & 1)) {
-				bump_up:
-					while(*--s == '9')
-						if (s == s0) {
-							k++;
-							*s = '0';
-							break;
-						}
-					++*s++;
-				}
-				break;
-			}
-			if (!(d *= 10.))
-				break;
-		}
-		goto ret1;
-	}
-
-	m2 = b2;
-	m5 = b5;
-	mhi = mlo = 0;
-	if (leftright) {
-		if (mode < 2) {
-			i =
-#ifndef Sudden_Underflow
-				denorm ? be + (Bias + (P-1) - 1 + 1) :
-#endif
-#ifdef IBM
-				1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3);
-#else
-			1 + P - bbits;
-#endif
-		}
-		else {
-			j = ilim - 1;
-			if (m5 >= j)
-				m5 -= j;
-			else {
-				s5 += j -= m5;
-				b5 += j;
-				m5 = 0;
-			}
-			if ((i = ilim) < 0) {
-				m2 -= i;
-				i = 0;
-			}
-		}
-		b2 += i;
-		s2 += i;
-		mhi = i2b(1);
-	}
-	if (m2 > 0 && s2 > 0) {
-		i = m2 < s2 ? m2 : s2;
-		b2 -= i;
-		m2 -= i;
-		s2 -= i;
-	}
-	if (b5 > 0) {
-		if (leftright) {
-			if (m5 > 0) {
-				mhi = pow5mult(mhi, m5);
-				b1 = mult(mhi, b);
-				Bfree(b);
-				b = b1;
-			}
-			if ((j = b5 - m5) != 0)
-				b = pow5mult(b, j);
-		}
-		else
-			b = pow5mult(b, b5);
-	}
-	S = i2b(1);
-	if (s5 > 0)
-		S = pow5mult(S, s5);
-
-	/* Check for special case that d is a normalized power of 2. */
-
-	if (mode < 2) {
-		if (!word1(d) && !(word0(d) & Bndry_mask)
-#ifndef Sudden_Underflow
-			&& word0(d) & Exp_mask
-#endif
-			) {
-			/* The special case */
-			b2 += Log2P;
-			s2 += Log2P;
-			spec_case = 1;
-		}
-		else
-			spec_case = 0;
-	}
-
-	/* Arrange for convenient computation of quotients:
-	 * shift left if necessary so divisor has 4 leading 0 bits.
-	 *
-	 * Perhaps we should just compute leading 28 bits of S once
-	 * and for all and pass them and a shift to quorem, so it
-	 * can do shifts and ors to compute the numerator for q.
-	 */
-#ifdef Pack_32
-	if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f) != 0)
-		i = 32 - i;
-#else
-	if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf)
-		i = 16 - i;
-#endif
-	if (i > 4) {
-		i -= 4;
-		b2 += i;
-		m2 += i;
-		s2 += i;
-	}
-	else if (i < 4) {
-		i += 28;
-		b2 += i;
-		m2 += i;
-		s2 += i;
-	}
-	if (b2 > 0)
-		b = lshift(b, b2);
-	if (s2 > 0)
-		S = lshift(S, s2);
-	if (k_check) {
-		if (cmp(b,S) < 0) {
-			k--;
-			b = multadd(b, 10, 0);	/* we botched the k estimate */
-			if (leftright)
-				mhi = multadd(mhi, 10, 0);
-			ilim = ilim1;
-		}
-	}
-	if (ilim <= 0 && mode > 2) {
-		if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) {
-			/* no digits, fcvt style */
-		no_digits:
-			k = -1 - ndigits;
-			goto ret;
-		}
-	one_digit:
-		*s++ = '1';
-		k++;
-		goto ret;
-	}
-	if (leftright) {
-		if (m2 > 0)
-			mhi = lshift(mhi, m2);
-
-		/* Compute mlo -- check for special case
-		 * that d is a normalized power of 2.
-		 */
-
-		mlo = mhi;
-		if (spec_case) {
-			mhi = Balloc(mhi->k);
-			Bcopy(mhi, mlo);
-			mhi = lshift(mhi, Log2P);
-		}
-
-		for(i = 1;;i++) {
-			dig = quorem(b,S) + '0';
-			/* Do we yet have the shortest decimal string
-			 * that will round to d?
-			 */
-			j = cmp(b, mlo);
-			delta = diff(S, mhi);
-			j1 = delta->sign ? 1 : cmp(b, delta);
-			Bfree(delta);
-#ifndef ROUND_BIASED
-			if (j1 == 0 && !mode && !(word1(d) & 1)) {
-				if (dig == '9')
-					goto round_9_up;
-				if (j > 0)
-					dig++;
-				*s++ = dig;
-				goto ret;
-			}
-#endif
-			if ((j < 0) || ((j == 0) && (!mode)
-#ifndef ROUND_BIASED
-				&& (!(word1(d) & 1)))
-#endif
-				) {
-				if (j1 > 0) {
-					b = lshift(b, 1);
-					j1 = cmp(b, S);
-					if (((j1 > 0) || (j1 == 0 && dig & 1))
-						&& (dig++ == '9'))
-						goto round_9_up;
-				}
-				*s++ = dig;
-				goto ret;
-			}
-			if (j1 > 0) {
-				if (dig == '9') { /* possible if i == 1 */
-				round_9_up:
-					*s++ = '9';
-					goto roundoff;
-				}
-				*s++ = dig + 1;
-				goto ret;
-			}
-			*s++ = dig;
-			if (i == ilim)
-				break;
-			b = multadd(b, 10, 0);
-			if (mlo == mhi)
-				mlo = mhi = multadd(mhi, 10, 0);
-			else {
-				mlo = multadd(mlo, 10, 0);
-				mhi = multadd(mhi, 10, 0);
-			}
-		}
-	}
-	else
-		for(i = 1;; i++) {
-			*s++ = dig = quorem(b,S) + '0';
-			if (i >= ilim)
-				break;
-			b = multadd(b, 10, 0);
-		}
-
-	/* Round off last digit */
-
-	b = lshift(b, 1);
-	j = cmp(b, S);
-	if ((j > 0) || (j == 0 && dig & 1)) {
-	roundoff:
-		while(*--s == '9')
-			if (s == s0) {
-				k++;
-				*s++ = '1';
-				goto ret;
-			}
-		++*s++;
-	}
-	else {
-		while(*--s == '0'){} /* just count -- nothing to execute */
-		s++;
-	}
-ret:
-	Bfree(S);
-	if (mhi) {
-		if (mlo && mlo != mhi)
-			Bfree(mlo);
-		Bfree(mhi);
-	}
-ret1:
-	Bfree(b);
-	*s = 0;
-	*decpt = k + 1;
-	if (rve)
-		*rve = s;
-	return s0;
-}
-
-/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
+/* PR_dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
  *
  * Inspired by "How to Print Floating-Point Numbers Accurately" by
  * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101].
  *
  * Modifications:
  *	1. Rather than iterating, we use a simple numeric overestimate
  *	   to determine k = floor(log10(d)).  We scale relevant
  *	   quantities using O(log2(k)) rather than O(k) multiplications.
@@ -2462,17 +1837,17 @@ ret1:
  *	   guarantee that the floating-point calculation has given
  *	   the correctly rounded result.  For k requested digits and
  *	   "uniformly" distributed input, the probability is
  *	   something like 10^(k-15) that we must resort to the Long
  *	   calculation.
  */
 
 PR_IMPLEMENT(PRStatus)
-PR_dtoa_r(double d, int mode, int ndigits,
+PR_dtoa(double d, int mode, int ndigits,
 	int *decpt, int *sign, char **rve, char *buf, PRSize bufsize)
 {
 	/*	Arguments ndigits, decpt, sign are similar to those
 		of ecvt and fcvt; trailing zeros are suppressed from
 		the returned string.  If not null, *rve is set to point
 		to the end of the return value.  If d is +-Infinity or NaN,
 		then *decpt is set to 9999.
 
@@ -3118,17 +2493,17 @@ PR_cnvtf(char *buf,int bufsz, int prcsn,
 
 	/* If anything fails, we store an empty string in 'buf' */
 	num = (char*)PR_MALLOC(bufsz);
 	if (num == NULL) {
 		buf[0] = '\0';
 		return;
 	}
 	/* XXX Why use mode 1? */
-	if (PR_dtoa_r(fval,1,prcsn,&decpt,&sign,&endnum,num,bufsz)
+	if (PR_dtoa(fval,1,prcsn,&decpt,&sign,&endnum,num,bufsz)
 			== PR_FAILURE) {
 		buf[0] = '\0';
 		goto done;
 	}
 	numdigits = endnum - num;
 	nump = num;
 
 	if (sign &&
@@ -3151,23 +2526,28 @@ PR_cnvtf(char *buf,int bufsz, int prcsn,
 		
 	    while(*nump != '\0'){
 			*bufp++ = *nump++;
 	    }
 	    *bufp++ = 'e';
 	    PR_snprintf(bufp,bufsz - (bufp - buf), "%+d",decpt-1);
 	}
 	else if(decpt >= 0){
-	    while(decpt--){
+	    if(decpt == 0){
+			*bufp++ = '0';
+	    }
+	    else {
+		while(decpt--){
 			if(*nump != '\0'){
 				*bufp++ = *nump++;
 			}
 			else {
 				*bufp++ = '0';
 			}
+		}
 	    }
 	    if(*nump != '\0'){
 			*bufp++ = '.';
 			while(*nump != '\0'){
 				*bufp++ = *nump++;
 			}
 	    }
 	    *bufp++ = '\0';
--- a/pr/src/misc/prinit.c
+++ b/pr/src/misc/prinit.c
@@ -58,16 +58,18 @@ PRInt32 	_pr_intsOff;
 
 #endif /* _PR_LOCAL_THREADS_ONLY */
 
 /* Lock protecting all "termination" condition variables of all threads */
 PRLock *_pr_terminationCVLock;
 
 #endif /* !defined(_PR_PTHREADS) */
 
+PRLock *_pr_sleeplock;  /* used in PR_Sleep(), classic and pthreads */
+
 static void _PR_InitCallOnce(void);
 static void _PR_InitStuff(void);
 
 /************************************************************************/
 /**************************IDENTITY AND VERSIONING***********************/
 /************************************************************************/
 PR_IMPLEMENT(PRBool) PR_VersionCheck(const char *importedVersion)
 {
@@ -109,16 +111,19 @@ static void _PR_InitStuff()
     _PR_InitAtomic();
     _PR_InitLocks();
     _PR_InitSegs();
     _PR_InitStacks();
 	_PR_InitTPD();
     _PR_InitEnv();
     _PR_InitLayerCache();
 
+    _pr_sleeplock = PR_NewLock();
+    PR_ASSERT(NULL != _pr_sleeplock);
+
     _PR_InitThreads(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
     
 #ifdef WIN16
 	{
 	PRInt32 top;   /* artificial top of stack, win16 */
     _pr_top_of_task_stack = (char *) &top;
 	}
 #endif    
--- a/pr/src/misc/prnetdb.c
+++ b/pr/src/misc/prnetdb.c
@@ -73,17 +73,18 @@ static sigset_t timer_set;
 
 #if defined(SOLARIS) \
 	|| (defined(LINUX2_0) && defined(_REENTRANT) \
         && !(defined(__GLIBC__) && __GLIBC__ >= 2))
 #define _PR_HAVE_GETPROTO_R
 #define _PR_HAVE_GETPROTO_R_POINTER
 #endif
 
-#if defined(OSF1) || (defined(AIX) && defined(_THREAD_SAFE)) \
+#if defined(OSF1) \
+        || defined(AIX4_3) || (defined(AIX) && defined(_THREAD_SAFE)) \
 	|| (defined(HPUX10_10) && defined(_REENTRANT)) \
         || (defined(HPUX10_20) && defined(_REENTRANT))
 #define _PR_HAVE_GETPROTO_R
 #define _PR_HAVE_GETPROTO_R_INT
 #endif
 
 #if (defined(LINUX2_0) && defined(__GLIBC__) && __GLIBC__ >= 2)
 #define _PR_HAVE_GETPROTO_R
@@ -553,36 +554,28 @@ PR_IMPLEMENT(PRStatus) PR_GetProtoByNumb
     return rv;
 
 }
 
 PR_IMPLEMENT(PRUintn) PR_NetAddrSize(const PRNetAddr* addr)
 {
     PRUintn addrsize;
 
+    if (AF_INET == addr->raw.family)
+        addrsize = sizeof(addr->inet);
 #if defined(_PR_INET6)
-
-    if ((AF_INET == (0x00ff & addr->raw.family))
-    || (AF_INET == (0x00ff & ntohs(addr->raw.family))))
-        addrsize = sizeof(struct sockaddr_in);
-    else if ((AF_INET6 == (0x00ff & addr->raw.family))
-    || (AF_INET6 == (0x00ff & ntohs(addr->raw.family))))
-        addrsize = sizeof(struct sockaddr_in6);
+    else if (AF_INET6 == addr->raw.family)
+        addrsize = sizeof(addr->ipv6);
+#endif
+#if defined(XP_UNIX)
+    else if (AF_UNIX == addr->raw.family)
+        addrsize = sizeof(addr->local);
+#endif
     else addrsize = 0;
 
-#else /* defined(_PR_INET6) */
-    
-#if defined(XP_MAC)
-#pragma unused (addr)
-#endif
-
-    addrsize = sizeof(struct sockaddr_in);
-
-#endif  /* defined(_PR_INET6) */
-
     return addrsize;
 }  /* PR_NetAddrSize */
 
 PR_IMPLEMENT(PRIntn) PR_EnumerateHostEnt(
     PRIntn enumIndex, const PRHostEnt *hostEnt, PRUint16 port, PRNetAddr *address)
 {
     void *addr = hostEnt->h_addr_list[enumIndex++];
     memset(address, 0, sizeof(PRNetAddr));
--- a/pr/src/misc/prtime.c
+++ b/pr/src/misc/prtime.c
@@ -1137,17 +1137,17 @@ PR_ParseTimeString(
                           (rest[2] == 'd' || rest[2] == 'D'))
                         dotw = TT_WED;
                   break;
 
                 case '+': case '-':
                   {
                         const char *end;
                         int sign;
-                        if (zone_offset >= 0)
+                        if (zone_offset != -1)
                           {
                                 /* already got one... */
                                 rest++;
                                 break;
                           }
                         if (zone != TT_UNKNOWN && zone != TT_GMT)
                           {
                                 /* GMT+0300 is legal, but PST+0300 is not. */
@@ -1191,27 +1191,23 @@ PR_ParseTimeString(
                         const char *end = rest + 1;
                         while (*end >= '0' && *end <= '9')
                           end++;
 
                         /* end is now the first character after a range of digits. */
 
                         if (*end == ':')
                           {
-                                if (hour > 0 && min > 0) /* already got it */
+                                if (hour >= 0 && min >= 0) /* already got it */
                                   break;
 
                                 /* We have seen "[0-9]+:", so this is probably HH:MM[:SS] */
                                 if ((end - rest) > 2)
                                   /* it is [0-9][0-9][0-9]+: */
                                   break;
-                                else if (rest[1] != ':' &&
-                                                 rest[2] != ':')
-                                  /* it is not [0-9]: or [0-9][0-9]: */
-                                  break;
                                 else if ((end - rest) == 2)
                                   tmp_hour = ((rest[0]-'0')*10 +
                                                           (rest[1]-'0'));
                                 else
                                   tmp_hour = (rest[0]-'0');
 
                                 while (*rest && *rest != ':')
                                   rest++;
@@ -1336,36 +1332,41 @@ PR_ParseTimeString(
                                         (*s >= 'a' && *s <= 'z'))
                                   break;
 
                                 /* Ok, we parsed three 1-2 digit numbers, with / or -
                                    between them.  Now decide what the hell they are
                                    (DD/MM/YY or MM/DD/YY or YY/MM/DD.)
                                  */
 
-                                if (n1 > 70)        /* must be YY/MM/DD */
+                                if (n1 > 31 || n1 == 0)  /* must be YY/MM/DD */
                                   {
                                         if (n2 > 12) break;
                                         if (n3 > 31) break;
                                         year = n1;
-                                        if (year < 1900) year += 1900;
+                                        if (year < 70)
+                                            year += 2000;
+                                        else if (year < 100)
+                                            year += 1900;
                                         month = (TIME_TOKEN)(n2 + ((int)TT_JAN) - 1);
                                         date = n3;
                                         rest = s;
                                         break;
                                   }
 
-                                if (n3 < 70 ||                /* before epoch - can't represent it. */
-                                        (n1 > 12 && n2 > 12))        /* illegal */
+                                if (n1 > 12 && n2 > 12)  /* illegal */
                                   {
                                         rest = s;
                                         break;
                                   }
 
-                                if (n3 < 1900) n3 += 1900;
+                                if (n3 < 70)
+                                    n3 += 2000;
+                                else if (n3 < 100)
+                                    n3 += 1900;
 
                                 if (n1 > 12)  /* must be DD/MM/YY */
                                   {
                                         date = n1;
                                         month = (TIME_TOKEN)(n2 + ((int)TT_JAN) - 1);
                                         year = n3;
                                   }
                                 else                  /* assume MM/DD/YY */
@@ -1622,17 +1623,17 @@ PR_FormatTime(char *buf, int buflen, cha
     a.tm_isdst = tm->tm_params.tp_dst_offset ? 1 : 0;
 
 /*
  * On SunOS 4, struct tm has two additional fields: tm_zone
  * and tm_gmtoff.  The following code attempts to obtain values for
  * these two fields.
  */
 
-#if defined(SUNOS4) || defined(MACLINUX) || (__GLIBC__ >= 2)
+#if defined(SUNOS4) || defined(MKLINUX) || (__GLIBC__ >= 2)
     if (mktime(&a) == -1) {
         PR_snprintf(buf, buflen, "can't get timezone");
         return 0;
     }
 #endif
 
     return strftime(buf, buflen, fmt, &a);
 }
--- a/pr/src/pthreads/ptio.c
+++ b/pr/src/pthreads/ptio.c
@@ -19,42 +19,33 @@
 /*
 ** File:   ptio.c
 ** Descritpion:  Implemenation of I/O methods for pthreads
 ** Exports:   ptio.h
 */
 
 #if defined(_PR_PTHREADS)
 
+#include <pthread.h>
 #include <string.h>  /* for memset() */
 #include <sys/types.h>
 #include <dirent.h>
-
-/*
- * XXX: On Linux 2.0.27 sched.h uses this _P macro that seems to be undefined.
- * I suspect that it is a typo (should be __P).
- */
-#if defined(LINUX)
-#define _P(x) __P(x)
-#endif
-#include <pthread.h>
-
 #include <fcntl.h>
 #include <unistd.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/uio.h>
 #include <sys/file.h>
 #include <sys/ioctl.h>
 #ifdef SOLARIS
 #include <sys/filio.h>  /* to pick up FIONREAD */
 #endif
 /* Linux (except glibc) and FreeBSD don't have poll */
 #if !(defined(LINUX) && !(defined(__GLIBC__) && __GLIBC__ >= 2)) \
-	&& !defined(FREEBSD)
+    && !defined(FREEBSD)
 #include <poll.h>
 #endif
 #ifdef AIX
 /* To pick up sysconf() */
 #include <unistd.h>
 #else
 /* To pick up getrlimit() etc. */
 #include <sys/time.h>
@@ -66,17 +57,17 @@
 /* On Alpha Linux, these are already defined in sys/socket.h */
 #if !(defined(LINUX) && defined(__alpha))
 #include <netinet/tcp.h>  /* TCP_NODELAY, TCP_MAXSEG */
 #endif
 
 #if defined(SOLARIS)
 #define _PRSockOptVal_t char *
 #elif defined(IRIX) || defined(OSF1) || defined(AIX) || defined(HPUX) \
-	|| defined(LINUX) || defined(FREEBSD)
+    || defined(LINUX) || defined(FREEBSD)
 #define _PRSockOptVal_t void *
 #else
 #error "Cannot determine architecture"
 #endif
 
 #if (defined(HPUX) && !defined(HPUX10_30) && !defined(HPUX11))
 #define _PRSelectFdSetArg_t int *
 #elif defined(AIX4_1)
@@ -85,26 +76,59 @@
     || defined(OSF1) || defined(SOLARIS) \
     || defined(HPUX10_30) || defined(HPUX11) || defined(LINUX) \
     || defined(FREEBSD)
 #define _PRSelectFdSetArg_t fd_set *
 #else
 #error "Cannot determine architecture"
 #endif
 
-static PRStatus pt_InitIOContinuation(void);
 static PRFileDesc *pt_SetMethods(PRIntn osfd, PRDescType type);
 
 static pthread_condattr_t _pt_cvar_attr;
 static PRLock *_pr_flock_lock;  /* For PR_LockFile() etc. */
 static PRLock *_pr_rename_lock;  /* For PR_Rename() */
 
 extern struct _PT_Bookeeping pt_book;  /* defined in ptthread.c */
 extern PRIntn pt_schedpriv;  /* defined in ptthread.c */
 
+/**************************************************************************/
+
+/* These two functions are only used in assertions. */
+#if defined(DEBUG)
+
+static PRBool IsValidNetAddr(const PRNetAddr *addr)
+{
+    if ((addr != NULL)
+            && (addr->raw.family != AF_UNIX)
+#ifdef _PR_INET6
+            && (addr->raw.family != AF_INET6)
+#endif
+            && (addr->raw.family != AF_INET)) {
+        return PR_FALSE;
+    }
+    return PR_TRUE;
+}
+
+static PRBool IsValidNetAddrLen(const PRNetAddr *addr, PRInt32 addr_len)
+{
+    /*
+     * The definition of the length of a Unix domain socket address
+     * is not uniform, so we don't check it.
+     */
+    if ((addr != NULL)
+            && (addr->raw.family != AF_UNIX)
+            && (PR_NETADDR_SIZE(addr) != addr_len)) {
+        return PR_FALSE;
+    }
+    return PR_TRUE;
+}
+
+#endif /* DEBUG */
+
 /*****************************************************************************/
 /*****************************************************************************/
 /************************** File descriptor caching **************************/
 /*****************************************************************************/
 /*****************************************************************************/
 
 typedef struct _PT_Fd_Cache
 {
@@ -193,31 +217,31 @@ static void pt_Putfd(PRFileDesc *fd)
  */
 #define PT_DEFAULT_POLL_MSEC 100
 
 /*
  * Latest POSIX defines this type as socklen_t.  It may also be
  * size_t or int.
  */
 #if (defined(LINUX) && defined(__GLIBC__) && __GLIBC__ >= 2 \
-	&& !defined(__alpha))
+    && !defined(__alpha))
 typedef socklen_t pt_SockLen;
 #elif defined(AIX) || (defined(LINUX) && defined(__alpha))
 typedef PRSize pt_SockLen;
 #else
 typedef PRIntn pt_SockLen;
 #endif
 
 typedef struct pt_Continuation pt_Continuation;
 typedef PRBool (*ContinuationFn)(pt_Continuation *op, PRInt16 revents);
 
 typedef enum pr_ContuationStatus
 {
-    pt_continuation_sumbitted,
-    pt_continuation_inprogress,
+    pt_continuation_pending,
+    pt_continuation_recycle,
     pt_continuation_abort,
     pt_continuation_done
 } pr_ContuationStatus;
 
 struct pt_Continuation
 {
     /* These objects are linked in ascending timeout order */
     pt_Continuation *next, *prev;           /* self linked list of these things */
@@ -256,56 +280,103 @@ struct pt_Continuation
     ** The representation and notification of the results of the operation.
     ** These function can either return an int return code or a pointer to
     ** some object.
     */
     union { PRSize code; void *object; } result;
 
     PRIntn syserrno;                        /* in case it failed, why (errno) */
     pr_ContuationStatus status;             /* the status of the operation */
-    PRCondVar complete;                     /* to notify the initiating thread */
+    PRCondVar *complete;                    /* to notify the initiating thread */
 };
 
 static struct pt_TimedQueue
 {
-    PRCallOnceType once;                    /* controls the initialization
-                                             * of this structure */
     PRLock *ml;                             /* a little protection */
     PRThread *thread;                       /* internal thread's identification */
-    PRCondVar *new_op;                      /* new operation supplied */
     PRUintn op_count;                       /* number of operations in the list */
     pt_Continuation *head, *tail;           /* head/tail of list of operations */
 
     pt_Continuation *op;                    /* timed operation furthest in future */
-    PRBool exitFlag;                        /* a Boolean flag for signaling the
-                                             * continuation thread to exit */
 } pt_tq;
 
 #if defined(DEBUG)
-static struct pt_debug_s
+
+PTDebug pt_debug;  /* this is shared between several modules */
+
+PR_IMPLEMENT(PTDebug) PT_GetStats() { return pt_debug; }
+
+PR_IMPLEMENT(void) PT_FPrintStats(PRFileDesc *debug_out, const char *msg)
 {
-    PRUintn predictionsFoiled;
-    PRUintn pollingListMax;
-    PRUintn continuationsServed;
-} pt_debug;
+    char buffer[100];
+    PRExplodedTime tod;
+    PRInt64 elapsed, aMil;
+    PTDebug stats = PT_GetStats();  /* a copy */
+    PR_ExplodeTime(stats.timeStarted, PR_LocalTimeParameters, &tod);
+    (void)PR_FormatTime(buffer, sizeof(buffer), "%T", &tod);
+
+    LL_SUB(elapsed, PR_Now(), stats.timeStarted);
+    LL_I2L(aMil, 1000000);
+    LL_DIV(elapsed, elapsed, aMil);
+    
+    if (NULL != msg) PR_fprintf(debug_out, "%s", msg);
+    PR_fprintf(
+        debug_out, "\tstarted: %s[%lld]\n", buffer, elapsed);
+    PR_fprintf(
+        debug_out, "\tmissed predictions: %u\n", stats.predictionsFoiled);
+    PR_fprintf(
+        debug_out, "\tpollingList max: %u\n", stats.pollingListMax);
+    PR_fprintf(
+        debug_out, "\tcontinuations served: %u\n", stats.continuationsServed);
+    PR_fprintf(
+        debug_out, "\trecycles needed: %u\n", stats.recyclesNeeded);
+    PR_fprintf(
+        debug_out, "\tquiescent IO: %u\n", stats.quiescentIO);
+    PR_fprintf(
+        debug_out, "\tlocks [created: %u, destroyed: %u]\n",
+        stats.locks_created, stats.locks_destroyed);
+    PR_fprintf(
+        debug_out, "\tlocks [acquired: %u, released: %u]\n",
+        stats.locks_acquired, stats.locks_released);
+    PR_fprintf(
+        debug_out, "\tcvars [created: %u, destroyed: %u]\n",
+        stats.cvars_created, stats.cvars_destroyed);
+    PR_fprintf(
+        debug_out, "\tcvars [notified: %u, delayed_delete: %u]\n",
+        stats.cvars_notified, stats.delayed_cv_deletes);
+}  /* PT_FPrintStats */
+
 #endif  /* DEBUG */
 
 /*
  * The following two functions, pt_InsertTimedInternal and
  * pt_FinishTimedInternal, are always called with the pt_tq.ml
  * lock held.  The "internal" in the functions' names come from
  * the Mesa programming language.  Internal functions are always
  * called from inside a monitor.
  */
 
 static void pt_InsertTimedInternal(pt_Continuation *op)
 {
     pt_Continuation *t_op = NULL;
     PRIntervalTime now = PR_IntervalNow();
 
+#if defined(DEBUG)
+    {
+        PRIntn count;
+        pt_Continuation *tmp;
+        PR_ASSERT((pt_tq.head == NULL) == (pt_tq.tail == NULL));
+        PR_ASSERT((pt_tq.head == NULL) == (pt_tq.op_count == 0));
+        for (tmp = pt_tq.head, count = 0; tmp != NULL; tmp = tmp->next) count += 1;
+        PR_ASSERT(count == pt_tq.op_count);
+        for (tmp = pt_tq.tail, count = 0; tmp != NULL; tmp = tmp->prev) count += 1;
+        PR_ASSERT(count == pt_tq.op_count);
+    }
+#endif /* defined(DEBUG) */
+
     /*
      * If this element operation isn't timed, it gets queued at the
      * end of the list (just after pt_tq.tail) and we're
      * finishd early.
      */
     if (PR_INTERVAL_NO_TIMEOUT == op->timeout)
     {
         t_op = pt_tq.tail;  /* put it at the end */
@@ -359,17 +430,17 @@ done:
      *
      * We need to set up the 'next' and 'prev' pointers of 'op'
      * correctly before inserting 'op' into the queue.  Also, we insert
      * 'op' by updating pt_tq.head or op->prev->next first, and then
      * updating op->next->prev.  We want to make sure that the 'next'
      * pointers are linked up correctly at all times so that we can
      * traverse the queue by starting with pt_tq.head and following
      * the 'next' pointers, without having to acquire the pt_tq.ml lock.
-     * (We do that in ContinuationThread.)  We traverse the 'prev'
+     * (we do that in pt_ContinuationThreadInternal).  We traverse the 'prev'
      * pointers only in this function, which is called with the lock held.
      *
      * Similar care is taken in pt_FinishTimedInternal where we remove
      * an op from the queue.
      */
     if (NULL == t_op)
     {
         op->prev = NULL;
@@ -387,30 +458,82 @@ done:
         if (NULL != op->next)
             op->next->prev = op;
         if (t_op == pt_tq.tail)
             pt_tq.tail = op;
     }
 
     pt_tq.op_count += 1;
 
+#if defined(DEBUG)
+    {
+        PRIntn count;
+        pt_Continuation *tmp;
+        PR_ASSERT(pt_tq.head != NULL);
+        PR_ASSERT(pt_tq.tail != NULL);
+        PR_ASSERT(pt_tq.op_count != 0);
+        PR_ASSERT(pt_tq.head->prev == NULL);
+        PR_ASSERT(pt_tq.tail->next == NULL);
+        if (pt_tq.op_count > 1)
+        {
+            PR_ASSERT(pt_tq.head->next != NULL);
+            PR_ASSERT(pt_tq.tail->prev != NULL);
+        }
+        else
+        {
+            PR_ASSERT(pt_tq.head->next == NULL);
+            PR_ASSERT(pt_tq.tail->prev == NULL);
+        }
+        for (tmp = pt_tq.head, count = 0; tmp != NULL; tmp = tmp->next) count += 1;
+        PR_ASSERT(count == pt_tq.op_count);
+        for (tmp = pt_tq.tail, count = 0; tmp != NULL; tmp = tmp->prev) count += 1;
+        PR_ASSERT(count == pt_tq.op_count);
+    }
+#endif /* defined(DEBUG) */
+
 }  /* pt_InsertTimedInternal */
 
 /*
  * function: pt_FinishTimedInternal
  *
  * Takes the finished operation out of the timed queue. It
  * notifies the initiating thread that the opertions is
  * complete and returns to the caller the value of the next
  * operation in the list (or NULL).
  */
 static pt_Continuation *pt_FinishTimedInternal(pt_Continuation *op)
 {
     pt_Continuation *next;
 
+#if defined(DEBUG)
+    {
+        PRIntn count;
+        pt_Continuation *tmp;
+        PR_ASSERT(pt_tq.head != NULL);
+        PR_ASSERT(pt_tq.tail != NULL);
+        PR_ASSERT(pt_tq.op_count != 0);
+        PR_ASSERT(pt_tq.head->prev == NULL);
+        PR_ASSERT(pt_tq.tail->next == NULL);
+        if (pt_tq.op_count > 1)
+        {
+            PR_ASSERT(pt_tq.head->next != NULL);
+            PR_ASSERT(pt_tq.tail->prev != NULL);
+        }
+        else
+        {
+            PR_ASSERT(pt_tq.head->next == NULL);
+            PR_ASSERT(pt_tq.tail->prev == NULL);
+        }
+        for (tmp = pt_tq.head, count = 0; tmp != NULL; tmp = tmp->next) count += 1;
+        PR_ASSERT(count == pt_tq.op_count);
+        for (tmp = pt_tq.tail, count = 0; tmp != NULL; tmp = tmp->prev) count += 1;
+        PR_ASSERT(count == pt_tq.op_count);
+    }
+#endif /* defined(DEBUG) */
+
     /* remove this one from the list */
     if (NULL == op->prev) pt_tq.head = op->next;
     else op->prev->next = op->next;
     if (NULL == op->next) pt_tq.tail = op->prev;
     else op->next->prev = op->prev;
 
     /* did we happen to hit the timed op? */
     if (op == pt_tq.op) pt_tq.op = op->prev;
@@ -419,143 +542,175 @@ static pt_Continuation *pt_FinishTimedIn
     op->next = op->prev = NULL;
     op->status = pt_continuation_done;
 
     pt_tq.op_count -= 1;
 
 #if defined(DEBUG)
     pt_debug.continuationsServed += 1;
 #endif
-    PR_NotifyCondVar(&op->complete);
+    PR_NotifyCondVar(op->complete);
+
+#if defined(DEBUG)
+    {
+        PRIntn count;
+        pt_Continuation *tmp;
+        PR_ASSERT((pt_tq.head == NULL) == (pt_tq.tail == NULL));
+        PR_ASSERT((pt_tq.head == NULL) == (pt_tq.op_count == 0));
+        for (tmp = pt_tq.head, count = 0; tmp != NULL; tmp = tmp->next) count += 1;
+        PR_ASSERT(count == pt_tq.op_count);
+        for (tmp = pt_tq.tail, count = 0; tmp != NULL; tmp = tmp->prev) count += 1;
+        PR_ASSERT(count == pt_tq.op_count);
+    }
+#endif /* defined(DEBUG) */
 
     return next;
 }  /* pt_FinishTimedInternal */
 
-static void ContinuationThread(void *arg)
+static void pt_ContinuationThreadInternal(pt_Continuation *my_op)
 {
     /* initialization */
     PRInt32 msecs, mx_poll_ticks;
-    struct pollfd *pollingList = 0;         /* list built for polling */
+    PRThreadPriority priority;              /* used to save caller's prio */
     PRIntn pollingListUsed;                 /* # entries used in the list */
     PRIntn pollingListNeeded;               /* # entries needed this time */
-    PRIntn pollingSlotsAllocated = 0;       /* # entries available in list */
+    static struct pollfd *pollingList = 0;  /* list built for polling */
+    static PRIntn pollingSlotsAllocated = 0;/* # entries available in list */
     
+    PR_Unlock(pt_tq.ml);  /* don't need that silly lock for a bit */
+
+    priority = PR_GetThreadPriority(pt_tq.thread);
+    PR_SetThreadPriority(pt_tq.thread, PR_PRIORITY_HIGH);
+
     mx_poll_ticks = (PRInt32)PR_MillisecondsToInterval(PT_DEFAULT_POLL_MSEC);
 
     /* do some real work */
     while (PR_TRUE)
     {
         PRIntn rv;
         PRInt32 timeout;
         PRIntn pollIndex;
         PRIntervalTime now;
-        pt_Continuation *op;
-
-        PR_Lock(pt_tq.ml);
-        while (!pt_tq.exitFlag && (NULL == pt_tq.head))
-            PR_WaitCondVar(pt_tq.new_op, PR_INTERVAL_NO_TIMEOUT);
+        pt_Continuation *op, *next_op;
+
+        PR_ASSERT(NULL != pt_tq.head);
+
         pollingListNeeded = pt_tq.op_count;
-        PR_Unlock(pt_tq.ml);
-
-        /* Okay. We're history */
-        if (pt_tq.exitFlag) break;
 
     /*
      * We are not holding the pt_tq.ml lock now, so more items may
      * get added to pt_tq during this window of time.  We hope
      * that 10 more spaces in the polling list should be enough.
      */
         pollingListNeeded += 10;
         if (pollingListNeeded > pollingSlotsAllocated)
         {
             if (NULL != pollingList) PR_DELETE(pollingList);
-            pollingList = (struct pollfd*)PR_Malloc(
+            pollingList = (struct pollfd*)PR_MALLOC(
                 pollingListNeeded * sizeof(struct pollfd));
             PR_ASSERT(NULL != pollingList);
             pollingSlotsAllocated = pollingListNeeded;
         }
 
 #if defined(DEBUG)
         if (pollingListNeeded > pt_debug.pollingListMax)
             pt_debug.pollingListMax = pollingListNeeded;
 #endif
 
         /*
+        ** This is interrupt processing. If this thread was interrupted,
+        ** the thread state will have the PT_THREAD_ABORTED bit set. This
+        ** overrides good completions as well as timeouts.
+        **
+        ** BTW, it does no good to hold the lock here. This lock doesn't
+        ** protect the thread structure in any way. Testing the bit and
+        ** (perhaps) resetting it are safe 'cause it's the only modifiable
+        ** bit in that word.
+        */
+        if (pt_tq.thread->state & PT_THREAD_ABORTED)
+        {
+            my_op->status = pt_continuation_abort;
+            pt_tq.thread->state &= ~PT_THREAD_ABORTED;
+        }
+
+
+        /*
          * Build up a polling list.
          * This list is sorted on time. Operations that have been
          * interrupted are completed and not included in the list.
          * There is an assertion that the operation is in progress.
          */
         pollingListUsed = 0;
         PR_Lock(pt_tq.ml);
 
         for (op = pt_tq.head; NULL != op;)
         {
             if (pt_continuation_abort == op->status)
             {
                 op->result.code = -1;
                 op->syserrno = EINTR;
-                op = pt_FinishTimedInternal(op);
+                next_op = pt_FinishTimedInternal(op);
+                if (op == my_op) goto recycle;
+                else op = next_op;
+                PR_ASSERT(NULL != pt_tq.head);
             }
             else
             {
-                if (pollingListUsed == pollingSlotsAllocated) break;
-                PR_ASSERT(pt_continuation_done != op->status);
-                op->status = pt_continuation_inprogress;
+                op->status = pt_continuation_pending;
+                if (pollingListUsed >= pollingSlotsAllocated)
+                {
+#if defined(DEBUG)
+                    pt_debug.predictionsFoiled += 1;
+#endif
+                    break;
+                }
                 pollingList[pollingListUsed].revents = 0;
                 pollingList[pollingListUsed].fd = op->arg1.osfd;
                 pollingList[pollingListUsed].events = op->event;
                 pollingListUsed += 1;
                 op = op->next;
             }
         }
 
-        PR_Unlock(pt_tq.ml);
-
-        /*
-         * If 'op' isn't NULL at this point, then we didn't get to
-         * the end of the list. That means that more items got added
-         * to the list than we anticipated. So, forget this iteration,
-         * go around the horn again.
-         * One would hope this doesn't happen all that often.
-         */
-        if (NULL != op)
-        {
-#if defined(DEBUG)
-            pt_debug.predictionsFoiled += 1;  /* keep track */
-#endif
-            continue;  /* make it rethink things */
-        }
-
-        if (NULL == pt_tq.head) continue;  /* did list evaporate? */
-
         /*
          * We don't want to wait forever on this poll. So keep
          * the interval down. The operations, if they are timed,
          * still have to timeout, while those that are not timed
          * should persist forever. But they may be aborted. That's
          * what this anxiety is all about.
          */
         if (PR_INTERVAL_NO_TIMEOUT == pt_tq.head->timeout)
             msecs = PT_DEFAULT_POLL_MSEC;
         else
         {
             timeout = pt_tq.head->absolute - PR_IntervalNow();
             if (timeout <= 0) msecs = 0;  /* already timed out */
             else if (timeout >= mx_poll_ticks) msecs = PT_DEFAULT_POLL_MSEC;
             else msecs = (PRInt32)PR_IntervalToMilliseconds(timeout);
-    }
+        }
+
+        PR_Unlock(pt_tq.ml);
+
+        /*
+         * If 'op' isn't NULL at this point, then we didn't get to
+         * the end of the list. That means that more items got added
+         * to the list than we anticipated. So, forget this iteration,
+         * go around the horn again.
+         * One would hope this doesn't happen all that often.
+         */
+        if (NULL != op) continue;  /* make it rethink things */
 
         rv = poll(pollingList, pollingListUsed, msecs);
         
         if ((-1 == rv) && ((errno == EINTR) || (errno == EAGAIN)))
             continue; /* go around the loop again */
 
-    if (rv > 0)
-    {
+        PR_Lock(pt_tq.ml);
+        if (rv > 0)
+        {
             /*
              * poll() says that something in our list is ready for some more
              * action. Find it, load up the operation and see what happens.
              */
 
             /*
              * This may work out okay. The rule is that only this thread,
              * the continuation thread, can remove elements from the list.
@@ -584,125 +739,163 @@ static void ContinuationThread(void *arg
                     }
 
                     /*
                      * Skip over all those not in progress. They'll be
                      * pruned next time we build a polling list. Call
                      * the continuation function. If it reports completion,
                      * finish off the operation.
                      */
-                    if ((pt_continuation_inprogress == op->status)
+                    if ((pt_continuation_pending == op->status)
                     && (op->function(op, pollingList[pollIndex].revents)))
                     {
-                        PR_Lock(pt_tq.ml);
-                        op = pt_FinishTimedInternal(op);
-                        PR_Unlock(pt_tq.ml);
+                        next_op = pt_FinishTimedInternal(op);
+                        if (op == my_op) goto recycle;
+                        else op = next_op;
                     }
                     continue;
                 }
                 op = op->next;  /* progress to next operation */
             }
         }
 
         /*
          * This is timeout processing. It is done after checking
          * for good completions. Those that just made it under the
          * wire are lucky, but none the less, valid.
          */
-        if ((NULL != pt_tq.head)
+        now = PR_IntervalNow();
+        while ((NULL != pt_tq.head)
         && (PR_INTERVAL_NO_TIMEOUT != pt_tq.head->timeout))
         {
-            now = PR_IntervalNow();
-            while ((PRInt32)(pt_tq.head->absolute - now) <= 0)
-            {
-                /* 
-                 * The leading element of the timed queue has timed
-                 * out. Get rid of it. In any case go around the
-                 * loop again, computing the polling list, checking
-                 * for interrupted operations.
-                 */
-
-                PR_Lock(pt_tq.ml);
-                pt_tq.head->result.code = -1;
-                pt_tq.head->syserrno = ETIMEDOUT;
-                (void)pt_FinishTimedInternal(pt_tq.head);
-                PR_Unlock(pt_tq.ml);
-                if ((NULL == pt_tq.head)
-                || (PR_INTERVAL_NO_TIMEOUT == pt_tq.head->timeout))
-                    break;
-            }
+            op = pt_tq.head;  /* get a copy of this before finishing it */
+            if ((PRInt32)(op->absolute - now) > 0) break;
+            /* 
+             * The head element of the timed queue has timed out. Record
+             * the reason for completion and take it out of the list.
+             */
+            op->result.code = -1;
+            op->syserrno = ETIMEDOUT;
+            (void)pt_FinishTimedInternal(op);
+
+            /* 
+             * If it's 'my_op' then we have to switch threads. Exit w/o
+             * finishing the scan. The scan will be completed when another
+             * thread calls in acting as the continuation thread. 
+             */
+            if (op == my_op) goto recycle;  /* exit w/o unlocking */
         }
+        PR_Unlock(pt_tq.ml);  /* unlock and go back around again */
     }
-    if (NULL != pollingList) PR_DELETE(pollingList);
-}  /* ContinuationThread */
+
+recycle:
+    /*
+    ** Recycling the continuation thread.
+    **
+    ** The thread we were using for I/O continuations just completed 
+    ** the I/O it submitted. It has to return to it's caller. We need
+    ** another thread to act in the continuation role. We can do that
+    ** by taking any operation off the timed queue, setting its state
+    ** to 'recycle' and notifying the condition.
+    **
+    ** Selecting a likely thread seems like magic. I'm going to try
+    ** using one that has the longest (or no) timeout, pt_tq.tail.
+    ** If that slot's empty, then there's no outstanding I/O and we
+    ** don't need a thread at all.
+    **
+    ** BTW, we're locked right now, and we'll be returning with the
+    ** the lock held as well. Seems odd, doesn't it?
+    */
+
+    PR_SetThreadPriority(pt_tq.thread, priority);  /* reset back to caller's */
+
+    PR_ASSERT((NULL == pt_tq.head) == (0 == pt_tq.op_count));
+    PR_ASSERT((NULL == pt_tq.head) == (NULL == pt_tq.tail));
+    PR_ASSERT(pt_continuation_done == my_op->status);
+    
+    if (NULL != pt_tq.tail)
+    {
+        pt_tq.tail->status = pt_continuation_recycle;
+        PR_NotifyCondVar(pt_tq.tail->complete);
+#if defined(DEBUG)
+        pt_debug.recyclesNeeded += 1;
+#endif
+    }
+#if defined(DEBUG)
+     else pt_debug.quiescentIO += 1;
+#endif
+
+}  /* pt_ContinuationThreadInternal */
 
 static PRIntn pt_Continue(pt_Continuation *op)
 {
     PRIntn rc;
     PRStatus rv;
-#ifdef DEBUG
-    PRBool waitcv_interrupted = PR_FALSE;
-#endif /* DEBUG */
-
-    PR_CallOnce(&pt_tq.once, pt_InitIOContinuation);
-
+    PRThread *self = PR_GetCurrentThread();
+    /* lazy allocation of the thread's cv */
+    if (NULL == self->io_cv)
+        self->io_cv = PR_NewCondVar(pt_tq.ml);
     /* Finish filling in the blank slots */
-    /* op->complete = PR_NewCondVar(pt_tq.ml); */
-    op->complete.lock = pt_tq.ml;
-    rc = PTHREAD_COND_INIT(op->complete.cv, _pt_cvar_attr);  PR_ASSERT(0 == rc);
-    op->status = pt_continuation_sumbitted;
+    op->complete = self->io_cv;
+    op->status = pt_continuation_pending;  /* set default value */
     PR_Lock(pt_tq.ml);  /* we provide the locking */
 
     pt_InsertTimedInternal(op);  /* insert in the structure */
 
-    PR_NotifyCondVar(pt_tq.new_op);  /* notify the continuation thread */
-
-    while (pt_continuation_done != op->status)  /* wait for completion */
+    /*
+    ** At this point, we try to decide whether there is a continuation
+    ** thread, or whether we should assign this one to serve in that role.
+    */
+    do
     {
-        rv = PR_WaitCondVar(&op->complete, PR_INTERVAL_NO_TIMEOUT);
-        /*
-         * If we get interrupted, we set state the continuation thread will
-         * see and allow it to finish the I/O operation w/ error. That way
-         * the rule that only the continuation thread is removing elements
-         * from the list is still valid.
-         *
-         * Don't call interrupt on the continuation thread. That'll just
-         * irritate him. He's cycling around at least every mx_poll_ticks
-         * anyhow and should notice the request in there.
-         */
-        if ((PR_FAILURE == rv)
-        && (PR_PENDING_INTERRUPT_ERROR == PR_GetError()))
+        if (NULL == pt_tq.thread)
+        {
+            /*
+            ** We're the one. Call the processing function with the lock
+            ** held. It will return with it held as well, though there
+            ** will certainly be times within the function when it gets
+            ** released.
+            */
+            pt_tq.thread = PR_GetCurrentThread();  /* I'm taking control */
+            pt_ContinuationThreadInternal(op); /* go slash and burn */
+            PR_ASSERT(pt_continuation_done == op->status);
+            pt_tq.thread = NULL;  /* I'm abdicating my rule */
+        }
+        else
         {
-#ifdef DEBUG
-            waitcv_interrupted = PR_TRUE;
-#endif /* DEBUG */
-            if (pt_continuation_done != op->status)
+            rv = PR_WaitCondVar(op->complete, PR_INTERVAL_NO_TIMEOUT);
+            /*
+             * If we get interrupted, we set state the continuation thread will
+             * see and allow it to finish the I/O operation w/ error. That way
+             * the rule that only the continuation thread is removing elements
+             * from the list is still valid.
+             *
+             * Don't call interrupt on the continuation thread. That'll just
+             * irritate him. He's cycling around at least every mx_poll_ticks
+             * anyhow and should notice the request in there. When he does
+             * notice, this operation will be finished and the op's status
+             * marked as pt_continuation_done.
+             */
+            if ((PR_FAILURE == rv)  /* the wait failed */
+            && (pt_continuation_pending == op->status)  /* but the op hasn't */
+            && (PR_PENDING_INTERRUPT_ERROR == PR_GetError()))  /* was interrupted */
             {
-                /* tell the continuation thread to abort the operation */
-                op->status = pt_continuation_abort;
+                op->status = pt_continuation_abort;  /* go around the loop again */
             }
-            else
-            {
-                op->result.code = -1;
-                op->syserrno = EINTR;
-            }
+            /*
+             * If we're to recycle, continue within this loop. This will
+             * cause this thread to be come the continuation thread.
+             */
+
         }
-    }
-
-    PR_Unlock(pt_tq.ml);  /* we provide the locking */
-    rc = pthread_cond_destroy(&op->complete.cv); PR_ASSERT(0 == rc);
-
-    /* make sure that the continuation thread did abort the operation */
-#ifdef DEBUG
-    if (PR_TRUE == waitcv_interrupted)
-    {
-        PR_ASSERT(-1 == op->result.code);
-        PR_ASSERT(EINTR == op->syserrno);
-    }
-#endif /* DEBUG */
+    } while (pt_continuation_done != op->status);
+
+
+    PR_Unlock(pt_tq.ml);  /* we provided the locking */
+
     return op->result.code;  /* and the primary answer */
 }  /* pt_Continue */
 
 /*****************************************************************************/
 /*********************** specific continuation functions *********************/
 /*****************************************************************************/
 static PRBool pt_connect_cont(pt_Continuation *op, PRInt16 revents)
 {
@@ -815,24 +1008,23 @@ static PRBool pt_writev_cont(pt_Continua
 {
     /*
      * Same rules as write, but continuing seems to be a bit more
      * complicated. As the number of bytes sent grows, we have to
      * redefine the vector we're pointing at. We might have to
      * modify an individual vector parms or we might have to eliminate
      * a pair altogether.
      */
-    PRIntn bytes = writev(
-        op->arg1.osfd, (struct iovec*)op->arg2.buffer, op->arg3.amount);
+    struct iovec *iov = (struct iovec*)op->arg2.buffer;
+    PRIntn bytes = writev(op->arg1.osfd, iov, op->arg3.amount);
     op->syserrno = errno;
     if (bytes > 0)  /* this is progress */
     {
         PRIntn iov_index;
-        struct iovec *iov = (struct iovec*)op->arg2.buffer;
-    op->result.code += bytes;  /* accumulate the number sent */
+        op->result.code += bytes;  /* accumulate the number sent */
         for (iov_index = 0; iov_index < op->arg3.amount; ++iov_index)
         {
             /* how much progress did we make in the i/o vector? */
             if (bytes < iov[iov_index].iov_len)
             {
                 /* this element's not done yet */
                 char **bp = (char**)&(iov[iov_index].iov_base);
                 iov[iov_index].iov_len -= bytes;  /* there's that much left */
@@ -916,119 +1108,48 @@ static PRBool pt_hpux_transmitfile_cont(
         op->nbytes_to_send -= count;
         return PR_FALSE;
     }
 
     return PR_TRUE;
 }
 #endif  /* HPUX11 */
 
-#if !defined(PT_NO_ATFORK)
-
-static void pt_BeforeFork()
-{
-    PRStatus rv;
-    PRThread *thred = pt_tq.thread;
-
-    /*
-     * We shut down the continuation thread cleanly only if there are
-     * no other threads in the process when fork() is called.
-     * If there are other threads, they won't be duplicated in the child
-     * process.  Then the child process may already be unclean, so there
-     * is no point for us to try to be clean.
-     */
-
-    if ((NULL != thred) && (2 == pt_book.user + pt_book.system))
-    {
-        /* pt_tq should be empty */
-        PR_ASSERT((0 == pt_tq.op_count)
-            && (NULL == pt_tq.head)
-            && (NULL == pt_tq.tail)
-            && (NULL == pt_tq.op));
-        pt_tq.exitFlag = PR_TRUE;
-        rv = PR_Interrupt(thred);
-        PR_ASSERT(PR_SUCCESS == rv);
-        rv = PR_JoinThread(thred);
-        PR_ASSERT(PR_SUCCESS == rv);
-        pt_tq.exitFlag = PR_FALSE;
-        /* Indicates that the continuation thread is shut down cleanly */
-        pt_tq.thread = NULL;
-        memset(&pt_tq.once, 0, sizeof(pt_tq.once));
-        PR_ASSERT(1 == pt_book.user + pt_book.system);
-    }
-}  /* pt_BeforeFork */
-
-static void pt_AfterForkParent(void)
-{
-}  /* pt_AfterForkParent */
-
-static void pt_AfterForkChild(void)
-{
-    /*
-     * pt_tq may be in a corrupted state if the continuation thread
-     * existed and was not terminated cleanly before fork.  In this
-     * case, we expect the child process to call exec immediately.
-     */
-}  /* pt_AfterForkChild */
-
-#endif  /* PT_NO_ATFORK */
-
 void _PR_InitIO()
 {
+    PRIntn rv;
     _pr_stdin = pt_SetMethods(0, PR_DESC_FILE);
     _pr_stdout = pt_SetMethods(1, PR_DESC_FILE);
     _pr_stderr = pt_SetMethods(2, PR_DESC_FILE);
 
     PR_ASSERT(_pr_stdin && _pr_stdout && _pr_stderr);
 
+    pt_tq.ml = PR_NewLock();
+    PR_ASSERT(NULL != pt_tq.ml);
+
+#if defined(DEBUG)
+    memset(&pt_debug, 0, sizeof(PTDebug));
+    pt_debug.timeStarted = PR_Now();
+#endif
+
+    rv = PTHREAD_CONDATTR_INIT(&_pt_cvar_attr); 
+    PR_ASSERT(0 == rv);
+
+    pt_tq.thread = NULL;
+
     _pr_flock_lock = PR_NewLock();
     PR_ASSERT(NULL != _pr_flock_lock);
     _pr_rename_lock = PR_NewLock();
     PR_ASSERT(NULL != _pr_rename_lock);
 
     pt_fd_cache.ml = PR_NewLock();
     PR_ASSERT(NULL != pt_fd_cache.ml);
     pt_fd_cache.limit = FD_SETSIZE;
 }  /* _PR_InitIO */
 
-static PRStatus pt_InitIOContinuation()
-{
-    PRIntn rv;
-
-    PR_ASSERT((0 == pt_tq.op_count)
-        && (NULL == pt_tq.head)
-        && (NULL == pt_tq.tail)
-        && (NULL == pt_tq.op)
-        && (PR_FALSE == pt_tq.exitFlag));
-
-    if (NULL == pt_tq.ml)
-    {
-        /* The very first time */
-        pt_tq.ml = PR_NewLock();
-        PR_ASSERT(NULL != pt_tq.ml);
-        pt_tq.new_op = PR_NewCondVar(pt_tq.ml);
-        PR_ASSERT(NULL != pt_tq.new_op);
-        rv = PTHREAD_CONDATTR_INIT(&_pt_cvar_attr);
-        PR_ASSERT(0 == rv);
-
-#if !defined(PT_NO_ATFORK)
-	rv = pthread_atfork(pt_BeforeFork,
-            pt_AfterForkParent, pt_AfterForkChild);
-        PR_ASSERT(0 == rv);
-#endif
-    }
-
-    pt_tq.thread = PR_CreateThread(
-        PR_SYSTEM_THREAD, ContinuationThread, NULL,
-        PR_PRIORITY_URGENT, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
-    PR_ASSERT(NULL != pt_tq.thread);
-
-    return PR_SUCCESS;
-}
-
 PR_IMPLEMENT(PRFileDesc*) PR_GetSpecialFD(PRSpecialFD osfd)
 {
     PRFileDesc *result = NULL;
     PR_ASSERT(osfd >= PR_StandardInput && osfd <= PR_StandardError);
 
     if (!_pr_initialized) _PR_ImplicitInitialization();
     
     switch (osfd)
@@ -1069,17 +1190,18 @@ static void pt_MapError(void (*mapper)(P
         default:
             mapper(syserrno);
     }
 }  /* pt_MapError */
 
 static PRStatus pt_Close(PRFileDesc *fd)
 {
     PRIntn syserrno, rv = 0;
-    if ((NULL == fd) || (NULL == fd->secret))
+    if ((NULL == fd) || (NULL == fd->secret) ||
+				(_PR_FILEDESC_OPEN != fd->secret->state))
     {
         PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
         return PR_FAILURE;
     }
     if (pt_TestAbort()) return PR_FAILURE;
 
     if (_PR_FILEDESC_OPEN == fd->secret->state)
     {
@@ -1225,17 +1347,17 @@ static PRInt32 pt_Writev(
          * Allocate some storage and copy the (already) modified
          * bits into the new vector. The is copying only the
          * part of the array that's still valid. The array may
          * have a new length and the first element of the array may
          * have different values.
          */
         struct iovec *osiov = NULL, *tiov;
         PRIntn osiov_len = iov_len - iov_index;  /* recompute */
-        osiov = (struct iovec*)PR_Malloc(osiov_len * sizeof(struct iovec));
+        osiov = (struct iovec*)PR_MALLOC(osiov_len * sizeof(struct iovec));
         PR_ASSERT(NULL != osiov);
         for (tiov = osiov; iov_index < iov_len; ++iov_index)
         {
             tiov->iov_base = iov[iov_index].iov_base;
             tiov->iov_len = iov[iov_index].iov_len;
             tiov += 1;
         }
         osiov->iov_len -= bytes;  /* that may be partially done */
@@ -1408,33 +1530,34 @@ static PRStatus pt_Connect(
         pt_MapError(_PR_MD_MAP_CONNECT_ERROR, syserrno);
         return PR_FAILURE;
     }
     return PR_SUCCESS;
 }  /* pt_Connect */
 
 PR_IMPLEMENT(PRStatus) PR_GetConnectStatus(const PRPollDesc *pd)
 {
+    int err;
     PRInt32 osfd;
-    PRFileDesc *bottom = pd->fd;
-    int err;
-
+    PRFileDesc *bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+
+    if (NULL == bottom) {
+        PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+        return PR_FAILURE;
+    }
     if (pd->out_flags & PR_POLL_NVAL) {
         PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
         return PR_FAILURE;
     }
     if ((pd->out_flags & (PR_POLL_WRITE | PR_POLL_EXCEPT | PR_POLL_ERR)) == 0) {
         PR_ASSERT(pd->out_flags == 0);
         PR_SetError(PR_IN_PROGRESS_ERROR, 0);
         return PR_FAILURE;
     }
 
-    while (bottom->lower != NULL) {
-        bottom = bottom->lower;
-    }
     osfd = bottom->secret->md.osfd;
 
     err = _MD_unix_get_nonblocking_connect_error(osfd);
     if (err != 0) {
         _PR_MD_MAP_CONNECT_ERROR(err);
         return PR_FAILURE;
     }
     return PR_SUCCESS;
@@ -1479,50 +1602,54 @@ static PRFileDesc* pt_Accept(
     /* mask off the first byte of struct sockaddr (the length field) */
     if (addr)
     addr->inet.family &= 0x00ff;
 #endif
     newfd = pt_SetMethods(osfd, PR_DESC_SOCKET_TCP);
     if (newfd == NULL) close(osfd);  /* $$$ whoops! this doesn't work $$$ */
     else
     {
-        PR_ASSERT((NULL == addr) || (PR_NETADDR_SIZE(addr) == addr_len));
-#if defined(_PR_INET6)
-        PR_ASSERT((NULL == addr) || (addr->raw.family == AF_INET)
-                || (addr->raw.family == AF_INET6));
-#else
-        PR_ASSERT((NULL == addr) || (addr->raw.family == AF_INET));
-#endif
+        PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
+        PR_ASSERT(IsValidNetAddrLen(addr, addr_len) == PR_TRUE);
     }
     return newfd;
 
 failed:
     pt_MapError(_PR_MD_MAP_ACCEPT_ERROR, syserrno);
     return NULL;
 }  /* pt_Accept */
 
 static PRStatus pt_Bind(PRFileDesc *fd, const PRNetAddr *addr)
 {
     PRIntn rv;
     PRInt32 one = 1;
 
     if (pt_TestAbort()) return PR_FAILURE;
 
-#if defined(_PR_INET6)
-    PR_ASSERT(addr->raw.family == AF_INET || addr->raw.family == AF_INET6);
-#else
-    PR_ASSERT(addr->raw.family == AF_INET);
-#endif
-
-    rv = setsockopt(
-        fd->secret->md.osfd, SOL_SOCKET, SO_REUSEADDR,
-        (_PRSockOptVal_t) &one, sizeof(one));
-    if (rv == -1) {
-        pt_MapError(_PR_MD_MAP_SETSOCKOPT_ERROR, errno);
-        return PR_FAILURE;
+    PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
+
+    if (addr->raw.family == AF_UNIX)
+    {
+        /* Disallow relative pathnames */
+        if (addr->local.path[0] != '/')
+        {
+            PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+            return PR_FAILURE;
+        }
+    }
+    else
+    {
+        rv = setsockopt(
+            fd->secret->md.osfd, SOL_SOCKET, SO_REUSEADDR,
+            (_PRSockOptVal_t) &one, sizeof(one));
+        if (rv == -1)
+        {
+            pt_MapError(_PR_MD_MAP_SETSOCKOPT_ERROR, errno);
+            return PR_FAILURE;
+        }
     }
 
     rv = bind(fd->secret->md.osfd, (struct sockaddr*)addr, PR_NETADDR_SIZE(addr));
 
     if (rv == -1) {
         pt_MapError(_PR_MD_MAP_BIND_ERROR, errno);
         return PR_FAILURE;
     }
@@ -1552,16 +1679,22 @@ static PRStatus pt_Shutdown(PRFileDesc *
 
     if (rv == -1) {
         pt_MapError(_PR_MD_MAP_SHUTDOWN_ERROR, errno);
         return PR_FAILURE;
     }
     return PR_SUCCESS;
 }  /* pt_Shutdown */
 
+static PRInt16 pt_Poll(PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags)
+{
+    *out_flags = 0;
+    return in_flags;
+}  /* pt_Poll */
+
 static PRInt32 pt_Recv(
     PRFileDesc *fd, void *buf, PRInt32 amount,
     PRIntn flags, PRIntervalTime timeout)
 {
     PRInt32 syserrno, bytes = -1;
 
     if (pt_TestAbort()) return PR_FAILURE;
 
@@ -1596,17 +1729,17 @@ static PRInt32 pt_Send(
     PRIntn flags, PRIntervalTime timeout)
 {
     PRInt32 syserrno, bytes = -1;
     PRBool fNeedContinue = PR_FALSE;
 
     /*
      * Under HP-UX DCE threads, pthread.h includes dce/cma_ux.h,
      * which has the following:
-     *     #  define send		cma_send
+     *     #  define send        cma_send
      *     extern int  cma_send (int , void *, int, int );
      * So we need to cast away the 'const' of argument #2 for send().
      */
 #if defined (HPUX) && defined(_PR_DCETHREADS)
 #define PT_SENDBUF_CAST (void *)
 #else
 #define PT_SENDBUF_CAST
 #endif
@@ -1665,21 +1798,17 @@ static PRInt32 pt_SendTo(
     PRInt32 amount, PRIntn flags, const PRNetAddr *addr,
     PRIntervalTime timeout)
 {
     PRInt32 syserrno, bytes = -1;
     PRBool fNeedContinue = PR_FALSE;
 
     if (pt_TestAbort()) return PR_FAILURE;
 
-#if defined(_PR_INET6)
-    PR_ASSERT(addr->raw.family == AF_INET || addr->raw.family == AF_INET6);
-#else
-    PR_ASSERT(addr->raw.family == AF_INET);
-#endif
+    PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
     bytes = sendto(
         fd->secret->md.osfd, buf, amount, flags,
         (struct sockaddr*)addr, PR_NETADDR_SIZE(addr));
     syserrno = errno;
     if ( (bytes == -1) && (syserrno == EWOULDBLOCK || syserrno == EAGAIN)
         && (!fd->secret->nonblocking) )
     {
         if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT;
@@ -1748,22 +1877,22 @@ static PRInt32 pt_RecvFrom(PRFileDesc *f
         pt_MapError(_PR_MD_MAP_RECVFROM_ERROR, syserrno);
     return bytes;
 }  /* pt_RecvFrom */
 
 #ifdef HPUX11
 /*
  * pt_HPUXTransmitFile
  *
- *	Send file fd across socket sd. If headers is non-NULL, 'hlen'
- *	bytes of headers is sent before sending the file.
+ *    Send file fd across socket sd. If headers is non-NULL, 'hlen'
+ *    bytes of headers is sent before sending the file.
  *
- *	PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file
- *	
- *	return number of bytes sent or -1 on error
+ *    PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file
+ *    
+ *    return number of bytes sent or -1 on error
  *
  *      This implementation takes advantage of the sendfile() system
  *      call available in HP-UX B.11.00.
  */
 
 static PRInt32 pt_HPUXTransmitFile(PRFileDesc *sd, PRFileDesc *fd, 
         const void *headers, PRInt32 hlen, PRTransmitFileFlags flags,
         PRIntervalTime timeout)
@@ -1826,17 +1955,17 @@ static PRInt32 pt_HPUXTransmitFile(PRFil
         op.function = pt_hpux_transmitfile_cont;
         op.event = POLLOUT | POLLPRI;
         count = pt_Continue(&op);
         syserrno = op.syserrno;
     }
 
     if (count == -1) {
         _MD_hpux_map_sendfile_error(syserrno);
-	return -1;
+    return -1;
     }
     if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) {
         PR_Close(sd);
     }
     return count;
 }
 #endif  /* HPUX11 */
 
@@ -1909,22 +2038,18 @@ static PRStatus pt_GetSockName(PRFileDes
 #ifdef AIX
     /* mask off the first byte of struct sockaddr (the length field) */
     if (addr) addr->inet.family &= 0x00ff;
 #endif
     if (rv == -1) {
         pt_MapError(_PR_MD_MAP_GETSOCKNAME_ERROR, errno);
         return PR_FAILURE;
     } else {
-        PR_ASSERT(addr_len == PR_NETADDR_SIZE(addr));
-#if defined(_PR_INET6)
-        PR_ASSERT(addr->raw.family == AF_INET || addr->raw.family == AF_INET6);
-#else
-	PR_ASSERT(addr->raw.family == AF_INET);
-#endif
+        PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
+        PR_ASSERT(IsValidNetAddrLen(addr, addr_len) == PR_TRUE);
         return PR_SUCCESS;
     }
 }  /* pt_GetSockName */
 
 static PRStatus pt_GetPeerName(PRFileDesc *fd, PRNetAddr *addr)
 {
     PRIntn rv = -1;
     pt_SockLen addr_len = sizeof(PRNetAddr);
@@ -1937,22 +2062,18 @@ static PRStatus pt_GetPeerName(PRFileDes
 #ifdef AIX
     /* mask off the first byte of struct sockaddr (the length field) */
     if (addr) addr->inet.family &= 0x00ff;
 #endif
     if (rv == -1) {
         pt_MapError(_PR_MD_MAP_GETPEERNAME_ERROR, errno);
         return PR_FAILURE;
     } else {
-        PR_ASSERT(addr_len == PR_NETADDR_SIZE(addr));
-#if defined(_PR_INET6)
-        PR_ASSERT(addr->raw.family == AF_INET || addr->raw.family == AF_INET6);
-#else
-	PR_ASSERT(addr->raw.family == AF_INET);
-#endif
+        PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
+        PR_ASSERT(IsValidNetAddrLen(addr, addr_len) == PR_TRUE);
         return PR_SUCCESS;
     }
 }  /* pt_GetPeerName */
 
 static PRStatus pt_GetSockOpt(
     PRFileDesc *fd, PRSockOption optname, void* optval, PRInt32* optlen)
 {
     PRIntn rv = -1;
@@ -2096,23 +2217,23 @@ static PRStatus pt_GetSocketOption(PRFil
                 rv = getsockopt(
                     fd->secret->md.osfd, level, name, (char*)&value, &length);
                 PR_ASSERT((-1 == rv) || (sizeof(PRIntn) == length));
                 data->value.reuse_addr = (0 == value) ? PR_FALSE : PR_TRUE;
                 break;
             }
             case PR_SockOpt_McastLoopback:
             {
-                PRUint8 boolean;
-                length = sizeof(boolean);
+                PRUint8 xbool;
+                length = sizeof(xbool);
                 rv = getsockopt(
                     fd->secret->md.osfd, level, name,
-                    (char*)&boolean, &length);
-                PR_ASSERT((-1 == rv) || (sizeof(boolean) == length));
-                data->value.mcast_loopback = (0 == boolean) ? PR_FALSE : PR_TRUE;
+                    (char*)&xbool, &length);
+                PR_ASSERT((-1 == rv) || (sizeof(xbool) == length));
+                data->value.mcast_loopback = (0 == xbool) ? PR_FALSE : PR_TRUE;
                 break;
             }
             case PR_SockOpt_RecvBufferSize:
             case PR_SockOpt_SendBufferSize:
             case PR_SockOpt_MaxSegment:
             {
                 PRIntn value;
                 length = sizeof(PRIntn);
@@ -2174,17 +2295,17 @@ static PRStatus pt_GetSocketOption(PRFil
         if (-1 == rv) _PR_MD_MAP_GETSOCKOPT_ERROR(errno);
     }
     return (-1 == rv) ? PR_FAILURE : PR_SUCCESS;
 }  /* pt_GetSocketOption */
 
 static PRStatus pt_SetSocketOption(PRFileDesc *fd, const PRSocketOptionData *data)
 {
     PRIntn rv;
-	PRInt32 level, name;
+    PRInt32 level, name;
 
     /*
      * PR_SockOpt_Nonblocking is a special case that does not
      * translate to a setsockopt call.
      */
     if (PR_SockOpt_Nonblocking == data->option)
     {
         fd->secret->nonblocking = data->value.non_blocking;
@@ -2212,20 +2333,20 @@ static PRStatus pt_SetSocketOption(PRFil
                 PRIntn value = (data->value.reuse_addr) ? 1 : 0;
                 rv = setsockopt(
                     fd->secret->md.osfd, level, name,
                     (char*)&value, sizeof(PRIntn));
                 break;
             }
             case PR_SockOpt_McastLoopback:
             {
-                PRUint8 boolean = data->value.mcast_loopback ? 1 : 0;
+                PRUint8 xbool = data->value.mcast_loopback ? 1 : 0;
                 rv = setsockopt(
                     fd->secret->md.osfd, level, name,
-                    (char*)&boolean, sizeof(boolean));
+                    (char*)&xbool, sizeof(xbool));
                 break;
             }
             case PR_SockOpt_RecvBufferSize:
             case PR_SockOpt_SendBufferSize:
             case PR_SockOpt_MaxSegment:
             {
                 PRIntn value = data->value.recv_buffer_size;
                 rv = setsockopt(
@@ -2290,58 +2411,58 @@ static PRIOMethods _pr_file_methods = {
     pt_Write,
     pt_Available,
     pt_Available64,
     pt_Fsync,
     pt_Seek,
     pt_Seek64,
     pt_FileInfo,
     pt_FileInfo64,
-    (PRWritevFN)_PR_InvalidInt,		
-    (PRConnectFN)_PR_InvalidStatus,		
-    (PRAcceptFN)_PR_InvalidDesc,		
-    (PRBindFN)_PR_InvalidStatus,		
-    (PRListenFN)_PR_InvalidStatus,		
-    (PRShutdownFN)_PR_InvalidStatus,	
-    (PRRecvFN)_PR_InvalidInt,		
-    (PRSendFN)_PR_InvalidInt,		
-    (PRRecvfromFN)_PR_InvalidInt,	
-    (PRSendtoFN)_PR_InvalidInt,		
-    (PRPollFN)0,         
+    (PRWritevFN)_PR_InvalidInt,        
+    (PRConnectFN)_PR_InvalidStatus,        
+    (PRAcceptFN)_PR_InvalidDesc,        
+    (PRBindFN)_PR_InvalidStatus,        
+    (PRListenFN)_PR_InvalidStatus,        
+    (PRShutdownFN)_PR_InvalidStatus,    
+    (PRRecvFN)_PR_InvalidInt,        
+    (PRSendFN)_PR_InvalidInt,        
+    (PRRecvfromFN)_PR_InvalidInt,    
+    (PRSendtoFN)_PR_InvalidInt,        
+    pt_Poll,
     (PRAcceptreadFN)_PR_InvalidInt,   
     (PRTransmitfileFN)_PR_InvalidInt, 
-    (PRGetsocknameFN)_PR_InvalidStatus,	
-    (PRGetpeernameFN)_PR_InvalidStatus,	
-    (PRGetsockoptFN)_PR_InvalidStatus,	
-    (PRSetsockoptFN)_PR_InvalidStatus,	
+    (PRGetsocknameFN)_PR_InvalidStatus,    
+    (PRGetpeernameFN)_PR_InvalidStatus,    
+    (PRGetsockoptFN)_PR_InvalidStatus,    
+    (PRSetsockoptFN)_PR_InvalidStatus,    
 };
 
 static PRIOMethods _pr_tcp_methods = {
     PR_DESC_SOCKET_TCP,
     pt_Close,
     pt_Read,
     pt_Write,
     pt_Available,
     pt_Available64,
     pt_Synch,
-	(PRSeekFN)_PR_InvalidInt,
-	(PRSeek64FN)_PR_InvalidInt64,
-	(PRFileInfoFN)_PR_InvalidStatus,
-	(PRFileInfo64FN)_PR_InvalidStatus,
+    (PRSeekFN)_PR_InvalidInt,
+    (PRSeek64FN)_PR_InvalidInt64,
+    (PRFileInfoFN)_PR_InvalidStatus,
+    (PRFileInfo64FN)_PR_InvalidStatus,
     pt_Writev,
     pt_Connect,
     pt_Accept,
     pt_Bind,
     pt_Listen,
     pt_Shutdown,
     pt_Recv,
     pt_Send,
-	(PRRecvfromFN)_PR_InvalidInt,
-	(PRSendtoFN)_PR_InvalidInt,
-	(PRPollFN)0,
+    (PRRecvfromFN)_PR_InvalidInt,
+    (PRSendtoFN)_PR_InvalidInt,
+    pt_Poll,
     pt_AcceptRead,
     pt_TransmitFile,
     pt_GetSockName,
     pt_GetPeerName,
     pt_GetSockOpt,
     pt_SetSockOpt,
     pt_GetSocketOption,
     pt_SetSocketOption
@@ -2350,33 +2471,33 @@ static PRIOMethods _pr_tcp_methods = {
 static PRIOMethods _pr_udp_methods = {
     PR_DESC_SOCKET_UDP,
     pt_Close,
     pt_Read,
     pt_Write,
     pt_Available,
     pt_Available64,
     pt_Synch,
-	(PRSeekFN)_PR_InvalidInt,
-	(PRSeek64FN)_PR_InvalidInt64,
-	(PRFileInfoFN)_PR_InvalidStatus,
-	(PRFileInfo64FN)_PR_InvalidStatus,
+    (PRSeekFN)_PR_InvalidInt,
+    (PRSeek64FN)_PR_InvalidInt64,
+    (PRFileInfoFN)_PR_InvalidStatus,
+    (PRFileInfo64FN)_PR_InvalidStatus,
     pt_Writev,
     pt_Connect,
-	(PRAcceptFN)_PR_InvalidDesc,
+    (PRAcceptFN)_PR_InvalidDesc,
     pt_Bind,
     pt_Listen,
     pt_Shutdown,
     pt_Recv,
     pt_Send,
     pt_RecvFrom,
     pt_SendTo,
-	(PRPollFN)0,
-	(PRAcceptreadFN)_PR_InvalidInt,
-	(PRTransmitfileFN)_PR_InvalidInt,
+    pt_Poll,
+    (PRAcceptreadFN)_PR_InvalidInt,
+    (PRTransmitfileFN)_PR_InvalidInt,
     pt_GetSockName,
     pt_GetPeerName,
     pt_GetSockOpt,
     pt_SetSockOpt,
     pt_GetSocketOption,
     pt_SetSocketOption
 };
 
@@ -2422,32 +2543,33 @@ static PRFileDesc *pt_SetMethods(PRIntn 
                 break;
             default:
                 break;
         }
     }
     return fd;
 }  /* pt_SetMethods */
 
-PR_IMPLEMENT(PRIOMethods*) PR_GetFileMethods()
+PR_IMPLEMENT(const PRIOMethods*) PR_GetFileMethods()
 {
     return &_pr_file_methods;
 }  /* PR_GetFileMethods */
 
-PR_IMPLEMENT(PRIOMethods*) PR_GetTCPMethods()
+PR_IMPLEMENT(const PRIOMethods*) PR_GetTCPMethods()
 {
     return &_pr_tcp_methods;
 }  /* PR_GetTCPMethods */
 
-PR_IMPLEMENT(PRIOMethods*) PR_GetUDPMethods()
+PR_IMPLEMENT(const PRIOMethods*) PR_GetUDPMethods()
 {
     return &_pr_udp_methods;
 }  /* PR_GetUDPMethods */
 
-PR_IMPLEMENT(PRFileDesc*) PR_AllocFileDesc(PRInt32 osfd, PRIOMethods *methods)
+PR_IMPLEMENT(PRFileDesc*) PR_AllocFileDesc(
+    PRInt32 osfd, const PRIOMethods *methods)
 {
     PRFileDesc *fd = pt_Getfd();
 
     /*
      * Assert that the file descriptor is small enough to fit in the
      * fd_set passed to select
      */
     PR_ASSERT(osfd < FD_SETSIZE);
@@ -2478,19 +2600,19 @@ PR_IMPLEMENT(PRFileDesc*) PR_Socket(PRIn
     PRFileDesc *fd = NULL;
 
     if (!_pr_initialized) _PR_ImplicitInitialization();
 
     if (pt_TestAbort()) return NULL;
 
     if (PF_INET != domain
 #if defined(_PR_INET6)
-	&& PF_INET6 != domain
+        && PF_INET6 != domain
 #endif
-	)
+        && PF_UNIX != domain)
     {
         PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0);
         return fd;
     }
     if (type == SOCK_STREAM) ftype = PR_DESC_SOCKET_TCP;
     else if (type == SOCK_DGRAM) ftype = PR_DESC_SOCKET_UDP;
     else
     {
@@ -2741,44 +2863,64 @@ PR_IMPLEMENT(PRInt32) PR_Poll(
      */
     PRIntervalTime start, elapsed, remaining;
 
     if (0 == npds) PR_Sleep(timeout);
     else
     {
         PRIntn index, msecs;
         struct pollfd *syspoll = NULL;
-        syspoll = (struct pollfd*)PR_Malloc(npds * sizeof(struct pollfd));
+        syspoll = (struct pollfd*)PR_MALLOC(npds * sizeof(struct pollfd));
+        if (NULL == syspoll)
+        {
+            PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+            return -1;
+        }
         for (index = 0; index < npds; ++index)
         {
             PRFileDesc *bottom = pds[index].fd;
-
-            if (bottom == NULL)
+            PRInt16 polling_flags = pds[index].in_flags;
+
+            /* 'bottom' is really 'top' until we make it the bottom */
+            if (NULL != bottom)
+            {
+                polling_flags = (bottom->methods->poll)(
+                    bottom, polling_flags, &pds[index].out_flags);
+
+                if (0 != (polling_flags & pds[index].out_flags))
+                    ready += 1;  /* this one is ready right now */
+                else
+                {
+                    /* now locate the NSPR layer at the bottom of the stack */
+                    bottom = PR_GetIdentitiesLayer(bottom, PR_NSPR_IO_LAYER);
+                    PR_ASSERT(NULL != bottom);  /* what to do about that? */
+                    if ((NULL != bottom)
+                    && (_PR_FILEDESC_OPEN == bottom->secret->state))
+                    {
+                        syspoll[index].fd = bottom->secret->md.osfd;
+                        pds[index].out_flags = 0;  /* init the result */
+                        syspoll[index].events = 0;
+                        if (polling_flags & PR_POLL_READ)
+                            syspoll[index].events |= POLLIN;
+                        if (polling_flags & PR_POLL_WRITE)
+                            syspoll[index].events |= POLLOUT;
+                        if (polling_flags & PR_POLL_EXCEPT)
+                            syspoll[index].events |= POLLPRI;
+                    }
+                    else
+                    {
+                        ready += 1;  /* this will cause an abrupt return */
+                        pds[index].out_flags = POLLNVAL;  /* bogii */
+                    }
+                }
+            }
+            else
             {
                 /* make poll() ignore this entry */
                 syspoll[index].fd = -1;
-                continue;
-            }
-
-            while (bottom->lower != NULL) bottom = bottom->lower;
-            syspoll[index].fd = bottom->secret->md.osfd;
-
-            syspoll[index].events = 0;
-            if (pds[index].in_flags & PR_POLL_READ)
-                syspoll[index].events |= POLLIN;
-            if (pds[index].in_flags & PR_POLL_WRITE)
-                syspoll[index].events |= POLLOUT;
-            if (pds[index].in_flags & PR_POLL_EXCEPT)
-                syspoll[index].events |= POLLPRI;
-            if (_PR_FILEDESC_OPEN == bottom->secret->state)
-                pds[index].out_flags = 0;  /* init the result */
-            else
-            {
-                ready += 1;  /* this will cause an abrupt return */
-                pds[index].out_flags = POLLNVAL;  /* bogii */
             }
         }
         if (0 == ready)
         {
             switch (timeout)
             {
             case PR_INTERVAL_NO_WAIT: msecs = 0; break;
             case PR_INTERVAL_NO_TIMEOUT: msecs = -1; break;
@@ -2787,51 +2929,40 @@ PR_IMPLEMENT(PRInt32) PR_Poll(
                 start = PR_IntervalNow();
             }
 
 retry:
             ready = poll(syspoll, npds, msecs);
             if (-1 == ready)
             {
                 PRIntn oserror = errno;
-                PRErrorCode prerror;
-
-                switch (oserror) {
-                    case EAGAIN:
-                        prerror = PR_INSUFFICIENT_RESOURCES_ERROR;
-                        break;
-                    case EINTR:
-                        if (timeout == PR_INTERVAL_NO_TIMEOUT)
-                            goto retry;
-                        else if (timeout == PR_INTERVAL_NO_WAIT)
-                            ready = 0;  /* don't retry, just time out */
+
+                if (EINTR == oserror)
+                {
+                    if (timeout == PR_INTERVAL_NO_TIMEOUT)
+                        goto retry;
+                    else if (timeout == PR_INTERVAL_NO_WAIT)
+                        ready = 0;  /* don't retry, just time out */
+                    {
+                        elapsed = (PRIntervalTime) (PR_IntervalNow()
+                                - start);
+                        if (elapsed > timeout)
+                            ready = 0;  /* timed out */
+                        else
                         {
-                            elapsed = (PRIntervalTime) (PR_IntervalNow()
-                                    - start);
-                            if (elapsed > timeout)
-                                ready = 0;  /* timed out */
-                            else
-                            {
-                                remaining = timeout - elapsed;
-                                msecs = PR_IntervalToMilliseconds(remaining);
-                                goto retry;
-                            }
+                            remaining = timeout - elapsed;
+                            msecs = PR_IntervalToMilliseconds(remaining);
+                            goto retry;
                         }
-                        break;
-                case EINVAL:
-                        prerror = PR_INVALID_ARGUMENT_ERROR;
-                        break;
-                    case EFAULT:
-                        prerror = PR_ACCESS_FAULT_ERROR;
-                        break;
-                    default:
-                        prerror = PR_UNKNOWN_ERROR;
-                        break;
-                } 
-                PR_SetError(prerror, oserror);
+                    }
+                }
+                else
+                {
+                    _PR_MD_MAP_POLL_ERROR(oserror);
+                }
             }
             else if (ready > 0)
             {
                 for (index = 0; index < npds; ++index)
                 {
                     if (pds[index].fd == NULL) continue;
                     PR_ASSERT(0 == pds[index].out_flags);
                     if (0 != syspoll[index].revents)
@@ -2871,17 +3002,17 @@ PR_IMPLEMENT(PRDirEntry*) PR_ReadDir(PRD
         if ((flags & PR_SKIP_DOT)
             && ('.' == dp->d_name[0])
             && (0 == dp->d_name[1])) continue;
         if ((flags & PR_SKIP_DOT_DOT)
             && ('.' == dp->d_name[0])
             && ('.' == dp->d_name[1])
             && (0 == dp->d_name[2])) continue;
         if ((flags & PR_SKIP_HIDDEN) && ('.' == dp->d_name[0]))
-			continue;
+            continue;
         break;
     }
     dir->d.name = dp->d_name;
     return &dir->d;
 }  /* PR_ReadDir */
 
 PR_IMPLEMENT(PRFileDesc*) PR_NewUDPSocket()
 {
@@ -2969,17 +3100,17 @@ PR_IMPLEMENT(PRStatus) PR_CreatePipe(
 {
     int pipefd[2];
     int flags;
 
     if (pt_TestAbort()) return PR_FAILURE;
 
     if (pipe(pipefd) == -1)
     {
-	/* XXX map pipe error */
+    /* XXX map pipe error */
         PR_SetError(PR_UNKNOWN_ERROR, errno);
         return PR_FAILURE;
     }
     *readPipe = pt_SetMethods(pipefd[0], PR_DESC_FILE);
     if (NULL == *readPipe)
     {
         close(pipefd[0]);
         close(pipefd[1]);
@@ -3021,35 +3152,24 @@ PR_IMPLEMENT(PRFileDesc*) PR_ImportTCPSo
 
 PR_IMPLEMENT(PRFileDesc*) PR_ImportUDPSocket(PRInt32 osfd)
 {
     PRFileDesc *fd = pt_SetMethods(osfd, PR_DESC_SOCKET_UDP);
     if (NULL != fd) close(osfd);
     return fd;
 }  /* PR_ImportUDPSocket */
 
-PR_IMPLEMENT(PRInt32) PR_FileDesc2NativeHandle(PRFileDesc *fd)
+PR_IMPLEMENT(PRInt32) PR_FileDesc2NativeHandle(PRFileDesc *bottom)
 {
-    if (fd)
-    {
-        /*
-         * The fd may be layered.  Chase the links to the
-         * bottom layer to get the osfd.
-         */
-        PRFileDesc *bottom = fd;
-        while (bottom->lower != NULL) {
-            bottom = bottom->lower;
-        }
-        return bottom->secret->md.osfd;
-    }
-    else
-    {
-        PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
-        return -1;
-    }
+    PRInt32 osfd = -1;
+    bottom = (NULL == bottom) ?
+        NULL : PR_GetIdentitiesLayer(bottom, PR_NSPR_IO_LAYER);
+    if (NULL == bottom) PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+    else osfd = bottom->secret->md.osfd;
+    return osfd;
 }  /* PR_FileDesc2NativeHandle */
 
 PR_IMPLEMENT(void) PR_ChangeFileDescNativeHandle(PRFileDesc *fd,
     PRInt32 handle)
 {
     if (fd) fd->secret->md.osfd = handle;
 }  /*  PR_ChangeFileDescNativeHandle*/
 
--- a/pr/src/pthreads/ptsynch.c
+++ b/pr/src/pthreads/ptsynch.c
@@ -28,20 +28,24 @@
 #include "obsolete/prsem.h"
 
 #include <string.h>
 #include <pthread.h>
 #include <sys/time.h>
 
 static pthread_condattr_t _pt_cvar_attr;
 
-#if defined(DEBUG) && defined(_PR_DCETHREADS)
+#if defined(DEBUG)
+extern PTDebug pt_debug;  /* this is shared between several modules */
+
+#if defined(_PR_DCETHREADS)
 static pthread_t pt_zero_tid;  /* a null pthread_t (pthread_t is a struct
                                 * in DCE threads) to compare with */
-#endif
+#endif  /* defined(_PR_DCETHREADS) */
+#endif  /* defined(DEBUG) */
 
 /**************************************************************/
 /**************************************************************/
 /*****************************LOCKS****************************/
 /**************************************************************/
 /**************************************************************/
 
 void _PR_InitLocks(void)
@@ -78,31 +82,43 @@ static void pt_PostNotifies(PRLock *lock
         PR_ASSERT(0 == rv);
     }
 
     notified = &post;  /* this is where we start */
     do
     {
         for (index = 0; index < notified->length; ++index)
         {
-            PR_ASSERT(NULL != notified->cv[index].cv);
+            PRCondVar *cv = notified->cv[index].cv;
+            PR_ASSERT(NULL != cv);
             PR_ASSERT(0 != notified->cv[index].times);
             if (-1 == notified->cv[index].times)
             {
-                rv = pthread_cond_broadcast(&notified->cv[index].cv->cv);
+                rv = pthread_cond_broadcast(&cv->cv);
                 PR_ASSERT(0 == rv);
             }
             else
             {
                 while (notified->cv[index].times-- > 0)
                 {
-                    rv = pthread_cond_signal(&notified->cv[index].cv->cv);
-                    PR_ASSERT(0 == rv);
+                    rv = pthread_cond_signal(&cv->cv);
+                    PR_ASSERT((0 == rv) || (EINVAL == rv));
                 }
             }
+#if defined(DEBUG)
+            pt_debug.cvars_notified += 1;
+            if (0 > PR_AtomicDecrement(&cv->notify_pending))
+            {
+                pt_debug.delayed_cv_deletes += 1;
+                PR_DestroyCondVar(cv);
+            }
+#else  /* defined(DEBUG) */
+            if (0 > PR_AtomicDecrement(&cv->notify_pending))
+                PR_DestroyCondVar(cv);
+#endif  /* defined(DEBUG) */
         }
         prev = notified;
         notified = notified->link;
         if (&post != prev) PR_DELETE(prev);
     } while (NULL != notified);
 }  /* pt_PostNotifies */
 
 PR_IMPLEMENT(PRLock*) PR_NewLock(void)
@@ -118,44 +134,51 @@ PR_IMPLEMENT(PRLock*) PR_NewLock(void)
         pthread_mutexattr_t mattr;
         rv = PTHREAD_MUTEXATTR_INIT(&mattr); 
         PR_ASSERT(0 == rv);
         rv = PTHREAD_MUTEX_INIT(lock->mutex, mattr); 
         PR_ASSERT(0 == rv);
         rv = PTHREAD_MUTEXATTR_DESTROY(&mattr); 
         PR_ASSERT(0 == rv);
     }
+#if defined(DEBUG)
+    pt_debug.locks_created += 1;
+#endif
     return lock;
 }  /* PR_NewLock */
 
 PR_IMPLEMENT(void) PR_DestroyLock(PRLock *lock)
 {
     PRIntn rv;
     PR_ASSERT(NULL != lock);
     PR_ASSERT(PTHREAD_THR_HANDLE_IS_ZERO(lock->owner));
     PR_ASSERT(0 == lock->notified.length);
     PR_ASSERT(NULL == lock->notified.link);
     rv = pthread_mutex_destroy(&lock->mutex);
     PR_ASSERT(0 == rv);
 #if defined(DEBUG)
     memset(lock, 0xaf, sizeof(PRLock));
+    pt_debug.locks_destroyed += 1;
 #endif
     PR_DELETE(lock);
 }  /* PR_DestroyLock */
 
 PR_IMPLEMENT(void) PR_Lock(PRLock *lock)
 {
     PRIntn rv;
     PR_ASSERT(lock != NULL);
     rv = pthread_mutex_lock(&lock->mutex);
     PR_ASSERT(0 == rv);
     PR_ASSERT(0 == lock->notified.length);
     PR_ASSERT(NULL == lock->notified.link);
     PR_ASSERT(PTHREAD_THR_HANDLE_IS_ZERO(lock->owner));
     PTHREAD_COPY_THR_HANDLE(pthread_self(), lock->owner);
+#if defined(DEBUG)
+    pt_debug.locks_acquired += 1;
+#endif
 }  /* PR_Lock */
 
 PR_IMPLEMENT(PRStatus) PR_Unlock(PRLock *lock)
 {
     PRIntn rv;
 
     PR_ASSERT(lock != NULL);
     PR_ASSERT(PTHREAD_MUTEX_IS_LOCKED(lock->mutex));
@@ -167,16 +190,19 @@ PR_IMPLEMENT(PRStatus) PR_Unlock(PRLock 
     PTHREAD_ZERO_THR_HANDLE(lock->owner);
     if (0 == lock->notified.length)  /* shortcut */
     {
         rv = pthread_mutex_unlock(&lock->mutex);
         PR_ASSERT(0 == rv);
     }
     else pt_PostNotifies(lock, PR_TRUE);
 
+#if defined(DEBUG)
+    pt_debug.locks_released += 1;
+#endif
     return PR_SUCCESS;
 }  /* PR_Unlock */
 
 
 /**************************************************************/
 /**************************************************************/
 /***************************CONDITIONS*************************/
 /**************************************************************/
@@ -257,16 +283,17 @@ static void pt_PostNotifyToCvar(PRCondVa
 
         /* if there's no link, create an empty array and link it */
         if (NULL == notified->link)
             notified->link = PR_NEWZAP(_PT_Notified);
         notified = notified->link;
     }
 
     /* A brand new entry in the array */
+    (void)PR_AtomicIncrement(&cvar->notify_pending);
     notified->cv[index].times = (broadcast) ? -1 : 1;
     notified->cv[index].cv = cvar;
     notified->length += 1;
 
 finished:
     PR_ASSERT(pthread_equal(cvar->lock->owner, pthread_self()));
 }  /* pt_PostNotifyToCvar */
 
@@ -274,28 +301,35 @@ PR_IMPLEMENT(PRCondVar*) PR_NewCondVar(P
 {
     PRCondVar *cv = PR_NEW(PRCondVar);
     PR_ASSERT(lock != NULL);
     if (cv != NULL)
     {
         int rv = PTHREAD_COND_INIT(cv->cv, _pt_cvar_attr); 
         PR_ASSERT(0 == rv);
         cv->lock = lock;
+        cv->notify_pending = 0;
+#if defined(DEBUG)
+        pt_debug.cvars_created += 1;
+#endif
     }
     return cv;
 }  /* PR_NewCondVar */
 
 PR_IMPLEMENT(void) PR_DestroyCondVar(PRCondVar *cvar)
 {
-    int rv;
-    rv = pthread_cond_destroy(&cvar->cv); PR_ASSERT(0 == rv);
+    if (0 > PR_AtomicDecrement(&cvar->notify_pending))
+    {
+        PRIntn rv = pthread_cond_destroy(&cvar->cv); PR_ASSERT(0 == rv);
 #if defined(DEBUG)
         memset(cvar, 0xaf, sizeof(PRCondVar));
+        pt_debug.cvars_destroyed += 1;
 #endif
-    PR_DELETE(cvar);
+        PR_DELETE(cvar);
+    }
 }  /* PR_DestroyCondVar */
 
 PR_IMPLEMENT(PRStatus) PR_WaitCondVar(PRCondVar *cvar, PRIntervalTime timeout)
 {
     PRIntn rv;
     PRThread *thred = PR_CurrentThread();
 
     PR_ASSERT(cvar != NULL);
--- a/pr/src/pthreads/ptthread.c
+++ b/pr/src/pthreads/ptthread.c
@@ -34,16 +34,17 @@
 
 /*
  * Record whether or not we have the privilege to set the scheduling
  * policy and priority of threads.  0 means that privilege is available.
  * EPERM means that privilege is not available.
  */
 
 PRIntn pt_schedpriv;
+extern PRLock *_pr_sleeplock;
 
 struct _PT_Bookeeping pt_book = {0};
 
 static void init_pthread_gc_support(void);
 
 static PRIntn pt_PriorityMap(PRThreadPriority pri)
 {
     return pt_book.minPrio +
@@ -153,16 +154,18 @@ static void *_pt_root(void *arg)
         while (!thred->okToDelete)
             PR_WaitCondVar(pt_book.cv, PR_INTERVAL_NO_TIMEOUT);
     }
     PR_Unlock(pt_book.ml);
 
     /* last chance to delete this puppy if the thread is detached */
     if (detached)
     {
+        if (NULL != thred->io_cv)
+            PR_DestroyCondVar(thred->io_cv);
     	PR_DELETE(thred->stack);
 #if defined(DEBUG)
         memset(thred, 0xaf, sizeof(PRThread));
 #endif
         PR_DELETE(thred);
     }
 
     rv = pthread_setspecific(pt_book.key, NULL);
@@ -443,21 +446,25 @@ PR_IMPLEMENT(PRStatus) PR_JoinThread(PRT
 
         PR_ASSERT((0xafafafaf == thred->state)
         || (PT_THREAD_DETACHED & thred->state));
     }
     else
     {
         pthread_t id = thred->id;
         rv = pthread_join(id, &result);
+        PR_ASSERT(rv == 0 && result == NULL);
         if (0 != rv)
             PR_SetError(PR_UNKNOWN_ERROR, errno);
+        if (NULL != thred->io_cv)
+            PR_DestroyCondVar(thred->io_cv);
     	PR_DELETE(thred->stack);
+#if defined(DEBUG)
         memset(thred, 0xaf, sizeof(PRThread));
-        PR_ASSERT(result == NULL);
+#endif
         PR_DELETE(thred);
     }
     return (0 == rv) ? PR_SUCCESS : PR_FAILURE;
 }  /* PR_JoinThread */
 
 PR_IMPLEMENT(void) PR_DetachThread()
 {
     void *tmp;
@@ -476,20 +483,24 @@ PR_IMPLEMENT(void) PR_DetachThread()
             PR_NotifyAllCondVar(pt_book.cv);
         thred->prev->next = thred->next;
         if (NULL == thred->next)
             pt_book.last = thred->prev;
         else
             thred->next->prev = thred->prev;
         PR_Unlock(pt_book.ml);
 
+        if (NULL != thred->io_cv)
+            PR_DestroyCondVar(thred->io_cv);
         rv = pthread_setspecific(pt_book.key, NULL);
         PR_ASSERT(0 == rv);
     	PR_DELETE(thred->stack);
+#if defined(DEBUG)
         memset(thred, 0xaf, sizeof(PRThread));
+#endif
         PR_DELETE(thred);
     }    
 }  /* PR_DetachThread */
 
 PR_IMPLEMENT(PRThread*) PR_GetCurrentThread()
 {
     void *thred;
 
@@ -607,27 +618,37 @@ PR_IMPLEMENT(PRStatus) PR_Interrupt(PRTh
     ** If the target thread indicates that it's waiting,
     ** find the condition and broadcast to it. Broadcast
     ** since we don't know which thread (if there are more
     ** than one). This sounds risky, but clients must
     ** test their invariants when resumed from a wait and
     ** I don't expect very many threads to be waiting on
     ** a single condition and I don't expect interrupt to
     ** be used very often.
+    **
+    ** I don't know why I thought this would work. Must have
+    ** been one of those weaker momements after I'd been
+    ** smelling the vapors.
+    **
+    ** Even with the followng changes it is possible that
+    ** the pointer to the condition variable is pointing
+    ** at a bogus value. Will the unerlying code detect
+    ** that?
     */
-    PRCondVar *victim;
-    PR_ASSERT(thred != NULL);
+    PRCondVar *cv;
+    PR_ASSERT(NULL != thred);
+    if (NULL == thred) return PR_FAILURE;
+
     thred->state |= PT_THREAD_ABORTED;
-    victim = thred->waiting;
-    if (NULL != victim)
+
+    cv = thred->waiting;
+    if (NULL != cv)
     {
-        PRIntn haveLock = pthread_equal(victim->lock->owner, pthread_self());
-        if (!haveLock) PR_Lock(victim->lock);
-        PR_NotifyAllCondVar(victim);
-        if (!haveLock) PR_Unlock(victim->lock);
+        PRIntn rv = pthread_cond_broadcast(&cv->cv);
+        PR_ASSERT(0 == rv);
     }
     return PR_SUCCESS;
 }  /* PR_Interrupt */
 
 PR_IMPLEMENT(void) PR_ClearInterrupt()
 {
     PRThread *me = PR_CurrentThread();
     me->state &= ~PT_THREAD_ABORTED;
@@ -649,21 +670,21 @@ PR_IMPLEMENT(PRStatus) PR_Sleep(PRInterv
 
     if (PR_INTERVAL_NO_WAIT == ticks)
     {
         PTHREAD_YIELD();
         rv = PR_SUCCESS;
     }
     else
     {
-        PRCondVar *cv = PR_NewCondVar(pt_book.ml);
+        PRCondVar *cv = PR_NewCondVar(_pr_sleeplock);
         PR_ASSERT(cv != NULL);
-        PR_Lock(pt_book.ml);
+        PR_Lock(_pr_sleeplock);
         rv = PR_WaitCondVar(cv, ticks);
-        PR_Unlock(pt_book.ml);
+        PR_Unlock(_pr_sleeplock);
         PR_DestroyCondVar(cv);
     }
     return rv;
 }  /* PR_Sleep */
 
 void _PR_InitThreads(
     PRThreadType type, PRThreadPriority priority, PRUintn maxPTDs)
 {
@@ -1247,17 +1268,19 @@ PR_IMPLEMENT(void *)PR_GetSP(PRThread *t
  * particular thread.  We will just disable the preemption (virtual timer alarm) and
  * let the executing thread finish the garbage collection.  This stops all other threads
  * (GC able or not) and is very inefficient but there is no other choice.
  */
 PR_IMPLEMENT(void) PR_SuspendAll()
 {
     PRIntn rv;
 
+#ifdef DEBUG
     suspendAllOn = PR_TRUE;
+#endif
     PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_SuspendAll\n"));
     /* 
      * turn off preemption - i.e add virtual alarm signal to the set of 
      * blocking signals 
      */
     rv = sigprocmask(
         SIG_BLOCK, &javagc_vtalarm_sigmask, &javagc_intsoff_sigmask);
     PR_ASSERT(0 == rv);
@@ -1270,17 +1293,19 @@ PR_IMPLEMENT(void) PR_ResumeAll()
     PRIntn rv;
     
     suspendAllSuspended = PR_FALSE;
     PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_ResumeAll\n"));
     /* turn on preemption - i.e re-enable virtual alarm signal */
 
     rv = sigprocmask(SIG_SETMASK, &javagc_intsoff_sigmask, (sigset_t *)NULL);
     PR_ASSERT(0 == rv);
+#ifdef DEBUG
     suspendAllOn = PR_FALSE;
+#endif
 
     PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("End PR_ResumeAll\n"));
 }  /* PR_ResumeAll */
 
 /* Return the stack pointer for the given thread- used by the GC */
 PR_IMPLEMENT(void*)PR_GetSP(PRThread *thred)
 {
 	pthread_t tid = thred->id;
--- a/pr/src/threads/combined/prucv.c
+++ b/pr/src/threads/combined/prucv.c
@@ -21,17 +21,17 @@
 #include "prinrval.h"
 #include "prtypes.h"
 
 
 /*
 ** Notify one thread that it has finished waiting on a condition variable
 ** Caller must hold the _PR_CVAR_LOCK(cv)
 */
-PRBool NotifyThread (PRThread *thread, PRThread *me)
+PRBool _PR_NotifyThread (PRThread *thread, PRThread *me)
 {
     PRBool rv;
 
     PR_ASSERT(_PR_IS_NATIVE_THREAD(me) || _PR_MD_GET_INTSOFF() != 0);
 
     _PR_THREAD_LOCK(thread);
     PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD));
     if ( !_PR_IS_NATIVE_THREAD(thread) ) {
@@ -269,17 +269,17 @@ void _PR_NotifyCondVar(PRCondVar *cvar, 
 
     _PR_CVAR_LOCK(cvar);
     q = cvar->condQ.next;
     while (q != &cvar->condQ) {
 #ifndef XP_MAC
         PR_LOG(_pr_cvar_lm, PR_LOG_MIN, ("_PR_NotifyCondVar: cvar=%p", cvar));
 #endif
         if (_PR_THREAD_CONDQ_PTR(q)->wait.cvar)  {
-            if (NotifyThread(_PR_THREAD_CONDQ_PTR(q), me) == PR_TRUE)
+            if (_PR_NotifyThread(_PR_THREAD_CONDQ_PTR(q), me) == PR_TRUE)
                 break;
         }
         q = q->next;
     }
     _PR_CVAR_UNLOCK(cvar);
 
     if ( !_PR_IS_NATIVE_THREAD(me))
     	_PR_INTSON(is);
@@ -376,17 +376,17 @@ void _PR_ClockInterrupt(void)
             _PR_MISCQ_LOCK(cpu);
             thread->state = _PR_SUSPENDED;
             _PR_ADD_SUSPENDQ(thread, cpu);
             _PR_MISCQ_UNLOCK(cpu);
         } else {
             if (thread->wait.cvar) {
                 PRThreadPriority pri;
 
-                /* Do work very similar to what NotifyThread does */
+                /* Do work very similar to what _PR_NotifyThread does */
                 PR_ASSERT( !_PR_IS_NATIVE_THREAD(thread) );
 
                 /* Make thread runnable */
                 pri = thread->priority;
                 thread->state = _PR_RUNNABLE;
                 PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD));
 
                 PR_ASSERT(thread->cpu == cpu);
@@ -540,17 +540,17 @@ PR_IMPLEMENT(PRStatus) PR_NotifyAllCondV
     return PR_SUCCESS;
 #else  /* _PR_GLOBAL_THREADS_ONLY */
     if ( !_PR_IS_NATIVE_THREAD(me))
     	_PR_INTSOFF(is);
     _PR_CVAR_LOCK(cvar);
     q = cvar->condQ.next;
     while (q != &cvar->condQ) {
 		PR_LOG(_pr_cvar_lm, PR_LOG_MIN, ("PR_NotifyAll: cvar=%p", cvar));
-		NotifyThread(_PR_THREAD_CONDQ_PTR(q), me);
+		_PR_NotifyThread(_PR_THREAD_CONDQ_PTR(q), me);
 		q = q->next;
     }
     _PR_CVAR_UNLOCK(cvar);
     if (!_PR_IS_NATIVE_THREAD(me))
     	_PR_INTSON(is);
 
     return PR_SUCCESS;
 #endif  /* _PR_GLOBAL_THREADS_ONLY */
@@ -618,17 +618,17 @@ PR_IMPLEMENT(PRStatus) PRP_NakedBroadcas
     PRThread *me = _PR_MD_CURRENT_THREAD();
     PR_ASSERT(_PR_NAKED_CV_LOCK == cvar->lock);
 
     if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is);
 	_PR_MD_LOCK( &(cvar->ilock) );
     q = cvar->condQ.next;
     while (q != &cvar->condQ) {
 		PR_LOG(_pr_cvar_lm, PR_LOG_MIN, ("PR_NotifyAll: cvar=%p", cvar));
-		NotifyThread(_PR_THREAD_CONDQ_PTR(q), me);
+		_PR_NotifyThread(_PR_THREAD_CONDQ_PTR(q), me);
 		q = q->next;
     }
 	_PR_MD_UNLOCK( &(cvar->ilock) );
     if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is);
 
     return PR_SUCCESS;
 }  /* PRP_NakedBroadcast */
 
--- a/pr/src/threads/combined/prulock.c
+++ b/pr/src/threads/combined/prulock.c
@@ -255,28 +255,36 @@ PR_IMPLEMENT(void) PR_Lock(PRLock *lock)
     }
 #endif
 
     /* 
     Add this thread to the asked for lock's list of waiting threads.  We
     add this thread thread in the right priority order so when the unlock
     occurs, the thread with the higher priority will get the lock.
     */
-    /* Sort thread into lock's waitQ at appropriate point */
     q = lock->waitQ.next;
-
-    /* Now scan the list for where to insert this entry */
-    while (q != &lock->waitQ) {
-        t = _PR_THREAD_CONDQ_PTR(lock->waitQ.next);
-        if (me->priority > t->priority) {
-            /* Found a lower priority thread to insert in front of */
-            break;
-        }
-        q = q->next;
-    }
+    if (q == &lock->waitQ || _PR_THREAD_CONDQ_PTR(q)->priority ==
+      	_PR_THREAD_CONDQ_PTR(lock->waitQ.prev)->priority) {
+		/*
+		 * If all the threads in the lock waitQ have the same priority,
+		 * then avoid scanning the list:  insert the element at the end.
+		 */
+		q = &lock->waitQ;
+    } else {
+		/* Sort thread into lock's waitQ at appropriate point */
+		/* Now scan the list for where to insert this entry */
+		while (q != &lock->waitQ) {
+			t = _PR_THREAD_CONDQ_PTR(lock->waitQ.next);
+			if (me->priority > t->priority) {
+				/* Found a lower priority thread to insert in front of */
+				break;
+			}
+			q = q->next;
+		}
+	}
     PR_INSERT_BEFORE(&me->waitQLinks, q);
 
 	/* 
 	Now grab the threadLock since we are about to change the state.  We have
 	to do this since a PR_Suspend or PR_SetThreadPriority type call that takes
 	a PRThread* as an argument could be changing the state of this thread from
 	a thread running on a different cpu.
 	*/
--- a/pr/src/threads/combined/pruthr.c
+++ b/pr/src/threads/combined/pruthr.c
@@ -116,18 +116,21 @@ void _PR_InitThreads(PRThreadType type, 
 
     if (!thread) PR_Abort();
 #ifdef _PR_GLOBAL_THREADS_ONLY
     thread->flags |= _PR_PRIMORDIAL | _PR_GLOBAL_SCOPE;
 #else
     thread->flags |= _PR_PRIMORDIAL;
 #endif
 
-	/* Needs _PR_PRIMORDIAL flag set before calling _PR_MD_INIT_THREAD() */
-    if (_PR_MD_INIT_THREAD(thread) == PR_FAILURE) {
+    /*
+     * Needs _PR_PRIMORDIAL flag set before calling
+     * _PR_MD_INIT_ATTACHED_THREAD()
+     */
+    if (_PR_MD_INIT_ATTACHED_THREAD(thread) == PR_FAILURE) {
 		/*
 		 * XXX do what?
 		 */
 	}
 
     if (_PR_IS_NATIVE_THREAD(thread)) {
     	PR_APPEND_LINK(&thread->active, &_PR_ACTIVE_GLOBAL_THREADQ());
 		_pr_global_threads++;
@@ -719,17 +722,17 @@ static void _PR_Resume(PRThread *thread)
     }
     _PR_THREAD_UNLOCK(thread);
     if (!_PR_IS_NATIVE_THREAD(me))
     	_PR_INTSON(is);
 
 }
 
 #if !defined(_PR_LOCAL_THREADS_ONLY) && defined(XP_UNIX)
-static PRThread *get_thread(_PRCPU *cpu)
+static PRThread *get_thread(_PRCPU *cpu, PRBool *wakeup_cpus)
 {
     PRThread *thread;
     PRIntn pri;
     PRUint32 r;
     PRCList *qp;
     PRIntn priMin, priMax;
 
     _PR_RUNQ_LOCK(cpu);
@@ -750,34 +753,38 @@ static PRThread *get_thread(_PRCPU *cpu)
                  qp = qp->next) {
                 thread = _PR_THREAD_PTR(qp);
                 /*
                 * skip non-schedulable threads
                 */
                 PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD));
                 if (thread->no_sched){
                     thread = NULL;
-		    /*
-		     * Need to wakeup cpus to avoid missing a
-		     * runnable thread
-		     */
-		    _PR_MD_WAKEUP_CPUS();
+					/*
+					 * Need to wakeup cpus to avoid missing a
+					 * runnable thread
+					 * Waking up all CPU's need happen only once.
+					 */
+
+					*wakeup_cpus = PR_TRUE;
                     continue;
                 } else if (thread->io_pending == PR_TRUE) {
 					/*
 					 * A thread that is blocked for I/O needs to run
-					 * on the same cpu on which it was blocked
+					 * on the same cpu on which it was blocked. This is because
+					 * the cpu's ioq is accessed without lock protection and scheduling
+					 * the thread on a different cpu would preclude this optimization.
 					 */
                     thread = NULL;
 					continue;
                 } else {
                     /* Pull thread off of its run queue */
                     _PR_DEL_RUNQ(thread);
                     _PR_RUNQ_UNLOCK(cpu);
-    		    return(thread);
+    		    	return(thread);
                 }
             }
         }
         thread = NULL;
     }
     _PR_RUNQ_UNLOCK(cpu);
     return(thread);
 }
@@ -795,16 +802,19 @@ static PRThread *get_thread(_PRCPU *cpu)
 void _PR_Schedule(void)
 {
     PRThread *thread, *me = _PR_MD_CURRENT_THREAD();
     _PRCPU *cpu = me->cpu;
     PRIntn pri;
     PRUint32 r;
     PRCList *qp;
     PRIntn priMin, priMax;
+#if !defined(_PR_LOCAL_THREADS_ONLY) && defined(XP_UNIX)
+    PRBool wakeup_cpus;
+#endif
 
     /* Interrupts must be disabled */
     PR_ASSERT(_PR_IS_NATIVE_THREAD(me) || _PR_MD_GET_INTSOFF() != 0);
 
     /* Since we are rescheduling, we no longer want to */
     _PR_CLEAR_RESCHED_FLAG();
 
     /*
@@ -864,27 +874,35 @@ void _PR_Schedule(void)
                 }
             }
         }
         thread = NULL;
     }
     _PR_RUNQ_UNLOCK(cpu);
 
 #if !defined(_PR_LOCAL_THREADS_ONLY) && defined(XP_UNIX)
+
+	wakeup_cpus = PR_FALSE;
     _PR_CPU_LIST_LOCK();
     for (qp = _PR_CPUQ().next; qp != &_PR_CPUQ(); qp = qp->next) {
 	    if (cpu != _PR_CPU_PTR(qp)) {
-		if ((thread = get_thread(_PR_CPU_PTR(qp))) != NULL) {
-		    thread->cpu = cpu;
-    		    _PR_CPU_LIST_UNLOCK();
-                    goto found_thread;
-		}
+			if ((thread = get_thread(_PR_CPU_PTR(qp), &wakeup_cpus))
+										!= NULL) {
+				thread->cpu = cpu;
+				_PR_CPU_LIST_UNLOCK();
+				if (wakeup_cpus == PR_TRUE)
+					_PR_MD_WAKEUP_CPUS();
+				goto found_thread;
+			}
 	    }
     }
     _PR_CPU_LIST_UNLOCK();
+	if (wakeup_cpus == PR_TRUE)
+		_PR_MD_WAKEUP_CPUS();
+
 #endif		/* _PR_LOCAL_THREADS_ONLY */
 
 idle_thread:
    /*
     ** There are no threads to run. Switch to the idle thread
     */
     PR_LOG(_pr_sched_lm, PR_LOG_MAX, ("pausing"));
     thread = _PR_MD_CURRENT_CPU()->idle_thread;
--- a/pr/src/threads/prcthr.c
+++ b/pr/src/threads/prcthr.c
@@ -13,16 +13,17 @@
  * The Initial Developer of this code under the NPL is Netscape
  * Communications Corporation.  Portions created by Netscape are
  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  * Reserved.
  */
 
 #include "primpl.h"
 
+extern PRLock *_pr_sleeplock;  /* allocated and initialized in prinit */
 /* 
 ** Routines common to both native and user threads.
 **
 **
 ** Clean up a thread object, releasing all of the attached data. Do not
 ** free the object itself (it may not have been malloc'd)
 */
 void _PR_CleanupThread(PRThread *thread)
@@ -80,18 +81,17 @@ PR_IMPLEMENT(PRStatus) PR_Yield()
 ** allowed in the expectation that another thread will interrupt().
 **
 ** A single lock is used for all threads calling sleep. Each caller
 ** does get its own condition variable since each is expected to have
 ** a unique 'timeout'.
 */
 PR_IMPLEMENT(PRStatus) PR_Sleep(PRIntervalTime timeout)
 {
-    static PRLock *ml = NULL;
-    PRStatus rv = PR_SUCCESS;
+     PRStatus rv = PR_SUCCESS;
     if (PR_INTERVAL_NO_WAIT == timeout)
     {
         /*
         ** This is a simple yield, nothing more, nothing less.
         */
         PRIntn is;
         PRThread *me = PR_GetCurrentThread();
         PRUintn pri = me->priority;
@@ -124,37 +124,30 @@ PR_IMPLEMENT(PRStatus) PR_Sleep(PRInterv
     else
     {
         /*
         ** This is waiting for some finite period of time.
         ** A thread in this state is interruptible (PR_Interrupt()),
         ** but the lock and cvar used are local to the implementation
         ** and not visible to the caller, therefore not notifiable.
         */
-        if (ml == NULL) ml = PR_NewLock();
-
-        if (ml == NULL) rv = PR_FAILURE;
-        else
-        {
-            PRCondVar *cv = PR_NewCondVar(ml);
-            PRIntervalTime timein = PR_IntervalNow();
+        PRIntervalTime timein = PR_IntervalNow();
+        PRCondVar *cv = PR_NewCondVar(_pr_sleeplock);
 
-            PR_Lock(ml);
-            while (rv == PR_SUCCESS)
-            {
-                PRIntervalTime delta = PR_IntervalNow() - timein;
-                if (delta > timeout) break;
-                rv = PR_WaitCondVar(cv, timeout - delta);
-            }
-            PR_Unlock(ml);
-
-            PR_DestroyCondVar(cv);
+        PR_Lock(_pr_sleeplock);
+        while (rv == PR_SUCCESS)
+        {
+            PRIntervalTime delta = PR_IntervalNow() - timein;
+            if (delta > timeout) break;
+            rv = PR_WaitCondVar(cv, timeout - delta);
         }
+        PR_Unlock(_pr_sleeplock);
+        PR_DestroyCondVar(cv);
     }
-        return rv;
+    return rv;
 }
 
 PR_IMPLEMENT(PRUint32) PR_GetThreadID(PRThread *thread)
 {
     return thread->id;
 }
 
 PR_IMPLEMENT(PRThreadPriority) PR_GetThreadPriority(const PRThread *thread)
--- a/pr/src/threads/prdump.c
+++ b/pr/src/threads/prdump.c
@@ -99,17 +99,17 @@ void _PR_DumpThreads(PRFileDesc *fd)
 
     _PR_DumpPrintf(fd, "CondVar wait Threads:\n");
     DumpThreadQueue(fd, &_PR_PAUSEQ(t->cpu));
 
     _PR_DumpPrintf(fd, "Suspended Threads:\n");
     DumpThreadQueue(fd, &_PR_SUSPENDQ(t->cpu));
 }
 
-void PR_ShowStatus(void)
+PR_IMPLEMENT(void) PR_ShowStatus(void)
 {
     PRIntn is;
 
     if ( _PR_MD_CURRENT_THREAD()
     && !_PR_IS_NATIVE_THREAD(_PR_MD_CURRENT_THREAD())) _PR_INTSOFF(is);
     _pr_dumpOut = _pr_stderr;
     _PR_DumpThreads(_pr_dumpOut);
     if ( _PR_MD_CURRENT_THREAD()
--- a/pr/tests/accept.c
+++ b/pr/tests/accept.c
@@ -70,17 +70,17 @@ extern void SetupMacPrintfLog(char *logF
 
 #if defined(XP_MAC) || defined(XP_OS2)
 #define TIMEOUTSECS 10
 #else
 #define TIMEOUTSECS 2
 #endif
 PRIntervalTime timeoutTime;
 
-static PRInt32 count = 10;
+static PRInt32 count = 1;
 static PRNetAddr serverAddr;
 static PRThreadScope thread_scope = PR_LOCAL_THREAD;
 
 PRIntn failed_already=0;
 PRIntn debug_mode;
 
 void Test_Assert(const char *msg, const char *file, PRIntn line)
 {
@@ -113,19 +113,19 @@ void timeout_callback(void *magic)
 
 static void PR_CALLBACK
 ClientThread(void *_action)
 {
     PRInt32 action = * (PRInt32 *) _action;
     PRInt32 iterations = count;
     PRFileDesc *sock = NULL;
 
-    serverAddr.inet.family = AF_INET;
+    serverAddr.inet.family = PR_AF_INET;
     serverAddr.inet.port = PR_htons(BASE_PORT);
-    serverAddr.inet.ip = PR_htonl(INADDR_LOOPBACK);
+    serverAddr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
 
     for (; iterations--;) {
         PRInt32 rv;
         char buf[CLIENT_DATA];
 
         sock = PR_NewTCPSocket();
         if (!sock) {
             if (!debug_mode)
@@ -196,51 +196,47 @@ static  PRInt32 bytesRead;
 
 static void 
 RunTest(PRInt32 acceptType, PRInt32 clientAction)
 {
 
     /* First bind to the socket */
     listenSock = PR_NewTCPSocket();
     if (!listenSock) {
-        if (!debug_mode)
-            failed_already=1;
-        else    
+        failed_already=1;
+        if (debug_mode)
             printf("unable to create listen socket\n");
         return;
     }
-    listenAddr.inet.family = AF_INET;
+    listenAddr.inet.family = PR_AF_INET;
     listenAddr.inet.port = PR_htons(BASE_PORT);
-    listenAddr.inet.ip = PR_htonl(INADDR_ANY);
+    listenAddr.inet.ip = PR_htonl(PR_INADDR_ANY);
     rv = PR_Bind(listenSock, &listenAddr);
     if (rv == PR_FAILURE) {
-        if (!debug_mode)
-            failed_already=1;
-        else    
+        failed_already=1;
+        if (debug_mode)
             printf("unable to bind\n");
         return;
     }
 
     rv = PR_Listen(listenSock, 100);
     if (rv == PR_FAILURE) {
-        if (!debug_mode)
-            failed_already=1;
-        else    
+        failed_already=1;
+        if (debug_mode)
             printf("unable to listen\n");
         return;
     }
 
     clientCommand = clientAction;
     clientThread = PR_CreateThread(PR_USER_THREAD, ClientThread,
         (void *)&clientCommand, PR_PRIORITY_NORMAL, thread_scope,
         PR_JOINABLE_THREAD, 0);
     if (!clientThread) {
-        if (!debug_mode)
-            failed_already=1;
-        else    
+        failed_already=1;
+        if (debug_mode)
             printf("error creating client thread\n");
         return;
     }
 
     iterations = count;
     for (;iterations--;) {
         switch (acceptType) {
         case ACCEPT_NORMAL:
@@ -465,17 +461,16 @@ int main(int argc, char **argv)
             count = atoi(opt->value);
             break;
         default:
             break;
         }
     }
     PL_DestroyOptState(opt);
 
-
     PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
     PR_STDIO_INIT();
 
 #ifdef XP_MAC
     SetupMacPrintfLog("accept.log");
     debug_mode = 1;
 #endif
 
@@ -490,19 +485,19 @@ int main(int argc, char **argv)
     Measure(AcceptReadNotUpdatedTest, "PR_NTFast_AcceptRead()");
     Measure(AcceptReadCallbackTest, "PR_NTFast_AcceptRead_WithTimeoutCallback()");
 #endif
     if (debug_mode)
         printf("\nRun accept() timeout in the accept tests\n");
 #ifdef WINNT
     Measure(TimeoutReadReadCallbackTest, "PR_NTFast_AcceptRead_WithTimeoutCallback()");
 #endif
+    Measure(TimeoutReadUpdatedTest, "PR_Accept()");
     if (debug_mode)
         printf("\nRun accept() timeout in the read tests\n");
-    Measure(TimeoutReadUpdatedTest, "PR_Accept()");
     Measure(TimeoutReadReadTest, "PR_AcceptRead()");
 #ifdef WINNT
     Measure(TimeoutReadNotUpdatedTest, "PR_NTFast_Accept()");
     Measure(TimeoutReadReadNotUpdatedTest, "PR_NTFast_AcceptRead()");
     Measure(TimeoutReadReadCallbackTest, "PR_NTFast_AcceptRead_WithTimeoutCallback()");
 #endif
     if(failed_already)
     {
--- a/pr/tests/alarm.c
+++ b/pr/tests/alarm.c
@@ -234,17 +234,17 @@ static PRBool AlarmFn1(PRAlarmID *id, vo
     return keepGoing;
 }  /* AlarmFn1 */
 
 static PRIntervalTime Alarms1(PRUint32 loops)
 {
     PRAlarm *alarm;
     AlarmData ad;
     PRIntervalTime overhead, timein = PR_IntervalNow();
-    PRIntervalTime duration = PR_SecondsToInterval(30);
+    PRIntervalTime duration = PR_SecondsToInterval(3);
 
     PRLock *ml = PR_NewLock();
     PRCondVar *cv = PR_NewCondVar(ml);
 
     ad.ml = ml;
     ad.cv = cv;
     ad.rate = 1;
     ad.times = loops;
@@ -464,17 +464,17 @@ static PRUint32 TimeThis(
             usecs, overhead, ((double)(usecs - overhead) / (double)loops));
     }
 
     return overhead;
 }  /* TimeThis */
 
 int prmain(int argc, char** argv)
 {
-    PRUint32 cpu, cpus = 2, loops = 100;
+    PRUint32 cpu, cpus = 0, loops = 0;
 
 	/* The command line argument: -d is used to determine if the test is being run
 	in debug mode. The regress tool requires only one line output:PASS or FAIL.
 	All of the printfs associated with this test has been handled with a if (debug_mode)
 	test.
 	Usage: test_name [-d]
 	*/
 	PLOptStatus os;
@@ -498,18 +498,18 @@ int prmain(int argc, char** argv)
             break;
          default:
             break;
         }
     }
 	PL_DestroyOptState(opt);
 
 
-    if (cpus == 0) cpus = 2;
-    if (loops == 0) loops = 100;
+    if (cpus == 0) cpus = 1;
+    if (loops == 0) loops = 4;
 
 	if (debug_mode)
 		printf("Alarm: Using %d loops\n", loops);
 
 	if (debug_mode)		
         printf("Alarm: Using %d cpu(s)\n", cpus);
 #ifdef XP_MAC
 	SetupMacPrintfLog("alarm.log");
--- a/pr/tests/atomic.c
+++ b/pr/tests/atomic.c
@@ -54,22 +54,31 @@ PRIntn main(PRIntn argc, char **argv)
         output, "PR_AtomicDecrement(%d) == %d: %s\n",
         test, rv, (rv == 0) ? "PASSED" : "FAILED");
     rv = PR_AtomicDecrement(&test);
     result = result | ((rv < 0) ? 0 : 1);
     PR_fprintf(
         output, "PR_AtomicDecrement(%d) == %d: %s\n",
         test, rv, (rv < 0) ? "PASSED" : "FAILED");
 
+    /* set to a different value */
     test = -2;
     rv = PR_AtomicSet(&test, 2);
     result = result | (((rv == -2) && (test == 2)) ? 0 : 1);
     PR_fprintf(
         output, "PR_AtomicSet(%d) == %d: %s\n",
         test, rv, ((rv == -2) && (test == 2)) ? "PASSED" : "FAILED");
 
+    /* set to the same value */
+    test = -2;
+    rv = PR_AtomicSet(&test, -2);
+    result = result | (((rv == -2) && (test == -2)) ? 0 : 1);
+    PR_fprintf(
+        output, "PR_AtomicSet(%d) == %d: %s\n",
+        test, rv, ((rv == -2) && (test == -2)) ? "PASSED" : "FAILED");
+
     PR_fprintf(
         output, "Atomic operations test %s\n",
         (result == 0) ? "PASSED" : "FAILED");
     return result;
 }  /* main */
 
 /* atomic.c */
--- a/pr/tests/attach.c
+++ b/pr/tests/attach.c
@@ -43,26 +43,19 @@
 /* Used to get the command line option */
 #include "nspr.h"
 #include "pprthred.h"
 #include "plgetopt.h"
 
 #include <stdio.h>
 
 #ifdef WIN32
-#include "process.h"
+#include <windows.h>
+#include <process.h>
 #elif defined(_PR_PTHREADS)
-/*
- * XXX: On Linux 2.0.27 (installed on tioman.mcom.com), sched.h uses
- * this _P macro that seems to be undefined.  I suspect that it is
- * a typo (should be __P).
- */
-#if defined(LINUX)
-#define _P(x) __P(x)
-#endif
 #include <pthread.h>
 #include "md/_pth.h"
 #elif defined(IRIX)
 #include <sys/types.h>
 #include <sys/prctl.h>
 #include <sys/wait.h>
 #include <errno.h>
 #elif defined(SOLARIS)
--- a/pr/tests/cltsrv.c
+++ b/pr/tests/cltsrv.c
@@ -862,41 +862,26 @@ static void PR_CALLBACK Server(void *arg
         ("\tServer(0x%lx): stopped after %lu operations and %lu bytes\n",
         me, server->operations, server->bytesTransferred));
 
     if (NULL != server->listener) PR_Close(server->listener);
     server->stopped = PR_IntervalNow();
 
 }  /* Server */
 
-#if 0 && defined(DEBUG) && defined(_PR_PTHREADS)
+#if defined(DEBUG) && defined(_PR_PTHREADS)
 static void PrintPthreadStats(void)
 {
-    char buffer[100];
-    PRExplodedTime tod;
-    PTDebug stats = PT_GetStats();
-    PRInt64 elapsed, aMil;
-    PR_ExplodeTime(stats.timeStarted, PR_LocalTimeParameters, &tod);
-    (void)PR_FormatTime(buffer, sizeof(buffer), "%T", &tod);
-
-    LL_SUB(elapsed, PR_Now(), stats.timeStarted);
-    LL_I2L(aMil, 1000000);
-    LL_DIV(elapsed, elapsed, aMil);
-    PR_fprintf(debug_out, "\npthread statistics\n\tstarted: %s[%lld]\n", buffer, elapsed);
-    PR_fprintf(debug_out, "\tmissed predictions: %u\n", stats.predictionsFoiled);
-    PR_fprintf(debug_out, "\tpollingList max: %u\n", stats.pollingListMax);
-    PR_fprintf(debug_out, "\tcontinuations served: %u\n", stats.continuationsServed);
-    PR_fprintf(debug_out, "\trecycles needed: %u\n", stats.recyclesNeeded);
-    PR_fprintf(debug_out, "\tquiescent IO: %u\n", stats.quiescentIO);
+    PT_FPrintStats(debug_out, "\nPThread Statistics\n");
 }  /* PrintPthreadStats */
 #endif /* defined(DEBUG) && defined(_PR_PTHREADS) */
 
 static void WaitForCompletion(PRIntn execution)
 {
-#if 0 && defined(DEBUG) && defined(_PR_PTHREADS)
+#if defined(DEBUG) && defined(_PR_PTHREADS)
     while (execution > 0)
     { 
         PRIntn dally = (execution > 30) ? 30 : execution;
         PR_Sleep(PR_SecondsToInterval(dally));
         if (pthread_stats) PrintPthreadStats();
         execution -= dally;
     }
 #else
@@ -925,17 +910,18 @@ static void Help(void)
     PR_fprintf(debug_out, "\t-h           this message\n");
 }  /* Help */
 
 static Verbosity IncrementVerbosity(void)
 {
     PRIntn verboge = (PRIntn)verbosity + 1;
     return (Verbosity)verboge;
 }  /* IncrementVerbosity */
-PRIntn xmain(PRIntn argc, char** argv)
+
+PRIntn main(PRIntn argc, char** argv)
 {
     PRUintn index;
     PRBool boolean;
     CSClient_t *client;
     PRStatus rv, joinStatus;
     CSServer_t *server = NULL;
 
     PRUintn backlog = DEFAULT_BACKLOG;
@@ -955,17 +941,17 @@ PRIntn xmain(PRIntn argc, char** argv)
      * -w <threads> minimal number of server threads
      * -W <threads> maximum number of server threads
      * -e <seconds> duration of the test in seconds
      * -s <string>  dsn name of server (implies no server here)
      * -v           verbosity
      */
 
     PLOptStatus os;
-    PLOptState *opt = PL_CreateOptState(argc, argv, "GX6b:a:c:l:w:W:e:s:vdhp");
+    PLOptState *opt = PL_CreateOptState(argc, argv, "GX6b:a:c:w:W:e:s:vdhp");
 
     debug_out = PR_GetSpecialFD(PR_StandardError);
 
     while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
     {
         if (PL_OPT_BAD == os) continue;
         switch (opt->option)
         {
@@ -985,18 +971,16 @@ PRIntn xmain(PRIntn argc, char** argv)
             accepting = atoi(opt->value);
             break;
         case 'b':  /* the value for backlock */
             backlog = atoi(opt->value);
             break;
         case 'c':  /* number of client threads */
             clients = atoi(opt->value);
             break;
-        case 'l':  /* number of outer loops */
-            break;
         case 'w':  /* minimum server worker threads */
             workersMin = atoi(opt->value);
             break;
         case 'W':  /* maximum server worker threads */
             workersMax = atoi(opt->value);
             break;
         case 'e':  /* program execution time in seconds */
             execution = atoi(opt->value);
@@ -1207,45 +1191,17 @@ PRIntn xmain(PRIntn argc, char** argv)
         PR_DestroyLock(server->ml);
         PR_DELETE(server);
     }
 
     TEST_LOG(
         cltsrv_log_file, TEST_LOG_ALWAYS, 
         ("main(0x%lx): test complete\n", PR_CurrentThread()));
 
-#if 0 && defined(DEBUG) && defined(_PR_PTHREADS)
+#if defined(DEBUG) && defined(_PR_PTHREADS)
     PrintPthreadStats();
 #endif  /* defined(DEBUG) && defined(_PR_PTHREADS) */
 
     TimeOfDayMessage("Test exiting at", PR_CurrentThread());
     return 0;
-}  /* xmain */
-
-PRIntn main(PRIntn argc, char **argv)
-{
-    PRIntn loops = 1;
-    PRIntn rv;
-    PLOptStatus os;
-    PLOptState *opt = PL_CreateOptState(argc, argv, "GX6b:a:c:l:w:W:e:s:vdhp");
-    while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
-    {
-        if (PL_OPT_BAD == os) continue;
-        switch (opt->option)
-        {
-        case 'l':  /* number of outer loops */
-            loops = atoi(opt->value);
-            break;
-        default:
-            break;
-        }
-    }
-    PL_DestroyOptState(opt);
-    while (loops-- > 0)
-    {
-        rv = xmain(argc, argv);
-        PR_fprintf(debug_out, "*****\n\n");
-        if (0 != rv) break;
-    }
-    return rv;
 }  /* main */
 
 /* cltsrv.c */
--- a/pr/tests/intrupt.c
+++ b/pr/tests/intrupt.c
@@ -189,18 +189,18 @@ void PR_CALLBACK Intrupt(void *arg)
     rv = PR_JoinThread(abortJoin);
     PR_ASSERT(PR_SUCCESS == rv);
     if (debug_mode) printf("and succeeded\n");
 
     /* Part III */
     if (debug_mode) printf("Part III\n");
     listner = PR_NewTCPSocket();
     memset(&netaddr, 0, sizeof(netaddr));
-    netaddr.inet.ip = PR_htonl(INADDR_ANY);
-    netaddr.inet.family = AF_INET;
+    netaddr.inet.ip = PR_htonl(PR_INADDR_ANY);
+    netaddr.inet.family = PR_AF_INET;
     do
     {
         netaddr.inet.port = PR_htons(port);
         rv = PR_Bind(listner, &netaddr);
         port += 1;
         PR_ASSERT(port < (12848 + 10));
     } while (PR_FAILURE == rv);
 
--- a/pr/tests/io_timeout.c
+++ b/pr/tests/io_timeout.c
@@ -70,19 +70,19 @@ thread_main(void *_info)
     printf("thread %d is alive\n", info->id);
 
     listenSock = PR_NewTCPSocket();
     if (!listenSock) {
         printf("unable to create listen socket\n");
         goto dead;
     }
   
-    listenAddr.inet.family = AF_INET;
+    listenAddr.inet.family = PR_AF_INET;
     listenAddr.inet.port = PR_htons(BASE_PORT + info->id);
-    listenAddr.inet.ip = PR_htonl(INADDR_ANY);
+    listenAddr.inet.ip = PR_htonl(PR_INADDR_ANY);
     rv = PR_Bind(listenSock, &listenAddr);
     if (rv == PR_FAILURE) {
         printf("unable to bind\n");
         goto dead;
     }
 
     rv = PR_Listen(listenSock, 4);
     if (rv == PR_FAILURE) {
--- a/pr/tests/ipv6.c
+++ b/pr/tests/ipv6.c
@@ -60,16 +60,17 @@ static PRStatus PrintAddress(const PRNet
 {
     PRNetAddr translation;
     char buffer[ADDR_BUFFER];
     PRStatus rv = PR_NetAddrToString(address, buffer, sizeof(buffer));
     if (PR_FAILURE == rv) PL_FPrintError(err, "PR_NetAddrToString");
     else
     {
         PR_fprintf(err, "\t%s\n", buffer);
+        memset(&translation, 0, sizeof(translation));
         rv = PR_StringToNetAddr(buffer, &translation);
         if (PR_FAILURE == rv) PL_FPrintError(err, "PR_StringToNetAddr");
         else
         {
             PRSize addr_len = PR_NETADDR_SIZE(address);
             if (0 != memcmp(address, &translation, addr_len))
             {
                 PR_fprintf(err, "Address translations do not match\n");
--- a/pr/tests/layer.c
+++ b/pr/tests/layer.c
@@ -56,17 +56,17 @@ static PRUint16 default_port = 12273;
 
 static PRFileDesc *PushLayer(PRFileDesc *stack)
 {
     PRFileDesc *layer = PR_CreateIOLayerStub(identity, &myMethods);
     PRStatus rv = PR_PushIOLayer(stack, PR_GetLayersIdentity(stack), layer);
     if (verbosity > quiet)
         PR_fprintf(logFile, "Pushed layer(0x%x) onto stack(0x%x)\n", layer, stack);
     PR_ASSERT(PR_SUCCESS == rv);
-    return layer;
+    return stack;
 }  /* PushLayer */
 
 static PRFileDesc *PopLayer(PRFileDesc *stack)
 {
     PRFileDesc *popped = PR_PopIOLayer(stack, identity);
     if (verbosity > quiet)
         PR_fprintf(logFile, "Popped layer(0x%x) from stack(0x%x)\n", popped, stack);
     popped->dtor(popped);
@@ -144,29 +144,101 @@ static void PR_CALLBACK Server(void *arg
 
     if (verbosity > quiet)
         PR_fprintf(logFile, "Server shutting down and closing stack\n");
     rv = PR_Shutdown(service, PR_SHUTDOWN_BOTH); PR_ASSERT(PR_SUCCESS == rv);
     rv = PR_Close(service); PR_ASSERT(PR_SUCCESS == rv);
 
 }  /* Server */
 
+static PRInt32 PR_CALLBACK MyRecv(
+    PRFileDesc *fd, void *buf, PRInt32 amount,
+    PRIntn flags, PRIntervalTime timeout)
+{
+    char *b = (char*)buf;
+    PRFileDesc *lo = fd->lower;
+    PRInt32 rv, readin = 0, request;
+    rv = lo->methods->recv(lo, &request, sizeof(request), flags, timeout);
+    if (verbosity > chatty) PR_fprintf(
+        logFile, "MyRecv sending permission for %d bytes\n", request);
+    if (0 < rv)
+    {
+        if (verbosity > chatty) PR_fprintf(
+            logFile, "MyRecv received permission request for %d bytes\n", request);
+        rv = lo->methods->send(
+            lo, &request, sizeof(request), flags, timeout);
+        if (0 < rv)
+        {
+            if (verbosity > chatty) PR_fprintf(
+                logFile, "MyRecv sending permission for %d bytes\n", request);
+            while (readin < request)
+            {
+                rv = lo->methods->recv(
+                    lo, b + readin, amount - readin, flags, timeout);
+                if (rv <= 0) break;
+                if (verbosity > chatty) PR_fprintf(
+                    logFile, "MyRecv received %d bytes\n", rv);
+                readin += rv;
+            }
+            rv = readin;
+        }
+    }
+    return rv;
+}  /* MyRecv */
+
+static PRInt32 PR_CALLBACK MySend(
+    PRFileDesc *fd, const void *buf, PRInt32 amount,
+    PRIntn flags, PRIntervalTime timeout)
+{
+    PRFileDesc *lo = fd->lower;
+    const char *b = (const char*)buf;
+    PRInt32 rv, wroteout = 0, request;
+    if (verbosity > chatty) PR_fprintf(
+        logFile, "MySend asking permission to send %d bytes\n", amount);
+    rv = lo->methods->send(lo, &amount, sizeof(amount), flags, timeout);
+    if (0 < rv)
+    {
+        rv = lo->methods->recv(
+            lo, &request, sizeof(request), flags, timeout);
+        if (0 < rv)
+        {
+            PR_ASSERT(request == amount);
+            if (verbosity > chatty) PR_fprintf(
+                logFile, "MySend got permission to send %d bytes\n", request);
+            while (wroteout < request)
+            {
+                rv = lo->methods->send(
+                    lo, b + wroteout, request - wroteout, flags, timeout);
+                if (rv <= 0) break;
+                if (verbosity > chatty) PR_fprintf(
+                    logFile, "MySend wrote %d bytes\n", rv);
+                wroteout += rv;
+            }
+            rv = amount;
+        }
+    }
+    return rv;
+}  /* MySend */
+
 static Verbosity ChangeVerbosity(Verbosity verbosity, PRIntn delta)
 {
-    PRIntn verbage = (PRIntn)verbosity;
-    return (Verbosity)(verbage + delta);
+    PRIntn verbage = (PRIntn)verbosity + delta;
+    if (verbage < (PRIntn)silent) verbage = (PRIntn)silent;
+    else if (verbage > (PRIntn)noisy) verbage = (PRIntn)noisy;
+    return (Verbosity)verbage;
 }  /* ChangeVerbosity */
 
 PRIntn main(PRIntn argc, char **argv)
 {
     PRStatus rv;
+    PRIntn mits;
     PLOptStatus os;
     PRFileDesc *client, *service;
     const char *server_name = NULL;
-    PRIOMethods const *stubMethods;
+    const PRIOMethods *stubMethods;
     PRThread *client_thread, *server_thread;
     PRThreadScope thread_scope = PR_LOCAL_THREAD;
     PLOptState *opt = PL_CreateOptState(argc, argv, "dqGC:c:p:");
     while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
     {
         if (PL_OPT_BAD == os) continue;
         switch (opt->option)
         {
@@ -201,43 +273,47 @@ PRIntn main(PRIntn argc, char **argv)
     PR_STDIO_INIT();
 
     logFile = PR_GetSpecialFD(PR_StandardError);
 
     identity = PR_GetUniqueIdentity("Dummy");
     stubMethods = PR_GetDefaultIOMethods();
 
     /*
-    ** Normally here one would pick and choose between the default
-    ** stub methods and local, unique implmentation. I'm not going
-    ** quite that far.
+    ** The protocol we're going to implement is one where in order to initiate
+    ** a send, the sender must first solicit permission. Therefore, every
+    ** send is really a send - receive - send sequence.
     */
-    myMethods = *stubMethods;
+    myMethods = *stubMethods;  /* first get the entire batch */
+    myMethods.recv = MyRecv;  /* then override the ones we care about */
+    myMethods.send = MySend;  /* then override the ones we care about */
 
     if (NULL == server_name)
         rv = PR_InitializeNetAddr(
             PR_IpAddrLoopback, default_port, &server_address);
     else
     {
         rv = PR_StringToNetAddr(server_name, &server_address);
         PR_ASSERT(PR_SUCCESS == rv);
         rv = PR_InitializeNetAddr(
             PR_IpAddrNull, default_port, &server_address);
     }
     PR_ASSERT(PR_SUCCESS == rv);
 
     /* one type w/o layering */
 
+    mits = minor_iterations;
     while (major_iterations-- > 0)
     {
         if (verbosity > silent)
             PR_fprintf(logFile, "Beginning non-layered test\n");
         client = PR_NewTCPSocket(); PR_ASSERT(NULL != client);
         service = PR_NewTCPSocket(); PR_ASSERT(NULL != service);
 
+        minor_iterations = mits;
         server_thread = PR_CreateThread(
             PR_USER_THREAD, Server, service,
             PR_PRIORITY_HIGH, thread_scope,
             PR_JOINABLE_THREAD, 16 * 1024);
         PR_ASSERT(NULL != server_thread);
 
         client_thread = PR_CreateThread(
             PR_USER_THREAD, Client, client,
@@ -256,16 +332,17 @@ PRIntn main(PRIntn argc, char **argv)
             PR_fprintf(logFile, "Ending non-layered test\n");
 
         /* with layering */
         if (verbosity > silent)
             PR_fprintf(logFile, "Beginning layered test\n");
         client = PR_NewTCPSocket(); PR_ASSERT(NULL != client);
         service = PR_NewTCPSocket(); PR_ASSERT(NULL != service);
 
+        minor_iterations = mits;
         server_thread = PR_CreateThread(
             PR_USER_THREAD, Server, PushLayer(service),
             PR_PRIORITY_HIGH, thread_scope,
             PR_JOINABLE_THREAD, 16 * 1024);
         PR_ASSERT(NULL != server_thread);
 
         client_thread = PR_CreateThread(
             PR_USER_THREAD, Client, PushLayer(client),
--- a/pr/tests/many_cv.c
+++ b/pr/tests/many_cv.c
@@ -19,44 +19,56 @@
 #include "prinit.h"
 #include "prprf.h"
 #include "prthread.h"
 #include "prcvar.h"
 #include "prlock.h"
 #include "prlog.h"
 #include "prmem.h"
 
+#include "primpl.h"
+
 #include "plgetopt.h"
 
 #include <stdlib.h>
 
+static PRInt32 Random(void)
+{
+    PRInt32 ran = rand() >> 16;
+    return ran;
+}  /* Random */
+
 static void Help(void)
 {
     PRFileDesc *err = PR_GetSpecialFD(PR_StandardError);
     PR_fprintf(err, "many_cv usage: [-c n] [-l n] [-h]\n");
     PR_fprintf(err, "\t-c n Number of conditions per lock       (default: 10)\n");
     PR_fprintf(err, "\t-l n Number of times to loop the test    (default:  1)\n");
     PR_fprintf(err, "\t-h   This message and nothing else\n");
 }  /* Help */
 
 static PRIntn PR_CALLBACK RealMain( PRIntn argc, char **argv )
 {
     PLOptStatus os;
     PRIntn index, nl;
     PRLock *ml = NULL;
     PRCondVar **cv = NULL;
-    PRIntn loops = 1, cvs = 10;
+    PRBool stats = PR_FALSE;
+    PRIntn nc, loops = 1, cvs = 10;
     PRFileDesc *err = PR_GetSpecialFD(PR_StandardError);
-    PLOptState *opt = PL_CreateOptState(argc, argv, "hc:l:");
+    PLOptState *opt = PL_CreateOptState(argc, argv, "hsc:l:");
 
     while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
     {
         if (PL_OPT_BAD == os) continue;
         switch (opt->option)
         {
+        case 's':  /* number of CVs to association with lock */
+            stats = PR_TRUE;
+            break;
         case 'c':  /* number of CVs to association with lock */
             cvs = atoi(opt->value);
             break;
         case 'l':  /* number of times to run the tests */
             loops = atoi(opt->value);
             break;
         case 'h':  /* user wants some guidance */
          default:
@@ -81,27 +93,35 @@ static PRIntn PR_CALLBACK RealMain( PRIn
         cv[index] = PR_NewCondVar(ml);
         PR_ASSERT(NULL != cv[index]);
     }
 
     for (index = 0; index < loops; ++index)
     {
         PR_Lock(ml);
         for (nl = 0; nl < cvs; ++nl)
-            PR_NotifyCondVar(cv[nl]);
+        {
+            PRInt32 ran = Random() % 8;
+            if (0 == ran) PR_NotifyAllCondVar(cv[nl]);
+            else for (nc = 0; nc < ran; ++nc)
+                PR_NotifyCondVar(cv[nl]);
+        }
         PR_Unlock(ml);
     }
 
     for (index = 0; index < cvs; ++index)
         PR_DestroyCondVar(cv[index]);
 
     PR_DestroyLock(ml);
     
     printf("PASS\n");
 
+#if defined(DEBUG) && defined(_PR_PTHREADS)
+    PT_FPrintStats(err, "\nPThread Statistics\n");
+#endif /* defined(DEBUG) && defined(_PR_PTHREADS) */
     return 0;
 }
 
 
 PRIntn main(PRIntn argc, char **argv)
 {
     PRIntn rv;
     
--- a/pr/tests/nonblock.c
+++ b/pr/tests/nonblock.c
@@ -69,19 +69,19 @@ clientThreadFunc(void *arg)
     PRNetAddr addr;
     char buf[CHUNK_SIZE];
     int i;
     PRIntervalTime unitTime = PR_MillisecondsToInterval(UNIT_TIME);
     PRIntn optval = 1;
     PRStatus retVal;
     PRInt32 nBytes;
 
-    addr.inet.family = AF_INET;
+    addr.inet.family = PR_AF_INET;
     addr.inet.port = PR_htons((PRUint16)port);
-    addr.inet.ip = PR_htonl(INADDR_LOOPBACK);
+    addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
     PR_snprintf(buf, sizeof(buf), "%hu", addr.inet.ip);
 
     /* time 1 */
     PR_Sleep(unitTime);
     sock = PR_NewTCPSocket();
     PR_SetSockOpt(sock, PR_SockOpt_Nonblocking, &optval, sizeof(optval));
     retVal = PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT);
     if (retVal == PR_FAILURE && PR_GetError() == PR_IN_PROGRESS_ERROR) {
@@ -143,18 +143,18 @@ static PRIntn PR_CALLBACK RealMain( PRIn
 	SetupMacPrintfLog("nonblock.log");
 #endif
 
     /* Create a listening socket */
     if ((listenSock = PR_NewTCPSocket()) == NULL) {
 	fprintf(stderr, "Can't create a new TCP socket\n");
 	exit(1);
     }
-    addr.inet.family = AF_INET;
-    addr.inet.ip = PR_htonl(INADDR_ANY);
+    addr.inet.family = PR_AF_INET;
+    addr.inet.ip = PR_htonl(PR_INADDR_ANY);
     addr.inet.port = PR_htons(0);
     if (PR_Bind(listenSock, &addr) == PR_FAILURE) {
 	fprintf(stderr, "Can't bind socket\n");
 	exit(1);
     }
     if (PR_GetSockName(listenSock, &addr) == PR_FAILURE) {
 	fprintf(stderr, "PR_GetSockName failed\n");
 	exit(1);
--- a/pr/tests/poll_nm.c
+++ b/pr/tests/poll_nm.c
@@ -80,19 +80,19 @@ clientThreadFunc(void *arg)
     PRUintn port = (PRUintn) arg;
     PRFileDesc *sock;
     PRNetAddr addr;
     char buf[128];
     int i;
     PRStatus sts;
     PRInt32 n;
 
-    addr.inet.family = AF_INET;
+    addr.inet.family = PR_AF_INET;
     addr.inet.port = PR_htons((PRUint16)port);
-    addr.inet.ip = PR_htonl(INADDR_LOOPBACK);
+    addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
     memset(buf, 0, sizeof(buf));
     PR_snprintf(buf, sizeof(buf), "%hu", addr.inet.ip);
 
     for (i = 0; i < NUM_ITERATIONS; i++) {
 	sock = PR_NewTCPSocket();
 	PR_ASSERT(sock != NULL);
 	
     sts = PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT);
@@ -157,18 +157,18 @@ int main(int argc, char **argv)
 	}
 
     /* Create two listening sockets */
     if ((listenSock1 = PR_NewTCPSocket()) == NULL) {
 	fprintf(stderr, "Can't create a new TCP socket\n");
 	failed_already=1;
 	goto exit_now;
     }
-    addr.inet.family = AF_INET;
-    addr.inet.ip = PR_htonl(INADDR_ANY);
+    addr.inet.family = PR_AF_INET;
+    addr.inet.ip = PR_htonl(PR_INADDR_ANY);
     addr.inet.port = PR_htons(0);
     if (PR_Bind(listenSock1, &addr) == PR_FAILURE) {
 	fprintf(stderr, "Can't bind socket\n");
 	failed_already=1;
 	goto exit_now;
     }
     if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) {
 	fprintf(stderr, "PR_GetSockName failed\n");
@@ -183,18 +183,18 @@ int main(int argc, char **argv)
 	goto exit_now;
     }
 
     if ((listenSock2  = PR_NewTCPSocket()) == NULL) {
 	fprintf(stderr, "Can't create a new TCP socket\n");
 	failed_already=1;	
 	goto exit_now;
     }
-    addr.inet.family = AF_INET;
-    addr.inet.ip = PR_htonl(INADDR_ANY);
+    addr.inet.family = PR_AF_INET;
+    addr.inet.ip = PR_htonl(PR_INADDR_ANY);
     addr.inet.port = PR_htons(0);
     if (PR_Bind(listenSock2, &addr) == PR_FAILURE) {
 	fprintf(stderr, "Can't bind socket\n");
 	failed_already=1;	
 	goto exit_now;
     }
     if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) {
 	fprintf(stderr, "PR_GetSockName failed\n");
--- a/pr/tests/poll_to.c
+++ b/pr/tests/poll_to.c
@@ -100,18 +100,18 @@ int main(int argc, char **argv)
 	}
 
     /* Create two listening sockets */
     if ((listenSock1 = PR_NewTCPSocket()) == NULL) {
 	fprintf(stderr, "Can't create a new TCP socket\n");
 	if (!debug_mode)  failed_already=1;
 	goto exit_now;
     }
-    addr.inet.family = AF_INET;
-    addr.inet.ip = PR_htonl(INADDR_ANY);
+    addr.inet.family = PR_AF_INET;
+    addr.inet.ip = PR_htonl(PR_INADDR_ANY);
     addr.inet.port = PR_htons(0);
     if (PR_Bind(listenSock1, &addr) == PR_FAILURE) {
 	fprintf(stderr, "Can't bind socket\n");
 	if (!debug_mode)  failed_already=1;
 	goto exit_now;
     }
     if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) {
 	fprintf(stderr, "PR_GetSockName failed\n");
@@ -125,18 +125,18 @@ int main(int argc, char **argv)
 	goto exit_now;
     }
 
     if ((listenSock2  = PR_NewTCPSocket()) == NULL) {
 	fprintf(stderr, "Can't create a new TCP socket\n");
 	if (!debug_mode)  failed_already=1;	
 	goto exit_now;
     }
-    addr.inet.family = AF_INET;
-    addr.inet.ip = PR_htonl(INADDR_ANY);
+    addr.inet.family = PR_AF_INET;
+    addr.inet.ip = PR_htonl(PR_INADDR_ANY);
     addr.inet.port = PR_htons(0);
     if (PR_Bind(listenSock2, &addr) == PR_FAILURE) {
 	fprintf(stderr, "Can't bind socket\n");
 	if (!debug_mode)  failed_already=1;	
 	goto exit_now;
     }
     if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) {
 	fprintf(stderr, "PR_GetSockName failed\n");
--- a/pr/tests/priotest.c
+++ b/pr/tests/priotest.c
@@ -16,48 +16,43 @@
  * Reserved.
  */
 
 /*
  * File:        priotest.c
  * Purpose:     testing priorities
  */
 
+#ifdef XP_MAC
+#error "This test does not run on Macintosh"
+#else
+
+
 #include "prcmon.h"
 #include "prinit.h"
 #include "prinrval.h"
 #include "prlock.h"
 #include "prlog.h"
 #include "prmon.h"
 #include "prprf.h"
 #include "prthread.h"
 #include "prtypes.h"
 
 #include "plerror.h"
 #include "plgetopt.h"
 
 #include <stdio.h>
 #include <stdlib.h>
 
-#ifdef XP_MAC
-#include "prlog.h"