xref: /freebsd-src/contrib/netbsd-tests/lib/libpthread/t_mutex.c (revision 371f152c7ff76b99acbdf0decf5aa5ca1cc45bd6)
13b0a9131SEnji Cooper /* $NetBSD: t_mutex.c,v 1.15 2017/01/16 16:23:41 christos Exp $ */
257718be8SEnji Cooper 
357718be8SEnji Cooper /*
457718be8SEnji Cooper  * Copyright (c) 2008 The NetBSD Foundation, Inc.
557718be8SEnji Cooper  * All rights reserved.
657718be8SEnji Cooper  *
757718be8SEnji Cooper  * Redistribution and use in source and binary forms, with or without
857718be8SEnji Cooper  * modification, are permitted provided that the following conditions
957718be8SEnji Cooper  * are met:
1057718be8SEnji Cooper  * 1. Redistributions of source code must retain the above copyright
1157718be8SEnji Cooper  *    notice, this list of conditions and the following disclaimer.
1257718be8SEnji Cooper  * 2. Redistributions in binary form must reproduce the above copyright
1357718be8SEnji Cooper  *    notice, this list of conditions and the following disclaimer in the
1457718be8SEnji Cooper  *    documentation and/or other materials provided with the distribution.
1557718be8SEnji Cooper  *
1657718be8SEnji Cooper  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
1757718be8SEnji Cooper  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
1857718be8SEnji Cooper  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1957718be8SEnji Cooper  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2057718be8SEnji Cooper  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2157718be8SEnji Cooper  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2257718be8SEnji Cooper  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2357718be8SEnji Cooper  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2457718be8SEnji Cooper  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2557718be8SEnji Cooper  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2657718be8SEnji Cooper  * POSSIBILITY OF SUCH DAMAGE.
2757718be8SEnji Cooper  */
2857718be8SEnji Cooper 
2957718be8SEnji Cooper #include <sys/cdefs.h>
3057718be8SEnji Cooper __COPYRIGHT("@(#) Copyright (c) 2008\
3157718be8SEnji Cooper  The NetBSD Foundation, inc. All rights reserved.");
323b0a9131SEnji Cooper __RCSID("$NetBSD: t_mutex.c,v 1.15 2017/01/16 16:23:41 christos Exp $");
3357718be8SEnji Cooper 
34cdebaff8SEnji Cooper #include <sys/time.h> /* For timespecadd */
35cdebaff8SEnji Cooper #include <inttypes.h> /* For UINT16_MAX */
3657718be8SEnji Cooper #include <pthread.h>
3757718be8SEnji Cooper #include <stdio.h>
38*371f152cSAlex Richardson #ifdef __FreeBSD__
39*371f152cSAlex Richardson #include <stdlib.h>
40*371f152cSAlex Richardson #endif
4157718be8SEnji Cooper #include <string.h>
42640235e2SEnji Cooper #include <errno.h>
43cdebaff8SEnji Cooper #include <time.h>
4457718be8SEnji Cooper #include <unistd.h>
45640235e2SEnji Cooper #include <sys/sched.h>
46640235e2SEnji Cooper #include <sys/param.h>
4757718be8SEnji Cooper 
4857718be8SEnji Cooper #include <atf-c.h>
4957718be8SEnji Cooper 
5057718be8SEnji Cooper #include "h_common.h"
5157718be8SEnji Cooper 
5257718be8SEnji Cooper static pthread_mutex_t mutex;
5357718be8SEnji Cooper static pthread_mutex_t static_mutex = PTHREAD_MUTEX_INITIALIZER;
5457718be8SEnji Cooper static int global_x;
5557718be8SEnji Cooper 
56cdebaff8SEnji Cooper #ifdef TIMEDMUTEX
57cdebaff8SEnji Cooper /* This code is used for verifying non-timed specific code */
58cdebaff8SEnji Cooper static struct timespec ts_lengthy = {
59cdebaff8SEnji Cooper 	.tv_sec = UINT16_MAX,
60cdebaff8SEnji Cooper 	.tv_nsec = 0
61cdebaff8SEnji Cooper };
62cdebaff8SEnji Cooper /* This code is used for verifying timed-only specific code */
63cdebaff8SEnji Cooper static struct timespec ts_shortlived = {
64cdebaff8SEnji Cooper 	.tv_sec = 0,
65cdebaff8SEnji Cooper 	.tv_nsec = 120
66cdebaff8SEnji Cooper };
67cdebaff8SEnji Cooper 
68cdebaff8SEnji Cooper static int
mutex_lock(pthread_mutex_t * m,const struct timespec * ts)69cdebaff8SEnji Cooper mutex_lock(pthread_mutex_t *m, const struct timespec *ts)
70cdebaff8SEnji Cooper {
71cdebaff8SEnji Cooper 	struct timespec ts_wait;
72cdebaff8SEnji Cooper 	ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &ts_wait) != -1);
73cdebaff8SEnji Cooper 	timespecadd(&ts_wait, ts, &ts_wait);
74cdebaff8SEnji Cooper 
75cdebaff8SEnji Cooper 	return pthread_mutex_timedlock(m, &ts_wait);
76cdebaff8SEnji Cooper }
77cdebaff8SEnji Cooper #else
78cdebaff8SEnji Cooper #define mutex_lock(a, b) pthread_mutex_lock(a)
79cdebaff8SEnji Cooper #endif
80cdebaff8SEnji Cooper 
8157718be8SEnji Cooper static void *
mutex1_threadfunc(void * arg)8257718be8SEnji Cooper mutex1_threadfunc(void *arg)
8357718be8SEnji Cooper {
8457718be8SEnji Cooper 	int *param;
8557718be8SEnji Cooper 
8657718be8SEnji Cooper 	printf("2: Second thread.\n");
8757718be8SEnji Cooper 
8857718be8SEnji Cooper 	param = arg;
8957718be8SEnji Cooper 	printf("2: Locking mutex\n");
90cdebaff8SEnji Cooper 	mutex_lock(&mutex, &ts_lengthy);
9157718be8SEnji Cooper 	printf("2: Got mutex. *param = %d\n", *param);
9257718be8SEnji Cooper 	ATF_REQUIRE_EQ(*param, 20);
9357718be8SEnji Cooper 	(*param)++;
9457718be8SEnji Cooper 
9557718be8SEnji Cooper 	pthread_mutex_unlock(&mutex);
9657718be8SEnji Cooper 
9757718be8SEnji Cooper 	return param;
9857718be8SEnji Cooper }
9957718be8SEnji Cooper 
10057718be8SEnji Cooper ATF_TC(mutex1);
ATF_TC_HEAD(mutex1,tc)10157718be8SEnji Cooper ATF_TC_HEAD(mutex1, tc)
10257718be8SEnji Cooper {
10357718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks mutexes");
10457718be8SEnji Cooper }
ATF_TC_BODY(mutex1,tc)10557718be8SEnji Cooper ATF_TC_BODY(mutex1, tc)
10657718be8SEnji Cooper {
10757718be8SEnji Cooper 	int x;
10857718be8SEnji Cooper 	pthread_t new;
10957718be8SEnji Cooper 	void *joinval;
11057718be8SEnji Cooper 
11157718be8SEnji Cooper 	printf("1: Mutex-test 1\n");
11257718be8SEnji Cooper 
11357718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
11457718be8SEnji Cooper 	x = 1;
115cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
11657718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex1_threadfunc, &x));
11757718be8SEnji Cooper 	printf("1: Before changing the value.\n");
11857718be8SEnji Cooper 	sleep(2);
11957718be8SEnji Cooper 	x = 20;
12057718be8SEnji Cooper 	printf("1: Before releasing the mutex.\n");
12157718be8SEnji Cooper 	sleep(2);
12257718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
12357718be8SEnji Cooper 	printf("1: After releasing the mutex.\n");
12457718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_join(new, &joinval));
12557718be8SEnji Cooper 
126cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
12757718be8SEnji Cooper 	printf("1: Thread joined. X was %d. Return value (int) was %d\n",
12857718be8SEnji Cooper 		x, *(int *)joinval);
12957718be8SEnji Cooper 	ATF_REQUIRE_EQ(x, 21);
13057718be8SEnji Cooper 	ATF_REQUIRE_EQ(*(int *)joinval, 21);
13157718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
13257718be8SEnji Cooper }
13357718be8SEnji Cooper 
134*371f152cSAlex Richardson #ifdef __FreeBSD__
135*371f152cSAlex Richardson /*
136*371f152cSAlex Richardson  * Increment the value using a noinline function that includes a small delay
137*371f152cSAlex Richardson  * to increase the window for the RMW data race.
138*371f152cSAlex Richardson  */
139*371f152cSAlex Richardson __noinline static int
increment(int value)140*371f152cSAlex Richardson increment(int value)
141*371f152cSAlex Richardson {
142*371f152cSAlex Richardson 	for (volatile int i = 0; i < 100; i++) {
143*371f152cSAlex Richardson 		/* Small delay between read+write to increase chance of race */
144*371f152cSAlex Richardson 		__compiler_membar();
145*371f152cSAlex Richardson 	}
146*371f152cSAlex Richardson 	return value + 1;
147*371f152cSAlex Richardson }
148*371f152cSAlex Richardson 
149*371f152cSAlex Richardson static volatile bool thread2_started = false;
150*371f152cSAlex Richardson #endif
151*371f152cSAlex Richardson 
15257718be8SEnji Cooper static void *
mutex2_threadfunc(void * arg)15357718be8SEnji Cooper mutex2_threadfunc(void *arg)
15457718be8SEnji Cooper {
15557718be8SEnji Cooper 	long count = *(int *)arg;
15657718be8SEnji Cooper 
157*371f152cSAlex Richardson #ifdef __FreeBSD__
158*371f152cSAlex Richardson 	thread2_started = true;
159*371f152cSAlex Richardson #endif
16057718be8SEnji Cooper 	printf("2: Second thread (%p). Count is %ld\n", pthread_self(), count);
16157718be8SEnji Cooper 
16257718be8SEnji Cooper 	while (count--) {
163cdebaff8SEnji Cooper 		PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
164*371f152cSAlex Richardson #ifdef __FreeBSD__
165*371f152cSAlex Richardson 		global_x = increment(global_x);
166*371f152cSAlex Richardson #else
16757718be8SEnji Cooper 		global_x++;
168*371f152cSAlex Richardson #endif
16957718be8SEnji Cooper 		PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
17057718be8SEnji Cooper 	}
17157718be8SEnji Cooper 
17257718be8SEnji Cooper 	return (void *)count;
17357718be8SEnji Cooper }
17457718be8SEnji Cooper 
17557718be8SEnji Cooper ATF_TC(mutex2);
ATF_TC_HEAD(mutex2,tc)17657718be8SEnji Cooper ATF_TC_HEAD(mutex2, tc)
17757718be8SEnji Cooper {
17857718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks mutexes");
179190e1b1cSEnji Cooper #ifdef __NetBSD__
18057718be8SEnji Cooper #if defined(__powerpc__)
18157718be8SEnji Cooper 	atf_tc_set_md_var(tc, "timeout", "40");
18257718be8SEnji Cooper #endif
183190e1b1cSEnji Cooper #endif
18457718be8SEnji Cooper }
ATF_TC_BODY(mutex2,tc)18557718be8SEnji Cooper ATF_TC_BODY(mutex2, tc)
18657718be8SEnji Cooper {
18757718be8SEnji Cooper 	int count, count2;
188*371f152cSAlex Richardson #ifdef __FreeBSD__
189*371f152cSAlex Richardson 	int num_increments;
190*371f152cSAlex Richardson #endif
19157718be8SEnji Cooper 	pthread_t new;
19257718be8SEnji Cooper 	void *joinval;
19357718be8SEnji Cooper 
19457718be8SEnji Cooper 	printf("1: Mutex-test 2\n");
19557718be8SEnji Cooper 
196190e1b1cSEnji Cooper #ifdef __NetBSD__
19757718be8SEnji Cooper #if defined(__powerpc__)
19857718be8SEnji Cooper 	atf_tc_expect_timeout("PR port-powerpc/44387");
19957718be8SEnji Cooper #endif
200190e1b1cSEnji Cooper #endif
20157718be8SEnji Cooper 
20257718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
20357718be8SEnji Cooper 
20457718be8SEnji Cooper 	global_x = 0;
205*371f152cSAlex Richardson #ifdef __FreeBSD__
206*371f152cSAlex Richardson 	num_increments = count = count2 = 1000;
207*371f152cSAlex Richardson 	if (getenv("NUM_ITERATIONS") != NULL) {
208*371f152cSAlex Richardson 		num_increments = count = count2 =
209*371f152cSAlex Richardson 		    MIN(INT_MAX, strtoul(getenv("NUM_ITERATIONS"), NULL, 10));
210*371f152cSAlex Richardson 	}
211*371f152cSAlex Richardson 	printf("Will use %d iterations\n", num_increments);
212*371f152cSAlex Richardson #else
21357718be8SEnji Cooper 	count = count2 = 10000000;
214*371f152cSAlex Richardson #endif
21557718be8SEnji Cooper 
216cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
217*371f152cSAlex Richardson #ifdef __FreeBSD__
218*371f152cSAlex Richardson 	thread2_started = false;
219*371f152cSAlex Richardson #endif
22057718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex2_threadfunc, &count2));
22157718be8SEnji Cooper 
22257718be8SEnji Cooper 	printf("1: Thread %p\n", pthread_self());
223*371f152cSAlex Richardson #ifdef __FreeBSD__
224*371f152cSAlex Richardson 	while (!thread2_started) {
225*371f152cSAlex Richardson 		/* Wait for thread 2 to start to increase chance of race */
226*371f152cSAlex Richardson 	}
227*371f152cSAlex Richardson 	printf("1: Unlocking to start increment loop %p\n", pthread_self());
228*371f152cSAlex Richardson #endif
22957718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
23057718be8SEnji Cooper 
23157718be8SEnji Cooper 	while (count--) {
232cdebaff8SEnji Cooper 		PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
233*371f152cSAlex Richardson #ifdef __FreeBSD__
234*371f152cSAlex Richardson 		global_x = increment(global_x);
235*371f152cSAlex Richardson #else
23657718be8SEnji Cooper 		global_x++;
237*371f152cSAlex Richardson #endif
23857718be8SEnji Cooper 		PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
23957718be8SEnji Cooper 	}
24057718be8SEnji Cooper 
24157718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_join(new, &joinval));
24257718be8SEnji Cooper 
243cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
24457718be8SEnji Cooper 	printf("1: Thread joined. X was %d. Return value (long) was %ld\n",
24557718be8SEnji Cooper 		global_x, (long)joinval);
246*371f152cSAlex Richardson #ifdef __FreeBSD__
247*371f152cSAlex Richardson 	ATF_REQUIRE_EQ_MSG(count, -1, "%d", count);
248*371f152cSAlex Richardson 	ATF_REQUIRE_EQ_MSG((long)joinval, -1, "%ld", (long)joinval);
249*371f152cSAlex Richardson 	ATF_REQUIRE_EQ_MSG(global_x, num_increments * 2, "%d vs %d", global_x,
250*371f152cSAlex Richardson 	    num_increments * 2);
251*371f152cSAlex Richardson #else
25257718be8SEnji Cooper 	ATF_REQUIRE_EQ(global_x, 20000000);
253*371f152cSAlex Richardson #endif
25457718be8SEnji Cooper 
255190e1b1cSEnji Cooper #ifdef __NetBSD__
25657718be8SEnji Cooper #if defined(__powerpc__)
25757718be8SEnji Cooper 	/* XXX force a timeout in ppc case since an un-triggered race
25857718be8SEnji Cooper 	   otherwise looks like a "failure" */
25957718be8SEnji Cooper 	/* We sleep for longer than the timeout to make ATF not
26057718be8SEnji Cooper 	   complain about unexpected success */
26157718be8SEnji Cooper 	sleep(41);
26257718be8SEnji Cooper #endif
263190e1b1cSEnji Cooper #endif
26457718be8SEnji Cooper }
26557718be8SEnji Cooper 
266*371f152cSAlex Richardson #ifdef __FreeBSD__
267*371f152cSAlex Richardson static volatile bool thread3_started = false;
268*371f152cSAlex Richardson #endif
269*371f152cSAlex Richardson 
27057718be8SEnji Cooper static void *
mutex3_threadfunc(void * arg)27157718be8SEnji Cooper mutex3_threadfunc(void *arg)
27257718be8SEnji Cooper {
27357718be8SEnji Cooper 	long count = *(int *)arg;
27457718be8SEnji Cooper 
275*371f152cSAlex Richardson #ifdef __FreeBSD__
276*371f152cSAlex Richardson 	thread3_started = true;
277*371f152cSAlex Richardson #endif
27857718be8SEnji Cooper 	printf("2: Second thread (%p). Count is %ld\n", pthread_self(), count);
27957718be8SEnji Cooper 
28057718be8SEnji Cooper 	while (count--) {
281cdebaff8SEnji Cooper 		PTHREAD_REQUIRE(mutex_lock(&static_mutex, &ts_lengthy));
282*371f152cSAlex Richardson #ifdef __FreeBSD__
283*371f152cSAlex Richardson 		global_x = increment(global_x);
284*371f152cSAlex Richardson #else
28557718be8SEnji Cooper 		global_x++;
286*371f152cSAlex Richardson #endif
28757718be8SEnji Cooper 		PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
28857718be8SEnji Cooper 	}
28957718be8SEnji Cooper 
29057718be8SEnji Cooper 	return (void *)count;
29157718be8SEnji Cooper }
29257718be8SEnji Cooper 
29357718be8SEnji Cooper ATF_TC(mutex3);
ATF_TC_HEAD(mutex3,tc)29457718be8SEnji Cooper ATF_TC_HEAD(mutex3, tc)
29557718be8SEnji Cooper {
29657718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks mutexes using a static "
29757718be8SEnji Cooper 	    "initializer");
298190e1b1cSEnji Cooper #ifdef __NetBSD__
29957718be8SEnji Cooper #if defined(__powerpc__)
30057718be8SEnji Cooper 	atf_tc_set_md_var(tc, "timeout", "40");
30157718be8SEnji Cooper #endif
302190e1b1cSEnji Cooper #endif
30357718be8SEnji Cooper }
ATF_TC_BODY(mutex3,tc)30457718be8SEnji Cooper ATF_TC_BODY(mutex3, tc)
30557718be8SEnji Cooper {
30657718be8SEnji Cooper 	int count, count2;
307*371f152cSAlex Richardson #ifdef __FreeBSD__
308*371f152cSAlex Richardson 	int num_increments;
309*371f152cSAlex Richardson #endif
31057718be8SEnji Cooper 	pthread_t new;
31157718be8SEnji Cooper 	void *joinval;
31257718be8SEnji Cooper 
31357718be8SEnji Cooper 	printf("1: Mutex-test 3\n");
31457718be8SEnji Cooper 
315190e1b1cSEnji Cooper #ifdef __NetBSD__
31657718be8SEnji Cooper #if defined(__powerpc__)
31757718be8SEnji Cooper 	atf_tc_expect_timeout("PR port-powerpc/44387");
31857718be8SEnji Cooper #endif
319190e1b1cSEnji Cooper #endif
32057718be8SEnji Cooper 
32157718be8SEnji Cooper 	global_x = 0;
322*371f152cSAlex Richardson #ifdef __FreeBSD__
323*371f152cSAlex Richardson 	num_increments = count = count2 = 1000;
324*371f152cSAlex Richardson 	if (getenv("NUM_ITERATIONS") != NULL) {
325*371f152cSAlex Richardson 		num_increments = count = count2 =
326*371f152cSAlex Richardson 		    MIN(INT_MAX, strtoul(getenv("NUM_ITERATIONS"), NULL, 10));
327*371f152cSAlex Richardson 	}
328*371f152cSAlex Richardson 	printf("Will use %d iterations\n", num_increments);
329*371f152cSAlex Richardson #else
33057718be8SEnji Cooper 	count = count2 = 10000000;
331*371f152cSAlex Richardson #endif
33257718be8SEnji Cooper 
333cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&static_mutex, &ts_lengthy));
33457718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex3_threadfunc, &count2));
33557718be8SEnji Cooper 
33657718be8SEnji Cooper 	printf("1: Thread %p\n", pthread_self());
337*371f152cSAlex Richardson #ifdef __FreeBSD__
338*371f152cSAlex Richardson 	while (!thread3_started) {
339*371f152cSAlex Richardson 		/* Wait for thread 3 to start to increase chance of race */
340*371f152cSAlex Richardson 	}
341*371f152cSAlex Richardson 	printf("1: Unlocking to start increment loop %p\n", pthread_self());
342*371f152cSAlex Richardson #endif
34357718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
34457718be8SEnji Cooper 
34557718be8SEnji Cooper 	while (count--) {
346cdebaff8SEnji Cooper 		PTHREAD_REQUIRE(mutex_lock(&static_mutex, &ts_lengthy));
347*371f152cSAlex Richardson #ifdef __FreeBSD__
348*371f152cSAlex Richardson 		global_x = increment(global_x);
349*371f152cSAlex Richardson #else
35057718be8SEnji Cooper 		global_x++;
351*371f152cSAlex Richardson #endif
35257718be8SEnji Cooper 		PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
35357718be8SEnji Cooper 	}
35457718be8SEnji Cooper 
35557718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_join(new, &joinval));
35657718be8SEnji Cooper 
357cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&static_mutex, &ts_lengthy));
35857718be8SEnji Cooper 	printf("1: Thread joined. X was %d. Return value (long) was %ld\n",
35957718be8SEnji Cooper 		global_x, (long)joinval);
360*371f152cSAlex Richardson #ifdef __FreeBSD__
361*371f152cSAlex Richardson 	ATF_REQUIRE_EQ_MSG(count, -1, "%d", count);
362*371f152cSAlex Richardson 	ATF_REQUIRE_EQ_MSG((long)joinval, -1, "%ld", (long)joinval);
363*371f152cSAlex Richardson 	ATF_REQUIRE_EQ_MSG(global_x, num_increments * 2, "%d vs %d", global_x,
364*371f152cSAlex Richardson 	    num_increments * 2);
365*371f152cSAlex Richardson #else
36657718be8SEnji Cooper 	ATF_REQUIRE_EQ(global_x, 20000000);
367*371f152cSAlex Richardson #endif
368190e1b1cSEnji Cooper #ifdef __NetBSD__
36957718be8SEnji Cooper #if defined(__powerpc__)
37057718be8SEnji Cooper 	/* XXX force a timeout in ppc case since an un-triggered race
37157718be8SEnji Cooper 	   otherwise looks like a "failure" */
37257718be8SEnji Cooper 	/* We sleep for longer than the timeout to make ATF not
37357718be8SEnji Cooper 	   complain about unexpected success */
37457718be8SEnji Cooper 	sleep(41);
37557718be8SEnji Cooper #endif
376190e1b1cSEnji Cooper #endif
37757718be8SEnji Cooper }
37857718be8SEnji Cooper 
37957718be8SEnji Cooper static void *
mutex4_threadfunc(void * arg)38057718be8SEnji Cooper mutex4_threadfunc(void *arg)
38157718be8SEnji Cooper {
38257718be8SEnji Cooper 	int *param;
38357718be8SEnji Cooper 
38457718be8SEnji Cooper 	printf("2: Second thread.\n");
38557718be8SEnji Cooper 
38657718be8SEnji Cooper 	param = arg;
38757718be8SEnji Cooper 	printf("2: Locking mutex\n");
388cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
38957718be8SEnji Cooper 	printf("2: Got mutex. *param = %d\n", *param);
39057718be8SEnji Cooper 	(*param)++;
39157718be8SEnji Cooper 
39257718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
39357718be8SEnji Cooper 
39457718be8SEnji Cooper 	return param;
39557718be8SEnji Cooper }
39657718be8SEnji Cooper 
39757718be8SEnji Cooper ATF_TC(mutex4);
ATF_TC_HEAD(mutex4,tc)39857718be8SEnji Cooper ATF_TC_HEAD(mutex4, tc)
39957718be8SEnji Cooper {
40057718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks mutexes");
40157718be8SEnji Cooper }
ATF_TC_BODY(mutex4,tc)40257718be8SEnji Cooper ATF_TC_BODY(mutex4, tc)
40357718be8SEnji Cooper {
40457718be8SEnji Cooper 	int x;
40557718be8SEnji Cooper 	pthread_t new;
40657718be8SEnji Cooper 	pthread_mutexattr_t mattr;
40757718be8SEnji Cooper 	void *joinval;
40857718be8SEnji Cooper 
40957718be8SEnji Cooper 	printf("1: Mutex-test 4\n");
41057718be8SEnji Cooper 
41157718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_init(&mattr));
41257718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE));
41357718be8SEnji Cooper 
41457718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, &mattr));
41557718be8SEnji Cooper 
41657718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_destroy(&mattr));
41757718be8SEnji Cooper 
41857718be8SEnji Cooper 	x = 1;
419cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
42057718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex4_threadfunc, &x));
42157718be8SEnji Cooper 
42257718be8SEnji Cooper 	printf("1: Before recursively acquiring the mutex.\n");
423cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
42457718be8SEnji Cooper 
42557718be8SEnji Cooper 	printf("1: Before releasing the mutex once.\n");
42657718be8SEnji Cooper 	sleep(2);
42757718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
42857718be8SEnji Cooper 	printf("1: After releasing the mutex once.\n");
42957718be8SEnji Cooper 
43057718be8SEnji Cooper 	x = 20;
43157718be8SEnji Cooper 
43257718be8SEnji Cooper 	printf("1: Before releasing the mutex twice.\n");
43357718be8SEnji Cooper 	sleep(2);
43457718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
43557718be8SEnji Cooper 	printf("1: After releasing the mutex twice.\n");
43657718be8SEnji Cooper 
43757718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_join(new, &joinval));
43857718be8SEnji Cooper 
439cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
44057718be8SEnji Cooper 	printf("1: Thread joined. X was %d. Return value (int) was %d\n",
44157718be8SEnji Cooper 		x, *(int *)joinval);
44257718be8SEnji Cooper 	ATF_REQUIRE_EQ(x, 21);
44357718be8SEnji Cooper 	ATF_REQUIRE_EQ(*(int *)joinval, 21);
44457718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
44557718be8SEnji Cooper }
44657718be8SEnji Cooper 
447640235e2SEnji Cooper #ifdef __NetBSD__
448640235e2SEnji Cooper static pthread_mutexattr_t attr5;
449640235e2SEnji Cooper static pthread_mutex_t mutex5;
450640235e2SEnji Cooper static int min_fifo_prio, max_fifo_prio;
451640235e2SEnji Cooper 
452640235e2SEnji Cooper static void *
child_func(void * arg)453640235e2SEnji Cooper child_func(void* arg)
454640235e2SEnji Cooper {
455640235e2SEnji Cooper 	int res;
456640235e2SEnji Cooper 
457640235e2SEnji Cooper 	printf("child is waiting\n");
458640235e2SEnji Cooper 	res = _sched_protect(-2);
459640235e2SEnji Cooper 	ATF_REQUIRE_EQ_MSG(res, -1, "sched_protect returned %d", res);
460640235e2SEnji Cooper 	ATF_REQUIRE_EQ(errno, ENOENT);
461cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex5, &ts_lengthy));
462640235e2SEnji Cooper 	printf("child is owning resource\n");
463640235e2SEnji Cooper 	res = _sched_protect(-2);
464640235e2SEnji Cooper 	ATF_REQUIRE_EQ(res,  max_fifo_prio);
465640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex5));
466640235e2SEnji Cooper 	printf("child is done\n");
467640235e2SEnji Cooper 
468640235e2SEnji Cooper 	return 0;
469640235e2SEnji Cooper }
470640235e2SEnji Cooper 
471640235e2SEnji Cooper ATF_TC(mutex5);
ATF_TC_HEAD(mutex5,tc)472640235e2SEnji Cooper ATF_TC_HEAD(mutex5, tc)
473640235e2SEnji Cooper {
474640235e2SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks mutexes for priority setting");
475640235e2SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
476640235e2SEnji Cooper }
477640235e2SEnji Cooper 
ATF_TC_BODY(mutex5,tc)478640235e2SEnji Cooper ATF_TC_BODY(mutex5, tc)
479640235e2SEnji Cooper {
480640235e2SEnji Cooper 	int res;
481640235e2SEnji Cooper 	struct sched_param param;
482640235e2SEnji Cooper 	pthread_t child;
483640235e2SEnji Cooper 
484640235e2SEnji Cooper 	min_fifo_prio = sched_get_priority_min(SCHED_FIFO);
485640235e2SEnji Cooper 	max_fifo_prio = sched_get_priority_max(SCHED_FIFO);
486640235e2SEnji Cooper 	printf("min prio for FIFO = %d\n", min_fifo_prio);
487640235e2SEnji Cooper 	param.sched_priority = min_fifo_prio;
488640235e2SEnji Cooper 
489640235e2SEnji Cooper 	/* = 0 OTHER, 1 FIFO, 2 RR, -1 NONE */
490640235e2SEnji Cooper 	res = sched_setscheduler(getpid(), SCHED_FIFO, &param);
491640235e2SEnji Cooper 	printf("previous policy used = %d\n", res);
492640235e2SEnji Cooper 
493640235e2SEnji Cooper 	res = sched_getscheduler(getpid());
494640235e2SEnji Cooper 	ATF_REQUIRE_EQ_MSG(res, SCHED_FIFO, "sched %d != FIFO %d", res,
495640235e2SEnji Cooper 	    SCHED_FIFO);
496640235e2SEnji Cooper 
497640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_init(&attr5));
498640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_setprotocol(&attr5,
499640235e2SEnji Cooper 	    PTHREAD_PRIO_PROTECT));
500640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_setprioceiling(&attr5,
501640235e2SEnji Cooper 	    max_fifo_prio));
502640235e2SEnji Cooper 
503640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_init(&mutex5, &attr5));
504cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex5, &ts_lengthy));
505640235e2SEnji Cooper 	printf("enter critical section for main\n");
506640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_create(&child, NULL, child_func, NULL));
507640235e2SEnji Cooper 	printf("main starts to sleep\n");
508640235e2SEnji Cooper 	sleep(10);
509640235e2SEnji Cooper 	printf("main completes\n");
510640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex5));
511640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_join(child, NULL));
512640235e2SEnji Cooper }
513640235e2SEnji Cooper 
514640235e2SEnji Cooper static pthread_mutex_t mutex6;
515640235e2SEnji Cooper static int start = 0;
516640235e2SEnji Cooper static uintmax_t high_cnt = 0, low_cnt = 0, MAX_LOOP = 100000000;
517640235e2SEnji Cooper 
518640235e2SEnji Cooper static void *
high_prio(void * arg)519640235e2SEnji Cooper high_prio(void* arg)
520640235e2SEnji Cooper {
521640235e2SEnji Cooper 	struct sched_param param;
522640235e2SEnji Cooper 	int policy;
523640235e2SEnji Cooper 	param.sched_priority = min_fifo_prio + 10;
524640235e2SEnji Cooper 	pthread_t childid = pthread_self();
525640235e2SEnji Cooper 
526640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_setschedparam(childid, 1, &param));
527640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_getschedparam(childid, &policy, &param));
528640235e2SEnji Cooper 	printf("high protect = %d, prio = %d\n",
529640235e2SEnji Cooper 	    _sched_protect(-2), param.sched_priority);
530640235e2SEnji Cooper 	ATF_REQUIRE_EQ(policy, 1);
531640235e2SEnji Cooper 	printf("high prio = %d\n", param.sched_priority);
532640235e2SEnji Cooper 	sleep(1);
533640235e2SEnji Cooper 	long tmp = 0;
534640235e2SEnji Cooper 	for (int i = 0; i < 20; i++) {
535640235e2SEnji Cooper 		while (high_cnt < MAX_LOOP) {
536640235e2SEnji Cooper 			tmp += (123456789 % 1234) * (987654321 % 54321);
537640235e2SEnji Cooper 			high_cnt += 1;
538640235e2SEnji Cooper 		}
539640235e2SEnji Cooper 		high_cnt = 0;
540640235e2SEnji Cooper 		sleep(1);
541640235e2SEnji Cooper 	}
542cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex6, &ts_lengthy));
543640235e2SEnji Cooper 	if (start == 0) start = 2;
544640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex6));
545640235e2SEnji Cooper 
546640235e2SEnji Cooper 	return 0;
547640235e2SEnji Cooper }
548640235e2SEnji Cooper 
549640235e2SEnji Cooper static void *
low_prio(void * arg)550640235e2SEnji Cooper low_prio(void* arg)
551640235e2SEnji Cooper {
552640235e2SEnji Cooper 	struct sched_param param;
553640235e2SEnji Cooper 	int policy;
554640235e2SEnji Cooper 	param.sched_priority = min_fifo_prio;
555640235e2SEnji Cooper 	pthread_t childid = pthread_self();
556640235e2SEnji Cooper 	int res = _sched_protect(max_fifo_prio);
557640235e2SEnji Cooper 	ATF_REQUIRE_EQ(res, 0);
558640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_setschedparam(childid, 1, &param));
559640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_getschedparam(childid, &policy, &param));
560640235e2SEnji Cooper 	printf("low protect = %d, prio = %d\n", _sched_protect(-2),
561640235e2SEnji Cooper 	    param.sched_priority);
562640235e2SEnji Cooper 	ATF_REQUIRE_EQ(policy, 1);
563640235e2SEnji Cooper 	printf("low prio = %d\n", param.sched_priority);
564640235e2SEnji Cooper 	sleep(1);
565640235e2SEnji Cooper 	long tmp = 0;
566640235e2SEnji Cooper 	for (int i = 0; i < 20; i++) {
567640235e2SEnji Cooper 		while (low_cnt < MAX_LOOP) {
568640235e2SEnji Cooper 			tmp += (123456789 % 1234) * (987654321 % 54321);
569640235e2SEnji Cooper 			low_cnt += 1;
570640235e2SEnji Cooper 		}
571640235e2SEnji Cooper 		low_cnt = 0;
572640235e2SEnji Cooper 		sleep(1);
573640235e2SEnji Cooper 	}
574cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex6, &ts_lengthy));
575640235e2SEnji Cooper 	if (start == 0)
576640235e2SEnji Cooper 		start = 1;
577640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex6));
578640235e2SEnji Cooper 
579640235e2SEnji Cooper 	return 0;
580640235e2SEnji Cooper }
581640235e2SEnji Cooper 
582640235e2SEnji Cooper ATF_TC(mutex6);
ATF_TC_HEAD(mutex6,tc)583640235e2SEnji Cooper ATF_TC_HEAD(mutex6, tc)
584640235e2SEnji Cooper {
585640235e2SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
586640235e2SEnji Cooper 	    "Checks scheduling for priority ceiling");
587640235e2SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
588640235e2SEnji Cooper }
589640235e2SEnji Cooper 
590640235e2SEnji Cooper /*
591640235e2SEnji Cooper  * 1. main thread sets itself to be a realtime task and launched two tasks,
592640235e2SEnji Cooper  *    one has higher priority and the other has lower priority.
593640235e2SEnji Cooper  * 2. each child thread(low and high priority thread) sets its scheduler and
594640235e2SEnji Cooper  *    priority.
595640235e2SEnji Cooper  * 3. each child thread did several rounds of computation, after each round it
596640235e2SEnji Cooper  *    sleep 1 second.
597640235e2SEnji Cooper  * 4. the child thread with low priority will call _sched_protect to increase
598640235e2SEnji Cooper  *    its protect priority.
599640235e2SEnji Cooper  * 5. We verify the thread with low priority runs first.
600640235e2SEnji Cooper  *
601640235e2SEnji Cooper  * Why does it work? From the main thread, we launched the high
602640235e2SEnji Cooper  * priority thread first. This gives this thread the benefit of
603640235e2SEnji Cooper  * starting first. The low priority thread did not call _sched_protect(2).
604640235e2SEnji Cooper  * The high priority thread should finish the task first. After each
605640235e2SEnji Cooper  * round of computation, we call sleep, to put the task into the
606640235e2SEnji Cooper  * sleep queue, and wake up again after the timer expires. This
607640235e2SEnji Cooper  * gives the scheduler the chance to decide which task to run. So,
608640235e2SEnji Cooper  * the thread with real high priority will always block the thread
609640235e2SEnji Cooper  * with real low priority.
610640235e2SEnji Cooper  *
611640235e2SEnji Cooper  */
ATF_TC_BODY(mutex6,tc)612640235e2SEnji Cooper ATF_TC_BODY(mutex6, tc)
613640235e2SEnji Cooper {
614640235e2SEnji Cooper 	struct sched_param param;
615640235e2SEnji Cooper 	int res;
616640235e2SEnji Cooper 	pthread_t high, low;
617640235e2SEnji Cooper 
618640235e2SEnji Cooper 	min_fifo_prio = sched_get_priority_min(SCHED_FIFO);
619640235e2SEnji Cooper 	max_fifo_prio = sched_get_priority_max(SCHED_FIFO);
620640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
621640235e2SEnji Cooper 	printf("min_fifo_prio = %d, max_fifo_info = %d\n", min_fifo_prio,
622640235e2SEnji Cooper 	    max_fifo_prio);
623640235e2SEnji Cooper 
624640235e2SEnji Cooper 	param.sched_priority = min_fifo_prio;
625640235e2SEnji Cooper 	res = sched_setscheduler(getpid(), SCHED_FIFO, &param);
626640235e2SEnji Cooper 	printf("previous policy used = %d\n", res);
627640235e2SEnji Cooper 
628640235e2SEnji Cooper 	res = sched_getscheduler(getpid());
629640235e2SEnji Cooper 	ATF_REQUIRE_EQ(res, 1);
630640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_create(&high, NULL, high_prio, NULL));
631640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_create(&low, NULL, low_prio, NULL));
632640235e2SEnji Cooper 	sleep(5);
633640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_join(low, NULL));
634640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_join(high, NULL));
635640235e2SEnji Cooper 
636640235e2SEnji Cooper 	ATF_REQUIRE_EQ(start, 1);
637640235e2SEnji Cooper }
638640235e2SEnji Cooper #endif
639640235e2SEnji Cooper 
640640235e2SEnji Cooper ATF_TC(mutexattr1);
ATF_TC_HEAD(mutexattr1,tc)641640235e2SEnji Cooper ATF_TC_HEAD(mutexattr1, tc)
642640235e2SEnji Cooper {
643640235e2SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks mutexattr");
644640235e2SEnji Cooper }
645640235e2SEnji Cooper 
ATF_TC_BODY(mutexattr1,tc)646640235e2SEnji Cooper ATF_TC_BODY(mutexattr1, tc)
647640235e2SEnji Cooper {
648640235e2SEnji Cooper 	pthread_mutexattr_t mattr;
649640235e2SEnji Cooper 	int protocol, target;
650640235e2SEnji Cooper 
651640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_init(&mattr));
652640235e2SEnji Cooper 
653640235e2SEnji Cooper 	target = PTHREAD_PRIO_NONE;
654640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_setprotocol(&mattr, target));
655640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_getprotocol(&mattr, &protocol));
656640235e2SEnji Cooper 	ATF_REQUIRE_EQ(protocol, target);
657640235e2SEnji Cooper 
658640235e2SEnji Cooper 	/*
659640235e2SEnji Cooper 	target = PTHREAD_PRIO_INHERIT;
660640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_setprotocol(&mattr, target));
661640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_getprotocol(&mattr, &protocol));
662640235e2SEnji Cooper 	ATF_REQUIRE_EQ(protocol, target);
663640235e2SEnji Cooper 	*/
664640235e2SEnji Cooper 
665640235e2SEnji Cooper 	target = PTHREAD_PRIO_PROTECT;
666640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_setprotocol(&mattr, target));
667640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_getprotocol(&mattr, &protocol));
668640235e2SEnji Cooper 	ATF_REQUIRE_EQ(protocol, target);
669640235e2SEnji Cooper }
670640235e2SEnji Cooper 
671640235e2SEnji Cooper ATF_TC(mutexattr2);
ATF_TC_HEAD(mutexattr2,tc)672640235e2SEnji Cooper ATF_TC_HEAD(mutexattr2, tc)
673640235e2SEnji Cooper {
674640235e2SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks mutexattr");
675640235e2SEnji Cooper }
676640235e2SEnji Cooper 
ATF_TC_BODY(mutexattr2,tc)677640235e2SEnji Cooper ATF_TC_BODY(mutexattr2, tc)
678640235e2SEnji Cooper {
679640235e2SEnji Cooper 	pthread_mutexattr_t mattr;
680640235e2SEnji Cooper 
68182bc57c2SEnji Cooper #ifdef __FreeBSD__
68282bc57c2SEnji Cooper 	atf_tc_expect_fail("fails on i == 0 with: "
68382bc57c2SEnji Cooper 	    "pthread_mutexattr_setprioceiling(&mattr, i): Invalid argument "
68482bc57c2SEnji Cooper 	    "-- PR # 211802");
68582bc57c2SEnji Cooper #endif
68682bc57c2SEnji Cooper 
687640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_init(&mattr));
688640235e2SEnji Cooper 	int max_prio = sched_get_priority_max(SCHED_FIFO);
689640235e2SEnji Cooper 	int min_prio = sched_get_priority_min(SCHED_FIFO);
690640235e2SEnji Cooper 	for (int i = min_prio; i <= max_prio; i++) {
691640235e2SEnji Cooper 		int prioceiling;
69282bc57c2SEnji Cooper 		int protocol;
69382bc57c2SEnji Cooper 
69482bc57c2SEnji Cooper 		PTHREAD_REQUIRE(pthread_mutexattr_getprotocol(&mattr,
69582bc57c2SEnji Cooper 		    &protocol));
69682bc57c2SEnji Cooper 
69782bc57c2SEnji Cooper 		printf("priority: %d\nprotocol: %d\n", i, protocol);
698640235e2SEnji Cooper 		PTHREAD_REQUIRE(pthread_mutexattr_setprioceiling(&mattr, i));
699640235e2SEnji Cooper 		PTHREAD_REQUIRE(pthread_mutexattr_getprioceiling(&mattr,
700640235e2SEnji Cooper 		    &prioceiling));
70182bc57c2SEnji Cooper 		printf("prioceiling: %d\n", prioceiling);
702640235e2SEnji Cooper 		ATF_REQUIRE_EQ(i, prioceiling);
703640235e2SEnji Cooper 	}
704640235e2SEnji Cooper }
705640235e2SEnji Cooper 
706cdebaff8SEnji Cooper #ifdef TIMEDMUTEX
707cdebaff8SEnji Cooper ATF_TC(timedmutex1);
ATF_TC_HEAD(timedmutex1,tc)708cdebaff8SEnji Cooper ATF_TC_HEAD(timedmutex1, tc)
709cdebaff8SEnji Cooper {
710cdebaff8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks timeout on selflock");
711cdebaff8SEnji Cooper }
712cdebaff8SEnji Cooper 
ATF_TC_BODY(timedmutex1,tc)713cdebaff8SEnji Cooper ATF_TC_BODY(timedmutex1, tc)
714cdebaff8SEnji Cooper {
715cdebaff8SEnji Cooper 
716cdebaff8SEnji Cooper 	printf("Timed mutex-test 1\n");
717cdebaff8SEnji Cooper 
718cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
719cdebaff8SEnji Cooper 
720cdebaff8SEnji Cooper 	printf("Before acquiring mutex\n");
721cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
722cdebaff8SEnji Cooper 
723cdebaff8SEnji Cooper 	printf("Before endeavor to reacquire timed-mutex (timeout expected)\n");
724cdebaff8SEnji Cooper 	PTHREAD_REQUIRE_STATUS(mutex_lock(&mutex, &ts_shortlived),
725cdebaff8SEnji Cooper 	    ETIMEDOUT);
726cdebaff8SEnji Cooper 
727cdebaff8SEnji Cooper 	printf("Unlocking mutex\n");
728cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
729cdebaff8SEnji Cooper }
730cdebaff8SEnji Cooper 
731cdebaff8SEnji Cooper ATF_TC(timedmutex2);
ATF_TC_HEAD(timedmutex2,tc)732cdebaff8SEnji Cooper ATF_TC_HEAD(timedmutex2, tc)
733cdebaff8SEnji Cooper {
734cdebaff8SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
735cdebaff8SEnji Cooper 	    "Checks timeout on selflock with timedlock");
736cdebaff8SEnji Cooper }
737cdebaff8SEnji Cooper 
ATF_TC_BODY(timedmutex2,tc)738cdebaff8SEnji Cooper ATF_TC_BODY(timedmutex2, tc)
739cdebaff8SEnji Cooper {
740cdebaff8SEnji Cooper 
741cdebaff8SEnji Cooper 	printf("Timed mutex-test 2\n");
742cdebaff8SEnji Cooper 
743cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
744cdebaff8SEnji Cooper 
745cdebaff8SEnji Cooper 	printf("Before acquiring mutex with timedlock\n");
746cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
747cdebaff8SEnji Cooper 
748cdebaff8SEnji Cooper 	printf("Before endeavor to reacquire timed-mutex (timeout expected)\n");
749cdebaff8SEnji Cooper 	PTHREAD_REQUIRE_STATUS(mutex_lock(&mutex, &ts_shortlived),
750cdebaff8SEnji Cooper 	    ETIMEDOUT);
751cdebaff8SEnji Cooper 
752cdebaff8SEnji Cooper 	printf("Unlocking mutex\n");
753cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
754cdebaff8SEnji Cooper }
755cdebaff8SEnji Cooper 
756cdebaff8SEnji Cooper ATF_TC(timedmutex3);
ATF_TC_HEAD(timedmutex3,tc)757cdebaff8SEnji Cooper ATF_TC_HEAD(timedmutex3, tc)
758cdebaff8SEnji Cooper {
759cdebaff8SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
760cdebaff8SEnji Cooper 	    "Checks timeout on selflock in a new thread");
761cdebaff8SEnji Cooper }
762cdebaff8SEnji Cooper 
763cdebaff8SEnji Cooper static void *
timedmtx_thrdfunc(void * arg)764cdebaff8SEnji Cooper timedmtx_thrdfunc(void *arg)
765cdebaff8SEnji Cooper {
766cdebaff8SEnji Cooper 	printf("Before endeavor to reacquire timed-mutex (timeout expected)\n");
767cdebaff8SEnji Cooper 	PTHREAD_REQUIRE_STATUS(mutex_lock(&mutex, &ts_shortlived),
768cdebaff8SEnji Cooper 	    ETIMEDOUT);
769cdebaff8SEnji Cooper 
770cdebaff8SEnji Cooper 	return NULL;
771cdebaff8SEnji Cooper }
772cdebaff8SEnji Cooper 
ATF_TC_BODY(timedmutex3,tc)773cdebaff8SEnji Cooper ATF_TC_BODY(timedmutex3, tc)
774cdebaff8SEnji Cooper {
775cdebaff8SEnji Cooper 	pthread_t new;
776cdebaff8SEnji Cooper 
777cdebaff8SEnji Cooper 	printf("Timed mutex-test 3\n");
778cdebaff8SEnji Cooper 
779cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
780cdebaff8SEnji Cooper 
781cdebaff8SEnji Cooper 	printf("Before acquiring mutex with timedlock\n");
782cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
783cdebaff8SEnji Cooper 
784cdebaff8SEnji Cooper 	printf("Before creating new thread\n");
785cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_create(&new, NULL, timedmtx_thrdfunc, NULL));
786cdebaff8SEnji Cooper 
787cdebaff8SEnji Cooper 	printf("Before joining the mutex\n");
788cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_join(new, NULL));
789cdebaff8SEnji Cooper 
790cdebaff8SEnji Cooper 	printf("Unlocking mutex\n");
791cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
792cdebaff8SEnji Cooper }
793cdebaff8SEnji Cooper 
794cdebaff8SEnji Cooper ATF_TC(timedmutex4);
ATF_TC_HEAD(timedmutex4,tc)795cdebaff8SEnji Cooper ATF_TC_HEAD(timedmutex4, tc)
796cdebaff8SEnji Cooper {
797cdebaff8SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
798cdebaff8SEnji Cooper 	    "Checks timeout on selflock with timedlock in a new thread");
799cdebaff8SEnji Cooper }
800cdebaff8SEnji Cooper 
ATF_TC_BODY(timedmutex4,tc)801cdebaff8SEnji Cooper ATF_TC_BODY(timedmutex4, tc)
802cdebaff8SEnji Cooper {
803cdebaff8SEnji Cooper 	pthread_t new;
804cdebaff8SEnji Cooper 
805cdebaff8SEnji Cooper 	printf("Timed mutex-test 4\n");
806cdebaff8SEnji Cooper 
807cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
808cdebaff8SEnji Cooper 
809cdebaff8SEnji Cooper 	printf("Before acquiring mutex with timedlock\n");
810cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
811cdebaff8SEnji Cooper 
812cdebaff8SEnji Cooper 	printf("Before creating new thread\n");
813cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_create(&new, NULL, timedmtx_thrdfunc, NULL));
814cdebaff8SEnji Cooper 
815cdebaff8SEnji Cooper 	printf("Before joining the mutex\n");
816cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_join(new, NULL));
817cdebaff8SEnji Cooper 
818cdebaff8SEnji Cooper 	printf("Unlocking mutex\n");
819cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
820cdebaff8SEnji Cooper }
821cdebaff8SEnji Cooper #endif
822cdebaff8SEnji Cooper 
ATF_TP_ADD_TCS(tp)82357718be8SEnji Cooper ATF_TP_ADD_TCS(tp)
82457718be8SEnji Cooper {
82557718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, mutex1);
82657718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, mutex2);
82757718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, mutex3);
82857718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, mutex4);
829640235e2SEnji Cooper #ifdef __NetBSD__
830640235e2SEnji Cooper 	ATF_TP_ADD_TC(tp, mutex5);
831640235e2SEnji Cooper 	ATF_TP_ADD_TC(tp, mutex6);
832640235e2SEnji Cooper #endif
833640235e2SEnji Cooper 	ATF_TP_ADD_TC(tp, mutexattr1);
834640235e2SEnji Cooper 	ATF_TP_ADD_TC(tp, mutexattr2);
83557718be8SEnji Cooper 
836cdebaff8SEnji Cooper #ifdef TIMEDMUTEX
837cdebaff8SEnji Cooper 	ATF_TP_ADD_TC(tp, timedmutex1);
838cdebaff8SEnji Cooper 	ATF_TP_ADD_TC(tp, timedmutex2);
839cdebaff8SEnji Cooper 	ATF_TP_ADD_TC(tp, timedmutex3);
840cdebaff8SEnji Cooper 	ATF_TP_ADD_TC(tp, timedmutex4);
841cdebaff8SEnji Cooper #endif
842cdebaff8SEnji Cooper 
84357718be8SEnji Cooper 	return atf_no_error();
84457718be8SEnji Cooper }
845