]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/netbsd-tests/lib/libpthread/t_mutex.c
Improve libnetbsd compatibility with NetBSD
[FreeBSD/FreeBSD.git] / contrib / netbsd-tests / lib / libpthread / t_mutex.c
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 }