home *** CD-ROM | disk | FTP | other *** search
- /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /*
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
-
- #include "primpl.h"
-
- static int winsockNotPresent = 0;
-
- void
- _PR_MD_INIT_IO()
- {
- int rv;
-
- WORD WSAVersion = 0x0101;
- WSADATA WSAData;
-
- rv = WSAStartup( WSAVersion, &WSAData );
- if ( rv != 0 )
- {
- _PR_MD_MAP_WSASTARTUP_ERROR(WSAGetLastError());
- winsockNotPresent = 1;
- }
- return;
- }
-
- void
- _PR_MD_CLEANUP_BEFORE_EXIT(void)
- {
- int rv;
- int err;
-
- rv = WSACleanup();
- if ( rv == SOCKET_ERROR )
- {
- err = WSAGetLastError();
- PR_ASSERT(0);
- }
- return;
- } /* end _PR_MD_CLEANUP_BEFORE_EXIT() */
-
- /* --- SOCKET IO --------------------------------------------------------- */
-
- PRStatus
- _MD_WindowsGetHostName(char *name, PRUint32 namelen)
- {
- PRIntn rv;
- PRInt32 syserror;
-
- rv = gethostname(name, (PRInt32) namelen);
- if (0 == rv) {
- return PR_SUCCESS;
- }
- syserror = WSAGetLastError();
- PR_ASSERT(WSANOTINITIALISED != syserror);
- _PR_MD_MAP_GETHOSTNAME_ERROR(syserror);
- return PR_FAILURE;
- }
-
-
- PRInt32
- _PR_MD_SOCKET(int af, int type, int flags)
- {
- SOCKET sock;
- PRUint32 one = 1;
- PRInt32 rv;
- PRInt32 err;
-
- if ( winsockNotPresent )
- return( (PRInt32)INVALID_SOCKET );
-
- sock = socket(af, type, flags);
-
- if (sock == INVALID_SOCKET )
- {
- int rv = GetLastError();
- closesocket(sock);
- _PR_MD_MAP_SOCKET_ERROR(rv);
- return (PRInt32)INVALID_SOCKET;
- }
-
- /*
- ** Make the socket Non-Blocking
- */
- rv = ioctlsocket( sock, FIONBIO, &one);
- if ( rv != 0 )
- {
- err = WSAGetLastError();
- return -1;
- }
-
- return (PRInt32)sock;
- }
-
-
- PRInt32
- _PR_MD_SOCKETAVAILABLE(PRFileDesc *fd)
- {
- PRUint32 result;
-
- if (ioctlsocket(fd->secret->md.osfd, FIONREAD, &result) < 0) {
- PR_SetError(PR_BAD_DESCRIPTOR_ERROR, WSAGetLastError());
- return -1;
- }
- return result;
- }
-
-
- /*
- ** _MD_CloseSocket() -- Close a socket
- **
- */
- PRInt32
- _PR_MD_CLOSE_SOCKET(PRInt32 osfd)
- {
- PRInt32 rv;
-
- rv = closesocket((SOCKET) osfd );
- if (rv < 0)
- _PR_MD_MAP_CLOSE_ERROR(WSAGetLastError());
-
- return rv;
- }
-
- PRInt32 _PR_MD_LISTEN(PRFileDesc *fd, PRIntn backlog)
- {
- int rv, err;
-
- rv = listen(fd->secret->md.osfd, backlog);
- if ( rv == SOCKET_ERROR ) {
- _PR_MD_MAP_LISTEN_ERROR(WSAGetLastError());
- return(-1);
- }
- return(rv);
- }
-
- PRInt32
- _PR_MD_ACCEPT(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen,
- PRIntervalTime timeout )
- {
- PRInt32 osfd = fd->secret->md.osfd;
- PRThread *me = _PR_MD_CURRENT_THREAD();
- PRInt32 err;
- PRIntn rv;
-
- MD_ASSERTINT( *addrlen );
-
- while ((rv = (SOCKET)accept(osfd, (struct sockaddr *) addr,
- (int *)addrlen)) == INVALID_SOCKET ) {
- err = WSAGetLastError();
- if ( err == WSAEWOULDBLOCK ) {
- if (fd->secret->nonblocking) {
- break;
- }
- if (_PR_WaitForFD(osfd, PR_POLL_READ, timeout) == 0) {
- if ( _PR_PENDING_INTERRUPT(me))
- {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
- } else
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- }
- rv = -1;
- goto done;
- } else if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
- rv = -1;
- goto done;
- }
- } else if ((err == WSAEINTR) && (!_PR_PENDING_INTERRUPT(me))){
- continue;
- } else {
- break;
- }
- }
- if (rv < 0) {
- _PR_MD_MAP_ACCEPT_ERROR(err);
- }
- done:
- if ( rv == INVALID_SOCKET )
- return(-1 );
- else
- return(rv);
- } /* end _MD_Accept() */
-
-
- PRInt32
- _PR_MD_CONNECT(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen,
- PRIntervalTime timeout)
- {
- PRInt32 osfd = fd->secret->md.osfd;
- PRThread *me = _PR_MD_CURRENT_THREAD();
- PRInt32 rv, err;
-
- while ((rv = connect(osfd, (struct sockaddr *)addr, addrlen)) == -1) {
- err = WSAGetLastError();
- if (err == WSAEISCONN) {
- rv = 0;
- break;
- }
- /* for winsock1.1, it reports EALREADY as EINVAL */
- if ((err == WSAEWOULDBLOCK)
- ||(err == WSAEALREADY)
- || (err = WSAEINVAL)) {
- if (fd->secret->nonblocking) {
- break;
- }
- if (_PR_WaitForFD(osfd, PR_POLL_WRITE, timeout) == 0) {
- if ( _PR_PENDING_INTERRUPT(me))
- {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
- } else
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- }
- rv = -1;
- goto done;
- } else if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
- rv = -1;
- goto done;
- }
- } else if ((err == WSAEINTR) && (!_PR_PENDING_INTERRUPT(me))){
- continue;
- } else {
- break;
- }
- }
-
- if (rv < 0) {
- _PR_MD_MAP_CONNECT_ERROR(err);
- }
- done:
- return rv;
- }
-
- PRInt32
- _PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen)
- {
- PRInt32 rv;
- int one = 1;
-
- rv = bind(fd->secret->md.osfd, (const struct sockaddr *)&(addr->inet), addrlen);
-
- if (rv == SOCKET_ERROR) {
- _PR_MD_MAP_BIND_ERROR(WSAGetLastError());
- return -1;
- }
-
- return 0;
- }
-
-
- PRInt32
- _PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
- PRIntervalTime timeout)
- {
- PRInt32 osfd = fd->secret->md.osfd;
- PRThread *me = _PR_MD_CURRENT_THREAD();
- PRInt32 rv, err;
-
- while ((rv = recv(osfd,buf,amount,flags)) == -1) {
- err = WSAGetLastError();
- if ( err == WSAEWOULDBLOCK ) {
- if (fd->secret->nonblocking) {
- break;
- }
- if (_PR_WaitForFD(osfd, PR_POLL_READ, timeout) == 0) {
- if ( _PR_PENDING_INTERRUPT(me))
- {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
- } else
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- }
- rv = -1;
- goto done;
- } else if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
- rv = -1;
- goto done;
- }
- } else if ((err == WSAEINTR) && (!_PR_PENDING_INTERRUPT(me))){
- continue;
- } else {
- break;
- }
- }
- if (rv < 0) {
- _PR_MD_MAP_RECV_ERROR(err);
- }
- done:
- return(rv);
- }
-
- PRInt32
- _PR_MD_SEND(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
- PRIntervalTime timeout)
- {
- PRInt32 osfd = fd->secret->md.osfd;
- PRThread *me = _PR_MD_CURRENT_THREAD();
- PRInt32 rv, err;
-
- while ((rv = send(osfd,buf,amount,flags)) == -1) {
- err = WSAGetLastError();
- if ( err == WSAEWOULDBLOCK ) {
- if (fd->secret->nonblocking) {
- break;
- }
- if (_PR_WaitForFD(osfd, PR_POLL_WRITE, timeout) == 0) {
- if ( _PR_PENDING_INTERRUPT(me))
- {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
- } else
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- }
- rv = -1;
- goto done;
- } else if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
- rv = -1;
- goto done;
- }
- } else if ((err == WSAEINTR) && (!_PR_PENDING_INTERRUPT(me))){
- continue;
- } else {
- break;
- }
- }
- if (rv < 0) {
- _PR_MD_MAP_SEND_ERROR(err);
- }
- done:
- return rv;
- }
-
- PRInt32
- _PR_MD_SENDTO(PRFileDesc*fd, const void *buf, PRInt32 amount, PRIntn flags,
- const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
- {
- PRInt32 osfd = fd->secret->md.osfd;
- PRThread *me = _PR_MD_CURRENT_THREAD();
- PRInt32 rv, err;
-
- while ((rv = sendto(osfd, buf, amount, flags,
- (struct sockaddr *) addr, addrlen)) == -1) {
- err = WSAGetLastError();
- if ( err == WSAEWOULDBLOCK ) {
- if (fd->secret->nonblocking) {
- break;
- }
- if (_PR_WaitForFD(osfd, PR_POLL_WRITE, timeout) == 0) {
- if ( _PR_PENDING_INTERRUPT(me))
- {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
- } else
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- }
- rv = -1;
- goto done;
- } else if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
- rv = -1;
- goto done;
- }
- } else if ((err == WSAEINTR) && (!_PR_PENDING_INTERRUPT(me))){
- continue;
- } else {
- break;
- }
- }
- if (rv < 0) {
- _PR_MD_MAP_SENDTO_ERROR(err);
- }
- done:
- return rv;
- }
-
- PRInt32
- _PR_MD_RECVFROM(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
- PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout)
- {
- PRInt32 osfd = fd->secret->md.osfd;
- PRThread *me = _PR_MD_CURRENT_THREAD();
- PRInt32 rv, err;
-
- while ((*addrlen = PR_NETADDR_SIZE(addr)),
- ((rv = recvfrom(osfd, buf, amount, flags,
- (struct sockaddr FAR *) addr,(int FAR *)addrlen)) == -1)) {
- err = WSAGetLastError();
- if ( err == WSAEWOULDBLOCK ) {
- if (fd->secret->nonblocking) {
- break;
- }
- if (_PR_WaitForFD(osfd, PR_POLL_READ, timeout) == 0) {
- if ( _PR_PENDING_INTERRUPT(me))
- {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
- } else
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- }
- rv = -1;
- goto done;
- } else if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
- rv = -1;
- goto done;
- }
- } else if ((err == WSAEINTR) && (!_PR_PENDING_INTERRUPT(me))){
- continue;
- } else {
- break;
- }
- }
- if (rv < 0) {
- _PR_MD_MAP_RECVFROM_ERROR(err);
- }
- done:
- return(rv);
- }
-
- PRInt32
- _PR_MD_WRITEV(PRFileDesc *fd, PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout)
- {
- int index;
- int sent = 0;
- int rv;
-
- for (index=0; index < iov_size; index++)
- {
-
- /*
- * XXX To be fixed
- * should call PR_Send
- */
-
- rv = _PR_MD_SEND(fd, iov[index].iov_base, iov[index].iov_len, 0, timeout);
- if (rv > 0)
- sent += rv;
- if ( rv != iov[index].iov_len )
- {
- if (sent <= 0)
- return -1;
- return -1;
- }
- }
- return sent;
- }
-
- PRInt32
- _PR_MD_SHUTDOWN(PRFileDesc *fd, PRIntn how)
- {
- PRInt32 rv;
-
- rv = shutdown(fd->secret->md.osfd, how);
- if (rv < 0)
- _PR_MD_MAP_SHUTDOWN_ERROR(WSAGetLastError());
- return rv;
- }
-
- PRStatus
- _PR_MD_GETSOCKNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *len)
- {
- PRInt32 rv;
-
- rv = getsockname((SOCKET)fd->secret->md.osfd, (struct sockaddr *)addr, (int *)len);
- if (rv==0)
- return PR_SUCCESS;
- else {
- _PR_MD_MAP_GETSOCKNAME_ERROR(WSAGetLastError());
- return PR_FAILURE;
- }
- }
-
- PRStatus
- _PR_MD_GETPEERNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *len)
- {
- PRInt32 rv;
-
- rv = getpeername((SOCKET)fd->secret->md.osfd, (struct sockaddr *)addr, (int*)len);
- if (rv==0)
- return PR_SUCCESS;
- else {
- _PR_MD_MAP_GETPEERNAME_ERROR(WSAGetLastError());
- return PR_FAILURE;
- }
- }
-
- PRStatus
- _PR_MD_GETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval, PRInt32* optlen)
- {
- PRInt32 rv;
-
- rv = getsockopt((SOCKET)fd->secret->md.osfd, level, optname, optval, (int*)optlen);
- if (rv==0)
- return PR_SUCCESS;
- else {
- _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError());
- return PR_FAILURE;
- }
- }
-
- PRStatus
- _PR_MD_SETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, const char* optval, PRInt32 optlen)
- {
- PRInt32 rv;
-
- rv = setsockopt((SOCKET)fd->secret->md.osfd, level, optname, optval, optlen);
- if (rv==0)
- return PR_SUCCESS;
- else {
- _PR_MD_MAP_SETSOCKOPT_ERROR(WSAGetLastError());
- return PR_FAILURE;
- }
- }
-
- void
- _PR_MD_MAKE_NONBLOCK(PRFileDesc *f)
- {
- return; // do nothing!
- }
-
- /*
- ** Wait for I/O on a single descriptor.
- *
- * return 0, if timed-out, else return 1
- */
- PRInt32
- _PR_WaitForFD(PRInt32 osfd, PRUintn how, PRIntervalTime timeout)
- {
- _PRWin16PollDesc *pd;
- PRPollQueue *pq;
- PRIntn is;
- PRInt32 rv = 1;
- PRThread *me = _PR_MD_CURRENT_THREAD();
-
- PR_ASSERT(!(me->flags & _PR_IDLE_THREAD));
-
- pd = &me->md.thr_pd;
- pq = &me->md.thr_pq;
- if (timeout == PR_INTERVAL_NO_WAIT) return 0;
-
- pd->osfd = osfd;
- pd->in_flags = how;
- pd->out_flags = 0;
-
- pq->pds = pd;
- pq->npds = 1;
-
- _PR_INTSOFF(is);
- _PR_MD_IOQ_LOCK();
- _PR_THREAD_LOCK(me);
-
- if (_PR_PENDING_INTERRUPT(me)) {
- _PR_THREAD_UNLOCK(me);
- _PR_MD_IOQ_UNLOCK();
- return 0;
- }
-
- pq->thr = me;
- pq->on_ioq = PR_TRUE;
- pq->timeout = timeout;
- _PR_ADD_TO_IOQ((*pq), me->cpu);
- if (how == PR_POLL_READ) {
- FD_SET(osfd, &_PR_FD_READ_SET(me->cpu));
- (_PR_FD_READ_CNT(me->cpu))[osfd]++;
- } else if (how == PR_POLL_WRITE) {
- FD_SET(osfd, &_PR_FD_WRITE_SET(me->cpu));
- (_PR_FD_WRITE_CNT(me->cpu))[osfd]++;
- } else {
- FD_SET(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
- (_PR_FD_EXCEPTION_CNT(me->cpu))[osfd]++;
- }
- if (_PR_IOQ_MAX_OSFD(me->cpu) < osfd)
- _PR_IOQ_MAX_OSFD(me->cpu) = osfd;
- if (_PR_IOQ_TIMEOUT(me->cpu) > timeout)
- _PR_IOQ_TIMEOUT(me->cpu) = timeout;
-
- _PR_THREAD_LOCK(me);
-
- _PR_SLEEPQ_LOCK(me->cpu);
- _PR_ADD_SLEEPQ(me, timeout);
- me->state = _PR_IO_WAIT;
- me->io_pending = PR_TRUE;
- me->io_suspended = PR_FALSE;
- _PR_SLEEPQ_UNLOCK(me->cpu);
- _PR_THREAD_UNLOCK(me);
- _PR_MD_IOQ_UNLOCK();
-
- _PR_MD_WAIT(me, timeout);
- me->io_pending = PR_FALSE;
- me->io_suspended = PR_FALSE;
-
- /*
- ** If we timed out the pollq might still be on the ioq. Remove it
- ** before continuing.
- */
- if (pq->on_ioq) {
- _PR_INTSOFF(is);
- _PR_MD_IOQ_LOCK();
- /*
- * Need to check pq.on_ioq again
- */
- if (pq->on_ioq) {
- PR_REMOVE_LINK(&pq->links);
- if (how == PR_POLL_READ) {
- if ((--(_PR_FD_READ_CNT(me->cpu))[osfd]) == 0)
- FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));
-
- } else if (how == PR_POLL_WRITE) {
- if ((--(_PR_FD_WRITE_CNT(me->cpu))[osfd]) == 0)
- FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));
- } else {
- if ((--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd]) == 0)
- FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
- }
- }
- _PR_MD_IOQ_UNLOCK();
- rv = 0;
- }
- _PR_FAST_INTSON(is);
- return(rv);
- }
-
- /*
- * 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)
- {
- int pri = thr->priority;
- _PRCPU *cpu = thr->cpu;
-
- PR_ASSERT(thr->flags & (_PR_ON_SLEEPQ | _PR_ON_PAUSEQ));
- _PR_SLEEPQ_LOCK(cpu);
- _PR_DEL_SLEEPQ(thr, PR_TRUE);
- _PR_SLEEPQ_UNLOCK(cpu);
-
- PR_ASSERT(!(thr->flags & _PR_IDLE_THREAD));
- thr->state = _PR_RUNNABLE;
- _PR_RUNQ_LOCK(cpu);
- _PR_ADD_RUNQ(thr, cpu, pri);
- _PR_RUNQ_UNLOCK(cpu);
- _PR_THREAD_UNLOCK(thr);
- _PR_MD_WAKEUP_WAITER(thr);
- }
-
- /*
- ** Scan through io queue and find any bad fd's that triggered the error
- ** from _MD_SELECT
- */
- static void FindBadFDs(void)
- {
- PRCList *q;
- PRThread *me = _MD_CURRENT_THREAD();
- int sockOpt;
- int sockOptLen = sizeof(sockOpt);
-
- PR_ASSERT(!_PR_IS_NATIVE_THREAD(me));
- q = (_PR_IOQ(me->cpu)).next;
- _PR_IOQ_MAX_OSFD(me->cpu) = -1;
- _PR_IOQ_TIMEOUT(me->cpu) = PR_INTERVAL_NO_TIMEOUT;
- while (q != &_PR_IOQ(me->cpu)) {
- PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
- PRBool notify = PR_FALSE;
- _PRWin16PollDesc *pds = pq->pds;
- _PRWin16PollDesc *epds = pds + pq->npds;
- PRInt32 pq_max_osfd = -1;
-
- q = q->next;
- for (; pds < epds; pds++) {
- PRInt32 osfd = pds->osfd;
- pds->out_flags = 0;
- PR_ASSERT(osfd >= 0 || pds->in_flags == 0);
- if (pds->in_flags == 0) {
- continue; /* skip this fd */
- }
- if ( getsockopt(osfd,
- (int)SOL_SOCKET,
- SO_TYPE,
- (char*)&sockOpt,
- &sockOptLen) == SOCKET_ERROR )
- {
- if ( WSAGetLastError() == WSAENOTSOCK )
- {
- PR_LOG(_pr_io_lm, PR_LOG_MAX,
- ("file descriptor %d is bad", osfd));
- pds->out_flags = PR_POLL_NVAL;
- notify = PR_TRUE;
- }
- }
- if (osfd > pq_max_osfd) {
- pq_max_osfd = osfd;
- }
- }
-
- if (notify) {
- PRIntn pri;
- PR_REMOVE_LINK(&pq->links);
- pq->on_ioq = PR_FALSE;
-
- /*
- * Decrement the count of descriptors for each desciptor/event
- * because this I/O request is being removed from the
- * ioq
- */
- pds = pq->pds;
- for (; pds < epds; pds++) {
- PRInt32 osfd = pds->osfd;
- PRInt16 in_flags = pds->in_flags;
- PR_ASSERT(osfd >= 0 || in_flags == 0);
- if (in_flags & PR_POLL_READ) {
- if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0)
- FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));
- }
- if (in_flags & PR_POLL_WRITE) {
- if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0)
- FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));
- }
- if (in_flags & PR_POLL_EXCEPT) {
- if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0)
- FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
- }
- }
-
- _PR_THREAD_LOCK(pq->thr);
- if (pq->thr->flags & (_PR_ON_PAUSEQ|_PR_ON_SLEEPQ)) {
- _PRCPU *cpu = pq->thr->cpu;
-
- _PR_SLEEPQ_LOCK(pq->thr->cpu);
- _PR_DEL_SLEEPQ(pq->thr, PR_TRUE);
- _PR_SLEEPQ_UNLOCK(pq->thr->cpu);
-
- pri = pq->thr->priority;
- pq->thr->state = _PR_RUNNABLE;
-
- _PR_RUNQ_LOCK(cpu);
- _PR_ADD_RUNQ(pq->thr, cpu, pri);
- _PR_RUNQ_UNLOCK(cpu);
- }
- _PR_THREAD_UNLOCK(pq->thr);
- } else {
- if (pq->timeout < _PR_IOQ_TIMEOUT(me->cpu))
- _PR_IOQ_TIMEOUT(me->cpu) = pq->timeout;
- if (_PR_IOQ_MAX_OSFD(me->cpu) < pq_max_osfd)
- _PR_IOQ_MAX_OSFD(me->cpu) = pq_max_osfd;
- }
- }
- } /* end FindBadFDs() */
-
- /*
- ** Called by the scheduler when there is nothing to do. This means that
- ** all threads are blocked on some monitor somewhere.
- **
- ** Pause the current CPU. longjmp to the cpu's pause stack
- */
- PRInt32 _PR_MD_PAUSE_CPU( PRIntervalTime ticks)
- {
- PRThread *me = _MD_CURRENT_THREAD();
- struct timeval timeout, *tvp;
- fd_set r, w, e;
- fd_set *rp, *wp, *ep;
- PRInt32 max_osfd, nfd;
- PRInt32 rv;
- PRCList *q;
- PRUint32 min_timeout;
-
- PR_ASSERT(_PR_MD_GET_INTSOFF() != 0);
-
- /*
- * assigment of fd_sets
- */
- r = _PR_FD_READ_SET(me->cpu);
- w = _PR_FD_WRITE_SET(me->cpu);
- e = _PR_FD_EXCEPTION_SET(me->cpu);
-
- rp = &r;
- wp = &w;
- ep = &e;
-
- max_osfd = _PR_IOQ_MAX_OSFD(me->cpu) + 1;
- min_timeout = _PR_IOQ_TIMEOUT(me->cpu);
- /*
- ** Compute the minimum timeout value: make it the smaller of the
- ** timeouts specified by the i/o pollers or the timeout of the first
- ** sleeping thread.
- */
- q = _PR_SLEEPQ(me->cpu).next;
-
- if (q != &_PR_SLEEPQ(me->cpu)) {
- PRThread *t = _PR_THREAD_PTR(q);
-
- if (t->sleep < min_timeout) {
- min_timeout = t->sleep;
- }
- }
- if (min_timeout > ticks) {
- min_timeout = ticks;
- }
-
- if (min_timeout == PR_INTERVAL_NO_TIMEOUT) {
- tvp = NULL;
- } else {
- timeout.tv_sec = PR_IntervalToSeconds(min_timeout);
- timeout.tv_usec = PR_IntervalToMicroseconds(min_timeout)
- % PR_USEC_PER_SEC;
- tvp = &timeout;
- }
-
- _PR_MD_IOQ_UNLOCK();
- _MD_CHECK_FOR_EXIT();
- /*
- * check for i/o operations
- */
-
- nfd = _MD_SELECT(max_osfd, rp, wp, ep, tvp);
-
- _MD_CHECK_FOR_EXIT();
- _PR_MD_IOQ_LOCK();
- /*
- ** Notify monitors that are associated with the selected descriptors.
- */
- if (nfd > 0) {
- q = _PR_IOQ(me->cpu).next;
- _PR_IOQ_MAX_OSFD(me->cpu) = -1;
- _PR_IOQ_TIMEOUT(me->cpu) = PR_INTERVAL_NO_TIMEOUT;
- while (q != &_PR_IOQ(me->cpu)) {
- PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
- PRBool notify = PR_FALSE;
- _PRWin16PollDesc *pds = pq->pds;
- _PRWin16PollDesc *epds = pds + pq->npds;
- PRInt32 pq_max_osfd = -1;
-
- q = q->next;
- for (; pds < epds; pds++) {
- PRInt32 osfd = pds->osfd;
- PRInt16 in_flags = pds->in_flags;
- PRInt16 out_flags = 0;
- PR_ASSERT(osfd >= 0 || in_flags == 0);
- if ((in_flags & PR_POLL_READ) && FD_ISSET(osfd, rp)) {
- out_flags |= PR_POLL_READ;
- }
- if ((in_flags & PR_POLL_WRITE) && FD_ISSET(osfd, wp)) {
- out_flags |= PR_POLL_WRITE;
- }
- if ((in_flags & PR_POLL_EXCEPT) && FD_ISSET(osfd, ep)) {
- out_flags |= PR_POLL_EXCEPT;
- }
- pds->out_flags = out_flags;
- if (out_flags) {
- notify = PR_TRUE;
- }
- if (osfd > pq_max_osfd) {
- pq_max_osfd = osfd;
- }
- }
- if (notify == PR_TRUE) {
- PRIntn pri;
- PRThread *thred;
-
- PR_REMOVE_LINK(&pq->links);
- pq->on_ioq = PR_FALSE;
-
- /*
- * Decrement the count of descriptors for each desciptor/event
- * because this I/O request is being removed from the
- * ioq
- */
- pds = pq->pds;
- for (; pds < epds; pds++) {
- PRInt32 osfd = pds->osfd;
- PRInt16 in_flags = pds->in_flags;
- PR_ASSERT(osfd >= 0 || in_flags == 0);
- if (in_flags & PR_POLL_READ) {
- if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0)
- FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));
- }
- if (in_flags & PR_POLL_WRITE) {
- if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0)
- FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));
- }
- if (in_flags & PR_POLL_EXCEPT) {
- if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0)
- FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
- }
- }
- thred = pq->thr;
- _PR_THREAD_LOCK(thred);
- if (pq->thr->flags & (_PR_ON_PAUSEQ|_PR_ON_SLEEPQ)) {
- _PRCPU *cpu = thred->cpu;
- _PR_SLEEPQ_LOCK(pq->thr->cpu);
- _PR_DEL_SLEEPQ(pq->thr, PR_TRUE);
- _PR_SLEEPQ_UNLOCK(pq->thr->cpu);
-
- pri = pq->thr->priority;
- pq->thr->state = _PR_RUNNABLE;
-
- pq->thr->cpu = cpu;
- _PR_RUNQ_LOCK(cpu);
- _PR_ADD_RUNQ(pq->thr, cpu, pri);
- _PR_RUNQ_UNLOCK(cpu);
- if (_pr_md_idle_cpus > 1)
- _PR_MD_WAKEUP_WAITER(thred);
- }
- _PR_THREAD_UNLOCK(thred);
- } else {
- if (pq->timeout < _PR_IOQ_TIMEOUT(me->cpu))
- _PR_IOQ_TIMEOUT(me->cpu) = pq->timeout;
- if (_PR_IOQ_MAX_OSFD(me->cpu) < pq_max_osfd)
- _PR_IOQ_MAX_OSFD(me->cpu) = pq_max_osfd;
- }
- }
- } else if (nfd < 0) {
- if ( WSAGetLastError() == WSAENOTSOCK )
- {
- FindBadFDs();
- } else {
- PR_LOG(_pr_io_lm, PR_LOG_MAX, ("select() failed with errno %d",
- errno));
- }
- }
- _PR_MD_IOQ_UNLOCK();
- return(0);
-
- } /* end _PR_MD_PAUSE_CPU() */
-
-
- /*
- ** _MD_pr_poll() -- Implement MD polling
- **
- ** The function was snatched (re-used) from the unix implementation.
- **
- ** The native thread stuff was deleted.
- ** The pollqueue is instantiated on the mdthread structure
- ** to keep the stack frame from being corrupted when this
- ** thread is waiting on the poll.
- **
- */
- extern PRInt32
- _MD_PR_POLL(PRPollDesc *pds, PRIntn npds,
- PRIntervalTime timeout)
- {
- PRPollDesc *pd, *epd;
- PRInt32 n, err, pdcnt;
- PRIntn is;
- _PRWin16PollDesc *spds, *spd;
- PRThread *me = _PR_MD_CURRENT_THREAD();
- PRPollQueue *pq;
-
- pq = &me->md.thr_pq;
-
- /*
- * XXX
- * PRPollDesc has a PRFileDesc field, fd, while the IOQ
- * is a list of PRPollQueue structures, each of which contains
- * a _PRWin16PollDesc. A _PRWin16PollDesc struct contains
- * the OS file descriptor, osfd, and not a PRFileDesc.
- * So, we have allocate memory for _PRWin16PollDesc structures,
- * copy the flags information from the pds list and have pq
- * point to this list of _PRWin16PollDesc structures.
- *
- * It would be better if the memory allocation can be avoided.
- */
-
- spds = (_PRWin16PollDesc*) PR_MALLOC(npds * sizeof(_PRWin16PollDesc));
- if (!spds) {
- PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
- return -1;
- }
- spd = spds;
-
- _PR_INTSOFF(is);
- _PR_MD_IOQ_LOCK();
- _PR_THREAD_LOCK(me);
-
- if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
- _PR_THREAD_UNLOCK(me);
- _PR_MD_IOQ_UNLOCK();
- PR_DELETE(spds);
- return -1;
- }
-
- pdcnt = 0;
- for (pd = pds, epd = pd + npds; pd < epd; pd++) {
- PRInt32 osfd;
- PRInt16 in_flags = pd->in_flags;
- PRFileDesc *bottom = pd->fd;
-
- if ((NULL == bottom) || (in_flags == 0)) {
- continue;
- }
- while (bottom->lower != NULL) {
- bottom = bottom->lower;
- }
- osfd = bottom->secret->md.osfd;
-
- PR_ASSERT(osfd >= 0 || in_flags == 0);
-
- spd->osfd = osfd;
- spd->in_flags = pd->in_flags;
- spd++;
- pdcnt++;
-
- if (in_flags & PR_POLL_READ) {
- FD_SET(osfd, &_PR_FD_READ_SET(me->cpu));
- _PR_FD_READ_CNT(me->cpu)[osfd]++;
- }
- if (in_flags & PR_POLL_WRITE) {
- FD_SET(osfd, &_PR_FD_WRITE_SET(me->cpu));
- (_PR_FD_WRITE_CNT(me->cpu))[osfd]++;
- }
- if (in_flags & PR_POLL_EXCEPT) {
- FD_SET(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
- (_PR_FD_EXCEPTION_CNT(me->cpu))[osfd]++;
- }
- if (osfd > _PR_IOQ_MAX_OSFD(me->cpu))
- _PR_IOQ_MAX_OSFD(me->cpu) = osfd;
- }
- if (timeout < _PR_IOQ_TIMEOUT(me->cpu))
- _PR_IOQ_TIMEOUT(me->cpu) = timeout;
-
-
- pq->pds = spds;
- pq->npds = pdcnt;
-
- pq->thr = me;
- pq->on_ioq = PR_TRUE;
- pq->timeout = timeout;
- _PR_ADD_TO_IOQ((*pq), me->cpu);
- _PR_SLEEPQ_LOCK(me->cpu);
- _PR_ADD_SLEEPQ(me, timeout);
- me->state = _PR_IO_WAIT;
- me->io_pending = PR_TRUE;
- me->io_suspended = PR_FALSE;
- _PR_SLEEPQ_UNLOCK(me->cpu);
- _PR_THREAD_UNLOCK(me);
- _PR_MD_IOQ_UNLOCK();
-
- _PR_MD_WAIT(me, timeout);
-
- me->io_pending = PR_FALSE;
- me->io_suspended = PR_FALSE;
-
- /*
- * Copy the out_flags from the _PRWin16PollDesc structures to the
- * user's PRPollDesc structures and free the allocated memory
- */
- spd = spds;
- for (pd = pds, epd = pd + npds; pd < epd; pd++) {
- if ((NULL == pd->fd) || (pd->in_flags == 0)) {
- pd->out_flags = 0;
- continue;
- }
- pd->out_flags = spd->out_flags;
- spd++;
- }
- PR_DELETE(spds);
-
- /*
- ** If we timed out the pollq might still be on the ioq. Remove it
- ** before continuing.
- */
- if (pq->on_ioq) {
- _PR_INTSOFF(is);
- _PR_MD_IOQ_LOCK();
- /*
- * Need to check pq.on_ioq again
- */
- if (pq->on_ioq == PR_TRUE) {
- PR_REMOVE_LINK(&pq->links);
- for (pd = pds, epd = pd + npds; pd < epd; pd++) {
- PRInt32 osfd;
- PRInt16 in_flags = pd->in_flags;
- PRFileDesc *bottom = pd->fd;
-
- if ((NULL == bottom) || (in_flags == 0)) {
- continue;
- }
- while (bottom->lower != NULL) {
- bottom = bottom->lower;
- }
- osfd = bottom->secret->md.osfd;
- PR_ASSERT(osfd >= 0 || in_flags == 0);
- if (in_flags & PR_POLL_READ) {
- if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0)
- FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));
- }
- if (in_flags & PR_POLL_WRITE) {
- if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0)
- FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));
- }
- if (in_flags & PR_POLL_EXCEPT) {
- if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0)
- FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
- }
- }
- }
- _PR_MD_IOQ_UNLOCK();
- _PR_INTSON(is);
- }
- if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
- return -1;
- } else {
- n = 0;
- if (pq->on_ioq == PR_FALSE) {
- /* Count the number of ready descriptors */
- while (--npds >= 0) {
- if (pds->out_flags) {
- n++;
- }
- pds++;
- }
- }
- return n;
- }
- } /* end _MD_pr_poll() */
-