2017-06-13 12:50:51 +03:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <sched.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <assert.h>
|
|
|
|
#include <unistd.h>
|
2017-04-21 13:43:26 +03:00
|
|
|
#include <netinet/in.h>
|
2017-06-13 12:50:51 +03:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <sys/select.h>
|
|
|
|
#include <sys/syscall.h>
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <sys/epoll.h>
|
2017-04-21 13:43:26 +03:00
|
|
|
|
|
|
|
#include "ff_api.h"
|
|
|
|
#include "ff_errno.h"
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
ff_epoll_create(int size __attribute__((__unused__)))
|
|
|
|
{
|
2017-06-13 14:26:38 +03:00
|
|
|
return ff_kqueue();
|
2017-04-21 13:43:26 +03:00
|
|
|
}
|
|
|
|
|
2017-12-05 12:51:02 +03:00
|
|
|
int
|
2017-04-21 13:43:26 +03:00
|
|
|
ff_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
|
|
|
|
{
|
2017-06-13 14:26:38 +03:00
|
|
|
struct kevent kev[3];
|
2017-06-13 12:50:51 +03:00
|
|
|
|
2017-06-13 14:26:38 +03:00
|
|
|
if (!event && op != EPOLL_CTL_DEL) {
|
2017-06-13 12:50:51 +03:00
|
|
|
errno = EINVAL;
|
2017-06-13 14:26:38 +03:00
|
|
|
return -1;
|
|
|
|
}
|
2017-04-21 13:43:26 +03:00
|
|
|
|
2017-06-13 14:26:38 +03:00
|
|
|
if (op == EPOLL_CTL_ADD){
|
2017-12-05 12:51:02 +03:00
|
|
|
int flags = EV_ADD;
|
|
|
|
if (event->events & EPOLLET) {
|
|
|
|
flags |= EV_CLEAR;
|
|
|
|
}
|
|
|
|
|
2017-06-13 14:26:38 +03:00
|
|
|
EV_SET(&kev[0], fd, EVFILT_READ,
|
2017-12-05 12:51:02 +03:00
|
|
|
flags | (event->events & EPOLLIN ? 0 : EV_DISABLE), 0, 0, NULL);
|
2017-06-13 14:26:38 +03:00
|
|
|
EV_SET(&kev[1], fd, EVFILT_WRITE,
|
2017-12-05 12:51:02 +03:00
|
|
|
flags | (event->events & EPOLLOUT ? 0 : EV_DISABLE), 0, 0, NULL);
|
2017-06-13 14:26:38 +03:00
|
|
|
EV_SET(&kev[2], fd, EVFILT_USER, EV_ADD,
|
2017-12-05 12:51:02 +03:00
|
|
|
event->events & EPOLLRDHUP ? 1 : 0, 0, NULL);
|
2017-06-13 14:26:38 +03:00
|
|
|
} else if (op == EPOLL_CTL_DEL) {
|
|
|
|
EV_SET(&kev[0], fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
|
|
|
|
EV_SET(&kev[1], fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
|
|
|
|
EV_SET(&kev[2], fd, EVFILT_USER, EV_DELETE, 0, 0, NULL);
|
|
|
|
} else if (op == EPOLL_CTL_MOD) {
|
2017-12-05 12:51:02 +03:00
|
|
|
int flags = 0;
|
|
|
|
if (event->events & EPOLLET) {
|
|
|
|
flags |= EV_CLEAR;
|
|
|
|
}
|
|
|
|
|
2017-06-13 14:26:38 +03:00
|
|
|
EV_SET(&kev[0], fd, EVFILT_READ,
|
2017-12-05 12:51:02 +03:00
|
|
|
flags | (event->events & EPOLLIN ? EV_ENABLE : EV_DISABLE), 0, 0, NULL);
|
2017-06-13 14:26:38 +03:00
|
|
|
EV_SET(&kev[1], fd, EVFILT_WRITE,
|
2017-12-05 12:51:02 +03:00
|
|
|
flags | (event->events & EPOLLOUT ? EV_ENABLE : EV_DISABLE), 0, 0, NULL);
|
2017-06-13 14:26:38 +03:00
|
|
|
EV_SET(&kev[2], fd, EVFILT_USER, 0,
|
2017-12-05 12:51:02 +03:00
|
|
|
NOTE_FFCOPY | (event->events & EPOLLRDHUP ? 1 : 0), 0, NULL);
|
2017-06-13 14:26:38 +03:00
|
|
|
} else {
|
|
|
|
errno = EINVAL;
|
|
|
|
return -1;
|
|
|
|
}
|
2017-04-21 13:43:26 +03:00
|
|
|
|
2017-06-13 14:26:38 +03:00
|
|
|
return ff_kevent(epfd, kev, 3, NULL, 0, NULL);
|
2017-04-21 13:43:26 +03:00
|
|
|
}
|
|
|
|
|
2017-06-13 12:50:51 +03:00
|
|
|
static void
|
|
|
|
ff_event_to_epoll(void **ev, struct kevent *kev)
|
2017-04-21 13:43:26 +03:00
|
|
|
{
|
2017-06-13 12:50:51 +03:00
|
|
|
unsigned int event_one = 0;
|
|
|
|
struct epoll_event **ppev = (struct epoll_event **)ev;
|
2017-04-21 13:43:26 +03:00
|
|
|
|
2017-11-27 13:39:34 +03:00
|
|
|
if (kev->filter == EVFILT_READ) {
|
|
|
|
if (kev->data || !(kev->flags & EV_EOF)) {
|
|
|
|
event_one |= EPOLLIN;
|
|
|
|
}
|
|
|
|
} else if (kev->filter == EVFILT_WRITE) {
|
2017-06-13 12:50:51 +03:00
|
|
|
event_one |= EPOLLOUT;
|
|
|
|
}
|
2017-04-21 13:43:26 +03:00
|
|
|
|
2017-06-13 12:50:51 +03:00
|
|
|
if (kev->flags & EV_ERROR) {
|
|
|
|
event_one |= EPOLLERR;
|
|
|
|
}
|
2017-04-21 13:43:26 +03:00
|
|
|
|
2017-06-13 12:50:51 +03:00
|
|
|
if (kev->flags & EV_EOF) {
|
2017-11-27 13:39:34 +03:00
|
|
|
event_one |= EPOLLHUP;
|
|
|
|
|
|
|
|
if (kev->fflags) {
|
|
|
|
event_one |= EPOLLERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (kev->filter == EVFILT_READ) {
|
|
|
|
event_one |= EPOLLIN;
|
|
|
|
} else if (kev->filter == EVFILT_WRITE) {
|
|
|
|
event_one |= EPOLLERR;
|
|
|
|
}
|
2017-06-13 12:50:51 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
(*ppev)->events = event_one;
|
|
|
|
(*ppev)->data.fd = kev->ident;
|
|
|
|
(*ppev)++;
|
2017-04-21 13:43:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2017-06-13 12:50:51 +03:00
|
|
|
ff_epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
|
2017-04-21 13:43:26 +03:00
|
|
|
{
|
2017-06-13 12:50:51 +03:00
|
|
|
int i, ret;
|
2017-06-13 14:26:38 +03:00
|
|
|
if (!events || maxevents < 1) {
|
|
|
|
errno = EINVAL;
|
|
|
|
return -1;
|
|
|
|
}
|
2017-06-13 12:50:51 +03:00
|
|
|
|
2017-06-13 14:26:38 +03:00
|
|
|
return ff_kevent_do_each(epfd, NULL, 0, events, maxevents, NULL, ff_event_to_epoll);
|
2017-04-21 13:43:26 +03:00
|
|
|
}
|
|
|
|
|