In rpoll(), we spin for a short period of time prior to calling poll(). And poll() is called in a loop, in order to handle events that may not update the desired rsocket state. For example, we could wake up from poll() to process a control message, such as a credit update, but be waiting for app data to be avaialble. This can result in the calling thread re-entering poll(). In order to avoid waiting in poll() for longer than the user specified timeout, track when we enter the call and update the timeout passed to poll() accordingly. Signed-off-by: Sean Hefty <sean.hefty@xxxxxxxxx> --- librdmacm/rsocket.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/librdmacm/rsocket.c b/librdmacm/rsocket.c index f64719e8..cee3bd01 100644 --- a/librdmacm/rsocket.c +++ b/librdmacm/rsocket.c @@ -2973,6 +2973,14 @@ ssize_t rwritev(int socket, const struct iovec *iov, int iovcnt) return rsendv(socket, iov, iovcnt, 0); } +static uint64_t rs_time_us(void) +{ + struct timeval now; + + gettimeofday(&now, NULL); + return now.tv_sec * 1000000 + now.tv_usec; +} + static struct pollfd *rs_fds_alloc(nfds_t nfds) { static __thread struct pollfd *rfds; @@ -3139,8 +3147,8 @@ static int rs_poll_events(struct pollfd *rfds, struct pollfd *fds, nfds_t nfds) */ int rpoll(struct pollfd *fds, nfds_t nfds, int timeout) { - struct timeval s, e; struct pollfd *rfds; + uint64_t start_time; uint32_t poll_time = 0; int ret; @@ -3150,11 +3158,9 @@ int rpoll(struct pollfd *fds, nfds_t nfds, int timeout) return ret; if (!poll_time) - gettimeofday(&s, NULL); + start_time = rs_time_us(); - gettimeofday(&e, NULL); - poll_time = (e.tv_sec - s.tv_sec) * 1000000 + - (e.tv_usec - s.tv_usec) + 1; + poll_time = (uint32_t) (rs_time_us() - start_time); } while (poll_time <= polling_time); rfds = rs_fds_alloc(nfds); @@ -3166,6 +3172,12 @@ int rpoll(struct pollfd *fds, nfds_t nfds, int timeout) if (ret) break; + if (timeout >= 0) { + timeout -= (int) ((rs_time_us() - start_time) / 1000); + if (timeout <= 0) + return 0; + } + ret = poll(rfds, nfds, timeout); if (ret <= 0) break;