⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 macthr.c

📁 Netscape NSPR库源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	// 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;	/* 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);	}	if ((status == PR_FAILURE) && (PR_GetError() == PR_PENDING_INTERRUPT_ERROR)) {		thread->md.osErrCode = kEINTRErr;	} else if (!thread->md.asyncNotifyPending) {		thread->md.osErrCode = kETIMEDOUTErr;		PR_SetError(PR_IO_TIMEOUT_ERROR, kETIMEDOUTErr);	}	thread->md.asyncNotifyPending = PR_FALSE;	PR_Unlock(thread->md.asyncIOLock);	_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;	/* 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_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;	} else {		AsyncNotify(thread);	}}//##############################################################################//###############################################################################pragma mark -#pragma mark PROCESS SUPPORT FUNCTIONSPRProcess * _MD_CreateProcess(    const char *path,    char *const *argv,    char *const *envp,    const PRProcessAttr *attr){#pragma unused (path, argv, envp, attr)	PR_SetError(PR_NOT_IMPLEMENTED_ERROR, unimpErr);	return NULL;}PRStatus _MD_DetachProcess(PRProcess *process){#pragma unused (process)	PR_SetError(PR_NOT_IMPLEMENTED_ERROR, unimpErr);	return PR_FAILURE;}PRStatus _MD_WaitProcess(PRProcess *process, PRInt32 *exitCode){#pragma unused (process, exitCode)	PR_SetError(PR_NOT_IMPLEMENTED_ERROR, unimpErr);	return PR_FAILURE;}PRStatus _MD_KillProcess(PRProcess *process){#pragma unused (process)	PR_SetError(PR_NOT_IMPLEMENTED_ERROR, unimpErr);	return PR_FAILURE;}//##############################################################################//###############################################################################pragma mark -#pragma mark ATOMIC OPERATIONS#ifdef _PR_HAVE_ATOMIC_OPSPRInt32_MD_AtomicSet(PRInt32 *val, PRInt32 newval){    PRInt32 rv;    do  {        rv = *val;    } while (!OTCompareAndSwap32(rv, newval, (UInt32*)val));    return rv;}#endif // _PR_HAVE_ATOMIC_OPS//##############################################################################//###############################################################################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 SUPPORTstatic PRBool RunningOnOSX(){    long    systemVersion;    OSErr   err = Gestalt(gestaltSystemVersion, &systemVersion);    return (err == noErr) && (systemVersion >= 0x00001000);}#if MAC_CRITICAL_REGIONSMDCriticalRegionID  gCriticalRegion;void InitCriticalRegion(){    OSStatus    err;            // we only need to do critical region stuff on Mac OS X        gUseCriticalRegions = RunningOnOSX();    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//##############################################################################//###############################################################################pragma mark -#pragma mark IDLE SEMAPHORE SUPPORT/*     Since the WaitNextEvent() in _MD_PauseCPU() is causing all sorts of     headache under Mac OS X we're going to switch to MPWaitOnSemaphore()     which should do what we want*/#if TARGET_CARBONPRBool					gUseIdleSemaphore = PR_FALSE;MPSemaphoreID			gIdleSemaphore = NULL;#endifvoid InitIdleSemaphore(){    // we only need to do idle semaphore stuff on Mac OS X#if TARGET_CARBON	gUseIdleSemaphore = RunningOnOSX();	if (gUseIdleSemaphore)	{		OSStatus  err = MPCreateSemaphore(1 /* max value */, 0 /* initial value */, &gIdleSemaphore);		PR_ASSERT(err == noErr);	}#endif}void TermIdleSemaphore(){#if TARGET_CARBON	if (gUseIdleSemaphore)	{		OSStatus  err = MPDeleteSemaphore(gIdleSemaphore);		PR_ASSERT(err == noErr);		gUseIdleSemaphore = NULL;	}#endif}void WaitOnIdleSemaphore(PRIntervalTime timeout){#if TARGET_CARBON	if (gUseIdleSemaphore)	{		OSStatus  err = MPWaitOnSemaphore(gIdleSemaphore, kDurationMillisecond * PR_IntervalToMilliseconds(timeout));		PR_ASSERT(err == noErr);	}	else#endif	{		EventRecord   theEvent;		/*		** 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.		*/		(void)WaitNextEvent(nullEvent, &theEvent, 1, NULL);	}}void SignalIdleSemaphore(){#if TARGET_CARBON	if (gUseIdleSemaphore)	{		// often we won't be waiting on the semaphore here, so ignore any errors		(void)MPSignalSemaphore(gIdleSemaphore);	}	else#endif	{		WakeUpProcess(&gApplicationProcess);	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -