PERFORCE change 123595 for review
Roman Divacky
rdivacky at FreeBSD.org
Mon Jul 16 15:57:31 UTC 2007
http://perforce.freebsd.org/chv.cgi?CH=123595
Change 123595 by rdivacky at rdivacky_witten on 2007/07/16 15:56:33
Epoll milestone.. Implement epoll_ctl in a way that seems to work ;) Please DONT
bother reviewing this as this is really WIP. I just want to have this milestone commited.
Affected files ...
.. //depot/projects/soc2007/rdivacky/linux_epoll/sys/compat/linux/linux_epoll.c#4 edit
.. //depot/projects/soc2007/rdivacky/linux_epoll/sys/compat/linux/linux_epoll.h#4 edit
Differences ...
==== //depot/projects/soc2007/rdivacky/linux_epoll/sys/compat/linux/linux_epoll.c#4 (text+ko) ====
@@ -29,33 +29,174 @@
#include "opt_compat.h"
-#include <linux_epoll.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#include <sys/event.h>
+#include <sys/sysproto.h>
+#include <sys/syscallsubr.h>
+#include <sys/timespec.h>
+#include <compat/linux/linux_epoll.h>
#ifdef COMPAT_LINUX32
#include <machine/../linux32/linux.h>
+#include <machine/../linux32/linux32_proto.h>
#else
#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
#endif
int
linux_epoll_create(struct thread *td, struct linux_epoll_create_args *args)
{
- struct kqueue_args args;
+ struct kqueue_args k_args;
/* XXX: args->size is ignored. Linux ignores it as well. */
- return kqueue(td, args);
+ return kqueue(td, &k_args);
+}
+
+static void
+linux_epoll_to_kevent(int fd, struct linux_epoll_event *event, struct kevent *kevent)
+{
+ int filter = 0;
+ int flags = kevent->flags;
+
+ if (event->events & LINUX_EPOLLIN)
+ filter |= EVFILT_READ;
+ if (event->events & LINUX_EPOLLOUT)
+ filter |= EVFILT_WRITE;
+ if (event->events & LINUX_EPOLLPRI)
+ filter |= EVFILT_READ;
+ if (event->events & LINUX_EPOLLET) /* XXX: ? */
+ flags |= EV_CLEAR;
+ if (event->events & LINUX_EPOLLONESHOT)
+ flags |= EV_ONESHOT;
+
+ EV_SET(kevent, fd, filter, flags, 0, 0, 0);
+}
+
+static void
+linux_kevent_to_epoll(struct kevent *kevent, struct linux_epoll_event *event)
+{
+ /* XXX: testing only!!! */
+ if (kevent->data > 0)
+ event->events = LINUX_EPOLLIN;
+
+ event->data = LINUX_EPOLL_CTL_ADD;
+}
+
+static int
+linux_kev_copyout(void *arg, struct kevent *kevp, int count)
+{
+ struct kevent_args *uap;
+ struct linux_epoll_event *eep;
+ int error, i;
+
+ uap = (struct kevent_args*) arg;
+ printf("Copyout: %i\n", count);
+
+ eep = malloc(sizeof(*eep) * count, M_TEMP, M_WAITOK | M_ZERO);
+
+ for (i = 0; i < count; i++) {
+ linux_kevent_to_epoll(&kevp[i], &eep[i]);
+ }
+
+ error = copyout(eep, uap->changelist, count * sizeof(*eep));
+ if (error)
+ uap->eventlist += count;
+
+ free(eep, M_TEMP);
+ return (0);
+}
+
+static int
+linux_kev_copyin(void *arg, struct kevent *kevp, int count)
+{
+ struct kevent_args *uap;
+
+ uap = (struct kevent_args*) arg;
+ printf("count: %i\n", count);
+
+ memcpy(kevp, uap->changelist, count * sizeof(*kevp));
+
+ printf("KeventX: %i, %i, %i, %i\n", kevp->ident, kevp->filter, kevp->flags, kevp->fflags);
+ printf("KeventY: %i, %i, %i, %i\n", uap->changelist->ident, uap->changelist->filter, uap->changelist->flags, uap->changelist->fflags);
+
+ uap->changelist += count;
+
+ return (0);
}
+
int
linux_epoll_ctl(struct thread *td, struct linux_epoll_ctl_args *args)
{
- return (ENOSYS);
+ struct kevent_args k_args;
+ struct kevent kev;
+ struct kevent_copyops k_ops = { &k_args,
+ linux_kev_copyout,
+ linux_kev_copyin};
+ struct linux_epoll_event le;
+ int error;
+
+ error = copyin(args->event, &le, sizeof(le));
+ if (error)
+ return (error);
+ printf("epoll_ctl: %i, %i, %i, %u\n", args->epfd, args->op,
+ args->fd, le.events);
+ k_args.fd = args->epfd;
+ k_args.changelist = &kev; /* epoll can register only 1 filter at once*/
+ k_args.nchanges = 1;
+ k_args.eventlist = NULL;
+ k_args.nevents = 0;
+ k_args.timeout = NULL;
+
+ switch (args->op) {
+ case LINUX_EPOLL_CTL_ADD:
+ kev.flags = EV_ADD | EV_ENABLE;
+ break;
+ case LINUX_EPOLL_CTL_MOD:
+ /* XXX: DELETE && ADD maybe? */
+ return (EINVAL);
+ break;
+ case LINUX_EPOLL_CTL_DEL:
+ kev.flags = EV_DELETE | EV_DISABLE;
+ break;
+ }
+ linux_epoll_to_kevent(args->fd, &le, &kev);
+
+ printf("Kevent: %i, %i, %i, %i\n", kev.ident, kev.filter, kev.flags, kev.fflags);
+ return kern_kevent(td, args->epfd, 1, 0, &k_ops, NULL);
}
int
linux_epoll_wait(struct thread *td, struct linux_epoll_wait_args *args)
{
- return (ENOSYS);
+ struct timespec ts;
+ struct kevent_args k_args;
+ struct kevent_copyops k_ops = { &k_args,
+ linux_kev_copyout,
+ linux_kev_copyin};
+ int error;
+
+ ts.tv_sec = args->timeout / 1000000;
+ ts.tv_nsec = (args->timeout % 1000000) * 1000;
+
+ k_args.fd = args->epfd;
+ k_args.changelist = NULL;
+ k_args.nchanges = 0;
+ /*
+ * we dont mind the wrong type-cast because
+ * our copyout function handles this
+ */
+ k_args.eventlist = (struct kevent *)args->events;
+ k_args.nevents = args->maxevents;
+ k_args.timeout = &ts;
+
+ error = kern_kevent(td, args->epfd, 0, args->maxevents, &k_ops, &ts);
+
+ /* XXX: translation? */
+ return (error);
}
==== //depot/projects/soc2007/rdivacky/linux_epoll/sys/compat/linux/linux_epoll.h#4 (text+ko) ====
@@ -40,4 +40,14 @@
uint64_t data;
} EPOLL_PACKED;
+#define LINUX_EPOLLIN 0x001
+#define LINUX_EPOLLPRI 0x002
+#define LINUX_EPOLLOUT 0x004
+#define LINUX_EPOLLONESHOT (1 << 30)
+#define LINUX_EPOLLET (1 << 31)
+
+#define LINUX_EPOLL_CTL_ADD 1
+#define LINUX_EPOLL_CTL_DEL 2
+#define LINUX_EPOLL_CTL_MOD 3
+
#endif /* !_LINUX_EPOLL_H_ */
More information about the p4-projects
mailing list