xref: /freebsd/contrib/netbsd-tests/lib/libpthread/t_mutex.c (revision cdebaff820b2a4915a16cedfd511823d78aab171)
1*cdebaff8SEnji Cooper /* $NetBSD: t_mutex.c,v 1.14 2016/10/31 23:51:20 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.");
32*cdebaff8SEnji Cooper __RCSID("$NetBSD: t_mutex.c,v 1.14 2016/10/31 23:51:20 christos Exp $");
3357718be8SEnji Cooper 
34*cdebaff8SEnji Cooper #ifdef __FreeBSD__
35*cdebaff8SEnji Cooper #include <sys/time.h> /* For timespecadd */
36*cdebaff8SEnji Cooper #include <inttypes.h> /* For UINT16_MAX */
37*cdebaff8SEnji Cooper #endif
3857718be8SEnji Cooper #include <pthread.h>
3957718be8SEnji Cooper #include <stdio.h>
4057718be8SEnji Cooper #include <string.h>
41640235e2SEnji Cooper #include <errno.h>
42*cdebaff8SEnji Cooper #include <time.h>
4357718be8SEnji Cooper #include <unistd.h>
44640235e2SEnji Cooper #include <sys/sched.h>
45640235e2SEnji Cooper #include <sys/param.h>
4657718be8SEnji Cooper 
4757718be8SEnji Cooper #include <atf-c.h>
4857718be8SEnji Cooper 
4957718be8SEnji Cooper #include "h_common.h"
5057718be8SEnji Cooper 
5157718be8SEnji Cooper static pthread_mutex_t mutex;
5257718be8SEnji Cooper static pthread_mutex_t static_mutex = PTHREAD_MUTEX_INITIALIZER;
5357718be8SEnji Cooper static int global_x;
5457718be8SEnji Cooper 
55*cdebaff8SEnji Cooper #ifdef TIMEDMUTEX
56*cdebaff8SEnji Cooper /* This code is used for verifying non-timed specific code */
57*cdebaff8SEnji Cooper static struct timespec ts_lengthy = {
58*cdebaff8SEnji Cooper 	.tv_sec = UINT16_MAX,
59*cdebaff8SEnji Cooper 	.tv_nsec = 0
60*cdebaff8SEnji Cooper };
61*cdebaff8SEnji Cooper /* This code is used for verifying timed-only specific code */
62*cdebaff8SEnji Cooper static struct timespec ts_shortlived = {
63*cdebaff8SEnji Cooper 	.tv_sec = 0,
64*cdebaff8SEnji Cooper 	.tv_nsec = 120
65*cdebaff8SEnji Cooper };
66*cdebaff8SEnji Cooper 
67*cdebaff8SEnji Cooper static int
68*cdebaff8SEnji Cooper mutex_lock(pthread_mutex_t *m, const struct timespec *ts)
69*cdebaff8SEnji Cooper {
70*cdebaff8SEnji Cooper 	struct timespec ts_wait;
71*cdebaff8SEnji Cooper 	ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &ts_wait) != -1);
72*cdebaff8SEnji Cooper 	timespecadd(&ts_wait, ts, &ts_wait);
73*cdebaff8SEnji Cooper 
74*cdebaff8SEnji Cooper 	return pthread_mutex_timedlock(m, &ts_wait);
75*cdebaff8SEnji Cooper }
76*cdebaff8SEnji Cooper #else
77*cdebaff8SEnji Cooper #define mutex_lock(a, b) pthread_mutex_lock(a)
78*cdebaff8SEnji Cooper #endif
79*cdebaff8SEnji Cooper 
8057718be8SEnji Cooper static void *
8157718be8SEnji Cooper mutex1_threadfunc(void *arg)
8257718be8SEnji Cooper {
8357718be8SEnji Cooper 	int *param;
8457718be8SEnji Cooper 
8557718be8SEnji Cooper 	printf("2: Second thread.\n");
8657718be8SEnji Cooper 
8757718be8SEnji Cooper 	param = arg;
8857718be8SEnji Cooper 	printf("2: Locking mutex\n");
89*cdebaff8SEnji Cooper 	mutex_lock(&mutex, &ts_lengthy);
9057718be8SEnji Cooper 	printf("2: Got mutex. *param = %d\n", *param);
9157718be8SEnji Cooper 	ATF_REQUIRE_EQ(*param, 20);
9257718be8SEnji Cooper 	(*param)++;
9357718be8SEnji Cooper 
9457718be8SEnji Cooper 	pthread_mutex_unlock(&mutex);
9557718be8SEnji Cooper 
9657718be8SEnji Cooper 	return param;
9757718be8SEnji Cooper }
9857718be8SEnji Cooper 
9957718be8SEnji Cooper ATF_TC(mutex1);
10057718be8SEnji Cooper ATF_TC_HEAD(mutex1, tc)
10157718be8SEnji Cooper {
10257718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks mutexes");
10357718be8SEnji Cooper }
10457718be8SEnji Cooper ATF_TC_BODY(mutex1, tc)
10557718be8SEnji Cooper {
10657718be8SEnji Cooper 	int x;
10757718be8SEnji Cooper 	pthread_t new;
10857718be8SEnji Cooper 	void *joinval;
10957718be8SEnji Cooper 
11057718be8SEnji Cooper 	printf("1: Mutex-test 1\n");
11157718be8SEnji Cooper 
11257718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
11357718be8SEnji Cooper 	x = 1;
114*cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
11557718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex1_threadfunc, &x));
11657718be8SEnji Cooper 	printf("1: Before changing the value.\n");
11757718be8SEnji Cooper 	sleep(2);
11857718be8SEnji Cooper 	x = 20;
11957718be8SEnji Cooper 	printf("1: Before releasing the mutex.\n");
12057718be8SEnji Cooper 	sleep(2);
12157718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
12257718be8SEnji Cooper 	printf("1: After releasing the mutex.\n");
12357718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_join(new, &joinval));
12457718be8SEnji Cooper 
125*cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
12657718be8SEnji Cooper 	printf("1: Thread joined. X was %d. Return value (int) was %d\n",
12757718be8SEnji Cooper 		x, *(int *)joinval);
12857718be8SEnji Cooper 	ATF_REQUIRE_EQ(x, 21);
12957718be8SEnji Cooper 	ATF_REQUIRE_EQ(*(int *)joinval, 21);
13057718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
13157718be8SEnji Cooper }
13257718be8SEnji Cooper 
13357718be8SEnji Cooper static void *
13457718be8SEnji Cooper mutex2_threadfunc(void *arg)
13557718be8SEnji Cooper {
13657718be8SEnji Cooper 	long count = *(int *)arg;
13757718be8SEnji Cooper 
13857718be8SEnji Cooper 	printf("2: Second thread (%p). Count is %ld\n", pthread_self(), count);
13957718be8SEnji Cooper 
14057718be8SEnji Cooper 	while (count--) {
141*cdebaff8SEnji Cooper 		PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
14257718be8SEnji Cooper 		global_x++;
14357718be8SEnji Cooper 		PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
14457718be8SEnji Cooper 	}
14557718be8SEnji Cooper 
14657718be8SEnji Cooper 	return (void *)count;
14757718be8SEnji Cooper }
14857718be8SEnji Cooper 
14957718be8SEnji Cooper ATF_TC(mutex2);
15057718be8SEnji Cooper ATF_TC_HEAD(mutex2, tc)
15157718be8SEnji Cooper {
15257718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks mutexes");
153190e1b1cSEnji Cooper #ifdef __NetBSD__
15457718be8SEnji Cooper #if defined(__powerpc__)
15557718be8SEnji Cooper 	atf_tc_set_md_var(tc, "timeout", "40");
15657718be8SEnji Cooper #endif
157190e1b1cSEnji Cooper #endif
15857718be8SEnji Cooper }
15957718be8SEnji Cooper ATF_TC_BODY(mutex2, tc)
16057718be8SEnji Cooper {
16157718be8SEnji Cooper 	int count, count2;
16257718be8SEnji Cooper 	pthread_t new;
16357718be8SEnji Cooper 	void *joinval;
16457718be8SEnji Cooper 
16557718be8SEnji Cooper 	printf("1: Mutex-test 2\n");
16657718be8SEnji Cooper 
167190e1b1cSEnji Cooper #ifdef __NetBSD__
16857718be8SEnji Cooper #if defined(__powerpc__)
16957718be8SEnji Cooper 	atf_tc_expect_timeout("PR port-powerpc/44387");
17057718be8SEnji Cooper #endif
171190e1b1cSEnji Cooper #endif
17257718be8SEnji Cooper 
17357718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
17457718be8SEnji Cooper 
17557718be8SEnji Cooper 	global_x = 0;
17657718be8SEnji Cooper 	count = count2 = 10000000;
17757718be8SEnji Cooper 
178*cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
17957718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex2_threadfunc, &count2));
18057718be8SEnji Cooper 
18157718be8SEnji Cooper 	printf("1: Thread %p\n", pthread_self());
18257718be8SEnji Cooper 
18357718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
18457718be8SEnji Cooper 
18557718be8SEnji Cooper 	while (count--) {
186*cdebaff8SEnji Cooper 		PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
18757718be8SEnji Cooper 		global_x++;
18857718be8SEnji Cooper 		PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
18957718be8SEnji Cooper 	}
19057718be8SEnji Cooper 
19157718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_join(new, &joinval));
19257718be8SEnji Cooper 
193*cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
19457718be8SEnji Cooper 	printf("1: Thread joined. X was %d. Return value (long) was %ld\n",
19557718be8SEnji Cooper 		global_x, (long)joinval);
19657718be8SEnji Cooper 	ATF_REQUIRE_EQ(global_x, 20000000);
19757718be8SEnji Cooper 
198190e1b1cSEnji Cooper #ifdef __NetBSD__
19957718be8SEnji Cooper #if defined(__powerpc__)
20057718be8SEnji Cooper 	/* XXX force a timeout in ppc case since an un-triggered race
20157718be8SEnji Cooper 	   otherwise looks like a "failure" */
20257718be8SEnji Cooper 	/* We sleep for longer than the timeout to make ATF not
20357718be8SEnji Cooper 	   complain about unexpected success */
20457718be8SEnji Cooper 	sleep(41);
20557718be8SEnji Cooper #endif
206190e1b1cSEnji Cooper #endif
20757718be8SEnji Cooper }
20857718be8SEnji Cooper 
20957718be8SEnji Cooper static void *
21057718be8SEnji Cooper mutex3_threadfunc(void *arg)
21157718be8SEnji Cooper {
21257718be8SEnji Cooper 	long count = *(int *)arg;
21357718be8SEnji Cooper 
21457718be8SEnji Cooper 	printf("2: Second thread (%p). Count is %ld\n", pthread_self(), count);
21557718be8SEnji Cooper 
21657718be8SEnji Cooper 	while (count--) {
217*cdebaff8SEnji Cooper 		PTHREAD_REQUIRE(mutex_lock(&static_mutex, &ts_lengthy));
21857718be8SEnji Cooper 		global_x++;
21957718be8SEnji Cooper 		PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
22057718be8SEnji Cooper 	}
22157718be8SEnji Cooper 
22257718be8SEnji Cooper 	return (void *)count;
22357718be8SEnji Cooper }
22457718be8SEnji Cooper 
22557718be8SEnji Cooper ATF_TC(mutex3);
22657718be8SEnji Cooper ATF_TC_HEAD(mutex3, tc)
22757718be8SEnji Cooper {
22857718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks mutexes using a static "
22957718be8SEnji Cooper 	    "initializer");
230190e1b1cSEnji Cooper #ifdef __NetBSD__
23157718be8SEnji Cooper #if defined(__powerpc__)
23257718be8SEnji Cooper 	atf_tc_set_md_var(tc, "timeout", "40");
23357718be8SEnji Cooper #endif
234190e1b1cSEnji Cooper #endif
23557718be8SEnji Cooper }
23657718be8SEnji Cooper ATF_TC_BODY(mutex3, tc)
23757718be8SEnji Cooper {
23857718be8SEnji Cooper 	int count, count2;
23957718be8SEnji Cooper 	pthread_t new;
24057718be8SEnji Cooper 	void *joinval;
24157718be8SEnji Cooper 
24257718be8SEnji Cooper 	printf("1: Mutex-test 3\n");
24357718be8SEnji Cooper 
244190e1b1cSEnji Cooper #ifdef __NetBSD__
24557718be8SEnji Cooper #if defined(__powerpc__)
24657718be8SEnji Cooper 	atf_tc_expect_timeout("PR port-powerpc/44387");
24757718be8SEnji Cooper #endif
248190e1b1cSEnji Cooper #endif
24957718be8SEnji Cooper 
25057718be8SEnji Cooper 	global_x = 0;
25157718be8SEnji Cooper 	count = count2 = 10000000;
25257718be8SEnji Cooper 
253*cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&static_mutex, &ts_lengthy));
25457718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex3_threadfunc, &count2));
25557718be8SEnji Cooper 
25657718be8SEnji Cooper 	printf("1: Thread %p\n", pthread_self());
25757718be8SEnji Cooper 
25857718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
25957718be8SEnji Cooper 
26057718be8SEnji Cooper 	while (count--) {
261*cdebaff8SEnji Cooper 		PTHREAD_REQUIRE(mutex_lock(&static_mutex, &ts_lengthy));
26257718be8SEnji Cooper 		global_x++;
26357718be8SEnji Cooper 		PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
26457718be8SEnji Cooper 	}
26557718be8SEnji Cooper 
26657718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_join(new, &joinval));
26757718be8SEnji Cooper 
268*cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&static_mutex, &ts_lengthy));
26957718be8SEnji Cooper 	printf("1: Thread joined. X was %d. Return value (long) was %ld\n",
27057718be8SEnji Cooper 		global_x, (long)joinval);
27157718be8SEnji Cooper 	ATF_REQUIRE_EQ(global_x, 20000000);
27257718be8SEnji Cooper 
273190e1b1cSEnji Cooper #ifdef __NetBSD__
27457718be8SEnji Cooper #if defined(__powerpc__)
27557718be8SEnji Cooper 	/* XXX force a timeout in ppc case since an un-triggered race
27657718be8SEnji Cooper 	   otherwise looks like a "failure" */
27757718be8SEnji Cooper 	/* We sleep for longer than the timeout to make ATF not
27857718be8SEnji Cooper 	   complain about unexpected success */
27957718be8SEnji Cooper 	sleep(41);
28057718be8SEnji Cooper #endif
281190e1b1cSEnji Cooper #endif
28257718be8SEnji Cooper }
28357718be8SEnji Cooper 
28457718be8SEnji Cooper static void *
28557718be8SEnji Cooper mutex4_threadfunc(void *arg)
28657718be8SEnji Cooper {
28757718be8SEnji Cooper 	int *param;
28857718be8SEnji Cooper 
28957718be8SEnji Cooper 	printf("2: Second thread.\n");
29057718be8SEnji Cooper 
29157718be8SEnji Cooper 	param = arg;
29257718be8SEnji Cooper 	printf("2: Locking mutex\n");
293*cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
29457718be8SEnji Cooper 	printf("2: Got mutex. *param = %d\n", *param);
29557718be8SEnji Cooper 	(*param)++;
29657718be8SEnji Cooper 
29757718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
29857718be8SEnji Cooper 
29957718be8SEnji Cooper 	return param;
30057718be8SEnji Cooper }
30157718be8SEnji Cooper 
30257718be8SEnji Cooper ATF_TC(mutex4);
30357718be8SEnji Cooper ATF_TC_HEAD(mutex4, tc)
30457718be8SEnji Cooper {
30557718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks mutexes");
30657718be8SEnji Cooper }
30757718be8SEnji Cooper ATF_TC_BODY(mutex4, tc)
30857718be8SEnji Cooper {
30957718be8SEnji Cooper 	int x;
31057718be8SEnji Cooper 	pthread_t new;
31157718be8SEnji Cooper 	pthread_mutexattr_t mattr;
31257718be8SEnji Cooper 	void *joinval;
31357718be8SEnji Cooper 
31457718be8SEnji Cooper 	printf("1: Mutex-test 4\n");
31557718be8SEnji Cooper 
31657718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_init(&mattr));
31757718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE));
31857718be8SEnji Cooper 
31957718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, &mattr));
32057718be8SEnji Cooper 
32157718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_destroy(&mattr));
32257718be8SEnji Cooper 
32357718be8SEnji Cooper 	x = 1;
324*cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
32557718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex4_threadfunc, &x));
32657718be8SEnji Cooper 
32757718be8SEnji Cooper 	printf("1: Before recursively acquiring the mutex.\n");
328*cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
32957718be8SEnji Cooper 
33057718be8SEnji Cooper 	printf("1: Before releasing the mutex once.\n");
33157718be8SEnji Cooper 	sleep(2);
33257718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
33357718be8SEnji Cooper 	printf("1: After releasing the mutex once.\n");
33457718be8SEnji Cooper 
33557718be8SEnji Cooper 	x = 20;
33657718be8SEnji Cooper 
33757718be8SEnji Cooper 	printf("1: Before releasing the mutex twice.\n");
33857718be8SEnji Cooper 	sleep(2);
33957718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
34057718be8SEnji Cooper 	printf("1: After releasing the mutex twice.\n");
34157718be8SEnji Cooper 
34257718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_join(new, &joinval));
34357718be8SEnji Cooper 
344*cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
34557718be8SEnji Cooper 	printf("1: Thread joined. X was %d. Return value (int) was %d\n",
34657718be8SEnji Cooper 		x, *(int *)joinval);
34757718be8SEnji Cooper 	ATF_REQUIRE_EQ(x, 21);
34857718be8SEnji Cooper 	ATF_REQUIRE_EQ(*(int *)joinval, 21);
34957718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
35057718be8SEnji Cooper }
35157718be8SEnji Cooper 
352640235e2SEnji Cooper #ifdef __NetBSD__
353640235e2SEnji Cooper static pthread_mutexattr_t attr5;
354640235e2SEnji Cooper static pthread_mutex_t mutex5;
355640235e2SEnji Cooper static int min_fifo_prio, max_fifo_prio;
356640235e2SEnji Cooper 
357640235e2SEnji Cooper static void *
358640235e2SEnji Cooper child_func(void* arg)
359640235e2SEnji Cooper {
360640235e2SEnji Cooper 	int res;
361640235e2SEnji Cooper 
362640235e2SEnji Cooper 	printf("child is waiting\n");
363640235e2SEnji Cooper 	res = _sched_protect(-2);
364640235e2SEnji Cooper 	ATF_REQUIRE_EQ_MSG(res, -1, "sched_protect returned %d", res);
365640235e2SEnji Cooper 	ATF_REQUIRE_EQ(errno, ENOENT);
366*cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex5, &ts_lengthy));
367640235e2SEnji Cooper 	printf("child is owning resource\n");
368640235e2SEnji Cooper 	res = _sched_protect(-2);
369640235e2SEnji Cooper 	ATF_REQUIRE_EQ(res,  max_fifo_prio);
370640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex5));
371640235e2SEnji Cooper 	printf("child is done\n");
372640235e2SEnji Cooper 
373640235e2SEnji Cooper 	return 0;
374640235e2SEnji Cooper }
375640235e2SEnji Cooper 
376640235e2SEnji Cooper ATF_TC(mutex5);
377640235e2SEnji Cooper ATF_TC_HEAD(mutex5, tc)
378640235e2SEnji Cooper {
379640235e2SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks mutexes for priority setting");
380640235e2SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
381640235e2SEnji Cooper }
382640235e2SEnji Cooper 
383640235e2SEnji Cooper ATF_TC_BODY(mutex5, tc)
384640235e2SEnji Cooper {
385640235e2SEnji Cooper 	int res;
386640235e2SEnji Cooper 	struct sched_param param;
387640235e2SEnji Cooper 	pthread_t child;
388640235e2SEnji Cooper 
389640235e2SEnji Cooper 	min_fifo_prio = sched_get_priority_min(SCHED_FIFO);
390640235e2SEnji Cooper 	max_fifo_prio = sched_get_priority_max(SCHED_FIFO);
391640235e2SEnji Cooper 	printf("min prio for FIFO = %d\n", min_fifo_prio);
392640235e2SEnji Cooper 	param.sched_priority = min_fifo_prio;
393640235e2SEnji Cooper 
394640235e2SEnji Cooper 	/* = 0 OTHER, 1 FIFO, 2 RR, -1 NONE */
395640235e2SEnji Cooper 	res = sched_setscheduler(getpid(), SCHED_FIFO, &param);
396640235e2SEnji Cooper 	printf("previous policy used = %d\n", res);
397640235e2SEnji Cooper 
398640235e2SEnji Cooper 	res = sched_getscheduler(getpid());
399640235e2SEnji Cooper 	ATF_REQUIRE_EQ_MSG(res, SCHED_FIFO, "sched %d != FIFO %d", res,
400640235e2SEnji Cooper 	    SCHED_FIFO);
401640235e2SEnji Cooper 
402640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_init(&attr5));
403640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_setprotocol(&attr5,
404640235e2SEnji Cooper 	    PTHREAD_PRIO_PROTECT));
405640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_setprioceiling(&attr5,
406640235e2SEnji Cooper 	    max_fifo_prio));
407640235e2SEnji Cooper 
408640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_init(&mutex5, &attr5));
409*cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex5, &ts_lengthy));
410640235e2SEnji Cooper 	printf("enter critical section for main\n");
411640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_create(&child, NULL, child_func, NULL));
412640235e2SEnji Cooper 	printf("main starts to sleep\n");
413640235e2SEnji Cooper 	sleep(10);
414640235e2SEnji Cooper 	printf("main completes\n");
415640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex5));
416640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_join(child, NULL));
417640235e2SEnji Cooper }
418640235e2SEnji Cooper 
419640235e2SEnji Cooper static pthread_mutex_t mutex6;
420640235e2SEnji Cooper static int start = 0;
421640235e2SEnji Cooper static uintmax_t high_cnt = 0, low_cnt = 0, MAX_LOOP = 100000000;
422640235e2SEnji Cooper 
423640235e2SEnji Cooper static void *
424640235e2SEnji Cooper high_prio(void* arg)
425640235e2SEnji Cooper {
426640235e2SEnji Cooper 	struct sched_param param;
427640235e2SEnji Cooper 	int policy;
428640235e2SEnji Cooper 	param.sched_priority = min_fifo_prio + 10;
429640235e2SEnji Cooper 	pthread_t childid = pthread_self();
430640235e2SEnji Cooper 
431640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_setschedparam(childid, 1, &param));
432640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_getschedparam(childid, &policy, &param));
433640235e2SEnji Cooper 	printf("high protect = %d, prio = %d\n",
434640235e2SEnji Cooper 	    _sched_protect(-2), param.sched_priority);
435640235e2SEnji Cooper 	ATF_REQUIRE_EQ(policy, 1);
436640235e2SEnji Cooper 	printf("high prio = %d\n", param.sched_priority);
437640235e2SEnji Cooper 	sleep(1);
438640235e2SEnji Cooper 	long tmp = 0;
439640235e2SEnji Cooper 	for (int i = 0; i < 20; i++) {
440640235e2SEnji Cooper 		while (high_cnt < MAX_LOOP) {
441640235e2SEnji Cooper 			tmp += (123456789 % 1234) * (987654321 % 54321);
442640235e2SEnji Cooper 			high_cnt += 1;
443640235e2SEnji Cooper 		}
444640235e2SEnji Cooper 		high_cnt = 0;
445640235e2SEnji Cooper 		sleep(1);
446640235e2SEnji Cooper 	}
447*cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex6, &ts_lengthy));
448640235e2SEnji Cooper 	if (start == 0) start = 2;
449640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex6));
450640235e2SEnji Cooper 
451640235e2SEnji Cooper 	return 0;
452640235e2SEnji Cooper }
453640235e2SEnji Cooper 
454640235e2SEnji Cooper static void *
455640235e2SEnji Cooper low_prio(void* arg)
456640235e2SEnji Cooper {
457640235e2SEnji Cooper 	struct sched_param param;
458640235e2SEnji Cooper 	int policy;
459640235e2SEnji Cooper 	param.sched_priority = min_fifo_prio;
460640235e2SEnji Cooper 	pthread_t childid = pthread_self();
461640235e2SEnji Cooper 	int res = _sched_protect(max_fifo_prio);
462640235e2SEnji Cooper 	ATF_REQUIRE_EQ(res, 0);
463640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_setschedparam(childid, 1, &param));
464640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_getschedparam(childid, &policy, &param));
465640235e2SEnji Cooper 	printf("low protect = %d, prio = %d\n", _sched_protect(-2),
466640235e2SEnji Cooper 	    param.sched_priority);
467640235e2SEnji Cooper 	ATF_REQUIRE_EQ(policy, 1);
468640235e2SEnji Cooper 	printf("low prio = %d\n", param.sched_priority);
469640235e2SEnji Cooper 	sleep(1);
470640235e2SEnji Cooper 	long tmp = 0;
471640235e2SEnji Cooper 	for (int i = 0; i < 20; i++) {
472640235e2SEnji Cooper 		while (low_cnt < MAX_LOOP) {
473640235e2SEnji Cooper 			tmp += (123456789 % 1234) * (987654321 % 54321);
474640235e2SEnji Cooper 			low_cnt += 1;
475640235e2SEnji Cooper 		}
476640235e2SEnji Cooper 		low_cnt = 0;
477640235e2SEnji Cooper 		sleep(1);
478640235e2SEnji Cooper 	}
479*cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex6, &ts_lengthy));
480640235e2SEnji Cooper 	if (start == 0)
481640235e2SEnji Cooper 		start = 1;
482640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex6));
483640235e2SEnji Cooper 
484640235e2SEnji Cooper 	return 0;
485640235e2SEnji Cooper }
486640235e2SEnji Cooper 
487640235e2SEnji Cooper ATF_TC(mutex6);
488640235e2SEnji Cooper ATF_TC_HEAD(mutex6, tc)
489640235e2SEnji Cooper {
490640235e2SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
491640235e2SEnji Cooper 	    "Checks scheduling for priority ceiling");
492640235e2SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
493640235e2SEnji Cooper }
494640235e2SEnji Cooper 
495640235e2SEnji Cooper /*
496640235e2SEnji Cooper  * 1. main thread sets itself to be a realtime task and launched two tasks,
497640235e2SEnji Cooper  *    one has higher priority and the other has lower priority.
498640235e2SEnji Cooper  * 2. each child thread(low and high priority thread) sets its scheduler and
499640235e2SEnji Cooper  *    priority.
500640235e2SEnji Cooper  * 3. each child thread did several rounds of computation, after each round it
501640235e2SEnji Cooper  *    sleep 1 second.
502640235e2SEnji Cooper  * 4. the child thread with low priority will call _sched_protect to increase
503640235e2SEnji Cooper  *    its protect priority.
504640235e2SEnji Cooper  * 5. We verify the thread with low priority runs first.
505640235e2SEnji Cooper  *
506640235e2SEnji Cooper  * Why does it work? From the main thread, we launched the high
507640235e2SEnji Cooper  * priority thread first. This gives this thread the benefit of
508640235e2SEnji Cooper  * starting first. The low priority thread did not call _sched_protect(2).
509640235e2SEnji Cooper  * The high priority thread should finish the task first. After each
510640235e2SEnji Cooper  * round of computation, we call sleep, to put the task into the
511640235e2SEnji Cooper  * sleep queue, and wake up again after the timer expires. This
512640235e2SEnji Cooper  * gives the scheduler the chance to decide which task to run. So,
513640235e2SEnji Cooper  * the thread with real high priority will always block the thread
514640235e2SEnji Cooper  * with real low priority.
515640235e2SEnji Cooper  *
516640235e2SEnji Cooper  */
517640235e2SEnji Cooper ATF_TC_BODY(mutex6, tc)
518640235e2SEnji Cooper {
519640235e2SEnji Cooper 	struct sched_param param;
520640235e2SEnji Cooper 	int res;
521640235e2SEnji Cooper 	pthread_t high, low;
522640235e2SEnji Cooper 
523640235e2SEnji Cooper 	min_fifo_prio = sched_get_priority_min(SCHED_FIFO);
524640235e2SEnji Cooper 	max_fifo_prio = sched_get_priority_max(SCHED_FIFO);
525640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
526640235e2SEnji Cooper 	printf("min_fifo_prio = %d, max_fifo_info = %d\n", min_fifo_prio,
527640235e2SEnji Cooper 	    max_fifo_prio);
528640235e2SEnji Cooper 
529640235e2SEnji Cooper 	param.sched_priority = min_fifo_prio;
530640235e2SEnji Cooper 	res = sched_setscheduler(getpid(), SCHED_FIFO, &param);
531640235e2SEnji Cooper 	printf("previous policy used = %d\n", res);
532640235e2SEnji Cooper 
533640235e2SEnji Cooper 	res = sched_getscheduler(getpid());
534640235e2SEnji Cooper 	ATF_REQUIRE_EQ(res, 1);
535640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_create(&high, NULL, high_prio, NULL));
536640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_create(&low, NULL, low_prio, NULL));
537640235e2SEnji Cooper 	sleep(5);
538640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_join(low, NULL));
539640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_join(high, NULL));
540640235e2SEnji Cooper 
541640235e2SEnji Cooper 	ATF_REQUIRE_EQ(start, 1);
542640235e2SEnji Cooper }
543640235e2SEnji Cooper #endif
544640235e2SEnji Cooper 
545640235e2SEnji Cooper ATF_TC(mutexattr1);
546640235e2SEnji Cooper ATF_TC_HEAD(mutexattr1, tc)
547640235e2SEnji Cooper {
548640235e2SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks mutexattr");
549640235e2SEnji Cooper }
550640235e2SEnji Cooper 
551640235e2SEnji Cooper ATF_TC_BODY(mutexattr1, tc)
552640235e2SEnji Cooper {
553640235e2SEnji Cooper 	pthread_mutexattr_t mattr;
554640235e2SEnji Cooper 	int protocol, target;
555640235e2SEnji Cooper 
556640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_init(&mattr));
557640235e2SEnji Cooper 
558640235e2SEnji Cooper 	target = PTHREAD_PRIO_NONE;
559640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_setprotocol(&mattr, target));
560640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_getprotocol(&mattr, &protocol));
561640235e2SEnji Cooper 	ATF_REQUIRE_EQ(protocol, target);
562640235e2SEnji Cooper 
563640235e2SEnji Cooper 	/*
564640235e2SEnji Cooper 	target = PTHREAD_PRIO_INHERIT;
565640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_setprotocol(&mattr, target));
566640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_getprotocol(&mattr, &protocol));
567640235e2SEnji Cooper 	ATF_REQUIRE_EQ(protocol, target);
568640235e2SEnji Cooper 	*/
569640235e2SEnji Cooper 
570640235e2SEnji Cooper 	target = PTHREAD_PRIO_PROTECT;
571640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_setprotocol(&mattr, target));
572640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_getprotocol(&mattr, &protocol));
573640235e2SEnji Cooper 	ATF_REQUIRE_EQ(protocol, target);
574640235e2SEnji Cooper }
575640235e2SEnji Cooper 
576640235e2SEnji Cooper ATF_TC(mutexattr2);
577640235e2SEnji Cooper ATF_TC_HEAD(mutexattr2, tc)
578640235e2SEnji Cooper {
579640235e2SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks mutexattr");
580640235e2SEnji Cooper }
581640235e2SEnji Cooper 
582640235e2SEnji Cooper ATF_TC_BODY(mutexattr2, tc)
583640235e2SEnji Cooper {
584640235e2SEnji Cooper 	pthread_mutexattr_t mattr;
585640235e2SEnji Cooper 
58682bc57c2SEnji Cooper #ifdef __FreeBSD__
58782bc57c2SEnji Cooper 	atf_tc_expect_fail("fails on i == 0 with: "
58882bc57c2SEnji Cooper 	    "pthread_mutexattr_setprioceiling(&mattr, i): Invalid argument "
58982bc57c2SEnji Cooper 	    "-- PR # 211802");
59082bc57c2SEnji Cooper #endif
59182bc57c2SEnji Cooper 
592640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_init(&mattr));
593640235e2SEnji Cooper 	int max_prio = sched_get_priority_max(SCHED_FIFO);
594640235e2SEnji Cooper 	int min_prio = sched_get_priority_min(SCHED_FIFO);
595640235e2SEnji Cooper 	for (int i = min_prio; i <= max_prio; i++) {
596640235e2SEnji Cooper 		int prioceiling;
59782bc57c2SEnji Cooper #ifdef __FreeBSD__
59882bc57c2SEnji Cooper 		int protocol;
59982bc57c2SEnji Cooper 
60082bc57c2SEnji Cooper 		PTHREAD_REQUIRE(pthread_mutexattr_getprotocol(&mattr,
60182bc57c2SEnji Cooper 		    &protocol));
60282bc57c2SEnji Cooper 
60382bc57c2SEnji Cooper 		printf("priority: %d\nprotocol: %d\n", i, protocol);
60482bc57c2SEnji Cooper #endif
605640235e2SEnji Cooper 		PTHREAD_REQUIRE(pthread_mutexattr_setprioceiling(&mattr, i));
606640235e2SEnji Cooper 		PTHREAD_REQUIRE(pthread_mutexattr_getprioceiling(&mattr,
607640235e2SEnji Cooper 		    &prioceiling));
60882bc57c2SEnji Cooper #ifdef __FreeBSD__
60982bc57c2SEnji Cooper 		printf("prioceiling: %d\n", prioceiling);
61082bc57c2SEnji Cooper #endif
611640235e2SEnji Cooper 		ATF_REQUIRE_EQ(i, prioceiling);
612640235e2SEnji Cooper 	}
613640235e2SEnji Cooper }
614640235e2SEnji Cooper 
615*cdebaff8SEnji Cooper #ifdef TIMEDMUTEX
616*cdebaff8SEnji Cooper ATF_TC(timedmutex1);
617*cdebaff8SEnji Cooper ATF_TC_HEAD(timedmutex1, tc)
618*cdebaff8SEnji Cooper {
619*cdebaff8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks timeout on selflock");
620*cdebaff8SEnji Cooper }
621*cdebaff8SEnji Cooper 
622*cdebaff8SEnji Cooper ATF_TC_BODY(timedmutex1, tc)
623*cdebaff8SEnji Cooper {
624*cdebaff8SEnji Cooper 
625*cdebaff8SEnji Cooper 	printf("Timed mutex-test 1\n");
626*cdebaff8SEnji Cooper 
627*cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
628*cdebaff8SEnji Cooper 
629*cdebaff8SEnji Cooper 	printf("Before acquiring mutex\n");
630*cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
631*cdebaff8SEnji Cooper 
632*cdebaff8SEnji Cooper 	printf("Before endeavor to reacquire timed-mutex (timeout expected)\n");
633*cdebaff8SEnji Cooper 	PTHREAD_REQUIRE_STATUS(mutex_lock(&mutex, &ts_shortlived),
634*cdebaff8SEnji Cooper 	    ETIMEDOUT);
635*cdebaff8SEnji Cooper 
636*cdebaff8SEnji Cooper 	printf("Unlocking mutex\n");
637*cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
638*cdebaff8SEnji Cooper }
639*cdebaff8SEnji Cooper 
640*cdebaff8SEnji Cooper ATF_TC(timedmutex2);
641*cdebaff8SEnji Cooper ATF_TC_HEAD(timedmutex2, tc)
642*cdebaff8SEnji Cooper {
643*cdebaff8SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
644*cdebaff8SEnji Cooper 	    "Checks timeout on selflock with timedlock");
645*cdebaff8SEnji Cooper }
646*cdebaff8SEnji Cooper 
647*cdebaff8SEnji Cooper ATF_TC_BODY(timedmutex2, tc)
648*cdebaff8SEnji Cooper {
649*cdebaff8SEnji Cooper 
650*cdebaff8SEnji Cooper 	printf("Timed mutex-test 2\n");
651*cdebaff8SEnji Cooper 
652*cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
653*cdebaff8SEnji Cooper 
654*cdebaff8SEnji Cooper 	printf("Before acquiring mutex with timedlock\n");
655*cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
656*cdebaff8SEnji Cooper 
657*cdebaff8SEnji Cooper 	printf("Before endeavor to reacquire timed-mutex (timeout expected)\n");
658*cdebaff8SEnji Cooper 	PTHREAD_REQUIRE_STATUS(mutex_lock(&mutex, &ts_shortlived),
659*cdebaff8SEnji Cooper 	    ETIMEDOUT);
660*cdebaff8SEnji Cooper 
661*cdebaff8SEnji Cooper 	printf("Unlocking mutex\n");
662*cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
663*cdebaff8SEnji Cooper }
664*cdebaff8SEnji Cooper 
665*cdebaff8SEnji Cooper ATF_TC(timedmutex3);
666*cdebaff8SEnji Cooper ATF_TC_HEAD(timedmutex3, tc)
667*cdebaff8SEnji Cooper {
668*cdebaff8SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
669*cdebaff8SEnji Cooper 	    "Checks timeout on selflock in a new thread");
670*cdebaff8SEnji Cooper }
671*cdebaff8SEnji Cooper 
672*cdebaff8SEnji Cooper static void *
673*cdebaff8SEnji Cooper timedmtx_thrdfunc(void *arg)
674*cdebaff8SEnji Cooper {
675*cdebaff8SEnji Cooper 	printf("Before endeavor to reacquire timed-mutex (timeout expected)\n");
676*cdebaff8SEnji Cooper 	PTHREAD_REQUIRE_STATUS(mutex_lock(&mutex, &ts_shortlived),
677*cdebaff8SEnji Cooper 	    ETIMEDOUT);
678*cdebaff8SEnji Cooper 
679*cdebaff8SEnji Cooper 	return NULL;
680*cdebaff8SEnji Cooper }
681*cdebaff8SEnji Cooper 
682*cdebaff8SEnji Cooper ATF_TC_BODY(timedmutex3, tc)
683*cdebaff8SEnji Cooper {
684*cdebaff8SEnji Cooper 	pthread_t new;
685*cdebaff8SEnji Cooper 
686*cdebaff8SEnji Cooper 	printf("Timed mutex-test 3\n");
687*cdebaff8SEnji Cooper 
688*cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
689*cdebaff8SEnji Cooper 
690*cdebaff8SEnji Cooper 	printf("Before acquiring mutex with timedlock\n");
691*cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
692*cdebaff8SEnji Cooper 
693*cdebaff8SEnji Cooper 	printf("Before creating new thread\n");
694*cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_create(&new, NULL, timedmtx_thrdfunc, NULL));
695*cdebaff8SEnji Cooper 
696*cdebaff8SEnji Cooper 	printf("Before joining the mutex\n");
697*cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_join(new, NULL));
698*cdebaff8SEnji Cooper 
699*cdebaff8SEnji Cooper 	printf("Unlocking mutex\n");
700*cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
701*cdebaff8SEnji Cooper }
702*cdebaff8SEnji Cooper 
703*cdebaff8SEnji Cooper ATF_TC(timedmutex4);
704*cdebaff8SEnji Cooper ATF_TC_HEAD(timedmutex4, tc)
705*cdebaff8SEnji Cooper {
706*cdebaff8SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
707*cdebaff8SEnji Cooper 	    "Checks timeout on selflock with timedlock in a new thread");
708*cdebaff8SEnji Cooper }
709*cdebaff8SEnji Cooper 
710*cdebaff8SEnji Cooper ATF_TC_BODY(timedmutex4, tc)
711*cdebaff8SEnji Cooper {
712*cdebaff8SEnji Cooper 	pthread_t new;
713*cdebaff8SEnji Cooper 
714*cdebaff8SEnji Cooper 	printf("Timed mutex-test 4\n");
715*cdebaff8SEnji Cooper 
716*cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
717*cdebaff8SEnji Cooper 
718*cdebaff8SEnji Cooper 	printf("Before acquiring mutex with timedlock\n");
719*cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
720*cdebaff8SEnji Cooper 
721*cdebaff8SEnji Cooper 	printf("Before creating new thread\n");
722*cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_create(&new, NULL, timedmtx_thrdfunc, NULL));
723*cdebaff8SEnji Cooper 
724*cdebaff8SEnji Cooper 	printf("Before joining the mutex\n");
725*cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_join(new, NULL));
726*cdebaff8SEnji Cooper 
727*cdebaff8SEnji Cooper 	printf("Unlocking mutex\n");
728*cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
729*cdebaff8SEnji Cooper }
730*cdebaff8SEnji Cooper #endif
731*cdebaff8SEnji Cooper 
73257718be8SEnji Cooper ATF_TP_ADD_TCS(tp)
73357718be8SEnji Cooper {
73457718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, mutex1);
73557718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, mutex2);
73657718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, mutex3);
73757718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, mutex4);
738640235e2SEnji Cooper #ifdef __NetBSD__
739640235e2SEnji Cooper 	ATF_TP_ADD_TC(tp, mutex5);
740640235e2SEnji Cooper 	ATF_TP_ADD_TC(tp, mutex6);
741640235e2SEnji Cooper #endif
742640235e2SEnji Cooper 	ATF_TP_ADD_TC(tp, mutexattr1);
743640235e2SEnji Cooper 	ATF_TP_ADD_TC(tp, mutexattr2);
74457718be8SEnji Cooper 
745*cdebaff8SEnji Cooper #ifdef TIMEDMUTEX
746*cdebaff8SEnji Cooper 	ATF_TP_ADD_TC(tp, timedmutex1);
747*cdebaff8SEnji Cooper 	ATF_TP_ADD_TC(tp, timedmutex2);
748*cdebaff8SEnji Cooper 	ATF_TP_ADD_TC(tp, timedmutex3);
749*cdebaff8SEnji Cooper 	ATF_TP_ADD_TC(tp, timedmutex4);
750*cdebaff8SEnji Cooper #endif
751*cdebaff8SEnji Cooper 
75257718be8SEnji Cooper 	return atf_no_error();
75357718be8SEnji Cooper }
754