mirror of https://github.com/F-Stack/f-stack.git
Merge pull request #37 from uvuv/devel
Epoll optimization: add ff_kevent_do_each()
This commit is contained in:
commit
a2d49456a2
|
@ -17,6 +17,7 @@ LIBS+= -Wl,--no-whole-archive -lrt -lm -ldl -lcrypto -pthread
|
||||||
TARGET="helloworld"
|
TARGET="helloworld"
|
||||||
all:
|
all:
|
||||||
cc -O -gdwarf-2 -I../lib -o ${TARGET} main.c ${LIBS}
|
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
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
|
|
|
@ -128,8 +128,7 @@ FF_SRCS+= \
|
||||||
ff_syscall_wrapper.c \
|
ff_syscall_wrapper.c \
|
||||||
ff_subr_prf.c \
|
ff_subr_prf.c \
|
||||||
ff_vfs_ops.c \
|
ff_vfs_ops.c \
|
||||||
ff_veth.c \
|
ff_veth.c
|
||||||
ff_epoll.c
|
|
||||||
|
|
||||||
FF_HOST_SRCS+= \
|
FF_HOST_SRCS+= \
|
||||||
ff_host_interface.c \
|
ff_host_interface.c \
|
||||||
|
@ -138,6 +137,7 @@ FF_HOST_SRCS+= \
|
||||||
ff_dpdk_if.c \
|
ff_dpdk_if.c \
|
||||||
ff_dpdk_kni.c \
|
ff_dpdk_kni.c \
|
||||||
ff_dpdk_pcap.c \
|
ff_dpdk_pcap.c \
|
||||||
|
ff_epoll.c \
|
||||||
ff_init.c
|
ff_init.c
|
||||||
|
|
||||||
ifdef FF_IPSEC
|
ifdef FF_IPSEC
|
||||||
|
|
|
@ -101,6 +101,9 @@ int ff_poll(struct pollfd fds[], nfds_t nfds, int timeout);
|
||||||
int ff_kqueue(void);
|
int ff_kqueue(void);
|
||||||
int ff_kevent(int kq, const struct kevent *changelist, int nchanges,
|
int ff_kevent(int kq, const struct kevent *changelist, int nchanges,
|
||||||
struct kevent *eventlist, int nevents, const struct timespec *timeout);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,10 +29,7 @@ ff_shutdown
|
||||||
ff_sysctl
|
ff_sysctl
|
||||||
ff_kqueue
|
ff_kqueue
|
||||||
ff_kevent
|
ff_kevent
|
||||||
ff_epoll_create
|
ff_kevent_do_each
|
||||||
ff_epoll_ctl
|
|
||||||
ff_epoll_wait
|
|
||||||
ff_epoll_close
|
|
||||||
ff_veth_attach
|
ff_veth_attach
|
||||||
ff_veth_detach
|
ff_veth_detach
|
||||||
ff_veth_process_packet
|
ff_veth_process_packet
|
||||||
|
|
104
lib/ff_epoll.c
104
lib/ff_epoll.c
|
@ -1,34 +1,24 @@
|
||||||
#include <sys/param.h>
|
#include <stdio.h>
|
||||||
#include <sys/limits.h>
|
#include <stdint.h>
|
||||||
#include <sys/uio.h>
|
#include <string.h>
|
||||||
#include <sys/proc.h>
|
#include <stdlib.h>
|
||||||
#include <sys/syscallsubr.h>
|
#include <stdarg.h>
|
||||||
#include <sys/module.h>
|
#include <sched.h>
|
||||||
#include <sys/param.h>
|
#include <fcntl.h>
|
||||||
#include <sys/malloc.h>
|
#include <errno.h>
|
||||||
#include <sys/socketvar.h>
|
#include <assert.h>
|
||||||
#include <sys/event.h>
|
#include <unistd.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 <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <netinet/tcp.h>
|
#include <sys/types.h>
|
||||||
#include <sys/ttycom.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/filio.h>
|
#include <sys/time.h>
|
||||||
#include <sys/sysproto.h>
|
#include <sys/select.h>
|
||||||
#include <sys/fcntl.h>
|
#include <sys/syscall.h>
|
||||||
#include <machine/stdarg.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <sys/epoll.h>
|
||||||
|
|
||||||
#include "ff_api.h"
|
#include "ff_api.h"
|
||||||
#include "ff_epoll.h"
|
|
||||||
#include "ff_errno.h"
|
#include "ff_errno.h"
|
||||||
#include "ff_host_interface.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -37,16 +27,16 @@ ff_epoll_create(int size __attribute__((__unused__)))
|
||||||
return ff_kqueue();
|
return ff_kqueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
ff_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
|
ff_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
|
||||||
{
|
{
|
||||||
|
struct kevent kev[3];
|
||||||
|
|
||||||
if (!event && op != EPOLL_CTL_DEL) {
|
if (!event && op != EPOLL_CTL_DEL) {
|
||||||
ff_os_errno(ff_EINVAL);
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct kevent kev[3];
|
|
||||||
if (op == EPOLL_CTL_ADD){
|
if (op == EPOLL_CTL_ADD){
|
||||||
EV_SET(&kev[0], fd, EVFILT_READ,
|
EV_SET(&kev[0], fd, EVFILT_READ,
|
||||||
EV_ADD | (event->events & EPOLLIN ? 0 : EV_DISABLE), 0, 0, NULL);
|
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,
|
EV_SET(&kev[2], fd, EVFILT_USER, 0,
|
||||||
NOTE_FFCOPY | (event->events & EPOLLRDHUP ? 1 : 0), 0, NULL);
|
NOTE_FFCOPY | (event->events & EPOLLRDHUP ? 1 : 0), 0, NULL);
|
||||||
} else {
|
} else {
|
||||||
ff_os_errno(ff_EINVAL);
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ff_kevent(epfd, kev, 3, NULL, 0, NULL);
|
return ff_kevent(epfd, kev, 3, NULL, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static void
|
||||||
ff_epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
|
ff_event_to_epoll(void **ev, struct kevent *kev)
|
||||||
{
|
{
|
||||||
if (!events || maxevents < 1) {
|
|
||||||
ff_os_errno(ff_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;
|
unsigned int event_one = 0;
|
||||||
for (int i = 0; i < ret; ++i) {
|
struct epoll_event **ppev = (struct epoll_event **)ev;
|
||||||
event_one = 0;
|
|
||||||
if (evlist[i].filter & EVFILT_READ) {
|
if (kev->filter & EVFILT_READ) {
|
||||||
event_one |= EPOLLIN;
|
event_one |= EPOLLIN;
|
||||||
}
|
}
|
||||||
if (evlist[i].filter & EVFILT_WRITE) {
|
if (kev->filter & EVFILT_WRITE) {
|
||||||
event_one |= EPOLLOUT;
|
event_one |= EPOLLOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (evlist[i].flags & EV_ERROR) {
|
if (kev->flags & EV_ERROR) {
|
||||||
event_one |= EPOLLERR;
|
event_one |= EPOLLERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (evlist[i].flags & EV_EOF) {
|
if (kev->flags & EV_EOF) {
|
||||||
event_one |= EPOLLIN;
|
event_one |= EPOLLIN;
|
||||||
}
|
}
|
||||||
events[i].events = event_one;
|
|
||||||
events[i].data.fd = evlist[i].ident;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(evlist, M_DEVBUF);
|
(*ppev)->events = event_one;
|
||||||
return ret;
|
(*ppev)->data.fd = kev->ident;
|
||||||
|
(*ppev)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ff_epoll_close(int epfd)
|
ff_epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
|
||||||
{
|
{
|
||||||
return ff_close(epfd);
|
int i, ret;
|
||||||
|
if (!events || maxevents < 1) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ff_kevent_do_each(epfd, NULL, 0, events, maxevents, NULL, ff_event_to_epoll);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,73 +1,11 @@
|
||||||
#ifndef _FF_EPOLL_H
|
#ifndef _FF_EPOLL_H
|
||||||
#define _FF_EPOLL_H
|
#define _FF_EPOLL_H
|
||||||
|
|
||||||
//#include <sys/stdint.h>
|
#include <sys/epoll.h>
|
||||||
//#include <sys/queue.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_create(int size);
|
||||||
int ff_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
|
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_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
|
||||||
int ff_epoll_close(int epfd);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -936,20 +936,30 @@ struct sys_kevent_args {
|
||||||
int fd;
|
int fd;
|
||||||
const struct kevent *changelist;
|
const struct kevent *changelist;
|
||||||
int nchanges;
|
int nchanges;
|
||||||
struct kevent *eventlist;
|
void *eventlist;
|
||||||
int nevents;
|
int nevents;
|
||||||
const struct timespec *timeout;
|
const struct timespec *timeout;
|
||||||
|
void (*do_each)(void **, struct kevent *);
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
kevent_copyout(void *arg, struct kevent *kevp, int count)
|
kevent_copyout(void *arg, struct kevent *kevp, int count)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
struct kevent *ke;
|
||||||
struct sys_kevent_args *uap;
|
struct sys_kevent_args *uap;
|
||||||
|
|
||||||
uap = (struct sys_kevent_args *)arg;
|
uap = (struct sys_kevent_args *)arg;
|
||||||
bcopy(kevp, uap->eventlist, count * sizeof *kevp);
|
|
||||||
|
|
||||||
uap->eventlist += count;
|
if (!uap->do_each) {
|
||||||
|
bcopy(kevp, uap->eventlist, count * sizeof *kevp);
|
||||||
|
uap->eventlist = (void *)((struct kevent *)(uap->eventlist) + count);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
for (ke = kevp, i = 0; i < count; i++, ke++) {
|
||||||
|
uap->do_each(&(uap->eventlist), ke);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
@ -971,21 +981,25 @@ kevent_copyin(void *arg, struct kevent *kevp, int count)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ff_kevent(int kq, const struct kevent *changelist, int nchanges,
|
ff_kevent_do_each(int kq, const struct kevent *changelist, int nchanges,
|
||||||
struct kevent *eventlist, int nevents, const struct timespec *timeout)
|
void *eventlist, int nevents, const struct timespec *timeout,
|
||||||
|
void (*do_each)(void **, struct kevent *))
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
ts.tv_sec = 0;
|
ts.tv_sec = 0;
|
||||||
ts.tv_nsec = 0;
|
ts.tv_nsec = 0;
|
||||||
|
|
||||||
struct sys_kevent_args ska = {
|
struct sys_kevent_args ska = {
|
||||||
kq,
|
kq,
|
||||||
changelist,
|
changelist,
|
||||||
nchanges,
|
nchanges,
|
||||||
eventlist,
|
eventlist,
|
||||||
nevents,
|
nevents,
|
||||||
&ts
|
&ts,
|
||||||
|
do_each
|
||||||
};
|
};
|
||||||
|
|
||||||
struct kevent_copyops k_ops = {
|
struct kevent_copyops k_ops = {
|
||||||
&ska,
|
&ska,
|
||||||
kevent_copyout,
|
kevent_copyout,
|
||||||
|
@ -1002,3 +1016,11 @@ kern_fail:
|
||||||
ff_os_errno(rc);
|
ff_os_errno(rc);
|
||||||
return (-1);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue