fixup commit for branch 'SUN_6_2_1_BRANCH' SUN_6_2_1_BRANCH
authorcvs2hg
Tue, 09 Oct 2001 02:16:59 +0000
branchSUN_6_2_1_BRANCH
changeset 2077 4780978e1aeb600abbf65b5758d5cbf94de0e5cf
parent 2016 8e47a5d8f3f35f33f951a82ac610cf81cc6e3243
push idunknown
push userunknown
push dateunknown
fixup commit for branch 'SUN_6_2_1_BRANCH'
config/nspr-config.in
config/prdepend.h
macbuild/NSPR20PPC.mcp
pr/include/md/_macos.h
pr/include/md/_pth.h
pr/include/private/primpl.h
pr/src/md/mac/macio.c
pr/src/md/mac/macrng.c
pr/src/md/mac/macsockotpt.c
pr/src/md/mac/macthr.c
pr/src/md/mac/mdcriticalregion.c
pr/src/md/mac/mdcriticalregion.h
pr/src/md/mac/mdmac.c
pr/src/md/unix/unix_errors.c
pr/src/misc/prnetdb.c
pr/src/misc/prtime.c
pr/src/pthreads/ptsynch.c
--- a/config/nspr-config.in
+++ b/config/nspr-config.in
@@ -102,15 +102,15 @@ if test "$echo_libs" = "yes"; then
       if test -n "$lib_plc"; then
 	libdirs="$libdirs -lplc${major_version}"
       fi
       if test -n "$lib_nspr"; then
 	libdirs="$libdirs -lnspr${major_version}"
       fi
       os_ldflags="@LDFLAGS@"
       for i in $os_ldflags ; do
-	if echo $i | grep ^-L >/dev/null; then
+	if echo $i | grep \^-L >/dev/null; then
 	  libdirs="$libdirs $i"
         fi
       done
       echo $libdirs @OS_LIBS@
 fi      
 
--- a/config/prdepend.h
+++ b/config/prdepend.h
@@ -34,8 +34,9 @@
 
 /*
  * A dummy header file that is a dependency for all the object files.
  * Used to force a full recompilation of NSPR in Mozilla's Tinderbox
  * depend builds.  See comments in rules.mk.
  */
 
 #error "Do not include this header file."
+
index a0a17543ac92688733d1c3145654aaba60558ccf..b305f7566f2194d8e2ee0031e4de89443061a9d9
GIT binary patch
literal 163969
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
BC364(
--- a/pr/include/md/_macos.h
+++ b/pr/include/md/_macos.h
@@ -115,34 +115,50 @@ struct _MDFileDesc {
 	PRBool      orderlyDisconnect;
 	PRBool      readReady;
 	PRBool      writeReady;
 	PRBool      exceptReady;
 	PRLock *    miscLock;
 	
 	/* Server sockets: listen bit tells the notifier func what to do */
 	PRBool		doListen;
-	
+
 	_MDSocketCallerInfo  misc;
 	_MDSocketCallerInfo  read;
 	_MDSocketCallerInfo  write;
-	_MDSocketCallerInfo  poll;
 };
 
 /*
 ** Iinitialization Related definitions
 */
 
 #define _MD_EARLY_INIT		_MD_EarlyInit
 #define _MD_FINAL_INIT		_MD_FinalInit
 
 /*
 ** Interrupts Related definitions
 */
 
+#define _MD_GET_INTSOFF()               (_pr_intsOff)
+
+#define _MD_INTSOFF(_is)                                  \
+    PR_BEGIN_MACRO                                        \
+        ENTER_CRITICAL_REGION();                          \
+        (_is) = _PR_MD_GET_INTSOFF();                     \
+        _PR_MD_SET_INTSOFF(1);                            \
+        LEAVE_CRITICAL_REGION();                          \
+    PR_END_MACRO
+
+#if TARGET_CARBON
+extern void _MD_SetIntsOff(PRInt32 ints);
+#define _MD_SET_INTSOFF(_val)           _MD_SetIntsOff(_val)
+#else /* not TARGET_CARBON */
+#define _MD_SET_INTSOFF(_val)           (_pr_intsOff = _val)
+#endif /* TARGET_CARBON */
+
 #define _MD_START_INTERRUPTS			_MD_StartInterrupts
 #define _MD_STOP_INTERRUPTS	    		_MD_StopInterrupts
 #define _MD_BLOCK_CLOCK_INTERRUPTS()
 #define _MD_UNBLOCK_CLOCK_INTERRUPTS()
 #define _MD_DISABLE_CLOCK_INTERRUPTS()
 #define _MD_ENABLE_CLOCK_INTERRUPTS()
 
 /*
@@ -233,26 +249,29 @@ extern PRStatus _MD_InitThread(PRThread 
     PR_BEGIN_MACRO				      					\
 	PR_DestroyCondVar(_thread->md.asyncIOCVar);			\
 	PR_DestroyLock(_thread->md.asyncIOLock);			\
     PR_END_MACRO
 
 
 /*
 ** Initialize the thread context preparing it to execute _main.
+** *sp = 0 zeros out the sp for the first stack frame so that
+** stack walking code can find the top of the stack.
 */
 #if defined(powerc) || defined(__powerc)
 #define _MD_INIT_CONTEXT(_thread, _sp, _main, _status)	\
     PR_BEGIN_MACRO				      					\
  	unsigned char *sp;									\
  	unsigned long *tvect;								\
 	long **jb = (_thread)->md.jb;		      			\
     *((PRBool *)_status) = PR_TRUE;              		\
 	(void) setjmp(jb);			      					\
     sp = INIT_STACKPTR(_sp);							\
+    *sp = 0;                                            \
     (_MD_GET_SP(_thread)) = (long) sp;   				\
 	tvect = (unsigned long *)_main;						\
     (_MD_GET_PC(_thread)) = (int) *tvect;   			\
     (_MD_GET_TOC(_thread)) = (int) *(tvect+1);   		\
 	_thread->no_sched = 0;                              \
     PR_END_MACRO
 #else
 #define _MD_INIT_CONTEXT(_thread, _sp, _main, _status)	\
@@ -622,9 +641,41 @@ extern PRStatus _MD_MemUnmap(void *addr,
 #define _MD_MEM_UNMAP _MD_MemUnmap
 
 extern PRStatus _MD_CloseFileMap(struct PRFileMap *fmap);
 #define _MD_CLOSE_FILE_MAP _MD_CloseFileMap
 
 extern void SetLogFileTypeCreator(const char *logFile);
 extern int _MD_mac_get_nonblocking_connect_error(PRInt32 osfd);
 
+
+/*
+ * Critical section support
+ */
+
+#define MAC_CRITICAL_REGIONS  TARGET_CARBON
+
+#if MAC_CRITICAL_REGIONS
+
+extern void InitCriticalRegion();
+extern void TermCriticalRegion();
+
+extern void EnterCritialRegion();
+extern void LeaveCritialRegion();
+
+#define INIT_CRITICAL_REGION()     InitCriticalRegion()
+#define TERM_CRITICAL_REGION()     TermCriticalRegion()
+
+#define ENTER_CRITICAL_REGION()     EnterCritialRegion()
+#define LEAVE_CRITICAL_REGION()     LeaveCritialRegion()
+
+#else
+
+#define INIT_CRITICAL_REGION()
+#define TERM_CRITICAL_REGION()
+
+#define ENTER_CRITICAL_REGION()
+#define LEAVE_CRITICAL_REGION()
+
+#endif
+
+
 #endif /* prmacos_h___ */
--- a/pr/include/md/_pth.h
+++ b/pr/include/md/_pth.h
@@ -91,16 +91,62 @@
 #define _PT_PTHREAD_MUTEXATTR_DESTROY     pthread_mutexattr_destroy
 #define _PT_PTHREAD_MUTEX_INIT(m, a)      pthread_mutex_init(&(m), &(a))
 #define _PT_PTHREAD_MUTEX_IS_LOCKED(m)    (EBUSY == pthread_mutex_trylock(&(m)))
 #define _PT_PTHREAD_CONDATTR_INIT         pthread_condattr_init
 #define _PT_PTHREAD_CONDATTR_DESTROY      pthread_condattr_destroy
 #define _PT_PTHREAD_COND_INIT(m, a)       pthread_cond_init(&(m), &(a))
 #endif
 
+/* The pthreads standard does not specify an invalid value for the
+ * pthread_t handle.  (0 is usually an invalid pthread identifier
+ * but there are exceptions, for example, DG/UX.)  These macros
+ * define a way to set the handle to or compare the handle with an
+ * invalid identifier.  These macros are not portable and may be
+ * more of a problem as we adapt to more pthreads implementations.
+ * They are only used in the PRMonitor functions.  Do not use them
+ * in new code.
+ *
+ * Unfortunately some of our clients depend on certain properties
+ * of our PRMonitor implementation, preventing us from replacing
+ * it by a portable implementation.
+ * - High-performance servers like the fact that PR_EnterMonitor
+ *   only calls PR_Lock and PR_ExitMonitor only calls PR_Unlock.
+ *   (A portable implementation would use a PRLock and a PRCondVar
+ *   to implement the recursive lock in a monitor and call both
+ *   PR_Lock and PR_Unlock in PR_EnterMonitor and PR_ExitMonitor.)
+ *   Unfortunately this forces us to read the monitor owner field
+ *   without holding a lock.
+ * - One way to make it safe to read the monitor owner field
+ *   without holding a lock is to make that field a PRThread*
+ *   (one should be able to read a pointer with a single machine
+ *   instruction).  However, PR_GetCurrentThread calls calloc if
+ *   it is called by a thread that was not created by NSPR.  The
+ *   malloc tracing tools in the Mozilla client use PRMonitor for
+ *   locking in their malloc, calloc, and free functions.  If
+ *   PR_EnterMonitor calls any of these functions, infinite
+ *   recursion ensues.
+ */
+#if defined(_PR_DCETHREADS)
+#define _PT_PTHREAD_INVALIDATE_THR_HANDLE(t) \
+	memset(&(t), 0, sizeof(pthread_t))
+#define _PT_PTHREAD_THR_HANDLE_IS_INVALID(t) \
+	(!memcmp(&(t), &pt_zero_tid, sizeof(pthread_t)))
+#define _PT_PTHREAD_COPY_THR_HANDLE(st, dt)   (dt) = (st)
+#elif defined(IRIX) || defined(OSF1) || defined(AIX) || defined(SOLARIS) \
+	|| defined(HPUX) || defined(LINUX) || defined(FREEBSD) \
+	|| defined(NETBSD) || defined(OPENBSD) || defined(BSDI) \
+	|| defined(VMS) || defined(NTO) || defined(RHAPSODY)
+#define _PT_PTHREAD_INVALIDATE_THR_HANDLE(t)  (t) = 0
+#define _PT_PTHREAD_THR_HANDLE_IS_INVALID(t)  (t) == 0
+#define _PT_PTHREAD_COPY_THR_HANDLE(st, dt)   (dt) = (st)
+#else 
+#error "pthreads is not supported for this architecture"
+#endif
+
 #if defined(_PR_DCETHREADS)
 #define _PT_PTHREAD_ATTR_INIT            pthread_attr_create
 #define _PT_PTHREAD_ATTR_DESTROY         pthread_attr_delete
 #define _PT_PTHREAD_CREATE(t, a, f, r)   pthread_create(t, a, f, r) 
 #define _PT_PTHREAD_KEY_CREATE           pthread_keycreate
 #define _PT_PTHREAD_ATTR_SETSCHEDPOLICY  pthread_attr_setsched
 #define _PT_PTHREAD_ATTR_GETSTACKSIZE(a, s) \
                                      (*(s) = pthread_attr_getstacksize(*(a)), 0)
--- a/pr/include/private/primpl.h
+++ b/pr/include/private/primpl.h
@@ -323,18 +323,20 @@ NSPR_API(PRInt32)                      _
 
 #define _MD_CURRENT_CPU()               (_pr_currentCPU)
 #define _MD_SET_CURRENT_CPU(_cpu)       (_pr_currentCPU = (_cpu))
 #define _MD_CURRENT_THREAD()            (_pr_currentThread)
 #define _MD_SET_CURRENT_THREAD(_thread) (_pr_currentThread = (_thread))
 #define _MD_LAST_THREAD()               (_pr_lastThread)
 #define _MD_SET_LAST_THREAD(t)          (_pr_lastThread = t)
 
+#ifndef XP_MAC
 #define _MD_GET_INTSOFF()               (_pr_intsOff)
 #define _MD_SET_INTSOFF(_val)           (_pr_intsOff = _val)
+#endif
 
 
 /* The unbalanced curly braces in these two macros are intentional */
 #define _PR_LOCK_HEAP() { PRIntn _is; if (_pr_currentCPU) _PR_INTSOFF(_is);
 #define _PR_UNLOCK_HEAP() if (_pr_currentCPU) _PR_INTSON(_is); }
 
 #endif /* _PR_LOCAL_THREADS_ONLY */
 
@@ -369,22 +371,30 @@ extern PRInt32                  _native_
 
 #define _PR_THREAD_SWITCH_CPU(_thread, _newCPU)
 
 #define _PR_IS_NATIVE_THREAD(thread) 1
 #define _PR_IS_NATIVE_THREAD_SUPPORTED() 1
 
 #else
 
+#ifdef XP_MAC
+
+#define _PR_INTSOFF(_is)        _MD_INTSOFF(_is)
+
+#else /* XP_MAC */
+
 #define _PR_INTSOFF(_is) \
     PR_BEGIN_MACRO \
         (_is) = _PR_MD_GET_INTSOFF(); \
         _PR_MD_SET_INTSOFF(1); \
     PR_END_MACRO
 
+#endif /* XP_MAC */
+
 #define _PR_FAST_INTSON(_is) \
     PR_BEGIN_MACRO \
         _PR_MD_SET_INTSOFF(_is); \
     PR_END_MACRO
 
 #define _PR_INTSON(_is) \
     PR_BEGIN_MACRO \
         if ((_is == 0) && (_PR_MD_CURRENT_CPU())->u.bits) \
@@ -1445,17 +1455,17 @@ struct PRCondVar {
 };
 
 /************************************************************************/
 
 struct PRMonitor {
     const char* name;           /* monitor name for debugging */
 #if defined(_PR_PTHREADS)
     PRLock lock;                /* the lock structure */
-    PRThread *owner;            /* the owner of the lock or NULL */
+    pthread_t owner;            /* the owner of the lock or invalid */
     PRCondVar *cvar;            /* condition variable queue */
 #else  /* defined(_PR_PTHREADS) */
     PRCondVar *cvar;            /* associated lock and condition variable queue */
 #endif /* defined(_PR_PTHREADS) */
     PRUint32 entryCount;        /* # of times re-entered */
 };
 
 /************************************************************************/
--- a/pr/src/md/mac/macio.c
+++ b/pr/src/md/mac/macio.c
@@ -86,30 +86,31 @@ struct ExtendedParamBlock {
 typedef struct ExtendedParamBlock ExtendedParamBlock;
 
 
 /* XXX Not done yet for 68K */
 /* I/O completion routne for _MD_READ and _MD_WRITE */
 static void AsyncIOCompletion (ExtendedParamBlock *pbAsyncPtr)
 {
     _PRCPU *cpu = _PR_MD_CURRENT_CPU();
-	PRThread *thread = pbAsyncPtr->thread;
-
+    PRThread *thread = pbAsyncPtr->thread;    
+    PRIntn is;
+    
     if (_PR_MD_GET_INTSOFF()) {
+        thread->md.missedIONotify = PR_TRUE;
         cpu->u.missed[cpu->where] |= _PR_MISSED_IO;
-        thread->md.missedIONotify = PR_TRUE;
-		return;
+        return;
     }
-    _PR_MD_SET_INTSOFF(1);
+
+    _PR_INTSOFF(is);
 
-	thread->md.osErrCode = noErr;
-	DoneWaitingOnThisThread(thread);
+    thread->md.osErrCode = noErr;
+    DoneWaitingOnThisThread(thread);
 
-    _PR_MD_SET_INTSOFF(0);
-
+    _PR_FAST_INTSON(is);
 }
 
 void  _MD_SetError(OSErr oserror)
 {
     PRErrorCode code;
 
     switch (oserror) {
       case memFullErr:
@@ -242,19 +243,19 @@ void _MD_IOInterrupt(void)
 ** All PR_read and PR_Write calls are synchronous from caller's perspective.
 ** They are internally made asynchronous calls.  This gives cpu to other
 ** user threads while the async io is in progress.
 */
 PRInt32 ReadWriteProc(PRFileDesc *fd, void *buf, PRUint32 bytes, IOOperation op)
 {
 	PRInt32 refNum = fd->secret->md.osfd;
 	OSErr				err;
- 	ExtendedParamBlock 	pbAsync;
+	ExtendedParamBlock 	pbAsync;
 	PRThread			*me = _PR_MD_CURRENT_THREAD();
-    _PRCPU *cpu = _PR_MD_CURRENT_CPU();
+	_PRCPU *cpu = _PR_MD_CURRENT_CPU();
 
 	/* quick hack to allow PR_fprintf, etc to work with stderr, stdin, stdout */
 	/* note, if a user chooses "seek" or the like as an operation in another function */
 	/* this will not work */
 	if (refNum >= 0 && refNum < 3)
 	{
 		switch (refNum)
 		{
@@ -265,22 +266,23 @@ PRInt32 ReadWriteProc(PRFileDesc *fd, vo
 					break;
 				case 1: /* stdout */
 				case 2: /* stderr */
 					puts(buf);
 					break;
 		}
 		
 		return (bytes);
-
 	}
 	else
 	{
 		static IOCompletionUPP	sCompletionUPP = NULL;
 		
+		PRBool  doingAsync = PR_FALSE;
+		
 		/* allocate the callback Universal Procedure Pointer (UPP). This actually allocates
 		   a 32 byte Ptr in the heap, so only do this once
 		*/
 		if (!sCompletionUPP)
 			sCompletionUPP = NewIOCompletionProc((IOCompletionProcPtr)&AsyncIOCompletion);
 			
 		/* grab the thread so we know which one to post to at completion */
 		pbAsync.thread	= me;
@@ -291,77 +293,73 @@ PRInt32 ReadWriteProc(PRFileDesc *fd, vo
 		pbAsync.pb.ioParam.ioBuffer		= buf;
 		pbAsync.pb.ioParam.ioReqCount	= bytes;
 		pbAsync.pb.ioParam.ioPosMode	= fsAtMark;
 		pbAsync.pb.ioParam.ioPosOffset	= 0;
 
 		/* 
 		** Issue the async read call and wait for the io semaphore associated
 		** with this thread.
-		** Don't compute error code from async call. Bug in OS returns a garbage value.
+		** Async file system calls *never* return error values, so ignore their
+		** results (see <http://developer.apple.com/technotes/fl/fl_515.html>);
+		** the completion routine is always called.
 		*/
-	    me->io_fd = refNum;
+		me->io_fd = refNum;
 		me->md.osErrCode = noErr;
 		if (op == READ_ASYNC)
 		{
 			/*
 			**  Skanky optimization so that reads < 20K are actually done synchronously
 			**  to optimize performance on small reads (e.g. registry reads on startup)
 			*/
 			if ( bytes > 20480L )
 			{
-				err = PBReadAsync(&pbAsync.pb);
-				if (err != noErr && err != eofErr)
-					goto ErrorExit;
+				doingAsync = PR_TRUE;
+				me->io_pending = PR_TRUE;
 				
-	   			me->io_pending = PR_TRUE; /* Only mark thread io pending if async call worked */
+				(void)PBReadAsync(&pbAsync.pb);
 			}
 			else
 			{
-				(void) PBReadSync(&pbAsync.pb);
-				/*
-				** This is probbaly redundant but want to make sure we indicate the read
-				** is complete so we don't wander off into the Sargasso Sea of Mac
-				** threading
-				*/
-				pbAsync.pb.ioParam.ioResult = 0;
+				pbAsync.pb.ioParam.ioCompletion = NULL;
+				me->io_pending = PR_FALSE;
+				
+				err = PBReadSync(&pbAsync.pb);
+				if (err != noErr && err != eofErr)
+					goto ErrorExit;
 			}
 		}
 		else
 		{
+			doingAsync = PR_TRUE;
+			me->io_pending = PR_TRUE;
+
 			/* writes are currently always async */
-			err = PBWriteAsync(&pbAsync.pb);
-				if (err != noErr)
-					goto ErrorExit;
-			
-			/* Didn't get an error on the asyn call so mark thread io pending */
-	   		me->io_pending = PR_TRUE;
+			(void)PBWriteAsync(&pbAsync.pb);
 		}
 		
-		/* See if the i/o call is still pending before we actually yield */
-		if (pbAsync.pb.ioParam.ioResult == 1)
+		if (doingAsync) {
 			WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
-		else
-			me->io_pending = PR_FALSE; /* io completed so don't mark thread io pending */
+		}
 	}
 	
 	err = me->md.osErrCode;
 	if (err != noErr)
 		goto ErrorExit;
 
 	err = pbAsync.pb.ioParam.ioResult;
 	if (err != noErr && err != eofErr)
 		goto ErrorExit;
-	else
-		return pbAsync.pb.ioParam.ioActCount;
+	
+	return pbAsync.pb.ioParam.ioActCount;
 
 ErrorExit:
 	me->md.osErrCode = err;
 	_MD_SetError(err);
-    return -1;
+	return -1;
 }
 
 /*
 Special WriteSyncProc for logging only.  IO occurs synchronously.  Otherwise,
 logging internal to NSPR causes ReadWriteProc above to recurse on PR_WaitSem logging.
 */
 PRInt32 WriteSyncProc(PRFileDesc *fd, void *buf, PRUint32 bytes)
 {
--- a/pr/src/md/mac/macrng.c
+++ b/pr/src/md/mac/macrng.c
@@ -28,23 +28,16 @@
  * indicate your decision by deleting the provisions above and
  * replace them with the notice and other provisions required by
  * the GPL.  If you do not delete the provisions above, a recipient
  * may use your version of this file under either the MPL or the
  * GPL.
  */
 
 
-#if 0 /* XXX what the flip is this all about? No MAC Wizards here. */
-#ifdef notdef
-#include "xp_core.h"
-#include "xp_file.h"
-#endif
-#endif /* 0 */
-
 /* XXX are all these headers required for a call to TickCount()? */
 #include <Events.h>
 #include <OSUtils.h>
 #include <QDOffscreen.h>
 #include <PPCToolbox.h>
 #include <Processes.h>
 #include <LowMem.h>
 #include "primpl.h"
--- a/pr/src/md/mac/macsockotpt.c
+++ b/pr/src/md/mac/macsockotpt.c
@@ -166,34 +166,34 @@ static pascal void  DNSNotifierRoutine(v
 	OSStatus    errOT;
 
 		dnsContext.thread->md.osErrCode = result;
 		dnsContext.cookie = cookie;
 	
 	switch (otEvent) {
 		case T_DNRSTRINGTOADDRCOMPLETE:
 				if (_PR_MD_GET_INTSOFF()) {
+					dnsContext.thread->md.missedIONotify = PR_TRUE;
 					cpu->u.missed[cpu->where] |= _PR_MISSED_IO;
-					dnsContext.thread->md.missedIONotify = PR_TRUE;
 					return;
 				}
 				DoneWaitingOnThisThread(dnsContext.thread);
 				break;
 		
         case kOTProviderWillClose:
                 errOT = OTSetSynchronous(dnsContext.serviceRef);
                 // fall through to kOTProviderIsClosed case
 		
         case kOTProviderIsClosed:
                 errOT = OTCloseProvider((ProviderRef)dnsContext.serviceRef);
                 dnsContext.serviceRef = nil;
 
 				if (_PR_MD_GET_INTSOFF()) {
+					dnsContext.thread->md.missedIONotify = PR_TRUE;
 					cpu->u.missed[cpu->where] |= _PR_MISSED_IO;
-					dnsContext.thread->md.missedIONotify = PR_TRUE;
 					return;
 				}
 				DoneWaitingOnThisThread(dnsContext.thread);
                 break;
 
         default: // or else we don't handle the event
 	            PR_ASSERT(otEvent==NULL);
 		
@@ -289,212 +289,208 @@ static void PrepareForAsyncCompletion(PR
 void
 WakeUpNotifiedThread(PRThread *thread, OTResult result)
 {
     _PRCPU *      cpu      = _PR_MD_CURRENT_CPU(); 
 
 	if (thread) {
 		thread->md.osErrCode = result;
 		if (_PR_MD_GET_INTSOFF()) {
+			thread->md.missedIONotify = PR_TRUE;
 			cpu->u.missed[cpu->where] |= _PR_MISSED_IO;
-			thread->md.missedIONotify = PR_TRUE;
 			return;
 		}
 		DoneWaitingOnThisThread(thread);
 	}
 }
 
 // Notification routine
 // Async callback routine.
 // A5 is OK. Cannot allocate memory here
+// Ref: http://gemma.apple.com/techpubs/mac/NetworkingOT/NetworkingWOT-100.html
+//
 static pascal void  NotifierRoutine(void * contextPtr, OTEventCode code, OTResult result, void * cookie)
 {
-	PRFilePrivate *secret  = (PRFilePrivate *) contextPtr;
-	_MDFileDesc * md       = &(secret->md);
-	EndpointRef   endpoint = (EndpointRef)secret->md.osfd;
-    PRThread *    thread   = NULL;
-    PRThread *	  pollThread = md->poll.thread;
-	OSStatus      err;
-	OTResult	  resultOT;
-    TDiscon		  discon;
+    PRFilePrivate *secret  = (PRFilePrivate *) contextPtr;
+    _MDFileDesc * md       = &(secret->md);
+    EndpointRef   endpoint = (EndpointRef)secret->md.osfd;
+    PRThread *    readThread   = NULL;          // also used for 'misc'
+    PRThread *    writeThread  = NULL;
+    OSStatus      err;
+    OTResult      resultOT;
+    TDiscon       discon;
 
     switch (code)
     {
 // OTLook Events - 
         case T_LISTEN:        // A connection request is available
-        	// If md->doListen is true, then PR_Listen has been
-        	// called on this endpoint; therefore, we're ready to
-        	// accept connections. But we'll do that with PR_Accept
-        	// (which calls OTListen, OTAccept, etc) instead of 
-        	// doing it here. 
-        	if (md->doListen) {
-				thread = secret->md.misc.thread;
-	            secret->md.misc.thread    = NULL;
-	            secret->md.misc.cookie    = cookie;
-	            break;
-        	} else {
-        		// Reject the connection, we're not listening
-        		OTSndDisconnect(endpoint, NULL);
-        	}
+            // If md->doListen is true, then PR_Listen has been
+            // called on this endpoint; therefore, we're ready to
+            // accept connections. But we'll do that with PR_Accept
+            // (which calls OTListen, OTAccept, etc) instead of 
+            // doing it here. 
+            if (md->doListen) {
+                readThread = secret->md.misc.thread;
+                secret->md.misc.thread    = NULL;
+                secret->md.misc.cookie    = cookie;
+                break;
+            } else {
+                // Reject the connection, we're not listening
+                OTSndDisconnect(endpoint, NULL);
+            }
             break;
-			
+
         case T_CONNECT:      // Confirmation of a connect request
-			// cookie = sndCall parameter from OTConnect()
+            // cookie = sndCall parameter from OTConnect()
             err = OTRcvConnect(endpoint, NULL);
             PR_ASSERT(err == kOTNoError);
 
-			// wake up waiting thread, if any
-            thread = secret->md.write.thread;
+            // wake up waiting thread, if any.
+            writeThread = secret->md.write.thread;
             secret->md.write.thread    = NULL;
-            secret->md.write.cookie    = cookie;
+            secret->md.write.cookie    = cookie;            
             break;
 
         case T_DATA:        // Standard data is available
-			// Mark this socket as readable.
-			secret->md.readReady = PR_TRUE;
+            // Mark this socket as readable.
+            secret->md.readReady = PR_TRUE;
 
-			// wake up waiting thread, if any
-            thread = secret->md.read.thread;
+            // wake up waiting thread, if any
+            readThread = secret->md.read.thread;
             secret->md.read.thread    = NULL;
             secret->md.read.cookie    = cookie;
-			break;
+            break;
 
         case T_EXDATA:      // Expedited data is available
             PR_ASSERT(!"T_EXDATA Not implemented");
-			return;
+            return;
 
         case T_DISCONNECT:  // A disconnect is available
             discon.udata.len = 0;
             err = OTRcvDisconnect(endpoint, &discon);
             PR_ASSERT(err == kOTNoError);
-            secret->md.exceptReady     = PR_TRUE;
-
-			// wake up waiting threads, if any
-			result = -3199 - discon.reason; // obtain the negative error code
+            secret->md.exceptReady = PR_TRUE;       // XXX Check this
 
-            if ((thread = secret->md.read.thread) != NULL) {
-		        secret->md.read.thread    = NULL;
-    	        secret->md.read.cookie    = cookie;
-            	WakeUpNotifiedThread(thread, result);
-    	    }
-            
-            if ((thread = secret->md.write.thread) != NULL) {
-	            secret->md.write.thread    = NULL;
-	            secret->md.write.cookie    = cookie;
-	            WakeUpNotifiedThread(thread, result);
-	        }
-	        
-	        thread = NULL; // already took care of notification here
+            // wake up waiting threads, if any
+            result = -3199 - discon.reason; // obtain the negative error code
+            if ((readThread = secret->md.read.thread) != NULL) {
+                secret->md.read.thread    = NULL;
+                secret->md.read.cookie    = cookie;
+            }
+
+            if ((writeThread = secret->md.write.thread) != NULL) {
+                secret->md.write.thread    = NULL;
+                secret->md.write.cookie    = cookie;
+            }
             break;
-		
+
         case T_ERROR:       // obsolete/unused in library
             PR_ASSERT(!"T_ERROR Not implemented");
-			return;		
-		
+            return;
+
         case T_UDERR:       // UDP Send error; clear the error
-			(void) OTRcvUDErr((EndpointRef) cookie, NULL);
+            (void) OTRcvUDErr((EndpointRef) cookie, NULL);
             break;
 
         case T_ORDREL:      // An orderly release is available
             err = OTRcvOrderlyDisconnect(endpoint);
             PR_ASSERT(err == kOTNoError);
             secret->md.readReady      = PR_TRUE;   // mark readable (to emulate bsd sockets)
             // remember connection is closed, so we can return 0 on read or receive
-			secret->md.orderlyDisconnect = PR_TRUE;
-	
-            thread = secret->md.read.thread;
-	        secret->md.read.thread    = NULL;
-	        secret->md.read.cookie    = cookie;
-
+            secret->md.orderlyDisconnect = PR_TRUE;
+            
+            readThread = secret->md.read.thread;
+            secret->md.read.thread    = NULL;
+            secret->md.read.cookie    = cookie;
             break;		
 
         case T_GODATA:   // Flow control lifted on standard data
             secret->md.writeReady = PR_TRUE;
-			resultOT = OTLook(endpoint);		// clear T_GODATA event
-			PR_ASSERT(resultOT == T_GODATA);
-			
-			// wake up waiting thread, if any
-            thread = secret->md.write.thread;
+            resultOT = OTLook(endpoint);        // clear T_GODATA event
+            PR_ASSERT(resultOT == T_GODATA);
+            
+            // wake up waiting thread, if any
+            writeThread = secret->md.write.thread;
             secret->md.write.thread    = NULL;
             secret->md.write.cookie    = cookie;
             break;
 
         case T_GOEXDATA: // Flow control lifted on expedited data
             PR_ASSERT(!"T_GOEXDATA Not implemented");
-			return;
+            return;
 
         case T_REQUEST:  // An Incoming request is available
             PR_ASSERT(!"T_REQUEST Not implemented");
             return;
 
         case T_REPLY:    // An Incoming reply is available
             PR_ASSERT(!"T_REPLY Not implemented");
             return;
 
         case T_PASSCON:  // State is now T_DATAXFER
-			// OTAccept() complete, receiving endpoint in T_DATAXFER state
-			// cookie = OTAccept() resRef parameter
-			break;
+            // OTAccept() complete, receiving endpoint in T_DATAXFER state
+            // cookie = OTAccept() resRef parameter
+            break;
 
         case T_RESET:    // Protocol has been reset
             PR_ASSERT(!"T_RESET Not implemented");
-			return;
+            return;
             
 // Async Completion Events
         case T_BINDCOMPLETE:
         case T_UNBINDCOMPLETE:
         case T_ACCEPTCOMPLETE:
         case T_OPTMGMTCOMPLETE:
         case T_GETPROTADDRCOMPLETE:
-			thread = secret->md.misc.thread;
+            readThread = secret->md.misc.thread;
             secret->md.misc.thread    = NULL;
             secret->md.misc.cookie    = cookie;
             break;
 
-//      case T_OPENCOMPLETE:			// we open endpoints in synchronous mode
+//      case T_OPENCOMPLETE:            // we open endpoints in synchronous mode
 //      case T_REPLYCOMPLETE:
-//      case T_DISCONNECTCOMPLETE:		// we don't call OTSndDisconnect()
+//      case T_DISCONNECTCOMPLETE:      // we don't call OTSndDisconnect()
 //      case T_RESOLVEADDRCOMPLETE:
 //      case T_GETINFOCOMPLETE:
 //      case T_SYNCCOMPLETE:
-//      case T_MEMORYRELEASED:			// only if OTAckSends() called on endpoint
+//      case T_MEMORYRELEASED:          // only if OTAckSends() called on endpoint
 //      case T_REGNAMECOMPLETE:
 //      case T_DELNAMECOMPLETE:
 //      case T_LKUPNAMECOMPLETE:
 //      case T_LKUPNAMERESULT:
-		// OpenTptInternet.h
-//      case T_DNRSTRINGTOADDRCOMPLETE:	// DNS is handled by dnsContext in DNSNotifierRoutine()
+        // OpenTptInternet.h
+//      case T_DNRSTRINGTOADDRCOMPLETE: // DNS is handled by dnsContext in DNSNotifierRoutine()
 //      case T_DNRADDRTONAMECOMPLETE:
 //      case T_DNRSYSINFOCOMPLETE:
 //      case T_DNRMAILEXCHANGECOMPLETE:
 //      case T_DNRQUERYCOMPLETE:
         default:
-        	// we should probably have a bit more sophisticated handling of kOTSystemSleep, etc.
-			// PR_ASSERT(code != 0);
+            // we should probably have a bit more sophisticated handling of kOTSystemSleep, etc.
+            // PR_ASSERT(code != 0);
             return;
     }
 
-	if (pollThread)
-		WakeUpNotifiedThread(pollThread, kOTNoError);
+    if (readThread)
+        WakeUpNotifiedThread(readThread, result);
 
-	if (thread && (thread != pollThread))
-		WakeUpNotifiedThread(thread, result);
+    if (writeThread && (writeThread != readThread))
+        WakeUpNotifiedThread(writeThread, result);
 }
 
 
 static OSErr CreateSocket(int type, EndpointRef *endpoint)
 {
     OSStatus err;
     PRThread *me = _PR_MD_CURRENT_THREAD();
     char *  configName;
     OTConfiguration *config;
     EndpointRef ep;
 
-	// for now we just create the endpoint
-	// we'll make it asynchronous and give it a notifier routine in _MD_makenonblock()
+    // for now we just create the endpoint
+    // we'll make it asynchronous and give it a notifier routine in _MD_makenonblock()
 
     switch (type){
         case SOCK_STREAM:   configName = kTCPName;  break;
         case SOCK_DGRAM:    configName = kUDPName;  break;
     }
     config = OTCreateConfiguration(configName);
     ep = OT_OPEN_ENDPOINT(config, 0, NULL, &err);
     if (err != kOTNoError)
@@ -514,17 +510,17 @@ ErrorExit:
 // kOTXXXX - OT returned error
 // EPROTONOSUPPORT - bad socket type/protocol
 // ENOBUFS - not enough space for another socket, or failure in socket creation routine
 PRInt32 _MD_socket(int domain, int type, int protocol)
 {
     OSStatus    err;
     EndpointRef endpoint;
     
-    	_MD_FinishInitNetAccess();
+    _MD_FinishInitNetAccess();
 
     // We only deal with internet domain
     if (domain != AF_INET) {
         err = kEPROTONOSUPPORTErr;
         goto ErrorExit;
     }
     
     // We only know about tcp & udp
@@ -1166,18 +1162,18 @@ static pascal void  RawEndpointNotifierR
 		// for other OT events, see NotifierRoutine above
         default:
             return;
     }
 
 	if (thread) {
 		thread->md.osErrCode = result;
 		if (_PR_MD_GET_INTSOFF()) {
+			thread->md.asyncNotifyPending = PR_TRUE;
 			cpu->u.missed[cpu->where] |= _PR_MISSED_IO;
-			thread->md.asyncNotifyPending = PR_TRUE;
 			return;
 		}
 		DoneWaitingOnThisThread(thread);
 	}
 }
 
 PRInt32 _MD_accept(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout)
 {
@@ -1344,17 +1340,18 @@ PRInt32 _MD_connect(PRFileDesc *fd, PRNe
 
     memset(&sndCall, 0 , sizeof(sndCall));
 
     sndCall.addr.maxlen = addrlen;
     sndCall.addr.len = addrlen;
     sndCall.addr.buf = (UInt8*) addr;
 
 	if (!fd->secret->nonblocking) {    
-        PrepareForAsyncCompletion(me, fd->secret->md.osfd);    
+        PrepareForAsyncCompletion(me, fd->secret->md.osfd);
+        PR_ASSERT(fd->secret->md.write.thread == NULL);
 	    fd->secret->md.write.thread = me;
     }
 	
     err = OTConnect (endpoint, &sndCall, NULL);
 	if (err == kOTNoError) {
         PR_ASSERT(!"OTConnect returned kOTNoError in async mode!?!");	
 	}
 	if (fd->secret->nonblocking) {
@@ -1402,26 +1399,28 @@ static PRInt32 SendReceiveStream(PRFileD
         err = kEBADFErr;
         goto ErrorExit;
     }
         
     if (buf == NULL) {
         err = kEFAULTErr;
         goto ErrorExit;
     }
-    
+
+    PR_ASSERT(opCode == kSTREAM_SEND ? fd->secret->md.write.thread == NULL :
+                                       fd->secret->md.read.thread  == NULL);
+
     while (bytesLeft > 0)
     {
         Boolean disabledNotifications = OTEnterNotifier(endpoint);
     
         PrepareForAsyncCompletion(me, fd->secret->md.osfd);    
 
         if (opCode == kSTREAM_SEND) {
         	do {
-
 				fd->secret->md.write.thread = me;
 				fd->secret->md.writeReady = PR_FALSE;				// expect the worst
 	            result = OTSnd(endpoint, buf, bytesLeft, NULL);
 				fd->secret->md.writeReady = (result != kOTFlowErr);
 				if (fd->secret->nonblocking)							// hope for the best
 					break;
 				else {
 
@@ -1495,73 +1494,86 @@ static PRInt32 SendReceiveStream(PRFileD
 
         // turn notifications back on
         if (disabledNotifications)
             OTLeaveNotifier(endpoint);
 
         if (result > 0) {
             buf = (void *) ( (UInt32) buf + (UInt32)result );
             bytesLeft -= result;
-            if (opCode == kSTREAM_RECEIVE)
-                return result;
+            if (opCode == kSTREAM_RECEIVE) {
+                amount = result;
+                goto NormalExit;
+            }
         } else {
 			switch (result) {
 				case kOTLookErr:
 				    PR_ASSERT(!"call to OTLook() required after all.");
 					break;
 				
 				case kOTFlowErr:
 				case kOTNoDataErr:
 				case kEAGAINErr:
 				case kEWOULDBLOCKErr:
 					if (fd->secret->nonblocking) {
-						err = result;
-						goto ErrorExit;
+					
+					    if (bytesLeft == amount) {  // no data was sent
+						    err = result;
+						    goto ErrorExit;
+						}
+						
+						// some data was sent
+						amount -= bytesLeft;
+						goto NormalExit;
 					}
 
 					WaitOnThisThread(me, timeout);
 					err = me->md.osErrCode;
 					if (err != kOTNoError)
 						goto ErrorExit;				
 					break;
 					
 				case kOTOutStateErr:	// if provider already closed, fall through to handle error
-					if (fd->secret->md.orderlyDisconnect)
-						return 0;
+					if (fd->secret->md.orderlyDisconnect) {
+						amount = 0;
+						goto NormalExit;
+					}
+					// else fall through
 				default:
 					err = result;
 					goto ErrorExit;
 			}
 		}
     }
 
-    PR_ASSERT(opCode == kSTREAM_SEND ? fd->secret->md.write.thread == nil :
-                                       fd->secret->md.read.thread  == nil);
+NormalExit:
+    PR_ASSERT(opCode == kSTREAM_SEND ? fd->secret->md.write.thread == NULL :
+                                       fd->secret->md.read.thread  == NULL);
     return amount;
 
 ErrorExit:
-    PR_ASSERT(opCode == kSTREAM_SEND ? fd->secret->md.write.thread == nil :
-                                       fd->secret->md.read.thread  == nil);
+    PR_ASSERT(opCode == kSTREAM_SEND ? fd->secret->md.write.thread == NULL :
+                                       fd->secret->md.read.thread  == NULL);
     macsock_map_error(err);
     return -1;
-}                               
+}
 
 
 PRInt32 _MD_recv(PRFileDesc *fd, void *buf, PRInt32 amount, 
                                PRIntn flags, PRIntervalTime timeout)
 {
     return (SendReceiveStream(fd, buf, amount, flags, timeout, kSTREAM_RECEIVE));
-}                               
+}
 
 
 PRInt32 _MD_send(PRFileDesc *fd,const void *buf, PRInt32 amount, 
                                PRIntn flags, PRIntervalTime timeout)
 {
     return (SendReceiveStream(fd, (void *)buf, amount, flags, timeout, kSTREAM_SEND));
-}                               
+}
 
 
 // Errors:
 // EBADF -- bad socket id
 // EFAULT -- bad buffer
 static PRInt32 SendReceiveDgram(PRFileDesc *fd, void *buf, PRInt32 amount, 
                                PRIntn flags, PRNetAddr *addr, PRUint32 *addrlen, 
                                PRIntervalTime timeout, SndRcvOpCode opCode)
@@ -1633,35 +1645,35 @@ static PRInt32 SendReceiveDgram(PRFileDe
     if (opCode == kDGRAM_RECEIVE)
         *addrlen = dgram.addr.len;
 
     return amount;
 
 ErrorExit:
     macsock_map_error(err);
     return -1;
-}                               
+}
 
 
 PRInt32 _MD_recvfrom(PRFileDesc *fd, void *buf, PRInt32 amount, 
                                PRIntn flags, PRNetAddr *addr, PRUint32 *addrlen,
                                PRIntervalTime timeout)
 {
     return (SendReceiveDgram(fd, buf, amount, flags, addr, addrlen,
                             timeout, kDGRAM_RECEIVE));
-}                               
+}
 
 
 PRInt32 _MD_sendto(PRFileDesc *fd,const void *buf, PRInt32 amount, 
                                PRIntn flags, PRNetAddr *addr, PRUint32 addrlen,
                                PRIntervalTime timeout)
 {
     return (SendReceiveDgram(fd, (void *)buf, amount, flags, addr, &addrlen,
                             timeout, kDGRAM_SEND));
-}                               
+}
 
 
 PRInt32 _MD_closesocket(PRInt32 osfd)
 {
     OSStatus err;
     EndpointRef endpoint = (EndpointRef) osfd;
     PRThread *me = _PR_MD_CURRENT_THREAD();
 
@@ -1678,47 +1690,67 @@ PRInt32 _MD_closesocket(PRInt32 osfd)
     if (err != kOTNoError)
         goto ErrorExit;
 
     return kOTNoError;
 
 ErrorExit:
     macsock_map_error(err);
     return -1;
-}                               
+}
 
 
 PRInt32 _MD_writev(PRFileDesc *fd, const struct PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout)
 {
 #pragma unused (fd, iov, iov_size, timeout)
 
     PR_ASSERT(0);
     _PR_MD_CURRENT_THREAD()->md.osErrCode = unimpErr;
     return -1;
-}                               
+}
 
-
+// OT endpoint states are documented here:
+// http://gemma.apple.com/techpubs/mac/NetworkingOT/NetworkingWOT-27.html#MARKER-9-65
+//
 static PRBool GetState(PRFileDesc *fd, PRBool *readReady, PRBool *writeReady, PRBool *exceptReady)
 {
     OTResult resultOT;
     // hack to emulate BSD sockets; say that a socket that has disconnected
     // is still readable.
     size_t   availableData = 1;
     if (!fd->secret->md.orderlyDisconnect)
         OTCountDataBytes((EndpointRef)fd->secret->md.osfd, &availableData);
 
     *readReady = fd->secret->md.readReady && (availableData > 0);
-	*exceptReady = fd->secret->md.exceptReady;
+    *exceptReady = fd->secret->md.exceptReady;
 
     resultOT = OTGetEndpointState((EndpointRef)fd->secret->md.osfd);
-    switch (resultOT)    {
-        case T_DATAXFER:
-        case T_INREL:
-            *writeReady = PR_TRUE;
+    switch (resultOT) {
+        case T_IDLE:
+        case T_UNBND:
+            // the socket is not connected. Emulating BSD sockets,
+            // we mark it readable and writable. The next PR_Read
+            // or PR_Write will then fail. Usually, in this situation,
+            // fd->secret->md.exceptReady is also set, and returned if
+            // anyone is polling for it.
+            *readReady = PR_FALSE;
+            *writeReady = PR_FALSE;
             break;
+
+        case T_DATAXFER:        // data transfer
+            *writeReady = fd->secret->md.writeReady;
+            break;
+
+        case T_INREL:           // incoming orderly release
+            *writeReady = fd->secret->md.writeReady;
+            break;
+
+        case T_OUTCON:          // outgoing connection pending  
+        case T_INCON:           // incoming connection pending
+        case T_OUTREL:          // outgoing orderly release
         default:
             *writeReady = PR_FALSE;
     }
     
     return  *readReady || *writeReady || *exceptReady;
 }
 
 // check to see if any of the poll descriptors have data available
@@ -1806,55 +1838,66 @@ static void SetDescPollThread(PRPollDesc
 
     for (pd = pds, epd = pd + npds; pd < epd; pd++)
     {   
         if (pd->fd)
         { 
             PRFileDesc *bottomFD = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
             if (bottomFD && (_PR_FILEDESC_OPEN == bottomFD->secret->state))
             {
-                bottomFD->secret->md.poll.thread = thread;
+                if (pd->in_flags & PR_POLL_READ) {
+                    PR_ASSERT(thread == NULL || bottomFD->secret->md.read.thread == NULL);
+                    bottomFD->secret->md.read.thread = thread;
+                }
+
+                if (pd->in_flags & PR_POLL_WRITE) {
+                    // it's possible for the writing thread to be non-null during
+                    // a non-blocking connect, so we assert that we're on
+                    // the same thread, or the thread is null.
+                    // Note that it's strictly possible for the connect and poll
+                    // to be on different threads, so ideally we need to assert
+                    // that if md.write.thread is non-null, there is a non-blocking
+                    // connect in progress.
+                    PR_ASSERT(thread == NULL ||
+                        (bottomFD->secret->md.write.thread == NULL ||
+                         bottomFD->secret->md.write.thread == thread));
+                    bottomFD->secret->md.write.thread = thread;
+                }
             }
         }        
     }
 }
 
 PRInt32 _MD_poll(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
 {
     PRThread    *thread = _PR_MD_CURRENT_THREAD();
     intn is;
     PRInt32 ready;
-    OSErr   result;
     
-    if (timeout == PR_INTERVAL_NO_WAIT) {        
+    if (timeout == PR_INTERVAL_NO_WAIT) {
         return CheckPollDescs(pds, npds);
     }
     
     _PR_INTSOFF(is);
     PR_Lock(thread->md.asyncIOLock);
 
     // ensure that we don't miss the firing of the notifier while checking socket status
     // need to set up the thread
     PrepareForAsyncCompletion(thread, 0);
 
-    SetDescPollThread(pds, npds, thread);        
+    SetDescPollThread(pds, npds, thread);
     ready = CheckPollDescs(pds, npds);
 
     PR_Unlock(thread->md.asyncIOLock);
     _PR_FAST_INTSON(is);
 
     if (ready == 0) {
         WaitOnThisThread(thread, timeout);
-        result = thread->md.osErrCode;
-        if (result != noErr && result != kETIMEDOUTErr) {
-            PR_ASSERT(0);   /* debug: catch unexpected errors */
-            ready = -1;
-        } else {
-            ready = CheckPollDescs(pds, npds);
-        }
+        ready = CheckPollDescs(pds, npds);
+
     } else {
         thread->io_pending = PR_FALSE;
     }
 
     SetDescPollThread(pds, npds, NULL);
 
     return ready;
 }
@@ -1932,17 +1975,17 @@ void _MD_queryfdinheritable(PRFileDesc *
 
 
 PR_IMPLEMENT(PRInt32) _MD_shutdown(PRFileDesc *fd, PRIntn how)
 {
 #pragma unused (fd, how)
 
 /* Just succeed silently!!! */
 return (0);
-}                               
+}
 
 
 PR_IMPLEMENT(PRStatus) 
 _MD_getpeername(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen)
 {
     PRThread *me = _PR_MD_CURRENT_THREAD();
 	EndpointRef ep = (EndpointRef) fd->secret->md.osfd;
 	InetAddress inetAddr;
@@ -1982,25 +2025,25 @@ PR_IMPLEMENT(PRStatus)
     addr->inet.ip = (PRUint32) inetAddr.fHost;
     
     *addrlen = PR_NETADDR_SIZE(addr); // return the amount of data obtained
 	return PR_SUCCESS;
 
 ErrorExit:
     macsock_map_error(err);
     return PR_FAILURE;
-}                               
+}
 
 
 PR_IMPLEMENT(unsigned long) inet_addr(const char *cp)
 {
     OSStatus err;
     InetHost host;    
 
-    	_MD_FinishInitNetAccess();
+    _MD_FinishInitNetAccess();
 
     err = OTInetStringToHost((char*) cp, &host);
     if (err != kOTNoError)
         return -1;
     
     return host;
 }
 
@@ -2062,30 +2105,30 @@ PR_IMPLEMENT(struct hostent *) gethostby
     OTInetHostToString((InetHost)addr, sHostInfo.name);
     
     return (gethostbyname(sHostInfo.name));
 }
 
 
 PR_IMPLEMENT(char *) inet_ntoa(struct in_addr addr)
 {
-    	_MD_FinishInitNetAccess();
+    _MD_FinishInitNetAccess();
 
     OTInetHostToString((InetHost)addr.s_addr, sHostInfo.name);
     
     return sHostInfo.name;
 }
 
 
 PRStatus _MD_gethostname(char *name, int namelen)
 {
     OSStatus err;
     InetInterfaceInfo info;
 
-    	_MD_FinishInitNetAccess();
+    _MD_FinishInitNetAccess();
 
     /*
      *    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.
      *    The alternative here is to ping a local DNS for our name, they
      *    will often know it.  This is the cheap, easiest, and safest way out.
      */
@@ -2159,15 +2202,15 @@ int _MD_mac_get_nonblocking_connect_erro
         case T_OUTCON:
             macsock_map_error(EINPROGRESS);
             return -1;
         case T_DATAXFER:
             return 0;
         case T_IDLE:
             return -1;
         case T_INREL:
-        	macsock_map_error(ENOTCONN);
-        	return -1;
+            macsock_map_error(ENOTCONN);
+            return -1;
         default:
             PR_ASSERT(0);
             return -1;
     }
 }
--- a/pr/src/md/mac/macthr.c
+++ b/pr/src/md/mac/macthr.c
@@ -31,22 +31,25 @@
  * may use your version of this file under either the MPL or the
  * GPL.
  */
 
 #include "primpl.h"
 
 #include <string.h>
 
-#include <Types.h>
+#include <MacTypes.h>
 #include <Timer.h>
 #include <OSUtils.h>
 
 #include <LowMem.h>
+#include <Multiprocessing.h>
+#include <Gestalt.h>
 
+#include "mdcriticalregion.h"
 
 TimerUPP	gTimerCallbackUPP	= NULL;
 PRThread *	gPrimaryThread		= NULL;
 
 PR_IMPLEMENT(PRThread *) PR_GetPrimaryThread()
 {
 	return gPrimaryThread;
 }
@@ -163,34 +166,36 @@ extern void _MD_IOInterrupt(void);
     { "clock", _PR_MISSED_CLOCK, _PR_ClockInterrupt, },
     { "i/o", _PR_MISSED_IO, _MD_IOInterrupt, },
     { 0 }
 };
 
 pascal void TimerCallback(TMTaskPtr tmTaskPtr)
 {
     _PRCPU *cpu = _PR_MD_CURRENT_CPU();
+    PRIntn is;
 
     if (_PR_MD_GET_INTSOFF()) {
         cpu->u.missed[cpu->where] |= _PR_MISSED_CLOCK;
-		PrimeTime((QElemPtr)tmTaskPtr, kMacTimerInMiliSecs);
-		return;
+        PrimeTime((QElemPtr)tmTaskPtr, kMacTimerInMiliSecs);
+        return;
     }
-    _PR_MD_SET_INTSOFF(1);
+
+    _PR_INTSOFF(is);
 
-	//	And tell nspr that a clock interrupt occured.
-	_PR_ClockInterrupt();
+    //	And tell nspr that a clock interrupt occured.
+    _PR_ClockInterrupt();
 	
-	if ((_PR_RUNQREADYMASK(cpu)) >> ((_PR_MD_CURRENT_THREAD()->priority)))
-		_PR_SET_RESCHED_FLAG();
+    if ((_PR_RUNQREADYMASK(cpu)) >> ((_PR_MD_CURRENT_THREAD()->priority)))
+        _PR_SET_RESCHED_FLAG();
 	
-    _PR_MD_SET_INTSOFF(0);
+    _PR_FAST_INTSON(is);
 
-	//	Reset the clock timer so that we fire again.
-	PrimeTime((QElemPtr)tmTaskPtr, kMacTimerInMiliSecs);
+    //	Reset the clock timer so that we fire again.
+    PrimeTime((QElemPtr)tmTaskPtr, kMacTimerInMiliSecs);
 }
 
 
 void _MD_StartInterrupts(void)
 {
 	gPrimaryThread = _PR_MD_CURRENT_THREAD();
 
 	if ( !gTimerCallbackUPP )
@@ -214,35 +219,32 @@ void _MD_StopInterrupts(void)
 	if (gTimeManagerTaskElem.tmAddr != NULL) {
 		RmvTime((QElemPtr)&gTimeManagerTaskElem);
 		gTimeManagerTaskElem.tmAddr = NULL;
 	}
 }
 
 void _MD_PauseCPU(PRIntervalTime timeout)
 {
-#pragma unused (timeout)
-
-	/* unsigned long finalTicks; */
-	EventRecord theEvent;
+    if (timeout != PR_INTERVAL_NO_WAIT)
+    {
+        EventRecord theEvent;
 	
-	if (timeout != PR_INTERVAL_NO_WAIT) {
-	   /* Delay(1,&finalTicks); */
+         /*
+            ** Calling WaitNextEvent() here is suboptimal. This routine should
+            ** pause the process until IO or the timeout occur, yielding time to
+            ** other processes on operating systems that require this (Mac OS classic).
+            ** WaitNextEvent() may incur too much latency, and has other problems,
+            ** such as the potential to drop suspend/resume events, and to handle
+            ** AppleEvents at a time at which we're not prepared to handle them.
+         */
+        (void) WaitNextEvent(nullEvent, &theEvent, 1, NULL);
 	   
-	   /*
-	   ** Rather than calling Delay() which basically just wedges the processor
-	   ** we'll instead call WaitNextEvent() with a mask that ignores all events
-	   ** which gives other apps a chance to get time rather than just locking up
-	   ** the machine when we're waiting for a long time (or in an infinite loop,
-	   ** whichever comes first)
-	   */
-	   (void)WaitNextEvent(nullEvent, &theEvent, 1, NULL);
-	   
-	    (void) _MD_IOInterrupt();
-	}
+        (void) _MD_IOInterrupt();
+    }
 }
 
 
 //##############################################################################
 //##############################################################################
 #pragma mark -
 #pragma mark THREAD SUPPORT FUNCTIONS
 
@@ -271,16 +273,21 @@ PRStatus _MD_wait(PRThread *thread, PRIn
 
 
 void WaitOnThisThread(PRThread *thread, PRIntervalTime timeout)
 {
     intn is;
     PRIntervalTime timein = PR_IntervalNow();
 	PRStatus status = PR_SUCCESS;
 
+    // Turn interrupts off to avoid a race over lock ownership with the callback
+    // (which can fire at any time). Interrupts may stay off until we leave
+    // this function, or another NSPR thread turns them back on. They certainly
+    // stay off until PR_WaitCondVar() relinquishes the asyncIOLock lock, which
+    // is what we care about.
 	_PR_INTSOFF(is);
 	PR_Lock(thread->md.asyncIOLock);
 	if (timeout == PR_INTERVAL_NO_TIMEOUT) {
 	    while ((thread->io_pending) && (status == PR_SUCCESS))
 	        status = PR_WaitCondVar(thread->md.asyncIOCVar, PR_INTERVAL_NO_TIMEOUT);
 	} else {
 	    while ((thread->io_pending) && ((PRIntervalTime)(PR_IntervalNow() - timein) < timeout) && (status == PR_SUCCESS))
 	        status = PR_WaitCondVar(thread->md.asyncIOCVar, timeout);
@@ -297,33 +304,49 @@ void WaitOnThisThread(PRThread *thread, 
 	_PR_FAST_INTSON(is);
 }
 
 
 void DoneWaitingOnThisThread(PRThread *thread)
 {
     intn is;
 
+    PR_ASSERT(thread->md.asyncIOLock->owner == NULL);
+
+	// DoneWaitingOnThisThread() is called from OT notifiers and async file I/O
+	// callbacks that can run at "interrupt" time (Classic Mac OS) or on pthreads
+	// that may run concurrently with the main threads (Mac OS X). They can thus
+	// be called when any NSPR thread is running, or even while NSPR is in a
+	// thread context switch. It is therefore vital that we can guarantee to
+	// be able to get the asyncIOLock without blocking (thus avoiding code
+	// that makes assumptions about the current NSPR thread etc). To achieve
+	// this, we use NSPR interrrupts as a semaphore on the lock; all code 
+	// that grabs the lock also disables interrupts for the time the lock
+	// is held. Callers of DoneWaitingOnThisThread() thus have to check whether
+	// interrupts are already off, and, if so, simply set the missed_IO flag on
+	// the CPU rather than calling this function.
+	
 	_PR_INTSOFF(is);
 	PR_Lock(thread->md.asyncIOLock);
-    thread->io_pending = PR_FALSE;
+	thread->io_pending = PR_FALSE;
 	/* let the waiting thread know that async IO completed */
 	PR_NotifyCondVar(thread->md.asyncIOCVar);
 	PR_Unlock(thread->md.asyncIOLock);
 	_PR_FAST_INTSON(is);
 }
 
 
 PR_IMPLEMENT(void) PR_Mac_WaitForAsyncNotify(PRIntervalTime timeout)
 {
     intn is;
     PRIntervalTime timein = PR_IntervalNow();
 	PRStatus status = PR_SUCCESS;
     PRThread *thread = _PR_MD_CURRENT_THREAD();
 
+    // See commments in WaitOnThisThread()
 	_PR_INTSOFF(is);
 	PR_Lock(thread->md.asyncIOLock);
 	if (timeout == PR_INTERVAL_NO_TIMEOUT) {
 	    while ((!thread->md.asyncNotifyPending) && (status == PR_SUCCESS))
 	        status = PR_WaitCondVar(thread->md.asyncIOCVar, PR_INTERVAL_NO_TIMEOUT);
 	} else {
 	    while ((!thread->md.asyncNotifyPending) && ((PRIntervalTime)(PR_IntervalNow() - timein) < timeout) && (status == PR_SUCCESS))
 	        status = PR_WaitCondVar(thread->md.asyncIOCVar, timeout);
@@ -339,33 +362,36 @@ PR_IMPLEMENT(void) PR_Mac_WaitForAsyncNo
 	_PR_FAST_INTSON(is);
 }
 
 
 void AsyncNotify(PRThread *thread)
 {
     intn is;
 	
+    PR_ASSERT(thread->md.asyncIOLock->owner == NULL);
+
+    // See commments in DoneWaitingOnThisThread()
 	_PR_INTSOFF(is);
 	PR_Lock(thread->md.asyncIOLock);
-    thread->md.asyncNotifyPending = PR_TRUE;
+	thread->md.asyncNotifyPending = PR_TRUE;
 	/* let the waiting thread know that async IO completed */
-	PR_NotifyCondVar(thread->md.asyncIOCVar);	// let thread know that async IO completed
+	PR_NotifyCondVar(thread->md.asyncIOCVar);
 	PR_Unlock(thread->md.asyncIOLock);
 	_PR_FAST_INTSON(is);
 }
 
 
 PR_IMPLEMENT(void) PR_Mac_PostAsyncNotify(PRThread *thread)
 {
 	_PRCPU *  cpu = _PR_MD_CURRENT_CPU();
 	
 	if (_PR_MD_GET_INTSOFF()) {
+		thread->md.missedAsyncNotify = PR_TRUE;
 		cpu->u.missed[cpu->where] |= _PR_MISSED_IO;
-		thread->md.missedAsyncNotify = PR_TRUE;
 	} else {
 		AsyncNotify(thread);
 	}
 }
 
 
 //##############################################################################
 //##############################################################################
@@ -402,8 +428,141 @@ PRStatus _MD_WaitProcess(PRProcess *proc
 
 PRStatus _MD_KillProcess(PRProcess *process)
 {
 #pragma unused (process)
 
 	PR_SetError(PR_NOT_IMPLEMENTED_ERROR, unimpErr);
 	return PR_FAILURE;
 }
+//##############################################################################
+//##############################################################################
+#pragma mark -
+#pragma mark INTERRUPT SUPPORT
+
+#if TARGET_CARBON
+
+/*
+     This critical region support is required for Mac NSPR to work correctly on dual CPU
+     machines on Mac OS X. This note explains why.
+
+     NSPR uses a timer task, and has callbacks for async file I/O and Open Transport
+     whose runtime behaviour differs depending on environment. On "Classic" Mac OS
+     these run at "interrupt" time (OS-level interrupts, that is, not NSPR interrupts),
+     and can thus preempt other code, but they always run to completion.
+
+     On Mac OS X, these are all emulated using MP tasks, which sit atop pthreads. Thus,
+     they can be preempted at any time (and not necessarily run to completion), and can
+     also run *concurrently* with eachother, and with application code, on multiple
+     CPU machines. Note that all NSPR threads are emulated, and all run on the main
+     application MP task.
+
+     We thus have to use MP critical sections to protect data that is shared between
+     the various callbacks and the main MP thread. It so happens that NSPR has this
+     concept of software interrupts, and making interrupt-off times be critical
+     sections works.
+
+*/
+
+
+/*  
+    Whether to use critical regions. True if running on Mac OS X and later
+*/
+
+PRBool  gUseCriticalRegions;
+
+/*
+    Count of the number of times we've entered the critical region.
+    We need this because ENTER_CRITICAL_REGION() will *not* block when
+    called from different NSPR threads (which all run on one MP thread),
+    and we need to ensure that when code turns interrupts back on (by
+    settings _pr_intsOff to 0) we exit the critical section enough times
+    to leave it.
+*/
+
+PRInt32 gCriticalRegionEntryCount;
+
+
+void _MD_SetIntsOff(PRInt32 ints)
+{
+    ENTER_CRITICAL_REGION();
+    gCriticalRegionEntryCount ++;
+    
+    _pr_intsOff = ints;
+    
+    if (!ints)
+    {
+        PRInt32     i = gCriticalRegionEntryCount;
+
+        gCriticalRegionEntryCount = 0;
+        for ( ;i > 0; i --) {
+            LEAVE_CRITICAL_REGION();
+        }
+    }
+}
+
+
+#endif /* TARGET_CARBON */
+
+
+//##############################################################################
+//##############################################################################
+#pragma mark -
+#pragma mark CRITICAL REGION SUPPORT
+
+#if MAC_CRITICAL_REGIONS
+
+MDCriticalRegionID  gCriticalRegion;
+
+void InitCriticalRegion()
+{
+    long        systemVersion;
+    OSStatus    err;    
+    
+    // we only need to do critical region stuff on Mac OS X    
+    err = Gestalt(gestaltSystemVersion, &systemVersion);
+    gUseCriticalRegions = (err == noErr) && (systemVersion >= 0x00001000);
+    
+    if (!gUseCriticalRegions) return;
+    
+    err = MD_CriticalRegionCreate(&gCriticalRegion);
+    PR_ASSERT(err == noErr);
+}
+
+void TermCriticalRegion()
+{
+    OSStatus    err;    
+
+    if (!gUseCriticalRegions) return;
+
+    err = MD_CriticalRegionDelete(gCriticalRegion);
+    PR_ASSERT(err == noErr);
+}
+
+
+void EnterCritialRegion()
+{
+    OSStatus    err;
+    
+    if (!gUseCriticalRegions) return;
+
+    PR_ASSERT(gCriticalRegion != kInvalidID);
+    
+    /* Change to a non-infinite timeout for debugging purposes */
+    err = MD_CriticalRegionEnter(gCriticalRegion, kDurationForever /* 10000 * kDurationMillisecond */ );
+    PR_ASSERT(err == noErr);
+}
+
+void LeaveCritialRegion()
+{
+    OSStatus    err;    
+
+    if (!gUseCriticalRegions) return;
+
+    PR_ASSERT(gCriticalRegion != kInvalidID);
+
+    err = MD_CriticalRegionExit(gCriticalRegion);
+    PR_ASSERT(err == noErr);
+}
+
+
+#endif // MAC_CRITICAL_REGIONS
+
new file mode 100644
--- /dev/null
+++ b/pr/src/md/mac/mdcriticalregion.c
@@ -0,0 +1,169 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: NULL; c-basic-offset: 2 -*- */
+/* 
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ * 
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ * 
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation.  Portions created by Netscape are 
+ * Copyright (C) 1998-2000 Netscape Communications Corporation.  All
+ * Rights Reserved.
+ * 
+ * Contributor(s):
+ *                George Warner, Apple Computer Inc.
+ *                Simon Fraser  <sfraser@netscape.com>
+ * 
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable 
+ * instead of those above.  If you wish to allow use of your 
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL.  If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "mdcriticalregion.h"
+
+/*
+  This code is a replacement for MPEnterCriticalRegion/MPLeaveCriticalRegion,
+  which is broken on Mac OS 10.0.x builds, but fixed in 10.1. This code works
+  everywhere.
+*/
+
+
+typedef struct MDCriticalRegionData_struct {
+  MPTaskID        mMPTaskID;          /* Who's in the critical region? */
+  UInt32          mDepthCount;        /* How deep? */
+  MPSemaphoreID   mMPSemaphoreID;     /* ready semaphore */
+} MDCriticalRegionData, *MDCriticalRegionDataPtr;
+
+
+OSStatus
+MD_CriticalRegionCreate(MDCriticalRegionID * outCriticalRegionID)
+{
+  MDCriticalRegionDataPtr newCriticalRegionPtr;
+  MPSemaphoreID           mpSemaphoreID;
+  OSStatus                err = noErr;
+
+  if (outCriticalRegionID == NULL)
+    return paramErr;
+
+  *outCriticalRegionID = NULL;
+
+  newCriticalRegionPtr = (MDCriticalRegionDataPtr)MPAllocateAligned(sizeof(MDCriticalRegionData),
+                        kMPAllocateDefaultAligned, kMPAllocateClearMask);
+  if (newCriticalRegionPtr == NULL)
+    return memFullErr;
+
+  // Note: this semaphore is pre-fired (ready!)
+  err = MPCreateBinarySemaphore(&mpSemaphoreID);
+  if (err == noErr)
+  {
+    newCriticalRegionPtr->mMPTaskID = kInvalidID;
+    newCriticalRegionPtr->mDepthCount = 0;
+    newCriticalRegionPtr->mMPSemaphoreID = mpSemaphoreID;
+
+    *outCriticalRegionID = (MDCriticalRegionID)newCriticalRegionPtr;
+  }
+  else
+  {
+    MPFree((LogicalAddress)newCriticalRegionPtr);
+  }
+
+  return err;
+}
+
+OSStatus
+MD_CriticalRegionDelete(MDCriticalRegionID inCriticalRegionID)
+{
+  MDCriticalRegionDataPtr criticalRegion = (MDCriticalRegionDataPtr)inCriticalRegionID;
+  OSStatus                err = noErr;
+
+  if (criticalRegion == NULL)
+    return paramErr;
+
+  if ((criticalRegion->mMPTaskID != kInvalidID) && (criticalRegion->mDepthCount > 0))
+    return kMPInsufficientResourcesErr;
+
+  if (criticalRegion->mMPSemaphoreID != kInvalidID)
+    err = MPDeleteSemaphore(criticalRegion->mMPSemaphoreID);
+  if (noErr != err) return err;
+
+  criticalRegion->mMPSemaphoreID = kInvalidID;
+  MPFree((LogicalAddress) criticalRegion);
+
+  return noErr;
+}
+
+OSStatus
+MD_CriticalRegionEnter(MDCriticalRegionID inCriticalRegionID, Duration inTimeout)
+{
+  MDCriticalRegionDataPtr criticalRegion = (MDCriticalRegionDataPtr)inCriticalRegionID;
+  MPTaskID                currentTaskID = MPCurrentTaskID();
+  OSStatus                err = noErr;
+
+  if (criticalRegion == NULL)
+    return paramErr;
+
+  // if I'm inside the critical region...
+  if (currentTaskID == criticalRegion->mMPTaskID)
+  {
+    // bump my depth
+    criticalRegion->mDepthCount++;
+    // and continue
+    return noErr;
+  }
+
+  // wait for the ready semaphore
+  err = MPWaitOnSemaphore(criticalRegion->mMPSemaphoreID, inTimeout);
+  // we didn't get it. return the error
+  if (noErr != err) return err;
+
+  // we got it!
+  criticalRegion->mMPTaskID = currentTaskID;
+  criticalRegion->mDepthCount = 1;
+
+  return noErr;
+}
+
+OSStatus
+MD_CriticalRegionExit(MDCriticalRegionID inCriticalRegionID)
+{
+  MDCriticalRegionDataPtr   criticalRegion = (MDCriticalRegionDataPtr)inCriticalRegionID;
+  MPTaskID                  currentTaskID = MPCurrentTaskID();
+  OSStatus                  err = noErr;
+
+  // if we don't own the critical region...
+  if (currentTaskID != criticalRegion->mMPTaskID)
+    return kMPInsufficientResourcesErr;
+
+  // if we aren't at a depth...
+  if (criticalRegion->mDepthCount == 0)
+    return kMPInsufficientResourcesErr;
+
+  // un-bump my depth
+  criticalRegion->mDepthCount--;
+
+  // if we just bottomed out...
+  if (criticalRegion->mDepthCount == 0)
+  {
+    // release ownership of the structure
+    criticalRegion->mMPTaskID = kInvalidID;
+    // and signal the ready semaphore
+    err = MPSignalSemaphore(criticalRegion->mMPSemaphoreID);
+  }
+  return err;
+}
+
new file mode 100644
--- /dev/null
+++ b/pr/src/md/mac/mdcriticalregion.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ * 
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ * 
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation.  Portions created by Netscape are 
+ * Copyright (C) 1998-2000 Netscape Communications Corporation.  All
+ * Rights Reserved.
+ * 
+ * Contributor(s):
+ *                George Warner, Apple Computer Inc.
+ *                Simon Fraser  <sfraser@netscape.com>
+ * 
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable 
+ * instead of those above.  If you wish to allow use of your 
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL.  If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#ifndef mdcriticalregion_h___
+#define mdcriticalregion_h___
+
+
+#ifndef __MULTIPROCESSING__
+#include <Multiprocessing.h>
+#endif
+
+typedef struct OpaqueMDCriticalRegionID*  MDCriticalRegionID;
+
+OSStatus MD_CriticalRegionCreate(MDCriticalRegionID * pMDCriticalRegionID);
+
+OSStatus MD_CriticalRegionDelete(MDCriticalRegionID pMDCriticalRegionID);
+
+OSStatus MD_CriticalRegionEnter(MDCriticalRegionID pMDCriticalRegionID, Duration pTimeout);
+
+OSStatus MD_CriticalRegionExit(MDCriticalRegionID pMDCriticalRegionID);
+
+#endif /* mdcriticalregion_h___ */
+
--- a/pr/src/md/mac/mdmac.c
+++ b/pr/src/md/mac/mdmac.c
@@ -283,16 +283,18 @@ void _MD_GetRegisters(PRUint32 *to)
 {
   (void) setjmp((void*) to);
 }
 
 void _MD_EarlyInit()
 {
 	Handle				environmentVariables;
 
+	INIT_CRITICAL_REGION();
+
 #if !defined(MAC_NSPR_STANDALONE)
 	// MacintoshInitializeMemory();  Moved to mdmacmem.c: AllocateRawMemory(Size blockSize)
 #else
 	MacintoshInitializeMemory();
 #endif
 	MacintoshInitializeTime();
 	
 	//	Install resource-controlled environment variables.
@@ -369,16 +371,17 @@ extern OTClientContextPtr	clientContext;
 
 extern pascal void __NSTerminate(void);
 
 void CleanupTermProc(void)
 {
 	_MD_StopInterrupts();	// deactive Time Manager task
 
 	CLOSE_OPEN_TRANSPORT();
+	TERM_CRITICAL_REGION();
 	
 	__NSTerminate();
 }
 
 
 
 //##############################################################################
 //##############################################################################
--- a/pr/src/md/unix/unix_errors.c
+++ b/pr/src/md/unix/unix_errors.c
@@ -378,19 +378,24 @@ void _MD_unix_map_mkdir_error(int err)
     _MD_unix_map_default_error(err);
 }
 
 void _MD_unix_map_rmdir_error(int err)
 {
     PRErrorCode prError;
 
     switch (err) {
+        /*
+         * On AIX 4.3, ENOTEMPTY is defined as EEXIST.
+         */
+#if ENOTEMPTY != EEXIST
         case ENOTEMPTY:
             prError = PR_DIRECTORY_NOT_EMPTY_ERROR;
             break;
+#endif
         case EEXIST:
             prError = PR_DIRECTORY_NOT_EMPTY_ERROR;
             break;
         case EINVAL:
             prError = PR_DIRECTORY_NOT_EMPTY_ERROR;
             break;
         case ETIMEDOUT:
             prError = PR_REMOTE_FILE_ERROR;
--- a/pr/src/misc/prnetdb.c
+++ b/pr/src/misc/prnetdb.c
@@ -79,17 +79,17 @@ PRLock *_pr_dnsLock = NULL;
 
 /*
  * Some platforms have the reentrant getprotobyname_r() and
  * getprotobynumber_r().  However, they come in two flavors.
  * Some return a pointer to struct protoent, others return
  * an int.
  */
 
-#if defined(SOLARIS) \
+#if defined(SOLARIS) || (defined(BSDI) && defined(_REENTRANT)) \
 	|| (defined(LINUX) && defined(_REENTRANT) \
         && !(defined(__GLIBC__) && __GLIBC__ >= 2))
 #define _PR_HAVE_GETPROTO_R
 #define _PR_HAVE_GETPROTO_R_POINTER
 #endif
 
 #if defined(OSF1) \
         || defined(AIX4_3) || (defined(AIX) && defined(_THREAD_SAFE)) \
--- a/pr/src/misc/prtime.c
+++ b/pr/src/misc/prtime.c
@@ -1578,22 +1578,23 @@ PR_ParseTimeString(
                   /* Set this to -1 to tell mktime "I don't care".  If you set
                      it to 0 or 1, you are making assertions about whether the
                      date you are handing it is in daylight savings mode or not;
                      and if you're wrong, it will "fix" it for you. */
                   localTime.tm_isdst = -1;
                   secs = mktime(&localTime);
                   if (secs != (time_t) -1)
                     {
-#if defined(XP_MAC)
+#if defined(XP_MAC) && (__MSL__ < 0x6000)
                       /*
                        * The mktime() routine in MetroWerks MSL C
                        * Runtime library returns seconds since midnight,
-                       * 1 Jan. 1900, not 1970.  So we need to adjust
-                       * its return value to the NSPR epoch.
+                       * 1 Jan. 1900, not 1970 - in versions of MSL (Metrowerks Standard
+                       * Library) prior to version 6.  Only for older versions of
+                       * MSL do we adjust the value of secs to the NSPR epoch
                        */
                       secs -= ((365 * 70UL) + 17) * 24 * 60 * 60;
 #endif
                       LL_I2L(*result, secs);
                       LL_I2L(usec_per_sec, PR_USEC_PER_SEC);
                       LL_MUL(*result, *result, usec_per_sec);
                       return PR_SUCCESS;
                     }
--- a/pr/src/pthreads/ptsynch.c
+++ b/pr/src/pthreads/ptsynch.c
@@ -439,16 +439,18 @@ PR_IMPLEMENT(PRMonitor*) PR_NewMonitor(v
     }
     mon = PR_NEWZAP(PRMonitor);
     if (mon != NULL)
     {
         int rv;
         rv = _PT_PTHREAD_MUTEX_INIT(mon->lock.mutex, _pt_mattr); 
         PR_ASSERT(0 == rv);
 
+        _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner);
+
         mon->cvar = cvar;
         rv = _PT_PTHREAD_COND_INIT(mon->cvar->cv, _pt_cvar_attr); 
         PR_ASSERT(0 == rv);
         mon->entryCount = 0;
         mon->cvar->lock = &mon->lock;
         if (0 != rv)
         {
             PR_DELETE(mon);
@@ -479,119 +481,120 @@ PR_IMPLEMENT(void) PR_DestroyMonitor(PRM
 }  /* PR_DestroyMonitor */
 
 
 /* The GC uses this; it is quite arguably a bad interface.  I'm just 
  * duplicating it for now - XXXMB
  */
 PR_IMPLEMENT(PRInt32) PR_GetMonitorEntryCount(PRMonitor *mon)
 {
-    PRThread *self = PR_GetCurrentThread();
-    if (mon->owner == self)
+    pthread_t self = pthread_self();
+    if (pthread_equal(mon->owner, self))
         return mon->entryCount;
     return 0;
 }
 
 PR_IMPLEMENT(void) PR_EnterMonitor(PRMonitor *mon)
 {
-    PRThread *self = PR_GetCurrentThread();
+    pthread_t self = pthread_self();
 
     PR_ASSERT(mon != NULL);
     /*
-     * This is safe only if mon->owner (a PRThread*) can be
-     * read in one instruction.
+     * This is safe only if mon->owner (a pthread_t) can be
+     * read in one instruction.  Perhaps mon->owner should be
+     * a "PRThread *"?
      */
-    if (mon->owner != self)
+    if (!pthread_equal(mon->owner, self))
     {
         PR_Lock(&mon->lock);
         /* and now I have the lock */
         PR_ASSERT(0 == mon->entryCount);
-        PR_ASSERT(NULL == mon->owner);
-        mon->owner = self;
+        PR_ASSERT(_PT_PTHREAD_THR_HANDLE_IS_INVALID(mon->owner));
+        _PT_PTHREAD_COPY_THR_HANDLE(self, mon->owner);
     }
     mon->entryCount += 1;
 }  /* PR_EnterMonitor */
 
 PR_IMPLEMENT(PRStatus) PR_ExitMonitor(PRMonitor *mon)
 {
-    PRThread *self = PR_GetCurrentThread();
+    pthread_t self = pthread_self();
 
     PR_ASSERT(mon != NULL);
     /* The lock better be that - locked */
     PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(mon->lock.mutex));
     /* we'd better be the owner */
-    PR_ASSERT(mon->owner == self);
-    if (mon->owner != self)
+    PR_ASSERT(pthread_equal(mon->owner, self));
+    if (!pthread_equal(mon->owner, self))
         return PR_FAILURE;
 
     /* if it's locked and we have it, then the entries should be > 0 */
     PR_ASSERT(mon->entryCount > 0);
     mon->entryCount -= 1;  /* reduce by one */
     if (mon->entryCount == 0)
     {
         /* and if it transitioned to zero - unlock */
-        mon->owner = NULL;  /* make the owner unknown */
+        _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner);  /* make the owner unknown */
         PR_Unlock(&mon->lock);
     }
     return PR_SUCCESS;
 }  /* PR_ExitMonitor */
 
 PR_IMPLEMENT(PRStatus) PR_Wait(PRMonitor *mon, PRIntervalTime timeout)
 {
     PRStatus rv;
     PRInt16 saved_entries;
-    PRThread *saved_owner;
+    pthread_t saved_owner;
 
     PR_ASSERT(mon != NULL);
     /* we'd better be locked */
     PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(mon->lock.mutex));
     /* and the entries better be positive */
     PR_ASSERT(mon->entryCount > 0);
     /* and it better be by us */
-    PR_ASSERT(mon->owner == PR_GetCurrentThread());
+    PR_ASSERT(pthread_equal(mon->owner, pthread_self()));
 
     /* tuck these away 'till later */
     saved_entries = mon->entryCount; 
     mon->entryCount = 0;
-    saved_owner = mon->owner;
-    mon->owner = NULL;
+    _PT_PTHREAD_COPY_THR_HANDLE(mon->owner, saved_owner);
+    _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner);
     
     rv = PR_WaitCondVar(mon->cvar, timeout);
 
     /* reinstate the intresting information */
     mon->entryCount = saved_entries;
-    mon->owner = saved_owner;
+    _PT_PTHREAD_COPY_THR_HANDLE(saved_owner, mon->owner);
 
     return rv;
 }  /* PR_Wait */
 
 PR_IMPLEMENT(PRStatus) PR_Notify(PRMonitor *mon)
 {
     PR_ASSERT(NULL != mon);
     /* we'd better be locked */
     PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(mon->lock.mutex));
     /* and the entries better be positive */
     PR_ASSERT(mon->entryCount > 0);
     /* and it better be by us */
-    PR_ASSERT(mon->owner == PR_GetCurrentThread());
+    PR_ASSERT(pthread_equal(mon->owner, pthread_self()));
 
     pt_PostNotifyToCvar(mon->cvar, PR_FALSE);
 
     return PR_SUCCESS;
 }  /* PR_Notify */
 
 PR_IMPLEMENT(PRStatus) PR_NotifyAll(PRMonitor *mon)
 {
     PR_ASSERT(mon != NULL);
     /* we'd better be locked */
     PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(mon->lock.mutex));
     /* and the entries better be positive */
     PR_ASSERT(mon->entryCount > 0);
     /* and it better be by us */
-    PR_ASSERT(mon->owner == PR_GetCurrentThread());
+    PR_ASSERT(pthread_equal(mon->owner, pthread_self()));
 
     pt_PostNotifyToCvar(mon->cvar, PR_TRUE);
 
     return PR_SUCCESS;
 }  /* PR_NotifyAll */
 
 /**************************************************************/
 /**************************************************************/