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