epoll optimization, add ff_kevent_do_each

dev
Ron 2017-06-13 17:50:51 +08:00
parent 61a488cc9b
commit 1a78ce8ea6
7 changed files with 90 additions and 152 deletions

View File

@ -17,6 +17,7 @@ LIBS+= -Wl,--no-whole-archive -lrt -lm -ldl -lcrypto -pthread
TARGET="helloworld"
all:
cc -O -gdwarf-2 -I../lib -o ${TARGET} main.c ${LIBS}
cc -O -gdwarf-2 -I../lib -o ${TARGET}_epoll main_epoll.c ${LIBS}
.PHONY: clean
clean:

View File

@ -128,8 +128,7 @@ FF_SRCS+= \
ff_syscall_wrapper.c \
ff_subr_prf.c \
ff_vfs_ops.c \
ff_veth.c \
ff_epoll.c
ff_veth.c
FF_HOST_SRCS+= \
ff_host_interface.c \
@ -138,6 +137,7 @@ FF_HOST_SRCS+= \
ff_dpdk_if.c \
ff_dpdk_kni.c \
ff_dpdk_pcap.c \
ff_epoll.c \
ff_init.c
ifdef FF_IPSEC

View File

@ -101,6 +101,9 @@ int ff_poll(struct pollfd fds[], nfds_t nfds, int timeout);
int ff_kqueue(void);
int ff_kevent(int kq, const struct kevent *changelist, int nchanges,
struct kevent *eventlist, int nevents, const struct timespec *timeout);
int ff_kevent_do_each(int kq, const struct kevent *changelist, int nchanges,
void *eventlist, int nevents, const struct timespec *timeout,
void (*do_each)(void **, struct kevent *));
#ifdef __cplusplus
}

View File

@ -29,10 +29,7 @@ ff_shutdown
ff_sysctl
ff_kqueue
ff_kevent
ff_epoll_create
ff_epoll_ctl
ff_epoll_wait
ff_epoll_close
ff_kevent_do_each
ff_veth_attach
ff_veth_detach
ff_veth_process_packet
@ -40,4 +37,4 @@ ff_mbuf_gethdr
ff_mbuf_get
ff_mbuf_free
ff_mbuf_copydata
ff_mbuf_tx_offload
ff_mbuf_tx_offload

View File

@ -1,34 +1,24 @@
#include <sys/param.h>
#include <sys/limits.h>
#include <sys/uio.h>
#include <sys/proc.h>
#include <sys/syscallsubr.h>
#include <sys/module.h>
#include <sys/param.h>
#include <sys/malloc.h>
#include <sys/socketvar.h>
#include <sys/event.h>
#include <sys/kernel.h>
#include <sys/refcount.h>
#include <sys/sysctl.h>
#include <sys/pcpu.h>
#include <sys/select.h>
#include <sys/poll.h>
#include <sys/event.h>
#include <sys/file.h>
#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>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/ttycom.h>
#include <sys/filio.h>
#include <sys/sysproto.h>
#include <sys/fcntl.h>
#include <machine/stdarg.h>
#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>
#include "ff_api.h"
#include "ff_epoll.h"
#include "ff_errno.h"
#include "ff_host_interface.h"
int
@ -37,16 +27,16 @@ ff_epoll_create(int size __attribute__((__unused__)))
return ff_kqueue();
}
int
ff_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
{
struct kevent kev[3];
if (!event && op != EPOLL_CTL_DEL) {
ff_os_errno(ff_EINVAL);
errno = EINVAL;
return -1;
}
struct kevent kev[3];
if (op == EPOLL_CTL_ADD){
EV_SET(&kev[0], fd, EVFILT_READ,
EV_ADD | (event->events & EPOLLIN ? 0 : EV_DISABLE), 0, 0, NULL);
@ -66,62 +56,48 @@ ff_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
EV_SET(&kev[2], fd, EVFILT_USER, 0,
NOTE_FFCOPY | (event->events & EPOLLRDHUP ? 1 : 0), 0, NULL);
} else {
ff_os_errno(ff_EINVAL);
errno = EINVAL;
return -1;
}
return ff_kevent(epfd, kev, 3, NULL, 0, NULL);
}
static void
ff_event_to_epoll(void **ev, struct kevent *kev)
{
unsigned int event_one = 0;
struct epoll_event **ppev = (struct epoll_event **)ev;
if (kev->filter & EVFILT_READ) {
event_one |= EPOLLIN;
}
if (kev->filter & EVFILT_WRITE) {
event_one |= EPOLLOUT;
}
if (kev->flags & EV_ERROR) {
event_one |= EPOLLERR;
}
if (kev->flags & EV_EOF) {
event_one |= EPOLLIN;
}
(*ppev)->events = event_one;
(*ppev)->data.fd = kev->ident;
(*ppev)++;
}
int
ff_epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
{
int i, ret;
if (!events || maxevents < 1) {
ff_os_errno(ff_EINVAL);
errno = EINVAL;
return -1;
}
struct kevent *evlist = malloc(sizeof(struct kevent)*maxevents, M_DEVBUF, M_ZERO|M_NOWAIT);
if(NULL == evlist){
ff_os_errno(ff_EINVAL);
return -1;
}
memset(evlist, 0, sizeof(struct kevent)*maxevents);
int ret = ff_kevent(epfd, NULL, 0, evlist, maxevents, NULL);
if (ret == -1) {
free(evlist, M_DEVBUF);
return ret;
}
unsigned int event_one = 0;
for (int i = 0; i < ret; ++i) {
event_one = 0;
if (evlist[i].filter & EVFILT_READ) {
event_one |= EPOLLIN;
}
if (evlist[i].filter & EVFILT_WRITE) {
event_one |= EPOLLOUT;
}
if (evlist[i].flags & EV_ERROR) {
event_one |= EPOLLERR;
}
if (evlist[i].flags & EV_EOF) {
event_one |= EPOLLIN;
}
events[i].events = event_one;
events[i].data.fd = evlist[i].ident;
}
free(evlist, M_DEVBUF);
return ret;
}
int
ff_epoll_close(int epfd)
{
return ff_close(epfd);
return ff_kevent_do_each(epfd, NULL, 0, events, maxevents, NULL, ff_event_to_epoll);
}

View File

@ -1,73 +1,11 @@
#ifndef _FF_EPOLL_H
#define _FF_EPOLL_H
//#include <sys/stdint.h>
//#include <sys/queue.h>
#include <sys/epoll.h>
#ifndef _KERNEL
#include <stdint.h>
#else
#include <sys/stdint.h>
#include <sys/types.h>
#endif
enum EPOLL_EVENTS
{
EPOLLIN = 0x001,
#define EPOLLIN EPOLLIN
EPOLLPRI = 0x002,
#define EPOLLPRI EPOLLPRI
EPOLLOUT = 0x004,
#define EPOLLOUT EPOLLOUT
EPOLLRDNORM = 0x040,
#define EPOLLRDNORM EPOLLRDNORM
EPOLLRDBAND = 0x080,
#define EPOLLRDBAND EPOLLRDBAND
EPOLLWRNORM = 0x100,
#define EPOLLWRNORM EPOLLWRNORM
EPOLLWRBAND = 0x200,
#define EPOLLWRBAND EPOLLWRBAND
EPOLLMSG = 0x400,
#define EPOLLMSG EPOLLMSG
EPOLLERR = 0x008,
#define EPOLLERR EPOLLERR
EPOLLHUP = 0x010,
#define EPOLLHUP EPOLLHUP
EPOLLRDHUP = 0x2000,
#define EPOLLRDHUP EPOLLRDHUP
EPOLLWAKEUP = 1u << 29,
#define EPOLLWAKEUP EPOLLWAKEUP
EPOLLONESHOT = 1u << 30,
#define EPOLLONESHOT EPOLLONESHOT
EPOLLET = 1u << 31
#define EPOLLET EPOLLET
};
/* Valid opcodes ( "op" parameter ) to issue to epoll_ctl(). */
#define EPOLL_CTL_ADD 1 /* Add a file descriptor to the interface. */
#define EPOLL_CTL_DEL 2 /* Remove a file descriptor from the interface. */
#define EPOLL_CTL_MOD 3 /* Change file descriptor epoll_event structure. */
typedef union epoll_data
{
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t;
struct epoll_event
{
uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};
/*warpper epoll api.*/
int ff_epoll_create(int size);
int ff_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
int ff_epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
int ff_epoll_close(int epfd);
int ff_epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
#endif

View File

@ -936,20 +936,31 @@ struct sys_kevent_args {
int fd;
const struct kevent *changelist;
int nchanges;
struct kevent *eventlist;
void *eventlist;
int nevents;
const struct timespec *timeout;
void (*do_each)(void **, struct kevent *);
};
static int
kevent_copyout(void *arg, struct kevent *kevp, int count)
{
int i;
struct kevent *ke, **el;
struct sys_kevent_args *uap;
uap = (struct sys_kevent_args *)arg;
bcopy(kevp, uap->eventlist, count * sizeof *kevp);
uap->eventlist += count;
for (ke = kevp, i = 0; i < count; i++, ke++) {
if (uap->do_each) {
uap->do_each(&(uap->eventlist), ke);
} else {
el = (struct kevent **)(&uap->eventlist);
**el = *ke;
(*el)++;
}
}
return (0);
}
@ -971,21 +982,25 @@ kevent_copyin(void *arg, struct kevent *kevp, int count)
}
int
ff_kevent(int kq, const struct kevent *changelist, int nchanges,
struct kevent *eventlist, int nevents, const struct timespec *timeout)
ff_kevent_do_each(int kq, const struct kevent *changelist, int nchanges,
void *eventlist, int nevents, const struct timespec *timeout,
void (*do_each)(void **, struct kevent *))
{
int rc;
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = 0;
struct sys_kevent_args ska = {
kq,
changelist,
nchanges,
eventlist,
nevents,
&ts
&ts,
do_each
};
struct kevent_copyops k_ops = {
&ska,
kevent_copyout,
@ -1002,3 +1017,11 @@ kern_fail:
ff_os_errno(rc);
return (-1);
}
int
ff_kevent(int kq, const struct kevent *changelist, int nchanges,
struct kevent *eventlist, int nevents, const struct timespec *timeout)
{
return ff_kevent_do_each(kq, changelist, nchanges, eventlist, nevents, timeout, NULL);
}