Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F147424520
D2172.id4493.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
23 KB
Referenced Files
None
Subscribers
None
D2172.id4493.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D2172: Implement native eventfd system call.
Attached
Detach File
Event Timeline
Log In to Comment