xref: /netbsd-src/tests/kernel/kqueue/t_scan.c (revision bea606508351baaf2bb25c7d4218b50cf2b53995)
1*bea60650Swiz /* $NetBSD: t_scan.c,v 1.2 2021/10/10 19:17:31 wiz Exp $ */
2a8831e8fSthorpej 
3a8831e8fSthorpej /*-
4a8831e8fSthorpej  * Copyright (c) 2021 The NetBSD Foundation, Inc.
5a8831e8fSthorpej  * All rights reserved.
6a8831e8fSthorpej  *
7a8831e8fSthorpej  * Redistribution and use in source and binary forms, with or without
8a8831e8fSthorpej  * modification, are permitted provided that the following conditions
9a8831e8fSthorpej  * are met:
10a8831e8fSthorpej  * 1. Redistributions of source code must retain the above copyright
11a8831e8fSthorpej  *    notice, this list of conditions and the following disclaimer.
12a8831e8fSthorpej  * 2. Redistributions in binary form must reproduce the above copyright
13a8831e8fSthorpej  *    notice, this list of conditions and the following disclaimer in the
14a8831e8fSthorpej  *    documentation and/or other materials provided with the distribution.
15a8831e8fSthorpej  *
16a8831e8fSthorpej  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17a8831e8fSthorpej  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18a8831e8fSthorpej  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19a8831e8fSthorpej  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20a8831e8fSthorpej  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21a8831e8fSthorpej  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22a8831e8fSthorpej  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23a8831e8fSthorpej  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24a8831e8fSthorpej  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25a8831e8fSthorpej  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26a8831e8fSthorpej  * POSSIBILITY OF SUCH DAMAGE.
27a8831e8fSthorpej  */
28a8831e8fSthorpej 
29a8831e8fSthorpej #include <sys/cdefs.h>
30*bea60650Swiz __RCSID("$NetBSD: t_scan.c,v 1.2 2021/10/10 19:17:31 wiz Exp $");
31a8831e8fSthorpej 
32a8831e8fSthorpej #include <sys/event.h>
33a8831e8fSthorpej #include <sys/time.h>
34a8831e8fSthorpej #include <sys/types.h>
35a8831e8fSthorpej 
36a8831e8fSthorpej #include <err.h>
37a8831e8fSthorpej #include <pthread.h>
38a8831e8fSthorpej #include <stdio.h>
39a8831e8fSthorpej #include <stdlib.h>
40a8831e8fSthorpej #include <unistd.h>
41a8831e8fSthorpej 
42a8831e8fSthorpej #include <atf-c.h>
43a8831e8fSthorpej 
44a8831e8fSthorpej /*
45a8831e8fSthorpej  * Each kevent thread will make this many kevent() calls, and if it
46a8831e8fSthorpej  * achieves this mark, we assume the race condition has not occurred
47*bea60650Swiz  * the declare the test passes.
48a8831e8fSthorpej  */
49a8831e8fSthorpej #define	NKEVENT_CALLS		10000
50a8831e8fSthorpej 
51a8831e8fSthorpej static int kq;
52a8831e8fSthorpej 
53a8831e8fSthorpej static void *
kevent_thread(void * arg)54a8831e8fSthorpej kevent_thread(void *arg)
55a8831e8fSthorpej {
56a8831e8fSthorpej 	struct timespec ts = { 0, 0 };
57a8831e8fSthorpej 	struct kevent event;
58a8831e8fSthorpej 	int rv, i;
59a8831e8fSthorpej 
60a8831e8fSthorpej 	for (i = 0; i < NKEVENT_CALLS; i++) {
61a8831e8fSthorpej 		rv = kevent(kq, NULL, 0, &event, 1, &ts);
62a8831e8fSthorpej 		if (rv < 0) {
63a8831e8fSthorpej 			i = rv;
64a8831e8fSthorpej 			break;
65a8831e8fSthorpej 		}
66a8831e8fSthorpej 		if (rv != 1) {
67a8831e8fSthorpej 			break;
68a8831e8fSthorpej 		}
69a8831e8fSthorpej 	}
70a8831e8fSthorpej 
71a8831e8fSthorpej 	return (void *)(intptr_t)i;
72a8831e8fSthorpej }
73a8831e8fSthorpej 
74a8831e8fSthorpej ATF_TC(scan1);
ATF_TC_HEAD(scan1,tc)75a8831e8fSthorpej ATF_TC_HEAD(scan1, tc)
76a8831e8fSthorpej {
77a8831e8fSthorpej 	atf_tc_set_md_var(tc, "descr",
78a8831e8fSthorpej 	    "Exercises multi-threaded kevent() calls (PR kern/50094)");
79a8831e8fSthorpej }
80a8831e8fSthorpej 
ATF_TC_BODY(scan1,tc)81a8831e8fSthorpej ATF_TC_BODY(scan1, tc)
82a8831e8fSthorpej {
83a8831e8fSthorpej 	pthread_t t1, t2;
84a8831e8fSthorpej 	void *v1, *v2;
85a8831e8fSthorpej 	intptr_t r1, r2;
86a8831e8fSthorpej 	struct kevent event;
87a8831e8fSthorpej 	int p[2];
88a8831e8fSthorpej 
89a8831e8fSthorpej 	ATF_REQUIRE(pipe(p) == 0);
90a8831e8fSthorpej 	ATF_REQUIRE((kq = kqueue()) >= 0);
91a8831e8fSthorpej 
92a8831e8fSthorpej 	EV_SET(&event, p[0], EVFILT_READ, EV_ADD, 0, 0, 0);
93a8831e8fSthorpej 	ATF_REQUIRE(kevent(kq, &event, 1, NULL, 0, NULL) == 0);
94a8831e8fSthorpej 	ATF_REQUIRE(write(p[1], p, 1) == 1);
95a8831e8fSthorpej 
96a8831e8fSthorpej 	ATF_REQUIRE(pthread_create(&t1, NULL, kevent_thread, NULL) == 0);
97a8831e8fSthorpej 	ATF_REQUIRE(pthread_create(&t2, NULL, kevent_thread, NULL) == 0);
98a8831e8fSthorpej 
99a8831e8fSthorpej 	ATF_REQUIRE(pthread_join(t1, &v1) == 0);
100a8831e8fSthorpej 	r1 = (intptr_t)v1;
101a8831e8fSthorpej 
102a8831e8fSthorpej 	ATF_REQUIRE(pthread_join(t2, &v2) == 0);
103a8831e8fSthorpej 	r2 = (intptr_t)v2;
104a8831e8fSthorpej 
105a8831e8fSthorpej 	ATF_REQUIRE(r1 >= 0);
106a8831e8fSthorpej 	ATF_REQUIRE(r2 >= 0);
107a8831e8fSthorpej 
108a8831e8fSthorpej 	ATF_REQUIRE(r1 == NKEVENT_CALLS);
109a8831e8fSthorpej 	ATF_REQUIRE(r2 == NKEVENT_CALLS);
110a8831e8fSthorpej }
111a8831e8fSthorpej 
ATF_TP_ADD_TCS(tp)112a8831e8fSthorpej ATF_TP_ADD_TCS(tp)
113a8831e8fSthorpej {
114a8831e8fSthorpej 	ATF_TP_ADD_TC(tp, scan1);
115a8831e8fSthorpej 
116a8831e8fSthorpej 	return atf_no_error();
117a8831e8fSthorpej }
118