1 | // SPDX-License-Identifier: LGPL-2.1+ |
2 | // Copyright (C) 2022, Linaro Ltd - Daniel Lezcano <daniel.lezcano@linaro.org> |
3 | #include <stdlib.h> |
4 | #include <errno.h> |
5 | #include <unistd.h> |
6 | #include <signal.h> |
7 | #include <sys/epoll.h> |
8 | #include "mainloop.h" |
9 | #include "log.h" |
10 | |
11 | static int epfd = -1; |
12 | static sig_atomic_t exit_mainloop; |
13 | |
14 | struct mainloop_data { |
15 | mainloop_callback_t cb; |
16 | void *data; |
17 | int fd; |
18 | }; |
19 | |
20 | #define MAX_EVENTS 10 |
21 | |
22 | int mainloop(unsigned int timeout) |
23 | { |
24 | int i, nfds; |
25 | struct epoll_event events[MAX_EVENTS]; |
26 | struct mainloop_data *md; |
27 | |
28 | if (epfd < 0) |
29 | return -1; |
30 | |
31 | for (;;) { |
32 | |
33 | nfds = epoll_wait(epfd, events, MAX_EVENTS, timeout); |
34 | |
35 | if (exit_mainloop || !nfds) |
36 | return 0; |
37 | |
38 | if (nfds < 0) { |
39 | if (errno == EINTR) |
40 | continue; |
41 | return -1; |
42 | } |
43 | |
44 | for (i = 0; i < nfds; i++) { |
45 | md = events[i].data.ptr; |
46 | |
47 | if (md->cb(md->fd, md->data) > 0) |
48 | return 0; |
49 | } |
50 | } |
51 | } |
52 | |
53 | int mainloop_add(int fd, mainloop_callback_t cb, void *data) |
54 | { |
55 | struct epoll_event ev = { |
56 | .events = EPOLLIN, |
57 | }; |
58 | |
59 | struct mainloop_data *md; |
60 | |
61 | md = malloc(sizeof(*md)); |
62 | if (!md) |
63 | return -1; |
64 | |
65 | md->data = data; |
66 | md->cb = cb; |
67 | md->fd = fd; |
68 | |
69 | ev.data.ptr = md; |
70 | |
71 | if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) < 0) { |
72 | free(md); |
73 | return -1; |
74 | } |
75 | |
76 | return 0; |
77 | } |
78 | |
79 | int mainloop_del(int fd) |
80 | { |
81 | if (epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL) < 0) |
82 | return -1; |
83 | |
84 | return 0; |
85 | } |
86 | |
87 | int mainloop_init(void) |
88 | { |
89 | epfd = epoll_create(2); |
90 | if (epfd < 0) |
91 | return -1; |
92 | |
93 | return 0; |
94 | } |
95 | |
96 | void mainloop_exit(void) |
97 | { |
98 | exit_mainloop = 1; |
99 | } |
100 | |
101 | void mainloop_fini(void) |
102 | { |
103 | close(epfd); |
104 | } |
105 | |