Add EV_MACHPORT support

This commit is contained in:
Lubos Dolezel 2017-04-18 17:07:59 +02:00
parent 9e2eb6157b
commit 2451eea5e8
3 changed files with 164 additions and 5 deletions

View File

@ -20,9 +20,12 @@ INCLUDE (CheckIncludeFiles)
project(kqueue)
if (DARLING)
include_directories("${CMAKE_SOURCE_DIR}/src/libc/include")
include_directories("${CMAKE_SOURCE_DIR}/src/libc/darwin")
include_directories("${CMAKE_SOURCE_DIR}/src/kernel/libsyscall/wrappers")
include_directories(
"${CMAKE_SOURCE_DIR}/src/libc/include"
"${CMAKE_SOURCE_DIR}/src/libc/darwin"
"${CMAKE_SOURCE_DIR}/src/kernel/libsyscall/wrappers"
"${CMAKE_SOURCE_DIR}/src/lkm"
)
# For epoll
include_directories("${CMAKE_SOURCE_DIR}/src/kernel/emulation/linux/ext")
@ -71,6 +74,7 @@ else()
src/linux/vnode.c
src/linux/write.c
src/linux/read.c
src/linux/machport.c
src/common/*.h
src/common/filter.c
src/common/knote.c

View File

@ -30,6 +30,7 @@ extern const struct filter evfilt_vnode;
extern const struct filter evfilt_proc;
extern const struct filter evfilt_timer;
extern const struct filter evfilt_user;
extern const struct filter evfilt_machport;
static int
filter_register(struct kqueue *kq, short filter, const struct filter *src)
@ -102,6 +103,7 @@ filter_register_all(struct kqueue *kq)
rv += filter_register(kq, EVFILT_PROC, &evfilt_proc);
rv += filter_register(kq, EVFILT_TIMER, &evfilt_timer);
rv += filter_register(kq, EVFILT_USER, &evfilt_user);
rv += filter_register(kq, EVFILT_MACHPORT, &evfilt_machport);
kq->kq_nfds++;
if (rv != 0) {
filter_unregister_all(kq);
@ -165,10 +167,12 @@ filter_name(short filt)
"EVFILT_PROC",
"EVFILT_SIGNAL",
"EVFILT_TIMER",
"EVFILT_NETDEV",
"EVFILT_MACHPORT",
"EVFILT_FS",
// "EVFILT_LIO",
"EVFILT_USER"
"EVFILT_USER",
// EVFILT_VM!
"EVFILT_NETDEV",
};
id = ~filt;

151
src/linux/machport.c Normal file
View File

@ -0,0 +1,151 @@
/*
* Copyright (c) 2017 Lubos Dolezel
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <errno.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <pthread.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
#include "api.h"
#include "private.h"
extern int lkm_call(int call_nr, void* arg);
int
evfilt_machport_copyout(struct kevent64_s *dst, struct knote *src, void *ptr)
{
struct epoll_event * const ev = (struct epoll_event *) ptr;
epoll_event_dump(ev);
kevent_int_to_64(&src->kev, dst);
dst->data = 1024; // TODO: dummy value (message size)
return (0);
}
int
evfilt_machport_knote_create(struct filter *filt, struct knote *kn)
{
struct epoll_event ev;
int port = kn->kev.ident;
struct eventfd_machport_attach args;
int rv;
/* Convert the kevent into an epoll_event */
kn->data.events = EPOLLIN;
kn->kn_epollfd = filter_epfd(filt);
memset(&ev, 0, sizeof(ev));
ev.events = kn->data.events;
ev.data.ptr = kn;
kn->kdata.kn_dupfd = eventfd(0, EFD_CLOEXEC);
args.port_name = port;
args.evfd = kn->kdata.kn_dupfd;
rv = lkm_call(NR_eventfd_machport_attach, &args);
if (rv != 0) {
dbg_printf("eventfd_machport_attach: %s", strerror(-rv));
return (-1);
}
if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_ADD, kn->kdata.kn_dupfd, &ev) < 0) {
dbg_printf("epoll_ctl(2): %s", strerror(errno));
return (-1);
}
return 0;
}
int
evfilt_machport_knote_modify(struct filter *filt, struct knote *kn,
const struct kevent64_s *kev)
{
return 0;
}
int
evfilt_machport_knote_delete(struct filter *filt, struct knote *kn)
{
if (kn->kev.flags & EV_DISABLE)
return (0);
else {
int rv;
struct eventfd_machport_detach args = {
.port_name = kn->kev.ident,
.evfd = kn->kdata.kn_dupfd
};
rv = lkm_call(NR_eventfd_machport_detach, &args);
if (rv != 0) {
dbg_printf("eventfd_machport_detach: %s", strerror(-rv));
}
if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_DEL, kn->kdata.kn_dupfd, NULL) < 0) {
dbg_perror("epoll_ctl(2)");
return (-1);
}
(void) close(kn->kdata.kn_dupfd);
kn->kdata.kn_dupfd = -1;
return 0;
}
}
int
evfilt_machport_knote_enable(struct filter *filt, struct knote *kn)
{
struct epoll_event ev;
memset(&ev, 0, sizeof(ev));
ev.events = kn->data.events;
ev.data.ptr = kn;
if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_ADD, kn->kdata.kn_dupfd, &ev) < 0) {
dbg_perror("epoll_ctl(2)");
return (-1);
}
return (0);
}
int
evfilt_machport_knote_disable(struct filter *filt, struct knote *kn)
{
if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_DEL, kn->kdata.kn_dupfd, NULL) < 0) {
dbg_perror("epoll_ctl(2)");
return (-1);
}
return (0);
}
const struct filter evfilt_machport = {
EVFILT_MACHPORT,
NULL,
NULL,
evfilt_machport_copyout,
evfilt_machport_knote_create,
evfilt_machport_knote_modify,
evfilt_machport_knote_delete,
evfilt_machport_knote_enable,
evfilt_machport_knote_disable,
};