12 #include <linux/poll.h>
15 #include <linux/sched.h>
16 #include <linux/kernel.h>
17 #include <linux/slab.h>
18 #include <linux/list.h>
20 #include <linux/time.h>
21 #include <linux/hrtimer.h>
57 spin_unlock_irqrestore(&ctx->
wqh.
lock, flags);
75 list_for_each_entry_rcu(ctx, &cancel_list,
clist) {
84 spin_unlock_irqrestore(&ctx->
wqh.
lock, flags);
93 spin_lock(&cancel_lock);
94 list_del_rcu(&ctx->
clist);
95 spin_unlock(&cancel_lock);
99 static bool timerfd_canceled(
struct timerfd_ctx *ctx)
113 spin_lock(&cancel_lock);
114 list_add_rcu(&ctx->
clist, &cancel_list);
115 spin_unlock(&cancel_lock);
118 timerfd_remove_cancel(ctx);
126 remaining = hrtimer_expires_remaining(&ctx->
tmr);
127 return remaining.
tv64 < 0 ? ktime_set(0, 0): remaining;
130 static int timerfd_setup(
struct timerfd_ctx *ctx,
int flags,
140 texp = timespec_to_ktime(ktmr->
it_value);
145 hrtimer_set_expires(&ctx->
tmr, texp);
146 ctx->
tmr.function = timerfd_tmrproc;
147 if (texp.
tv64 != 0) {
149 if (timerfd_canceled(ctx))
159 timerfd_remove_cancel(ctx);
171 poll_wait(file, &ctx->
wqh, wait);
176 spin_unlock_irqrestore(&ctx->
wqh.
lock, flags);
181 static ssize_t timerfd_read(
struct file *file,
char __user *
buf,
size_t count,
188 if (count <
sizeof(ticks))
201 if (timerfd_canceled(ctx)) {
217 ticks += hrtimer_forward_now(&ctx->
tmr,
224 spin_unlock_irq(&ctx->
wqh.
lock);
231 .release = timerfd_release,
232 .poll = timerfd_poll,
233 .read = timerfd_read,
237 static int timerfd_fget(
int fd,
struct fd *
p)
239 struct fd
f = fdget(fd);
242 if (f.
file->f_op != &timerfd_fops) {
298 ret = timerfd_fget(ufd, &f);
301 ctx = f.
file->private_data;
303 timerfd_setup_cancel(ctx, flags);
313 spin_unlock_irq(&ctx->
wqh.
lock);
324 hrtimer_forward_now(&ctx->
tmr, ctx->
tintv);
326 kotmr.
it_value = ktime_to_timespec(timerfd_get_remaining(ctx));
332 ret = timerfd_setup(ctx, flags, &ktmr);
334 spin_unlock_irq(&ctx->
wqh.
lock);
347 int ret = timerfd_fget(ufd, &f);
350 ctx = f.
file->private_data;
356 hrtimer_forward_now(&ctx->
tmr, ctx->
tintv) - 1;
359 kotmr.
it_value = ktime_to_timespec(timerfd_get_remaining(ctx));
361 spin_unlock_irq(&ctx->
wqh.
lock);