t_mutex.c revision 313535
1/* $NetBSD: t_mutex.c,v 1.14 2016/10/31 23:51:20 christos Exp $ */
2
3/*
4 * Copyright (c) 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30__COPYRIGHT("@(#) Copyright (c) 2008\
31 The NetBSD Foundation, inc. All rights reserved.");
32__RCSID("$NetBSD: t_mutex.c,v 1.14 2016/10/31 23:51:20 christos Exp $");
33
34#ifdef __FreeBSD__
35#include <sys/time.h> /* For timespecadd */
36#include <inttypes.h> /* For UINT16_MAX */
37#endif
38#include <pthread.h>
39#include <stdio.h>
40#include <string.h>
41#include <errno.h>
42#include <time.h>
43#include <unistd.h>
44#include <sys/sched.h>
45#include <sys/param.h>
46
47#include <atf-c.h>
48
49#include "h_common.h"
50
51static pthread_mutex_t mutex;
52static pthread_mutex_t static_mutex = PTHREAD_MUTEX_INITIALIZER;
53static int global_x;
54
55#ifdef TIMEDMUTEX
56/* This code is used for verifying non-timed specific code */
57static struct timespec ts_lengthy = {
58	.tv_sec = UINT16_MAX,
59	.tv_nsec = 0
60};
61/* This code is used for verifying timed-only specific code */
62static struct timespec ts_shortlived = {
63	.tv_sec = 0,
64	.tv_nsec = 120
65};
66
67static int
68mutex_lock(pthread_mutex_t *m, const struct timespec *ts)
69{
70	struct timespec ts_wait;
71	ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &ts_wait) != -1);
72	timespecadd(&ts_wait, ts, &ts_wait);
73
74	return pthread_mutex_timedlock(m, &ts_wait);
75}
76#else
77#define mutex_lock(a, b) pthread_mutex_lock(a)
78#endif
79
80static void *
81mutex1_threadfunc(void *arg)
82{
83	int *param;
84
85	printf("2: Second thread.\n");
86
87	param = arg;
88	printf("2: Locking mutex\n");
89	mutex_lock(&mutex, &ts_lengthy);
90	printf("2: Got mutex. *param = %d\n", *param);
91	ATF_REQUIRE_EQ(*param, 20);
92	(*param)++;
93
94	pthread_mutex_unlock(&mutex);
95
96	return param;
97}
98
99ATF_TC(mutex1);
100ATF_TC_HEAD(mutex1, tc)
101{
102	atf_tc_set_md_var(tc, "descr", "Checks mutexes");
103}
104ATF_TC_BODY(mutex1, tc)
105{
106	int x;
107	pthread_t new;
108	void *joinval;
109
110	printf("1: Mutex-test 1\n");
111
112	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
113	x = 1;
114	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
115	PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex1_threadfunc, &x));
116	printf("1: Before changing the value.\n");
117	sleep(2);
118	x = 20;
119	printf("1: Before releasing the mutex.\n");
120	sleep(2);
121	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
122	printf("1: After releasing the mutex.\n");
123	PTHREAD_REQUIRE(pthread_join(new, &joinval));
124
125	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
126	printf("1: Thread joined. X was %d. Return value (int) was %d\n",
127		x, *(int *)joinval);
128	ATF_REQUIRE_EQ(x, 21);
129	ATF_REQUIRE_EQ(*(int *)joinval, 21);
130	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
131}
132
133static void *
134mutex2_threadfunc(void *arg)
135{
136	long count = *(int *)arg;
137
138	printf("2: Second thread (%p). Count is %ld\n", pthread_self(), count);
139
140	while (count--) {
141		PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
142		global_x++;
143		PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
144	}
145
146	return (void *)count;
147}
148
149ATF_TC(mutex2);
150ATF_TC_HEAD(mutex2, tc)
151{
152	atf_tc_set_md_var(tc, "descr", "Checks mutexes");
153#ifdef __NetBSD__
154#if defined(__powerpc__)
155	atf_tc_set_md_var(tc, "timeout", "40");
156#endif
157#endif
158}
159ATF_TC_BODY(mutex2, tc)
160{
161	int count, count2;
162	pthread_t new;
163	void *joinval;
164
165	printf("1: Mutex-test 2\n");
166
167#ifdef __NetBSD__
168#if defined(__powerpc__)
169	atf_tc_expect_timeout("PR port-powerpc/44387");
170#endif
171#endif
172
173	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
174
175	global_x = 0;
176	count = count2 = 10000000;
177
178	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
179	PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex2_threadfunc, &count2));
180
181	printf("1: Thread %p\n", pthread_self());
182
183	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
184
185	while (count--) {
186		PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
187		global_x++;
188		PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
189	}
190
191	PTHREAD_REQUIRE(pthread_join(new, &joinval));
192
193	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
194	printf("1: Thread joined. X was %d. Return value (long) was %ld\n",
195		global_x, (long)joinval);
196	ATF_REQUIRE_EQ(global_x, 20000000);
197
198#ifdef __NetBSD__
199#if defined(__powerpc__)
200	/* XXX force a timeout in ppc case since an un-triggered race
201	   otherwise looks like a "failure" */
202	/* We sleep for longer than the timeout to make ATF not
203	   complain about unexpected success */
204	sleep(41);
205#endif
206#endif
207}
208
209static void *
210mutex3_threadfunc(void *arg)
211{
212	long count = *(int *)arg;
213
214	printf("2: Second thread (%p). Count is %ld\n", pthread_self(), count);
215
216	while (count--) {
217		PTHREAD_REQUIRE(mutex_lock(&static_mutex, &ts_lengthy));
218		global_x++;
219		PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
220	}
221
222	return (void *)count;
223}
224
225ATF_TC(mutex3);
226ATF_TC_HEAD(mutex3, tc)
227{
228	atf_tc_set_md_var(tc, "descr", "Checks mutexes using a static "
229	    "initializer");
230#ifdef __NetBSD__
231#if defined(__powerpc__)
232	atf_tc_set_md_var(tc, "timeout", "40");
233#endif
234#endif
235}
236ATF_TC_BODY(mutex3, tc)
237{
238	int count, count2;
239	pthread_t new;
240	void *joinval;
241
242	printf("1: Mutex-test 3\n");
243
244#ifdef __NetBSD__
245#if defined(__powerpc__)
246	atf_tc_expect_timeout("PR port-powerpc/44387");
247#endif
248#endif
249
250	global_x = 0;
251	count = count2 = 10000000;
252
253	PTHREAD_REQUIRE(mutex_lock(&static_mutex, &ts_lengthy));
254	PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex3_threadfunc, &count2));
255
256	printf("1: Thread %p\n", pthread_self());
257
258	PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
259
260	while (count--) {
261		PTHREAD_REQUIRE(mutex_lock(&static_mutex, &ts_lengthy));
262		global_x++;
263		PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
264	}
265
266	PTHREAD_REQUIRE(pthread_join(new, &joinval));
267
268	PTHREAD_REQUIRE(mutex_lock(&static_mutex, &ts_lengthy));
269	printf("1: Thread joined. X was %d. Return value (long) was %ld\n",
270		global_x, (long)joinval);
271	ATF_REQUIRE_EQ(global_x, 20000000);
272
273#ifdef __NetBSD__
274#if defined(__powerpc__)
275	/* XXX force a timeout in ppc case since an un-triggered race
276	   otherwise looks like a "failure" */
277	/* We sleep for longer than the timeout to make ATF not
278	   complain about unexpected success */
279	sleep(41);
280#endif
281#endif
282}
283
284static void *
285mutex4_threadfunc(void *arg)
286{
287	int *param;
288
289	printf("2: Second thread.\n");
290
291	param = arg;
292	printf("2: Locking mutex\n");
293	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
294	printf("2: Got mutex. *param = %d\n", *param);
295	(*param)++;
296
297	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
298
299	return param;
300}
301
302ATF_TC(mutex4);
303ATF_TC_HEAD(mutex4, tc)
304{
305	atf_tc_set_md_var(tc, "descr", "Checks mutexes");
306}
307ATF_TC_BODY(mutex4, tc)
308{
309	int x;
310	pthread_t new;
311	pthread_mutexattr_t mattr;
312	void *joinval;
313
314	printf("1: Mutex-test 4\n");
315
316	PTHREAD_REQUIRE(pthread_mutexattr_init(&mattr));
317	PTHREAD_REQUIRE(pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE));
318
319	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, &mattr));
320
321	PTHREAD_REQUIRE(pthread_mutexattr_destroy(&mattr));
322
323	x = 1;
324	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
325	PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex4_threadfunc, &x));
326
327	printf("1: Before recursively acquiring the mutex.\n");
328	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
329
330	printf("1: Before releasing the mutex once.\n");
331	sleep(2);
332	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
333	printf("1: After releasing the mutex once.\n");
334
335	x = 20;
336
337	printf("1: Before releasing the mutex twice.\n");
338	sleep(2);
339	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
340	printf("1: After releasing the mutex twice.\n");
341
342	PTHREAD_REQUIRE(pthread_join(new, &joinval));
343
344	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
345	printf("1: Thread joined. X was %d. Return value (int) was %d\n",
346		x, *(int *)joinval);
347	ATF_REQUIRE_EQ(x, 21);
348	ATF_REQUIRE_EQ(*(int *)joinval, 21);
349	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
350}
351
352#ifdef __NetBSD__
353static pthread_mutexattr_t attr5;
354static pthread_mutex_t mutex5;
355static int min_fifo_prio, max_fifo_prio;
356
357static void *
358child_func(void* arg)
359{
360	int res;
361
362	printf("child is waiting\n");
363	res = _sched_protect(-2);
364	ATF_REQUIRE_EQ_MSG(res, -1, "sched_protect returned %d", res);
365	ATF_REQUIRE_EQ(errno, ENOENT);
366	PTHREAD_REQUIRE(mutex_lock(&mutex5, &ts_lengthy));
367	printf("child is owning resource\n");
368	res = _sched_protect(-2);
369	ATF_REQUIRE_EQ(res,  max_fifo_prio);
370	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex5));
371	printf("child is done\n");
372
373	return 0;
374}
375
376ATF_TC(mutex5);
377ATF_TC_HEAD(mutex5, tc)
378{
379	atf_tc_set_md_var(tc, "descr", "Checks mutexes for priority setting");
380	atf_tc_set_md_var(tc, "require.user", "root");
381}
382
383ATF_TC_BODY(mutex5, tc)
384{
385	int res;
386	struct sched_param param;
387	pthread_t child;
388
389	min_fifo_prio = sched_get_priority_min(SCHED_FIFO);
390	max_fifo_prio = sched_get_priority_max(SCHED_FIFO);
391	printf("min prio for FIFO = %d\n", min_fifo_prio);
392	param.sched_priority = min_fifo_prio;
393
394	/* = 0 OTHER, 1 FIFO, 2 RR, -1 NONE */
395	res = sched_setscheduler(getpid(), SCHED_FIFO, &param);
396	printf("previous policy used = %d\n", res);
397
398	res = sched_getscheduler(getpid());
399	ATF_REQUIRE_EQ_MSG(res, SCHED_FIFO, "sched %d != FIFO %d", res,
400	    SCHED_FIFO);
401
402	PTHREAD_REQUIRE(pthread_mutexattr_init(&attr5));
403	PTHREAD_REQUIRE(pthread_mutexattr_setprotocol(&attr5,
404	    PTHREAD_PRIO_PROTECT));
405	PTHREAD_REQUIRE(pthread_mutexattr_setprioceiling(&attr5,
406	    max_fifo_prio));
407
408	PTHREAD_REQUIRE(pthread_mutex_init(&mutex5, &attr5));
409	PTHREAD_REQUIRE(mutex_lock(&mutex5, &ts_lengthy));
410	printf("enter critical section for main\n");
411	PTHREAD_REQUIRE(pthread_create(&child, NULL, child_func, NULL));
412	printf("main starts to sleep\n");
413	sleep(10);
414	printf("main completes\n");
415	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex5));
416	PTHREAD_REQUIRE(pthread_join(child, NULL));
417}
418
419static pthread_mutex_t mutex6;
420static int start = 0;
421static uintmax_t high_cnt = 0, low_cnt = 0, MAX_LOOP = 100000000;
422
423static void *
424high_prio(void* arg)
425{
426	struct sched_param param;
427	int policy;
428	param.sched_priority = min_fifo_prio + 10;
429	pthread_t childid = pthread_self();
430
431	PTHREAD_REQUIRE(pthread_setschedparam(childid, 1, &param));
432	PTHREAD_REQUIRE(pthread_getschedparam(childid, &policy, &param));
433	printf("high protect = %d, prio = %d\n",
434	    _sched_protect(-2), param.sched_priority);
435	ATF_REQUIRE_EQ(policy, 1);
436	printf("high prio = %d\n", param.sched_priority);
437	sleep(1);
438	long tmp = 0;
439	for (int i = 0; i < 20; i++) {
440		while (high_cnt < MAX_LOOP) {
441			tmp += (123456789 % 1234) * (987654321 % 54321);
442			high_cnt += 1;
443		}
444		high_cnt = 0;
445		sleep(1);
446	}
447	PTHREAD_REQUIRE(mutex_lock(&mutex6, &ts_lengthy));
448	if (start == 0) start = 2;
449	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex6));
450
451	return 0;
452}
453
454static void *
455low_prio(void* arg)
456{
457	struct sched_param param;
458	int policy;
459	param.sched_priority = min_fifo_prio;
460	pthread_t childid = pthread_self();
461	int res = _sched_protect(max_fifo_prio);
462	ATF_REQUIRE_EQ(res, 0);
463	PTHREAD_REQUIRE(pthread_setschedparam(childid, 1, &param));
464	PTHREAD_REQUIRE(pthread_getschedparam(childid, &policy, &param));
465	printf("low protect = %d, prio = %d\n", _sched_protect(-2),
466	    param.sched_priority);
467	ATF_REQUIRE_EQ(policy, 1);
468	printf("low prio = %d\n", param.sched_priority);
469	sleep(1);
470	long tmp = 0;
471	for (int i = 0; i < 20; i++) {
472		while (low_cnt < MAX_LOOP) {
473			tmp += (123456789 % 1234) * (987654321 % 54321);
474			low_cnt += 1;
475		}
476		low_cnt = 0;
477		sleep(1);
478	}
479	PTHREAD_REQUIRE(mutex_lock(&mutex6, &ts_lengthy));
480	if (start == 0)
481		start = 1;
482	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex6));
483
484	return 0;
485}
486
487ATF_TC(mutex6);
488ATF_TC_HEAD(mutex6, tc)
489{
490	atf_tc_set_md_var(tc, "descr",
491	    "Checks scheduling for priority ceiling");
492	atf_tc_set_md_var(tc, "require.user", "root");
493}
494
495/*
496 * 1. main thread sets itself to be a realtime task and launched two tasks,
497 *    one has higher priority and the other has lower priority.
498 * 2. each child thread(low and high priority thread) sets its scheduler and
499 *    priority.
500 * 3. each child thread did several rounds of computation, after each round it
501 *    sleep 1 second.
502 * 4. the child thread with low priority will call _sched_protect to increase
503 *    its protect priority.
504 * 5. We verify the thread with low priority runs first.
505 *
506 * Why does it work? From the main thread, we launched the high
507 * priority thread first. This gives this thread the benefit of
508 * starting first. The low priority thread did not call _sched_protect(2).
509 * The high priority thread should finish the task first. After each
510 * round of computation, we call sleep, to put the task into the
511 * sleep queue, and wake up again after the timer expires. This
512 * gives the scheduler the chance to decide which task to run. So,
513 * the thread with real high priority will always block the thread
514 * with real low priority.
515 *
516 */
517ATF_TC_BODY(mutex6, tc)
518{
519	struct sched_param param;
520	int res;
521	pthread_t high, low;
522
523	min_fifo_prio = sched_get_priority_min(SCHED_FIFO);
524	max_fifo_prio = sched_get_priority_max(SCHED_FIFO);
525	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
526	printf("min_fifo_prio = %d, max_fifo_info = %d\n", min_fifo_prio,
527	    max_fifo_prio);
528
529	param.sched_priority = min_fifo_prio;
530	res = sched_setscheduler(getpid(), SCHED_FIFO, &param);
531	printf("previous policy used = %d\n", res);
532
533	res = sched_getscheduler(getpid());
534	ATF_REQUIRE_EQ(res, 1);
535	PTHREAD_REQUIRE(pthread_create(&high, NULL, high_prio, NULL));
536	PTHREAD_REQUIRE(pthread_create(&low, NULL, low_prio, NULL));
537	sleep(5);
538	PTHREAD_REQUIRE(pthread_join(low, NULL));
539	PTHREAD_REQUIRE(pthread_join(high, NULL));
540
541	ATF_REQUIRE_EQ(start, 1);
542}
543#endif
544
545ATF_TC(mutexattr1);
546ATF_TC_HEAD(mutexattr1, tc)
547{
548	atf_tc_set_md_var(tc, "descr", "Checks mutexattr");
549}
550
551ATF_TC_BODY(mutexattr1, tc)
552{
553	pthread_mutexattr_t mattr;
554	int protocol, target;
555
556	PTHREAD_REQUIRE(pthread_mutexattr_init(&mattr));
557
558	target = PTHREAD_PRIO_NONE;
559	PTHREAD_REQUIRE(pthread_mutexattr_setprotocol(&mattr, target));
560	PTHREAD_REQUIRE(pthread_mutexattr_getprotocol(&mattr, &protocol));
561	ATF_REQUIRE_EQ(protocol, target);
562
563	/*
564	target = PTHREAD_PRIO_INHERIT;
565	PTHREAD_REQUIRE(pthread_mutexattr_setprotocol(&mattr, target));
566	PTHREAD_REQUIRE(pthread_mutexattr_getprotocol(&mattr, &protocol));
567	ATF_REQUIRE_EQ(protocol, target);
568	*/
569
570	target = PTHREAD_PRIO_PROTECT;
571	PTHREAD_REQUIRE(pthread_mutexattr_setprotocol(&mattr, target));
572	PTHREAD_REQUIRE(pthread_mutexattr_getprotocol(&mattr, &protocol));
573	ATF_REQUIRE_EQ(protocol, target);
574}
575
576ATF_TC(mutexattr2);
577ATF_TC_HEAD(mutexattr2, tc)
578{
579	atf_tc_set_md_var(tc, "descr", "Checks mutexattr");
580}
581
582ATF_TC_BODY(mutexattr2, tc)
583{
584	pthread_mutexattr_t mattr;
585
586#ifdef __FreeBSD__
587	atf_tc_expect_fail("fails on i == 0 with: "
588	    "pthread_mutexattr_setprioceiling(&mattr, i): Invalid argument "
589	    "-- PR # 211802");
590#endif
591
592	PTHREAD_REQUIRE(pthread_mutexattr_init(&mattr));
593	int max_prio = sched_get_priority_max(SCHED_FIFO);
594	int min_prio = sched_get_priority_min(SCHED_FIFO);
595	for (int i = min_prio; i <= max_prio; i++) {
596		int prioceiling;
597#ifdef __FreeBSD__
598		int protocol;
599
600		PTHREAD_REQUIRE(pthread_mutexattr_getprotocol(&mattr,
601		    &protocol));
602
603		printf("priority: %d\nprotocol: %d\n", i, protocol);
604#endif
605		PTHREAD_REQUIRE(pthread_mutexattr_setprioceiling(&mattr, i));
606		PTHREAD_REQUIRE(pthread_mutexattr_getprioceiling(&mattr,
607		    &prioceiling));
608#ifdef __FreeBSD__
609		printf("prioceiling: %d\n", prioceiling);
610#endif
611		ATF_REQUIRE_EQ(i, prioceiling);
612	}
613}
614
615#ifdef TIMEDMUTEX
616ATF_TC(timedmutex1);
617ATF_TC_HEAD(timedmutex1, tc)
618{
619	atf_tc_set_md_var(tc, "descr", "Checks timeout on selflock");
620}
621
622ATF_TC_BODY(timedmutex1, tc)
623{
624
625	printf("Timed mutex-test 1\n");
626
627	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
628
629	printf("Before acquiring mutex\n");
630	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
631
632	printf("Before endeavor to reacquire timed-mutex (timeout expected)\n");
633	PTHREAD_REQUIRE_STATUS(mutex_lock(&mutex, &ts_shortlived),
634	    ETIMEDOUT);
635
636	printf("Unlocking mutex\n");
637	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
638}
639
640ATF_TC(timedmutex2);
641ATF_TC_HEAD(timedmutex2, tc)
642{
643	atf_tc_set_md_var(tc, "descr",
644	    "Checks timeout on selflock with timedlock");
645}
646
647ATF_TC_BODY(timedmutex2, tc)
648{
649
650	printf("Timed mutex-test 2\n");
651
652	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
653
654	printf("Before acquiring mutex with timedlock\n");
655	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
656
657	printf("Before endeavor to reacquire timed-mutex (timeout expected)\n");
658	PTHREAD_REQUIRE_STATUS(mutex_lock(&mutex, &ts_shortlived),
659	    ETIMEDOUT);
660
661	printf("Unlocking mutex\n");
662	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
663}
664
665ATF_TC(timedmutex3);
666ATF_TC_HEAD(timedmutex3, tc)
667{
668	atf_tc_set_md_var(tc, "descr",
669	    "Checks timeout on selflock in a new thread");
670}
671
672static void *
673timedmtx_thrdfunc(void *arg)
674{
675	printf("Before endeavor to reacquire timed-mutex (timeout expected)\n");
676	PTHREAD_REQUIRE_STATUS(mutex_lock(&mutex, &ts_shortlived),
677	    ETIMEDOUT);
678
679	return NULL;
680}
681
682ATF_TC_BODY(timedmutex3, tc)
683{
684	pthread_t new;
685
686	printf("Timed mutex-test 3\n");
687
688	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
689
690	printf("Before acquiring mutex with timedlock\n");
691	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
692
693	printf("Before creating new thread\n");
694	PTHREAD_REQUIRE(pthread_create(&new, NULL, timedmtx_thrdfunc, NULL));
695
696	printf("Before joining the mutex\n");
697	PTHREAD_REQUIRE(pthread_join(new, NULL));
698
699	printf("Unlocking mutex\n");
700	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
701}
702
703ATF_TC(timedmutex4);
704ATF_TC_HEAD(timedmutex4, tc)
705{
706	atf_tc_set_md_var(tc, "descr",
707	    "Checks timeout on selflock with timedlock in a new thread");
708}
709
710ATF_TC_BODY(timedmutex4, tc)
711{
712	pthread_t new;
713
714	printf("Timed mutex-test 4\n");
715
716	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
717
718	printf("Before acquiring mutex with timedlock\n");
719	PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy));
720
721	printf("Before creating new thread\n");
722	PTHREAD_REQUIRE(pthread_create(&new, NULL, timedmtx_thrdfunc, NULL));
723
724	printf("Before joining the mutex\n");
725	PTHREAD_REQUIRE(pthread_join(new, NULL));
726
727	printf("Unlocking mutex\n");
728	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
729}
730#endif
731
732ATF_TP_ADD_TCS(tp)
733{
734	ATF_TP_ADD_TC(tp, mutex1);
735	ATF_TP_ADD_TC(tp, mutex2);
736	ATF_TP_ADD_TC(tp, mutex3);
737	ATF_TP_ADD_TC(tp, mutex4);
738#ifdef __NetBSD__
739	ATF_TP_ADD_TC(tp, mutex5);
740	ATF_TP_ADD_TC(tp, mutex6);
741#endif
742	ATF_TP_ADD_TC(tp, mutexattr1);
743	ATF_TP_ADD_TC(tp, mutexattr2);
744
745#ifdef TIMEDMUTEX
746	ATF_TP_ADD_TC(tp, timedmutex1);
747	ATF_TP_ADD_TC(tp, timedmutex2);
748	ATF_TP_ADD_TC(tp, timedmutex3);
749	ATF_TP_ADD_TC(tp, timedmutex4);
750#endif
751
752	return atf_no_error();
753}
754