lkml.org 
[lkml]   [2009]   [Aug]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    SubjectRe: [PATCH 0/2] eventfd: new EFD_STATE flag
    On Wed, 26 Aug 2009, Davide Libenzi wrote:

    > > I see no kernel equivalent to read(), but that's easily done.
    >
    > Adding an in-kernel read based on "ctx", that is no problem at all.

    Something like the untested below.
    I had thought you said the eventfd readers where in userspace, but I might
    have misunderstood you.



    - Davide



    ---
    fs/eventfd.c | 51 +++++++++++++++++++++++++++++++++---------------
    include/linux/eventfd.h | 7 ++++++
    2 files changed, 43 insertions(+), 15 deletions(-)

    Index: linux-2.6.mod/fs/eventfd.c
    ===================================================================
    --- linux-2.6.mod.orig/fs/eventfd.c 2009-08-26 15:58:03.000000000 -0700
    +++ linux-2.6.mod/fs/eventfd.c 2009-08-26 16:20:03.000000000 -0700
    @@ -130,26 +130,33 @@ static unsigned int eventfd_poll(struct
    return events;
    }

    -static ssize_t eventfd_read(struct file *file, char __user *buf, size_t count,
    - loff_t *ppos)
    +/**
    + * eventfd_ctx_read - Reads the eventfd counter or wait if it is zero.
    + * @ctx: [in] Pointer to eventfd context.
    + * @no_wait: [in] Different from zero if the operation should not block.
    + * @cnt: [out] Pointer to the 64bit conter value.
    + *
    + * Returns zero if successful, or the following error codes:
    + *
    + * -EAGAIN : The operation would have blocked but @no_wait was nonzero.
    + * -ERESTARTSYS : A signal interrupted the wait operation.
    + */
    +ssize_t eventfd_ctx_read(struct eventfd_ctx *ctx, int no_wait, __u64 *cnt)
    {
    - struct eventfd_ctx *ctx = file->private_data;
    ssize_t res;
    - __u64 ucnt = 0;
    DECLARE_WAITQUEUE(wait, current);

    - if (count < sizeof(ucnt))
    - return -EINVAL;
    spin_lock_irq(&ctx->wqh.lock);
    + *cnt = 0;
    res = -EAGAIN;
    if (ctx->count > 0)
    - res = sizeof(ucnt);
    - else if (!(file->f_flags & O_NONBLOCK)) {
    + res = 0;
    + else if (!no_wait) {
    __add_wait_queue(&ctx->wqh, &wait);
    - for (res = 0;;) {
    + for (;;) {
    set_current_state(TASK_INTERRUPTIBLE);
    if (ctx->count > 0) {
    - res = sizeof(ucnt);
    + res = 0;
    break;
    }
    if (signal_pending(current)) {
    @@ -163,18 +170,32 @@ static ssize_t eventfd_read(struct file
    __remove_wait_queue(&ctx->wqh, &wait);
    __set_current_state(TASK_RUNNING);
    }
    - if (likely(res > 0)) {
    - ucnt = (ctx->flags & EFD_SEMAPHORE) ? 1 : ctx->count;
    - ctx->count -= ucnt;
    + if (likely(res == 0)) {
    + *cnt = (ctx->flags & EFD_SEMAPHORE) ? 1 : ctx->count;
    + ctx->count -= *cnt;
    if (waitqueue_active(&ctx->wqh))
    wake_up_locked_poll(&ctx->wqh, POLLOUT);
    }
    spin_unlock_irq(&ctx->wqh.lock);
    - if (res > 0 && put_user(ucnt, (__u64 __user *) buf))
    - return -EFAULT;

    return res;
    }
    +EXPORT_SYMBOL_GPL(eventfd_ctx_read);
    +
    +static ssize_t eventfd_read(struct file *file, char __user *buf, size_t count,
    + loff_t *ppos)
    +{
    + struct eventfd_ctx *ctx = file->private_data;
    + ssize_t res;
    + __u64 cnt;
    +
    + if (count < sizeof(cnt))
    + return -EINVAL;
    + if ((res = eventfd_ctx_read(ctx, file->f_flags & O_NONBLOCK, &cnt)) < 0)
    + return res;
    +
    + return put_user(cnt, (__u64 __user *) buf) ? -EFAULT: sizeof(cnt);
    +}

    static ssize_t eventfd_write(struct file *file, const char __user *buf, size_t count,
    loff_t *ppos)
    Index: linux-2.6.mod/include/linux/eventfd.h
    ===================================================================
    --- linux-2.6.mod.orig/include/linux/eventfd.h 2009-08-26 15:58:03.000000000 -0700
    +++ linux-2.6.mod/include/linux/eventfd.h 2009-08-26 16:17:01.000000000 -0700
    @@ -33,6 +33,7 @@ struct file *eventfd_fget(int fd);
    struct eventfd_ctx *eventfd_ctx_fdget(int fd);
    struct eventfd_ctx *eventfd_ctx_fileget(struct file *file);
    int eventfd_signal(struct eventfd_ctx *ctx, int n);
    +ssize_t eventfd_ctx_read(struct eventfd_ctx *ctx, int no_wait, __u64 *cnt);

    #else /* CONFIG_EVENTFD */

    @@ -55,6 +56,12 @@ static inline void eventfd_ctx_put(struc

    }

    +static inline ssize_t eventfd_ctx_read(struct eventfd_ctx *ctx, int no_wait,
    + __u64 *cnt)
    +{
    + return -ENOSYS;
    +}
    +
    #endif

    #endif /* _LINUX_EVENTFD_H */

    \
     
     \ /
      Last update: 2009-08-27 01:33    [W:0.027 / U:92.632 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site