Re: [take8 2/2] kevent: poll/select() notifications. Timer notifications.

Andrew Morton
2006-08-11T15:45:53Z

On Fri, 11 Aug 2006 12:40:10 +0400
Evgeniy Polyakov <johnpol@2ka.mipt.ru> wrote:

>
> poll/select() notifications. Timer notifications.
>
> This patch includes generic poll/select and timer notifications.
>
> kevent_poll works simialr to epoll and has the same issues (callback
> is invoked not from internal state machine of the caller, but through
> process awake).
>
> Timer notifications can be used for fine grained per-process time
> management, since interval timers are very inconvenient to use,
> and they are limited.
>
> ...
>
> +static struct lock_class_key kevent_poll_key;
> +
> +void kevent_poll_reinit(struct file *file)
> +{
> + lockdep_set_class(&file->st.lock, &kevent_poll_key);
> +}

Why is this necessary?

> +#include <linux/kernel.h>
> +#include <linux/types.h>
> +#include <linux/list.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +#include <linux/timer.h>
> +#include <linux/jiffies.h>
> +#include <linux/kevent.h>
> +
> +static void kevent_timer_func(unsigned long data)
> +{
> + struct kevent *k = (struct kevent *)data;
> + struct timer_list *t = k->st->origin;
> +
> + kevent_storage_ready(k->st, NULL, KEVENT_MASK_ALL);
> + mod_timer(t, jiffies + msecs_to_jiffies(k->event.id.raw[0]));
> +}
> +
> +static struct lock_class_key kevent_timer_key;
> +
> +static int kevent_timer_enqueue(struct kevent *k)
> +{
> + struct timer_list *t;
> + struct kevent_storage *st;
> + int err;
> +
> + t = kmalloc(sizeof(struct timer_list) + sizeof(struct kevent_storage),
> + GFP_KERNEL);
> + if (!t)
> + return -ENOMEM;
> +
> + init_timer(t);
> + t->function = kevent_timer_func;
> + t->expires = jiffies + msecs_to_jiffies(k->event.id.raw[0]);
> + t->data = (unsigned long)k;

setup_timer().

> + st = (struct kevent_storage *)(t+1);

It would be cleaner to create

struct <something> {
struct timer_list timer;
struct kevent_storage storage;
};

> + err = kevent_storage_init(t, st);
> + if (err)
> + goto err_out_free;
> + lockdep_set_class(&st->lock, &kevent_timer_key);

Why is this necesary?

> +
> + kevent_storage_dequeue(st, k);
> +
> + kfree(t);
> +
> + return 0;
> +}
> +
> +static int kevent_timer_callback(struct kevent *k)
> +{
> + struct kevent_storage *st = k->st;
> + struct timer_list *t = st->origin;
> +
> + if (!t)
> + return -ENODEV;
> +
> + k->event.ret_data[0] = (__u32)jiffies;

What does this do?

Does it expose jiffies to userspace?

It truncates jiffies on 64-bit machines.

> +late_initcall(kevent_init_timer);

module_init() would be more typical. If there was a reason for using
late_initcall(), that reason should be commented.