[ovs-dev] [flow-stats 08/14] poll-loop: Track the poll timeout as an absolute, not a relative time.
Ben Pfaff
blp at nicira.com
Mon Dec 19 22:27:57 UTC 2011
I think I'll leave it as-is, because it has had the current name for a
long time without any confusion (as far as I know).
Thanks,
Ben.
On Mon, Dec 19, 2011 at 01:20:21PM -0800, Ethan Jackson wrote:
> It might make sense to rename poll_zero_timeout. Perhaps it would be
> more clear as poll_immediate_wake. I don't feel strongly about it.
>
> Looks good,
>
> Ethan
>
> On Thu, Dec 8, 2011 at 14:01, Ben Pfaff <blp at nicira.com> wrote:
> > This is a necessary prerequisite for allowing time to be "fast forwarded"
> > in unit tests, to keep tests that depend on the passage of time from
> > running in real time. ?Without this change, a code sequence like this:
> >
> > ? ? ? ?poll_timer_wait(1000);
> > ? ? ? ?...fast forward time 5 seconds...
> > ? ? ? ?poll_block();
> >
> > would still sleep for a second, because the poll_loop module would still
> > have a relative timeout of 1000 ms.
> > ---
> > ?lib/poll-loop.c | ? 56 ++++++++++++++++++++++++++++--------------------------
> > ?lib/timeval.c ? | ? 23 +++++++++++++++------
> > ?lib/timeval.h ? | ? ?3 +-
> > ?3 files changed, 47 insertions(+), 35 deletions(-)
> >
> > diff --git a/lib/poll-loop.c b/lib/poll-loop.c
> > index 5ff70d9..8bb5a9c 100644
> > --- a/lib/poll-loop.c
> > +++ b/lib/poll-loop.c
> > @@ -55,9 +55,10 @@ struct poll_waiter {
> > ?/* All active poll waiters. */
> > ?static struct list waiters = LIST_INITIALIZER(&waiters);
> >
> > -/* Max time to wait in next call to poll_block(), in milliseconds, or -1 to
> > +/* Time at which to wake up next call to poll_block(), in milliseconds as
> > + * returned by time_msec(), LLONG_MIN to wake up immediately, or LLONG_MAX to
> > ?* wait forever. */
> > -static int timeout = -1;
> > +static long long int timeout_when = LLONG_MAX;
> >
> > ?/* Location where waiter created. */
> > ?static const char *timeout_where;
> > @@ -82,16 +83,6 @@ poll_fd_wait(int fd, short int events, const char *where)
> > ? ? return new_waiter(fd, events, where);
> > ?}
> >
> > -/* The caller must ensure that 'msec' is not negative. */
> > -static void
> > -poll_timer_wait__(int msec, const char *where)
> > -{
> > - ? ?if (timeout < 0 || msec < timeout) {
> > - ? ? ? ?timeout = msec;
> > - ? ? ? ?timeout_where = where;
> > - ? ?}
> > -}
> > -
> > ?/* Causes the following call to poll_block() to block for no more than 'msec'
> > ?* milliseconds. ?If 'msec' is nonpositive, the following call to poll_block()
> > ?* will not block at all.
> > @@ -105,14 +96,25 @@ poll_timer_wait__(int msec, const char *where)
> > ?void
> > ?poll_timer_wait(long long int msec, const char *where)
> > ?{
> > - ? ?poll_timer_wait__((msec < 0 ? 0
> > - ? ? ? ? ? ? ? ? ? ? ? : msec > INT_MAX ? INT_MAX
> > - ? ? ? ? ? ? ? ? ? ? ? : msec),
> > - ? ? ? ? ? ? ? ? ? ? ?where);
> > + ? ?long long int now = time_msec();
> > + ? ?long long int when;
> > +
> > + ? ?if (msec <= 0) {
> > + ? ? ? ?/* Wake up immediately. */
> > + ? ? ? ?when = LLONG_MIN;
> > + ? ?} else if ((unsigned long long int) now + msec <= LLONG_MAX) {
> > + ? ? ? ?/* Normal case. */
> > + ? ? ? ?when = now + msec;
> > + ? ?} else {
> > + ? ? ? ?/* now + msec would overflow. */
> > + ? ? ? ?when = LLONG_MAX;
> > + ? ?}
> > +
> > + ? ?poll_timer_wait_until(when, where);
> > ?}
> >
> > ?/* Causes the following call to poll_block() to wake up when the current time,
> > - * as returned by time_msec(), reaches 'msec' or later. ?If 'msec' is earlier
> > + * as returned by time_msec(), reaches 'when' or later. ?If 'when' is earlier
> > ?* than the current time, the following call to poll_block() will not block at
> > ?* all.
> > ?*
> > @@ -123,13 +125,12 @@ poll_timer_wait(long long int msec, const char *where)
> > ?* Ordinarily the 'where' argument is supplied automatically; see poll-loop.h
> > ?* for more information. */
> > ?void
> > -poll_timer_wait_until(long long int msec, const char *where)
> > +poll_timer_wait_until(long long int when, const char *where)
> > ?{
> > - ? ?long long int now = time_msec();
> > - ? ?poll_timer_wait__((msec <= now ? 0
> > - ? ? ? ? ? ? ? ? ? ? ? : msec < now + INT_MAX ? msec - now
> > - ? ? ? ? ? ? ? ? ? ? ? : INT_MAX),
> > - ? ? ? ? ? ? ? ? ? ? ?where);
> > + ? ?if (when < timeout_when) {
> > + ? ? ? ?timeout_when = when;
> > + ? ? ? ?timeout_where = where;
> > + ? ?}
> > ?}
> >
> > ?/* Causes the following call to poll_block() to wake up immediately, without
> > @@ -215,6 +216,7 @@ poll_block(void)
> >
> > ? ? struct poll_waiter *pw, *next;
> > ? ? int n_waiters, n_pollfds;
> > + ? ?int elapsed;
> > ? ? int retval;
> >
> > ? ? /* Register fatal signal events before actually doing any real work for
> > @@ -236,15 +238,15 @@ poll_block(void)
> > ? ? ? ? n_pollfds++;
> > ? ? }
> >
> > - ? ?if (!timeout) {
> > + ? ?if (timeout_when == LLONG_MIN) {
> > ? ? ? ? COVERAGE_INC(poll_zero_timeout);
> > ? ? }
> > - ? ?retval = time_poll(pollfds, n_pollfds, timeout);
> > + ? ?retval = time_poll(pollfds, n_pollfds, timeout_when, &elapsed);
> > ? ? if (retval < 0) {
> > ? ? ? ? static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
> > ? ? ? ? VLOG_ERR_RL(&rl, "poll: %s", strerror(-retval));
> > ? ? } else if (!retval) {
> > - ? ? ? ?log_wakeup(timeout_where, NULL, timeout);
> > + ? ? ? ?log_wakeup(timeout_where, NULL, elapsed);
> > ? ? }
> >
> > ? ? LIST_FOR_EACH_SAFE (pw, next, node, &waiters) {
> > @@ -254,7 +256,7 @@ poll_block(void)
> > ? ? ? ? poll_cancel(pw);
> > ? ? }
> >
> > - ? ?timeout = -1;
> > + ? ?timeout_when = LLONG_MAX;
> > ? ? timeout_where = NULL;
> >
> > ? ? /* Handle any pending signals before doing anything else. */
> > diff --git a/lib/timeval.c b/lib/timeval.c
> > index 88a6679..bc7411f 100644
> > --- a/lib/timeval.c
> > +++ b/lib/timeval.c
> > @@ -269,16 +269,21 @@ time_alarm(unsigned int secs)
> >
> > ?/* Like poll(), except:
> > ?*
> > + * ? ? ?- The timeout is specified as an absolute time, as defined by
> > + * ? ? ? ?time_msec(), instead of a duration.
> > + *
> > ?* ? ? ?- On error, returns a negative error code (instead of setting errno).
> > ?*
> > ?* ? ? ?- If interrupted by a signal, retries automatically until the original
> > - * ? ? ? ?'timeout' expires. ?(Because of this property, this function will
> > + * ? ? ? ?timeout is reached. ?(Because of this property, this function will
> > ?* ? ? ? ?never return -EINTR.)
> > ?*
> > ?* ? ? ?- As a side effect, refreshes the current time (like time_refresh()).
> > - */
> > + *
> > + * Stores the number of milliseconds elapsed during poll in '*elapsed'. */
> > ?int
> > -time_poll(struct pollfd *pollfds, int n_pollfds, int timeout)
> > +time_poll(struct pollfd *pollfds, int n_pollfds, long long int timeout_when,
> > + ? ? ? ? ?int *elapsed)
> > ?{
> > ? ? static long long int last_wakeup;
> > ? ? long long int start;
> > @@ -292,12 +297,15 @@ time_poll(struct pollfd *pollfds, int n_pollfds, int timeout)
> > ? ? start = time_msec();
> > ? ? blocked = false;
> > ? ? for (;;) {
> > + ? ? ? ?long long int now = time_msec();
> > ? ? ? ? int time_left;
> > - ? ? ? ?if (timeout > 0) {
> > - ? ? ? ? ? ?long long int elapsed = time_msec() - start;
> > - ? ? ? ? ? ?time_left = timeout >= elapsed ? timeout - elapsed : 0;
> > +
> > + ? ? ? ?if (now >= timeout_when) {
> > + ? ? ? ? ? ?time_left = 0;
> > + ? ? ? ?} else if ((unsigned long long int) timeout_when - now > INT_MAX) {
> > + ? ? ? ? ? ?time_left = INT_MAX;
> > ? ? ? ? } else {
> > - ? ? ? ? ? ?time_left = timeout;
> > + ? ? ? ? ? ?time_left = timeout_when - now;
> > ? ? ? ? }
> >
> > ? ? ? ? retval = poll(pollfds, n_pollfds, time_left);
> > @@ -319,6 +327,7 @@ time_poll(struct pollfd *pollfds, int n_pollfds, int timeout)
> > ? ? }
> > ? ? last_wakeup = time_msec();
> > ? ? refresh_rusage();
> > + ? ?*elapsed = last_wakeup - start;
> > ? ? return retval;
> > ?}
> >
> > diff --git a/lib/timeval.h b/lib/timeval.h
> > index 517524c..e57f7ac 100644
> > --- a/lib/timeval.h
> > +++ b/lib/timeval.h
> > @@ -55,7 +55,8 @@ long long int time_wall_msec(void);
> > ?void time_timespec(struct timespec *);
> > ?void time_wall_timespec(struct timespec *);
> > ?void time_alarm(unsigned int secs);
> > -int time_poll(struct pollfd *, int n_pollfds, int timeout);
> > +int time_poll(struct pollfd *, int n_pollfds, long long int timeout_when,
> > + ? ? ? ? ? ? ?int *elapsed);
> >
> > ?long long int timespec_to_msec(const struct timespec *);
> > ?long long int timeval_to_msec(const struct timeval *);
> > --
> > 1.7.4.4
> >
> > _______________________________________________
> > dev mailing list
> > dev at openvswitch.org
> > http://openvswitch.org/mailman/listinfo/dev
More information about the dev
mailing list