diff options
Diffstat (limited to 'pr/src/md/os2/os2poll.c')
-rw-r--r-- | pr/src/md/os2/os2poll.c | 268 |
1 files changed, 185 insertions, 83 deletions
diff --git a/pr/src/md/os2/os2poll.c b/pr/src/md/os2/os2poll.c index 12f199f6..3b087e11 100644 --- a/pr/src/md/os2/os2poll.c +++ b/pr/src/md/os2/os2poll.c @@ -37,54 +37,64 @@ */ #ifdef XP_OS2_EMX - #include <sys/time.h> /* For timeval. */ + #include <sys/time.h> /* For timeval. */ #endif #include "primpl.h" -PRInt32 _PR_MD_PR_POLL( - PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout) +#ifndef BSD_SELECT +/* Utility functions called when using OS/2 select */ + +PRBool IsSocketSet( PRInt32 osfd, int* socks, int start, int count ) +{ + int i; + PRBool isSet = PR_FALSE; + + for( i = start; i < start+count; i++ ) + { + if( socks[i] == osfd ) + isSet = PR_TRUE; + } + + return isSet; +} +#endif + +PRInt32 _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout) { - PRInt32 osfd; - int maxfd = -1; +#ifdef BSD_SELECT fd_set rd, wt, ex; +#else + int rd, wt, ex; + int* socks; + unsigned long msecs; + int i, j; +#endif PRFileDesc *bottom; PRPollDesc *pd, *epd; - PRInt32 ready, err; - PRThread *me = _PR_MD_CURRENT_THREAD(); - struct timeval tv, *tvp = NULL; + PRInt32 maxfd = -1, ready, err; + PRIntervalTime remaining, elapsed, start; - /* - * For restarting _MD_SELECT() if it is interrupted by a signal. - * We use these variables to figure out how much time has elapsed - * and how much of the timeout still remains. - */ - PRIntervalTime start, elapsed, remaining; +#ifdef BSD_SELECT + struct timeval tv, *tvp = NULL; - if (_PR_PENDING_INTERRUPT(me)) + FD_ZERO(&rd); + FD_ZERO(&wt); + FD_ZERO(&ex); +#else + rd = 0; + wt = 0; + ex = 0; + socks = (int) PR_MALLOC( npds * 3 * sizeof(int) ); + + if (!socks) { - me->flags &= ~_PR_INTERRUPT; - PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return -1; } +#endif - /* - ** Is it an empty set? If so, just sleep for the timeout and return - */ - if (0 == npds) - { - PR_Sleep(timeout); - return 0; - } - - remaining = timeout; - start = PR_IntervalNow(); - - FD_ZERO(&rd); - FD_ZERO(&wt); - FD_ZERO(&ex); - - ready = 0; + ready = 0; for (pd = pds, epd = pd + npds; pd < epd; pd++) { PRInt16 in_flags_read = 0, in_flags_write = 0; @@ -95,19 +105,17 @@ PRInt32 _PR_MD_PR_POLL( if (pd->in_flags & PR_POLL_READ) { in_flags_read = (pd->fd->methods->poll)( - pd->fd, (PRInt16)(pd->in_flags & ~PR_POLL_WRITE), - &out_flags_read); + pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read); } if (pd->in_flags & PR_POLL_WRITE) { in_flags_write = (pd->fd->methods->poll)( - pd->fd, (PRInt16)(pd->in_flags & ~PR_POLL_READ), - &out_flags_write); + pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write); } - if ((0 != (in_flags_read & out_flags_read)) - || (0 != (in_flags_write & out_flags_write))) + if ((0 != (in_flags_read & out_flags_read)) || + (0 != (in_flags_write & out_flags_write))) { - /* this one's ready right now (buffered input) */ + /* this one's ready right now */ if (0 == ready) { /* @@ -128,37 +136,67 @@ PRInt32 _PR_MD_PR_POLL( else { pd->out_flags = 0; /* pre-condition */ + /* make sure this is an NSPR supported stack */ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); PR_ASSERT(NULL != bottom); /* what to do about that? */ - if ((NULL != bottom) - && (_PR_FILEDESC_OPEN == bottom->secret->state)) + if ((NULL != bottom) && + (_PR_FILEDESC_OPEN == bottom->secret->state)) { if (0 == ready) { - osfd = bottom->secret->md.osfd; - if (osfd > maxfd) maxfd = osfd; + PRInt32 osfd = bottom->secret->md.osfd; + if (osfd > maxfd) + maxfd = osfd; if (in_flags_read & PR_POLL_READ) { pd->out_flags |= _PR_POLL_READ_SYS_READ; +#ifdef BSD_SELECT FD_SET(osfd, &rd); +#else + socks[rd] = osfd; + rd++; +#endif } if (in_flags_read & PR_POLL_WRITE) { pd->out_flags |= _PR_POLL_READ_SYS_WRITE; +#ifdef BSD_SELECT FD_SET(osfd, &wt); +#else + socks[npds+wt] = osfd; + wt++; +#endif } if (in_flags_write & PR_POLL_READ) { pd->out_flags |= _PR_POLL_WRITE_SYS_READ; +#ifdef BSD_SELECT FD_SET(osfd, &rd); +#else + socks[rd] = osfd; + rd++; +#endif } if (in_flags_write & PR_POLL_WRITE) { pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE; +#ifdef BSD_SELECT FD_SET(osfd, &wt); +#else + socks[npds+wt] = osfd; + wt++; +#endif + } + if (pd->in_flags & PR_POLL_EXCEPT) + { +#ifdef BSD_SELECT + FD_SET(osfd, &ex); +#else + socks[npds*2+ex] = osfd; + ex++; +#endif } - if (pd->in_flags & PR_POLL_EXCEPT) FD_SET(osfd, &ex); } } else @@ -176,11 +214,25 @@ PRInt32 _PR_MD_PR_POLL( } } } + else + { + pd->out_flags = 0; + } } - if (0 != ready) return ready; /* no need to block */ + if (0 != ready) + { +#ifndef BSD_SELECT + free(socks); +#endif + return ready; /* no need to block */ + } + + remaining = timeout; + start = PR_IntervalNow(); retry: +#ifdef BSD_SELECT if (timeout != PR_INTERVAL_NO_TIMEOUT) { PRInt32 ticksPerSecond = PR_TicksPerSecond(); @@ -191,21 +243,50 @@ retry: } ready = _MD_SELECT(maxfd + 1, &rd, &wt, &ex, tvp); +#else + switch (timeout) + { + case PR_INTERVAL_NO_WAIT: + msecs = 0; + break; + case PR_INTERVAL_NO_TIMEOUT: + msecs = -1; + break; + default: + msecs = PR_IntervalToMilliseconds(remaining); + } + + /* compact array */ + for( i = rd, j = npds; j < npds+wt; i++,j++ ) + socks[i] = socks[j]; + for( i = rd+wt, j = npds*2; j < npds*2+ex; i++,j++ ) + socks[i] = socks[j]; + + ready = _MD_SELECT(socks, rd, wt, ex, msecs); +#endif + if (ready == -1 && errno == EINTR) { - if (timeout == PR_INTERVAL_NO_TIMEOUT) goto retry; - else + if (timeout == PR_INTERVAL_NO_TIMEOUT) + goto retry; + else { - elapsed = (PRIntervalTime) (PR_IntervalNow() - start); - if (elapsed > timeout) ready = 0; /* timed out */ - else + elapsed = (PRIntervalTime) (PR_IntervalNow() - start); + if (elapsed > timeout) + ready = 0; /* timed out */ + else { - remaining = timeout - elapsed; - goto retry; + remaining = timeout - elapsed; + goto retry; } - } + } } + /* + ** Now to unravel the select sets back into the client's poll + ** descriptor list. Is this possibly an area for pissing away + ** a few cycles or what? + */ if (ready > 0) { ready = 0; @@ -214,26 +295,44 @@ retry: PRInt16 out_flags = 0; if ((NULL != pd->fd) && (0 != pd->in_flags)) { + PRInt32 osfd; bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); PR_ASSERT(NULL != bottom); osfd = bottom->secret->md.osfd; +#ifdef BSD_SELECT if (FD_ISSET(osfd, &rd)) +#else + if( IsSocketSet(osfd, socks, 0, rd) ) +#endif { if (pd->out_flags & _PR_POLL_READ_SYS_READ) out_flags |= PR_POLL_READ; if (pd->out_flags & _PR_POLL_WRITE_SYS_READ) out_flags |= PR_POLL_WRITE; - } + } + +#ifdef BSD_SELECT if (FD_ISSET(osfd, &wt)) +#else + if( IsSocketSet(osfd, socks, rd, wt) ) +#endif { if (pd->out_flags & _PR_POLL_READ_SYS_WRITE) out_flags |= PR_POLL_READ; if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE) out_flags |= PR_POLL_WRITE; + } + +#ifdef BSD_SELECT + if (FD_ISSET(osfd, &ex)) +#else + if( IsSocketSet(osfd, socks, rd+wt, ex) ) +#endif + { + out_flags |= PR_POLL_EXCEPT; } - if (FD_ISSET(osfd, &ex)) out_flags |= PR_POLL_EXCEPT; } pd->out_flags = out_flags; if (out_flags) ready++; @@ -242,39 +341,42 @@ retry: } else if (ready < 0) { - err = _MD_ERRNO(); - if (err == EBADF) + err = _MD_ERRNO(); + if (err == EBADF) { - /* Find the bad fds */ - ready = 0; - for (pd = pds, epd = pd + npds; pd < epd; pd++) + /* Find the bad fds */ + int optval; + int optlen = sizeof(optval); + ready = 0; + for (pd = pds, epd = pd + npds; pd < epd; pd++) { - int optval; - int optlen = sizeof(optval); - pd->out_flags = 0; - if ((NULL == pd->fd) || (pd->in_flags == 0)) continue; - bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); - if (getsockopt(bottom->secret->md.osfd, SOL_SOCKET, - SO_TYPE, (char *) &optval, &optlen) == -1) + pd->out_flags = 0; + if ((NULL != pd->fd) && (0 != pd->in_flags)) { - PR_ASSERT(_MD_ERRNO() == ENOTSOCK); - if (_MD_ERRNO() == ENOTSOCK) + bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); + if (getsockopt(bottom->secret->md.osfd, SOL_SOCKET, + SO_TYPE, (char *) &optval, &optlen) == -1) { - pd->out_flags = PR_POLL_NVAL; - ready++; + PR_ASSERT(sock_errno() == ENOTSOCK); + if (sock_errno() == ENOTSOCK) + { + pd->out_flags = PR_POLL_NVAL; + ready++; + } } } - } - PR_ASSERT(ready > 0); - } - else - { - PR_ASSERT(err != EINTR); /* should have been handled above */ - _PR_MD_MAP_SELECT_ERROR(err); + } + PR_ASSERT(ready > 0); } - } - return ready; - } + else + _PR_MD_MAP_SELECT_ERROR(err); + } + +#ifndef BSD_SELECT + free(socks); +#endif + return ready; +} #ifdef XP_OS2_EMX HMTX thread_select_mutex = 0; /* because EMX's select is not thread safe - duh! */ |