home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / nsprpub / pr / src / md / windows / w16sock.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  32.8 KB  |  1,152 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /*
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  * 
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  * 
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. #include "primpl.h"
  20.  
  21. static  int winsockNotPresent = 0;
  22.  
  23. void
  24. _PR_MD_INIT_IO()
  25. {
  26.     int rv;
  27.     
  28.     WORD WSAVersion = 0x0101;
  29.     WSADATA WSAData;
  30.  
  31.     rv = WSAStartup( WSAVersion, &WSAData );
  32.     if ( rv != 0 )
  33.     {
  34.         _PR_MD_MAP_WSASTARTUP_ERROR(WSAGetLastError());
  35.         winsockNotPresent = 1;
  36.     }
  37.     return;
  38. }
  39.  
  40. void
  41. _PR_MD_CLEANUP_BEFORE_EXIT(void)
  42. {
  43.     int rv;
  44.     int err;
  45.     
  46.     rv = WSACleanup();
  47.     if ( rv == SOCKET_ERROR )
  48.     {
  49.         err = WSAGetLastError();
  50.         PR_ASSERT(0);
  51.     }
  52.     return;
  53. } /* end _PR_MD_CLEANUP_BEFORE_EXIT() */
  54.  
  55. /* --- SOCKET IO --------------------------------------------------------- */
  56.  
  57. PRStatus 
  58. _MD_WindowsGetHostName(char *name, PRUint32 namelen)
  59. {
  60.     PRIntn  rv;
  61.     PRInt32 syserror;
  62.     
  63.     rv = gethostname(name, (PRInt32) namelen);
  64.     if (0 == rv) {
  65.         return PR_SUCCESS;
  66.     }
  67.     syserror = WSAGetLastError();
  68.     PR_ASSERT(WSANOTINITIALISED != syserror);
  69.     _PR_MD_MAP_GETHOSTNAME_ERROR(syserror);
  70.     return PR_FAILURE;
  71. }
  72.  
  73.  
  74. PRInt32
  75. _PR_MD_SOCKET(int af, int type, int flags)
  76. {
  77.     SOCKET      sock;
  78.     PRUint32    one = 1;
  79.     PRInt32     rv;
  80.     PRInt32     err;
  81.  
  82.     if ( winsockNotPresent )
  83.         return( (PRInt32)INVALID_SOCKET );
  84.  
  85.     sock = socket(af, type, flags);
  86.  
  87.     if (sock == INVALID_SOCKET ) 
  88.     {
  89.         int rv = GetLastError();
  90.         closesocket(sock);
  91.         _PR_MD_MAP_SOCKET_ERROR(rv);
  92.         return (PRInt32)INVALID_SOCKET;
  93.     }
  94.  
  95.     /*
  96.     ** Make the socket Non-Blocking
  97.     */
  98.     rv = ioctlsocket( sock, FIONBIO, &one);
  99.     if ( rv != 0 )
  100.     {
  101.         err = WSAGetLastError();
  102.         return -1;
  103.     }
  104.  
  105.     return (PRInt32)sock;
  106. }
  107.  
  108.  
  109. PRInt32
  110. _PR_MD_SOCKETAVAILABLE(PRFileDesc *fd)
  111. {
  112.     PRUint32 result;
  113.  
  114.     if (ioctlsocket(fd->secret->md.osfd, FIONREAD, &result) < 0) {
  115.         PR_SetError(PR_BAD_DESCRIPTOR_ERROR, WSAGetLastError());
  116.         return -1;
  117.     }
  118.     return result;
  119. }
  120.  
  121.  
  122. /*
  123. ** _MD_CloseSocket() -- Close a socket
  124. **
  125. */
  126. PRInt32
  127. _PR_MD_CLOSE_SOCKET(PRInt32 osfd)
  128. {
  129.     PRInt32 rv;
  130.  
  131.     rv = closesocket((SOCKET) osfd );
  132.     if (rv < 0)
  133.         _PR_MD_MAP_CLOSE_ERROR(WSAGetLastError());
  134.  
  135.     return rv;
  136. }
  137.  
  138. PRInt32 _PR_MD_LISTEN(PRFileDesc *fd, PRIntn backlog)
  139. {
  140.     int rv, err;
  141.  
  142.     rv = listen(fd->secret->md.osfd, backlog);
  143.     if ( rv == SOCKET_ERROR ) {
  144.         _PR_MD_MAP_LISTEN_ERROR(WSAGetLastError());
  145.         return(-1);
  146.     }
  147.     return(rv);
  148. }
  149.  
  150. PRInt32
  151. _PR_MD_ACCEPT(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen,
  152.        PRIntervalTime timeout )
  153. {
  154.     PRInt32 osfd = fd->secret->md.osfd;
  155.     PRThread    *me = _PR_MD_CURRENT_THREAD();
  156.     PRInt32     err;
  157.     PRIntn      rv;
  158.  
  159.     MD_ASSERTINT( *addrlen );    
  160.  
  161.     while ((rv = (SOCKET)accept(osfd, (struct sockaddr *) addr,
  162.                                         (int *)addrlen)) == INVALID_SOCKET ) {
  163.         err = WSAGetLastError();
  164.         if ( err == WSAEWOULDBLOCK ) {
  165.             if (fd->secret->nonblocking) {
  166.                 break;
  167.             }
  168.             if (_PR_WaitForFD(osfd, PR_POLL_READ, timeout) == 0) {
  169.                 if ( _PR_PENDING_INTERRUPT(me))
  170.                 {
  171.                     me->flags &= ~_PR_INTERRUPT;
  172.                     PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
  173.                 } else
  174.                 {
  175.                     PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  176.                 }
  177.                 rv = -1;
  178.                 goto done;
  179.             } else if (_PR_PENDING_INTERRUPT(me)) {
  180.                 me->flags &= ~_PR_INTERRUPT;
  181.                 PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
  182.                 rv = -1;
  183.                 goto done;
  184.             }
  185.         } else if ((err == WSAEINTR) && (!_PR_PENDING_INTERRUPT(me))){
  186.             continue;
  187.         } else {
  188.             break;
  189.         }
  190.     }
  191.     if (rv < 0) {
  192.         _PR_MD_MAP_ACCEPT_ERROR(err);
  193.     }
  194. done:
  195.     if ( rv == INVALID_SOCKET )
  196.         return(-1 );
  197.     else
  198.         return(rv);
  199. } /* end _MD_Accept() */
  200.  
  201.  
  202. PRInt32
  203. _PR_MD_CONNECT(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen, 
  204.                PRIntervalTime timeout)
  205. {
  206.     PRInt32 osfd = fd->secret->md.osfd;
  207.     PRThread *me = _PR_MD_CURRENT_THREAD();
  208.     PRInt32 rv, err;
  209.  
  210.     while ((rv = connect(osfd, (struct sockaddr *)addr, addrlen)) == -1) {
  211.         err = WSAGetLastError();
  212.         if (err == WSAEISCONN) {
  213.             rv = 0;
  214.             break;
  215.         }
  216.         /* for winsock1.1, it reports EALREADY as EINVAL */
  217.         if ((err == WSAEWOULDBLOCK)
  218.             ||(err == WSAEALREADY) 
  219.             || (err = WSAEINVAL)) {
  220.             if (fd->secret->nonblocking) {
  221.                 break;
  222.             }
  223.             if (_PR_WaitForFD(osfd, PR_POLL_WRITE, timeout) == 0) {
  224.                 if ( _PR_PENDING_INTERRUPT(me))
  225.                 {
  226.                     me->flags &= ~_PR_INTERRUPT;
  227.                     PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
  228.                 } else
  229.                 {
  230.                     PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  231.                 }
  232.                 rv = -1;
  233.                 goto done;
  234.             } else if (_PR_PENDING_INTERRUPT(me)) {
  235.                 me->flags &= ~_PR_INTERRUPT;
  236.                 PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
  237.                 rv = -1;
  238.                 goto done;
  239.             }
  240.         } else if ((err == WSAEINTR) && (!_PR_PENDING_INTERRUPT(me))){
  241.             continue;
  242.         } else {
  243.             break;
  244.         }
  245.     }
  246.  
  247.     if (rv < 0) {
  248.         _PR_MD_MAP_CONNECT_ERROR(err);
  249.     }
  250. done:
  251.     return rv;
  252. }
  253.  
  254. PRInt32
  255. _PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen)
  256. {
  257.     PRInt32 rv;
  258.     int one = 1;
  259.  
  260.     rv = bind(fd->secret->md.osfd, (const struct sockaddr *)&(addr->inet), addrlen);
  261.  
  262.     if (rv == SOCKET_ERROR)  {
  263.         _PR_MD_MAP_BIND_ERROR(WSAGetLastError());
  264.         return -1;
  265.     }
  266.  
  267.     return 0;
  268. }
  269.  
  270.  
  271. PRInt32
  272. _PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, 
  273.             PRIntervalTime timeout)
  274. {
  275.     PRInt32 osfd = fd->secret->md.osfd;
  276.     PRThread *me = _PR_MD_CURRENT_THREAD();
  277.     PRInt32 rv, err;
  278.  
  279.     while ((rv = recv(osfd,buf,amount,flags)) == -1) {
  280.         err = WSAGetLastError();
  281.         if ( err == WSAEWOULDBLOCK ) {
  282.             if (fd->secret->nonblocking) {
  283.                 break;
  284.             }
  285.             if (_PR_WaitForFD(osfd, PR_POLL_READ, timeout) == 0) {
  286.                 if ( _PR_PENDING_INTERRUPT(me))
  287.                 {
  288.                     me->flags &= ~_PR_INTERRUPT;
  289.                     PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
  290.                 } else
  291.                 {
  292.                     PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  293.                 }
  294.                 rv = -1;
  295.                 goto done;
  296.             } else if (_PR_PENDING_INTERRUPT(me)) {
  297.                 me->flags &= ~_PR_INTERRUPT;
  298.                 PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
  299.                 rv = -1;
  300.                 goto done;
  301.             }
  302.         } else if ((err == WSAEINTR) && (!_PR_PENDING_INTERRUPT(me))){
  303.             continue;
  304.         } else {
  305.             break;
  306.         }
  307.     }
  308.     if (rv < 0) {
  309.         _PR_MD_MAP_RECV_ERROR(err);
  310.     }
  311. done:
  312.     return(rv);
  313. }
  314.  
  315. PRInt32
  316. _PR_MD_SEND(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
  317.             PRIntervalTime timeout)
  318. {
  319.     PRInt32 osfd = fd->secret->md.osfd;
  320.     PRThread *me = _PR_MD_CURRENT_THREAD();
  321.     PRInt32 rv, err;
  322.  
  323.     while ((rv = send(osfd,buf,amount,flags)) == -1) {
  324.         err = WSAGetLastError();
  325.         if ( err == WSAEWOULDBLOCK ) {
  326.             if (fd->secret->nonblocking) {
  327.                 break;
  328.             }
  329.             if (_PR_WaitForFD(osfd, PR_POLL_WRITE, timeout) == 0) {
  330.                 if ( _PR_PENDING_INTERRUPT(me))
  331.                 {
  332.                     me->flags &= ~_PR_INTERRUPT;
  333.                     PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
  334.                 } else
  335.                 {
  336.                     PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  337.                 }
  338.                 rv = -1;
  339.                 goto done;
  340.             } else if (_PR_PENDING_INTERRUPT(me)) {
  341.                 me->flags &= ~_PR_INTERRUPT;
  342.                 PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
  343.                 rv = -1;
  344.                 goto done;
  345.             }
  346.         } else if ((err == WSAEINTR) && (!_PR_PENDING_INTERRUPT(me))){
  347.             continue;
  348.         } else {
  349.             break;
  350.         }
  351.     }
  352.     if (rv < 0) {
  353.         _PR_MD_MAP_SEND_ERROR(err);
  354.     }
  355. done:
  356.     return rv;
  357. }
  358.  
  359. PRInt32
  360. _PR_MD_SENDTO(PRFileDesc*fd, const void *buf, PRInt32 amount, PRIntn flags,
  361.               const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
  362. {
  363.     PRInt32 osfd = fd->secret->md.osfd;
  364.     PRThread *me = _PR_MD_CURRENT_THREAD();
  365.     PRInt32 rv, err;
  366.  
  367.     while ((rv = sendto(osfd, buf, amount, flags,
  368.             (struct sockaddr *) addr, addrlen)) == -1) {
  369.         err = WSAGetLastError();
  370.         if ( err == WSAEWOULDBLOCK ) {
  371.             if (fd->secret->nonblocking) {
  372.                 break;
  373.             }
  374.             if (_PR_WaitForFD(osfd, PR_POLL_WRITE, timeout) == 0) {
  375.                 if ( _PR_PENDING_INTERRUPT(me))
  376.                 {
  377.                     me->flags &= ~_PR_INTERRUPT;
  378.                     PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
  379.                 } else
  380.                 {
  381.                     PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  382.                 }
  383.                 rv = -1;
  384.                 goto done;
  385.             } else if (_PR_PENDING_INTERRUPT(me)) {
  386.                 me->flags &= ~_PR_INTERRUPT;
  387.                 PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
  388.                 rv = -1;
  389.                 goto done;
  390.             }
  391.         } else if ((err == WSAEINTR) && (!_PR_PENDING_INTERRUPT(me))){
  392.             continue;
  393.         } else {
  394.             break;
  395.         }
  396.     }
  397.     if (rv < 0) {
  398.         _PR_MD_MAP_SENDTO_ERROR(err);
  399.     }
  400. done:
  401.     return rv;
  402. }
  403.  
  404. PRInt32
  405. _PR_MD_RECVFROM(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
  406.                 PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout)
  407. {
  408.     PRInt32 osfd = fd->secret->md.osfd;
  409.     PRThread *me = _PR_MD_CURRENT_THREAD();
  410.     PRInt32 rv, err;
  411.  
  412.     while ((*addrlen = PR_NETADDR_SIZE(addr)),
  413.                 ((rv = recvfrom(osfd, buf, amount, flags,
  414.                 (struct sockaddr FAR *) addr,(int FAR *)addrlen)) == -1)) {
  415.         err = WSAGetLastError();
  416.         if ( err == WSAEWOULDBLOCK ) {
  417.             if (fd->secret->nonblocking) {
  418.                 break;
  419.             }
  420.             if (_PR_WaitForFD(osfd, PR_POLL_READ, timeout) == 0) {
  421.                 if ( _PR_PENDING_INTERRUPT(me))
  422.                 {
  423.                     me->flags &= ~_PR_INTERRUPT;
  424.                     PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
  425.                 } else
  426.                 {
  427.                     PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  428.                 }
  429.                 rv = -1;
  430.                 goto done;
  431.             } else if (_PR_PENDING_INTERRUPT(me)) {
  432.                 me->flags &= ~_PR_INTERRUPT;
  433.                 PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
  434.                 rv = -1;
  435.                 goto done;
  436.             }
  437.         } else if ((err == WSAEINTR) && (!_PR_PENDING_INTERRUPT(me))){
  438.             continue;
  439.         } else {
  440.             break;
  441.         }
  442.     }
  443.     if (rv < 0) {
  444.         _PR_MD_MAP_RECVFROM_ERROR(err);
  445.     }
  446. done:
  447.     return(rv);
  448. }
  449.  
  450. PRInt32
  451. _PR_MD_WRITEV(PRFileDesc *fd, PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout)
  452. {
  453.     int index;
  454.     int sent = 0;
  455.     int rv;
  456.  
  457.     for (index=0; index < iov_size; index++) 
  458.     {
  459.  
  460. /*
  461.  * XXX To be fixed
  462.  * should call PR_Send
  463.  */
  464.  
  465.         rv = _PR_MD_SEND(fd, iov[index].iov_base, iov[index].iov_len, 0, timeout);
  466.         if (rv > 0) 
  467.             sent += rv;
  468.         if ( rv != iov[index].iov_len ) 
  469.         {
  470.             if (sent <= 0)
  471.                 return -1;
  472.             return -1;
  473.         }
  474.     }
  475.     return sent;
  476. }
  477.  
  478. PRInt32
  479. _PR_MD_SHUTDOWN(PRFileDesc *fd, PRIntn how)
  480. {
  481. PRInt32 rv;
  482.  
  483.     rv = shutdown(fd->secret->md.osfd, how);
  484.     if (rv < 0)
  485.         _PR_MD_MAP_SHUTDOWN_ERROR(WSAGetLastError());
  486.     return rv;
  487. }
  488.  
  489. PRStatus
  490. _PR_MD_GETSOCKNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *len)
  491. {
  492.     PRInt32 rv;
  493.  
  494.     rv = getsockname((SOCKET)fd->secret->md.osfd, (struct sockaddr *)addr, (int *)len);
  495.     if (rv==0)
  496.         return PR_SUCCESS;
  497.     else {
  498.         _PR_MD_MAP_GETSOCKNAME_ERROR(WSAGetLastError());
  499.         return PR_FAILURE;
  500.     }
  501. }
  502.  
  503. PRStatus
  504. _PR_MD_GETPEERNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *len)
  505. {
  506.     PRInt32 rv;
  507.  
  508.     rv = getpeername((SOCKET)fd->secret->md.osfd, (struct sockaddr *)addr, (int*)len);
  509.     if (rv==0)
  510.         return PR_SUCCESS;
  511.     else {
  512.         _PR_MD_MAP_GETPEERNAME_ERROR(WSAGetLastError());
  513.         return PR_FAILURE;
  514.     }
  515. }
  516.  
  517. PRStatus
  518. _PR_MD_GETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval, PRInt32* optlen)
  519. {
  520.     PRInt32 rv;
  521.  
  522.     rv = getsockopt((SOCKET)fd->secret->md.osfd, level, optname, optval, (int*)optlen);
  523.     if (rv==0)
  524.         return PR_SUCCESS;
  525.     else {
  526.         _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError());
  527.         return PR_FAILURE;
  528.     }
  529. }
  530.  
  531. PRStatus
  532. _PR_MD_SETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, const char* optval, PRInt32 optlen)
  533. {
  534.     PRInt32 rv;
  535.  
  536.     rv = setsockopt((SOCKET)fd->secret->md.osfd, level, optname, optval, optlen);
  537.     if (rv==0)
  538.         return PR_SUCCESS;
  539.     else {
  540.         _PR_MD_MAP_SETSOCKOPT_ERROR(WSAGetLastError());
  541.         return PR_FAILURE;
  542.     }
  543. }
  544.  
  545. void
  546. _PR_MD_MAKE_NONBLOCK(PRFileDesc *f)
  547. {
  548.     return; // do nothing!
  549. }
  550.  
  551. /*
  552. ** Wait for I/O on a single descriptor.
  553.  *
  554.  * return 0, if timed-out, else return 1
  555. */
  556. PRInt32
  557. _PR_WaitForFD(PRInt32 osfd, PRUintn how, PRIntervalTime timeout)
  558. {
  559.     _PRWin16PollDesc *pd;
  560.     PRPollQueue      *pq;
  561.     PRIntn is;
  562.     PRInt32 rv = 1;
  563.     PRThread *me = _PR_MD_CURRENT_THREAD();
  564.  
  565.     PR_ASSERT(!(me->flags & _PR_IDLE_THREAD));
  566.  
  567.     pd = &me->md.thr_pd;
  568.     pq = &me->md.thr_pq;
  569.     if (timeout == PR_INTERVAL_NO_WAIT) return 0;
  570.  
  571.     pd->osfd = osfd;
  572.     pd->in_flags = how;
  573.     pd->out_flags = 0;
  574.  
  575.     pq->pds = pd;
  576.     pq->npds = 1;
  577.  
  578.     _PR_INTSOFF(is);
  579.     _PR_MD_IOQ_LOCK();
  580.     _PR_THREAD_LOCK(me);
  581.  
  582.     if (_PR_PENDING_INTERRUPT(me)) {
  583.         _PR_THREAD_UNLOCK(me);
  584.         _PR_MD_IOQ_UNLOCK();
  585.         return 0;
  586.     }
  587.  
  588.     pq->thr = me;
  589.     pq->on_ioq = PR_TRUE;
  590.     pq->timeout = timeout;
  591.     _PR_ADD_TO_IOQ((*pq), me->cpu);
  592.     if (how == PR_POLL_READ) {
  593.         FD_SET(osfd, &_PR_FD_READ_SET(me->cpu));
  594.         (_PR_FD_READ_CNT(me->cpu))[osfd]++;
  595.     } else if (how == PR_POLL_WRITE) {
  596.         FD_SET(osfd, &_PR_FD_WRITE_SET(me->cpu));
  597.         (_PR_FD_WRITE_CNT(me->cpu))[osfd]++;
  598.     } else {
  599.         FD_SET(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
  600.         (_PR_FD_EXCEPTION_CNT(me->cpu))[osfd]++;
  601.     }
  602.     if (_PR_IOQ_MAX_OSFD(me->cpu) < osfd)
  603.         _PR_IOQ_MAX_OSFD(me->cpu) = osfd;
  604.     if (_PR_IOQ_TIMEOUT(me->cpu) > timeout)
  605.         _PR_IOQ_TIMEOUT(me->cpu) = timeout;
  606.         
  607.     _PR_THREAD_LOCK(me);
  608.  
  609.     _PR_SLEEPQ_LOCK(me->cpu);
  610.     _PR_ADD_SLEEPQ(me, timeout);
  611.     me->state = _PR_IO_WAIT;
  612.     me->io_pending = PR_TRUE;
  613.     me->io_suspended = PR_FALSE;
  614.     _PR_SLEEPQ_UNLOCK(me->cpu);
  615.     _PR_THREAD_UNLOCK(me);
  616.     _PR_MD_IOQ_UNLOCK();
  617.  
  618.     _PR_MD_WAIT(me, timeout);
  619.     me->io_pending = PR_FALSE;
  620.     me->io_suspended = PR_FALSE;
  621.  
  622.     /*
  623.     ** If we timed out the pollq might still be on the ioq. Remove it
  624.     ** before continuing.
  625.     */
  626.     if (pq->on_ioq) {
  627.         _PR_INTSOFF(is);
  628.         _PR_MD_IOQ_LOCK();
  629.     /*
  630.      * Need to check pq.on_ioq again
  631.      */
  632.         if (pq->on_ioq) {
  633.             PR_REMOVE_LINK(&pq->links);
  634.             if (how == PR_POLL_READ) {
  635.                 if ((--(_PR_FD_READ_CNT(me->cpu))[osfd]) == 0)
  636.                     FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));
  637.             
  638.             } else if (how == PR_POLL_WRITE) {
  639.                 if ((--(_PR_FD_WRITE_CNT(me->cpu))[osfd]) == 0)
  640.                     FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));
  641.             } else {
  642.                 if ((--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd]) == 0)
  643.                     FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
  644.             }
  645.         }
  646.         _PR_MD_IOQ_UNLOCK();
  647.         rv = 0;
  648.     }
  649.     _PR_FAST_INTSON(is);
  650.    return(rv);
  651. }
  652.  
  653. /*
  654.  * Unblock threads waiting for I/O
  655.  *    used when interrupting threads
  656.  *
  657.  * NOTE: The thread lock should held when this function is called.
  658.  * On return, the thread lock is released.
  659.  */
  660. void _PR_Unblock_IO_Wait(PRThread *thr)
  661. {
  662.     int pri = thr->priority;
  663.     _PRCPU *cpu = thr->cpu;
  664.  
  665.     PR_ASSERT(thr->flags & (_PR_ON_SLEEPQ | _PR_ON_PAUSEQ));
  666.     _PR_SLEEPQ_LOCK(cpu);
  667.     _PR_DEL_SLEEPQ(thr, PR_TRUE);
  668.     _PR_SLEEPQ_UNLOCK(cpu);
  669.  
  670.     PR_ASSERT(!(thr->flags & _PR_IDLE_THREAD));
  671.     thr->state = _PR_RUNNABLE;
  672.     _PR_RUNQ_LOCK(cpu);
  673.     _PR_ADD_RUNQ(thr, cpu, pri);
  674.     _PR_RUNQ_UNLOCK(cpu);
  675.     _PR_THREAD_UNLOCK(thr);
  676.     _PR_MD_WAKEUP_WAITER(thr);
  677. }
  678.  
  679. /*
  680. ** Scan through io queue and find any bad fd's that triggered the error
  681. ** from _MD_SELECT
  682. */
  683. static void FindBadFDs(void)
  684. {
  685.     PRCList *q;
  686.     PRThread *me = _MD_CURRENT_THREAD();
  687.     int sockOpt;
  688.     int sockOptLen = sizeof(sockOpt);
  689.  
  690.     PR_ASSERT(!_PR_IS_NATIVE_THREAD(me));
  691.     q = (_PR_IOQ(me->cpu)).next;
  692.     _PR_IOQ_MAX_OSFD(me->cpu) = -1;
  693.     _PR_IOQ_TIMEOUT(me->cpu) = PR_INTERVAL_NO_TIMEOUT;
  694.     while (q != &_PR_IOQ(me->cpu)) {
  695.         PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
  696.         PRBool notify = PR_FALSE;
  697.         _PRWin16PollDesc *pds = pq->pds;
  698.         _PRWin16PollDesc *epds = pds + pq->npds;
  699.         PRInt32 pq_max_osfd = -1;
  700.  
  701.         q = q->next;
  702.         for (; pds < epds; pds++) {
  703.             PRInt32 osfd = pds->osfd;
  704.             pds->out_flags = 0;
  705.             PR_ASSERT(osfd >= 0 || pds->in_flags == 0);
  706.             if (pds->in_flags == 0) {
  707.                 continue;  /* skip this fd */
  708.             }
  709.             if ( getsockopt(osfd, 
  710.                     (int)SOL_SOCKET, 
  711.                     SO_TYPE, 
  712.                     (char*)&sockOpt, 
  713.                     &sockOptLen) == SOCKET_ERROR ) 
  714.             {
  715.                 if ( WSAGetLastError() == WSAENOTSOCK )
  716.                 {
  717.                     PR_LOG(_pr_io_lm, PR_LOG_MAX,
  718.                         ("file descriptor %d is bad", osfd));
  719.                     pds->out_flags = PR_POLL_NVAL;
  720.                     notify = PR_TRUE;
  721.                 }
  722.             }
  723.             if (osfd > pq_max_osfd) {
  724.                 pq_max_osfd = osfd;
  725.             }
  726.         }
  727.  
  728.         if (notify) {
  729.             PRIntn pri;
  730.             PR_REMOVE_LINK(&pq->links);
  731.             pq->on_ioq = PR_FALSE;
  732.  
  733.             /*
  734.          * Decrement the count of descriptors for each desciptor/event
  735.          * because this I/O request is being removed from the
  736.          * ioq
  737.          */
  738.             pds = pq->pds;
  739.             for (; pds < epds; pds++) {
  740.                 PRInt32 osfd = pds->osfd;
  741.                 PRInt16 in_flags = pds->in_flags;
  742.                 PR_ASSERT(osfd >= 0 || in_flags == 0);
  743.                 if (in_flags & PR_POLL_READ) {
  744.                     if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0)
  745.                         FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));
  746.                 }
  747.                 if (in_flags & PR_POLL_WRITE) {
  748.                     if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0)
  749.                         FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));
  750.                 }
  751.                 if (in_flags & PR_POLL_EXCEPT) {
  752.                     if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0)
  753.                         FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
  754.                 }
  755.             }
  756.  
  757.             _PR_THREAD_LOCK(pq->thr);
  758.             if (pq->thr->flags & (_PR_ON_PAUSEQ|_PR_ON_SLEEPQ)) {
  759.                 _PRCPU *cpu = pq->thr->cpu;
  760.                 
  761.                 _PR_SLEEPQ_LOCK(pq->thr->cpu);
  762.                 _PR_DEL_SLEEPQ(pq->thr, PR_TRUE);
  763.                 _PR_SLEEPQ_UNLOCK(pq->thr->cpu);
  764.  
  765.                 pri = pq->thr->priority;
  766.                 pq->thr->state = _PR_RUNNABLE;
  767.  
  768.                 _PR_RUNQ_LOCK(cpu);
  769.                 _PR_ADD_RUNQ(pq->thr, cpu, pri);
  770.                 _PR_RUNQ_UNLOCK(cpu);
  771.             }
  772.             _PR_THREAD_UNLOCK(pq->thr);
  773.         } else {
  774.             if (pq->timeout < _PR_IOQ_TIMEOUT(me->cpu))
  775.                 _PR_IOQ_TIMEOUT(me->cpu) = pq->timeout;
  776.             if (_PR_IOQ_MAX_OSFD(me->cpu) < pq_max_osfd)
  777.                 _PR_IOQ_MAX_OSFD(me->cpu) = pq_max_osfd;
  778.         }
  779.     }
  780. } /* end FindBadFDs() */
  781.  
  782. /*
  783. ** Called by the scheduler when there is nothing to do. This means that
  784. ** all threads are blocked on some monitor somewhere.
  785. **
  786. ** Pause the current CPU. longjmp to the cpu's pause stack
  787. */
  788. PRInt32 _PR_MD_PAUSE_CPU( PRIntervalTime ticks)
  789. {
  790.     PRThread *me = _MD_CURRENT_THREAD();
  791.     struct timeval timeout, *tvp;
  792.     fd_set r, w, e;
  793.     fd_set *rp, *wp, *ep;
  794.     PRInt32 max_osfd, nfd;
  795.     PRInt32 rv;
  796.     PRCList *q;
  797.     PRUint32 min_timeout;
  798.  
  799.     PR_ASSERT(_PR_MD_GET_INTSOFF() != 0);
  800.  
  801.     /*
  802.      * assigment of fd_sets
  803.      */
  804.     r = _PR_FD_READ_SET(me->cpu);
  805.     w = _PR_FD_WRITE_SET(me->cpu);
  806.     e = _PR_FD_EXCEPTION_SET(me->cpu);
  807.  
  808.     rp = &r;
  809.     wp = &w;
  810.     ep = &e;
  811.  
  812.     max_osfd = _PR_IOQ_MAX_OSFD(me->cpu) + 1;
  813.     min_timeout = _PR_IOQ_TIMEOUT(me->cpu);
  814.     /*
  815.     ** Compute the minimum timeout value: make it the smaller of the
  816.     ** timeouts specified by the i/o pollers or the timeout of the first
  817.     ** sleeping thread.
  818.     */
  819.     q = _PR_SLEEPQ(me->cpu).next;
  820.  
  821.     if (q != &_PR_SLEEPQ(me->cpu)) {
  822.         PRThread *t = _PR_THREAD_PTR(q);
  823.  
  824.         if (t->sleep < min_timeout) {
  825.             min_timeout = t->sleep;
  826.         }
  827.     }
  828.     if (min_timeout > ticks) {
  829.         min_timeout = ticks;
  830.     }
  831.  
  832.     if (min_timeout == PR_INTERVAL_NO_TIMEOUT) {
  833.         tvp = NULL;
  834.     } else {
  835.         timeout.tv_sec = PR_IntervalToSeconds(min_timeout);
  836.         timeout.tv_usec = PR_IntervalToMicroseconds(min_timeout)
  837.             % PR_USEC_PER_SEC;
  838.         tvp = &timeout;
  839.     }
  840.  
  841.     _PR_MD_IOQ_UNLOCK();
  842.     _MD_CHECK_FOR_EXIT();
  843.     /*
  844.      * check for i/o operations
  845.      */
  846.  
  847.     nfd = _MD_SELECT(max_osfd, rp, wp, ep, tvp);
  848.  
  849.     _MD_CHECK_FOR_EXIT();
  850.     _PR_MD_IOQ_LOCK();
  851.     /*
  852.     ** Notify monitors that are associated with the selected descriptors.
  853.     */
  854.     if (nfd > 0) {
  855.         q = _PR_IOQ(me->cpu).next;
  856.         _PR_IOQ_MAX_OSFD(me->cpu) = -1;
  857.         _PR_IOQ_TIMEOUT(me->cpu) = PR_INTERVAL_NO_TIMEOUT;
  858.         while (q != &_PR_IOQ(me->cpu)) {
  859.             PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
  860.             PRBool notify = PR_FALSE;
  861.             _PRWin16PollDesc *pds = pq->pds;
  862.             _PRWin16PollDesc *epds = pds + pq->npds;
  863.             PRInt32 pq_max_osfd = -1;
  864.  
  865.             q = q->next;
  866.             for (; pds < epds; pds++) {
  867.                 PRInt32 osfd = pds->osfd;
  868.                 PRInt16 in_flags = pds->in_flags;
  869.                 PRInt16 out_flags = 0;
  870.                 PR_ASSERT(osfd >= 0 || in_flags == 0);
  871.                 if ((in_flags & PR_POLL_READ) && FD_ISSET(osfd, rp)) {
  872.                     out_flags |= PR_POLL_READ;
  873.                 }
  874.                 if ((in_flags & PR_POLL_WRITE) && FD_ISSET(osfd, wp)) {
  875.                     out_flags |= PR_POLL_WRITE;
  876.                 }
  877.                 if ((in_flags & PR_POLL_EXCEPT) && FD_ISSET(osfd, ep)) {
  878.                     out_flags |= PR_POLL_EXCEPT;
  879.                 }
  880.                 pds->out_flags = out_flags;
  881.                 if (out_flags) {
  882.                     notify = PR_TRUE;
  883.                 }
  884.                 if (osfd > pq_max_osfd) {
  885.                     pq_max_osfd = osfd;
  886.                 }
  887.             }
  888.             if (notify == PR_TRUE) {
  889.                 PRIntn pri;
  890.                 PRThread *thred;
  891.  
  892.                 PR_REMOVE_LINK(&pq->links);
  893.                 pq->on_ioq = PR_FALSE;
  894.  
  895.                 /*
  896.                  * Decrement the count of descriptors for each desciptor/event
  897.                  * because this I/O request is being removed from the
  898.                  * ioq
  899.                  */
  900.                 pds = pq->pds;
  901.                 for (; pds < epds; pds++) {
  902.                     PRInt32 osfd = pds->osfd;
  903.                     PRInt16 in_flags = pds->in_flags;
  904.                     PR_ASSERT(osfd >= 0 || in_flags == 0);
  905.                     if (in_flags & PR_POLL_READ) {
  906.                         if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0)
  907.                             FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));
  908.                     }
  909.                     if (in_flags & PR_POLL_WRITE) {
  910.                         if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0)
  911.                             FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));
  912.                     }
  913.                     if (in_flags & PR_POLL_EXCEPT) {
  914.                         if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0)
  915.                             FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
  916.                     }
  917.                 }
  918.                  thred = pq->thr;
  919.                 _PR_THREAD_LOCK(thred);
  920.                 if (pq->thr->flags & (_PR_ON_PAUSEQ|_PR_ON_SLEEPQ)) {
  921.                     _PRCPU *cpu = thred->cpu;
  922.                     _PR_SLEEPQ_LOCK(pq->thr->cpu);
  923.                     _PR_DEL_SLEEPQ(pq->thr, PR_TRUE);
  924.                     _PR_SLEEPQ_UNLOCK(pq->thr->cpu);
  925.  
  926.                     pri = pq->thr->priority;
  927.                     pq->thr->state = _PR_RUNNABLE;
  928.  
  929.                     pq->thr->cpu = cpu;
  930.                     _PR_RUNQ_LOCK(cpu);
  931.                     _PR_ADD_RUNQ(pq->thr, cpu, pri);
  932.                     _PR_RUNQ_UNLOCK(cpu);
  933.                     if (_pr_md_idle_cpus > 1)
  934.                         _PR_MD_WAKEUP_WAITER(thred);
  935.                 }
  936.                 _PR_THREAD_UNLOCK(thred);
  937.             } else {
  938.                 if (pq->timeout < _PR_IOQ_TIMEOUT(me->cpu))
  939.                     _PR_IOQ_TIMEOUT(me->cpu) = pq->timeout;
  940.                 if (_PR_IOQ_MAX_OSFD(me->cpu) < pq_max_osfd)
  941.                     _PR_IOQ_MAX_OSFD(me->cpu) = pq_max_osfd;
  942.             }
  943.         }
  944.     } else if (nfd < 0) {
  945.         if ( WSAGetLastError() == WSAENOTSOCK )
  946.         {
  947.             FindBadFDs();
  948.         } else {
  949.             PR_LOG(_pr_io_lm, PR_LOG_MAX, ("select() failed with errno %d",
  950.                 errno));
  951.         }
  952.     }
  953.     _PR_MD_IOQ_UNLOCK();
  954.     return(0);
  955.     
  956. } /* end _PR_MD_PAUSE_CPU() */
  957.  
  958.  
  959. /*
  960. ** _MD_pr_poll() -- Implement MD polling
  961. **
  962. ** The function was snatched (re-used) from the unix implementation.
  963. ** 
  964. ** The native thread stuff was deleted.
  965. ** The pollqueue is instantiated on the mdthread structure
  966. ** to keep the stack frame from being corrupted when this
  967. ** thread is waiting on the poll.
  968. **
  969. */
  970. extern PRInt32 
  971. _MD_PR_POLL(PRPollDesc *pds, PRIntn npds,
  972.                         PRIntervalTime timeout)
  973. {
  974.     PRPollDesc *pd, *epd;
  975.     PRInt32 n, err, pdcnt;
  976.     PRIntn is;
  977.     _PRWin16PollDesc *spds, *spd;
  978.     PRThread *me = _PR_MD_CURRENT_THREAD();
  979.     PRPollQueue *pq;
  980.  
  981.     pq = &me->md.thr_pq;
  982.     
  983.     /*
  984.      * XXX
  985.      *   PRPollDesc has a PRFileDesc field, fd, while the IOQ
  986.      *   is a list of PRPollQueue structures, each of which contains
  987.      *   a _PRWin16PollDesc. A _PRWin16PollDesc struct contains
  988.      *   the OS file descriptor, osfd, and not a PRFileDesc.
  989.      *   So, we have allocate memory for _PRWin16PollDesc structures,
  990.      *   copy the flags information from the pds list and have pq
  991.      *   point to this list of _PRWin16PollDesc structures.
  992.      *
  993.      *   It would be better if the memory allocation can be avoided.
  994.      */
  995.  
  996.     spds = (_PRWin16PollDesc*) PR_MALLOC(npds * sizeof(_PRWin16PollDesc));
  997.     if (!spds) {
  998.         PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
  999.            return -1;
  1000.     }
  1001.     spd = spds;
  1002.  
  1003.     _PR_INTSOFF(is);
  1004.     _PR_MD_IOQ_LOCK();
  1005.        _PR_THREAD_LOCK(me);
  1006.  
  1007.     if (_PR_PENDING_INTERRUPT(me)) {
  1008.         me->flags &= ~_PR_INTERRUPT;
  1009.         PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
  1010.         _PR_THREAD_UNLOCK(me);
  1011.         _PR_MD_IOQ_UNLOCK();
  1012.         PR_DELETE(spds);
  1013.            return -1;
  1014.     }
  1015.  
  1016.     pdcnt = 0;
  1017.     for (pd = pds, epd = pd + npds; pd < epd; pd++) {
  1018.         PRInt32 osfd;
  1019.         PRInt16 in_flags = pd->in_flags;
  1020.         PRFileDesc *bottom = pd->fd;
  1021.  
  1022.         if ((NULL == bottom) || (in_flags == 0)) {
  1023.             continue;
  1024.         }
  1025.         while (bottom->lower != NULL) {
  1026.             bottom = bottom->lower;
  1027.         }
  1028.         osfd = bottom->secret->md.osfd;
  1029.  
  1030.         PR_ASSERT(osfd >= 0 || in_flags == 0);
  1031.  
  1032.         spd->osfd = osfd;
  1033.         spd->in_flags = pd->in_flags;
  1034.         spd++;
  1035.         pdcnt++;
  1036.  
  1037.         if (in_flags & PR_POLL_READ)  {
  1038.             FD_SET(osfd, &_PR_FD_READ_SET(me->cpu));
  1039.             _PR_FD_READ_CNT(me->cpu)[osfd]++;
  1040.         }
  1041.         if (in_flags & PR_POLL_WRITE) {
  1042.             FD_SET(osfd, &_PR_FD_WRITE_SET(me->cpu));
  1043.             (_PR_FD_WRITE_CNT(me->cpu))[osfd]++;
  1044.         }
  1045.         if (in_flags & PR_POLL_EXCEPT) {
  1046.             FD_SET(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
  1047.             (_PR_FD_EXCEPTION_CNT(me->cpu))[osfd]++;
  1048.         }
  1049.         if (osfd > _PR_IOQ_MAX_OSFD(me->cpu))
  1050.             _PR_IOQ_MAX_OSFD(me->cpu) = osfd;
  1051.     }
  1052.     if (timeout < _PR_IOQ_TIMEOUT(me->cpu))
  1053.         _PR_IOQ_TIMEOUT(me->cpu) = timeout;
  1054.  
  1055.  
  1056.     pq->pds = spds;
  1057.     pq->npds = pdcnt;
  1058.  
  1059.     pq->thr = me;
  1060.     pq->on_ioq = PR_TRUE;
  1061.     pq->timeout = timeout;
  1062.     _PR_ADD_TO_IOQ((*pq), me->cpu);
  1063.     _PR_SLEEPQ_LOCK(me->cpu);
  1064.     _PR_ADD_SLEEPQ(me, timeout);
  1065.     me->state = _PR_IO_WAIT;
  1066.     me->io_pending = PR_TRUE;
  1067.     me->io_suspended = PR_FALSE;
  1068.     _PR_SLEEPQ_UNLOCK(me->cpu);
  1069.     _PR_THREAD_UNLOCK(me);
  1070.     _PR_MD_IOQ_UNLOCK();
  1071.  
  1072.     _PR_MD_WAIT(me, timeout);
  1073.  
  1074.     me->io_pending = PR_FALSE;
  1075.     me->io_suspended = PR_FALSE;
  1076.  
  1077.     /*
  1078.      * Copy the out_flags from the _PRWin16PollDesc structures to the
  1079.      * user's PRPollDesc structures and free the allocated memory
  1080.      */
  1081.     spd = spds;
  1082.     for (pd = pds, epd = pd + npds; pd < epd; pd++) {
  1083.         if ((NULL == pd->fd) || (pd->in_flags == 0)) {
  1084.             pd->out_flags = 0;
  1085.             continue;
  1086.         }
  1087.         pd->out_flags = spd->out_flags;
  1088.         spd++;
  1089.     }
  1090.     PR_DELETE(spds);
  1091.  
  1092.     /*
  1093.     ** If we timed out the pollq might still be on the ioq. Remove it
  1094.     ** before continuing.
  1095.     */
  1096.     if (pq->on_ioq) {
  1097.         _PR_INTSOFF(is);
  1098.         _PR_MD_IOQ_LOCK();
  1099.         /*
  1100.          * Need to check pq.on_ioq again
  1101.          */
  1102.         if (pq->on_ioq == PR_TRUE) {
  1103.             PR_REMOVE_LINK(&pq->links);
  1104.             for (pd = pds, epd = pd + npds; pd < epd; pd++) {
  1105.                 PRInt32 osfd;
  1106.                 PRInt16 in_flags = pd->in_flags;
  1107.                 PRFileDesc *bottom = pd->fd;
  1108.  
  1109.                 if ((NULL == bottom) || (in_flags == 0)) {
  1110.                     continue;
  1111.                 }
  1112.                 while (bottom->lower != NULL) {
  1113.                     bottom = bottom->lower;
  1114.                 }
  1115.                 osfd = bottom->secret->md.osfd;
  1116.                 PR_ASSERT(osfd >= 0 || in_flags == 0);
  1117.                 if (in_flags & PR_POLL_READ)  {
  1118.                     if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0)
  1119.                         FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));
  1120.                 }
  1121.                 if (in_flags & PR_POLL_WRITE) {
  1122.                     if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0)
  1123.                             FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));
  1124.                 }
  1125.                 if (in_flags & PR_POLL_EXCEPT) {
  1126.                     if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0)
  1127.                             FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
  1128.                 }
  1129.             }
  1130.         }
  1131.         _PR_MD_IOQ_UNLOCK();
  1132.         _PR_INTSON(is);
  1133.     }
  1134.     if (_PR_PENDING_INTERRUPT(me)) {
  1135.         me->flags &= ~_PR_INTERRUPT;
  1136.         PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
  1137.            return -1;
  1138.     } else {
  1139.         n = 0;
  1140.         if (pq->on_ioq == PR_FALSE) {
  1141.             /* Count the number of ready descriptors */
  1142.             while (--npds >= 0) {
  1143.             if (pds->out_flags) {
  1144.                 n++;
  1145.             }
  1146.                 pds++;
  1147.             }
  1148.         }
  1149.         return n;
  1150.     }
  1151. } /* end _MD_pr_poll() */
  1152.