Lines Matching +full:wakeup +full:- +full:counter
1 // SPDX-License-Identifier: GPL-2.0-only
36 * wakeup is performed on "wqh". If EFD_SEMAPHORE flag was not
39 * also, adds to the "count" counter and issue a wakeup.
52 * through waitqueue wakeup handlers. If the caller users potentially in eventfd_signal_mask()
53 * nested waitqueues with custom wakeup handlers, then it should in eventfd_signal_mask()
58 if (WARN_ON_ONCE(current->in_eventfd)) in eventfd_signal_mask()
61 spin_lock_irqsave(&ctx->wqh.lock, flags); in eventfd_signal_mask()
62 current->in_eventfd = 1; in eventfd_signal_mask()
63 if (ULLONG_MAX - ctx->count < n) in eventfd_signal_mask()
64 n = ULLONG_MAX - ctx->count; in eventfd_signal_mask()
65 ctx->count += n; in eventfd_signal_mask()
66 if (waitqueue_active(&ctx->wqh)) in eventfd_signal_mask()
67 wake_up_locked_poll(&ctx->wqh, EPOLLIN | mask); in eventfd_signal_mask()
68 current->in_eventfd = 0; in eventfd_signal_mask()
69 spin_unlock_irqrestore(&ctx->wqh.lock, flags); in eventfd_signal_mask()
75 * eventfd_signal - Adds @n to the eventfd counter.
77 * @n: [in] Value of the counter to be added to the eventfd internal counter.
81 * allow sleeping. In this function we allow the counter to reach the ULLONG_MAX
85 * Returns the amount by which the counter was incremented. This will be less
86 * than @n if the counter has overflowed.
96 if (ctx->id >= 0) in eventfd_free_ctx()
97 ida_simple_remove(&eventfd_ida, ctx->id); in eventfd_free_ctx()
109 * eventfd_ctx_put - Releases a reference to the internal eventfd context.
117 kref_put(&ctx->kref, eventfd_free); in eventfd_ctx_put()
123 struct eventfd_ctx *ctx = file->private_data; in eventfd_release()
125 wake_up_poll(&ctx->wqh, EPOLLHUP); in eventfd_release()
132 struct eventfd_ctx *ctx = file->private_data; in eventfd_poll()
136 poll_wait(file, &ctx->wqh, wait); in eventfd_poll()
139 * All writes to ctx->count occur within ctx->wqh.lock. This read in eventfd_poll()
140 * can be done outside ctx->wqh.lock because we know that poll_wait in eventfd_poll()
149 * ----------------- ------------ in eventfd_poll()
150 * lock ctx->wqh.lock (in poll_wait) in eventfd_poll()
151 * count = ctx->count in eventfd_poll()
153 * unlock ctx->wqh.lock in eventfd_poll()
154 * lock ctx->qwh.lock in eventfd_poll()
155 * ctx->count += n in eventfd_poll()
158 * unlock ctx->qwh.lock in eventfd_poll()
161 * but the following, which would miss a wakeup, cannot happen: in eventfd_poll()
164 * ----------------- ------------ in eventfd_poll()
165 * count = ctx->count (INVALID!) in eventfd_poll()
166 * lock ctx->qwh.lock in eventfd_poll()
167 * ctx->count += n in eventfd_poll()
170 * unlock ctx->qwh.lock in eventfd_poll()
171 * lock ctx->wqh.lock (in poll_wait) in eventfd_poll()
173 * unlock ctx->wqh.lock in eventfd_poll()
176 count = READ_ONCE(ctx->count); in eventfd_poll()
182 if (ULLONG_MAX - 1 > count) in eventfd_poll()
190 lockdep_assert_held(&ctx->wqh.lock); in eventfd_ctx_do_read()
192 *cnt = ((ctx->flags & EFD_SEMAPHORE) && ctx->count) ? 1 : ctx->count; in eventfd_ctx_do_read()
193 ctx->count -= *cnt; in eventfd_ctx_do_read()
198 * eventfd_ctx_remove_wait_queue - Read the current counter and removes wait queue.
201 * @cnt: [out] Pointer to the 64-bit counter value.
205 * -EAGAIN : The operation would have blocked.
208 * queue head, and read/reset the counter value.
215 spin_lock_irqsave(&ctx->wqh.lock, flags); in eventfd_ctx_remove_wait_queue()
217 __remove_wait_queue(&ctx->wqh, wait); in eventfd_ctx_remove_wait_queue()
218 if (*cnt != 0 && waitqueue_active(&ctx->wqh)) in eventfd_ctx_remove_wait_queue()
219 wake_up_locked_poll(&ctx->wqh, EPOLLOUT); in eventfd_ctx_remove_wait_queue()
220 spin_unlock_irqrestore(&ctx->wqh.lock, flags); in eventfd_ctx_remove_wait_queue()
222 return *cnt != 0 ? 0 : -EAGAIN; in eventfd_ctx_remove_wait_queue()
228 struct file *file = iocb->ki_filp; in eventfd_read()
229 struct eventfd_ctx *ctx = file->private_data; in eventfd_read()
233 return -EINVAL; in eventfd_read()
234 spin_lock_irq(&ctx->wqh.lock); in eventfd_read()
235 if (!ctx->count) { in eventfd_read()
236 if ((file->f_flags & O_NONBLOCK) || in eventfd_read()
237 (iocb->ki_flags & IOCB_NOWAIT)) { in eventfd_read()
238 spin_unlock_irq(&ctx->wqh.lock); in eventfd_read()
239 return -EAGAIN; in eventfd_read()
242 if (wait_event_interruptible_locked_irq(ctx->wqh, ctx->count)) { in eventfd_read()
243 spin_unlock_irq(&ctx->wqh.lock); in eventfd_read()
244 return -ERESTARTSYS; in eventfd_read()
248 current->in_eventfd = 1; in eventfd_read()
249 if (waitqueue_active(&ctx->wqh)) in eventfd_read()
250 wake_up_locked_poll(&ctx->wqh, EPOLLOUT); in eventfd_read()
251 current->in_eventfd = 0; in eventfd_read()
252 spin_unlock_irq(&ctx->wqh.lock); in eventfd_read()
254 return -EFAULT; in eventfd_read()
262 struct eventfd_ctx *ctx = file->private_data; in eventfd_write()
267 return -EINVAL; in eventfd_write()
269 return -EFAULT; in eventfd_write()
271 return -EINVAL; in eventfd_write()
272 spin_lock_irq(&ctx->wqh.lock); in eventfd_write()
273 res = -EAGAIN; in eventfd_write()
274 if (ULLONG_MAX - ctx->count > ucnt) in eventfd_write()
276 else if (!(file->f_flags & O_NONBLOCK)) { in eventfd_write()
277 res = wait_event_interruptible_locked_irq(ctx->wqh, in eventfd_write()
278 ULLONG_MAX - ctx->count > ucnt); in eventfd_write()
283 ctx->count += ucnt; in eventfd_write()
284 current->in_eventfd = 1; in eventfd_write()
285 if (waitqueue_active(&ctx->wqh)) in eventfd_write()
286 wake_up_locked_poll(&ctx->wqh, EPOLLIN); in eventfd_write()
287 current->in_eventfd = 0; in eventfd_write()
289 spin_unlock_irq(&ctx->wqh.lock); in eventfd_write()
297 struct eventfd_ctx *ctx = f->private_data; in eventfd_show_fdinfo()
299 spin_lock_irq(&ctx->wqh.lock); in eventfd_show_fdinfo()
300 seq_printf(m, "eventfd-count: %16llx\n", in eventfd_show_fdinfo()
301 (unsigned long long)ctx->count); in eventfd_show_fdinfo()
302 spin_unlock_irq(&ctx->wqh.lock); in eventfd_show_fdinfo()
303 seq_printf(m, "eventfd-id: %d\n", ctx->id); in eventfd_show_fdinfo()
304 seq_printf(m, "eventfd-semaphore: %d\n", in eventfd_show_fdinfo()
305 !!(ctx->flags & EFD_SEMAPHORE)); in eventfd_show_fdinfo()
321 * eventfd_fget - Acquire a reference of an eventfd file descriptor.
327 * -EBADF : Invalid @fd file descriptor.
328 * -EINVAL : The @fd file descriptor is not an eventfd file.
336 return ERR_PTR(-EBADF); in eventfd_fget()
337 if (file->f_op != &eventfd_fops) { in eventfd_fget()
339 return ERR_PTR(-EINVAL); in eventfd_fget()
347 * eventfd_ctx_fdget - Acquires a reference to the internal eventfd context.
360 return ERR_PTR(-EBADF); in eventfd_ctx_fdget()
368 * eventfd_ctx_fileget - Acquires a reference to the internal eventfd context.
374 * -EINVAL : The @fd file descriptor is not an eventfd file.
380 if (file->f_op != &eventfd_fops) in eventfd_ctx_fileget()
381 return ERR_PTR(-EINVAL); in eventfd_ctx_fileget()
383 ctx = file->private_data; in eventfd_ctx_fileget()
384 kref_get(&ctx->kref); in eventfd_ctx_fileget()
400 return -EINVAL; in do_eventfd()
404 return -ENOMEM; in do_eventfd()
406 kref_init(&ctx->kref); in do_eventfd()
407 init_waitqueue_head(&ctx->wqh); in do_eventfd()
408 ctx->count = count; in do_eventfd()
409 ctx->flags = flags; in do_eventfd()
410 ctx->id = ida_simple_get(&eventfd_ida, 0, 0, GFP_KERNEL); in do_eventfd()
425 file->f_mode |= FMODE_NOWAIT; in do_eventfd()