128 lines
2.1 KiB
C
128 lines
2.1 KiB
C
/*
|
|
* SPDX-License-Identifier: MIT
|
|
*
|
|
* Copyright (C) 2019 Philippe Gerum <rpm@xenomai.org>
|
|
*/
|
|
|
|
#include <errno.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <sys/epoll.h>
|
|
#include <evl/poll.h>
|
|
#include "internal.h"
|
|
|
|
int evl_new_poll(void)
|
|
{
|
|
return epoll_create1(EPOLL_CLOEXEC);
|
|
}
|
|
|
|
int evl_add_pollfd(int efd, int newfd, unsigned int events,
|
|
union evl_value pollval)
|
|
{
|
|
struct epoll_event ev;
|
|
int ret;
|
|
|
|
if (efd == newfd)
|
|
return -ELOOP;
|
|
|
|
ev.events = events;
|
|
ev.data.fd = newfd;
|
|
|
|
ret = epoll_ctl(efd, EPOLL_CTL_ADD, newfd, &ev);
|
|
if (ret)
|
|
return -errno;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int evl_del_pollfd(int efd, int delfd)
|
|
{
|
|
int ret;
|
|
|
|
ret = epoll_ctl(efd, EPOLL_CTL_DEL, delfd, NULL);
|
|
if (ret)
|
|
return -errno;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int evl_mod_pollfd(int efd, int modfd, unsigned int events,
|
|
union evl_value pollval)
|
|
{
|
|
struct epoll_event ev;
|
|
int ret;
|
|
|
|
ev.events = events;
|
|
ev.data.fd = modfd;
|
|
|
|
ret = epoll_ctl(efd, EPOLL_CTL_MOD, modfd, &ev);
|
|
if (ret)
|
|
return -errno;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Use a fast stack-based array for monitoring a small number of
|
|
* events.
|
|
*/
|
|
#define FAST_EVENT_NR 8
|
|
|
|
static int do_timedpoll(int efd, struct evl_poll_event *pollset,
|
|
int nrset, int msecs)
|
|
{
|
|
struct epoll_event fast_evs[FAST_EVENT_NR], *evs = fast_evs;
|
|
int ret, n;
|
|
|
|
if (nrset == 0)
|
|
return 0;
|
|
|
|
if (nrset < 0)
|
|
return -EINVAL;
|
|
|
|
if (nrset > FAST_EVENT_NR) {
|
|
evs = malloc(sizeof(*evs) * nrset);
|
|
if (evs == NULL)
|
|
return -ENOMEM;
|
|
}
|
|
|
|
ret = epoll_wait(efd, evs, nrset, msecs);
|
|
if (ret < 0) {
|
|
ret = -errno;
|
|
goto out;
|
|
}
|
|
|
|
if (ret == 0) {
|
|
ret = -ETIMEDOUT;
|
|
goto out;
|
|
}
|
|
|
|
for (n = 0; n < nrset; n++) {
|
|
pollset[n].fd = evs[n].data.fd;
|
|
pollset[n].events = evs[n].events;
|
|
}
|
|
out:
|
|
if (evs != fast_evs)
|
|
free(evs);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int evl_timedpoll(int efd, struct evl_poll_event *pollset,
|
|
int nrset, struct timespec *timeout)
|
|
{
|
|
int msecs;
|
|
|
|
if (timeout->tv_sec < 0 || timeout->tv_nsec >= 1000000000L)
|
|
return -EINVAL;
|
|
|
|
msecs = timeout->tv_sec * 1000 + timeout->tv_nsec / 1000000;
|
|
|
|
return do_timedpoll(efd, pollset, nrset, msecs);
|
|
}
|
|
|
|
int evl_poll(int efd, struct evl_poll_event *pollset, int nrset)
|
|
{
|
|
return do_timedpoll(efd, pollset, nrset, -1);
|
|
}
|