forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
120 lines
1.7 KiB
120 lines
1.7 KiB
// SPDX-License-Identifier: LGPL-2.1+ |
|
// Copyright (C) 2022, Linaro Ltd - Daniel Lezcano <[email protected]> |
|
#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); |
|
}
|
|
|