diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/cmd/devfsadm/misc_link.c | 3 | ||||
-rw-r--r-- | usr/src/lib/libc/amd64/Makefile | 1 | ||||
-rw-r--r-- | usr/src/lib/libc/i386/Makefile.com | 1 | ||||
-rw-r--r-- | usr/src/lib/libc/port/mapfile-vers | 3 | ||||
-rw-r--r-- | usr/src/lib/libc/port/sys/eventfd.c | 65 | ||||
-rw-r--r-- | usr/src/lib/libc/sparc/Makefile.com | 1 | ||||
-rw-r--r-- | usr/src/man/man3c/Makefile | 1 | ||||
-rw-r--r-- | usr/src/man/man3c/eventfd.3c | 161 | ||||
-rw-r--r-- | usr/src/man/man5/Makefile | 1 | ||||
-rw-r--r-- | usr/src/man/man5/eventfd.5 | 34 | ||||
-rw-r--r-- | usr/src/uts/common/Makefile.files | 2 | ||||
-rw-r--r-- | usr/src/uts/common/io/eventfd.c | 411 | ||||
-rw-r--r-- | usr/src/uts/common/io/eventfd.conf | 16 | ||||
-rw-r--r-- | usr/src/uts/common/sys/Makefile | 1 | ||||
-rw-r--r-- | usr/src/uts/common/sys/eventfd.h | 68 | ||||
-rw-r--r-- | usr/src/uts/intel/Makefile.intel | 1 | ||||
-rw-r--r-- | usr/src/uts/intel/eventfd/Makefile | 68 | ||||
-rw-r--r-- | usr/src/uts/sparc/Makefile.sparc | 1 | ||||
-rw-r--r-- | usr/src/uts/sparc/eventfd/Makefile | 68 |
19 files changed, 907 insertions, 0 deletions
diff --git a/usr/src/cmd/devfsadm/misc_link.c b/usr/src/cmd/devfsadm/misc_link.c index 70599d6039..9f4c20ac5e 100644 --- a/usr/src/cmd/devfsadm/misc_link.c +++ b/usr/src/cmd/devfsadm/misc_link.c @@ -89,6 +89,9 @@ static devfsadm_create_t misc_cbt[] = { { "pseudo", "ddi_pseudo", "consms", TYPE_EXACT | DRV_EXACT, ILEVEL_0, consms }, + { "pseudo", "ddi_pseudo", "eventfd", + TYPE_EXACT | DRV_EXACT, ILEVEL_0, minor_name + }, { "pseudo", "ddi_pseudo", "rsm", TYPE_EXACT | DRV_EXACT, ILEVEL_0, minor_name }, diff --git a/usr/src/lib/libc/amd64/Makefile b/usr/src/lib/libc/amd64/Makefile index 9a496b0d7e..12fe1429fb 100644 --- a/usr/src/lib/libc/amd64/Makefile +++ b/usr/src/lib/libc/amd64/Makefile @@ -858,6 +858,7 @@ PORTSYS= \ execl.o \ execle.o \ execv.o \ + eventfd.o \ fcntl.o \ getpagesizes.o \ getpeerucred.o \ diff --git a/usr/src/lib/libc/i386/Makefile.com b/usr/src/lib/libc/i386/Makefile.com index 01f71c334c..b6a9c822c6 100644 --- a/usr/src/lib/libc/i386/Makefile.com +++ b/usr/src/lib/libc/i386/Makefile.com @@ -892,6 +892,7 @@ PORTSYS= \ chown.o \ corectl.o \ epoll.o \ + eventfd.o \ exacctsys.o \ execl.o \ execle.o \ diff --git a/usr/src/lib/libc/port/mapfile-vers b/usr/src/lib/libc/port/mapfile-vers index 70d37d04be..09db2c67e4 100644 --- a/usr/src/lib/libc/port/mapfile-vers +++ b/usr/src/lib/libc/port/mapfile-vers @@ -2815,6 +2815,9 @@ $endif epoll_pwait; _errfp; _errxfp; + eventfd; + eventfd_read; + eventfd_write; exportfs; _F_cplx_div; _F_cplx_div_ix; diff --git a/usr/src/lib/libc/port/sys/eventfd.c b/usr/src/lib/libc/port/sys/eventfd.c new file mode 100644 index 0000000000..bd2eba4efa --- /dev/null +++ b/usr/src/lib/libc/port/sys/eventfd.c @@ -0,0 +1,65 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014, Joyent, Inc. All rights reserved. + */ + +#include <sys/eventfd.h> +#include <sys/stat.h> +#include <unistd.h> +#include <errno.h> +#include <fcntl.h> + +int +eventfd(unsigned int initval, int flags) +{ + int oflags = O_RDWR; + uint64_t val = initval; + int fd; + + if (flags & ~(EFD_NONBLOCK | EFD_CLOEXEC | EFD_SEMAPHORE)) + return (EINVAL); + + if (flags & EFD_NONBLOCK) + oflags |= O_NONBLOCK; + + if (flags & EFD_CLOEXEC) + oflags |= O_CLOEXEC; + + if ((fd = open("/dev/eventfd", oflags)) < 0) + return (-1); + + if ((flags & EFD_SEMAPHORE) && + ioctl(fd, EVENTFDIOC_SEMAPHORE, 0) != 0) { + (void) close(fd); + return (-1); + } + + if (write(fd, &val, sizeof (val)) < sizeof (val)) { + (void) close(fd); + return (-1); + } + + return (fd); +} + +int +eventfd_read(int fd, eventfd_t *valp) +{ + return (read(fd, valp, sizeof (*valp)) < sizeof (*valp) ? -1 : 0); +} + +int +eventfd_write(int fd, eventfd_t val) +{ + return (write(fd, &val, sizeof (val)) < sizeof (val) ? -1 : 0); +} diff --git a/usr/src/lib/libc/sparc/Makefile.com b/usr/src/lib/libc/sparc/Makefile.com index 4c5bbcfc96..11ad0b3996 100644 --- a/usr/src/lib/libc/sparc/Makefile.com +++ b/usr/src/lib/libc/sparc/Makefile.com @@ -926,6 +926,7 @@ PORTSYS= \ chown.o \ corectl.o \ epoll.o \ + eventfd.o \ exacctsys.o \ execl.o \ execle.o \ diff --git a/usr/src/man/man3c/Makefile b/usr/src/man/man3c/Makefile index bb75c1d4b6..55fd0615df 100644 --- a/usr/src/man/man3c/Makefile +++ b/usr/src/man/man3c/Makefile @@ -113,6 +113,7 @@ MANFILES= __fbufsize.3c \ epoll_wait.3c \ err.3c \ euclen.3c \ + eventfd.3c \ exit.3c \ fattach.3c \ fclose.3c \ diff --git a/usr/src/man/man3c/eventfd.3c b/usr/src/man/man3c/eventfd.3c new file mode 100644 index 0000000000..6e7d1c6a5b --- /dev/null +++ b/usr/src/man/man3c/eventfd.3c @@ -0,0 +1,161 @@ +'\" te +.\" Copyright (c) 2014, Joyent, Inc. All Rights Reserved. +.\" This file and its contents are supplied under the terms of the +.\" Common Development and Distribution License ("CDDL"), version 1.0. +.\" You may only use this file in accordance with the terms of version +.\" 1.0 of the CDDL. +.\" +.\" A full copy of the text of the CDDL should have accompanied this +.\" source. A copy of the CDDL is also available via the Internet at +.\" http://www.illumos.org/license/CDDL. +.TH EVENTFD 3C "Dec 3, 2014" +.SH NAME +eventfd \- create a file descriptor for event notification +.SH SYNOPSIS + +.LP +.nf +#include <sys/eventfd.h> + +\fBint\fR \fBeventfd\fR(\fBunsigned int\fR \fIinitval\fR, \fBint\fR \fIflags\fR); +.fi + +.SH DESCRIPTION +.sp +.LP +The \fBeventfd()\fR function creates an \fBeventfd\fR(5) instance that +has an associated 64-bit unsigned counter. It returns a file descriptor +that can be operated upon via \fBread\fR(2), \fBwrite\fR(2) and the facilities +that notify of file descriptor activity (e.g., \fBpoll\fR(2), +\fBport_get\fR(3C), \fBepoll_wait\fR(3C)). To dispose of the instance, +\fBclose\fR(2) should be called on the file descriptor. + +The \fIinitval\fR argument specifies the +initial value of the 64-bit counter associated with the instance. (Note +that this limits the initial value to be a 32-bit quantity despite the +fact that the underlying counter is 64-bit.) + +The \fIflags\fR argument specifies additional parameters for the +instance, and can have any of the following values: + +.sp +.ne 2 +.na +\fBEFD_CLOEXEC\fR +.ad +.RS 12n +Instance will be closed upon an +\fBexec\fR(2); see \fBopen\fR(2)'s description of \fBO_CLOEXEC\fR. +.RE + +.sp +.ne 2 +.na +\fBEFD_NONBLOCK\fR +.ad +.RS 12n +Instance will be set to be non-blocking. A \fBread\fR(2) on an +\fBeventfd\fR instance that has been initialized with +\fBEFD_NONBLOCK\fR will return \fBEAGAIN\fR in lieu of blocking if the +count associated with the instance is zero. +.RE + +.sp +.ne 2 +.na +\fBEFD_SEMAPHORE\fR +.ad +.RS 12n +Provide counting semaphore semantics whereby a \fBread\fR(2) will +atomically decrement rather than atomically clear the count when it +becomes non-zero. See below for details on \fBread\fR(2) semantics. +.RE + +.sp +The following operations can be performed upon an \fBeventfd\fR instance: + +.sp +.ne 2 +.na +\fBread\fR(2) +.ad +.RS 12n +Atomically reads and modifies the value of the 64-bit counter associated +with the instance. The precise semantics +of \fBread\fR(2) depend on the disposition of \fBEFD_SEMAPHORE\fR with +respect to the instance: if \fBEFD_SEMAPHORE\fR was set when the instance +was created, \fBread\fR(2) will \fIatomically decrement\fR the counter if +(and when) +it is non-zero, copying the value 1 to the eight byte buffer passed to +the system call; if \fBEFD_SEMAPHORE\fR was not set, \fBread\fR(2) will +\fIatomically clear\fR the counter if (and when) it is non-zero, copying +the former value of the counter to the eight byte buffer passed to the +system call. In either case, \fBread\fR(2) will block if the counter is +zero (or return \fBEAGAIN\fR if the instance was created with +\fBEFD_NONBLOCK\fR). If the buffer specified to \fBread\fR(2) is less than +eight bytes in length, \fBEINVAL\fR will be returned. + +.RE + +.sp +.ne 2 +.na +\fBwrite\fR(2) +.ad +.RS 12n +Atomically adds the 64-bit value pointed to by the buffer to the 64-bit +counter associated with the instance. If the resulting value would overflow, +the \fBwrite\fR(2) will block until the value would not overflow +(or return \fBEAGAIN\fR if the instance was created with +\fBEFD_NONBLOCK\fR). If the buffer specified to \fBwrite\fR(2) is less than +eight bytes in length, \fBEINVAL\fR will be returned. + +.RE + +.sp +.ne 2 +.na +\fBpoll\fR(2), \fBport_get\fR(3C), \fBepoll_wait\fR(3C) +.ad +.RS 12n +Provide notification when the 64-bit counter associated +with the instance is ready for reading or writing, as specified. +If the 64-bit value associated with the instance is non-zero, \fBPOLLIN\fR +and \fBPOLLRDNORM\fR will be set; if the value 1 can be added the value +without blocking, \fBPOLLOUT\fR and \fBPOLLWRNORM\fR will be set. +.RE + +.SH RETURN VALUES +.sp +.LP +Upon succesful completion, a file descriptor associated with the instance +is returned. Otherwise, -1 is returned and errno +is set to indicate the error. +.SH ERRORS +.sp +.LP +The \fBeventfd()\fR function will fail if: +.sp +.ne 2 +.na +\fB\fBEINVAL\fR\fR +.ad +.RS 10n +The \fIflags\fR are invalid. +.RE + +.sp +.ne 2 +.na +\fB\fBEMFILE\fR\fR +.ad +.RS 10n +There are currently {\fBOPEN_MAX\fR} file descriptors open in the calling +process. +.RE + +.SH SEE ALSO +.sp +.LP +\fBpoll\fR(2), \fBport_get\fR(3C), \fBepoll_wait\fR(3C), \fBeventfd\fR(5) + diff --git a/usr/src/man/man5/Makefile b/usr/src/man/man5/Makefile index 466d5c0f16..e73c19a10a 100644 --- a/usr/src/man/man5/Makefile +++ b/usr/src/man/man5/Makefile @@ -45,6 +45,7 @@ MANFILES= Intro.5 \ epoll.5 \ eqn.5 \ eqnchar.5 \ + eventfd.5 \ extendedFILE.5 \ filesystem.5 \ fnmatch.5 \ diff --git a/usr/src/man/man5/eventfd.5 b/usr/src/man/man5/eventfd.5 new file mode 100644 index 0000000000..fc30495070 --- /dev/null +++ b/usr/src/man/man5/eventfd.5 @@ -0,0 +1,34 @@ +'\" te +.\" Copyright (c) 2014, Joyent, Inc. All Rights Reserved. +.\" This file and its contents are supplied under the terms of the +.\" Common Development and Distribution License ("CDDL"), version 1.0. +.\" You may only use this file in accordance with the terms of version +.\" 1.0 of the CDDL. +.\" +.\" A full copy of the text of the CDDL should have accompanied this +.\" source. A copy of the CDDL is also available via the Internet at +.\" http://www.illumos.org/license/CDDL. +.TH EVENTFD 5 "Dec 3, 2014" +.SH NAME +eventfd \- Linux-compatible user event notification facility +.SH SYNOPSIS + +.LP +.nf +#include <sys/eventfd.h> +.fi + +.SH DESCRIPTION +.sp +.LP + +\fBeventfd\fR is a Linux-borne facility for sending and receiving user +events via a file descriptor. While the facility itself is somewhat dubious +(it can be mimicked in an entirely portable way with a pipe), it is +small and straightforward and this implementation is entirely compatible +with its Linux antecedent; see \fBeventfd\fR(3C) for details. + +.SH SEE ALSO +.sp +.LP +\fBeventfd\fR(3C) diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files index 1f3166fa85..517a7a6363 100644 --- a/usr/src/uts/common/Makefile.files +++ b/usr/src/uts/common/Makefile.files @@ -1005,6 +1005,8 @@ DEVPOLL_OBJS += devpoll.o DEVPOOL_OBJS += devpool.o +EVENTFD_OBJS += eventfd.o + I8042_OBJS += i8042.o INOTIFY_OBJS += inotify.o diff --git a/usr/src/uts/common/io/eventfd.c b/usr/src/uts/common/io/eventfd.c new file mode 100644 index 0000000000..bd7b6fed5e --- /dev/null +++ b/usr/src/uts/common/io/eventfd.c @@ -0,0 +1,411 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Support for the eventfd facility, a Linux-borne facility for user-generated + * file descriptor-based events. + */ + +#include <sys/ddi.h> +#include <sys/sunddi.h> +#include <sys/eventfd.h> +#include <sys/conf.h> +#include <sys/vmem.h> +#include <sys/sysmacros.h> +#include <sys/filio.h> +#include <sys/stat.h> +#include <sys/file.h> + +struct eventfd_state; +typedef struct eventfd_state eventfd_state_t; + +struct eventfd_state { + kmutex_t efd_lock; /* lock protecting state */ + boolean_t efd_semaphore; /* boolean: sema. semantics */ + kcondvar_t efd_cv; /* condvar */ + pollhead_t efd_pollhd; /* poll head */ + uint64_t efd_value; /* value */ + eventfd_state_t *efd_next; /* next state on global list */ +}; + +/* + * Internal global variables. + */ +static kmutex_t eventfd_lock; /* lock protecting state */ +static dev_info_t *eventfd_devi; /* device info */ +static vmem_t *eventfd_minor; /* minor number arena */ +static void *eventfd_softstate; /* softstate pointer */ +static eventfd_state_t *eventfd_state; /* global list of state */ + +/*ARGSUSED*/ +static int +eventfd_open(dev_t *devp, int flag, int otyp, cred_t *cred_p) +{ + eventfd_state_t *state; + major_t major = getemajor(*devp); + minor_t minor = getminor(*devp); + + if (minor != EVENTFDMNRN_INOTIFY) + return (ENXIO); + + mutex_enter(&eventfd_lock); + + minor = (minor_t)(uintptr_t)vmem_alloc(eventfd_minor, 1, + VM_BESTFIT | VM_SLEEP); + + if (ddi_soft_state_zalloc(eventfd_softstate, minor) != DDI_SUCCESS) { + vmem_free(eventfd_minor, (void *)(uintptr_t)minor, 1); + mutex_exit(&eventfd_lock); + return (NULL); + } + + state = ddi_get_soft_state(eventfd_softstate, minor); + *devp = makedevice(major, minor); + + state->efd_next = eventfd_state; + eventfd_state = state; + + mutex_exit(&eventfd_lock); + + return (0); +} + +/*ARGSUSED*/ +static int +eventfd_read(dev_t dev, uio_t *uio, cred_t *cr) +{ + eventfd_state_t *state; + minor_t minor = getminor(dev); + uint64_t val, oval; + int err; + + if (uio->uio_resid < sizeof (val)) + return (EINVAL); + + state = ddi_get_soft_state(eventfd_softstate, minor); + + mutex_enter(&state->efd_lock); + + while (state->efd_value == 0) { + if (uio->uio_fmode & (FNDELAY|FNONBLOCK)) { + mutex_exit(&state->efd_lock); + return (EAGAIN); + } + + if (!cv_wait_sig_swap(&state->efd_cv, &state->efd_lock)) { + mutex_exit(&state->efd_lock); + return (EINTR); + } + } + + /* + * We have a non-zero value and we own the lock; our behavior now + * depends on whether or not EFD_SEMAPHORE was set when the eventfd + * was created. + */ + val = oval = state->efd_value; + + if (state->efd_semaphore) { + state->efd_value--; + val = 1; + } else { + state->efd_value = 0; + } + + err = uiomove(&val, sizeof (val), UIO_READ, uio); + + mutex_exit(&state->efd_lock); + + if (oval == EVENTFD_VALMAX) { + cv_broadcast(&state->efd_cv); + pollwakeup(&state->efd_pollhd, POLLWRNORM | POLLOUT); + } + + return (err); +} + +/*ARGSUSED*/ +static int +eventfd_write(dev_t dev, struct uio *uio, cred_t *credp) +{ + eventfd_state_t *state; + minor_t minor = getminor(dev); + uint64_t val, oval; + int err; + + if (uio->uio_resid < sizeof (val)) + return (EINVAL); + + if ((err = uiomove(&val, sizeof (val), UIO_WRITE, uio)) != 0) + return (err); + + if (val > EVENTFD_VALMAX) + return (EINVAL); + + state = ddi_get_soft_state(eventfd_softstate, minor); + + mutex_enter(&state->efd_lock); + + while (val > EVENTFD_VALMAX - state->efd_value) { + if (uio->uio_fmode & (FNDELAY|FNONBLOCK)) { + mutex_exit(&state->efd_lock); + return (EAGAIN); + } + + if (!cv_wait_sig_swap(&state->efd_cv, &state->efd_lock)) { + mutex_exit(&state->efd_lock); + return (EINTR); + } + } + + /* + * We now know that we can add the value without overflowing. + */ + state->efd_value = (oval = state->efd_value) + val; + + mutex_exit(&state->efd_lock); + + if (oval == 0) { + cv_broadcast(&state->efd_cv); + pollwakeup(&state->efd_pollhd, POLLRDNORM | POLLIN); + } + + return (0); +} + +/*ARGSUSED*/ +static int +eventfd_poll(dev_t dev, short events, int anyyet, short *reventsp, + struct pollhead **phpp) +{ + eventfd_state_t *state; + minor_t minor = getminor(dev); + short revents = 0; + + state = ddi_get_soft_state(eventfd_softstate, minor); + + mutex_enter(&state->efd_lock); + + if (state->efd_value > 0) + revents |= POLLRDNORM | POLLIN; + + if (state->efd_value < EVENTFD_VALMAX) + revents |= POLLWRNORM | POLLOUT; + + *reventsp = revents & events; + + if (!revents && !anyyet) + *phpp = &state->efd_pollhd; + + mutex_exit(&state->efd_lock); + + return (0); +} + +/*ARGSUSED*/ +static int +eventfd_ioctl(dev_t dev, int cmd, intptr_t arg, int md, cred_t *cr, int *rv) +{ + eventfd_state_t *state; + minor_t minor = getminor(dev); + + state = ddi_get_soft_state(eventfd_softstate, minor); + + switch (cmd) { + case EVENTFDIOC_SEMAPHORE: { + mutex_enter(&state->efd_lock); + state->efd_semaphore ^= 1; + mutex_exit(&state->efd_lock); + + return (0); + } + + default: + break; + } + + return (ENOTTY); +} + +/*ARGSUSED*/ +static int +eventfd_close(dev_t dev, int flag, int otyp, cred_t *cred_p) +{ + eventfd_state_t *state, **sp; + minor_t minor = getminor(dev); + + state = ddi_get_soft_state(eventfd_softstate, minor); + + mutex_enter(&eventfd_lock); + + /* + * Remove our state from our global list. + */ + for (sp = &eventfd_state; *sp != state; sp = &((*sp)->efd_next)) + VERIFY(*sp != NULL); + + *sp = (*sp)->efd_next; + + ddi_soft_state_free(eventfd_softstate, minor); + vmem_free(eventfd_minor, (void *)(uintptr_t)minor, 1); + + mutex_exit(&eventfd_lock); + + return (0); +} + +/*ARGSUSED*/ +static int +eventfd_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) +{ + mutex_enter(&eventfd_lock); + + if (ddi_soft_state_init(&eventfd_softstate, + sizeof (eventfd_state_t), 0) != 0) { + cmn_err(CE_NOTE, "/dev/eventfd failed to create soft state"); + mutex_exit(&eventfd_lock); + return (DDI_FAILURE); + } + + if (ddi_create_minor_node(devi, "eventfd", S_IFCHR, + EVENTFDMNRN_INOTIFY, DDI_PSEUDO, NULL) == DDI_FAILURE) { + cmn_err(CE_NOTE, "/dev/eventfd couldn't create minor node"); + ddi_soft_state_fini(&eventfd_softstate); + mutex_exit(&eventfd_lock); + return (DDI_FAILURE); + } + + ddi_report_dev(devi); + eventfd_devi = devi; + + eventfd_minor = vmem_create("eventfd_minor", (void *)EVENTFDMNRN_CLONE, + UINT32_MAX - EVENTFDMNRN_CLONE, 1, NULL, NULL, NULL, 0, + VM_SLEEP | VMC_IDENTIFIER); + + mutex_exit(&eventfd_lock); + + return (DDI_SUCCESS); +} + +/*ARGSUSED*/ +static int +eventfd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) +{ + switch (cmd) { + case DDI_DETACH: + break; + + case DDI_SUSPEND: + return (DDI_SUCCESS); + + default: + return (DDI_FAILURE); + } + + mutex_enter(&eventfd_lock); + vmem_destroy(eventfd_minor); + + ddi_remove_minor_node(eventfd_devi, NULL); + eventfd_devi = NULL; + + ddi_soft_state_fini(&eventfd_softstate); + mutex_exit(&eventfd_lock); + + return (DDI_SUCCESS); +} + +/*ARGSUSED*/ +static int +eventfd_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) +{ + int error; + + switch (infocmd) { + case DDI_INFO_DEVT2DEVINFO: + *result = (void *)eventfd_devi; + error = DDI_SUCCESS; + break; + case DDI_INFO_DEVT2INSTANCE: + *result = (void *)0; + error = DDI_SUCCESS; + break; + default: + error = DDI_FAILURE; + } + return (error); +} + +static struct cb_ops eventfd_cb_ops = { + eventfd_open, /* open */ + eventfd_close, /* close */ + nulldev, /* strategy */ + nulldev, /* print */ + nodev, /* dump */ + eventfd_read, /* read */ + eventfd_write, /* write */ + eventfd_ioctl, /* ioctl */ + nodev, /* devmap */ + nodev, /* mmap */ + nodev, /* segmap */ + eventfd_poll, /* poll */ + ddi_prop_op, /* cb_prop_op */ + 0, /* streamtab */ + D_NEW | D_MP /* Driver compatibility flag */ +}; + +static struct dev_ops eventfd_ops = { + DEVO_REV, /* devo_rev */ + 0, /* refcnt */ + eventfd_info, /* get_dev_info */ + nulldev, /* identify */ + nulldev, /* probe */ + eventfd_attach, /* attach */ + eventfd_detach, /* detach */ + nodev, /* reset */ + &eventfd_cb_ops, /* driver operations */ + NULL, /* bus operations */ + nodev, /* dev power */ + ddi_quiesce_not_needed, /* quiesce */ +}; + +static struct modldrv modldrv = { + &mod_driverops, /* module type (this is a pseudo driver) */ + "eventfd support", /* name of module */ + &eventfd_ops, /* driver ops */ +}; + +static struct modlinkage modlinkage = { + MODREV_1, + (void *)&modldrv, + NULL +}; + +int +_init(void) +{ + return (mod_install(&modlinkage)); +} + +int +_info(struct modinfo *modinfop) +{ + return (mod_info(&modlinkage, modinfop)); +} + +int +_fini(void) +{ + return (mod_remove(&modlinkage)); +} diff --git a/usr/src/uts/common/io/eventfd.conf b/usr/src/uts/common/io/eventfd.conf new file mode 100644 index 0000000000..f9c6dc11b2 --- /dev/null +++ b/usr/src/uts/common/io/eventfd.conf @@ -0,0 +1,16 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2014 Joyent, Inc. All rights reserved. +# + +name="eventfd" parent="pseudo" instance=0; diff --git a/usr/src/uts/common/sys/Makefile b/usr/src/uts/common/sys/Makefile index ce449efd20..b52be94c90 100644 --- a/usr/src/uts/common/sys/Makefile +++ b/usr/src/uts/common/sys/Makefile @@ -221,6 +221,7 @@ CHKHDRS= \ ethernet.h \ euc.h \ eucioctl.h \ + eventfd.h \ exacct.h \ exacct_catalog.h \ exacct_impl.h \ diff --git a/usr/src/uts/common/sys/eventfd.h b/usr/src/uts/common/sys/eventfd.h new file mode 100644 index 0000000000..c7dbaf947f --- /dev/null +++ b/usr/src/uts/common/sys/eventfd.h @@ -0,0 +1,68 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Header file to support for the eventfd facility. Note that this facility + * is designed to be binary compatible with the Linux eventfd facility; values + * for constants here should therefore exactly match those found in Linux, and + * this facility shouldn't be extended independently of Linux. + */ + +#ifndef _SYS_EVENTFD_H +#define _SYS_EVENTFD_H + +#include <sys/types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef uint64_t eventfd_t; + +/* + * To assure binary compatibility with Linux, these values are fixed at their + * Linux equivalents, not their native ones. + */ +#define EFD_CLOEXEC 02000000 /* LX_O_CLOEXEC */ +#define EFD_NONBLOCK 04000 /* LX_O_NONBLOCK */ +#define EFD_SEMAPHORE 1 + +/* + * These ioctl values are specific to the native implementation; applications + * shouldn't be using them directly, and they should therefore be safe to + * change without breaking apps. + */ +#define EVENTFDIOC (('e' << 24) | ('f' << 16) | ('d' << 8)) +#define EVENTFDIOC_SEMAPHORE (EVENTFDIOC | 1) /* toggle sem state */ + +#ifndef _KERNEL + +extern int eventfd(unsigned int, int); +extern int eventfd_read(int, eventfd_t *); +extern int eventfd_write(int, eventfd_t); + +#else + +#define EVENTFDMNRN_INOTIFY 0 +#define EVENTFDMNRN_CLONE 1 +#define EVENTFD_VALMAX (ULLONG_MAX - 1ULL) + +#endif /* _KERNEL */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_EVENTFD_H */ diff --git a/usr/src/uts/intel/Makefile.intel b/usr/src/uts/intel/Makefile.intel index 4c0194240b..49ff0b8a2e 100644 --- a/usr/src/uts/intel/Makefile.intel +++ b/usr/src/uts/intel/Makefile.intel @@ -242,6 +242,7 @@ DRV_KMODS += dr_sas DRV_KMODS += dump DRV_KMODS += ecpp DRV_KMODS += emlxs +DRV_KMODS += eventfd DRV_KMODS += fd DRV_KMODS += fdc DRV_KMODS += fm diff --git a/usr/src/uts/intel/eventfd/Makefile b/usr/src/uts/intel/eventfd/Makefile new file mode 100644 index 0000000000..6edff0931a --- /dev/null +++ b/usr/src/uts/intel/eventfd/Makefile @@ -0,0 +1,68 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2014 Joyent, Inc. All rights reserved. +# + +# +# Path to the base of the uts directory tree (usually /usr/src/uts). +# +UTSBASE = ../.. + +# +# Define the module and object file sets. +# +MODULE = eventfd +OBJECTS = $(EVENTFD_OBJS:%=$(OBJS_DIR)/%) +LINTS = $(EVENTFD_OBJS:%.o=$(LINTS_DIR)/%.ln) +ROOTMODULE = $(USR_DRV_DIR)/$(MODULE) +CONF_SRCDIR = $(UTSBASE)/common/io + +# +# Include common rules. +# +include $(UTSBASE)/intel/Makefile.intel + +CERRWARN += -_gcc=-Wno-parentheses + +# +# Define targets +# +ALL_TARGET = $(BINARY) $(SRC_CONFILE) +LINT_TARGET = $(MODULE).lint +INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE) + +# +# Default build targets. +# +.KEEP_STATE: + +def: $(DEF_DEPS) + +all: $(ALL_DEPS) + +clean: $(CLEAN_DEPS) + +clobber: $(CLOBBER_DEPS) + +lint: $(LINT_DEPS) + +modlintlib: $(MODLINTLIB_DEPS) + +clean.lint: $(CLEAN_LINT_DEPS) + +install: $(INSTALL_DEPS) + +# +# Include common targets. +# +include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/sparc/Makefile.sparc b/usr/src/uts/sparc/Makefile.sparc index b989364998..cd7206a353 100644 --- a/usr/src/uts/sparc/Makefile.sparc +++ b/usr/src/uts/sparc/Makefile.sparc @@ -238,6 +238,7 @@ DRV_KMODS += bridge trill DRV_KMODS += bpf DRV_KMODS += dca DRV_KMODS += inotify +DRV_KMODS += eventfd # # Hardware Drivers in common space diff --git a/usr/src/uts/sparc/eventfd/Makefile b/usr/src/uts/sparc/eventfd/Makefile new file mode 100644 index 0000000000..063aa29b78 --- /dev/null +++ b/usr/src/uts/sparc/eventfd/Makefile @@ -0,0 +1,68 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2014 Joyent, Inc. All rights reserved. +# + +# +# Path to the base of the uts directory tree (usually /usr/src/uts). +# +UTSBASE = ../.. + +# +# Define the module and object file sets. +# +MODULE = eventfd +OBJECTS = $(EVENTFD_OBJS:%=$(OBJS_DIR)/%) +LINTS = $(EVENTFD_OBJS:%.o=$(LINTS_DIR)/%.ln) +ROOTMODULE = $(USR_DRV_DIR)/$(MODULE) +CONF_SRCDIR = $(UTSBASE)/common/io + +# +# Include common rules. +# +include $(UTSBASE)/sparc/Makefile.sparc + +CERRWARN += -_gcc=-Wno-parentheses + +# +# Define targets +# +ALL_TARGET = $(BINARY) $(SRC_CONFILE) +LINT_TARGET = $(MODULE).lint +INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE) + +# +# Default build targets. +# +.KEEP_STATE: + +def: $(DEF_DEPS) + +all: $(ALL_DEPS) + +clean: $(CLEAN_DEPS) + +clobber: $(CLOBBER_DEPS) + +lint: $(LINT_DEPS) + +modlintlib: $(MODLINTLIB_DEPS) + +clean.lint: $(CLEAN_LINT_DEPS) + +install: $(INSTALL_DEPS) + +# +# Include common targets. +# +include $(UTSBASE)/sparc/Makefile.targ |