lkml.org 
[lkml]   [2020]   [Nov]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v4 1/4] epoll: convert internal api to timespec64
    Date
    From: Willem de Bruijn <willemb@google.com>

    Make epoll more consistent with select/poll: pass along the timeout as
    timespec64 pointer.

    In anticipation of additional changes affecting all three polling
    mechanisms:

    - add epoll_pwait2 syscall with timespec semantics,
    and share poll_select_set_timeout implementation.
    - compute slack before conversion to absolute time,
    to save one ktime_get_ts64 call.

    Signed-off-by: Willem de Bruijn <willemb@google.com>
    ---
    fs/eventpoll.c | 57 ++++++++++++++++++++++++++++++++------------------
    1 file changed, 37 insertions(+), 20 deletions(-)

    diff --git a/fs/eventpoll.c b/fs/eventpoll.c
    index 297aeb0ee9d1..7082dfbc3166 100644
    --- a/fs/eventpoll.c
    +++ b/fs/eventpoll.c
    @@ -1714,15 +1714,25 @@ static int ep_send_events(struct eventpoll *ep,
    return res;
    }

    -static inline struct timespec64 ep_set_mstimeout(long ms)
    +static struct timespec64 *ep_timeout_to_timespec(struct timespec64 *to, long ms)
    {
    - struct timespec64 now, ts = {
    - .tv_sec = ms / MSEC_PER_SEC,
    - .tv_nsec = NSEC_PER_MSEC * (ms % MSEC_PER_SEC),
    - };
    + struct timespec64 now;
    +
    + if (ms < 0)
    + return NULL;
    +
    + if (!ms) {
    + to->tv_sec = 0;
    + to->tv_nsec = 0;
    + return to;
    + }
    +
    + to->tv_sec = ms / MSEC_PER_SEC;
    + to->tv_nsec = NSEC_PER_MSEC * (ms % MSEC_PER_SEC);

    ktime_get_ts64(&now);
    - return timespec64_add_safe(now, ts);
    + *to = timespec64_add_safe(now, *to);
    + return to;
    }

    /**
    @@ -1734,8 +1744,8 @@ static inline struct timespec64 ep_set_mstimeout(long ms)
    * stored.
    * @maxevents: Size (in terms of number of events) of the caller event buffer.
    * @timeout: Maximum timeout for the ready events fetch operation, in
    - * milliseconds. If the @timeout is zero, the function will not block,
    - * while if the @timeout is less than zero, the function will block
    + * timespec. If the timeout is zero, the function will not block,
    + * while if the @timeout ptr is NULL, the function will block
    * until at least one event has been retrieved (or an error
    * occurred).
    *
    @@ -1743,7 +1753,7 @@ static inline struct timespec64 ep_set_mstimeout(long ms)
    * error code, in case of error.
    */
    static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,
    - int maxevents, long timeout)
    + int maxevents, struct timespec64 *timeout)
    {
    int res, eavail, timed_out = 0;
    u64 slack = 0;
    @@ -1752,13 +1762,11 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,

    lockdep_assert_irqs_enabled();

    - if (timeout > 0) {
    - struct timespec64 end_time = ep_set_mstimeout(timeout);
    -
    - slack = select_estimate_accuracy(&end_time);
    + if (timeout && (timeout->tv_sec | timeout->tv_nsec)) {
    + slack = select_estimate_accuracy(timeout);
    to = &expires;
    - *to = timespec64_to_ktime(end_time);
    - } else if (timeout == 0) {
    + *to = timespec64_to_ktime(*timeout);
    + } else if (timeout) {
    /*
    * Avoid the unnecessary trip to the wait queue loop, if the
    * caller specified a non blocking operation.
    @@ -2177,7 +2185,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
    * part of the user space epoll_wait(2).
    */
    static int do_epoll_wait(int epfd, struct epoll_event __user *events,
    - int maxevents, int timeout)
    + int maxevents, struct timespec64 *to)
    {
    int error;
    struct fd f;
    @@ -2211,7 +2219,7 @@ static int do_epoll_wait(int epfd, struct epoll_event __user *events,
    ep = f.file->private_data;

    /* Time to fish for events ... */
    - error = ep_poll(ep, events, maxevents, timeout);
    + error = ep_poll(ep, events, maxevents, to);

    error_fput:
    fdput(f);
    @@ -2221,7 +2229,10 @@ static int do_epoll_wait(int epfd, struct epoll_event __user *events,
    SYSCALL_DEFINE4(epoll_wait, int, epfd, struct epoll_event __user *, events,
    int, maxevents, int, timeout)
    {
    - return do_epoll_wait(epfd, events, maxevents, timeout);
    + struct timespec64 to;
    +
    + return do_epoll_wait(epfd, events, maxevents,
    + ep_timeout_to_timespec(&to, timeout));
    }

    /*
    @@ -2232,6 +2243,7 @@ SYSCALL_DEFINE6(epoll_pwait, int, epfd, struct epoll_event __user *, events,
    int, maxevents, int, timeout, const sigset_t __user *, sigmask,
    size_t, sigsetsize)
    {
    + struct timespec64 to;
    int error;

    /*
    @@ -2242,7 +2254,9 @@ SYSCALL_DEFINE6(epoll_pwait, int, epfd, struct epoll_event __user *, events,
    if (error)
    return error;

    - error = do_epoll_wait(epfd, events, maxevents, timeout);
    + error = do_epoll_wait(epfd, events, maxevents,
    + ep_timeout_to_timespec(&to, timeout));
    +
    restore_saved_sigmask_unless(error == -EINTR);

    return error;
    @@ -2255,6 +2269,7 @@ COMPAT_SYSCALL_DEFINE6(epoll_pwait, int, epfd,
    const compat_sigset_t __user *, sigmask,
    compat_size_t, sigsetsize)
    {
    + struct timespec64 to;
    long err;

    /*
    @@ -2265,7 +2280,9 @@ COMPAT_SYSCALL_DEFINE6(epoll_pwait, int, epfd,
    if (err)
    return err;

    - err = do_epoll_wait(epfd, events, maxevents, timeout);
    + err = do_epoll_wait(epfd, events, maxevents,
    + ep_timeout_to_timespec(&to, timeout));
    +
    restore_saved_sigmask_unless(err == -EINTR);

    return err;
    --
    2.29.2.454.gaff20da3a2-goog
    \
     
     \ /
      Last update: 2020-11-21 15:46    [W:2.608 / U:0.016 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site