зеркало из https://github.com/mozilla/gecko-dev.git
For the IO continuation operation, use select(), instead of poll(),
on OSF1. Bug #153459.
This commit is contained in:
Родитель
9fdbed74a4
Коммит
d254f1ca9a
|
@ -23,6 +23,11 @@
|
|||
|
||||
#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 <string.h> /* for memset() */
|
||||
#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.
|
||||
*/
|
||||
#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
|
||||
|
@ -304,6 +314,150 @@ PR_IMPLEMENT(void) PT_FPrintStats(PRFileDesc *debug_out, const char *msg)
|
|||
|
||||
#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 = ≀
|
||||
} 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 = ≀
|
||||
} 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)
|
||||
{
|
||||
PRInt32 msecs;
|
||||
|
@ -311,6 +465,15 @@ static void pt_poll_now(pt_Continuation *op)
|
|||
PRThread *self = PR_GetCurrentThread();
|
||||
|
||||
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) {
|
||||
case PR_INTERVAL_NO_TIMEOUT:
|
||||
|
|
Загрузка…
Ссылка в новой задаче