121 lines
1.7 KiB
C
121 lines
1.7 KiB
C
// SPDX-License-Identifier: LGPL-2.1+
|
|
// Copyright (C) 2022, Linaro Ltd - Daniel Lezcano <daniel.lezcano@linaro.org>
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
#include <unistd.h>
|
|
#include <signal.h>
|
|
#include <sys/epoll.h>
|
|
#include "mainloop.h"
|
|
#include "log.h"
|
|
|
|
static int epfd = -1;
|
|
static unsigned short nrhandler;
|
|
static sig_atomic_t exit_mainloop;
|
|
|
|
struct mainloop_data {
|
|
mainloop_callback_t cb;
|
|
void *data;
|
|
int fd;
|
|
};
|
|
|
|
static struct mainloop_data **mds;
|
|
|
|
#define MAX_EVENTS 10
|
|
|
|
int mainloop(unsigned int timeout)
|
|
{
|
|
int i, nfds;
|
|
struct epoll_event events[MAX_EVENTS];
|
|
struct mainloop_data *md;
|
|
|
|
if (epfd < 0)
|
|
return -1;
|
|
|
|
for (;;) {
|
|
|
|
nfds = epoll_wait(epfd, events, MAX_EVENTS, timeout);
|
|
|
|
if (exit_mainloop || !nfds)
|
|
return 0;
|
|
|
|
if (nfds < 0) {
|
|
if (errno == EINTR)
|
|
continue;
|
|
return -1;
|
|
}
|
|
|
|
for (i = 0; i < nfds; i++) {
|
|
md = events[i].data.ptr;
|
|
|
|
if (md->cb(md->fd, md->data) > 0)
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
int mainloop_add(int fd, mainloop_callback_t cb, void *data)
|
|
{
|
|
struct epoll_event ev = {
|
|
.events = EPOLLIN,
|
|
};
|
|
|
|
struct mainloop_data *md;
|
|
|
|
if (fd >= nrhandler) {
|
|
mds = realloc(mds, sizeof(*mds) * (fd + 1));
|
|
if (!mds)
|
|
return -1;
|
|
nrhandler = fd + 1;
|
|
}
|
|
|
|
md = malloc(sizeof(*md));
|
|
if (!md)
|
|
return -1;
|
|
|
|
md->data = data;
|
|
md->cb = cb;
|
|
md->fd = fd;
|
|
|
|
mds[fd] = md;
|
|
ev.data.ptr = md;
|
|
|
|
if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) < 0) {
|
|
free(md);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int mainloop_del(int fd)
|
|
{
|
|
if (fd >= nrhandler)
|
|
return -1;
|
|
|
|
if (epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL) < 0)
|
|
return -1;
|
|
|
|
free(mds[fd]);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int mainloop_init(void)
|
|
{
|
|
epfd = epoll_create(2);
|
|
if (epfd < 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void mainloop_exit(void)
|
|
{
|
|
exit_mainloop = 1;
|
|
}
|
|
|
|
void mainloop_fini(void)
|
|
{
|
|
close(epfd);
|
|
}
|