Michael S. Tsirkin | 2292b33 | 2010-03-17 13:07:58 +0200 | [diff] [blame] | 1 | /* |
| 2 | * event notifier support |
| 3 | * |
| 4 | * Copyright Red Hat, Inc. 2010 |
| 5 | * |
| 6 | * Authors: |
| 7 | * Michael S. Tsirkin <mst@redhat.com> |
| 8 | * |
Paolo Bonzini | 6b620ca | 2012-01-13 17:44:23 +0100 | [diff] [blame] | 9 | * This work is licensed under the terms of the GNU GPL, version 2 or later. |
| 10 | * See the COPYING file in the top-level directory. |
Michael S. Tsirkin | 2292b33 | 2010-03-17 13:07:58 +0200 | [diff] [blame] | 11 | */ |
| 12 | |
Michael S. Tsirkin | 2292b33 | 2010-03-17 13:07:58 +0200 | [diff] [blame] | 13 | #include "event_notifier.h" |
| 14 | #ifdef CONFIG_EVENTFD |
| 15 | #include <sys/eventfd.h> |
| 16 | #endif |
| 17 | |
| 18 | int event_notifier_init(EventNotifier *e, int active) |
| 19 | { |
| 20 | #ifdef CONFIG_EVENTFD |
| 21 | int fd = eventfd(!!active, EFD_NONBLOCK | EFD_CLOEXEC); |
| 22 | if (fd < 0) |
| 23 | return -errno; |
| 24 | e->fd = fd; |
| 25 | return 0; |
| 26 | #else |
| 27 | return -ENOSYS; |
| 28 | #endif |
| 29 | } |
| 30 | |
| 31 | void event_notifier_cleanup(EventNotifier *e) |
| 32 | { |
| 33 | close(e->fd); |
| 34 | } |
| 35 | |
| 36 | int event_notifier_get_fd(EventNotifier *e) |
| 37 | { |
| 38 | return e->fd; |
| 39 | } |
| 40 | |
| 41 | int event_notifier_test_and_clear(EventNotifier *e) |
| 42 | { |
| 43 | uint64_t value; |
| 44 | int r = read(e->fd, &value, sizeof(value)); |
| 45 | return r == sizeof(value); |
| 46 | } |
| 47 | |
| 48 | int event_notifier_test(EventNotifier *e) |
| 49 | { |
| 50 | uint64_t value; |
| 51 | int r = read(e->fd, &value, sizeof(value)); |
| 52 | if (r == sizeof(value)) { |
| 53 | /* restore previous value. */ |
| 54 | int s = write(e->fd, &value, sizeof(value)); |
| 55 | /* never blocks because we use EFD_SEMAPHORE. |
| 56 | * If we didn't we'd get EAGAIN on overflow |
| 57 | * and we'd have to write code to ignore it. */ |
| 58 | assert(s == sizeof(value)); |
| 59 | } |
| 60 | return r == sizeof(value); |
| 61 | } |