Page MenuHomeFreeBSD

D2172.id4493.diff
No OneTemporary

D2172.id4493.diff

Index: lib/libc/sys/Makefile.inc
===================================================================
--- lib/libc/sys/Makefile.inc
+++ lib/libc/sys/Makefile.inc
@@ -38,7 +38,7 @@
NOASM+= ${SYSCALL_COMPAT_SRCS:S/.c/.o/}
.endif
-SRCS+= futimens.c utimensat.c
+SRCS+= futimens.c utimensat.c eventfd_rw.c
NOASM+= futimens.o utimensat.o
PSEUDO+= _futimens.o _utimensat.o
@@ -166,6 +166,7 @@
cpuset.2 \
cpuset_getaffinity.2 \
dup.2 \
+ eventfd.2 \
execve.2 \
_exit.2 \
extattr_get_file.2 \
Index: lib/libc/sys/Symbol.map
===================================================================
--- lib/libc/sys/Symbol.map
+++ lib/libc/sys/Symbol.map
@@ -397,6 +397,9 @@
};
FBSD_1.4 {
+ eventfd;
+ eventfd_read;
+ eventfd_write;
futimens;
ppoll;
utimensat;
@@ -539,6 +542,8 @@
__sys_dup2;
_eaccess;
__sys_eaccess;
+ _eventfd;
+ __sys_eventfd;
_execve;
__sys_execve;
_extattr_delete_fd;
Index: lib/libc/sys/eventfd.2
===================================================================
--- /dev/null
+++ lib/libc/sys/eventfd.2
@@ -0,0 +1,254 @@
+.\" Copyright (c) 2015 Dmitry Chagin
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 28, 2015
+.Dt EVENTFD 2
+.Os
+.Sh NAME
+.Nm eventfd
+.Nd interprocess communication mechanism
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/eventfd.h
+.Ft int
+.Fn eventfd "unsigned int initval" "int flags"
+.Bd -literal
+typedef uint64_t eventfd_t;
+.Ed
+.Pp
+.Ft int
+.Fn eventfd_read "int fd" "eventfd_t *value"
+.Pp
+.Ft int
+.Fn eventfd_write "int fd" "eventfd_t value"
+.Sh DESCRIPTION
+The
+.Fn eventfd
+function creates an "eventfd object" that can be used
+as an event wait/notify mechanism by user-space applications.
+The object points to the 64-bit integer counter that is
+maintained by the kernel.
+This counter is initialized with the value specified in the argument
+.Fa initval .
+.Pp
+The
+.Fa flags
+field can contain the following values:
+.Bl -tag -width EFD_SEMAPHORE
+.It Dv EFD_CLOEXEC
+Set the close-on-exec flag on the new eventfd
+file descriptor.
+.It Dv EFD_NONBLOCK
+Set the O_NONBLOCK file status on the new eventfd
+file descriptor.
+.It Dv EFD_SEMAPHORE
+Provide semaphore-like semantics for reads from the new
+eventfd file descriptor.
+.El
+.Pp
+The following operations can be performed on the
+eventfd file descriptor:
+.Bl -tag -width EFD_SEMAPHORE
+.It Xr read 2
+Each successful
+.Xr read 2
+returns an 64-bit integer. A
+.Xr read 2
+will fail with the error EINVAL if the size of the
+supplied buffer is less than 8 bytes.
+.Pp
+The semantics of
+.Xr read 2
+depend on whether the eventfd counter currently has
+a nonzero value and whether the
+.Dv EFD_SEMAPHORE
+flag was specified when creating the eventfd file descriptor:
+.Bl -tag -width *
+.It *
+If
+.Dv EFD_SEMAPHORE
+was not specified and the eventfd counter has a nonzero value,
+then a
+.Xr read 2
+returns 8 bytes containing that value, and the counter's value
+is reset to zero.
+.It *
+If
+.Dv EFD_SEMAPHORE
+was specified and the eventfd counter has a nonzero value,
+then a
+.Xr read 2
+returns 8 bytes containing the value 1, and the counter's
+value is decremented by 1.
+.It *
+If the eventfd counter is zero at the time of the call to
+.Xr read 2 ,
+then the call either blocks until the counter becomes nonzero
+(at which time, the
+.Xr read 2
+proceeds as described above) or fails with the error EAGAIN
+if the file descriptor has been made nonblocking.
+.El
+.It Xr write 2
+A
+.Xr write 2
+call adds the 64-bit integer value supplied in its buffer
+to the counter.
+The maximum value that may be stored in the counter is the
+largest unsigned 64-bit value minus 1 (i.e., 0xfffffffffffffffe).
+.Pp
+If the addition would cause the
+counter's value to exceed the maximum, then the
+.Xr write 2
+either blocks until a
+.Xr read 2
+is performed on the file descriptor, or fails with the error
+EAGAIN if the file descriptor has been made nonblocking.
+.Pp
+A
+.Xr write 2
+will fail with the error EINVAL if the size of the supplied
+buffer is less than 8 bytes, or if an attempt is made to
+write the value 0xffffffffffffffff.
+.It Xr poll 2
+The returned file descriptor supports
+.Xr poll 2
+as follows:
+.Bl -tag -width *
+.It *
+The file descriptor is readable if the counter has a value
+greater than 0.
+.It *
+The file descriptor is writable if it is possible to write
+a value of at least "1" without blocking.
+.It *
+If an overflow of the counter value was detected, then
+.Xr select 2
+indicates the file descriptor as being both readable and
+writable, and
+.Xr poll 2
+returns a
+.Fa POLLERR
+event.
+As noted above,
+.Xr write 2
+can never overflow the counter.
+.El
+.Pp
+The eventfd file descriptor also supports the other file-
+descriptor multiplexing APIs:
+.Xr kqueue 2 ,
+.Xr pselect 2 ,
+.Xr select 2
+and
+.Xr ppoll 2 .
+.It Xr close 2
+When the file descriptor is no longer required it should be closed.
+When all file descriptors associated with the same eventfd object
+have been closed, the resources for object are freed by the kernel.
+.El
+.Pp
+A copy of the file descriptor created by
+.Fn eventfd
+is inherited by the child produced by
+.Xr fork 2 .
+The duplicate file descriptor is associated with the same
+eventfd object.
+File descriptors created by
+.Fn eventfd
+are preserved across
+.Xr execve 2 ,
+unless the close-on-exec flag has been set.
+.Sh NOTES
+Applications can use an eventfd file descriptor
+instead of a
+.Xr pipe 2
+in all cases where a
+.Xr pipe 2
+is used simply to signal events.
+The kernel overhead of an eventfd file descriptor is much lower than
+that of a
+.Xr pipe 2 ,
+and only one file descriptor is required.
+.Pp
+A key point about an eventfd file descriptor is that it can
+be monitored just like any other file descriptor using
+.Xr select 2 ,
+.Xr poll 2 .
+.Sh RETURN VALUES
+On success,
+.Fn eventfd
+returns a new eventfd file descriptor.
+On error, -1 is returned and errno is set to indicate the error.
+.Pp
+The
+.Fn eventfd_read
+and
+.Fn eventfd_write
+functions perform the read and write operations on an eventfd
+file descriptor, returning 0 if the correct number of bytes
+was transferred, or -1 otherwise.
+.Sh ERRORS
+The
+.Fn eventfd
+function call fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The unsupported value was specified in
+.Fa flags .
+.It Bq Er EMFILE
+The process has already reached its limit for open
+file descriptors.
+.It Bq Er ENFILE
+The system file table is full.
+.It Bq Er ENOMEM
+No memory was available to create new eventfd file descriptor.
+.El
+.Sh SEE ALSO
+.Xr close 2 ,
+.Xr kqueue 2 ,
+.Xr poll 2 ,
+.Xr ppoll 2 ,
+.Xr pselect 2 ,
+.Xr read 2 ,
+.Xr select 2 ,
+.Xr write 2
+.Sh HISTORY
+The
+.Fn eventfd
+function is based on a similar feature of Linux and first
+appeared in
+.Fx 11.0
+.Sh AUTHORS
+The
+.Fn eventfd
+function and this manual page were written by
+.An Dmitry Chagin Aq Mt dchagin@FreeBSD.org
+starting from a version by
+.An Michael Kerrisk Aq Mt mtk.manpages@gmail.com
+and
+.An Davide Libenzi Aq Mt davidel@xmailserver.org .
Index: lib/libc/sys/eventfd_rw.c
===================================================================
--- /dev/null
+++ lib/libc/sys/eventfd_rw.c
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 2015 Dmitry Chagin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/eventfd.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+int
+eventfd_read(int fd, eventfd_t *value)
+{
+ int bytes;
+
+ bytes = read(fd, value, sizeof(eventfd_t));
+ if (bytes != sizeof(eventfd_t))
+ return (-1);
+ else
+ return (0);
+}
+
+int
+eventfd_write(int fd, eventfd_t value)
+{
+ int bytes;
+
+ bytes = write(fd, &value, sizeof(eventfd_t));
+ if (bytes != sizeof(eventfd_t))
+ return (-1);
+ else
+ return (0);
+}
Index: sys/compat/freebsd32/syscalls.master
===================================================================
--- sys/compat/freebsd32/syscalls.master
+++ sys/compat/freebsd32/syscalls.master
@@ -1074,3 +1074,5 @@
547 AUE_FUTIMESAT STD { int freebsd32_utimensat(int fd, \
char *path, \
struct timespec *times, int flag); }
+548 AUE_NULL NOPROTO { int eventfd(unsigned int initval, \
+ int flags); }
Index: sys/conf/files
===================================================================
--- sys/conf/files
+++ sys/conf/files
@@ -2996,6 +2996,7 @@
kern/kern_environment.c standard
kern/kern_et.c standard
kern/kern_event.c standard
+kern/kern_eventfd.c standard
kern/kern_exec.c standard
kern/kern_exit.c standard
kern/kern_fail.c standard
Index: sys/kern/kern_eventfd.c
===================================================================
--- /dev/null
+++ sys/kern/kern_eventfd.c
@@ -0,0 +1,419 @@
+/*-
+ * Copyright (c) 2015 Dmitry Chagin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/capsicum.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/rwlock.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/unistd.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/filio.h>
+#include <sys/fcntl.h>
+#include <sys/kthread.h>
+#include <sys/selinfo.h>
+#include <sys/stdatomic.h>
+#include <sys/queue.h>
+#include <sys/eventfd.h>
+#include <sys/eventvar.h>
+#include <sys/poll.h>
+#include <sys/protosw.h>
+#include <sys/resourcevar.h>
+#include <sys/sigio.h>
+#include <sys/signalvar.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/sysproto.h>
+#include <sys/syscallsubr.h>
+#include <sys/taskqueue.h>
+#include <sys/uio.h>
+#include <sys/user.h>
+
+#include <vm/uma.h>
+
+static uma_zone_t eventfd_zone;
+
+static fo_rdwr_t eventfd_read;
+static fo_rdwr_t eventfd_write;
+static fo_truncate_t eventfd_truncate;
+static fo_ioctl_t eventfd_ioctl;
+static fo_poll_t eventfd_poll;
+static fo_kqfilter_t eventfd_kqfilter;
+static fo_stat_t eventfd_stat;
+static fo_close_t eventfd_close;
+static fo_fill_kinfo_t eventfd_fill_kinfo;
+
+static struct fileops eventfdops = {
+ .fo_read = eventfd_read,
+ .fo_write = eventfd_write,
+ .fo_truncate = eventfd_truncate,
+ .fo_ioctl = eventfd_ioctl,
+ .fo_poll = eventfd_poll,
+ .fo_kqfilter = eventfd_kqfilter,
+ .fo_stat = eventfd_stat,
+ .fo_close = eventfd_close,
+ .fo_chmod = invfo_chmod,
+ .fo_chown = invfo_chown,
+ .fo_sendfile = invfo_sendfile,
+ .fo_fill_kinfo = eventfd_fill_kinfo,
+ .fo_flags = DFLAG_PASSABLE
+};
+
+static void filt_eventfddetach(struct knote *kn);
+static int filt_eventfdread(struct knote *kn, long hint);
+static int filt_eventfdwrite(struct knote *kn, long hint);
+
+static struct filterops eventfd_rfiltops = {
+ .f_isfd = 1,
+ .f_detach = filt_eventfddetach,
+ .f_event = filt_eventfdread
+};
+static struct filterops eventfd_wfiltops = {
+ .f_isfd = 1,
+ .f_detach = filt_eventfddetach,
+ .f_event = filt_eventfdwrite
+};
+
+struct eventfd {
+ eventfd_t efd_count;
+ int efd_flags;
+ struct selinfo efd_sel;
+ struct mtx efd_lock;
+};
+
+static void eventfdinit();
+static int eventfd_init();
+static void eventfd_fini();
+
+
+static int
+eventfd_init(void *mem, int size, int flags)
+{
+ struct eventfd *efd;
+
+ efd = (struct eventfd *)mem;
+
+ mtx_init(&efd->efd_lock, "eventfd", NULL, MTX_DEF);
+ knlist_init_mtx(&efd->efd_sel.si_note, &efd->efd_lock);
+ return (0);
+}
+
+static void
+eventfd_fini(void *mem, int size)
+{
+ struct eventfd *efd;
+
+ efd = (struct eventfd *)mem;
+
+ knlist_destroy(&efd->efd_sel.si_note);
+ mtx_destroy(&efd->efd_lock);
+}
+
+static void
+eventfdinit()
+{
+
+ eventfd_zone = uma_zcreate("EVENTFD", sizeof(struct eventfd),
+ NULL, NULL, eventfd_init, eventfd_fini, UMA_ALIGN_PTR, 0);
+}
+SYSINIT(eventfd, SI_SUB_PSEUDO, SI_ORDER_ANY, eventfdinit, NULL);
+
+int
+sys_eventfd(struct thread *td, struct eventfd_args *args)
+{
+ struct filedesc *fdp;
+ struct eventfd *efd;
+ struct file *fp;
+ int fflags, fd;
+ int error;
+
+ if ((args->flags & ~(EFD_CLOEXEC|EFD_NONBLOCK|EFD_SEMAPHORE)) != 0)
+ return (EINVAL);
+
+ fflags = 0;
+ if ((args->flags & EFD_CLOEXEC) != 0)
+ fflags |= O_CLOEXEC;
+
+ fdp = td->td_proc->p_fd;
+ error = falloc(td, &fp, &fd, fflags);
+ if (error != 0)
+ return (error);
+
+ efd = uma_zalloc(eventfd_zone, M_WAITOK);
+ efd->efd_flags = args->flags;
+ efd->efd_count = args->initval;
+
+ fflags = FREAD | FWRITE;
+ if ((args->flags & EFD_NONBLOCK) != 0)
+ fflags |= FNONBLOCK;
+
+ finit(fp, fflags, DTYPE_EVENTFD, efd, &eventfdops);
+ fdrop(fp, td);
+
+ td->td_retval[0] = fd;
+ return (error);
+}
+
+static int
+eventfd_close(struct file *fp, struct thread *td)
+{
+ struct eventfd *efd;
+
+ efd = fp->f_data;
+ if (fp->f_type != DTYPE_EVENTFD || efd == NULL)
+ return (EBADF);
+
+ seldrain(&efd->efd_sel);
+ fp->f_ops = &badfileops;
+ uma_zfree(eventfd_zone, efd);
+ return (0);
+}
+
+static int
+eventfd_read(struct file *fp, struct uio *uio, struct ucred *active_cred,
+ int flags, struct thread *td)
+{
+ struct eventfd *efd;
+ eventfd_t count;
+ int error;
+
+ efd = fp->f_data;
+ if (fp->f_type != DTYPE_EVENTFD || efd == NULL)
+ return (EBADF);
+
+ if (uio->uio_resid < sizeof(eventfd_t))
+ return (EINVAL);
+
+ error = 0;
+ mtx_lock(&efd->efd_lock);
+ retry:
+ if (efd->efd_count == 0) {
+ if ((efd->efd_flags & EFD_NONBLOCK) != 0) {
+ mtx_unlock(&efd->efd_lock);
+ return (EAGAIN);
+ }
+ error = mtx_sleep(&efd->efd_count, &efd->efd_lock,
+ PCATCH, "evfdrd", 0);
+ if (error == 0)
+ goto retry;
+ }
+ if (error == 0) {
+ if ((efd->efd_flags & EFD_SEMAPHORE) != 0) {
+ count = 1;
+ --efd->efd_count;
+ } else {
+ count = efd->efd_count;
+ efd->efd_count = 0;
+ }
+ KNOTE_LOCKED(&efd->efd_sel.si_note, 0);
+ selwakeup(&efd->efd_sel);
+ wakeup(&efd->efd_count);
+ mtx_unlock(&efd->efd_lock);
+ error = uiomove(&count, sizeof(eventfd_t), uio);
+ } else
+ mtx_unlock(&efd->efd_lock);
+
+ return (error);
+}
+
+static int
+eventfd_write(struct file *fp, struct uio *uio, struct ucred *active_cred,
+ int flags, struct thread *td)
+{
+ struct eventfd *efd;
+ eventfd_t count;
+ int error;
+
+ efd = fp->f_data;
+ if (fp->f_type != DTYPE_EVENTFD || efd == NULL)
+ return (EBADF);
+
+ if (uio->uio_resid < sizeof(eventfd_t))
+ return (EINVAL);
+
+ error = uiomove(&count, sizeof(eventfd_t), uio);
+ if (error != 0)
+ return (error);
+ if (count == UINT64_MAX)
+ return (EINVAL);
+
+ mtx_lock(&efd->efd_lock);
+ retry:
+ if (UINT64_MAX - efd->efd_count <= count) {
+ if ((efd->efd_flags & EFD_NONBLOCK) != 0) {
+ mtx_unlock(&efd->efd_lock);
+ return (EAGAIN);
+ }
+ error = mtx_sleep(&efd->efd_count, &efd->efd_lock,
+ PCATCH, "evfdwr", 0);
+ if (error == 0)
+ goto retry;
+ }
+ if (error == 0) {
+ efd->efd_count += count;
+ KNOTE_LOCKED(&efd->efd_sel.si_note, 0);
+ selwakeup(&efd->efd_sel);
+ wakeup(&efd->efd_count);
+ }
+ mtx_unlock(&efd->efd_lock);
+
+ return (error);
+}
+
+static int
+eventfd_poll(struct file *fp, int events, struct ucred *active_cred,
+ struct thread *td)
+{
+ struct eventfd *efd;
+ int revents = 0;
+
+ efd = fp->f_data;
+ if (fp->f_type != DTYPE_EVENTFD || efd == NULL)
+ return (POLLERR);
+
+ mtx_lock(&efd->efd_lock);
+ if ((events & (POLLIN|POLLRDNORM)) && efd->efd_count > 0)
+ revents |= events & (POLLIN|POLLRDNORM);
+ if ((events & (POLLOUT|POLLWRNORM)) && UINT64_MAX - 1 > efd->efd_count)
+ revents |= events & (POLLOUT|POLLWRNORM);
+ if (revents == 0)
+ selrecord(td, &efd->efd_sel);
+ mtx_unlock(&efd->efd_lock);
+
+ return (revents);
+}
+
+/*ARGSUSED*/
+static int
+eventfd_kqfilter(struct file *fp, struct knote *kn)
+{
+ struct eventfd *efd;
+
+ efd = fp->f_data;
+ if (fp->f_type != DTYPE_EVENTFD || efd == NULL)
+ return (EINVAL);
+
+ mtx_lock(&efd->efd_lock);
+ switch (kn->kn_filter) {
+ case EVFILT_READ:
+ kn->kn_fop = &eventfd_rfiltops;
+ break;
+ case EVFILT_WRITE:
+ kn->kn_fop = &eventfd_wfiltops;
+ break;
+ default:
+ mtx_unlock(&efd->efd_lock);
+ return (EINVAL);
+ }
+
+ kn->kn_hook = efd;
+ knlist_add(&efd->efd_sel.si_note, kn, 1);
+ mtx_unlock(&efd->efd_lock);
+
+ return (0);
+}
+
+static void
+filt_eventfddetach(struct knote *kn)
+{
+ struct eventfd *efd = kn->kn_hook;
+
+ mtx_lock(&efd->efd_lock);
+ knlist_remove(&efd->efd_sel.si_note, kn, 1);
+ mtx_unlock(&efd->efd_lock);
+}
+
+/*ARGSUSED*/
+static int
+filt_eventfdread(struct knote *kn, long hint)
+{
+ struct eventfd *efd = kn->kn_hook;
+ int ret;
+
+ mtx_assert(&efd->efd_lock, MA_OWNED);
+ ret = (efd->efd_count > 0);
+
+ return (ret);
+}
+
+/*ARGSUSED*/
+static int
+filt_eventfdwrite(struct knote *kn, long hint)
+{
+ struct eventfd *efd = kn->kn_hook;
+ int ret;
+
+ mtx_assert(&efd->efd_lock, MA_OWNED);
+ ret = (UINT64_MAX - 1 > efd->efd_count);
+
+ return (ret);
+}
+
+/*ARGSUSED*/
+static int
+eventfd_truncate(struct file *fp, off_t length, struct ucred *active_cred,
+ struct thread *td)
+{
+
+ return (ENXIO);
+}
+
+/*ARGSUSED*/
+static int
+eventfd_ioctl(struct file *fp, u_long cmd, void *data,
+ struct ucred *active_cred, struct thread *td)
+{
+
+ return (ENXIO);
+}
+
+/*ARGSUSED*/
+static int
+eventfd_stat(struct file *fp, struct stat *st, struct ucred *active_cred,
+ struct thread *td)
+{
+
+ return (ENXIO);
+}
+
+/*ARGSUSED*/
+static int
+eventfd_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
+{
+
+ kif->kf_type = KF_TYPE_EVENTFD;
+ return (0);
+}
Index: sys/kern/syscalls.master
===================================================================
--- sys/kern/syscalls.master
+++ sys/kern/syscalls.master
@@ -988,5 +988,7 @@
547 AUE_FUTIMESAT STD { int utimensat(int fd, \
char *path, \
struct timespec *times, int flag); }
+548 AUE_NULL STD { int eventfd(unsigned int initval, \
+ int flags); }
; Please copy any additions and changes to the following compatability tables:
; sys/compat/freebsd32/syscalls.master
Index: sys/sys/eventfd.h
===================================================================
--- /dev/null
+++ sys/sys/eventfd.h
@@ -0,0 +1,50 @@
+/*-
+ * Copyright (c) 2015 Dmitry Chagin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SYS_EVENTFD_H_
+#define _SYS_EVENTFD_H_
+
+#define EFD_SEMAPHORE 0x0001
+#define EFD_CLOEXEC 0x0002
+#define EFD_NONBLOCK 0x0004
+
+#ifndef _KERNEL
+#include <stdint.h>
+#endif
+
+typedef uint64_t eventfd_t;
+
+#ifndef _KERNEL
+__BEGIN_DECLS
+int eventfd(unsigned int initval, int flags);
+int eventfd_read(int fd, eventfd_t *value);
+int eventfd_write(int fd, eventfd_t value);
+__END_DECLS
+#endif
+
+#endif /* !_SYS_EVENTFD_H_ */
Index: sys/sys/file.h
===================================================================
--- sys/sys/file.h
+++ sys/sys/file.h
@@ -66,6 +66,7 @@
#define DTYPE_PTS 10 /* pseudo teletype master device */
#define DTYPE_DEV 11 /* Device specific fd type */
#define DTYPE_PROCDESC 12 /* process descriptor */
+#define DTYPE_EVENTFD 13 /* eventfd type */
#ifdef _KERNEL
Index: sys/sys/user.h
===================================================================
--- sys/sys/user.h
+++ sys/sys/user.h
@@ -258,6 +258,7 @@
#define KF_TYPE_SEM 9
#define KF_TYPE_PTS 10
#define KF_TYPE_PROCDESC 11
+#define KF_TYPE_EVENTFD 12
#define KF_TYPE_UNKNOWN 255
#define KF_VTYPE_VNON 0

File Metadata

Mime Type
text/plain
Expires
Wed, Mar 11, 9:19 PM (9 h, 12 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29551628
Default Alt Text
D2172.id4493.diff (23 KB)

Event Timeline