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