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

📄 ntio.c

📁 Netscape NSPR库源码
💻 C
📖 第 1 页 / 共 5 页
字号:
						 * 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;}static PRStatus_native_thread_md_wait(PRThread *thread, PRIntervalTime ticks){    DWORD rv;	PRUint32 msecs = (ticks == PR_INTERVAL_NO_TIMEOUT) ?		INFINITE : PR_IntervalToMilliseconds(ticks);	/*	 * thread waiting for a cvar or a joining thread	 */	rv = WaitForSingleObject(thread->md.blocked_sema, msecs);	switch(rv) {		case WAIT_OBJECT_0:			return PR_SUCCESS;			break;		case WAIT_TIMEOUT:			_PR_THREAD_LOCK(thread);			PR_ASSERT (thread->state != _PR_IO_WAIT);			if (thread->wait.cvar != NULL) {				PR_ASSERT(thread->state == _PR_COND_WAIT);				thread->wait.cvar = NULL;				thread->state = _PR_RUNNING;				_PR_THREAD_UNLOCK(thread);			} else {				/* The CVAR was notified just as the timeout				 * occurred.  This left the semaphore in the				 * signaled state.  Call WaitForSingleObject()				 * to clear the semaphore.				 */				_PR_THREAD_UNLOCK(thread);				rv = WaitForSingleObject(thread->md.blocked_sema, INFINITE);				PR_ASSERT(rv == WAIT_OBJECT_0);			}			return PR_SUCCESS;			break;		default:			return PR_FAILURE;			break;	}    return PR_SUCCESS;}PRStatus_PR_MD_WAIT(PRThread *thread, PRIntervalTime ticks){    DWORD rv;	if (_native_threads_only) {		return(_native_thread_md_wait(thread, ticks));	}    if ( thread->flags & _PR_GLOBAL_SCOPE ) {        PRUint32 msecs = (ticks == PR_INTERVAL_NO_TIMEOUT) ?            INFINITE : PR_IntervalToMilliseconds(ticks);        rv = WaitForSingleObject(thread->md.blocked_sema, msecs);        switch(rv) {            case WAIT_OBJECT_0:                return PR_SUCCESS;                break;            case WAIT_TIMEOUT:                _PR_THREAD_LOCK(thread);                if (thread->state == _PR_IO_WAIT) {                    if (thread->io_pending == PR_TRUE) {                        thread->state = _PR_RUNNING;                        thread->io_suspended = PR_TRUE;                        _PR_THREAD_UNLOCK(thread);                    } else {                        /* The IO completed just at the same time the timeout                         * occurred.  This left the semaphore in the signaled                         * state.  Call WaitForSingleObject() to clear the                         * semaphore.                         */                        _PR_THREAD_UNLOCK(thread);                        rv = WaitForSingleObject(thread->md.blocked_sema, INFINITE);                        PR_ASSERT(rv == WAIT_OBJECT_0);                    }                } else {                    if (thread->wait.cvar != NULL) {                        PR_ASSERT(thread->state == _PR_COND_WAIT);                        thread->wait.cvar = NULL;                        thread->state = _PR_RUNNING;                        _PR_THREAD_UNLOCK(thread);                    } else {                        /* The CVAR was notified just as the timeout                         * occurred.  This left the semaphore in the                         * signaled state.  Call WaitForSingleObject()                         * to clear the semaphore.                         */                        _PR_THREAD_UNLOCK(thread);                        rv = WaitForSingleObject(thread->md.blocked_sema, INFINITE);                        PR_ASSERT(rv == WAIT_OBJECT_0);                    }                }                return PR_SUCCESS;                break;            default:                return PR_FAILURE;                break;        }    } else {        PRInt32 is;        _PR_INTSOFF(is);        _PR_MD_SWITCH_CONTEXT(thread);    }    return PR_SUCCESS;}static void_native_thread_io_nowait(    PRThread *thread,    int rv,    int bytes){    int rc;    PR_ASSERT(rv != 0);    _PR_THREAD_LOCK(thread);    if (thread->state == _PR_IO_WAIT) {        PR_ASSERT(thread->io_suspended == PR_FALSE);        PR_ASSERT(thread->io_pending == PR_TRUE);        thread->state = _PR_RUNNING;        thread->io_pending = PR_FALSE;        _PR_THREAD_UNLOCK(thread);    } else {        /* The IO completed just at the same time the         * thread was interrupted. This left the semaphore         * in the signaled state. Call WaitForSingleObject()         * to clear the semaphore.         */        PR_ASSERT(thread->io_suspended == PR_TRUE);        PR_ASSERT(thread->io_pending == PR_TRUE);        thread->io_pending = PR_FALSE;        _PR_THREAD_UNLOCK(thread);        rc = WaitForSingleObject(thread->md.blocked_sema, INFINITE);        PR_ASSERT(rc == WAIT_OBJECT_0);    }    thread->md.blocked_io_status = rv;    thread->md.blocked_io_bytes = bytes;    rc = ResetEvent(thread->md.thr_event);    PR_ASSERT(rc != 0);    return;}static PRStatus_native_thread_io_wait(PRThread *thread, PRIntervalTime ticks){    DWORD rv, bytes;#define _NATIVE_IO_WAIT_HANDLES		2#define _NATIVE_WAKEUP_EVENT_INDEX	0#define _NATIVE_IO_EVENT_INDEX		1	HANDLE wait_handles[_NATIVE_IO_WAIT_HANDLES];	PRUint32 msecs = (ticks == PR_INTERVAL_NO_TIMEOUT) ?		INFINITE : PR_IntervalToMilliseconds(ticks);    PR_ASSERT(thread->flags & _PR_GLOBAL_SCOPE);	wait_handles[0] = thread->md.blocked_sema;	wait_handles[1] = thread->md.thr_event;	rv = WaitForMultipleObjects(_NATIVE_IO_WAIT_HANDLES, wait_handles,										FALSE, msecs);	switch(rv) {		case WAIT_OBJECT_0 + _NATIVE_IO_EVENT_INDEX:			/*			 * I/O op completed			 */			_PR_THREAD_LOCK(thread);			if (thread->state == _PR_IO_WAIT) {				PR_ASSERT(thread->io_suspended == PR_FALSE);				PR_ASSERT(thread->io_pending == PR_TRUE);				thread->state = _PR_RUNNING;				thread->io_pending = PR_FALSE;				_PR_THREAD_UNLOCK(thread);			} else {				/* The IO completed just at the same time the				 * thread was interrupted. This led to us being				 * notified twice. Call WaitForSingleObject()				 * to clear the semaphore.				 */				PR_ASSERT(thread->io_suspended == PR_TRUE);				PR_ASSERT(thread->io_pending == PR_TRUE);				thread->io_pending = PR_FALSE;				_PR_THREAD_UNLOCK(thread);				rv = WaitForSingleObject(thread->md.blocked_sema,							INFINITE);				PR_ASSERT(rv == WAIT_OBJECT_0);			}			rv = GetOverlappedResult((HANDLE) thread->io_fd,				&thread->md.overlapped.overlapped, &bytes, FALSE);			thread->md.blocked_io_status = rv;			if (rv != 0) {				thread->md.blocked_io_bytes = bytes;			} else {				thread->md.blocked_io_error = GetLastError();				PR_ASSERT(ERROR_IO_PENDING != thread->md.blocked_io_error);			}			rv = ResetEvent(thread->md.thr_event);			PR_ASSERT(rv != 0);			break;		case WAIT_OBJECT_0 + _NATIVE_WAKEUP_EVENT_INDEX:			/*			 * I/O interrupted; 			 */#ifdef DEBUG			_PR_THREAD_LOCK(thread);			PR_ASSERT(thread->io_suspended == PR_TRUE);			_PR_THREAD_UNLOCK(thread);#endif			break;		case WAIT_TIMEOUT:			_PR_THREAD_LOCK(thread);			if (thread->state == _PR_IO_WAIT) {				thread->state = _PR_RUNNING;				thread->io_suspended = PR_TRUE;				_PR_THREAD_UNLOCK(thread);			} else {				/*				 * The thread was interrupted just as the timeout				 * occurred. This left the semaphore in the signaled				 * state. Call WaitForSingleObject() to clear the				 * semaphore.				 */				PR_ASSERT(thread->io_suspended == PR_TRUE);				_PR_THREAD_UNLOCK(thread);				rv = WaitForSingleObject(thread->md.blocked_sema, INFINITE);				PR_ASSERT(rv == WAIT_OBJECT_0);			}			break;		default:			return PR_FAILURE;			break;	}    return PR_SUCCESS;}static PRStatus_NT_IO_WAIT(PRThread *thread, PRIntervalTime timeout){    PRBool fWait = PR_TRUE;	if (_native_threads_only) {		return(_native_thread_io_wait(thread, timeout));	}    if (!_PR_IS_NATIVE_THREAD(thread))  {        _PR_THREAD_LOCK(thread);        /* The IO may have already completed; if so, don't add to sleepQ,          * since we are already on the runQ!         */        if (thread->io_pending == PR_TRUE) {            _PR_SLEEPQ_LOCK(thread->cpu);            _PR_ADD_SLEEPQ(thread, timeout);            _PR_SLEEPQ_UNLOCK(thread->cpu);        } else            fWait = PR_FALSE;        _PR_THREAD_UNLOCK(thread);    }    if (fWait)        return _PR_MD_WAIT(thread, timeout);    else        return PR_SUCCESS;}/* * Unblock threads waiting for I/O * used when interrupting threads * * NOTE: The thread lock should held when this function is called. * On return, the thread lock is released. */void _PR_Unblock_IO_Wait(PRThread *thr){    PRStatus rv;    _PRCPU *cpu = thr->cpu;     PR_ASSERT(thr->state == _PR_IO_WAIT);	/*	 * A thread for which an I/O timed out or was interrupted cannot be	 * in an IO_WAIT state except as a result of calling PR_Close or	 * PR_NT_CancelIo for the FD. For these two cases, _PR_IO_WAIT state	 * is not interruptible	 */	if (thr->md.interrupt_disabled == PR_TRUE) {    	_PR_THREAD_UNLOCK(thr);		return;	}    thr->io_suspended = PR_TRUE;    thr->state = _PR_RUNNABLE;    if (!_PR_IS_NATIVE_THREAD(thr)) {        PRThread *me = _PR_MD_CURRENT_THREAD();        PR_ASSERT(thr->flags & (_PR_ON_SLEEPQ | _PR_ON_PAUSEQ));        _PR_SLEEPQ_LOCK(cpu);        _PR_DEL_SLEEPQ(thr, PR_TRUE);        _PR_SLEEPQ_UNLOCK(cpu);		/*		 * this thread will continue to run on the same cpu until the		 * I/O is aborted by closing the FD or calling CancelIO		 */		thr->md.thr_bound_cpu = cpu;        PR_ASSERT(!(thr->flags & _PR_IDLE_THREAD));        _PR_AddThreadToRunQ(me, thr);    }    _PR_THREAD_UNLOCK(thr);    rv = _PR_MD_WAKEUP_WAITER(thr);    PR_ASSERT(PR_SUCCESS == rv);}/* Resume an outstanding IO; requires that after the switch, we disable */static PRStatus_NT_ResumeIO(PRThread *thread, PRIntervalTime ticks){    PRBool fWait = PR_TRUE;    if (!_PR_IS_NATIVE_THREAD(thread)) {        if (_pr_use_static_tls) {            _pr_io_restarted_io = thread;        } else {            TlsSetValue(_pr_io_restartedIOIndex, thread);        }    } else {        _PR_THREAD_LOCK(thread);        if (!thread->io_pending)            fWait = PR_FALSE;        thread->io_suspended = PR_FALSE;                    _PR_THREAD_UNLOCK(thread);    }    /* We don't put ourselves back on the sleepQ yet; until we      * set the suspended bit to false, we can't do that.  Just save     * the sleep time here, and then continue.  The restarted_io handler     * will add us to the sleepQ if needed.     */    thread->sleep = ticks;    if (fWait) {        if (!_PR_IS_NATIVE_THREAD(thread))            return _PR_MD_WAIT(thread, ticks);        else            return _NT_IO_WAIT(thread, ticks);    }    return PR_SUCCESS;}PRStatus_PR_MD_WAKEUP_WAITER(PRThread *thread){    if (thread == NULL) {        /* If thread is NULL, we aren't waking a thread, we're just poking         * idle thread          */        if ( PostQueuedCompletionStatus(_pr_completion_port, 0,             KEY_CVAR, NULL) == FALSE)             return PR_FAILURE;        return PR_SUCCESS;    }    if ( _PR_IS_NATIVE_THREAD(thread) ) {        if (ReleaseSemaphore(thread->md.blocked_sema, 1, NULL) == FALSE)            return PR_FAILURE;        else            return PR_SUCCESS;    } else {        PRThread *me = _PR_MD_CURRENT_THREAD();        /* When a Native thread has to awaken a user thread, it has to poke         * the completion port because all user threads might be idle, and         * thus the CPUs are just waiting for a completion.           *

⌨️ 快捷键说明

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