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