forked from kvmtool/kvmtool
-
Notifications
You must be signed in to change notification settings - Fork 0
/
epoll.c
91 lines (72 loc) · 1.79 KB
/
epoll.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include <sys/eventfd.h>
#include "kvm/epoll.h"
#define EPOLLFD_MAX_EVENTS 20
static void *epoll__thread(void *param)
{
u64 stop;
int nfds, i;
struct kvm__epoll *epoll = param;
struct kvm *kvm = epoll->kvm;
struct epoll_event events[EPOLLFD_MAX_EVENTS];
kvm__set_thread_name(epoll->name);
for (;;) {
nfds = epoll_wait(epoll->fd, events, EPOLLFD_MAX_EVENTS, -1);
for (i = 0; i < nfds; i++) {
if (events[i].data.ptr == &epoll->stop_fd)
goto done;
epoll->handle_event(kvm, &events[i]);
}
}
done:
if (read(epoll->stop_fd, &stop, sizeof(stop)) < 0)
pr_warning("%s: read(stop) failed with %d", __func__, errno);
if (write(epoll->stop_fd, &stop, sizeof(stop)) < 0)
pr_warning("%s: write(stop) failed with %d", __func__, errno);
return NULL;
}
int epoll__init(struct kvm *kvm, struct kvm__epoll *epoll,
const char *name, epoll__event_handler_t handle_event)
{
int r;
struct epoll_event stop_event = {
.events = EPOLLIN,
.data.ptr = &epoll->stop_fd,
};
epoll->kvm = kvm;
epoll->name = name;
epoll->handle_event = handle_event;
epoll->fd = epoll_create(EPOLLFD_MAX_EVENTS);
if (epoll->fd < 0)
return -errno;
epoll->stop_fd = eventfd(0, 0);
if (epoll->stop_fd < 0) {
r = -errno;
goto err_close_fd;
}
r = epoll_ctl(epoll->fd, EPOLL_CTL_ADD, epoll->stop_fd, &stop_event);
if (r < 0)
goto err_close_all;
r = pthread_create(&epoll->thread, NULL, epoll__thread, epoll);
if (r < 0)
goto err_close_all;
return 0;
err_close_all:
close(epoll->stop_fd);
err_close_fd:
close(epoll->fd);
return r;
}
int epoll__exit(struct kvm__epoll *epoll)
{
int r;
u64 stop = 1;
r = write(epoll->stop_fd, &stop, sizeof(stop));
if (r < 0)
return r;
r = read(epoll->stop_fd, &stop, sizeof(stop));
if (r < 0)
return r;
close(epoll->stop_fd);
close(epoll->fd);
return 0;
}