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

📄 ntio.c

📁 Netscape NSPR库源码
💻 C
📖 第 1 页 / 共 5 页
字号:
         * XXXMB - can we know when we are truely idle (and not checking          *         the runq)?         */        if ((_PR_IS_NATIVE_THREAD(me) || (thread->cpu != me->cpu)) &&                (!thread->md.thr_bound_cpu)) {            /* The thread should not be in any queue */            PR_ASSERT(thread->queueCount == 0);            if ( PostQueuedCompletionStatus(_pr_completion_port, 0,                 KEY_CVAR, &(thread->md.overlapped.overlapped)) == FALSE)                 return PR_FAILURE;        }        return PR_SUCCESS;    }}void_PR_MD_INIT_IO(){    WORD WSAVersion = 0x0101;    WSADATA WSAData;    int err;    OSVERSIONINFO OSversion;    err = WSAStartup( WSAVersion, &WSAData );    PR_ASSERT(0 == err);                                                          _pr_completion_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE,                                                  NULL,                                                  0,                                                  0);     _MD_NEW_LOCK(&_pr_recycle_lock);    _MD_NEW_LOCK(&_pr_ioq_lock);    OSversion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);    if (GetVersionEx(&OSversion)) {        _nt_version_gets_lockfile_completion = PR_FALSE;        if (OSversion.dwMajorVersion >= 4) {            _nt_version_gets_lockfile_completion = PR_TRUE;        }    } else         PR_ASSERT(0);    IsFileLocalInit();    /*     * UDP support: start up the continuation thread     */    pt_tq.op_count = 0;    pt_tq.head = pt_tq.tail = NULL;    pt_tq.ml = PR_NewLock();    PR_ASSERT(NULL != pt_tq.ml);    pt_tq.new_op = PR_NewCondVar(pt_tq.ml);    PR_ASSERT(NULL != pt_tq.new_op);#if defined(DEBUG)    memset(&pt_debug, 0, sizeof(struct pt_debug_s));#endif    pt_tq.thread = PR_CreateThread(        PR_SYSTEM_THREAD, ContinuationThread, NULL,        PR_PRIORITY_URGENT, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);    PR_ASSERT(NULL != pt_tq.thread);#ifdef DEBUG    /* Doublecheck _pr_filetime_offset's hard-coded value is correct. */    {        SYSTEMTIME systime;        union {           PRTime prt;           FILETIME ft;        } filetime;        BOOL rv;        systime.wYear = 1970;        systime.wMonth = 1;        /* wDayOfWeek is ignored */        systime.wDay = 1;        systime.wHour = 0;        systime.wMinute = 0;        systime.wSecond = 0;        systime.wMilliseconds = 0;        rv = SystemTimeToFileTime(&systime, &filetime.ft);        PR_ASSERT(0 != rv);        PR_ASSERT(filetime.prt == _pr_filetime_offset);    }#endif /* DEBUG */    _PR_NT_InitSids();}/* --- SOCKET IO --------------------------------------------------------- *//* _md_get_recycled_socket() * Get a socket from the recycle bin; if no sockets are in the bin, * create one.  The socket will be passed to AcceptEx() as the * second argument. */static SOCKET_md_get_recycled_socket(){    SOCKET rv;    int af = AF_INET;    _MD_LOCK(&_pr_recycle_lock);    if (_pr_recycle_tail) {        _pr_recycle_tail--;        rv = _pr_recycle_array[_pr_recycle_tail];        _MD_UNLOCK(&_pr_recycle_lock);        return rv;    }    _MD_UNLOCK(&_pr_recycle_lock);    rv = _PR_MD_SOCKET(af, SOCK_STREAM, 0);    if (rv != INVALID_SOCKET && _md_Associate((HANDLE)rv) == 0) {        closesocket(rv);        return INVALID_SOCKET;    }    return rv;}/* _md_put_recycled_socket() * Add a socket to the recycle bin. */static void_md_put_recycled_socket(SOCKET newsock){    PR_ASSERT(_pr_recycle_tail >= 0);    _MD_LOCK(&_pr_recycle_lock);    if (_pr_recycle_tail < RECYCLE_SIZE) {        _pr_recycle_array[_pr_recycle_tail] = newsock;        _pr_recycle_tail++;        _MD_UNLOCK(&_pr_recycle_lock);    } else {        _MD_UNLOCK(&_pr_recycle_lock);        closesocket(newsock);    }     return;}/* _md_Associate() * Associates a file with the completion port. * Returns 0 on failure, 1 on success. */PRInt32_md_Associate(HANDLE file){    HANDLE port;	if (!_native_threads_only) {		port = CreateIoCompletionPort((HANDLE)file, 										_pr_completion_port, 										KEY_IO,										0);		/* XXX should map error codes on failures */		return (port == _pr_completion_port);	} else {		return 1;	}}/* * _md_MakeNonblock() * Make a socket nonblocking. * Returns 0 on failure, 1 on success. */static PRInt32_md_MakeNonblock(HANDLE file){    int rv;    u_long one = 1;    rv = ioctlsocket((SOCKET)file, FIONBIO, &one);    /* XXX should map error codes on failures */    return (rv == 0);}static int missing_completions = 0;static int max_wait_loops = 0;static PRInt32_NT_IO_ABORT(PRInt32 sock){    PRThread *me = _PR_MD_CURRENT_THREAD();    PRBool fWait;    PRInt32 rv;    int loop_count;    /* This is a clumsy way to abort the IO, but it is all we can do.     * It looks a bit racy, but we handle all the cases.      * case 1:  IO completes before calling closesocket     *     case 1a:  fWait is set to PR_FALSE     *           This should e the most likely case.  We'll properly     *           not wait call _NT_IO_WAIT, since the closesocket()     *           won't be forcing a completion.     *     case 1b: fWait is set to PR_TRUE     *           This hopefully won't happen much.  When it does, this     *           thread will timeout in _NT_IO_WAIT for CLOSE_INTERVAL     *           before cleaning up.     * case 2:  IO does not complete before calling closesocket     *     case 2a: IO never completes     *           This is the likely case.  We'll close it and wait     *           for the completion forced by the close.  Return should     *           be immediate.     *     case 2b: IO completes just after calling closesocket     *           Since the closesocket is issued, we'll either get a     *           completion back for the real IO or for the close.  We     *           don't really care.  It may not even be possible to get     *           a real completion here.  In any event, we'll awaken     *           from NT_IO_WAIT immediately.     */    _PR_THREAD_LOCK(me);    fWait = me->io_pending;    if (fWait) {        /*         * If there's still I/O pending, it should have already timed         * out once before this function is called.         */        PR_ASSERT(me->io_suspended == PR_TRUE);        /* Set up to wait for I/O completion again */        me->state = _PR_IO_WAIT;        me->io_suspended = PR_FALSE;        me->md.interrupt_disabled = PR_TRUE;    }    _PR_THREAD_UNLOCK(me);    /* Close the socket if there is one */    if (sock != INVALID_SOCKET) {        rv = closesocket((SOCKET)sock);    }    /* If there was I/O pending before the close, wait for it to complete */    if (fWait) {        /* Wait and wait for the I/O to complete */        for (loop_count = 0; fWait; ++loop_count) {            _NT_IO_WAIT(me, CLOSE_TIMEOUT);            _PR_THREAD_LOCK(me);            fWait = me->io_pending;            if (fWait) {                PR_ASSERT(me->io_suspended == PR_TRUE);                me->state = _PR_IO_WAIT;                me->io_suspended = PR_FALSE;            }            _PR_THREAD_UNLOCK(me);            if (loop_count > max_wait_loops) {                max_wait_loops = loop_count;            }        }        if (loop_count > 1) {            ++missing_completions;        }        me->md.interrupt_disabled = PR_FALSE;        me->io_pending = PR_FALSE;        me->state = _PR_RUNNING;    }    PR_ASSERT(me->io_pending == PR_FALSE);    me->md.thr_bound_cpu = NULL;    me->io_suspended = PR_FALSE;    return rv;}PRInt32_PR_MD_SOCKET(int af, int type, int flags){    SOCKET sock;    sock = socket(af, type, flags);    if (sock == INVALID_SOCKET) {        _PR_MD_MAP_SOCKET_ERROR(WSAGetLastError());    }    return (PRInt32)sock;}struct connect_data_s {    PRInt32 status;    PRInt32 error;    PRInt32 osfd;    struct sockaddr *addr;    PRUint32 addrlen;    PRIntervalTime timeout;};void_PR_MD_connect_thread(void *cdata){    struct connect_data_s *cd = (struct connect_data_s *)cdata;    cd->status = connect(cd->osfd, cd->addr, cd->addrlen);    if (cd->status == SOCKET_ERROR)        cd->error = WSAGetLastError();    return;}PRInt32_PR_MD_CONNECT(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen,                PRIntervalTime timeout){    PRInt32 osfd = fd->secret->md.osfd;    PRInt32 rv, err;    u_long nbio;    PRInt32 rc;    if (fd->secret->nonblocking) {        if (!fd->secret->md.io_model_committed) {            rv = _md_MakeNonblock((HANDLE)osfd);            PR_ASSERT(0 != rv);            fd->secret->md.io_model_committed = PR_TRUE;        }        if ((rv = connect(osfd, (struct sockaddr *) addr, addrlen)) == -1) {            err = WSAGetLastError();            _PR_MD_MAP_CONNECT_ERROR(err);        }        return rv;    }    /*     * Temporarily make the socket non-blocking so that we can     * initiate a non-blocking connect and wait for its completion     * (with a timeout) in select.     */    PR_ASSERT(!fd->secret->md.io_model_committed);    nbio = 1;    rv = ioctlsocket((SOCKET)osfd, FIONBIO, &nbio);    PR_ASSERT(0 == rv);    rc = _nt_nonblock_connect(fd, (struct sockaddr *) addr, addrlen, timeout);    /* Set the socket back to blocking. */    nbio = 0;    rv = ioctlsocket((SOCKET)osfd, FIONBIO, &nbio);    PR_ASSERT(0 == rv);    return rc;}PRInt32_PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen){    PRInt32 rv;#if 0    int one = 1;#endif    rv = bind(fd->secret->md.osfd, (const struct sockaddr *)&(addr->inet), addrlen);    if (rv == SOCKET_ERROR) {        _PR_MD_MAP_BIND_ERROR(WSAGetLastError());        return -1;    }#if 0    /* Disable nagle- so far unknown if this is good or not...     */    rv = setsockopt(fd->secret->md.osfd,                     SOL_SOCKET,                    TCP_NODELAY,                    (const char *)&one,                    sizeof(one));    PR_ASSERT(rv == 0);#endif    return 0;}void _PR_MD_UPDATE_ACCEPT_CONTEXT(PRInt32 accept_sock, PRInt32 listen_sock){    /* Sockets accept()'d with AcceptEx need to call this setsockopt before     * calling anything other than ReadFile(), WriteFile(), send(), recv(),      * Transmitfile(), and closesocket().  In order to call any other      * winsock functions, we have to make this setsockopt call.     *     * XXXMB - For the server, we *NEVER* need this in     * the "normal" code path.  But now we have to call it.  This is a waste     * of a system call.  We'd like to only call it before calling the      * obscure socket calls, but since we don't know at that point what the     * original socket was (or even if it is still alive) we can't do it     * at that point...      */    setsockopt((SOCKET)accept_sock,                SOL_SOCKET,                SO_UPDATE_ACCEPT_CONTEXT,               (char *)&listen_sock,               sizeof(listen_sock));}#define INET_ADDR_PADDED (sizeof(PRNetAddr) + 16)PRInt32_PR_MD_FAST_ACCEPT(PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen,              PRIntervalTime timeout, PRBool fast,               _PR_AcceptTimeoutCallback callback, void *callbackArg){    PRInt32 osfd = fd->secret->md.osfd;    PRThread *me = _PR_MD_CURRENT_THREAD();    SOCKET accept_sock;    int bytes;    PRNetAddr *Laddr;    PRNetAddr *Raddr;    PRUint32 llen, err;    int rv;    if (_NT_USE_NB_IO(fd)) {        if (!fd->secret->md.io_model_committed) {            rv = _md_MakeNonblock((HANDLE)osfd);            PR_ASSERT(0 != rv);

⌨️ 快捷键说明

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