This source file includes following definitions.
- eventfd_signal
- eventfd_free_ctx
- eventfd_free
- eventfd_ctx_put
- eventfd_release
- eventfd_poll
- eventfd_ctx_do_read
- eventfd_ctx_remove_wait_queue
- eventfd_read
- eventfd_write
- eventfd_show_fdinfo
- eventfd_fget
- eventfd_ctx_fdget
- eventfd_ctx_fileget
- do_eventfd
- SYSCALL_DEFINE2
- SYSCALL_DEFINE1
1
2
3
4
5
6
7
8
9 #include <linux/file.h>
10 #include <linux/poll.h>
11 #include <linux/init.h>
12 #include <linux/fs.h>
13 #include <linux/sched/signal.h>
14 #include <linux/kernel.h>
15 #include <linux/slab.h>
16 #include <linux/list.h>
17 #include <linux/spinlock.h>
18 #include <linux/anon_inodes.h>
19 #include <linux/syscalls.h>
20 #include <linux/export.h>
21 #include <linux/kref.h>
22 #include <linux/eventfd.h>
23 #include <linux/proc_fs.h>
24 #include <linux/seq_file.h>
25 #include <linux/idr.h>
26
27 DEFINE_PER_CPU(int, eventfd_wake_count);
28
29 static DEFINE_IDA(eventfd_ida);
30
31 struct eventfd_ctx {
32 struct kref kref;
33 wait_queue_head_t wqh;
34
35
36
37
38
39
40
41
42 __u64 count;
43 unsigned int flags;
44 int id;
45 };
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61 __u64 eventfd_signal(struct eventfd_ctx *ctx, __u64 n)
62 {
63 unsigned long flags;
64
65
66
67
68
69
70
71
72
73 if (WARN_ON_ONCE(this_cpu_read(eventfd_wake_count)))
74 return 0;
75
76 spin_lock_irqsave(&ctx->wqh.lock, flags);
77 this_cpu_inc(eventfd_wake_count);
78 if (ULLONG_MAX - ctx->count < n)
79 n = ULLONG_MAX - ctx->count;
80 ctx->count += n;
81 if (waitqueue_active(&ctx->wqh))
82 wake_up_locked_poll(&ctx->wqh, EPOLLIN);
83 this_cpu_dec(eventfd_wake_count);
84 spin_unlock_irqrestore(&ctx->wqh.lock, flags);
85
86 return n;
87 }
88 EXPORT_SYMBOL_GPL(eventfd_signal);
89
90 static void eventfd_free_ctx(struct eventfd_ctx *ctx)
91 {
92 if (ctx->id >= 0)
93 ida_simple_remove(&eventfd_ida, ctx->id);
94 kfree(ctx);
95 }
96
97 static void eventfd_free(struct kref *kref)
98 {
99 struct eventfd_ctx *ctx = container_of(kref, struct eventfd_ctx, kref);
100
101 eventfd_free_ctx(ctx);
102 }
103
104
105
106
107
108
109
110
111 void eventfd_ctx_put(struct eventfd_ctx *ctx)
112 {
113 kref_put(&ctx->kref, eventfd_free);
114 }
115 EXPORT_SYMBOL_GPL(eventfd_ctx_put);
116
117 static int eventfd_release(struct inode *inode, struct file *file)
118 {
119 struct eventfd_ctx *ctx = file->private_data;
120
121 wake_up_poll(&ctx->wqh, EPOLLHUP);
122 eventfd_ctx_put(ctx);
123 return 0;
124 }
125
126 static __poll_t eventfd_poll(struct file *file, poll_table *wait)
127 {
128 struct eventfd_ctx *ctx = file->private_data;
129 __poll_t events = 0;
130 u64 count;
131
132 poll_wait(file, &ctx->wqh, wait);
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172 count = READ_ONCE(ctx->count);
173
174 if (count > 0)
175 events |= EPOLLIN;
176 if (count == ULLONG_MAX)
177 events |= EPOLLERR;
178 if (ULLONG_MAX - 1 > count)
179 events |= EPOLLOUT;
180
181 return events;
182 }
183
184 static void eventfd_ctx_do_read(struct eventfd_ctx *ctx, __u64 *cnt)
185 {
186 *cnt = (ctx->flags & EFD_SEMAPHORE) ? 1 : ctx->count;
187 ctx->count -= *cnt;
188 }
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203 int eventfd_ctx_remove_wait_queue(struct eventfd_ctx *ctx, wait_queue_entry_t *wait,
204 __u64 *cnt)
205 {
206 unsigned long flags;
207
208 spin_lock_irqsave(&ctx->wqh.lock, flags);
209 eventfd_ctx_do_read(ctx, cnt);
210 __remove_wait_queue(&ctx->wqh, wait);
211 if (*cnt != 0 && waitqueue_active(&ctx->wqh))
212 wake_up_locked_poll(&ctx->wqh, EPOLLOUT);
213 spin_unlock_irqrestore(&ctx->wqh.lock, flags);
214
215 return *cnt != 0 ? 0 : -EAGAIN;
216 }
217 EXPORT_SYMBOL_GPL(eventfd_ctx_remove_wait_queue);
218
219 static ssize_t eventfd_read(struct file *file, char __user *buf, size_t count,
220 loff_t *ppos)
221 {
222 struct eventfd_ctx *ctx = file->private_data;
223 ssize_t res;
224 __u64 ucnt = 0;
225 DECLARE_WAITQUEUE(wait, current);
226
227 if (count < sizeof(ucnt))
228 return -EINVAL;
229
230 spin_lock_irq(&ctx->wqh.lock);
231 res = -EAGAIN;
232 if (ctx->count > 0)
233 res = sizeof(ucnt);
234 else if (!(file->f_flags & O_NONBLOCK)) {
235 __add_wait_queue(&ctx->wqh, &wait);
236 for (;;) {
237 set_current_state(TASK_INTERRUPTIBLE);
238 if (ctx->count > 0) {
239 res = sizeof(ucnt);
240 break;
241 }
242 if (signal_pending(current)) {
243 res = -ERESTARTSYS;
244 break;
245 }
246 spin_unlock_irq(&ctx->wqh.lock);
247 schedule();
248 spin_lock_irq(&ctx->wqh.lock);
249 }
250 __remove_wait_queue(&ctx->wqh, &wait);
251 __set_current_state(TASK_RUNNING);
252 }
253 if (likely(res > 0)) {
254 eventfd_ctx_do_read(ctx, &ucnt);
255 if (waitqueue_active(&ctx->wqh))
256 wake_up_locked_poll(&ctx->wqh, EPOLLOUT);
257 }
258 spin_unlock_irq(&ctx->wqh.lock);
259
260 if (res > 0 && put_user(ucnt, (__u64 __user *)buf))
261 return -EFAULT;
262
263 return res;
264 }
265
266 static ssize_t eventfd_write(struct file *file, const char __user *buf, size_t count,
267 loff_t *ppos)
268 {
269 struct eventfd_ctx *ctx = file->private_data;
270 ssize_t res;
271 __u64 ucnt;
272 DECLARE_WAITQUEUE(wait, current);
273
274 if (count < sizeof(ucnt))
275 return -EINVAL;
276 if (copy_from_user(&ucnt, buf, sizeof(ucnt)))
277 return -EFAULT;
278 if (ucnt == ULLONG_MAX)
279 return -EINVAL;
280 spin_lock_irq(&ctx->wqh.lock);
281 res = -EAGAIN;
282 if (ULLONG_MAX - ctx->count > ucnt)
283 res = sizeof(ucnt);
284 else if (!(file->f_flags & O_NONBLOCK)) {
285 __add_wait_queue(&ctx->wqh, &wait);
286 for (res = 0;;) {
287 set_current_state(TASK_INTERRUPTIBLE);
288 if (ULLONG_MAX - ctx->count > ucnt) {
289 res = sizeof(ucnt);
290 break;
291 }
292 if (signal_pending(current)) {
293 res = -ERESTARTSYS;
294 break;
295 }
296 spin_unlock_irq(&ctx->wqh.lock);
297 schedule();
298 spin_lock_irq(&ctx->wqh.lock);
299 }
300 __remove_wait_queue(&ctx->wqh, &wait);
301 __set_current_state(TASK_RUNNING);
302 }
303 if (likely(res > 0)) {
304 ctx->count += ucnt;
305 if (waitqueue_active(&ctx->wqh))
306 wake_up_locked_poll(&ctx->wqh, EPOLLIN);
307 }
308 spin_unlock_irq(&ctx->wqh.lock);
309
310 return res;
311 }
312
313 #ifdef CONFIG_PROC_FS
314 static void eventfd_show_fdinfo(struct seq_file *m, struct file *f)
315 {
316 struct eventfd_ctx *ctx = f->private_data;
317
318 spin_lock_irq(&ctx->wqh.lock);
319 seq_printf(m, "eventfd-count: %16llx\n",
320 (unsigned long long)ctx->count);
321 spin_unlock_irq(&ctx->wqh.lock);
322 seq_printf(m, "eventfd-id: %d\n", ctx->id);
323 }
324 #endif
325
326 static const struct file_operations eventfd_fops = {
327 #ifdef CONFIG_PROC_FS
328 .show_fdinfo = eventfd_show_fdinfo,
329 #endif
330 .release = eventfd_release,
331 .poll = eventfd_poll,
332 .read = eventfd_read,
333 .write = eventfd_write,
334 .llseek = noop_llseek,
335 };
336
337
338
339
340
341
342
343
344
345
346
347 struct file *eventfd_fget(int fd)
348 {
349 struct file *file;
350
351 file = fget(fd);
352 if (!file)
353 return ERR_PTR(-EBADF);
354 if (file->f_op != &eventfd_fops) {
355 fput(file);
356 return ERR_PTR(-EINVAL);
357 }
358
359 return file;
360 }
361 EXPORT_SYMBOL_GPL(eventfd_fget);
362
363
364
365
366
367
368
369
370
371
372 struct eventfd_ctx *eventfd_ctx_fdget(int fd)
373 {
374 struct eventfd_ctx *ctx;
375 struct fd f = fdget(fd);
376 if (!f.file)
377 return ERR_PTR(-EBADF);
378 ctx = eventfd_ctx_fileget(f.file);
379 fdput(f);
380 return ctx;
381 }
382 EXPORT_SYMBOL_GPL(eventfd_ctx_fdget);
383
384
385
386
387
388
389
390
391
392
393 struct eventfd_ctx *eventfd_ctx_fileget(struct file *file)
394 {
395 struct eventfd_ctx *ctx;
396
397 if (file->f_op != &eventfd_fops)
398 return ERR_PTR(-EINVAL);
399
400 ctx = file->private_data;
401 kref_get(&ctx->kref);
402 return ctx;
403 }
404 EXPORT_SYMBOL_GPL(eventfd_ctx_fileget);
405
406 static int do_eventfd(unsigned int count, int flags)
407 {
408 struct eventfd_ctx *ctx;
409 int fd;
410
411
412 BUILD_BUG_ON(EFD_CLOEXEC != O_CLOEXEC);
413 BUILD_BUG_ON(EFD_NONBLOCK != O_NONBLOCK);
414
415 if (flags & ~EFD_FLAGS_SET)
416 return -EINVAL;
417
418 ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
419 if (!ctx)
420 return -ENOMEM;
421
422 kref_init(&ctx->kref);
423 init_waitqueue_head(&ctx->wqh);
424 ctx->count = count;
425 ctx->flags = flags;
426 ctx->id = ida_simple_get(&eventfd_ida, 0, 0, GFP_KERNEL);
427
428 fd = anon_inode_getfd("[eventfd]", &eventfd_fops, ctx,
429 O_RDWR | (flags & EFD_SHARED_FCNTL_FLAGS));
430 if (fd < 0)
431 eventfd_free_ctx(ctx);
432
433 return fd;
434 }
435
436 SYSCALL_DEFINE2(eventfd2, unsigned int, count, int, flags)
437 {
438 return do_eventfd(count, flags);
439 }
440
441 SYSCALL_DEFINE1(eventfd, unsigned int, count)
442 {
443 return do_eventfd(count, 0);
444 }
445