Fixes for 71718 and 97866. Make Mac NSPR work on dual CPU Mac OS X machines, and fix the async IO code for Mac OS X. See bugs for reviewers. a=pdt MOZILLA_0_9_4_BRANCH PSM_2_2_DEV_20011002_BASE PSM_2_2_DEV_20011015 PSM_2_2_DEV_20011016_1736
authorsfraser%netscape.com
Thu, 27 Sep 2001 22:50:40 +0000
branchMOZILLA_0_9_4_BRANCH
changeset 2060 6d61dc682c11eae4335c3bc5ea220f026b3d3727
parent 2056 29917e4d5f952ad933cade7b4ebe3a5bd4ae3ec5
child 2073 215a968a13f89a46d0d84f44f8d627c1a16220c8
push idunknown
push userunknown
push dateunknown
reviewerspdt
bugs71718, 97866
Fixes for 71718 and 97866. Make Mac NSPR work on dual CPU Mac OS X machines, and fix the async IO code for Mac OS X. See bugs for reviewers. a=pdt
macbuild/NSPR20PPC.mcp
pr/include/md/_macos.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
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
@@ -133,16 +133,33 @@ struct _MDFileDesc {
 
 #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 +250,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 +642,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/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) \
--- 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,18 +289,18 @@ 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.
@@ -1166,18 +1166,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)
 {
--- 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();
 }
 
 
 
 //##############################################################################
 //##############################################################################