For the IO continuation operation, use select(), instead of poll(),

on OSF1. Bug #153459.
This commit is contained in:
srinivas%netscape.com 2000-03-17 20:01:41 +00:00
Родитель 9fdbed74a4
Коммит d254f1ca9a
1 изменённых файлов: 163 добавлений и 0 удалений

Просмотреть файл

@ -23,6 +23,11 @@
#if defined(_PR_PTHREADS) #if defined(_PR_PTHREADS)
#if defined(OSF1)
/* set fd limit for select(), before including system header files */
#define FD_SETSIZE (16 * 1024)
#endif
#include <pthread.h> #include <pthread.h>
#include <string.h> /* for memset() */ #include <string.h> /* for memset() */
#include <sys/types.h> #include <sys/types.h>
@ -190,6 +195,11 @@ static PRBool IsValidNetAddrLen(const PRNetAddr *addr, PRInt32 addr_len)
* might hang up before an interrupt is noticed. * might hang up before an interrupt is noticed.
*/ */
#define PT_DEFAULT_POLL_MSEC 5000 #define PT_DEFAULT_POLL_MSEC 5000
#if defined(OSF1)
#define PT_DEFAULT_SELECT_SEC (PT_DEFAULT_POLL_MSEC/PR_MSEC_PER_SEC)
#define PT_DEFAULT_SELECT_USEC \
((PT_DEFAULT_POLL_MSEC % PR_MSEC_PER_SEC) * PR_USEC_PER_MSEC)
#endif
/* /*
* pt_SockLen is the type for the length of a socket address * pt_SockLen is the type for the length of a socket address
@ -304,6 +314,150 @@ PR_IMPLEMENT(void) PT_FPrintStats(PRFileDesc *debug_out, const char *msg)
#endif /* DEBUG */ #endif /* DEBUG */
#if defined(OSF1)
/*
* OSF1 reports the POLLHUP event for a socket when the shutdown(SHUT_WR)
* operation is called for the remote end, even though the socket is still
* writeable. Use select(), instead of poll(), to workaround this problem.
*/
static void osf_pt_poll_now(pt_Continuation *op)
{
PRInt32 msecs;
fd_set rd, wr, *rdp, *wrp;
struct timeval tv;
PRIntervalTime epoch, now, elapsed, remaining;
PRThread *self = PR_GetCurrentThread();
PR_ASSERT(PR_INTERVAL_NO_WAIT != op->timeout);
PR_ASSERT(op->arg1.osfd < FD_SETSIZE);
switch (op->timeout) {
case PR_INTERVAL_NO_TIMEOUT:
tv.tv_sec = PT_DEFAULT_SELECT_SEC;
tv.tv_usec = PT_DEFAULT_SELECT_USEC;
do
{
PRIntn rv;
if (op->event & POLLIN) {
FD_ZERO(&rd);
FD_SET(op->arg1.osfd, &rd);
rdp = &rd;
} else
rdp = NULL;
if (op->event & POLLOUT) {
FD_ZERO(&wr);
FD_SET(op->arg1.osfd, &wr);
wrp = &wr;
} else
wrp = NULL;
rv = select(op->arg1.osfd + 1, rdp, wrp, NULL, &tv);
if (self->state & PT_THREAD_ABORTED)
{
self->state &= ~PT_THREAD_ABORTED;
op->result.code = -1;
op->syserrno = EINTR;
op->status = pt_continuation_done;
return;
}
if ((-1 == rv) && ((errno == EINTR) || (errno == EAGAIN)))
continue; /* go around the loop again */
if (rv > 0)
{
PRInt16 revents = 0;
if ((op->event & POLLIN) && FD_ISSET(op->arg1.osfd, &rd))
revents |= POLLIN;
if ((op->event & POLLOUT) && FD_ISSET(op->arg1.osfd, &wr))
revents |= POLLOUT;
if (op->function(op, revents))
op->status = pt_continuation_done;
} else if (rv == -1) {
op->result.code = -1;
op->syserrno = errno;
op->status = pt_continuation_done;
}
/* else, select timed out */
} while (pt_continuation_done != op->status);
break;
default:
now = epoch = PR_IntervalNow();
remaining = op->timeout;
do
{
PRIntn rv;
if (op->event & POLLIN) {
FD_ZERO(&rd);
FD_SET(op->arg1.osfd, &rd);
rdp = &rd;
} else
rdp = NULL;
if (op->event & POLLOUT) {
FD_ZERO(&wr);
FD_SET(op->arg1.osfd, &wr);
wrp = &wr;
} else
wrp = NULL;
msecs = (PRInt32)PR_IntervalToMilliseconds(remaining);
if (msecs > PT_DEFAULT_POLL_MSEC)
msecs = PT_DEFAULT_POLL_MSEC;
tv.tv_sec = msecs/PR_MSEC_PER_SEC;
tv.tv_usec = (msecs % PR_MSEC_PER_SEC) * PR_USEC_PER_MSEC;
rv = select(op->arg1.osfd + 1, rdp, wrp, NULL, &tv);
if (self->state & PT_THREAD_ABORTED)
{
self->state &= ~PT_THREAD_ABORTED;
op->result.code = -1;
op->syserrno = EINTR;
op->status = pt_continuation_done;
return;
}
if (rv > 0) {
PRInt16 revents = 0;
if ((op->event & POLLIN) && FD_ISSET(op->arg1.osfd, &rd))
revents |= POLLIN;
if ((op->event & POLLOUT) && FD_ISSET(op->arg1.osfd, &wr))
revents |= POLLOUT;
if (op->function(op, revents))
op->status = pt_continuation_done;
} else if ((rv == 0) ||
((errno == EINTR) || (errno == EAGAIN))) {
if (rv == 0) /* select timed out */
now += PR_MillisecondsToInterval(msecs);
else
now = PR_IntervalNow();
elapsed = (PRIntervalTime) (now - epoch);
if (elapsed >= op->timeout) {
op->result.code = -1;
op->syserrno = ETIMEDOUT;
op->status = pt_continuation_done;
} else
remaining = op->timeout - elapsed;
} else {
op->result.code = -1;
op->syserrno = errno;
op->status = pt_continuation_done;
}
} while (pt_continuation_done != op->status);
break;
}
} /* osf_pt_poll_now */
#endif /* OSF1 */
static void pt_poll_now(pt_Continuation *op) static void pt_poll_now(pt_Continuation *op)
{ {
PRInt32 msecs; PRInt32 msecs;
@ -311,6 +465,15 @@ static void pt_poll_now(pt_Continuation *op)
PRThread *self = PR_GetCurrentThread(); PRThread *self = PR_GetCurrentThread();
PR_ASSERT(PR_INTERVAL_NO_WAIT != op->timeout); PR_ASSERT(PR_INTERVAL_NO_WAIT != op->timeout);
#if defined (OSF1)
/*
* If the fd is small enough call the select-based poll operation
*/
if (op->arg1.osfd < FD_SETSIZE) {
osf_pt_poll_now(op);
return;
}
#endif
switch (op->timeout) { switch (op->timeout) {
case PR_INTERVAL_NO_TIMEOUT: case PR_INTERVAL_NO_TIMEOUT: