xref: /freebsd/contrib/netbsd-tests/lib/libpthread/t_mutex.c (revision 792bbaba989533a1fc93823df1720c8c4aaf0442)
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 
51 static pthread_mutex_t mutex;
52 static pthread_mutex_t static_mutex = PTHREAD_MUTEX_INITIALIZER;
53 static int global_x;
54 
55 #ifdef TIMEDMUTEX
56 /* This code is used for verifying non-timed specific code */
57 static 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 */
62 static struct timespec ts_shortlived = {
63 	.tv_sec = 0,
64 	.tv_nsec = 120
65 };
66 
67 static int
68 mutex_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 
80 static void *
81 mutex1_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 
99 ATF_TC(mutex1);
100 ATF_TC_HEAD(mutex1, tc)
101 {
102 	atf_tc_set_md_var(tc, "descr", "Checks mutexes");
103 }
104 ATF_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 
133 static void *
134 mutex2_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 
149 ATF_TC(mutex2);
150 ATF_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 }
159 ATF_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 
209 static void *
210 mutex3_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 
225 ATF_TC(mutex3);
226 ATF_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 }
236 ATF_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 
284 static void *
285 mutex4_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 
302 ATF_TC(mutex4);
303 ATF_TC_HEAD(mutex4, tc)
304 {
305 	atf_tc_set_md_var(tc, "descr", "Checks mutexes");
306 }
307 ATF_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__
353 static pthread_mutexattr_t attr5;
354 static pthread_mutex_t mutex5;
355 static int min_fifo_prio, max_fifo_prio;
356 
357 static void *
358 child_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 
376 ATF_TC(mutex5);
377 ATF_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 
383 ATF_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 
419 static pthread_mutex_t mutex6;
420 static int start = 0;
421 static uintmax_t high_cnt = 0, low_cnt = 0, MAX_LOOP = 100000000;
422 
423 static void *
424 high_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 
454 static void *
455 low_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 
487 ATF_TC(mutex6);
488 ATF_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  */
517 ATF_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 
545 ATF_TC(mutexattr1);
546 ATF_TC_HEAD(mutexattr1, tc)
547 {
548 	atf_tc_set_md_var(tc, "descr", "Checks mutexattr");
549 }
550 
551 ATF_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 
576 ATF_TC(mutexattr2);
577 ATF_TC_HEAD(mutexattr2, tc)
578 {
579 	atf_tc_set_md_var(tc, "descr", "Checks mutexattr");
580 }
581 
582 ATF_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
616 ATF_TC(timedmutex1);
617 ATF_TC_HEAD(timedmutex1, tc)
618 {
619 	atf_tc_set_md_var(tc, "descr", "Checks timeout on selflock");
620 }
621 
622 ATF_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 
640 ATF_TC(timedmutex2);
641 ATF_TC_HEAD(timedmutex2, tc)
642 {
643 	atf_tc_set_md_var(tc, "descr",
644 	    "Checks timeout on selflock with timedlock");
645 }
646 
647 ATF_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 
665 ATF_TC(timedmutex3);
666 ATF_TC_HEAD(timedmutex3, tc)
667 {
668 	atf_tc_set_md_var(tc, "descr",
669 	    "Checks timeout on selflock in a new thread");
670 }
671 
672 static void *
673 timedmtx_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 
682 ATF_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 
703 ATF_TC(timedmutex4);
704 ATF_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 
710 ATF_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 
732 ATF_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