Page MenuHomeFreeBSD

D3308.id7674.diff
No OneTemporary

D3308.id7674.diff

Index: sys/compat/cloudabi64/cloudabi64_poll.c
===================================================================
--- sys/compat/cloudabi64/cloudabi64_poll.c
+++ sys/compat/cloudabi64/cloudabi64_poll.c
@@ -26,22 +26,258 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/syscallsubr.h>
+
+#include <compat/cloudabi/cloudabi_util.h>
+
#include <compat/cloudabi64/cloudabi64_syscalldefs.h>
#include <compat/cloudabi64/cloudabi64_proto.h>
+/* Converts a FreeBSD signal number to a CloudABI signal number. */
+static cloudabi_signal_t
+convert_signal(int sig)
+{
+ static const cloudabi_signal_t signals[] = {
+ [SIGABRT] = CLOUDABI_SIGABRT,
+ [SIGALRM] = CLOUDABI_SIGALRM,
+ [SIGBUS] = CLOUDABI_SIGBUS,
+ [SIGCHLD] = CLOUDABI_SIGCHLD,
+ [SIGCONT] = CLOUDABI_SIGCONT,
+ [SIGFPE] = CLOUDABI_SIGFPE,
+ [SIGHUP] = CLOUDABI_SIGHUP,
+ [SIGILL] = CLOUDABI_SIGILL,
+ [SIGINT] = CLOUDABI_SIGINT,
+ [SIGKILL] = CLOUDABI_SIGKILL,
+ [SIGPIPE] = CLOUDABI_SIGPIPE,
+ [SIGQUIT] = CLOUDABI_SIGQUIT,
+ [SIGSEGV] = CLOUDABI_SIGSEGV,
+ [SIGSTOP] = CLOUDABI_SIGSTOP,
+ [SIGSYS] = CLOUDABI_SIGSYS,
+ [SIGTERM] = CLOUDABI_SIGTERM,
+ [SIGTRAP] = CLOUDABI_SIGTRAP,
+ [SIGTSTP] = CLOUDABI_SIGTSTP,
+ [SIGTTIN] = CLOUDABI_SIGTTIN,
+ [SIGTTOU] = CLOUDABI_SIGTTOU,
+ [SIGURG] = CLOUDABI_SIGURG,
+ [SIGUSR1] = CLOUDABI_SIGUSR1,
+ [SIGUSR2] = CLOUDABI_SIGUSR2,
+ [SIGVTALRM] = CLOUDABI_SIGVTALRM,
+ [SIGXCPU] = CLOUDABI_SIGXCPU,
+ [SIGXFSZ] = CLOUDABI_SIGXFSZ,
+ };
+
+ /* Convert unknown signals to SIGABRT. */
+ if (sig < 0 || sig >= nitems(signals) || signals[sig] == 0)
+ return (SIGABRT);
+ return (signals[sig]);
+}
+
+struct cloudabi64_kevent_args {
+ const cloudabi64_subscription_t *in;
+ cloudabi64_event_t *out;
+ bool once;
+};
+
+/* Converts CloudABI's subscription objects to FreeBSD's struct kevent. */
+static int
+cloudabi64_kevent_copyin(void *arg, struct kevent *kevp, int count)
+{
+ cloudabi64_subscription_t sub;
+ struct cloudabi64_kevent_args *args;
+ cloudabi_timestamp_t ts;
+ int error;
+
+ args = arg;
+ while (count-- > 0) {
+ error = copyin(args->in++, &sub, sizeof(sub));
+ if (error != 0)
+ return (error);
+
+ memset(kevp, '\0', sizeof(kevp));
+ kevp->udata = (void *)sub.userdata;
+ switch (sub.type) {
+ case CLOUDABI_EVENTTYPE_CLOCK:
+ kevp->filter = EVFILT_TIMER;
+ kevp->ident = sub.clock.identifier;
+ kevp->fflags = NOTE_NSECONDS;
+ if ((sub.clock.flags &
+ CLOUDABI_SUBSCRIPTION_CLOCK_ABSTIME) != 0 &&
+ sub.clock.timeout > 0) {
+ /* Convert absolute timestamp to a relative. */
+ error = cloudabi_clock_time_get(curthread,
+ sub.clock.clock_id, &ts);
+ if (error != 0)
+ return (error);
+ ts = ts > sub.clock.timeout ? 0 :
+ sub.clock.timeout - ts;
+ } else {
+ /* Relative timestamp. */
+ ts = sub.clock.timeout;
+ }
+ kevp->data = ts > INTPTR_MAX ? INTPTR_MAX : ts;
+ break;
+ case CLOUDABI_EVENTTYPE_FD_READ:
+ kevp->filter = EVFILT_READ;
+ kevp->ident = sub.fd_readwrite.fd;
+ if ((sub.fd_readwrite.flags &
+ CLOUDABI_SUBSCRIPTION_FD_READWRITE_POLL) != 0)
+ kevp->fflags = NOTE_FILE_POLL;
+ break;
+ case CLOUDABI_EVENTTYPE_FD_WRITE:
+ kevp->filter = EVFILT_WRITE;
+ kevp->ident = sub.fd_readwrite.fd;
+ break;
+ case CLOUDABI_EVENTTYPE_PROC_TERMINATE:
+ kevp->filter = EVFILT_PROCDESC;
+ kevp->ident = sub.proc_terminate.fd;
+ kevp->fflags = NOTE_EXIT;
+ break;
+ }
+ if (args->once) {
+ /* Ignore flags. Simply use oneshot mode. */
+ kevp->flags = EV_ADD | EV_ONESHOT;
+ } else {
+ /* Translate flags. */
+ if ((sub.flags & CLOUDABI_SUBSCRIPTION_ADD) != 0)
+ kevp->flags |= EV_ADD;
+ if ((sub.flags & CLOUDABI_SUBSCRIPTION_CLEAR) != 0)
+ kevp->flags |= EV_CLEAR;
+ if ((sub.flags & CLOUDABI_SUBSCRIPTION_DELETE) != 0)
+ kevp->flags |= EV_DELETE;
+ if ((sub.flags & CLOUDABI_SUBSCRIPTION_DISABLE) != 0)
+ kevp->flags |= EV_DISABLE;
+ if ((sub.flags & CLOUDABI_SUBSCRIPTION_ENABLE) != 0)
+ kevp->flags |= EV_ENABLE;
+ if ((sub.flags & CLOUDABI_SUBSCRIPTION_ONESHOT) != 0)
+ kevp->flags |= EV_ONESHOT;
+ }
+ ++kevp;
+ }
+ return (0);
+}
+
+/* Converts FreeBSD's struct kevent to CloudABI's event objects. */
+static int
+cloudabi64_kevent_copyout(void *arg, struct kevent *kevp, int count)
+{
+ cloudabi64_event_t ev;
+ struct cloudabi64_kevent_args *args;
+ int error;
+
+ args = arg;
+ while (count-- > 0) {
+ /* Convert fields that should always be present. */
+ memset(&ev, '\0', sizeof(ev));
+ ev.userdata = (uintptr_t)kevp->udata;
+ switch (kevp->filter) {
+ case EVFILT_TIMER:
+ ev.type = CLOUDABI_EVENTTYPE_CLOCK;
+ ev.clock.identifier = kevp->ident;
+ break;
+ case EVFILT_READ:
+ ev.type = CLOUDABI_EVENTTYPE_FD_READ;
+ ev.fd_readwrite.fd = kevp->ident;
+ break;
+ case EVFILT_WRITE:
+ ev.type = CLOUDABI_EVENTTYPE_FD_WRITE;
+ ev.fd_readwrite.fd = kevp->ident;
+ break;
+ case EVFILT_PROCDESC:
+ ev.type = CLOUDABI_EVENTTYPE_PROC_TERMINATE;
+ ev.proc_terminate.fd = kevp->ident;
+ break;
+ }
+
+ if ((kevp->flags & EV_ERROR) == 0) {
+ /* Success. */
+ switch (kevp->filter) {
+ case EVFILT_READ:
+ case EVFILT_WRITE:
+ ev.fd_readwrite.nbytes = kevp->data;
+ if ((kevp->flags & EV_EOF) != 0) {
+ ev.fd_readwrite.flags |=
+ CLOUDABI_EVENT_FD_READWRITE_HANGUP;
+ }
+ break;
+ case EVFILT_PROCDESC:
+ if (WIFSIGNALED(kevp->data)) {
+ /* Process got signalled. */
+ ev.proc_terminate.signal =
+ convert_signal(WTERMSIG(kevp->data));
+ ev.proc_terminate.exitcode = 0;
+ } else {
+ /* Process exited. */
+ ev.proc_terminate.signal = 0;
+ ev.proc_terminate.exitcode =
+ WEXITSTATUS(kevp->data);
+ }
+ break;
+ }
+ } else {
+ /* Error. */
+ ev.error = cloudabi_convert_errno(kevp->data);
+ }
+ ++kevp;
+
+ error = copyout(&ev, args->out++, sizeof(ev));
+ if (error != 0)
+ return (error);
+ }
+ return (0);
+}
+
int
cloudabi64_sys_poll(struct thread *td, struct cloudabi64_sys_poll_args *uap)
{
+ struct cloudabi64_kevent_args args = {
+ .in = uap->in,
+ .out = uap->out,
+ .once = true,
+ };
+ struct kevent_copyops copyops = {
+ .k_copyin = cloudabi64_kevent_copyin,
+ .k_copyout = cloudabi64_kevent_copyout,
+ .arg = &args,
+ };
- /* Not implemented. */
- return (ENOSYS);
+ return (kern_kevent_anonymous(td, uap->nevents, &copyops));
}
int
cloudabi64_sys_poll_fd(struct thread *td,
struct cloudabi64_sys_poll_fd_args *uap)
{
+ struct cloudabi64_kevent_args args = {
+ .in = uap->in,
+ .out = uap->out,
+ .once = false,
+ };
+ struct kevent_copyops copyops = {
+ .k_copyin = cloudabi64_kevent_copyin,
+ .k_copyout = cloudabi64_kevent_copyout,
+ .arg = &args,
+ };
+ cloudabi64_subscription_t subtimo;
+ struct timespec timeout;
+ int error;
- /* Not implemented. */
- return (ENOSYS);
+ if (uap->timeout != NULL) {
+ /* Poll with a timeout. */
+ error = copyin(uap->timeout, &subtimo, sizeof(subtimo));
+ if (error != 0)
+ return (error);
+ if (subtimo.type != CLOUDABI_EVENTTYPE_CLOCK ||
+ subtimo.clock.flags != 0)
+ return (EINVAL);
+ timeout.tv_sec = subtimo.clock.timeout / 1000000000;
+ timeout.tv_nsec = subtimo.clock.timeout % 1000000000;
+ return (kern_kevent(td, uap->fd, uap->nin, uap->nout, &copyops,
+ &timeout));
+ } else {
+ /* Poll without a timeout. */
+ return (kern_kevent(td, uap->fd, uap->nin, uap->nout, &copyops,
+ NULL));
+ }
}

File Metadata

Mime Type
text/plain
Expires
Tue, Jul 7, 4:29 AM (15 h, 56 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34783143
Default Alt Text
D3308.id7674.diff (7 KB)

Event Timeline