xref: /freebsd/contrib/netbsd-tests/lib/libpthread/t_mutex.c (revision 3b0a9131e6cb4ada420cbfc4e2d89a04ca7ad384)
1*3b0a9131SEnji 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.");
32*3b0a9131SEnji 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>
3857718be8SEnji Cooper #include <string.h>
39640235e2SEnji Cooper #include <errno.h>
40cdebaff8SEnji Cooper #include <time.h>
4157718be8SEnji Cooper #include <unistd.h>
42640235e2SEnji Cooper #include <sys/sched.h>
43640235e2SEnji Cooper #include <sys/param.h>
4457718be8SEnji Cooper 
4557718be8SEnji Cooper #include <atf-c.h>
4657718be8SEnji Cooper 
4757718be8SEnji Cooper #include "h_common.h"
4857718be8SEnji Cooper 
4957718be8SEnji Cooper static pthread_mutex_t mutex;
5057718be8SEnji Cooper static pthread_mutex_t static_mutex = PTHREAD_MUTEX_INITIALIZER;
5157718be8SEnji Cooper static int global_x;
5257718be8SEnji Cooper 
53cdebaff8SEnji Cooper #ifdef TIMEDMUTEX
54cdebaff8SEnji Cooper /* This code is used for verifying non-timed specific code */
55cdebaff8SEnji Cooper static struct timespec ts_lengthy = {
56cdebaff8SEnji Cooper 	.tv_sec = UINT16_MAX,
57cdebaff8SEnji Cooper 	.tv_nsec = 0
58cdebaff8SEnji Cooper };
59cdebaff8SEnji Cooper /* This code is used for verifying timed-only specific code */
60cdebaff8SEnji Cooper static struct timespec ts_shortlived = {
61cdebaff8SEnji Cooper 	.tv_sec = 0,
62cdebaff8SEnji Cooper 	.tv_nsec = 120
63cdebaff8SEnji Cooper };
64cdebaff8SEnji Cooper 
65cdebaff8SEnji Cooper static int
66cdebaff8SEnji Cooper mutex_lock(pthread_mutex_t *m, const struct timespec *ts)
67cdebaff8SEnji Cooper {
68cdebaff8SEnji Cooper 	struct timespec ts_wait;
69cdebaff8SEnji Cooper 	ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &ts_wait) != -1);
70cdebaff8SEnji Cooper 	timespecadd(&ts_wait, ts, &ts_wait);
71cdebaff8SEnji Cooper 
72cdebaff8SEnji Cooper 	return pthread_mutex_timedlock(m, &ts_wait);
73cdebaff8SEnji Cooper }
74cdebaff8SEnji Cooper #else
75cdebaff8SEnji Cooper #define mutex_lock(a, b) pthread_mutex_lock(a)
76cdebaff8SEnji Cooper #endif
77cdebaff8SEnji Cooper 
7857718be8SEnji Cooper static void *
7957718be8SEnji Cooper mutex1_threadfunc(void *arg)
8057718be8SEnji Cooper {
8157718be8SEnji Cooper 	int *param;
8257718be8SEnji Cooper 
8357718be8SEnji Cooper 	printf("2: Second thread.\n");
8457718be8SEnji Cooper 
8557718be8SEnji Cooper 	param = arg;
8657718be8SEnji Cooper 	printf("2: Locking mutex\n");
87cdebaff8SEnji Cooper 	mutex_lock(&mutex, &ts_lengthy);
8857718be8SEnji Cooper 	printf("2: Got mutex. *param = %d\n", *param);
8957718be8SEnji Cooper 	ATF_REQUIRE_EQ(*param, 20);
9057718be8SEnji Cooper 	(*param)++;
9157718be8SEnji Cooper 
9257718be8SEnji Cooper 	pthread_mutex_unlock(&mutex);
9357718be8SEnji Cooper 
9457718be8SEnji Cooper 	return param;
9557718be8SEnji Cooper }
9657718be8SEnji Cooper 
9757718be8SEnji Cooper ATF_TC(mutex1);
9857718be8SEnji Cooper ATF_TC_HEAD(mutex1, tc)
9957718be8SEnji Cooper {
10057718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks mutexes");
10157718be8SEnji Cooper }
10257718be8SEnji Cooper ATF_TC_BODY(mutex1, tc)
10357718be8SEnji Cooper {
10457718be8SEnji Cooper 	int x;
10557718be8SEnji Cooper 	pthread_t new;
10657718be8SEnji Cooper 	void *joinval;
10757718be8SEnji Cooper 
10857718be8SEnji Cooper 	printf("1: Mutex-test 1\n");
10957718be8SEnji Cooper 
11057718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
11157718be8SEnji Cooper 	x = 1;
112cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
11357718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex1_threadfunc, &x));
11457718be8SEnji Cooper 	printf("1: Before changing the value.\n");
11557718be8SEnji Cooper 	sleep(2);
11657718be8SEnji Cooper 	x = 20;
11757718be8SEnji Cooper 	printf("1: Before releasing the mutex.\n");
11857718be8SEnji Cooper 	sleep(2);
11957718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
12057718be8SEnji Cooper 	printf("1: After releasing the mutex.\n");
12157718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_join(new, &joinval));
12257718be8SEnji Cooper 
123cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
12457718be8SEnji Cooper 	printf("1: Thread joined. X was %d. Return value (int) was %d\n",
12557718be8SEnji Cooper 		x, *(int *)joinval);
12657718be8SEnji Cooper 	ATF_REQUIRE_EQ(x, 21);
12757718be8SEnji Cooper 	ATF_REQUIRE_EQ(*(int *)joinval, 21);
12857718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
12957718be8SEnji Cooper }
13057718be8SEnji Cooper 
13157718be8SEnji Cooper static void *
13257718be8SEnji Cooper mutex2_threadfunc(void *arg)
13357718be8SEnji Cooper {
13457718be8SEnji Cooper 	long count = *(int *)arg;
13557718be8SEnji Cooper 
13657718be8SEnji Cooper 	printf("2: Second thread (%p). Count is %ld\n", pthread_self(), count);
13757718be8SEnji Cooper 
13857718be8SEnji Cooper 	while (count--) {
139cdebaff8SEnji Cooper 		PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
14057718be8SEnji Cooper 		global_x++;
14157718be8SEnji Cooper 		PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
14257718be8SEnji Cooper 	}
14357718be8SEnji Cooper 
14457718be8SEnji Cooper 	return (void *)count;
14557718be8SEnji Cooper }
14657718be8SEnji Cooper 
14757718be8SEnji Cooper ATF_TC(mutex2);
14857718be8SEnji Cooper ATF_TC_HEAD(mutex2, tc)
14957718be8SEnji Cooper {
15057718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks mutexes");
151190e1b1cSEnji Cooper #ifdef __NetBSD__
15257718be8SEnji Cooper #if defined(__powerpc__)
15357718be8SEnji Cooper 	atf_tc_set_md_var(tc, "timeout", "40");
15457718be8SEnji Cooper #endif
155190e1b1cSEnji Cooper #endif
15657718be8SEnji Cooper }
15757718be8SEnji Cooper ATF_TC_BODY(mutex2, tc)
15857718be8SEnji Cooper {
15957718be8SEnji Cooper 	int count, count2;
16057718be8SEnji Cooper 	pthread_t new;
16157718be8SEnji Cooper 	void *joinval;
16257718be8SEnji Cooper 
16357718be8SEnji Cooper 	printf("1: Mutex-test 2\n");
16457718be8SEnji Cooper 
165190e1b1cSEnji Cooper #ifdef __NetBSD__
16657718be8SEnji Cooper #if defined(__powerpc__)
16757718be8SEnji Cooper 	atf_tc_expect_timeout("PR port-powerpc/44387");
16857718be8SEnji Cooper #endif
169190e1b1cSEnji Cooper #endif
17057718be8SEnji Cooper 
17157718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
17257718be8SEnji Cooper 
17357718be8SEnji Cooper 	global_x = 0;
17457718be8SEnji Cooper 	count = count2 = 10000000;
17557718be8SEnji Cooper 
176cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
17757718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex2_threadfunc, &count2));
17857718be8SEnji Cooper 
17957718be8SEnji Cooper 	printf("1: Thread %p\n", pthread_self());
18057718be8SEnji Cooper 
18157718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
18257718be8SEnji Cooper 
18357718be8SEnji Cooper 	while (count--) {
184cdebaff8SEnji Cooper 		PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
18557718be8SEnji Cooper 		global_x++;
18657718be8SEnji Cooper 		PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
18757718be8SEnji Cooper 	}
18857718be8SEnji Cooper 
18957718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_join(new, &joinval));
19057718be8SEnji Cooper 
191cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
19257718be8SEnji Cooper 	printf("1: Thread joined. X was %d. Return value (long) was %ld\n",
19357718be8SEnji Cooper 		global_x, (long)joinval);
19457718be8SEnji Cooper 	ATF_REQUIRE_EQ(global_x, 20000000);
19557718be8SEnji Cooper 
196190e1b1cSEnji Cooper #ifdef __NetBSD__
19757718be8SEnji Cooper #if defined(__powerpc__)
19857718be8SEnji Cooper 	/* XXX force a timeout in ppc case since an un-triggered race
19957718be8SEnji Cooper 	   otherwise looks like a "failure" */
20057718be8SEnji Cooper 	/* We sleep for longer than the timeout to make ATF not
20157718be8SEnji Cooper 	   complain about unexpected success */
20257718be8SEnji Cooper 	sleep(41);
20357718be8SEnji Cooper #endif
204190e1b1cSEnji Cooper #endif
20557718be8SEnji Cooper }
20657718be8SEnji Cooper 
20757718be8SEnji Cooper static void *
20857718be8SEnji Cooper mutex3_threadfunc(void *arg)
20957718be8SEnji Cooper {
21057718be8SEnji Cooper 	long count = *(int *)arg;
21157718be8SEnji Cooper 
21257718be8SEnji Cooper 	printf("2: Second thread (%p). Count is %ld\n", pthread_self(), count);
21357718be8SEnji Cooper 
21457718be8SEnji Cooper 	while (count--) {
215cdebaff8SEnji Cooper 		PTHREAD_REQUIRE(mutex_lock(&static_mutex, &ts_lengthy));
21657718be8SEnji Cooper 		global_x++;
21757718be8SEnji Cooper 		PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
21857718be8SEnji Cooper 	}
21957718be8SEnji Cooper 
22057718be8SEnji Cooper 	return (void *)count;
22157718be8SEnji Cooper }
22257718be8SEnji Cooper 
22357718be8SEnji Cooper ATF_TC(mutex3);
22457718be8SEnji Cooper ATF_TC_HEAD(mutex3, tc)
22557718be8SEnji Cooper {
22657718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks mutexes using a static "
22757718be8SEnji Cooper 	    "initializer");
228190e1b1cSEnji Cooper #ifdef __NetBSD__
22957718be8SEnji Cooper #if defined(__powerpc__)
23057718be8SEnji Cooper 	atf_tc_set_md_var(tc, "timeout", "40");
23157718be8SEnji Cooper #endif
232190e1b1cSEnji Cooper #endif
23357718be8SEnji Cooper }
23457718be8SEnji Cooper ATF_TC_BODY(mutex3, tc)
23557718be8SEnji Cooper {
23657718be8SEnji Cooper 	int count, count2;
23757718be8SEnji Cooper 	pthread_t new;
23857718be8SEnji Cooper 	void *joinval;
23957718be8SEnji Cooper 
24057718be8SEnji Cooper 	printf("1: Mutex-test 3\n");
24157718be8SEnji Cooper 
242190e1b1cSEnji Cooper #ifdef __NetBSD__
24357718be8SEnji Cooper #if defined(__powerpc__)
24457718be8SEnji Cooper 	atf_tc_expect_timeout("PR port-powerpc/44387");
24557718be8SEnji Cooper #endif
246190e1b1cSEnji Cooper #endif
24757718be8SEnji Cooper 
24857718be8SEnji Cooper 	global_x = 0;
24957718be8SEnji Cooper 	count = count2 = 10000000;
25057718be8SEnji Cooper 
251cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&static_mutex, &ts_lengthy));
25257718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex3_threadfunc, &count2));
25357718be8SEnji Cooper 
25457718be8SEnji Cooper 	printf("1: Thread %p\n", pthread_self());
25557718be8SEnji Cooper 
25657718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
25757718be8SEnji Cooper 
25857718be8SEnji Cooper 	while (count--) {
259cdebaff8SEnji Cooper 		PTHREAD_REQUIRE(mutex_lock(&static_mutex, &ts_lengthy));
26057718be8SEnji Cooper 		global_x++;
26157718be8SEnji Cooper 		PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
26257718be8SEnji Cooper 	}
26357718be8SEnji Cooper 
26457718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_join(new, &joinval));
26557718be8SEnji Cooper 
266cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&static_mutex, &ts_lengthy));
26757718be8SEnji Cooper 	printf("1: Thread joined. X was %d. Return value (long) was %ld\n",
26857718be8SEnji Cooper 		global_x, (long)joinval);
26957718be8SEnji Cooper 	ATF_REQUIRE_EQ(global_x, 20000000);
27057718be8SEnji Cooper 
271190e1b1cSEnji Cooper #ifdef __NetBSD__
27257718be8SEnji Cooper #if defined(__powerpc__)
27357718be8SEnji Cooper 	/* XXX force a timeout in ppc case since an un-triggered race
27457718be8SEnji Cooper 	   otherwise looks like a "failure" */
27557718be8SEnji Cooper 	/* We sleep for longer than the timeout to make ATF not
27657718be8SEnji Cooper 	   complain about unexpected success */
27757718be8SEnji Cooper 	sleep(41);
27857718be8SEnji Cooper #endif
279190e1b1cSEnji Cooper #endif
28057718be8SEnji Cooper }
28157718be8SEnji Cooper 
28257718be8SEnji Cooper static void *
28357718be8SEnji Cooper mutex4_threadfunc(void *arg)
28457718be8SEnji Cooper {
28557718be8SEnji Cooper 	int *param;
28657718be8SEnji Cooper 
28757718be8SEnji Cooper 	printf("2: Second thread.\n");
28857718be8SEnji Cooper 
28957718be8SEnji Cooper 	param = arg;
29057718be8SEnji Cooper 	printf("2: Locking mutex\n");
291cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
29257718be8SEnji Cooper 	printf("2: Got mutex. *param = %d\n", *param);
29357718be8SEnji Cooper 	(*param)++;
29457718be8SEnji Cooper 
29557718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
29657718be8SEnji Cooper 
29757718be8SEnji Cooper 	return param;
29857718be8SEnji Cooper }
29957718be8SEnji Cooper 
30057718be8SEnji Cooper ATF_TC(mutex4);
30157718be8SEnji Cooper ATF_TC_HEAD(mutex4, tc)
30257718be8SEnji Cooper {
30357718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks mutexes");
30457718be8SEnji Cooper }
30557718be8SEnji Cooper ATF_TC_BODY(mutex4, tc)
30657718be8SEnji Cooper {
30757718be8SEnji Cooper 	int x;
30857718be8SEnji Cooper 	pthread_t new;
30957718be8SEnji Cooper 	pthread_mutexattr_t mattr;
31057718be8SEnji Cooper 	void *joinval;
31157718be8SEnji Cooper 
31257718be8SEnji Cooper 	printf("1: Mutex-test 4\n");
31357718be8SEnji Cooper 
31457718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_init(&mattr));
31557718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE));
31657718be8SEnji Cooper 
31757718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, &mattr));
31857718be8SEnji Cooper 
31957718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_destroy(&mattr));
32057718be8SEnji Cooper 
32157718be8SEnji Cooper 	x = 1;
322cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
32357718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex4_threadfunc, &x));
32457718be8SEnji Cooper 
32557718be8SEnji Cooper 	printf("1: Before recursively acquiring the mutex.\n");
326cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
32757718be8SEnji Cooper 
32857718be8SEnji Cooper 	printf("1: Before releasing the mutex once.\n");
32957718be8SEnji Cooper 	sleep(2);
33057718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
33157718be8SEnji Cooper 	printf("1: After releasing the mutex once.\n");
33257718be8SEnji Cooper 
33357718be8SEnji Cooper 	x = 20;
33457718be8SEnji Cooper 
33557718be8SEnji Cooper 	printf("1: Before releasing the mutex twice.\n");
33657718be8SEnji Cooper 	sleep(2);
33757718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
33857718be8SEnji Cooper 	printf("1: After releasing the mutex twice.\n");
33957718be8SEnji Cooper 
34057718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_join(new, &joinval));
34157718be8SEnji Cooper 
342cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
34357718be8SEnji Cooper 	printf("1: Thread joined. X was %d. Return value (int) was %d\n",
34457718be8SEnji Cooper 		x, *(int *)joinval);
34557718be8SEnji Cooper 	ATF_REQUIRE_EQ(x, 21);
34657718be8SEnji Cooper 	ATF_REQUIRE_EQ(*(int *)joinval, 21);
34757718be8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
34857718be8SEnji Cooper }
34957718be8SEnji Cooper 
350640235e2SEnji Cooper #ifdef __NetBSD__
351640235e2SEnji Cooper static pthread_mutexattr_t attr5;
352640235e2SEnji Cooper static pthread_mutex_t mutex5;
353640235e2SEnji Cooper static int min_fifo_prio, max_fifo_prio;
354640235e2SEnji Cooper 
355640235e2SEnji Cooper static void *
356640235e2SEnji Cooper child_func(void* arg)
357640235e2SEnji Cooper {
358640235e2SEnji Cooper 	int res;
359640235e2SEnji Cooper 
360640235e2SEnji Cooper 	printf("child is waiting\n");
361640235e2SEnji Cooper 	res = _sched_protect(-2);
362640235e2SEnji Cooper 	ATF_REQUIRE_EQ_MSG(res, -1, "sched_protect returned %d", res);
363640235e2SEnji Cooper 	ATF_REQUIRE_EQ(errno, ENOENT);
364cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex5, &ts_lengthy));
365640235e2SEnji Cooper 	printf("child is owning resource\n");
366640235e2SEnji Cooper 	res = _sched_protect(-2);
367640235e2SEnji Cooper 	ATF_REQUIRE_EQ(res,  max_fifo_prio);
368640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex5));
369640235e2SEnji Cooper 	printf("child is done\n");
370640235e2SEnji Cooper 
371640235e2SEnji Cooper 	return 0;
372640235e2SEnji Cooper }
373640235e2SEnji Cooper 
374640235e2SEnji Cooper ATF_TC(mutex5);
375640235e2SEnji Cooper ATF_TC_HEAD(mutex5, tc)
376640235e2SEnji Cooper {
377640235e2SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks mutexes for priority setting");
378640235e2SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
379640235e2SEnji Cooper }
380640235e2SEnji Cooper 
381640235e2SEnji Cooper ATF_TC_BODY(mutex5, tc)
382640235e2SEnji Cooper {
383640235e2SEnji Cooper 	int res;
384640235e2SEnji Cooper 	struct sched_param param;
385640235e2SEnji Cooper 	pthread_t child;
386640235e2SEnji Cooper 
387640235e2SEnji Cooper 	min_fifo_prio = sched_get_priority_min(SCHED_FIFO);
388640235e2SEnji Cooper 	max_fifo_prio = sched_get_priority_max(SCHED_FIFO);
389640235e2SEnji Cooper 	printf("min prio for FIFO = %d\n", min_fifo_prio);
390640235e2SEnji Cooper 	param.sched_priority = min_fifo_prio;
391640235e2SEnji Cooper 
392640235e2SEnji Cooper 	/* = 0 OTHER, 1 FIFO, 2 RR, -1 NONE */
393640235e2SEnji Cooper 	res = sched_setscheduler(getpid(), SCHED_FIFO, &param);
394640235e2SEnji Cooper 	printf("previous policy used = %d\n", res);
395640235e2SEnji Cooper 
396640235e2SEnji Cooper 	res = sched_getscheduler(getpid());
397640235e2SEnji Cooper 	ATF_REQUIRE_EQ_MSG(res, SCHED_FIFO, "sched %d != FIFO %d", res,
398640235e2SEnji Cooper 	    SCHED_FIFO);
399640235e2SEnji Cooper 
400640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_init(&attr5));
401640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_setprotocol(&attr5,
402640235e2SEnji Cooper 	    PTHREAD_PRIO_PROTECT));
403640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_setprioceiling(&attr5,
404640235e2SEnji Cooper 	    max_fifo_prio));
405640235e2SEnji Cooper 
406640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_init(&mutex5, &attr5));
407cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex5, &ts_lengthy));
408640235e2SEnji Cooper 	printf("enter critical section for main\n");
409640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_create(&child, NULL, child_func, NULL));
410640235e2SEnji Cooper 	printf("main starts to sleep\n");
411640235e2SEnji Cooper 	sleep(10);
412640235e2SEnji Cooper 	printf("main completes\n");
413640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex5));
414640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_join(child, NULL));
415640235e2SEnji Cooper }
416640235e2SEnji Cooper 
417640235e2SEnji Cooper static pthread_mutex_t mutex6;
418640235e2SEnji Cooper static int start = 0;
419640235e2SEnji Cooper static uintmax_t high_cnt = 0, low_cnt = 0, MAX_LOOP = 100000000;
420640235e2SEnji Cooper 
421640235e2SEnji Cooper static void *
422640235e2SEnji Cooper high_prio(void* arg)
423640235e2SEnji Cooper {
424640235e2SEnji Cooper 	struct sched_param param;
425640235e2SEnji Cooper 	int policy;
426640235e2SEnji Cooper 	param.sched_priority = min_fifo_prio + 10;
427640235e2SEnji Cooper 	pthread_t childid = pthread_self();
428640235e2SEnji Cooper 
429640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_setschedparam(childid, 1, &param));
430640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_getschedparam(childid, &policy, &param));
431640235e2SEnji Cooper 	printf("high protect = %d, prio = %d\n",
432640235e2SEnji Cooper 	    _sched_protect(-2), param.sched_priority);
433640235e2SEnji Cooper 	ATF_REQUIRE_EQ(policy, 1);
434640235e2SEnji Cooper 	printf("high prio = %d\n", param.sched_priority);
435640235e2SEnji Cooper 	sleep(1);
436640235e2SEnji Cooper 	long tmp = 0;
437640235e2SEnji Cooper 	for (int i = 0; i < 20; i++) {
438640235e2SEnji Cooper 		while (high_cnt < MAX_LOOP) {
439640235e2SEnji Cooper 			tmp += (123456789 % 1234) * (987654321 % 54321);
440640235e2SEnji Cooper 			high_cnt += 1;
441640235e2SEnji Cooper 		}
442640235e2SEnji Cooper 		high_cnt = 0;
443640235e2SEnji Cooper 		sleep(1);
444640235e2SEnji Cooper 	}
445cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex6, &ts_lengthy));
446640235e2SEnji Cooper 	if (start == 0) start = 2;
447640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex6));
448640235e2SEnji Cooper 
449640235e2SEnji Cooper 	return 0;
450640235e2SEnji Cooper }
451640235e2SEnji Cooper 
452640235e2SEnji Cooper static void *
453640235e2SEnji Cooper low_prio(void* arg)
454640235e2SEnji Cooper {
455640235e2SEnji Cooper 	struct sched_param param;
456640235e2SEnji Cooper 	int policy;
457640235e2SEnji Cooper 	param.sched_priority = min_fifo_prio;
458640235e2SEnji Cooper 	pthread_t childid = pthread_self();
459640235e2SEnji Cooper 	int res = _sched_protect(max_fifo_prio);
460640235e2SEnji Cooper 	ATF_REQUIRE_EQ(res, 0);
461640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_setschedparam(childid, 1, &param));
462640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_getschedparam(childid, &policy, &param));
463640235e2SEnji Cooper 	printf("low protect = %d, prio = %d\n", _sched_protect(-2),
464640235e2SEnji Cooper 	    param.sched_priority);
465640235e2SEnji Cooper 	ATF_REQUIRE_EQ(policy, 1);
466640235e2SEnji Cooper 	printf("low prio = %d\n", param.sched_priority);
467640235e2SEnji Cooper 	sleep(1);
468640235e2SEnji Cooper 	long tmp = 0;
469640235e2SEnji Cooper 	for (int i = 0; i < 20; i++) {
470640235e2SEnji Cooper 		while (low_cnt < MAX_LOOP) {
471640235e2SEnji Cooper 			tmp += (123456789 % 1234) * (987654321 % 54321);
472640235e2SEnji Cooper 			low_cnt += 1;
473640235e2SEnji Cooper 		}
474640235e2SEnji Cooper 		low_cnt = 0;
475640235e2SEnji Cooper 		sleep(1);
476640235e2SEnji Cooper 	}
477cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex6, &ts_lengthy));
478640235e2SEnji Cooper 	if (start == 0)
479640235e2SEnji Cooper 		start = 1;
480640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex6));
481640235e2SEnji Cooper 
482640235e2SEnji Cooper 	return 0;
483640235e2SEnji Cooper }
484640235e2SEnji Cooper 
485640235e2SEnji Cooper ATF_TC(mutex6);
486640235e2SEnji Cooper ATF_TC_HEAD(mutex6, tc)
487640235e2SEnji Cooper {
488640235e2SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
489640235e2SEnji Cooper 	    "Checks scheduling for priority ceiling");
490640235e2SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
491640235e2SEnji Cooper }
492640235e2SEnji Cooper 
493640235e2SEnji Cooper /*
494640235e2SEnji Cooper  * 1. main thread sets itself to be a realtime task and launched two tasks,
495640235e2SEnji Cooper  *    one has higher priority and the other has lower priority.
496640235e2SEnji Cooper  * 2. each child thread(low and high priority thread) sets its scheduler and
497640235e2SEnji Cooper  *    priority.
498640235e2SEnji Cooper  * 3. each child thread did several rounds of computation, after each round it
499640235e2SEnji Cooper  *    sleep 1 second.
500640235e2SEnji Cooper  * 4. the child thread with low priority will call _sched_protect to increase
501640235e2SEnji Cooper  *    its protect priority.
502640235e2SEnji Cooper  * 5. We verify the thread with low priority runs first.
503640235e2SEnji Cooper  *
504640235e2SEnji Cooper  * Why does it work? From the main thread, we launched the high
505640235e2SEnji Cooper  * priority thread first. This gives this thread the benefit of
506640235e2SEnji Cooper  * starting first. The low priority thread did not call _sched_protect(2).
507640235e2SEnji Cooper  * The high priority thread should finish the task first. After each
508640235e2SEnji Cooper  * round of computation, we call sleep, to put the task into the
509640235e2SEnji Cooper  * sleep queue, and wake up again after the timer expires. This
510640235e2SEnji Cooper  * gives the scheduler the chance to decide which task to run. So,
511640235e2SEnji Cooper  * the thread with real high priority will always block the thread
512640235e2SEnji Cooper  * with real low priority.
513640235e2SEnji Cooper  *
514640235e2SEnji Cooper  */
515640235e2SEnji Cooper ATF_TC_BODY(mutex6, tc)
516640235e2SEnji Cooper {
517640235e2SEnji Cooper 	struct sched_param param;
518640235e2SEnji Cooper 	int res;
519640235e2SEnji Cooper 	pthread_t high, low;
520640235e2SEnji Cooper 
521640235e2SEnji Cooper 	min_fifo_prio = sched_get_priority_min(SCHED_FIFO);
522640235e2SEnji Cooper 	max_fifo_prio = sched_get_priority_max(SCHED_FIFO);
523640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
524640235e2SEnji Cooper 	printf("min_fifo_prio = %d, max_fifo_info = %d\n", min_fifo_prio,
525640235e2SEnji Cooper 	    max_fifo_prio);
526640235e2SEnji Cooper 
527640235e2SEnji Cooper 	param.sched_priority = min_fifo_prio;
528640235e2SEnji Cooper 	res = sched_setscheduler(getpid(), SCHED_FIFO, &param);
529640235e2SEnji Cooper 	printf("previous policy used = %d\n", res);
530640235e2SEnji Cooper 
531640235e2SEnji Cooper 	res = sched_getscheduler(getpid());
532640235e2SEnji Cooper 	ATF_REQUIRE_EQ(res, 1);
533640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_create(&high, NULL, high_prio, NULL));
534640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_create(&low, NULL, low_prio, NULL));
535640235e2SEnji Cooper 	sleep(5);
536640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_join(low, NULL));
537640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_join(high, NULL));
538640235e2SEnji Cooper 
539640235e2SEnji Cooper 	ATF_REQUIRE_EQ(start, 1);
540640235e2SEnji Cooper }
541640235e2SEnji Cooper #endif
542640235e2SEnji Cooper 
543640235e2SEnji Cooper ATF_TC(mutexattr1);
544640235e2SEnji Cooper ATF_TC_HEAD(mutexattr1, tc)
545640235e2SEnji Cooper {
546640235e2SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks mutexattr");
547640235e2SEnji Cooper }
548640235e2SEnji Cooper 
549640235e2SEnji Cooper ATF_TC_BODY(mutexattr1, tc)
550640235e2SEnji Cooper {
551640235e2SEnji Cooper 	pthread_mutexattr_t mattr;
552640235e2SEnji Cooper 	int protocol, target;
553640235e2SEnji Cooper 
554640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_init(&mattr));
555640235e2SEnji Cooper 
556640235e2SEnji Cooper 	target = PTHREAD_PRIO_NONE;
557640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_setprotocol(&mattr, target));
558640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_getprotocol(&mattr, &protocol));
559640235e2SEnji Cooper 	ATF_REQUIRE_EQ(protocol, target);
560640235e2SEnji Cooper 
561640235e2SEnji Cooper 	/*
562640235e2SEnji Cooper 	target = PTHREAD_PRIO_INHERIT;
563640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_setprotocol(&mattr, target));
564640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_getprotocol(&mattr, &protocol));
565640235e2SEnji Cooper 	ATF_REQUIRE_EQ(protocol, target);
566640235e2SEnji Cooper 	*/
567640235e2SEnji Cooper 
568640235e2SEnji Cooper 	target = PTHREAD_PRIO_PROTECT;
569640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_setprotocol(&mattr, target));
570640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_getprotocol(&mattr, &protocol));
571640235e2SEnji Cooper 	ATF_REQUIRE_EQ(protocol, target);
572640235e2SEnji Cooper }
573640235e2SEnji Cooper 
574640235e2SEnji Cooper ATF_TC(mutexattr2);
575640235e2SEnji Cooper ATF_TC_HEAD(mutexattr2, tc)
576640235e2SEnji Cooper {
577640235e2SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks mutexattr");
578640235e2SEnji Cooper }
579640235e2SEnji Cooper 
580640235e2SEnji Cooper ATF_TC_BODY(mutexattr2, tc)
581640235e2SEnji Cooper {
582640235e2SEnji Cooper 	pthread_mutexattr_t mattr;
583640235e2SEnji Cooper 
58482bc57c2SEnji Cooper #ifdef __FreeBSD__
58582bc57c2SEnji Cooper 	atf_tc_expect_fail("fails on i == 0 with: "
58682bc57c2SEnji Cooper 	    "pthread_mutexattr_setprioceiling(&mattr, i): Invalid argument "
58782bc57c2SEnji Cooper 	    "-- PR # 211802");
58882bc57c2SEnji Cooper #endif
58982bc57c2SEnji Cooper 
590640235e2SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutexattr_init(&mattr));
591640235e2SEnji Cooper 	int max_prio = sched_get_priority_max(SCHED_FIFO);
592640235e2SEnji Cooper 	int min_prio = sched_get_priority_min(SCHED_FIFO);
593640235e2SEnji Cooper 	for (int i = min_prio; i <= max_prio; i++) {
594640235e2SEnji Cooper 		int prioceiling;
59582bc57c2SEnji Cooper 		int protocol;
59682bc57c2SEnji Cooper 
59782bc57c2SEnji Cooper 		PTHREAD_REQUIRE(pthread_mutexattr_getprotocol(&mattr,
59882bc57c2SEnji Cooper 		    &protocol));
59982bc57c2SEnji Cooper 
60082bc57c2SEnji Cooper 		printf("priority: %d\nprotocol: %d\n", i, protocol);
601640235e2SEnji Cooper 		PTHREAD_REQUIRE(pthread_mutexattr_setprioceiling(&mattr, i));
602640235e2SEnji Cooper 		PTHREAD_REQUIRE(pthread_mutexattr_getprioceiling(&mattr,
603640235e2SEnji Cooper 		    &prioceiling));
60482bc57c2SEnji Cooper 		printf("prioceiling: %d\n", prioceiling);
605640235e2SEnji Cooper 		ATF_REQUIRE_EQ(i, prioceiling);
606640235e2SEnji Cooper 	}
607640235e2SEnji Cooper }
608640235e2SEnji Cooper 
609cdebaff8SEnji Cooper #ifdef TIMEDMUTEX
610cdebaff8SEnji Cooper ATF_TC(timedmutex1);
611cdebaff8SEnji Cooper ATF_TC_HEAD(timedmutex1, tc)
612cdebaff8SEnji Cooper {
613cdebaff8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks timeout on selflock");
614cdebaff8SEnji Cooper }
615cdebaff8SEnji Cooper 
616cdebaff8SEnji Cooper ATF_TC_BODY(timedmutex1, tc)
617cdebaff8SEnji Cooper {
618cdebaff8SEnji Cooper 
619cdebaff8SEnji Cooper 	printf("Timed mutex-test 1\n");
620cdebaff8SEnji Cooper 
621cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
622cdebaff8SEnji Cooper 
623cdebaff8SEnji Cooper 	printf("Before acquiring mutex\n");
624cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
625cdebaff8SEnji Cooper 
626cdebaff8SEnji Cooper 	printf("Before endeavor to reacquire timed-mutex (timeout expected)\n");
627cdebaff8SEnji Cooper 	PTHREAD_REQUIRE_STATUS(mutex_lock(&mutex, &ts_shortlived),
628cdebaff8SEnji Cooper 	    ETIMEDOUT);
629cdebaff8SEnji Cooper 
630cdebaff8SEnji Cooper 	printf("Unlocking mutex\n");
631cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
632cdebaff8SEnji Cooper }
633cdebaff8SEnji Cooper 
634cdebaff8SEnji Cooper ATF_TC(timedmutex2);
635cdebaff8SEnji Cooper ATF_TC_HEAD(timedmutex2, tc)
636cdebaff8SEnji Cooper {
637cdebaff8SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
638cdebaff8SEnji Cooper 	    "Checks timeout on selflock with timedlock");
639cdebaff8SEnji Cooper }
640cdebaff8SEnji Cooper 
641cdebaff8SEnji Cooper ATF_TC_BODY(timedmutex2, tc)
642cdebaff8SEnji Cooper {
643cdebaff8SEnji Cooper 
644cdebaff8SEnji Cooper 	printf("Timed mutex-test 2\n");
645cdebaff8SEnji Cooper 
646cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
647cdebaff8SEnji Cooper 
648cdebaff8SEnji Cooper 	printf("Before acquiring mutex with timedlock\n");
649cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
650cdebaff8SEnji Cooper 
651cdebaff8SEnji Cooper 	printf("Before endeavor to reacquire timed-mutex (timeout expected)\n");
652cdebaff8SEnji Cooper 	PTHREAD_REQUIRE_STATUS(mutex_lock(&mutex, &ts_shortlived),
653cdebaff8SEnji Cooper 	    ETIMEDOUT);
654cdebaff8SEnji Cooper 
655cdebaff8SEnji Cooper 	printf("Unlocking mutex\n");
656cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
657cdebaff8SEnji Cooper }
658cdebaff8SEnji Cooper 
659cdebaff8SEnji Cooper ATF_TC(timedmutex3);
660cdebaff8SEnji Cooper ATF_TC_HEAD(timedmutex3, tc)
661cdebaff8SEnji Cooper {
662cdebaff8SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
663cdebaff8SEnji Cooper 	    "Checks timeout on selflock in a new thread");
664cdebaff8SEnji Cooper }
665cdebaff8SEnji Cooper 
666cdebaff8SEnji Cooper static void *
667cdebaff8SEnji Cooper timedmtx_thrdfunc(void *arg)
668cdebaff8SEnji Cooper {
669cdebaff8SEnji Cooper 	printf("Before endeavor to reacquire timed-mutex (timeout expected)\n");
670cdebaff8SEnji Cooper 	PTHREAD_REQUIRE_STATUS(mutex_lock(&mutex, &ts_shortlived),
671cdebaff8SEnji Cooper 	    ETIMEDOUT);
672cdebaff8SEnji Cooper 
673cdebaff8SEnji Cooper 	return NULL;
674cdebaff8SEnji Cooper }
675cdebaff8SEnji Cooper 
676cdebaff8SEnji Cooper ATF_TC_BODY(timedmutex3, tc)
677cdebaff8SEnji Cooper {
678cdebaff8SEnji Cooper 	pthread_t new;
679cdebaff8SEnji Cooper 
680cdebaff8SEnji Cooper 	printf("Timed mutex-test 3\n");
681cdebaff8SEnji Cooper 
682cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
683cdebaff8SEnji Cooper 
684cdebaff8SEnji Cooper 	printf("Before acquiring mutex with timedlock\n");
685cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
686cdebaff8SEnji Cooper 
687cdebaff8SEnji Cooper 	printf("Before creating new thread\n");
688cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_create(&new, NULL, timedmtx_thrdfunc, NULL));
689cdebaff8SEnji Cooper 
690cdebaff8SEnji Cooper 	printf("Before joining the mutex\n");
691cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_join(new, NULL));
692cdebaff8SEnji Cooper 
693cdebaff8SEnji Cooper 	printf("Unlocking mutex\n");
694cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
695cdebaff8SEnji Cooper }
696cdebaff8SEnji Cooper 
697cdebaff8SEnji Cooper ATF_TC(timedmutex4);
698cdebaff8SEnji Cooper ATF_TC_HEAD(timedmutex4, tc)
699cdebaff8SEnji Cooper {
700cdebaff8SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
701cdebaff8SEnji Cooper 	    "Checks timeout on selflock with timedlock in a new thread");
702cdebaff8SEnji Cooper }
703cdebaff8SEnji Cooper 
704cdebaff8SEnji Cooper ATF_TC_BODY(timedmutex4, tc)
705cdebaff8SEnji Cooper {
706cdebaff8SEnji Cooper 	pthread_t new;
707cdebaff8SEnji Cooper 
708cdebaff8SEnji Cooper 	printf("Timed mutex-test 4\n");
709cdebaff8SEnji Cooper 
710cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
711cdebaff8SEnji Cooper 
712cdebaff8SEnji Cooper 	printf("Before acquiring mutex with timedlock\n");
713cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
714cdebaff8SEnji Cooper 
715cdebaff8SEnji Cooper 	printf("Before creating new thread\n");
716cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_create(&new, NULL, timedmtx_thrdfunc, NULL));
717cdebaff8SEnji Cooper 
718cdebaff8SEnji Cooper 	printf("Before joining the mutex\n");
719cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_join(new, NULL));
720cdebaff8SEnji Cooper 
721cdebaff8SEnji Cooper 	printf("Unlocking mutex\n");
722cdebaff8SEnji Cooper 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
723cdebaff8SEnji Cooper }
724cdebaff8SEnji Cooper #endif
725cdebaff8SEnji Cooper 
72657718be8SEnji Cooper ATF_TP_ADD_TCS(tp)
72757718be8SEnji Cooper {
72857718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, mutex1);
72957718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, mutex2);
73057718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, mutex3);
73157718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, mutex4);
732640235e2SEnji Cooper #ifdef __NetBSD__
733640235e2SEnji Cooper 	ATF_TP_ADD_TC(tp, mutex5);
734640235e2SEnji Cooper 	ATF_TP_ADD_TC(tp, mutex6);
735640235e2SEnji Cooper #endif
736640235e2SEnji Cooper 	ATF_TP_ADD_TC(tp, mutexattr1);
737640235e2SEnji Cooper 	ATF_TP_ADD_TC(tp, mutexattr2);
73857718be8SEnji Cooper 
739cdebaff8SEnji Cooper #ifdef TIMEDMUTEX
740cdebaff8SEnji Cooper 	ATF_TP_ADD_TC(tp, timedmutex1);
741cdebaff8SEnji Cooper 	ATF_TP_ADD_TC(tp, timedmutex2);
742cdebaff8SEnji Cooper 	ATF_TP_ADD_TC(tp, timedmutex3);
743cdebaff8SEnji Cooper 	ATF_TP_ADD_TC(tp, timedmutex4);
744cdebaff8SEnji Cooper #endif
745cdebaff8SEnji Cooper 
74657718be8SEnji Cooper 	return atf_no_error();
74757718be8SEnji Cooper }
748