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