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