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.
47 * eventfd_signal_mask - Increment the event counter
52 * allow sleeping. In this function we allow the counter to reach the ULLONG_MAX
62 * through waitqueue wakeup handlers. If the caller users potentially in eventfd_signal_mask()
63 * nested waitqueues with custom wakeup handlers, then it should in eventfd_signal_mask()
68 if (WARN_ON_ONCE(current->in_eventfd)) in eventfd_signal_mask()
71 spin_lock_irqsave(&ctx->wqh.lock, flags); in eventfd_signal_mask()
72 current->in_eventfd = 1; in eventfd_signal_mask()
73 if (ctx->count < ULLONG_MAX) in eventfd_signal_mask()
74 ctx->count++; in eventfd_signal_mask()
75 if (waitqueue_active(&ctx->wqh)) in eventfd_signal_mask()
76 wake_up_locked_poll(&ctx->wqh, EPOLLIN | mask); in eventfd_signal_mask()
77 current->in_eventfd = 0; in eventfd_signal_mask()
78 spin_unlock_irqrestore(&ctx->wqh.lock, flags); in eventfd_signal_mask()
84 if (ctx->id >= 0) in eventfd_free_ctx()
85 ida_free(&eventfd_ida, ctx->id); in eventfd_free_ctx()
97 * eventfd_ctx_put - Releases a reference to the internal eventfd context.
105 kref_put(&ctx->kref, eventfd_free); in eventfd_ctx_put()
111 struct eventfd_ctx *ctx = file->private_data; in eventfd_release()
113 wake_up_poll(&ctx->wqh, EPOLLHUP); in eventfd_release()
120 struct eventfd_ctx *ctx = file->private_data; in eventfd_poll()
124 poll_wait(file, &ctx->wqh, wait); in eventfd_poll()
127 * All writes to ctx->count occur within ctx->wqh.lock. This read in eventfd_poll()
128 * can be done outside ctx->wqh.lock because we know that poll_wait in eventfd_poll()
137 * ----------------- ------------ in eventfd_poll()
138 * lock ctx->wqh.lock (in poll_wait) in eventfd_poll()
139 * count = ctx->count in eventfd_poll()
141 * unlock ctx->wqh.lock in eventfd_poll()
142 * lock ctx->qwh.lock in eventfd_poll()
143 * ctx->count += n in eventfd_poll()
146 * unlock ctx->qwh.lock in eventfd_poll()
149 * but the following, which would miss a wakeup, cannot happen: in eventfd_poll()
152 * ----------------- ------------ in eventfd_poll()
153 * count = ctx->count (INVALID!) 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()
159 * lock ctx->wqh.lock (in poll_wait) in eventfd_poll()
161 * unlock ctx->wqh.lock in eventfd_poll()
164 count = READ_ONCE(ctx->count); in eventfd_poll()
170 if (ULLONG_MAX - 1 > count) in eventfd_poll()
178 lockdep_assert_held(&ctx->wqh.lock); in eventfd_ctx_do_read()
180 *cnt = ((ctx->flags & EFD_SEMAPHORE) && ctx->count) ? 1 : ctx->count; in eventfd_ctx_do_read()
181 ctx->count -= *cnt; in eventfd_ctx_do_read()
186 * eventfd_ctx_remove_wait_queue - Read the current counter and removes wait queue.
189 * @cnt: [out] Pointer to the 64-bit counter value.
193 * -EAGAIN : The operation would have blocked.
196 * queue head, and read/reset the counter value.
203 spin_lock_irqsave(&ctx->wqh.lock, flags); in eventfd_ctx_remove_wait_queue()
205 __remove_wait_queue(&ctx->wqh, wait); in eventfd_ctx_remove_wait_queue()
206 if (*cnt != 0 && waitqueue_active(&ctx->wqh)) in eventfd_ctx_remove_wait_queue()
207 wake_up_locked_poll(&ctx->wqh, EPOLLOUT); in eventfd_ctx_remove_wait_queue()
208 spin_unlock_irqrestore(&ctx->wqh.lock, flags); in eventfd_ctx_remove_wait_queue()
210 return *cnt != 0 ? 0 : -EAGAIN; in eventfd_ctx_remove_wait_queue()
216 struct file *file = iocb->ki_filp; in eventfd_read()
217 struct eventfd_ctx *ctx = file->private_data; in eventfd_read()
221 return -EINVAL; in eventfd_read()
222 spin_lock_irq(&ctx->wqh.lock); in eventfd_read()
223 if (!ctx->count) { in eventfd_read()
224 if ((file->f_flags & O_NONBLOCK) || in eventfd_read()
225 (iocb->ki_flags & IOCB_NOWAIT)) { in eventfd_read()
226 spin_unlock_irq(&ctx->wqh.lock); in eventfd_read()
227 return -EAGAIN; in eventfd_read()
230 if (wait_event_interruptible_locked_irq(ctx->wqh, ctx->count)) { in eventfd_read()
231 spin_unlock_irq(&ctx->wqh.lock); in eventfd_read()
232 return -ERESTARTSYS; in eventfd_read()
236 current->in_eventfd = 1; in eventfd_read()
237 if (waitqueue_active(&ctx->wqh)) in eventfd_read()
238 wake_up_locked_poll(&ctx->wqh, EPOLLOUT); in eventfd_read()
239 current->in_eventfd = 0; in eventfd_read()
240 spin_unlock_irq(&ctx->wqh.lock); in eventfd_read()
242 return -EFAULT; in eventfd_read()
250 struct eventfd_ctx *ctx = file->private_data; in eventfd_write()
255 return -EINVAL; in eventfd_write()
257 return -EFAULT; in eventfd_write()
259 return -EINVAL; in eventfd_write()
260 spin_lock_irq(&ctx->wqh.lock); in eventfd_write()
261 res = -EAGAIN; in eventfd_write()
262 if (ULLONG_MAX - ctx->count > ucnt) in eventfd_write()
264 else if (!(file->f_flags & O_NONBLOCK)) { in eventfd_write()
265 res = wait_event_interruptible_locked_irq(ctx->wqh, in eventfd_write()
266 ULLONG_MAX - ctx->count > ucnt); in eventfd_write()
271 ctx->count += ucnt; in eventfd_write()
272 current->in_eventfd = 1; in eventfd_write()
273 if (waitqueue_active(&ctx->wqh)) in eventfd_write()
274 wake_up_locked_poll(&ctx->wqh, EPOLLIN); in eventfd_write()
275 current->in_eventfd = 0; in eventfd_write()
277 spin_unlock_irq(&ctx->wqh.lock); in eventfd_write()
285 struct eventfd_ctx *ctx = f->private_data; in eventfd_show_fdinfo()
288 spin_lock_irq(&ctx->wqh.lock); in eventfd_show_fdinfo()
289 cnt = ctx->count; in eventfd_show_fdinfo()
290 spin_unlock_irq(&ctx->wqh.lock); in eventfd_show_fdinfo()
293 "eventfd-count: %16llx\n" in eventfd_show_fdinfo()
294 "eventfd-id: %d\n" in eventfd_show_fdinfo()
295 "eventfd-semaphore: %d\n", in eventfd_show_fdinfo()
297 ctx->id, in eventfd_show_fdinfo()
298 !!(ctx->flags & EFD_SEMAPHORE)); in eventfd_show_fdinfo()
314 * eventfd_fget - Acquire a reference of an eventfd file descriptor.
320 * -EBADF : Invalid @fd file descriptor.
321 * -EINVAL : The @fd file descriptor is not an eventfd file.
329 return ERR_PTR(-EBADF); in eventfd_fget()
330 if (file->f_op != &eventfd_fops) { in eventfd_fget()
332 return ERR_PTR(-EINVAL); in eventfd_fget()
340 * eventfd_ctx_fdget - Acquires a reference to the internal eventfd context.
352 return ERR_PTR(-EBADF); in eventfd_ctx_fdget()
358 * eventfd_ctx_fileget - Acquires a reference to the internal eventfd context.
364 * -EINVAL : The @fd file descriptor is not an eventfd file.
370 if (file->f_op != &eventfd_fops) in eventfd_ctx_fileget()
371 return ERR_PTR(-EINVAL); in eventfd_ctx_fileget()
373 ctx = file->private_data; in eventfd_ctx_fileget()
374 kref_get(&ctx->kref); in eventfd_ctx_fileget()
391 return -EINVAL; in do_eventfd()
395 return -ENOMEM; in do_eventfd()
397 kref_init(&ctx->kref); in do_eventfd()
398 init_waitqueue_head(&ctx->wqh); in do_eventfd()
399 ctx->count = count; in do_eventfd()
400 ctx->flags = flags; in do_eventfd()
401 ctx->id = ida_alloc(&eventfd_ida, GFP_KERNEL); in do_eventfd()
416 file->f_mode |= FMODE_NOWAIT; in do_eventfd()