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 11static int epfd = -1; 12static sig_atomic_t exit_mainloop; 13 14struct mainloop_data { 15 mainloop_callback_t cb; 16 void *data; 17 int fd; 18}; 19 20#define MAX_EVENTS 10 21 22int 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 53int 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 79int 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 87int mainloop_init(void) 88{ 89 epfd = epoll_create(2); 90 if (epfd < 0) 91 return -1; 92 93 return 0; 94} 95 96void mainloop_exit(void) 97{ 98 exit_mainloop = 1; 99} 100 101void mainloop_fini(void) 102{ 103 close(epfd); 104} 105