📄 prucv.c
字号:
PR_ASSERT(_PR_MD_GET_INTSOFF() != 0); /* Figure out how much time elapsed since the last clock tick */ now = PR_IntervalNow(); elapsed = now - cpu->last_clock; cpu->last_clock = now;#ifndef XP_MAC PR_LOG(_pr_clock_lm, PR_LOG_MAX, ("ExpireWaits: elapsed=%lld usec", elapsed));#endif while(1) { _PR_SLEEPQ_LOCK(cpu); if (_PR_SLEEPQ(cpu).next == &_PR_SLEEPQ(cpu)) { _PR_SLEEPQ_UNLOCK(cpu); break; } thread = _PR_THREAD_PTR(_PR_SLEEPQ(cpu).next); PR_ASSERT(thread->cpu == cpu); if (elapsed < thread->sleep) { thread->sleep -= elapsed; _PR_SLEEPQMAX(thread->cpu) -= elapsed; _PR_SLEEPQ_UNLOCK(cpu); break; } _PR_SLEEPQ_UNLOCK(cpu); PR_ASSERT(!_PR_IS_NATIVE_THREAD(thread)); _PR_THREAD_LOCK(thread); if (thread->cpu != cpu) { /* ** The thread was switched to another CPU ** between the time we unlocked the sleep ** queue and the time we acquired the thread ** lock, so it is none of our business now. */ _PR_THREAD_UNLOCK(thread); continue; } /* ** Consume this sleeper's amount of elapsed time from the elapsed ** time value. The next remaining piece of elapsed time will be ** available for the next sleeping thread's timer. */ _PR_SLEEPQ_LOCK(cpu); PR_ASSERT(!(thread->flags & _PR_ON_PAUSEQ)); if (thread->flags & _PR_ON_SLEEPQ) { _PR_DEL_SLEEPQ(thread, PR_FALSE); elapsed -= thread->sleep; _PR_SLEEPQ_UNLOCK(cpu); } else { /* Thread was already handled; Go get another one */ _PR_SLEEPQ_UNLOCK(cpu); _PR_THREAD_UNLOCK(thread); continue; } /* Notify the thread waiting on the condition variable */ if (thread->flags & _PR_SUSPENDING) { PR_ASSERT((thread->state == _PR_IO_WAIT) || (thread->state == _PR_COND_WAIT)); /* ** Thread is suspended and its condition timeout ** expired. Transfer thread from sleepQ to suspendQ. */ thread->wait.cvar = NULL; _PR_MISCQ_LOCK(cpu); thread->state = _PR_SUSPENDED; _PR_ADD_SUSPENDQ(thread, cpu); _PR_MISCQ_UNLOCK(cpu); } else { if (thread->wait.cvar) { PRThreadPriority pri; /* Do work very similar to what _PR_NotifyThread does */ PR_ASSERT( !_PR_IS_NATIVE_THREAD(thread) ); /* Make thread runnable */ pri = thread->priority; thread->state = _PR_RUNNABLE; PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD)); PR_ASSERT(thread->cpu == cpu); _PR_RUNQ_LOCK(cpu); _PR_ADD_RUNQ(thread, cpu, pri); _PR_RUNQ_UNLOCK(cpu); if (pri > me->priority) _PR_SET_RESCHED_FLAG(); thread->wait.cvar = NULL; _PR_MD_WAKEUP_WAITER(thread); } else if (thread->io_pending == PR_TRUE) { /* Need to put IO sleeper back on runq */ int pri = thread->priority; thread->io_suspended = PR_TRUE;#ifdef WINNT /* * For NT, record the cpu on which I/O was issued * I/O cancellation is done on the same cpu */ thread->md.thr_bound_cpu = cpu;#endif PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD)); PR_ASSERT(thread->cpu == cpu); thread->state = _PR_RUNNABLE; _PR_RUNQ_LOCK(cpu); _PR_ADD_RUNQ(thread, cpu, pri); _PR_RUNQ_UNLOCK(cpu); } } _PR_THREAD_UNLOCK(thread); }}/************************************************************************//*** Create a new condition variable.** "lock" is the lock to use with the condition variable.**** Condition variables are synchronization objects that threads can use** to wait for some condition to occur.**** This may fail if memory is tight or if some operating system resource** is low.*/PR_IMPLEMENT(PRCondVar*) PR_NewCondVar(PRLock *lock){ PRCondVar *cvar; PR_ASSERT(lock != NULL); cvar = PR_NEWZAP(PRCondVar); if (cvar) {#ifdef _PR_GLOBAL_THREADS_ONLY if(_PR_MD_NEW_CV(&cvar->md)) { PR_DELETE(cvar); PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); return NULL; }#endif if (_PR_MD_NEW_LOCK(&(cvar->ilock)) == PR_FAILURE) { PR_DELETE(cvar); PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); return NULL; } cvar->lock = lock; PR_INIT_CLIST(&cvar->condQ); } else { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); } return cvar;}/*** Destroy a condition variable. There must be no thread** waiting on the condvar. The caller is responsible for guaranteeing** that the condvar is no longer in use.***/PR_IMPLEMENT(void) PR_DestroyCondVar(PRCondVar *cvar){ PR_ASSERT(cvar->condQ.next == &cvar->condQ);#ifdef _PR_GLOBAL_THREADS_ONLY _PR_MD_FREE_CV(&cvar->md);#endif _PR_MD_FREE_LOCK(&(cvar->ilock)); PR_DELETE(cvar);}/*** Wait for a notify on the condition variable. Sleep for "tiemout" amount** of ticks (if "timeout" is zero then the sleep is indefinite). While** the thread is waiting it unlocks lock. When the wait has** finished the thread regains control of the condition variable after** locking the associated lock.**** The thread waiting on the condvar will be resumed when the condvar is** notified (assuming the thread is the next in line to receive the** notify) or when the timeout elapses.**** Returns PR_FAILURE if the caller has not locked the lock associated** with the condition variable or the thread has been interrupted.*/extern PRThread *suspendAllThread;PR_IMPLEMENT(PRStatus) PR_WaitCondVar(PRCondVar *cvar, PRIntervalTime timeout){ PRThread *me = _PR_MD_CURRENT_THREAD(); PR_ASSERT(cvar->lock->owner == me); PR_ASSERT(me != suspendAllThread); if (cvar->lock->owner != me) return PR_FAILURE; return _PR_WaitCondVar(me, cvar, cvar->lock, timeout);}/*** Notify the highest priority thread waiting on the condition** variable. If a thread is waiting on the condition variable (using** PR_Wait) then it is awakened and begins waiting on the lock.*/PR_IMPLEMENT(PRStatus) PR_NotifyCondVar(PRCondVar *cvar){ PRThread *me = _PR_MD_CURRENT_THREAD(); PR_ASSERT(cvar->lock->owner == me); PR_ASSERT(me != suspendAllThread); if (cvar->lock->owner != me) return PR_FAILURE; _PR_NotifyCondVar(cvar, me); return PR_SUCCESS;}/*** Notify all of the threads waiting on the condition variable. All of** threads are notified in turn. The highest priority thread will** probably acquire the lock.*/PR_IMPLEMENT(PRStatus) PR_NotifyAllCondVar(PRCondVar *cvar){ PRCList *q; PRIntn is; PRThread *me = _PR_MD_CURRENT_THREAD(); PR_ASSERT(cvar->lock->owner == me); if (cvar->lock->owner != me) return PR_FAILURE;#ifdef _PR_GLOBAL_THREADS_ONLY _PR_MD_NOTIFYALL_CV(&cvar->md, &cvar->lock->ilock); return PR_SUCCESS;#else /* _PR_GLOBAL_THREADS_ONLY */ if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is); _PR_CVAR_LOCK(cvar); q = cvar->condQ.next; while (q != &cvar->condQ) { PR_LOG(_pr_cvar_lm, PR_LOG_MIN, ("PR_NotifyAll: cvar=%p", cvar)); _PR_NotifyThread(_PR_THREAD_CONDQ_PTR(q), me); q = q->next; } _PR_CVAR_UNLOCK(cvar); if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is); return PR_SUCCESS;#endif /* _PR_GLOBAL_THREADS_ONLY */}/*********************************************************************//*********************************************************************//********************ROUTINES FOR DCE EMULATION***********************//*********************************************************************//*********************************************************************/#include "prpdce.h"PR_IMPLEMENT(PRCondVar*) PRP_NewNakedCondVar(void){ PRCondVar *cvar = PR_NEWZAP(PRCondVar); if (NULL != cvar) { if (_PR_MD_NEW_LOCK(&(cvar->ilock)) == PR_FAILURE) { PR_DELETE(cvar); cvar = NULL; } else { PR_INIT_CLIST(&cvar->condQ); cvar->lock = _PR_NAKED_CV_LOCK; } } return cvar;}PR_IMPLEMENT(void) PRP_DestroyNakedCondVar(PRCondVar *cvar){ PR_ASSERT(cvar->condQ.next == &cvar->condQ); PR_ASSERT(_PR_NAKED_CV_LOCK == cvar->lock); _PR_MD_FREE_LOCK(&(cvar->ilock)); PR_DELETE(cvar);}PR_IMPLEMENT(PRStatus) PRP_NakedWait( PRCondVar *cvar, PRLock *lock, PRIntervalTime timeout){ PRThread *me = _PR_MD_CURRENT_THREAD(); PR_ASSERT(_PR_NAKED_CV_LOCK == cvar->lock); return _PR_WaitCondVar(me, cvar, lock, timeout);} /* PRP_NakedWait */PR_IMPLEMENT(PRStatus) PRP_NakedNotify(PRCondVar *cvar){ PRThread *me = _PR_MD_CURRENT_THREAD(); PR_ASSERT(_PR_NAKED_CV_LOCK == cvar->lock); _PR_NotifyCondVar(cvar, me); return PR_SUCCESS;} /* PRP_NakedNotify */PR_IMPLEMENT(PRStatus) PRP_NakedBroadcast(PRCondVar *cvar){ PRCList *q; PRIntn is; PRThread *me = _PR_MD_CURRENT_THREAD(); PR_ASSERT(_PR_NAKED_CV_LOCK == cvar->lock); if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is); _PR_MD_LOCK( &(cvar->ilock) ); q = cvar->condQ.next; while (q != &cvar->condQ) { PR_LOG(_pr_cvar_lm, PR_LOG_MIN, ("PR_NotifyAll: cvar=%p", cvar)); _PR_NotifyThread(_PR_THREAD_CONDQ_PTR(q), me); q = q->next; } _PR_MD_UNLOCK( &(cvar->ilock) ); if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is); return PR_SUCCESS;} /* PRP_NakedBroadcast */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -