• Home
  • Raw
  • Download

Lines Matching +full:wakeup +full:- +full:counter

1 // SPDX-License-Identifier: GPL-2.0-only
38 * wakeup is performed on "wqh". A read(2) will return the "count"
40 * side eventfd_signal() also, adds to the "count" counter and
41 * issue a wakeup.
54 * through waitqueue wakeup handlers. If the caller users potentially in eventfd_signal_mask()
55 * nested waitqueues with custom wakeup handlers, then it should in eventfd_signal_mask()
63 spin_lock_irqsave(&ctx->wqh.lock, flags); in eventfd_signal_mask()
65 if (ULLONG_MAX - ctx->count < n) in eventfd_signal_mask()
66 n = ULLONG_MAX - ctx->count; in eventfd_signal_mask()
67 ctx->count += n; in eventfd_signal_mask()
68 if (waitqueue_active(&ctx->wqh)) in eventfd_signal_mask()
69 wake_up_locked_poll(&ctx->wqh, EPOLLIN | mask); in eventfd_signal_mask()
71 spin_unlock_irqrestore(&ctx->wqh.lock, flags); in eventfd_signal_mask()
77 * eventfd_signal - Adds @n to the eventfd counter.
79 * @n: [in] Value of the counter to be added to the eventfd internal counter.
83 * allow sleeping. In this function we allow the counter to reach the ULLONG_MAX
87 * Returns the amount by which the counter was incremented. This will be less
88 * than @n if the counter has overflowed.
98 if (ctx->id >= 0) in eventfd_free_ctx()
99 ida_simple_remove(&eventfd_ida, ctx->id); in eventfd_free_ctx()
111 * eventfd_ctx_put - Releases a reference to the internal eventfd context.
119 kref_put(&ctx->kref, eventfd_free); in eventfd_ctx_put()
125 struct eventfd_ctx *ctx = file->private_data; in eventfd_release()
127 wake_up_poll(&ctx->wqh, EPOLLHUP); in eventfd_release()
134 struct eventfd_ctx *ctx = file->private_data; in eventfd_poll()
138 poll_wait(file, &ctx->wqh, wait); in eventfd_poll()
141 * All writes to ctx->count occur within ctx->wqh.lock. This read in eventfd_poll()
142 * can be done outside ctx->wqh.lock because we know that poll_wait in eventfd_poll()
151 * ----------------- ------------ in eventfd_poll()
152 * lock ctx->wqh.lock (in poll_wait) in eventfd_poll()
153 * count = ctx->count in eventfd_poll()
155 * unlock ctx->wqh.lock in eventfd_poll()
156 * lock ctx->qwh.lock in eventfd_poll()
157 * ctx->count += n in eventfd_poll()
160 * unlock ctx->qwh.lock in eventfd_poll()
163 * but the following, which would miss a wakeup, cannot happen: in eventfd_poll()
166 * ----------------- ------------ in eventfd_poll()
167 * count = ctx->count (INVALID!) in eventfd_poll()
168 * lock ctx->qwh.lock in eventfd_poll()
169 * ctx->count += n in eventfd_poll()
172 * unlock ctx->qwh.lock in eventfd_poll()
173 * lock ctx->wqh.lock (in poll_wait) in eventfd_poll()
175 * unlock ctx->wqh.lock in eventfd_poll()
178 count = READ_ONCE(ctx->count); in eventfd_poll()
184 if (ULLONG_MAX - 1 > count) in eventfd_poll()
192 lockdep_assert_held(&ctx->wqh.lock); in eventfd_ctx_do_read()
194 *cnt = ((ctx->flags & EFD_SEMAPHORE) && ctx->count) ? 1 : ctx->count; in eventfd_ctx_do_read()
195 ctx->count -= *cnt; in eventfd_ctx_do_read()
200 * eventfd_ctx_remove_wait_queue - Read the current counter and removes wait queue.
203 * @cnt: [out] Pointer to the 64-bit counter value.
207 * -EAGAIN : The operation would have blocked.
210 * queue head, and read/reset the counter value.
217 spin_lock_irqsave(&ctx->wqh.lock, flags); in eventfd_ctx_remove_wait_queue()
219 __remove_wait_queue(&ctx->wqh, wait); in eventfd_ctx_remove_wait_queue()
220 if (*cnt != 0 && waitqueue_active(&ctx->wqh)) in eventfd_ctx_remove_wait_queue()
221 wake_up_locked_poll(&ctx->wqh, EPOLLOUT); in eventfd_ctx_remove_wait_queue()
222 spin_unlock_irqrestore(&ctx->wqh.lock, flags); in eventfd_ctx_remove_wait_queue()
224 return *cnt != 0 ? 0 : -EAGAIN; in eventfd_ctx_remove_wait_queue()
230 struct file *file = iocb->ki_filp; in eventfd_read()
231 struct eventfd_ctx *ctx = file->private_data; in eventfd_read()
236 return -EINVAL; in eventfd_read()
237 spin_lock_irq(&ctx->wqh.lock); in eventfd_read()
238 if (!ctx->count) { in eventfd_read()
239 if ((file->f_flags & O_NONBLOCK) || in eventfd_read()
240 (iocb->ki_flags & IOCB_NOWAIT)) { in eventfd_read()
241 spin_unlock_irq(&ctx->wqh.lock); in eventfd_read()
242 return -EAGAIN; in eventfd_read()
244 __add_wait_queue(&ctx->wqh, &wait); in eventfd_read()
247 if (ctx->count) in eventfd_read()
250 __remove_wait_queue(&ctx->wqh, &wait); in eventfd_read()
252 spin_unlock_irq(&ctx->wqh.lock); in eventfd_read()
253 return -ERESTARTSYS; in eventfd_read()
255 spin_unlock_irq(&ctx->wqh.lock); in eventfd_read()
257 spin_lock_irq(&ctx->wqh.lock); in eventfd_read()
259 __remove_wait_queue(&ctx->wqh, &wait); in eventfd_read()
263 if (waitqueue_active(&ctx->wqh)) in eventfd_read()
264 wake_up_locked_poll(&ctx->wqh, EPOLLOUT); in eventfd_read()
265 spin_unlock_irq(&ctx->wqh.lock); in eventfd_read()
267 return -EFAULT; in eventfd_read()
275 struct eventfd_ctx *ctx = file->private_data; in eventfd_write()
281 return -EINVAL; in eventfd_write()
283 return -EFAULT; in eventfd_write()
285 return -EINVAL; in eventfd_write()
286 spin_lock_irq(&ctx->wqh.lock); in eventfd_write()
287 res = -EAGAIN; in eventfd_write()
288 if (ULLONG_MAX - ctx->count > ucnt) in eventfd_write()
290 else if (!(file->f_flags & O_NONBLOCK)) { in eventfd_write()
291 __add_wait_queue(&ctx->wqh, &wait); in eventfd_write()
294 if (ULLONG_MAX - ctx->count > ucnt) { in eventfd_write()
299 res = -ERESTARTSYS; in eventfd_write()
302 spin_unlock_irq(&ctx->wqh.lock); in eventfd_write()
304 spin_lock_irq(&ctx->wqh.lock); in eventfd_write()
306 __remove_wait_queue(&ctx->wqh, &wait); in eventfd_write()
310 ctx->count += ucnt; in eventfd_write()
311 if (waitqueue_active(&ctx->wqh)) in eventfd_write()
312 wake_up_locked_poll(&ctx->wqh, EPOLLIN); in eventfd_write()
314 spin_unlock_irq(&ctx->wqh.lock); in eventfd_write()
322 struct eventfd_ctx *ctx = f->private_data; in eventfd_show_fdinfo()
324 spin_lock_irq(&ctx->wqh.lock); in eventfd_show_fdinfo()
325 seq_printf(m, "eventfd-count: %16llx\n", in eventfd_show_fdinfo()
326 (unsigned long long)ctx->count); in eventfd_show_fdinfo()
327 spin_unlock_irq(&ctx->wqh.lock); in eventfd_show_fdinfo()
328 seq_printf(m, "eventfd-id: %d\n", ctx->id); in eventfd_show_fdinfo()
344 * eventfd_fget - Acquire a reference of an eventfd file descriptor.
350 * -EBADF : Invalid @fd file descriptor.
351 * -EINVAL : The @fd file descriptor is not an eventfd file.
359 return ERR_PTR(-EBADF); in eventfd_fget()
360 if (file->f_op != &eventfd_fops) { in eventfd_fget()
362 return ERR_PTR(-EINVAL); in eventfd_fget()
370 * eventfd_ctx_fdget - Acquires a reference to the internal eventfd context.
383 return ERR_PTR(-EBADF); in eventfd_ctx_fdget()
391 * eventfd_ctx_fileget - Acquires a reference to the internal eventfd context.
397 * -EINVAL : The @fd file descriptor is not an eventfd file.
403 if (file->f_op != &eventfd_fops) in eventfd_ctx_fileget()
404 return ERR_PTR(-EINVAL); in eventfd_ctx_fileget()
406 ctx = file->private_data; in eventfd_ctx_fileget()
407 kref_get(&ctx->kref); in eventfd_ctx_fileget()
423 return -EINVAL; in do_eventfd()
427 return -ENOMEM; in do_eventfd()
429 kref_init(&ctx->kref); in do_eventfd()
430 init_waitqueue_head(&ctx->wqh); in do_eventfd()
431 ctx->count = count; in do_eventfd()
432 ctx->flags = flags; in do_eventfd()
433 ctx->id = ida_simple_get(&eventfd_ida, 0, 0, GFP_KERNEL); in do_eventfd()
448 file->f_mode |= FMODE_NOWAIT; in do_eventfd()