xref: /netbsd/tests/lib/libc/sys/t_eventfd.c (revision 91de26f0)
1*91de26f0Sthorpej /* $NetBSD: t_eventfd.c,v 1.3 2022/02/20 15:21:14 thorpej Exp $ */
275f1bc66Sthorpej 
375f1bc66Sthorpej /*-
475f1bc66Sthorpej  * Copyright (c) 2020 The NetBSD Foundation, Inc.
575f1bc66Sthorpej  * All rights reserved.
675f1bc66Sthorpej  *
775f1bc66Sthorpej  * Redistribution and use in source and binary forms, with or without
875f1bc66Sthorpej  * modification, are permitted provided that the following conditions
975f1bc66Sthorpej  * are met:
1075f1bc66Sthorpej  * 1. Redistributions of source code must retain the above copyright
1175f1bc66Sthorpej  *    notice, this list of conditions and the following disclaimer.
1275f1bc66Sthorpej  * 2. Redistributions in binary form must reproduce the above copyright
1375f1bc66Sthorpej  *    notice, this list of conditions and the following disclaimer in the
1475f1bc66Sthorpej  *    documentation and/or other materials provided with the distribution.
1575f1bc66Sthorpej  *
1675f1bc66Sthorpej  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
1775f1bc66Sthorpej  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
1875f1bc66Sthorpej  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1975f1bc66Sthorpej  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2075f1bc66Sthorpej  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2175f1bc66Sthorpej  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2275f1bc66Sthorpej  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2375f1bc66Sthorpej  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2475f1bc66Sthorpej  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2575f1bc66Sthorpej  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2675f1bc66Sthorpej  * POSSIBILITY OF SUCH DAMAGE.
2775f1bc66Sthorpej  */
2875f1bc66Sthorpej 
2975f1bc66Sthorpej #include <sys/cdefs.h>
3075f1bc66Sthorpej __COPYRIGHT("@(#) Copyright (c) 2020\
3175f1bc66Sthorpej  The NetBSD Foundation, inc. All rights reserved.");
32*91de26f0Sthorpej __RCSID("$NetBSD: t_eventfd.c,v 1.3 2022/02/20 15:21:14 thorpej Exp $");
3375f1bc66Sthorpej 
3475f1bc66Sthorpej #include <sys/types.h>
3575f1bc66Sthorpej #include <sys/event.h>
3675f1bc66Sthorpej #include <sys/eventfd.h>
37*91de26f0Sthorpej #include <sys/ioctl.h>
3875f1bc66Sthorpej #include <sys/select.h>
3975f1bc66Sthorpej #include <sys/stat.h>
4075f1bc66Sthorpej #include <sys/syscall.h>
4175f1bc66Sthorpej #include <errno.h>
4275f1bc66Sthorpej #include <poll.h>
4375f1bc66Sthorpej #include <pthread.h>
4475f1bc66Sthorpej #include <stdlib.h>
4575f1bc66Sthorpej #include <stdio.h>
4675f1bc66Sthorpej #include <time.h>
4775f1bc66Sthorpej #include <unistd.h>
4875f1bc66Sthorpej 
4975f1bc66Sthorpej #include <atf-c.h>
5075f1bc66Sthorpej 
5175f1bc66Sthorpej struct helper_context {
5275f1bc66Sthorpej 	int	efd;
5375f1bc66Sthorpej 
5475f1bc66Sthorpej 	pthread_mutex_t mutex;
5575f1bc66Sthorpej 	pthread_cond_t cond;
5675f1bc66Sthorpej 	pthread_barrier_t barrier;
5775f1bc66Sthorpej 	int	state;
5875f1bc66Sthorpej };
5975f1bc66Sthorpej 
6075f1bc66Sthorpej static void
init_helper_context(struct helper_context * const ctx)6175f1bc66Sthorpej init_helper_context(struct helper_context * const ctx)
6275f1bc66Sthorpej {
6375f1bc66Sthorpej 	pthread_condattr_t condattr;
6475f1bc66Sthorpej 
6575f1bc66Sthorpej 	memset(ctx, 0, sizeof(*ctx));
6675f1bc66Sthorpej 
6775f1bc66Sthorpej 	ATF_REQUIRE(pthread_mutex_init(&ctx->mutex, NULL) == 0);
6875f1bc66Sthorpej 
6975f1bc66Sthorpej 	ATF_REQUIRE(pthread_condattr_init(&condattr) == 0);
7075f1bc66Sthorpej 	ATF_REQUIRE(pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC) == 0);
7175f1bc66Sthorpej 	ATF_REQUIRE(pthread_cond_init(&ctx->cond, &condattr) == 0);
7275f1bc66Sthorpej 	ATF_REQUIRE(pthread_condattr_destroy(&condattr) == 0);
7375f1bc66Sthorpej 
7475f1bc66Sthorpej 	ATF_REQUIRE(pthread_barrier_init(&ctx->barrier, NULL, 2) == 0);
7575f1bc66Sthorpej }
7675f1bc66Sthorpej 
7775f1bc66Sthorpej static void
set_state(struct helper_context * const ctx,int const new)7875f1bc66Sthorpej set_state(struct helper_context * const ctx, int const new)
7975f1bc66Sthorpej {
8075f1bc66Sthorpej 	pthread_mutex_lock(&ctx->mutex);
8175f1bc66Sthorpej 	ctx->state = new;
8275f1bc66Sthorpej 	pthread_cond_signal(&ctx->cond);
8375f1bc66Sthorpej 	pthread_mutex_unlock(&ctx->mutex);
8475f1bc66Sthorpej }
8575f1bc66Sthorpej 
8675f1bc66Sthorpej static int
get_state(struct helper_context * const ctx)8775f1bc66Sthorpej get_state(struct helper_context * const ctx)
8875f1bc66Sthorpej {
8975f1bc66Sthorpej 	int rv;
9075f1bc66Sthorpej 
9175f1bc66Sthorpej 	pthread_mutex_lock(&ctx->mutex);
9275f1bc66Sthorpej 	rv = ctx->state;
9375f1bc66Sthorpej 	pthread_mutex_unlock(&ctx->mutex);
9475f1bc66Sthorpej 
9575f1bc66Sthorpej 	return rv;
9675f1bc66Sthorpej }
9775f1bc66Sthorpej 
9875f1bc66Sthorpej static bool
wait_state(struct helper_context * const ctx,int const val)9975f1bc66Sthorpej wait_state(struct helper_context * const ctx, int const val)
10075f1bc66Sthorpej {
10175f1bc66Sthorpej 	struct timespec deadline;
10275f1bc66Sthorpej 	int error;
10375f1bc66Sthorpej 	bool rv;
10475f1bc66Sthorpej 
10575f1bc66Sthorpej 	pthread_mutex_lock(&ctx->mutex);
10675f1bc66Sthorpej 
10775f1bc66Sthorpej 	ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &deadline) == 0);
10875f1bc66Sthorpej 	deadline.tv_sec += 5;
10975f1bc66Sthorpej 
11075f1bc66Sthorpej 	while (ctx->state != val) {
11175f1bc66Sthorpej 		error = pthread_cond_timedwait(&ctx->cond, &ctx->mutex,
11275f1bc66Sthorpej 		    &deadline);
11375f1bc66Sthorpej 		if (error) {
11475f1bc66Sthorpej 			break;
11575f1bc66Sthorpej 		}
11675f1bc66Sthorpej 	}
11775f1bc66Sthorpej 	rv = ctx->state == val;
11875f1bc66Sthorpej 
11975f1bc66Sthorpej 	pthread_mutex_unlock(&ctx->mutex);
12075f1bc66Sthorpej 
12175f1bc66Sthorpej 	return rv;
12275f1bc66Sthorpej }
12375f1bc66Sthorpej 
12475f1bc66Sthorpej static bool
wait_barrier(struct helper_context * const ctx)12575f1bc66Sthorpej wait_barrier(struct helper_context * const ctx)
12675f1bc66Sthorpej {
12775f1bc66Sthorpej 	int rv = pthread_barrier_wait(&ctx->barrier);
12875f1bc66Sthorpej 
12975f1bc66Sthorpej 	return rv == 0 || rv == PTHREAD_BARRIER_SERIAL_THREAD;
13075f1bc66Sthorpej }
13175f1bc66Sthorpej 
13275f1bc66Sthorpej /*****************************************************************************/
13375f1bc66Sthorpej 
13475f1bc66Sthorpej static void *
eventfd_normal_helper(void * const v)13575f1bc66Sthorpej eventfd_normal_helper(void * const v)
13675f1bc66Sthorpej {
13775f1bc66Sthorpej 	struct helper_context * const ctx = v;
13875f1bc66Sthorpej 	eventfd_t efd_value;
13975f1bc66Sthorpej 
14075f1bc66Sthorpej 	ATF_REQUIRE(wait_barrier(ctx));
14175f1bc66Sthorpej 
14275f1bc66Sthorpej 	/* Read the value.  This will reset it to zero. */
14375f1bc66Sthorpej 	ATF_REQUIRE(get_state(ctx) == 666);
14475f1bc66Sthorpej 	ATF_REQUIRE(eventfd_read(ctx->efd, &efd_value) == 0);
14575f1bc66Sthorpej 
14675f1bc66Sthorpej 	/* Assert the value. */
14775f1bc66Sthorpej 	ATF_REQUIRE(efd_value == 0xcafebabe);
14875f1bc66Sthorpej 
14975f1bc66Sthorpej 	set_state(ctx, 0);
15075f1bc66Sthorpej 
15175f1bc66Sthorpej 	/* Wait for the main thread to prep the next test. */
15275f1bc66Sthorpej 	ATF_REQUIRE(wait_barrier(ctx));
15375f1bc66Sthorpej 
15475f1bc66Sthorpej 	/* Read the value. */
15575f1bc66Sthorpej 	ATF_REQUIRE(eventfd_read(ctx->efd, &efd_value) == 0);
15675f1bc66Sthorpej 
15775f1bc66Sthorpej 	/* Assert the value. */
15875f1bc66Sthorpej 	ATF_REQUIRE(efd_value == 0xbeefcafe);
15975f1bc66Sthorpej 
16075f1bc66Sthorpej 	ATF_REQUIRE(wait_barrier(ctx));
16175f1bc66Sthorpej 
16275f1bc66Sthorpej 	return NULL;
16375f1bc66Sthorpej }
16475f1bc66Sthorpej 
16575f1bc66Sthorpej ATF_TC(eventfd_normal);
ATF_TC_HEAD(eventfd_normal,tc)16675f1bc66Sthorpej ATF_TC_HEAD(eventfd_normal, tc)
16775f1bc66Sthorpej {
16875f1bc66Sthorpej 	atf_tc_set_md_var(tc, "descr",
16975f1bc66Sthorpej 	    "validates basic normal eventfd operation");
17075f1bc66Sthorpej }
ATF_TC_BODY(eventfd_normal,tc)17175f1bc66Sthorpej ATF_TC_BODY(eventfd_normal, tc)
17275f1bc66Sthorpej {
17375f1bc66Sthorpej 	struct helper_context ctx;
17475f1bc66Sthorpej 	pthread_t helper;
17575f1bc66Sthorpej 	void *join_val;
17675f1bc66Sthorpej 
17775f1bc66Sthorpej 	init_helper_context(&ctx);
17875f1bc66Sthorpej 
17975f1bc66Sthorpej 	ATF_REQUIRE((ctx.efd = eventfd(0, 0)) >= 0);
18075f1bc66Sthorpej 
18175f1bc66Sthorpej 	ATF_REQUIRE(pthread_create(&helper, NULL,
18275f1bc66Sthorpej 				   eventfd_normal_helper, &ctx) == 0);
18375f1bc66Sthorpej 
18475f1bc66Sthorpej 	/*
18575f1bc66Sthorpej 	 * Wait for the helper to block in read().  Give it some time
18675f1bc66Sthorpej 	 * so that if the read fails or returns immediately, we'll
18775f1bc66Sthorpej 	 * notice.
18875f1bc66Sthorpej 	 */
18975f1bc66Sthorpej 	set_state(&ctx, 666);
19075f1bc66Sthorpej 	ATF_REQUIRE(wait_barrier(&ctx));
19175f1bc66Sthorpej 	sleep(2);
19275f1bc66Sthorpej 	ATF_REQUIRE(get_state(&ctx) == 666);
19375f1bc66Sthorpej 
19475f1bc66Sthorpej 	/* Write a distinct value; helper will assert it. */
19575f1bc66Sthorpej 	ATF_REQUIRE(eventfd_write(ctx.efd, 0xcafebabe) == 0);
19675f1bc66Sthorpej 
19775f1bc66Sthorpej 	/* Wait for helper to read the value. */
19875f1bc66Sthorpej 	ATF_REQUIRE(wait_state(&ctx, 0));
19975f1bc66Sthorpej 
20075f1bc66Sthorpej 	/* Helper is now blocked in a barrier. */
20175f1bc66Sthorpej 
20275f1bc66Sthorpej 	/* Test additive property of the efd value. */
20375f1bc66Sthorpej 	ATF_REQUIRE(eventfd_write(ctx.efd, 0x0000cafe) == 0);
20475f1bc66Sthorpej 	ATF_REQUIRE(eventfd_write(ctx.efd, 0xbeef0000) == 0);
20575f1bc66Sthorpej 
20675f1bc66Sthorpej 	/* Satisfy the barrier; helper will read value and assert 0xbeefcafe. */
20775f1bc66Sthorpej 	ATF_REQUIRE(wait_barrier(&ctx));
20875f1bc66Sthorpej 
20975f1bc66Sthorpej 	/* And wait for it to finish. */
21075f1bc66Sthorpej 	ATF_REQUIRE(wait_barrier(&ctx));
21175f1bc66Sthorpej 
21275f1bc66Sthorpej 	/* Reap the helper. */
21375f1bc66Sthorpej 	ATF_REQUIRE(pthread_join(helper, &join_val) == 0);
21475f1bc66Sthorpej 
21575f1bc66Sthorpej 	(void) close(ctx.efd);
21675f1bc66Sthorpej }
21775f1bc66Sthorpej 
21875f1bc66Sthorpej /*****************************************************************************/
21975f1bc66Sthorpej 
22075f1bc66Sthorpej ATF_TC(eventfd_semaphore);
ATF_TC_HEAD(eventfd_semaphore,tc)22175f1bc66Sthorpej ATF_TC_HEAD(eventfd_semaphore, tc)
22275f1bc66Sthorpej {
22375f1bc66Sthorpej 	atf_tc_set_md_var(tc, "descr",
22475f1bc66Sthorpej 	    "validates semaphore and non-blocking eventfd operation");
22575f1bc66Sthorpej }
ATF_TC_BODY(eventfd_semaphore,tc)22675f1bc66Sthorpej ATF_TC_BODY(eventfd_semaphore, tc)
22775f1bc66Sthorpej {
22875f1bc66Sthorpej 	eventfd_t efd_value;
22975f1bc66Sthorpej 	int efd;
23075f1bc66Sthorpej 
23175f1bc66Sthorpej 	ATF_REQUIRE((efd = eventfd(3, EFD_SEMAPHORE | EFD_NONBLOCK)) >= 0);
23275f1bc66Sthorpej 
23375f1bc66Sthorpej 	/* 3 reads should succeed without blocking. */
23475f1bc66Sthorpej 	ATF_REQUIRE(eventfd_read(efd, &efd_value) == 0);
23575f1bc66Sthorpej 	ATF_REQUIRE(efd_value == 1);
23675f1bc66Sthorpej 
23775f1bc66Sthorpej 	ATF_REQUIRE(eventfd_read(efd, &efd_value) == 0);
23875f1bc66Sthorpej 	ATF_REQUIRE(efd_value == 1);
23975f1bc66Sthorpej 
24075f1bc66Sthorpej 	ATF_REQUIRE(eventfd_read(efd, &efd_value) == 0);
24175f1bc66Sthorpej 	ATF_REQUIRE(efd_value == 1);
24275f1bc66Sthorpej 
24375f1bc66Sthorpej 	/* This one should block. */
24475f1bc66Sthorpej 	ATF_REQUIRE_ERRNO(EAGAIN,
24575f1bc66Sthorpej 	    eventfd_read(efd, &efd_value) == -1);
24675f1bc66Sthorpej 
24775f1bc66Sthorpej 	/* Add 1 to the semaphore. */
24875f1bc66Sthorpej 	ATF_REQUIRE(eventfd_write(efd, 1) == 0);
24975f1bc66Sthorpej 
25075f1bc66Sthorpej 	/* One more read allowed. */
25175f1bc66Sthorpej 	ATF_REQUIRE(eventfd_read(efd, &efd_value) == 0);
25275f1bc66Sthorpej 	ATF_REQUIRE(efd_value == 1);
25375f1bc66Sthorpej 
25475f1bc66Sthorpej 	/* And this one again should block. */
25575f1bc66Sthorpej 	ATF_REQUIRE_ERRNO(EAGAIN,
25675f1bc66Sthorpej 	    eventfd_read(efd, &efd_value) == -1);
25775f1bc66Sthorpej 
25875f1bc66Sthorpej 	(void) close(efd);
25975f1bc66Sthorpej }
26075f1bc66Sthorpej 
26175f1bc66Sthorpej /*****************************************************************************/
26275f1bc66Sthorpej 
26375f1bc66Sthorpej ATF_TC(eventfd_select_poll_kevent_immed);
ATF_TC_HEAD(eventfd_select_poll_kevent_immed,tc)26475f1bc66Sthorpej ATF_TC_HEAD(eventfd_select_poll_kevent_immed, tc)
26575f1bc66Sthorpej {
26675f1bc66Sthorpej 	atf_tc_set_md_var(tc, "descr",
26775f1bc66Sthorpej 	    "validates select/poll/kevent behavior - immediate return");
26875f1bc66Sthorpej }
ATF_TC_BODY(eventfd_select_poll_kevent_immed,tc)26975f1bc66Sthorpej ATF_TC_BODY(eventfd_select_poll_kevent_immed, tc)
27075f1bc66Sthorpej {
27175f1bc66Sthorpej 	const struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 };
27275f1bc66Sthorpej 	struct timeval tv;
27375f1bc66Sthorpej 	struct pollfd fds[1];
27475f1bc66Sthorpej 	fd_set readfds, writefds, exceptfds;
27575f1bc66Sthorpej 	int efd;
27675f1bc66Sthorpej 	int kq;
27775f1bc66Sthorpej 	struct kevent kev[2];
27875f1bc66Sthorpej 
27975f1bc66Sthorpej 	ATF_REQUIRE((efd = eventfd(0, EFD_NONBLOCK)) >= 0);
28075f1bc66Sthorpej 
28175f1bc66Sthorpej 	ATF_REQUIRE((kq = kqueue()) >= 0);
28275f1bc66Sthorpej 	EV_SET(&kev[0], efd, EVFILT_READ, EV_ADD, 0, 0, NULL);
28375f1bc66Sthorpej 	EV_SET(&kev[1], efd, EVFILT_WRITE, EV_ADD, 0, 0, NULL);
28475f1bc66Sthorpej 	ATF_REQUIRE(kevent(kq, kev, 2, NULL, 0, &ts) == 0);
28575f1bc66Sthorpej 
28675f1bc66Sthorpej 	/*
28775f1bc66Sthorpej 	 * efd should be writable but not readable.  Pass all of the
28875f1bc66Sthorpej 	 * event bits; we should only get back POLLOUT | POLLWRNORM.
28975f1bc66Sthorpej 	 */
29075f1bc66Sthorpej 	fds[0].fd = efd;
29175f1bc66Sthorpej 	fds[0].events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI |
29275f1bc66Sthorpej 	    POLLOUT | POLLWRNORM | POLLWRBAND | POLLHUP;
29375f1bc66Sthorpej 	fds[0].revents = 0;
29475f1bc66Sthorpej 	ATF_REQUIRE(poll(fds, 1, 0) == 1);
29575f1bc66Sthorpej 	ATF_REQUIRE(fds[0].revents == (POLLOUT | POLLWRNORM));
29675f1bc66Sthorpej 
29775f1bc66Sthorpej 	/*
29875f1bc66Sthorpej 	 * As above; efd should only be set in writefds upon return
29975f1bc66Sthorpej 	 * from the select() call.
30075f1bc66Sthorpej 	 */
30175f1bc66Sthorpej 	FD_ZERO(&readfds);
30275f1bc66Sthorpej 	FD_ZERO(&writefds);
30375f1bc66Sthorpej 	FD_ZERO(&exceptfds);
30475f1bc66Sthorpej 	tv.tv_sec = 0;
30575f1bc66Sthorpej 	tv.tv_usec = 0;
30675f1bc66Sthorpej 	FD_SET(efd, &readfds);
30775f1bc66Sthorpej 	FD_SET(efd, &writefds);
30875f1bc66Sthorpej 	FD_SET(efd, &exceptfds);
30975f1bc66Sthorpej 	ATF_REQUIRE(select(efd + 1, &readfds, &writefds, &exceptfds, &tv) == 1);
31075f1bc66Sthorpej 	ATF_REQUIRE(!FD_ISSET(efd, &readfds));
31175f1bc66Sthorpej 	ATF_REQUIRE(FD_ISSET(efd, &writefds));
31275f1bc66Sthorpej 	ATF_REQUIRE(!FD_ISSET(efd, &exceptfds));
31375f1bc66Sthorpej 
31475f1bc66Sthorpej 	/*
31575f1bc66Sthorpej 	 * Check that we get an EVFILT_WRITE event (and only that event)
31675f1bc66Sthorpej 	 * on efd.
31775f1bc66Sthorpej 	 */
31875f1bc66Sthorpej 	memset(kev, 0, sizeof(kev));
31975f1bc66Sthorpej 	ATF_REQUIRE(kevent(kq, NULL, 0, kev, 2, &ts) == 1);
32075f1bc66Sthorpej 	ATF_REQUIRE(kev[0].ident == (uintptr_t)efd);
32175f1bc66Sthorpej 	ATF_REQUIRE(kev[0].filter == EVFILT_WRITE);
32275f1bc66Sthorpej 	ATF_REQUIRE((kev[0].flags & (EV_EOF | EV_ERROR)) == 0);
32375f1bc66Sthorpej 	ATF_REQUIRE(kev[0].data == 0);
32475f1bc66Sthorpej 
32575f1bc66Sthorpej 	/*
32675f1bc66Sthorpej 	 * Write the maximum value into the eventfd.  This should result
32775f1bc66Sthorpej 	 * in the eventfd becoming readable but NOT writable.
32875f1bc66Sthorpej 	 */
32975f1bc66Sthorpej 	ATF_REQUIRE(eventfd_write(efd, UINT64_MAX - 1) == 0);
33075f1bc66Sthorpej 
33175f1bc66Sthorpej 	fds[0].fd = efd;
33275f1bc66Sthorpej 	fds[0].events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI |
33375f1bc66Sthorpej 	    POLLOUT | POLLWRNORM | POLLWRBAND | POLLHUP;
33475f1bc66Sthorpej 	fds[0].revents = 0;
33575f1bc66Sthorpej 	ATF_REQUIRE(poll(fds, 1, 0) == 1);
33675f1bc66Sthorpej 	ATF_REQUIRE(fds[0].revents == (POLLIN | POLLRDNORM));
33775f1bc66Sthorpej 
33875f1bc66Sthorpej 	FD_ZERO(&readfds);
33975f1bc66Sthorpej 	FD_ZERO(&writefds);
34075f1bc66Sthorpej 	FD_ZERO(&exceptfds);
34175f1bc66Sthorpej 	tv.tv_sec = 0;
34275f1bc66Sthorpej 	tv.tv_usec = 0;
34375f1bc66Sthorpej 	FD_SET(efd, &readfds);
34475f1bc66Sthorpej 	FD_SET(efd, &writefds);
34575f1bc66Sthorpej 	FD_SET(efd, &exceptfds);
34675f1bc66Sthorpej 	ATF_REQUIRE(select(efd + 1, &readfds, &writefds, &exceptfds, &tv) == 1);
34775f1bc66Sthorpej 	ATF_REQUIRE(FD_ISSET(efd, &readfds));
34875f1bc66Sthorpej 	ATF_REQUIRE(!FD_ISSET(efd, &writefds));
34975f1bc66Sthorpej 	ATF_REQUIRE(!FD_ISSET(efd, &exceptfds));
35075f1bc66Sthorpej 
35175f1bc66Sthorpej 	/*
35275f1bc66Sthorpej 	 * Check that we get an EVFILT_READ event (and only that event)
35375f1bc66Sthorpej 	 * on efd.
35475f1bc66Sthorpej 	 */
35575f1bc66Sthorpej 	memset(kev, 0, sizeof(kev));
35675f1bc66Sthorpej 	ATF_REQUIRE(kevent(kq, NULL, 0, kev, 2, &ts) == 1);
35775f1bc66Sthorpej 	ATF_REQUIRE(kev[0].ident == (uintptr_t)efd);
35875f1bc66Sthorpej 	ATF_REQUIRE(kev[0].filter == EVFILT_READ);
35975f1bc66Sthorpej 	ATF_REQUIRE((kev[0].flags & (EV_EOF | EV_ERROR)) == 0);
36075f1bc66Sthorpej 	ATF_REQUIRE(kev[0].data == (int64_t)(UINT64_MAX - 1));
36175f1bc66Sthorpej 
36275f1bc66Sthorpej 	(void) close(kq);
36375f1bc66Sthorpej 	(void) close(efd);
36475f1bc66Sthorpej }
36575f1bc66Sthorpej 
36675f1bc66Sthorpej /*****************************************************************************/
36775f1bc66Sthorpej 
36875f1bc66Sthorpej static void *
eventfd_select_poll_kevent_block_helper(void * const v)36975f1bc66Sthorpej eventfd_select_poll_kevent_block_helper(void * const v)
37075f1bc66Sthorpej {
37175f1bc66Sthorpej 	struct helper_context * const ctx = v;
37275f1bc66Sthorpej 	struct pollfd fds[1];
37375f1bc66Sthorpej 	fd_set selfds;
37475f1bc66Sthorpej 	eventfd_t efd_value;
37575f1bc66Sthorpej 	int kq;
37675f1bc66Sthorpej 	struct kevent kev[1];
37775f1bc66Sthorpej 
37875f1bc66Sthorpej 	fds[0].fd = ctx->efd;
37975f1bc66Sthorpej 	fds[0].events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI;
38075f1bc66Sthorpej 	fds[0].revents = 0;
38175f1bc66Sthorpej 
38275f1bc66Sthorpej 	ATF_REQUIRE_ERRNO(EAGAIN,
38375f1bc66Sthorpej 	    eventfd_read(ctx->efd, &efd_value) == -1);
38475f1bc66Sthorpej 
38575f1bc66Sthorpej 	ATF_REQUIRE(wait_barrier(ctx));
38675f1bc66Sthorpej 
38775f1bc66Sthorpej 	ATF_REQUIRE(get_state(ctx) == 666);
38875f1bc66Sthorpej 	ATF_REQUIRE(poll(fds, 1, INFTIM) == 1);
38975f1bc66Sthorpej 	ATF_REQUIRE(fds[0].revents == (POLLIN | POLLRDNORM));
39075f1bc66Sthorpej 	set_state(ctx, 0);
39175f1bc66Sthorpej 
39275f1bc66Sthorpej 	ATF_REQUIRE(wait_barrier(ctx));
39375f1bc66Sthorpej 
39475f1bc66Sthorpej 	/*
39575f1bc66Sthorpej 	 * The maximum value was written to the eventfd, so we
39675f1bc66Sthorpej 	 * should block waiting for writability.
39775f1bc66Sthorpej 	 */
39875f1bc66Sthorpej 	fds[0].fd = ctx->efd;
39975f1bc66Sthorpej 	fds[0].events = POLLOUT | POLLWRNORM;
40075f1bc66Sthorpej 	fds[0].revents = 0;
40175f1bc66Sthorpej 
40275f1bc66Sthorpej 	ATF_REQUIRE_ERRNO(EAGAIN,
40375f1bc66Sthorpej 	    eventfd_write(ctx->efd, UINT64_MAX - 1) == -1);
40475f1bc66Sthorpej 
40575f1bc66Sthorpej 	ATF_REQUIRE(wait_barrier(ctx));
40675f1bc66Sthorpej 
40775f1bc66Sthorpej 	ATF_REQUIRE(get_state(ctx) == 666);
40875f1bc66Sthorpej 	ATF_REQUIRE(poll(fds, 1, INFTIM) == 1);
40975f1bc66Sthorpej 	ATF_REQUIRE(fds[0].revents == (POLLOUT | POLLWRNORM));
41075f1bc66Sthorpej 	set_state(ctx, 0);
41175f1bc66Sthorpej 
41275f1bc66Sthorpej 	ATF_REQUIRE(wait_barrier(ctx));
41375f1bc66Sthorpej 
41475f1bc66Sthorpej 	/*
41575f1bc66Sthorpej 	 * Now, the same dance again, with select().
41675f1bc66Sthorpej 	 */
41775f1bc66Sthorpej 
41875f1bc66Sthorpej 	FD_ZERO(&selfds);
41975f1bc66Sthorpej 	FD_SET(ctx->efd, &selfds);
42075f1bc66Sthorpej 
42175f1bc66Sthorpej 	ATF_REQUIRE_ERRNO(EAGAIN,
42275f1bc66Sthorpej 	    eventfd_read(ctx->efd, &efd_value) == -1);
42375f1bc66Sthorpej 
42475f1bc66Sthorpej 	ATF_REQUIRE(wait_barrier(ctx));
42575f1bc66Sthorpej 
42675f1bc66Sthorpej 	ATF_REQUIRE(get_state(ctx) == 666);
42775f1bc66Sthorpej 	ATF_REQUIRE(select(ctx->efd + 1, &selfds, NULL, NULL, NULL) == 1);
42875f1bc66Sthorpej 	ATF_REQUIRE(FD_ISSET(ctx->efd, &selfds));
42975f1bc66Sthorpej 	set_state(ctx, 0);
43075f1bc66Sthorpej 
43175f1bc66Sthorpej 	ATF_REQUIRE(wait_barrier(ctx));
43275f1bc66Sthorpej 
43375f1bc66Sthorpej 	FD_ZERO(&selfds);
43475f1bc66Sthorpej 	FD_SET(ctx->efd, &selfds);
43575f1bc66Sthorpej 
43675f1bc66Sthorpej 	ATF_REQUIRE_ERRNO(EAGAIN,
43775f1bc66Sthorpej 	    eventfd_write(ctx->efd, UINT64_MAX - 1) == -1);
43875f1bc66Sthorpej 
43975f1bc66Sthorpej 	ATF_REQUIRE(wait_barrier(ctx));
44075f1bc66Sthorpej 
44175f1bc66Sthorpej 	ATF_REQUIRE(get_state(ctx) == 666);
44275f1bc66Sthorpej 	ATF_REQUIRE(select(ctx->efd + 1, NULL, &selfds, NULL, NULL) == 1);
44375f1bc66Sthorpej 	ATF_REQUIRE(FD_ISSET(ctx->efd, &selfds));
44475f1bc66Sthorpej 	set_state(ctx, 0);
44575f1bc66Sthorpej 
44675f1bc66Sthorpej 	ATF_REQUIRE(wait_barrier(ctx));
44775f1bc66Sthorpej 
44875f1bc66Sthorpej 	/*
44975f1bc66Sthorpej 	 * Now, the same dance again, with kevent().
45075f1bc66Sthorpej 	 */
45175f1bc66Sthorpej 	ATF_REQUIRE((kq = kqueue()) >= 0);
45275f1bc66Sthorpej 
45375f1bc66Sthorpej 	EV_SET(&kev[0], ctx->efd, EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, NULL);
45475f1bc66Sthorpej 	ATF_REQUIRE(kevent(kq, kev, 1, NULL, 0, NULL) == 0);
45575f1bc66Sthorpej 
45675f1bc66Sthorpej 	ATF_REQUIRE_ERRNO(EAGAIN,
45775f1bc66Sthorpej 	    eventfd_read(ctx->efd, &efd_value) == -1);
45875f1bc66Sthorpej 
45975f1bc66Sthorpej 	ATF_REQUIRE(wait_barrier(ctx));
46075f1bc66Sthorpej 
46175f1bc66Sthorpej 	ATF_REQUIRE(get_state(ctx) == 666);
46275f1bc66Sthorpej 	ATF_REQUIRE(kevent(kq, NULL, 0, kev, 1, NULL) == 1);
46375f1bc66Sthorpej 	ATF_REQUIRE(kev[0].ident == (uintptr_t)ctx->efd);
46475f1bc66Sthorpej 	ATF_REQUIRE(kev[0].filter == EVFILT_READ);
46575f1bc66Sthorpej 	ATF_REQUIRE((kev[0].flags & (EV_EOF | EV_ERROR)) == 0);
46675f1bc66Sthorpej 	ATF_REQUIRE(kev[0].data == (int64_t)(UINT64_MAX - 1));
46775f1bc66Sthorpej 	set_state(ctx, 0);
46875f1bc66Sthorpej 
46975f1bc66Sthorpej 	ATF_REQUIRE(wait_barrier(ctx));
47075f1bc66Sthorpej 
47175f1bc66Sthorpej 	EV_SET(&kev[0], ctx->efd, EVFILT_WRITE, EV_ADD | EV_ONESHOT, 0, 0,
47275f1bc66Sthorpej 	       NULL);
47375f1bc66Sthorpej 	ATF_REQUIRE(kevent(kq, kev, 1, NULL, 0, NULL) == 0);
47475f1bc66Sthorpej 
47575f1bc66Sthorpej 	ATF_REQUIRE_ERRNO(EAGAIN,
47675f1bc66Sthorpej 	    eventfd_write(ctx->efd, UINT64_MAX - 1) == -1);
47775f1bc66Sthorpej 
47875f1bc66Sthorpej 	ATF_REQUIRE(wait_barrier(ctx));
47975f1bc66Sthorpej 
48075f1bc66Sthorpej 	ATF_REQUIRE(get_state(ctx) == 666);
48175f1bc66Sthorpej 	ATF_REQUIRE(kevent(kq, NULL, 0, kev, 1, NULL) == 1);
48275f1bc66Sthorpej 	ATF_REQUIRE(kev[0].ident == (uintptr_t)ctx->efd);
48375f1bc66Sthorpej 	ATF_REQUIRE(kev[0].filter == EVFILT_WRITE);
48475f1bc66Sthorpej 	ATF_REQUIRE((kev[0].flags & (EV_EOF | EV_ERROR)) == 0);
48575f1bc66Sthorpej 	ATF_REQUIRE(kev[0].data == 0);
48675f1bc66Sthorpej 	set_state(ctx, 0);
48775f1bc66Sthorpej 
48875f1bc66Sthorpej 	ATF_REQUIRE(wait_barrier(ctx));
48975f1bc66Sthorpej 
49075f1bc66Sthorpej 	(void) close(kq);
49175f1bc66Sthorpej 
49275f1bc66Sthorpej 	return NULL;
49375f1bc66Sthorpej }
49475f1bc66Sthorpej 
49575f1bc66Sthorpej ATF_TC(eventfd_select_poll_kevent_block);
ATF_TC_HEAD(eventfd_select_poll_kevent_block,tc)49675f1bc66Sthorpej ATF_TC_HEAD(eventfd_select_poll_kevent_block, tc)
49775f1bc66Sthorpej {
49875f1bc66Sthorpej 	atf_tc_set_md_var(tc, "descr",
49975f1bc66Sthorpej 	    "validates select/poll/kevent behavior - return after blocking");
50075f1bc66Sthorpej }
ATF_TC_BODY(eventfd_select_poll_kevent_block,tc)50175f1bc66Sthorpej ATF_TC_BODY(eventfd_select_poll_kevent_block, tc)
50275f1bc66Sthorpej {
50375f1bc66Sthorpej 	struct helper_context ctx;
50475f1bc66Sthorpej 	pthread_t helper;
50575f1bc66Sthorpej 	eventfd_t efd_value;
50675f1bc66Sthorpej 	void *join_val;
50775f1bc66Sthorpej 
50875f1bc66Sthorpej 	init_helper_context(&ctx);
50975f1bc66Sthorpej 
51075f1bc66Sthorpej 	ATF_REQUIRE((ctx.efd = eventfd(0, EFD_NONBLOCK)) >= 0);
51175f1bc66Sthorpej 
51275f1bc66Sthorpej 	ATF_REQUIRE(pthread_create(&helper, NULL,
51375f1bc66Sthorpej 				   eventfd_select_poll_kevent_block_helper,
51475f1bc66Sthorpej 				   &ctx) == 0);
51575f1bc66Sthorpej 
51675f1bc66Sthorpej 	/*
51775f1bc66Sthorpej 	 * Wait for the helper to block in poll().  Give it some time
51875f1bc66Sthorpej 	 * so that if the poll returns immediately, we'll notice.
51975f1bc66Sthorpej 	 */
52075f1bc66Sthorpej 	set_state(&ctx, 666);
52175f1bc66Sthorpej 	ATF_REQUIRE(wait_barrier(&ctx));
52275f1bc66Sthorpej 	sleep(2);
52375f1bc66Sthorpej 	ATF_REQUIRE(get_state(&ctx) == 666);
52475f1bc66Sthorpej 
52575f1bc66Sthorpej 	/*
52675f1bc66Sthorpej 	 * Write the max value to the eventfd so that it becomes readable
52775f1bc66Sthorpej 	 * and unblocks the helper waiting in poll().
52875f1bc66Sthorpej 	 */
52975f1bc66Sthorpej 	ATF_REQUIRE(eventfd_write(ctx.efd, UINT64_MAX - 1) == 0);
53075f1bc66Sthorpej 
53175f1bc66Sthorpej 	/*
53275f1bc66Sthorpej 	 * Ensure the helper woke from the poll() call.
53375f1bc66Sthorpej 	 */
53475f1bc66Sthorpej 	ATF_REQUIRE(wait_barrier(&ctx));
53575f1bc66Sthorpej 	ATF_REQUIRE(get_state(&ctx) == 0);
53675f1bc66Sthorpej 
53775f1bc66Sthorpej 	/*
53875f1bc66Sthorpej 	 * Wait for the helper to block in poll(), this time waiting
53975f1bc66Sthorpej 	 * for writability.
54075f1bc66Sthorpej 	 */
54175f1bc66Sthorpej 	set_state(&ctx, 666);
54275f1bc66Sthorpej 	ATF_REQUIRE(wait_barrier(&ctx));
54375f1bc66Sthorpej 	sleep(2);
54475f1bc66Sthorpej 	ATF_REQUIRE(get_state(&ctx) == 666);
54575f1bc66Sthorpej 
54675f1bc66Sthorpej 	/*
54775f1bc66Sthorpej 	 * Now read the value, which will reset the eventfd to 0 and
54875f1bc66Sthorpej 	 * unblock the poll() call.
54975f1bc66Sthorpej 	 */
55075f1bc66Sthorpej 	ATF_REQUIRE(eventfd_read(ctx.efd, &efd_value) == 0);
55175f1bc66Sthorpej 	ATF_REQUIRE(efd_value == UINT64_MAX - 1);
55275f1bc66Sthorpej 
55375f1bc66Sthorpej 	/*
55475f1bc66Sthorpej 	 * Ensure that the helper woke from the poll() call.
55575f1bc66Sthorpej 	 */
55675f1bc66Sthorpej 	ATF_REQUIRE(wait_barrier(&ctx));
55775f1bc66Sthorpej 	ATF_REQUIRE(get_state(&ctx) == 0);
55875f1bc66Sthorpej 
55975f1bc66Sthorpej 	/*
56075f1bc66Sthorpej 	 * Wait for the helper to block in select(), waiting for readability.
56175f1bc66Sthorpej 	 */
56275f1bc66Sthorpej 	set_state(&ctx, 666);
56375f1bc66Sthorpej 	ATF_REQUIRE(wait_barrier(&ctx));
56475f1bc66Sthorpej 	sleep(2);
56575f1bc66Sthorpej 	ATF_REQUIRE(get_state(&ctx) == 666);
56675f1bc66Sthorpej 
56775f1bc66Sthorpej 	/*
56875f1bc66Sthorpej 	 * Write the max value to the eventfd so that it becomes readable
56975f1bc66Sthorpej 	 * and unblocks the helper waiting in select().
57075f1bc66Sthorpej 	 */
57175f1bc66Sthorpej 	efd_value = UINT64_MAX - 1;
57275f1bc66Sthorpej 	ATF_REQUIRE(eventfd_write(ctx.efd, UINT64_MAX - 1) == 0);
57375f1bc66Sthorpej 
57475f1bc66Sthorpej 	/*
57575f1bc66Sthorpej 	 * Ensure the helper woke from the select() call.
57675f1bc66Sthorpej 	 */
57775f1bc66Sthorpej 	ATF_REQUIRE(wait_barrier(&ctx));
57875f1bc66Sthorpej 	ATF_REQUIRE(get_state(&ctx) == 0);
57975f1bc66Sthorpej 
58075f1bc66Sthorpej 	/*
58175f1bc66Sthorpej 	 * Wait for the helper to block in select(), this time waiting
58275f1bc66Sthorpej 	 * for writability.
58375f1bc66Sthorpej 	 */
58475f1bc66Sthorpej 	set_state(&ctx, 666);
58575f1bc66Sthorpej 	ATF_REQUIRE(wait_barrier(&ctx));
58675f1bc66Sthorpej 	sleep(2);
58775f1bc66Sthorpej 	ATF_REQUIRE(get_state(&ctx) == 666);
58875f1bc66Sthorpej 
58975f1bc66Sthorpej 	/*
59075f1bc66Sthorpej 	 * Now read the value, which will reset the eventfd to 0 and
59175f1bc66Sthorpej 	 * unblock the select() call.
59275f1bc66Sthorpej 	 */
59375f1bc66Sthorpej 	ATF_REQUIRE(eventfd_read(ctx.efd, &efd_value) == 0);
59475f1bc66Sthorpej 	ATF_REQUIRE(efd_value == UINT64_MAX - 1);
59575f1bc66Sthorpej 
59675f1bc66Sthorpej 	/*
59775f1bc66Sthorpej 	 * Ensure that the helper woke from the select() call.
59875f1bc66Sthorpej 	 */
59975f1bc66Sthorpej 	ATF_REQUIRE(wait_barrier(&ctx));
60075f1bc66Sthorpej 	ATF_REQUIRE(get_state(&ctx) == 0);
60175f1bc66Sthorpej 
60275f1bc66Sthorpej 	/*
60375f1bc66Sthorpej 	 * Wait for the helper to block in kevent(), waiting for readability.
60475f1bc66Sthorpej 	 */
60575f1bc66Sthorpej 	set_state(&ctx, 666);
60675f1bc66Sthorpej 	ATF_REQUIRE(wait_barrier(&ctx));
60775f1bc66Sthorpej 	sleep(2);
60875f1bc66Sthorpej 	ATF_REQUIRE(get_state(&ctx) == 666);
60975f1bc66Sthorpej 
61075f1bc66Sthorpej 	/*
61175f1bc66Sthorpej 	 * Write the max value to the eventfd so that it becomes readable
61275f1bc66Sthorpej 	 * and unblocks the helper waiting in kevent().
61375f1bc66Sthorpej 	 */
61475f1bc66Sthorpej 	efd_value = UINT64_MAX - 1;
61575f1bc66Sthorpej 	ATF_REQUIRE(eventfd_write(ctx.efd, UINT64_MAX - 1) == 0);
61675f1bc66Sthorpej 
61775f1bc66Sthorpej 	/*
61875f1bc66Sthorpej 	 * Ensure the helper woke from the kevent() call.
61975f1bc66Sthorpej 	 */
62075f1bc66Sthorpej 	ATF_REQUIRE(wait_barrier(&ctx));
62175f1bc66Sthorpej 	ATF_REQUIRE(get_state(&ctx) == 0);
62275f1bc66Sthorpej 
62375f1bc66Sthorpej 	/*
62475f1bc66Sthorpej 	 * Wait for the helper to block in kevent(), this time waiting
62575f1bc66Sthorpej 	 * for writability.
62675f1bc66Sthorpej 	 */
62775f1bc66Sthorpej 	set_state(&ctx, 666);
62875f1bc66Sthorpej 	ATF_REQUIRE(wait_barrier(&ctx));
62975f1bc66Sthorpej 	sleep(2);
63075f1bc66Sthorpej 	ATF_REQUIRE(get_state(&ctx) == 666);
63175f1bc66Sthorpej 
63275f1bc66Sthorpej 	/*
63375f1bc66Sthorpej 	 * Now read the value, which will reset the eventfd to 0 and
63475f1bc66Sthorpej 	 * unblock the select() call.
63575f1bc66Sthorpej 	 */
63675f1bc66Sthorpej 	ATF_REQUIRE(eventfd_read(ctx.efd, &efd_value) == 0);
63775f1bc66Sthorpej 	ATF_REQUIRE(efd_value == UINT64_MAX - 1);
63875f1bc66Sthorpej 
63975f1bc66Sthorpej 	/*
64075f1bc66Sthorpej 	 * Ensure that the helper woke from the kevent() call.
64175f1bc66Sthorpej 	 */
64275f1bc66Sthorpej 	ATF_REQUIRE(wait_barrier(&ctx));
64375f1bc66Sthorpej 	ATF_REQUIRE(get_state(&ctx) == 0);
64475f1bc66Sthorpej 
64575f1bc66Sthorpej 	/* Reap the helper. */
64675f1bc66Sthorpej 	ATF_REQUIRE(pthread_join(helper, &join_val) == 0);
64775f1bc66Sthorpej 
64875f1bc66Sthorpej 	(void) close(ctx.efd);
64975f1bc66Sthorpej }
65075f1bc66Sthorpej 
65175f1bc66Sthorpej /*****************************************************************************/
65275f1bc66Sthorpej 
65375f1bc66Sthorpej static void *
eventfd_restart_helper(void * const v)65475f1bc66Sthorpej eventfd_restart_helper(void * const v)
65575f1bc66Sthorpej {
65675f1bc66Sthorpej 	struct helper_context * const ctx = v;
65775f1bc66Sthorpej 	eventfd_t efd_value;
65875f1bc66Sthorpej 
65975f1bc66Sthorpej 	/*
66075f1bc66Sthorpej 	 * Issue a single read to ensure that the descriptor is valid.
66175f1bc66Sthorpej 	 * Thius will not block because it was created with an initial
66275f1bc66Sthorpej 	 * count of 1.
66375f1bc66Sthorpej 	 */
66475f1bc66Sthorpej 	ATF_REQUIRE(eventfd_read(ctx->efd, &efd_value) == 0);
66575f1bc66Sthorpej 	ATF_REQUIRE(efd_value == 1);
66675f1bc66Sthorpej 
66775f1bc66Sthorpej 	ATF_REQUIRE(wait_barrier(ctx));
66875f1bc66Sthorpej 
66975f1bc66Sthorpej 	/*
67075f1bc66Sthorpej 	 * Block in read.  The main thread will close the descriptor,
67175f1bc66Sthorpej 	 * which should unblock us and result in EBADF.
67275f1bc66Sthorpej 	 */
67375f1bc66Sthorpej 	ATF_REQUIRE(get_state(ctx) == 666);
67475f1bc66Sthorpej 	ATF_REQUIRE_ERRNO(EBADF, eventfd_read(ctx->efd, &efd_value) == -1);
67575f1bc66Sthorpej 	set_state(ctx, 0);
67675f1bc66Sthorpej 
67775f1bc66Sthorpej 	ATF_REQUIRE(wait_barrier(ctx));
67875f1bc66Sthorpej 
67975f1bc66Sthorpej 	return NULL;
68075f1bc66Sthorpej }
68175f1bc66Sthorpej 
68275f1bc66Sthorpej ATF_TC(eventfd_restart);
ATF_TC_HEAD(eventfd_restart,tc)68375f1bc66Sthorpej ATF_TC_HEAD(eventfd_restart, tc)
68475f1bc66Sthorpej {
68575f1bc66Sthorpej 	atf_tc_set_md_var(tc, "descr",
68675f1bc66Sthorpej 	    "exercises the 'restart' fileop code path");
68775f1bc66Sthorpej }
ATF_TC_BODY(eventfd_restart,tc)68875f1bc66Sthorpej ATF_TC_BODY(eventfd_restart, tc)
68975f1bc66Sthorpej {
69075f1bc66Sthorpej 	struct helper_context ctx;
69175f1bc66Sthorpej 	pthread_t helper;
69275f1bc66Sthorpej 	void *join_val;
69375f1bc66Sthorpej 
69475f1bc66Sthorpej 	init_helper_context(&ctx);
69575f1bc66Sthorpej 
69675f1bc66Sthorpej 	ATF_REQUIRE((ctx.efd = eventfd(1, 0)) >= 0);
69775f1bc66Sthorpej 
69875f1bc66Sthorpej 	ATF_REQUIRE(pthread_create(&helper, NULL,
69975f1bc66Sthorpej 				   eventfd_restart_helper, &ctx) == 0);
70075f1bc66Sthorpej 
70175f1bc66Sthorpej 	/*
70275f1bc66Sthorpej 	 * Wait for the helper to block in read().  Give it some time
70375f1bc66Sthorpej 	 * so that if the poll returns immediately, we'll notice.
70475f1bc66Sthorpej 	 */
70575f1bc66Sthorpej 	set_state(&ctx, 666);
70675f1bc66Sthorpej 	ATF_REQUIRE(wait_barrier(&ctx));
70775f1bc66Sthorpej 	sleep(2);
70875f1bc66Sthorpej 	ATF_REQUIRE(get_state(&ctx) == 666);
70975f1bc66Sthorpej 
71075f1bc66Sthorpej 	/*
71175f1bc66Sthorpej 	 * Close the descriptor.  This should unblock the reader,
71275f1bc66Sthorpej 	 * and cause it to receive EBADF.
71375f1bc66Sthorpej 	 */
71475f1bc66Sthorpej 	ATF_REQUIRE(close(ctx.efd) == 0);
71575f1bc66Sthorpej 
71675f1bc66Sthorpej 	/*
71775f1bc66Sthorpej 	 * Ensure that the helper woke from the read() call.
71875f1bc66Sthorpej 	 */
71975f1bc66Sthorpej 	ATF_REQUIRE(wait_barrier(&ctx));
72075f1bc66Sthorpej 	ATF_REQUIRE(get_state(&ctx) == 0);
72175f1bc66Sthorpej 
72275f1bc66Sthorpej 	/* Reap the helper. */
72375f1bc66Sthorpej 	ATF_REQUIRE(pthread_join(helper, &join_val) == 0);
72475f1bc66Sthorpej }
72575f1bc66Sthorpej 
72675f1bc66Sthorpej /*****************************************************************************/
72775f1bc66Sthorpej 
72875f1bc66Sthorpej ATF_TC(eventfd_badflags);
ATF_TC_HEAD(eventfd_badflags,tc)72975f1bc66Sthorpej ATF_TC_HEAD(eventfd_badflags, tc)
73075f1bc66Sthorpej {
73175f1bc66Sthorpej 	atf_tc_set_md_var(tc, "descr",
73275f1bc66Sthorpej 	    "validates behavior when eventfd() called with bad flags");
73375f1bc66Sthorpej }
ATF_TC_BODY(eventfd_badflags,tc)73475f1bc66Sthorpej ATF_TC_BODY(eventfd_badflags, tc)
73575f1bc66Sthorpej {
73675f1bc66Sthorpej 	ATF_REQUIRE_ERRNO(EINVAL,
73775f1bc66Sthorpej 	    eventfd(0, ~(EFD_SEMAPHORE | EFD_CLOEXEC | EFD_NONBLOCK)) == -1);
73875f1bc66Sthorpej }
73975f1bc66Sthorpej 
74075f1bc66Sthorpej /*****************************************************************************/
74175f1bc66Sthorpej 
74275f1bc66Sthorpej ATF_TC(eventfd_bufsize);
ATF_TC_HEAD(eventfd_bufsize,tc)74375f1bc66Sthorpej ATF_TC_HEAD(eventfd_bufsize, tc)
74475f1bc66Sthorpej {
74575f1bc66Sthorpej 	atf_tc_set_md_var(tc, "descr",
74675f1bc66Sthorpej 	    "validates expected buffer size behavior");
74775f1bc66Sthorpej }
ATF_TC_BODY(eventfd_bufsize,tc)74875f1bc66Sthorpej ATF_TC_BODY(eventfd_bufsize, tc)
74975f1bc66Sthorpej {
75075f1bc66Sthorpej 	eventfd_t efd_value[2];
75175f1bc66Sthorpej 	int efd;
75275f1bc66Sthorpej 
75375f1bc66Sthorpej 	ATF_REQUIRE((efd = eventfd(1, EFD_NONBLOCK)) >= 0);
75475f1bc66Sthorpej 
75575f1bc66Sthorpej 	ATF_REQUIRE_ERRNO(EINVAL,
75675f1bc66Sthorpej 	    read(efd, efd_value, sizeof(efd_value[0]) - 1) == -1);
75775f1bc66Sthorpej 
75875f1bc66Sthorpej 	efd_value[0] = 0xdeadbeef;
75975f1bc66Sthorpej 	efd_value[1] = 0xdeadbeef;
76075f1bc66Sthorpej 	ATF_REQUIRE(read(efd, efd_value, sizeof(efd_value)) ==
76175f1bc66Sthorpej 	    sizeof(efd_value[0]));
76275f1bc66Sthorpej 	ATF_REQUIRE(efd_value[0] == 1);
76375f1bc66Sthorpej 	ATF_REQUIRE(efd_value[1] == 0xdeadbeef);
76475f1bc66Sthorpej 
76575f1bc66Sthorpej 	ATF_REQUIRE_ERRNO(EINVAL,
76675f1bc66Sthorpej 	    write(efd, efd_value, sizeof(efd_value[0]) - 1) == -1);
76775f1bc66Sthorpej 	ATF_REQUIRE(write(efd, efd_value, sizeof(efd_value)) ==
76875f1bc66Sthorpej 	    sizeof(efd_value[0]));
76975f1bc66Sthorpej 
77075f1bc66Sthorpej 	ATF_REQUIRE(read(efd, efd_value, sizeof(efd_value)) ==
77175f1bc66Sthorpej 	    sizeof(efd_value[0]));
77275f1bc66Sthorpej 	ATF_REQUIRE(efd_value[0] == 1);
77375f1bc66Sthorpej 	ATF_REQUIRE(efd_value[1] == 0xdeadbeef);
77475f1bc66Sthorpej 
77575f1bc66Sthorpej 	(void) close(efd);
77675f1bc66Sthorpej }
77775f1bc66Sthorpej 
77875f1bc66Sthorpej /*****************************************************************************/
77975f1bc66Sthorpej 
780*91de26f0Sthorpej ATF_TC(eventfd_fcntl);
ATF_TC_HEAD(eventfd_fcntl,tc)781*91de26f0Sthorpej ATF_TC_HEAD(eventfd_fcntl, tc)
782*91de26f0Sthorpej {
783*91de26f0Sthorpej 	atf_tc_set_md_var(tc, "descr",
784*91de26f0Sthorpej 	    "validates fcntl behavior");
785*91de26f0Sthorpej }
ATF_TC_BODY(eventfd_fcntl,tc)786*91de26f0Sthorpej ATF_TC_BODY(eventfd_fcntl, tc)
787*91de26f0Sthorpej {
788*91de26f0Sthorpej 	int efd;
789*91de26f0Sthorpej 	int val;
790*91de26f0Sthorpej 
791*91de26f0Sthorpej 	ATF_REQUIRE((efd = eventfd(1, 0)) >= 0);
792*91de26f0Sthorpej 	ATF_REQUIRE((fcntl(efd, F_GETFL) & O_NONBLOCK) == 0);
793*91de26f0Sthorpej 	ATF_REQUIRE(fcntl(efd, F_SETFL, O_NONBLOCK) == 0);
794*91de26f0Sthorpej 	ATF_REQUIRE((fcntl(efd, F_GETFL) & O_NONBLOCK) != 0);
795*91de26f0Sthorpej 	ATF_REQUIRE((fcntl(efd, F_GETFD) & FD_CLOEXEC) == 0);
796*91de26f0Sthorpej 
797*91de26f0Sthorpej 	ATF_REQUIRE(ioctl(efd, FIONREAD, &val) == 0);
798*91de26f0Sthorpej 	ATF_REQUIRE(val == sizeof(eventfd_t));
799*91de26f0Sthorpej 
800*91de26f0Sthorpej 	ATF_REQUIRE(ioctl(efd, FIONWRITE, &val) == 0);
801*91de26f0Sthorpej 	ATF_REQUIRE(val == 0);
802*91de26f0Sthorpej 
803*91de26f0Sthorpej 	ATF_REQUIRE_ERRNO(ENOTTY, ioctl(efd, FIONSPACE, &val) == -1);
804*91de26f0Sthorpej 	(void)close(efd);
805*91de26f0Sthorpej 
806*91de26f0Sthorpej 	ATF_REQUIRE((efd = eventfd(1, EFD_NONBLOCK | EFD_CLOEXEC)) >= 0);
807*91de26f0Sthorpej 	ATF_REQUIRE((fcntl(efd, F_GETFL) & ~O_ACCMODE) == O_NONBLOCK);
808*91de26f0Sthorpej 	ATF_REQUIRE((fcntl(efd, F_GETFD) & FD_CLOEXEC) != 0);
809*91de26f0Sthorpej 	ATF_REQUIRE(fcntl(efd, F_SETFD, 0) == 0);
810*91de26f0Sthorpej 	ATF_REQUIRE((fcntl(efd, F_GETFD) & FD_CLOEXEC) == 0);
811*91de26f0Sthorpej 	ATF_REQUIRE(fcntl(efd, F_SETFD, FD_CLOEXEC) == 0);
812*91de26f0Sthorpej 	ATF_REQUIRE((fcntl(efd, F_GETFD) & FD_CLOEXEC) != 0);
813*91de26f0Sthorpej 	(void)close(efd);
814*91de26f0Sthorpej }
815*91de26f0Sthorpej 
816*91de26f0Sthorpej /*****************************************************************************/
817*91de26f0Sthorpej 
ATF_TP_ADD_TCS(tp)81875f1bc66Sthorpej ATF_TP_ADD_TCS(tp)
81975f1bc66Sthorpej {
82075f1bc66Sthorpej 	ATF_TP_ADD_TC(tp, eventfd_normal);
82175f1bc66Sthorpej 	ATF_TP_ADD_TC(tp, eventfd_semaphore);
82275f1bc66Sthorpej 	ATF_TP_ADD_TC(tp, eventfd_badflags);
82375f1bc66Sthorpej 	ATF_TP_ADD_TC(tp, eventfd_bufsize);
82475f1bc66Sthorpej 	ATF_TP_ADD_TC(tp, eventfd_select_poll_kevent_immed);
82575f1bc66Sthorpej 	ATF_TP_ADD_TC(tp, eventfd_select_poll_kevent_block);
82675f1bc66Sthorpej 	ATF_TP_ADD_TC(tp, eventfd_restart);
827*91de26f0Sthorpej 	ATF_TP_ADD_TC(tp, eventfd_fcntl);
82875f1bc66Sthorpej 
82975f1bc66Sthorpej 	return atf_no_error();
83075f1bc66Sthorpej }
831