105 lines · c
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 1021 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