diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2003-12-31 03:27:24 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2003-12-31 03:27:24 +0000 |
commit | 23f499490dbfd44837b6e8444733b39e8577d76f (patch) | |
tree | 36e51f78cf130e80aa8a9bfc92190cd065ce4098 /lib/libc/rpc/clnt_tcp.c | |
parent | 8d7e31dc1a81c4e63b4f5022186f2a529198c3ac (diff) |
Implement svc_getreq_poll(3) and friends and use poll(2) instead of select(2)
in the libc rpc code. The main difference between this and the previous
version is the use of a simple free list that simplifies the logic when
adding a socket to svc_pollfd. I've also added code to pack svc_pollfd
when the free list gets too big. The idea general idea is to keep
svc_pollfd as tightly packed as possible to make poll(2) efficient.
Tested by many people and OK deraadt@
Diffstat (limited to 'lib/libc/rpc/clnt_tcp.c')
-rw-r--r-- | lib/libc/rpc/clnt_tcp.c | 47 |
1 files changed, 19 insertions, 28 deletions
diff --git a/lib/libc/rpc/clnt_tcp.c b/lib/libc/rpc/clnt_tcp.c index bb2f5607d3a..c2110224df0 100644 --- a/lib/libc/rpc/clnt_tcp.c +++ b/lib/libc/rpc/clnt_tcp.c @@ -28,7 +28,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char *rcsid = "$OpenBSD: clnt_tcp.c,v 1.18 2001/09/15 13:51:00 deraadt Exp $"; +static char *rcsid = "$OpenBSD: clnt_tcp.c,v 1.19 2003/12/31 03:27:23 millert Exp $"; #endif /* LIBC_SCCS and not lint */ /* @@ -402,58 +402,49 @@ readtcp(ct, buf, len) caddr_t buf; int len; { - fd_set *fds, readfds; - struct timeval start, after, duration, delta, tmp; - int r, save_errno; + struct pollfd pfd[1]; + struct timeval start, after, duration, tmp; + int delta, r, save_errno; if (len == 0) return (0); - if (ct->ct_sock+1 > FD_SETSIZE) { - int bytes = howmany(ct->ct_sock+1, NFDBITS) * sizeof(fd_mask); - fds = (fd_set *)malloc(bytes); - if (fds == NULL) - return (-1); - memset(fds, 0, bytes); - } else { - fds = &readfds; - FD_ZERO(fds); - } - + pfd[0].fd = ct->ct_sock; + pfd[0].events = POLLIN; + delta = ct->ct_wait.tv_sec * 1000 + ct->ct_wait.tv_usec / 1000; gettimeofday(&start, NULL); - delta = ct->ct_wait; - while (TRUE) { - /* XXX we know the other bits are still clear */ - FD_SET(ct->ct_sock, fds); - r = select(ct->ct_sock+1, fds, NULL, NULL, &delta); + for (;;) { + r = poll(pfd, 1, delta); save_errno = errno; gettimeofday(&after, NULL); timersub(&start, &after, &duration); timersub(&ct->ct_wait, &duration, &tmp); - delta = tmp; - if (delta.tv_sec < 0 || !timerisset(&delta)) + delta = tmp.tv_sec * 1000 + tmp.tv_usec / 1000; + if (delta <= 0) r = 0; switch (r) { case 0: ct->ct_error.re_status = RPC_TIMEDOUT; - if (fds != &readfds) - free(fds); return (-1); + case 1: + if (pfd[0].revents & POLLNVAL) + errno = EBADF; + else if (pfd[0].revents & POLLERR) + errno = EIO; + else + break; + /* FALLTHROUGH */ case -1: if (errno == EINTR) continue; ct->ct_error.re_status = RPC_CANTRECV; ct->ct_error.re_errno = save_errno; - if (fds != &readfds) - free(fds); return (-1); } break; } - if (fds != &readfds) - free(fds); switch (len = read(ct->ct_sock, buf, len)) { case 0: |