Statistics
| Branch: | Revision:

root / util / event_notifier-posix.c @ dccfcd0e

History | View | Annotate | Download (2.4 kB)

1
/*
2
 * event notifier support
3
 *
4
 * Copyright Red Hat, Inc. 2010
5
 *
6
 * Authors:
7
 *  Michael S. Tsirkin <mst@redhat.com>
8
 *
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.
11
 */
12

    
13
#include "qemu-common.h"
14
#include "qemu/event_notifier.h"
15
#include "sysemu/char.h"
16
#include "qemu/main-loop.h"
17

    
18
#ifdef CONFIG_EVENTFD
19
#include <sys/eventfd.h>
20
#endif
21

    
22
void event_notifier_init_fd(EventNotifier *e, int fd)
23
{
24
    e->rfd = fd;
25
    e->wfd = fd;
26
}
27

    
28
int event_notifier_init(EventNotifier *e, int active)
29
{
30
    int fds[2];
31
    int ret;
32

    
33
#ifdef CONFIG_EVENTFD
34
    ret = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
35
#else
36
    ret = -1;
37
    errno = ENOSYS;
38
#endif
39
    if (ret >= 0) {
40
        e->rfd = e->wfd = ret;
41
    } else {
42
        if (errno != ENOSYS) {
43
            return -errno;
44
        }
45
        if (qemu_pipe(fds) < 0) {
46
            return -errno;
47
        }
48
        ret = fcntl_setfl(fds[0], O_NONBLOCK);
49
        if (ret < 0) {
50
            ret = -errno;
51
            goto fail;
52
        }
53
        ret = fcntl_setfl(fds[1], O_NONBLOCK);
54
        if (ret < 0) {
55
            ret = -errno;
56
            goto fail;
57
        }
58
        e->rfd = fds[0];
59
        e->wfd = fds[1];
60
    }
61
    if (active) {
62
        event_notifier_set(e);
63
    }
64
    return 0;
65

    
66
fail:
67
    close(fds[0]);
68
    close(fds[1]);
69
    return ret;
70
}
71

    
72
void event_notifier_cleanup(EventNotifier *e)
73
{
74
    if (e->rfd != e->wfd) {
75
        close(e->rfd);
76
    }
77
    close(e->wfd);
78
}
79

    
80
int event_notifier_get_fd(EventNotifier *e)
81
{
82
    return e->rfd;
83
}
84

    
85
int event_notifier_set_handler(EventNotifier *e,
86
                               EventNotifierHandler *handler)
87
{
88
    return qemu_set_fd_handler(e->rfd, (IOHandler *)handler, NULL, e);
89
}
90

    
91
int event_notifier_set(EventNotifier *e)
92
{
93
    static const uint64_t value = 1;
94
    ssize_t ret;
95

    
96
    do {
97
        ret = write(e->wfd, &value, sizeof(value));
98
    } while (ret < 0 && errno == EINTR);
99

    
100
    /* EAGAIN is fine, a read must be pending.  */
101
    if (ret < 0 && errno != EAGAIN) {
102
        return -errno;
103
    }
104
    return 0;
105
}
106

    
107
int event_notifier_test_and_clear(EventNotifier *e)
108
{
109
    int value;
110
    ssize_t len;
111
    char buffer[512];
112

    
113
    /* Drain the notify pipe.  For eventfd, only 8 bytes will be read.  */
114
    value = 0;
115
    do {
116
        len = read(e->rfd, buffer, sizeof(buffer));
117
        value |= (len > 0);
118
    } while ((len == -1 && errno == EINTR) || len == sizeof(buffer));
119

    
120
    return value;
121
}