PR_ASSERT(completed_io->io_pending == PR_FALSE || completed_io->io_suspended == PR_TRUE);
PR_ASSERT(completed_io->io_pending == PR_FALSE); PR_ASSERT(completed_io->io_suspended == PR_FALSE); PR_ASSERT(completed_io->md.thr_bound_cpu == NULL);
_PR_MD_PAUSE_CPU(PRIntervalTime ticks){    int awoken = 0;    unsigned long bytes, key;    int rv;    LPOVERLAPPED olp;    _MDOverlapped *mdOlp;    PRUint32 timeout;    if (_nt_idleCount > 0) {        PRThread *deadThread;        _MD_LOCK(&_nt_idleLock);        while( !PR_CLIST_IS_EMPTY(&_nt_idleList) ) {            deadThread = _PR_THREAD_PTR(PR_LIST_HEAD(&_nt_idleList));            PR_REMOVE_LINK(&deadThread->links);            PR_ASSERT(deadThread->state == _PR_DEAD_STATE);            /* XXXMB - cleanup to do here? */            if ( !_PR_IS_NATIVE_THREAD(deadThread) ){                /* Spinlock while user thread is still running.                 * There is no way to use a condition variable here. The thread                 * is dead, and we have to wait until we switch off the dead                  * thread before we can kill the fiber completely.                 */                while ( deadThread->no_sched)                    ;                DeleteFiber(deadThread->md.fiber_id);            }            memset(deadThread, 0xa, sizeof(PRThread)); /* debugging */            if (!deadThread->threadAllocatedOnStack)                PR_DELETE(deadThread);            _nt_idleCount--;        }        _MD_UNLOCK(&_nt_idleLock);    }    if (ticks == PR_INTERVAL_NO_TIMEOUT)#if 0        timeout = INFINITE;#else    /* temporary hack to poll the runq every 5 seconds because of bug in     * native threads creating user threads and not poking the right cpu.     */        timeout = 5000;#endif    else         timeout = PR_IntervalToMilliseconds(ticks);    /*     * The idea of looping here is to complete as many IOs as possible before     * returning.  This should minimize trips to the idle thread.     */    while(1) {        rv = GetQueuedCompletionStatus(                _pr_completion_port,                &bytes,                &key,                &olp,                timeout);         if (rv == 0 && olp == NULL) {            /* Error in GetQueuedCompetionStatus */            if (GetLastError() != WAIT_TIMEOUT) {                /* ARGH - what can we do here? Log an error? XXXMB */                return -1;            } else {                /* If awoken == 0, then we just had a timeout */                return awoken;            }        }        if (olp == NULL)             return 0;        mdOlp = (_MDOverlapped *)olp;        if (mdOlp->ioModel == _MD_MultiWaitIO) {            PRRecvWait *desc;            PRWaitGroup *group;            PRThread *thred = NULL;            PRMWStatus mwstatus;            desc = mdOlp->data.mw.desc;            PR_ASSERT(desc != NULL);            mwstatus = rv ? PR_MW_SUCCESS : PR_MW_FAILURE;            if (InterlockedCompareExchange((PVOID *)&desc->outcome,                    (PVOID)mwstatus, (PVOID)PR_MW_PENDING)                    == (PVOID)PR_MW_PENDING) {                if (mwstatus == PR_MW_SUCCESS) {                    desc->bytesRecv = bytes;                } else {                    mdOlp->data.mw.error = GetLastError();                }            }            group = mdOlp->data.mw.group;            PR_ASSERT(group != NULL);            _PR_MD_LOCK(&group->mdlock);            PR_APPEND_LINK(&mdOlp->data.mw.links, &group->io_ready);            PR_ASSERT(desc->fd != NULL);            NT_HashRemoveInternal(group, desc->fd);            if (!PR_CLIST_IS_EMPTY(&group->wait_list)) {                thred = _PR_THREAD_CONDQ_PTR(PR_LIST_HEAD(&group->wait_list));                PR_REMOVE_LINK(&thred->waitQLinks);            }            _PR_MD_UNLOCK(&group->mdlock);            if (thred) {                if (!_PR_IS_NATIVE_THREAD(thred)) {                    int pri = thred->priority;                    _PRCPU *lockedCPU = _PR_MD_CURRENT_CPU();                    _PR_THREAD_LOCK(thred);                    if (thred->flags & _PR_ON_PAUSEQ) {                        _PR_SLEEPQ_LOCK(thred->cpu);                        _PR_DEL_SLEEPQ(thred, PR_TRUE);                        _PR_SLEEPQ_UNLOCK(thred->cpu);                        _PR_THREAD_UNLOCK(thred);                        thred->cpu = lockedCPU;                        thred->state = _PR_RUNNABLE;                        _PR_RUNQ_LOCK(lockedCPU);                        _PR_ADD_RUNQ(thred, lockedCPU, pri);                        _PR_RUNQ_UNLOCK(lockedCPU);                    } else {                        /*                         * The thread was just interrupted and moved                         * from the pause queue to the run queue.                         */                        _PR_THREAD_UNLOCK(thred);                    }                } else {                    _PR_THREAD_LOCK(thred);                    thred->state = _PR_RUNNABLE;                    _PR_THREAD_UNLOCK(thred);                    ReleaseSemaphore(thred->md.blocked_sema, 1, NULL);                }            }        } else {            PRThread *completed_io;            PR_ASSERT(mdOlp->ioModel == _MD_BlockingIO);            completed_io = _PR_THREAD_MD_TO_PTR(mdOlp->data.mdThread);            completed_io->md.blocked_io_status = rv;            if (rv == 0)                completed_io->md.blocked_io_error = GetLastError();            completed_io->md.blocked_io_bytes = bytes;            if ( !_PR_IS_NATIVE_THREAD(completed_io) ) {                int pri = completed_io->priority;                _PRCPU *lockedCPU = _PR_MD_CURRENT_CPU();                /* The KEY_CVAR notification only occurs when a native thread                 * is notifying a user thread.  For user-user notifications                 * the wakeup occurs by having the notifier place the thread                  * on the runq directly; for native-native notifications the                 * wakeup occurs by calling ReleaseSemaphore.                 */                if ( key == KEY_CVAR ) {                    PR_ASSERT(completed_io->io_pending == PR_FALSE || completed_io->io_suspended == PR_TRUE);                    /* Thread has already been deleted from sleepQ */                    /* Switch CPU and add to runQ */                    completed_io->cpu = lockedCPU;                    completed_io->state = _PR_RUNNABLE;                    _PR_RUNQ_LOCK(lockedCPU);                    _PR_ADD_RUNQ(completed_io, lockedCPU, pri);                    _PR_RUNQ_UNLOCK(lockedCPU);                } else {                    PR_ASSERT(key == KEY_IO);                    PR_ASSERT(completed_io->io_pending == PR_TRUE);                    _PR_THREAD_LOCK(completed_io);                    completed_io->io_pending = PR_FALSE;                    /* If io_suspended is true, then this IO has already resumed.                     * We don't need to do anything; because the thread is                     * already running.                     */                    if (completed_io->io_suspended == PR_FALSE) {                        if (completed_io->flags & (_PR_ON_SLEEPQ|_PR_ON_PAUSEQ)) {                            _PR_SLEEPQ_LOCK(completed_io->cpu);                            _PR_DEL_SLEEPQ(completed_io, PR_TRUE);                            _PR_SLEEPQ_UNLOCK(completed_io->cpu);                            _PR_THREAD_UNLOCK(completed_io);						/*						 * If an I/O operation is suspended, the thread						 * must be running on the same cpu on which the						 * I/O operation was issued.						 */						PR_ASSERT(!completed_io->md.thr_bound_cpu ||					(completed_io->cpu == completed_io->md.thr_bound_cpu));							if (!completed_io->md.thr_bound_cpu)                            	completed_io->cpu = lockedCPU;                            completed_io->state = _PR_RUNNABLE;                            _PR_RUNQ_LOCK(completed_io->cpu);                            _PR_ADD_RUNQ(completed_io, completed_io->cpu, pri);                            _PR_RUNQ_UNLOCK(completed_io->cpu);                        } else {                            _PR_THREAD_UNLOCK(completed_io);                        }                    } else {                        _PR_THREAD_UNLOCK(completed_io);                    }                }            } else {                /* For native threads, they are only notified through this loop                 * when completing IO.  So, don't worry about this being a CVAR                 * notification, because that is not possible.                 */                _PR_THREAD_LOCK(completed_io);                completed_io->io_pending = PR_FALSE;                if (completed_io->io_suspended == PR_FALSE) {                    completed_io->state = _PR_RUNNABLE;                    _PR_THREAD_UNLOCK(completed_io);                    rv = ReleaseSemaphore(completed_io->md.blocked_sema,                            1, NULL);                    PR_ASSERT(0 != rv);                } else {                    _PR_THREAD_UNLOCK(completed_io);                }            }        }        awoken++;        timeout = 0;   /* Don't block on subsequent trips through the loop */    }    /* never reached */    return 0;}