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