xref: /freebsd/sys/kern/sys_eventfd.c (revision 0a7c164d91a85a0cc5cfb9ea1afb93c5e4f2e628)
17a202823SKonstantin Belousov /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
37a202823SKonstantin Belousov  *
41ca6b15bSDmitry Chagin  * Copyright (c) 2014 Dmitry Chagin <dchagin@FreeBSD.org>
57a202823SKonstantin Belousov  *
67a202823SKonstantin Belousov  * Redistribution and use in source and binary forms, with or without
77a202823SKonstantin Belousov  * modification, are permitted provided that the following conditions
87a202823SKonstantin Belousov  * are met:
97a202823SKonstantin Belousov  * 1. Redistributions of source code must retain the above copyright
107a202823SKonstantin Belousov  *    notice, this list of conditions and the following disclaimer.
117a202823SKonstantin Belousov  * 2. Redistributions in binary form must reproduce the above copyright
127a202823SKonstantin Belousov  *    notice, this list of conditions and the following disclaimer in the
137a202823SKonstantin Belousov  *    documentation and/or other materials provided with the distribution.
147a202823SKonstantin Belousov  *
157a202823SKonstantin Belousov  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
167a202823SKonstantin Belousov  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
177a202823SKonstantin Belousov  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
187a202823SKonstantin Belousov  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
197a202823SKonstantin Belousov  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
207a202823SKonstantin Belousov  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
217a202823SKonstantin Belousov  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
227a202823SKonstantin Belousov  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
237a202823SKonstantin Belousov  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
247a202823SKonstantin Belousov  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
257a202823SKonstantin Belousov  * SUCH DAMAGE.
267a202823SKonstantin Belousov  */
277a202823SKonstantin Belousov 
287a202823SKonstantin Belousov #include <sys/systm.h>
29*0a7c164dSKonstantin Belousov #include <sys/event.h>
30*0a7c164dSKonstantin Belousov #include <sys/eventfd.h>
31*0a7c164dSKonstantin Belousov #include <sys/errno.h>
327a202823SKonstantin Belousov #include <sys/fcntl.h>
337a202823SKonstantin Belousov #include <sys/file.h>
347a202823SKonstantin Belousov #include <sys/filedesc.h>
357a202823SKonstantin Belousov #include <sys/filio.h>
36*0a7c164dSKonstantin Belousov #include <sys/kernel.h>
37*0a7c164dSKonstantin Belousov #include <sys/limits.h>
38*0a7c164dSKonstantin Belousov #include <sys/lock.h>
39*0a7c164dSKonstantin Belousov #include <sys/malloc.h>
40*0a7c164dSKonstantin Belousov #include <sys/mutex.h>
417a202823SKonstantin Belousov #include <sys/poll.h>
427a202823SKonstantin Belousov #include <sys/proc.h>
437a202823SKonstantin Belousov #include <sys/selinfo.h>
44*0a7c164dSKonstantin Belousov #include <sys/stat.h>
45*0a7c164dSKonstantin Belousov #include <sys/uio.h>
46*0a7c164dSKonstantin Belousov #include <sys/user.h>
477a202823SKonstantin Belousov 
487a202823SKonstantin Belousov #include <security/audit/audit.h>
497a202823SKonstantin Belousov 
507a202823SKonstantin Belousov _Static_assert(EFD_CLOEXEC == O_CLOEXEC, "Mismatched EFD_CLOEXEC");
517a202823SKonstantin Belousov _Static_assert(EFD_NONBLOCK == O_NONBLOCK, "Mismatched EFD_NONBLOCK");
527a202823SKonstantin Belousov 
537a202823SKonstantin Belousov MALLOC_DEFINE(M_EVENTFD, "eventfd", "eventfd structures");
547a202823SKonstantin Belousov 
557a202823SKonstantin Belousov static fo_rdwr_t	eventfd_read;
567a202823SKonstantin Belousov static fo_rdwr_t	eventfd_write;
577a202823SKonstantin Belousov static fo_ioctl_t	eventfd_ioctl;
587a202823SKonstantin Belousov static fo_poll_t	eventfd_poll;
597a202823SKonstantin Belousov static fo_kqfilter_t	eventfd_kqfilter;
607a202823SKonstantin Belousov static fo_stat_t	eventfd_stat;
617a202823SKonstantin Belousov static fo_close_t	eventfd_close;
627a202823SKonstantin Belousov static fo_fill_kinfo_t	eventfd_fill_kinfo;
637a202823SKonstantin Belousov 
64ef9ffb85SMark Johnston static const struct fileops eventfdops = {
657a202823SKonstantin Belousov 	.fo_read = eventfd_read,
667a202823SKonstantin Belousov 	.fo_write = eventfd_write,
677a202823SKonstantin Belousov 	.fo_truncate = invfo_truncate,
687a202823SKonstantin Belousov 	.fo_ioctl = eventfd_ioctl,
697a202823SKonstantin Belousov 	.fo_poll = eventfd_poll,
707a202823SKonstantin Belousov 	.fo_kqfilter = eventfd_kqfilter,
717a202823SKonstantin Belousov 	.fo_stat = eventfd_stat,
727a202823SKonstantin Belousov 	.fo_close = eventfd_close,
737a202823SKonstantin Belousov 	.fo_chmod = invfo_chmod,
747a202823SKonstantin Belousov 	.fo_chown = invfo_chown,
757a202823SKonstantin Belousov 	.fo_sendfile = invfo_sendfile,
767a202823SKonstantin Belousov 	.fo_fill_kinfo = eventfd_fill_kinfo,
77f28526e9SKonstantin Belousov 	.fo_cmp = file_kcmp_generic,
787a202823SKonstantin Belousov 	.fo_flags = DFLAG_PASSABLE
797a202823SKonstantin Belousov };
807a202823SKonstantin Belousov 
817a202823SKonstantin Belousov static void	filt_eventfddetach(struct knote *kn);
827a202823SKonstantin Belousov static int	filt_eventfdread(struct knote *kn, long hint);
837a202823SKonstantin Belousov static int	filt_eventfdwrite(struct knote *kn, long hint);
847a202823SKonstantin Belousov 
85ef9ffb85SMark Johnston static const struct filterops eventfd_rfiltops = {
867a202823SKonstantin Belousov 	.f_isfd = 1,
877a202823SKonstantin Belousov 	.f_detach = filt_eventfddetach,
887a202823SKonstantin Belousov 	.f_event = filt_eventfdread
897a202823SKonstantin Belousov };
907a202823SKonstantin Belousov 
91ef9ffb85SMark Johnston static const struct filterops eventfd_wfiltops = {
927a202823SKonstantin Belousov 	.f_isfd = 1,
937a202823SKonstantin Belousov 	.f_detach = filt_eventfddetach,
947a202823SKonstantin Belousov 	.f_event = filt_eventfdwrite
957a202823SKonstantin Belousov };
967a202823SKonstantin Belousov 
977a202823SKonstantin Belousov struct eventfd {
987a202823SKonstantin Belousov 	eventfd_t	efd_count;
997a202823SKonstantin Belousov 	uint32_t	efd_flags;
1007a202823SKonstantin Belousov 	struct selinfo	efd_sel;
1017a202823SKonstantin Belousov 	struct mtx	efd_lock;
1027a202823SKonstantin Belousov };
1037a202823SKonstantin Belousov 
1047a202823SKonstantin Belousov int
eventfd_create_file(struct thread * td,struct file * fp,uint32_t initval,int flags)1057a202823SKonstantin Belousov eventfd_create_file(struct thread *td, struct file *fp, uint32_t initval,
1067a202823SKonstantin Belousov     int flags)
1077a202823SKonstantin Belousov {
1087a202823SKonstantin Belousov 	struct eventfd *efd;
1097a202823SKonstantin Belousov 	int fflags;
1107a202823SKonstantin Belousov 
1117a202823SKonstantin Belousov 	AUDIT_ARG_FFLAGS(flags);
1127a202823SKonstantin Belousov 	AUDIT_ARG_VALUE(initval);
1137a202823SKonstantin Belousov 
1147a202823SKonstantin Belousov 	efd = malloc(sizeof(*efd), M_EVENTFD, M_WAITOK | M_ZERO);
1157a202823SKonstantin Belousov 	efd->efd_flags = flags;
1167a202823SKonstantin Belousov 	efd->efd_count = initval;
1177a202823SKonstantin Belousov 	mtx_init(&efd->efd_lock, "eventfd", NULL, MTX_DEF);
1187a202823SKonstantin Belousov 	knlist_init_mtx(&efd->efd_sel.si_note, &efd->efd_lock);
1197a202823SKonstantin Belousov 
1207a202823SKonstantin Belousov 	fflags = FREAD | FWRITE;
1217a202823SKonstantin Belousov 	if ((flags & EFD_NONBLOCK) != 0)
1227a202823SKonstantin Belousov 		fflags |= FNONBLOCK;
1237a202823SKonstantin Belousov 	finit(fp, fflags, DTYPE_EVENTFD, efd, &eventfdops);
1247a202823SKonstantin Belousov 
1257a202823SKonstantin Belousov 	return (0);
1267a202823SKonstantin Belousov }
1277a202823SKonstantin Belousov 
1287a202823SKonstantin Belousov static int
eventfd_close(struct file * fp,struct thread * td)1297a202823SKonstantin Belousov eventfd_close(struct file *fp, struct thread *td)
1307a202823SKonstantin Belousov {
1317a202823SKonstantin Belousov 	struct eventfd *efd;
1327a202823SKonstantin Belousov 
1337a202823SKonstantin Belousov 	efd = fp->f_data;
1347a202823SKonstantin Belousov 	seldrain(&efd->efd_sel);
1357a202823SKonstantin Belousov 	knlist_destroy(&efd->efd_sel.si_note);
1367a202823SKonstantin Belousov 	mtx_destroy(&efd->efd_lock);
1377a202823SKonstantin Belousov 	free(efd, M_EVENTFD);
1387a202823SKonstantin Belousov 	return (0);
1397a202823SKonstantin Belousov }
1407a202823SKonstantin Belousov 
1417a202823SKonstantin Belousov static int
eventfd_read(struct file * fp,struct uio * uio,struct ucred * active_cred,int flags,struct thread * td)1427a202823SKonstantin Belousov eventfd_read(struct file *fp, struct uio *uio, struct ucred *active_cred,
1437a202823SKonstantin Belousov     int flags, struct thread *td)
1447a202823SKonstantin Belousov {
1457a202823SKonstantin Belousov 	struct eventfd *efd;
1467a202823SKonstantin Belousov 	eventfd_t count;
1477a202823SKonstantin Belousov 	int error;
1487a202823SKonstantin Belousov 
1497a202823SKonstantin Belousov 	if (uio->uio_resid < sizeof(eventfd_t))
1507a202823SKonstantin Belousov 		return (EINVAL);
1517a202823SKonstantin Belousov 
1527a202823SKonstantin Belousov 	error = 0;
1537a202823SKonstantin Belousov 	efd = fp->f_data;
1547a202823SKonstantin Belousov 	mtx_lock(&efd->efd_lock);
1557a202823SKonstantin Belousov 	while (error == 0 && efd->efd_count == 0) {
1567a202823SKonstantin Belousov 		if ((fp->f_flag & FNONBLOCK) != 0) {
1577a202823SKonstantin Belousov 			mtx_unlock(&efd->efd_lock);
1587a202823SKonstantin Belousov 			return (EAGAIN);
1597a202823SKonstantin Belousov 		}
1607a202823SKonstantin Belousov 		error = mtx_sleep(&efd->efd_count, &efd->efd_lock, PCATCH,
1617a202823SKonstantin Belousov 		    "efdrd", 0);
1627a202823SKonstantin Belousov 	}
1637a202823SKonstantin Belousov 	if (error == 0) {
1647a202823SKonstantin Belousov 		MPASS(efd->efd_count > 0);
1657a202823SKonstantin Belousov 		if ((efd->efd_flags & EFD_SEMAPHORE) != 0) {
1667a202823SKonstantin Belousov 			count = 1;
1677a202823SKonstantin Belousov 			--efd->efd_count;
1687a202823SKonstantin Belousov 		} else {
1697a202823SKonstantin Belousov 			count = efd->efd_count;
1707a202823SKonstantin Belousov 			efd->efd_count = 0;
1717a202823SKonstantin Belousov 		}
1727a202823SKonstantin Belousov 		KNOTE_LOCKED(&efd->efd_sel.si_note, 0);
1737a202823SKonstantin Belousov 		selwakeup(&efd->efd_sel);
1747a202823SKonstantin Belousov 		wakeup(&efd->efd_count);
1757a202823SKonstantin Belousov 		mtx_unlock(&efd->efd_lock);
1767a202823SKonstantin Belousov 		error = uiomove(&count, sizeof(eventfd_t), uio);
1777a202823SKonstantin Belousov 	} else
1787a202823SKonstantin Belousov 		mtx_unlock(&efd->efd_lock);
1797a202823SKonstantin Belousov 
1807a202823SKonstantin Belousov 	return (error);
1817a202823SKonstantin Belousov }
1827a202823SKonstantin Belousov 
1837a202823SKonstantin Belousov static int
eventfd_write(struct file * fp,struct uio * uio,struct ucred * active_cred,int flags,struct thread * td)1847a202823SKonstantin Belousov eventfd_write(struct file *fp, struct uio *uio, struct ucred *active_cred,
1857a202823SKonstantin Belousov     int flags, struct thread *td)
1867a202823SKonstantin Belousov {
1877a202823SKonstantin Belousov 	struct eventfd *efd;
1887a202823SKonstantin Belousov 	eventfd_t count;
1897a202823SKonstantin Belousov 	int error;
1907a202823SKonstantin Belousov 
1917a202823SKonstantin Belousov 	if (uio->uio_resid < sizeof(eventfd_t))
1927a202823SKonstantin Belousov 		return (EINVAL);
1937a202823SKonstantin Belousov 
1947a202823SKonstantin Belousov 	error = uiomove(&count, sizeof(eventfd_t), uio);
1957a202823SKonstantin Belousov 	if (error != 0)
1967a202823SKonstantin Belousov 		return (error);
1977a202823SKonstantin Belousov 	if (count == UINT64_MAX)
1987a202823SKonstantin Belousov 		return (EINVAL);
1997a202823SKonstantin Belousov 
2007a202823SKonstantin Belousov 	efd = fp->f_data;
2017a202823SKonstantin Belousov 	mtx_lock(&efd->efd_lock);
2027a202823SKonstantin Belousov retry:
2037a202823SKonstantin Belousov 	if (UINT64_MAX - efd->efd_count <= count) {
2047a202823SKonstantin Belousov 		if ((fp->f_flag & FNONBLOCK) != 0) {
2057a202823SKonstantin Belousov 			mtx_unlock(&efd->efd_lock);
2067a202823SKonstantin Belousov 			/* Do not not return the number of bytes written */
2077a202823SKonstantin Belousov 			uio->uio_resid += sizeof(eventfd_t);
2087a202823SKonstantin Belousov 			return (EAGAIN);
2097a202823SKonstantin Belousov 		}
2107a202823SKonstantin Belousov 		error = mtx_sleep(&efd->efd_count, &efd->efd_lock,
2117a202823SKonstantin Belousov 		    PCATCH, "efdwr", 0);
2127a202823SKonstantin Belousov 		if (error == 0)
2137a202823SKonstantin Belousov 			goto retry;
2147a202823SKonstantin Belousov 	}
2157a202823SKonstantin Belousov 	if (error == 0) {
2167a202823SKonstantin Belousov 		MPASS(UINT64_MAX - efd->efd_count > count);
2177a202823SKonstantin Belousov 		efd->efd_count += count;
2187a202823SKonstantin Belousov 		KNOTE_LOCKED(&efd->efd_sel.si_note, 0);
2197a202823SKonstantin Belousov 		selwakeup(&efd->efd_sel);
2207a202823SKonstantin Belousov 		wakeup(&efd->efd_count);
2217a202823SKonstantin Belousov 	}
2227a202823SKonstantin Belousov 	mtx_unlock(&efd->efd_lock);
2237a202823SKonstantin Belousov 
2247a202823SKonstantin Belousov 	return (error);
2257a202823SKonstantin Belousov }
2267a202823SKonstantin Belousov 
2277a202823SKonstantin Belousov static int
eventfd_poll(struct file * fp,int events,struct ucred * active_cred,struct thread * td)2287a202823SKonstantin Belousov eventfd_poll(struct file *fp, int events, struct ucred *active_cred,
2297a202823SKonstantin Belousov     struct thread *td)
2307a202823SKonstantin Belousov {
2317a202823SKonstantin Belousov 	struct eventfd *efd;
2327a202823SKonstantin Belousov 	int revents;
2337a202823SKonstantin Belousov 
2347a202823SKonstantin Belousov 	efd = fp->f_data;
2357a202823SKonstantin Belousov 	revents = 0;
2367a202823SKonstantin Belousov 	mtx_lock(&efd->efd_lock);
2377a202823SKonstantin Belousov 	if ((events & (POLLIN | POLLRDNORM)) != 0 && efd->efd_count > 0)
2387a202823SKonstantin Belousov 		revents |= events & (POLLIN | POLLRDNORM);
2397a202823SKonstantin Belousov 	if ((events & (POLLOUT | POLLWRNORM)) != 0 && UINT64_MAX - 1 >
2407a202823SKonstantin Belousov 	    efd->efd_count)
2417a202823SKonstantin Belousov 		revents |= events & (POLLOUT | POLLWRNORM);
2427a202823SKonstantin Belousov 	if (revents == 0)
2437a202823SKonstantin Belousov 		selrecord(td, &efd->efd_sel);
2447a202823SKonstantin Belousov 	mtx_unlock(&efd->efd_lock);
2457a202823SKonstantin Belousov 
2467a202823SKonstantin Belousov 	return (revents);
2477a202823SKonstantin Belousov }
2487a202823SKonstantin Belousov 
2497a202823SKonstantin Belousov static int
eventfd_kqfilter(struct file * fp,struct knote * kn)2507a202823SKonstantin Belousov eventfd_kqfilter(struct file *fp, struct knote *kn)
2517a202823SKonstantin Belousov {
2527a202823SKonstantin Belousov 	struct eventfd *efd = fp->f_data;
2537a202823SKonstantin Belousov 
2547a202823SKonstantin Belousov 	mtx_lock(&efd->efd_lock);
2557a202823SKonstantin Belousov 	switch (kn->kn_filter) {
2567a202823SKonstantin Belousov 	case EVFILT_READ:
2577a202823SKonstantin Belousov 		kn->kn_fop = &eventfd_rfiltops;
2587a202823SKonstantin Belousov 		break;
2597a202823SKonstantin Belousov 	case EVFILT_WRITE:
2607a202823SKonstantin Belousov 		kn->kn_fop = &eventfd_wfiltops;
2617a202823SKonstantin Belousov 		break;
2627a202823SKonstantin Belousov 	default:
2637a202823SKonstantin Belousov 		mtx_unlock(&efd->efd_lock);
2647a202823SKonstantin Belousov 		return (EINVAL);
2657a202823SKonstantin Belousov 	}
2667a202823SKonstantin Belousov 
2677a202823SKonstantin Belousov 	kn->kn_hook = efd;
2687a202823SKonstantin Belousov 	knlist_add(&efd->efd_sel.si_note, kn, 1);
2697a202823SKonstantin Belousov 	mtx_unlock(&efd->efd_lock);
2707a202823SKonstantin Belousov 
2717a202823SKonstantin Belousov 	return (0);
2727a202823SKonstantin Belousov }
2737a202823SKonstantin Belousov 
2747a202823SKonstantin Belousov static void
filt_eventfddetach(struct knote * kn)2757a202823SKonstantin Belousov filt_eventfddetach(struct knote *kn)
2767a202823SKonstantin Belousov {
2777a202823SKonstantin Belousov 	struct eventfd *efd = kn->kn_hook;
2787a202823SKonstantin Belousov 
2797a202823SKonstantin Belousov 	mtx_lock(&efd->efd_lock);
2807a202823SKonstantin Belousov 	knlist_remove(&efd->efd_sel.si_note, kn, 1);
2817a202823SKonstantin Belousov 	mtx_unlock(&efd->efd_lock);
2827a202823SKonstantin Belousov }
2837a202823SKonstantin Belousov 
2847a202823SKonstantin Belousov static int
filt_eventfdread(struct knote * kn,long hint)2857a202823SKonstantin Belousov filt_eventfdread(struct knote *kn, long hint)
2867a202823SKonstantin Belousov {
2877a202823SKonstantin Belousov 	struct eventfd *efd = kn->kn_hook;
2887a202823SKonstantin Belousov 	int ret;
2897a202823SKonstantin Belousov 
2907a202823SKonstantin Belousov 	mtx_assert(&efd->efd_lock, MA_OWNED);
2917a202823SKonstantin Belousov 	kn->kn_data = (int64_t)efd->efd_count;
2927a202823SKonstantin Belousov 	ret = efd->efd_count > 0;
2937a202823SKonstantin Belousov 
2947a202823SKonstantin Belousov 	return (ret);
2957a202823SKonstantin Belousov }
2967a202823SKonstantin Belousov 
2977a202823SKonstantin Belousov static int
filt_eventfdwrite(struct knote * kn,long hint)2987a202823SKonstantin Belousov filt_eventfdwrite(struct knote *kn, long hint)
2997a202823SKonstantin Belousov {
3007a202823SKonstantin Belousov 	struct eventfd *efd = kn->kn_hook;
3017a202823SKonstantin Belousov 	int ret;
3027a202823SKonstantin Belousov 
3037a202823SKonstantin Belousov 	mtx_assert(&efd->efd_lock, MA_OWNED);
3047a202823SKonstantin Belousov 	kn->kn_data = (int64_t)(UINT64_MAX - 1 - efd->efd_count);
3057a202823SKonstantin Belousov 	ret = UINT64_MAX - 1 > efd->efd_count;
3067a202823SKonstantin Belousov 
3077a202823SKonstantin Belousov 	return (ret);
3087a202823SKonstantin Belousov }
3097a202823SKonstantin Belousov 
3107a202823SKonstantin Belousov static int
eventfd_ioctl(struct file * fp,u_long cmd,void * data,struct ucred * active_cred,struct thread * td)3117a202823SKonstantin Belousov eventfd_ioctl(struct file *fp, u_long cmd, void *data,
3127a202823SKonstantin Belousov     struct ucred *active_cred, struct thread *td)
3137a202823SKonstantin Belousov {
3147a202823SKonstantin Belousov 	switch (cmd) {
3157a202823SKonstantin Belousov 	case FIONBIO:
3167a202823SKonstantin Belousov 	case FIOASYNC:
3177a202823SKonstantin Belousov 		return (0);
3187a202823SKonstantin Belousov 	}
3197a202823SKonstantin Belousov 
3207a202823SKonstantin Belousov 	return (ENOTTY);
3217a202823SKonstantin Belousov }
3227a202823SKonstantin Belousov 
3237a202823SKonstantin Belousov static int
eventfd_stat(struct file * fp,struct stat * st,struct ucred * active_cred)3242b68eb8eSMateusz Guzik eventfd_stat(struct file *fp, struct stat *st, struct ucred *active_cred)
3257a202823SKonstantin Belousov {
3267a202823SKonstantin Belousov 	bzero((void *)st, sizeof *st);
3277a202823SKonstantin Belousov 	st->st_mode = S_IFIFO;
3287a202823SKonstantin Belousov 	return (0);
3297a202823SKonstantin Belousov }
3307a202823SKonstantin Belousov 
3317a202823SKonstantin Belousov static int
eventfd_fill_kinfo(struct file * fp,struct kinfo_file * kif,struct filedesc * fdp)3327a202823SKonstantin Belousov eventfd_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
3337a202823SKonstantin Belousov {
3347a202823SKonstantin Belousov 	struct eventfd *efd = fp->f_data;
3357a202823SKonstantin Belousov 
3367a202823SKonstantin Belousov 	kif->kf_type = KF_TYPE_EVENTFD;
3377a202823SKonstantin Belousov 	mtx_lock(&efd->efd_lock);
3387a202823SKonstantin Belousov 	kif->kf_un.kf_eventfd.kf_eventfd_value = efd->efd_count;
3397a202823SKonstantin Belousov 	kif->kf_un.kf_eventfd.kf_eventfd_flags = efd->efd_flags;
3408c309d48SDamjan Jovanovic 	kif->kf_un.kf_eventfd.kf_eventfd_addr = (uintptr_t)efd;
3417a202823SKonstantin Belousov 	mtx_unlock(&efd->efd_lock);
3427a202823SKonstantin Belousov 	return (0);
3437a202823SKonstantin Belousov }
344