xref: /kvmtool/epoll.c (revision d30d94872e7fe998bd527e5cc6c38db58d46ee03)
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