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