1*640235e2SEnji Cooper /* $NetBSD: t_mutex.c,v 1.10 2016/07/31 13:01:29 christos Exp $ */ 257718be8SEnji Cooper 357718be8SEnji Cooper /* 457718be8SEnji Cooper * Copyright (c) 2008 The NetBSD Foundation, Inc. 557718be8SEnji Cooper * All rights reserved. 657718be8SEnji Cooper * 757718be8SEnji Cooper * Redistribution and use in source and binary forms, with or without 857718be8SEnji Cooper * modification, are permitted provided that the following conditions 957718be8SEnji Cooper * are met: 1057718be8SEnji Cooper * 1. Redistributions of source code must retain the above copyright 1157718be8SEnji Cooper * notice, this list of conditions and the following disclaimer. 1257718be8SEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright 1357718be8SEnji Cooper * notice, this list of conditions and the following disclaimer in the 1457718be8SEnji Cooper * documentation and/or other materials provided with the distribution. 1557718be8SEnji Cooper * 1657718be8SEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 1757718be8SEnji Cooper * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 1857718be8SEnji Cooper * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 1957718be8SEnji Cooper * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 2057718be8SEnji Cooper * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2157718be8SEnji Cooper * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2257718be8SEnji Cooper * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2357718be8SEnji Cooper * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2457718be8SEnji Cooper * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2557718be8SEnji Cooper * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2657718be8SEnji Cooper * POSSIBILITY OF SUCH DAMAGE. 2757718be8SEnji Cooper */ 2857718be8SEnji Cooper 2957718be8SEnji Cooper #include <sys/cdefs.h> 3057718be8SEnji Cooper __COPYRIGHT("@(#) Copyright (c) 2008\ 3157718be8SEnji Cooper The NetBSD Foundation, inc. All rights reserved."); 32*640235e2SEnji Cooper __RCSID("$NetBSD: t_mutex.c,v 1.10 2016/07/31 13:01:29 christos Exp $"); 3357718be8SEnji Cooper 3457718be8SEnji Cooper #include <pthread.h> 3557718be8SEnji Cooper #include <stdio.h> 3657718be8SEnji Cooper #include <string.h> 37*640235e2SEnji Cooper #include <errno.h> 3857718be8SEnji Cooper #include <unistd.h> 39*640235e2SEnji Cooper #include <sys/sched.h> 40*640235e2SEnji Cooper #include <sys/param.h> 4157718be8SEnji Cooper 4257718be8SEnji Cooper #include <atf-c.h> 4357718be8SEnji Cooper 4457718be8SEnji Cooper #include "h_common.h" 4557718be8SEnji Cooper 4657718be8SEnji Cooper static pthread_mutex_t mutex; 4757718be8SEnji Cooper static pthread_mutex_t static_mutex = PTHREAD_MUTEX_INITIALIZER; 4857718be8SEnji Cooper static int global_x; 4957718be8SEnji Cooper 5057718be8SEnji Cooper static void * 5157718be8SEnji Cooper mutex1_threadfunc(void *arg) 5257718be8SEnji Cooper { 5357718be8SEnji Cooper int *param; 5457718be8SEnji Cooper 5557718be8SEnji Cooper printf("2: Second thread.\n"); 5657718be8SEnji Cooper 5757718be8SEnji Cooper param = arg; 5857718be8SEnji Cooper printf("2: Locking mutex\n"); 5957718be8SEnji Cooper pthread_mutex_lock(&mutex); 6057718be8SEnji Cooper printf("2: Got mutex. *param = %d\n", *param); 6157718be8SEnji Cooper ATF_REQUIRE_EQ(*param, 20); 6257718be8SEnji Cooper (*param)++; 6357718be8SEnji Cooper 6457718be8SEnji Cooper pthread_mutex_unlock(&mutex); 6557718be8SEnji Cooper 6657718be8SEnji Cooper return param; 6757718be8SEnji Cooper } 6857718be8SEnji Cooper 6957718be8SEnji Cooper ATF_TC(mutex1); 7057718be8SEnji Cooper ATF_TC_HEAD(mutex1, tc) 7157718be8SEnji Cooper { 7257718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Checks mutexes"); 7357718be8SEnji Cooper } 7457718be8SEnji Cooper ATF_TC_BODY(mutex1, tc) 7557718be8SEnji Cooper { 7657718be8SEnji Cooper int x; 7757718be8SEnji Cooper pthread_t new; 7857718be8SEnji Cooper void *joinval; 7957718be8SEnji Cooper 8057718be8SEnji Cooper printf("1: Mutex-test 1\n"); 8157718be8SEnji Cooper 8257718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL)); 8357718be8SEnji Cooper x = 1; 8457718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 8557718be8SEnji Cooper PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex1_threadfunc, &x)); 8657718be8SEnji Cooper printf("1: Before changing the value.\n"); 8757718be8SEnji Cooper sleep(2); 8857718be8SEnji Cooper x = 20; 8957718be8SEnji Cooper printf("1: Before releasing the mutex.\n"); 9057718be8SEnji Cooper sleep(2); 9157718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 9257718be8SEnji Cooper printf("1: After releasing the mutex.\n"); 9357718be8SEnji Cooper PTHREAD_REQUIRE(pthread_join(new, &joinval)); 9457718be8SEnji Cooper 9557718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 9657718be8SEnji Cooper printf("1: Thread joined. X was %d. Return value (int) was %d\n", 9757718be8SEnji Cooper x, *(int *)joinval); 9857718be8SEnji Cooper ATF_REQUIRE_EQ(x, 21); 9957718be8SEnji Cooper ATF_REQUIRE_EQ(*(int *)joinval, 21); 10057718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 10157718be8SEnji Cooper } 10257718be8SEnji Cooper 10357718be8SEnji Cooper static void * 10457718be8SEnji Cooper mutex2_threadfunc(void *arg) 10557718be8SEnji Cooper { 10657718be8SEnji Cooper long count = *(int *)arg; 10757718be8SEnji Cooper 10857718be8SEnji Cooper printf("2: Second thread (%p). Count is %ld\n", pthread_self(), count); 10957718be8SEnji Cooper 11057718be8SEnji Cooper while (count--) { 11157718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 11257718be8SEnji Cooper global_x++; 11357718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 11457718be8SEnji Cooper } 11557718be8SEnji Cooper 11657718be8SEnji Cooper return (void *)count; 11757718be8SEnji Cooper } 11857718be8SEnji Cooper 11957718be8SEnji Cooper ATF_TC(mutex2); 12057718be8SEnji Cooper ATF_TC_HEAD(mutex2, tc) 12157718be8SEnji Cooper { 12257718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Checks mutexes"); 123190e1b1cSEnji Cooper #ifdef __NetBSD__ 12457718be8SEnji Cooper #if defined(__powerpc__) 12557718be8SEnji Cooper atf_tc_set_md_var(tc, "timeout", "40"); 12657718be8SEnji Cooper #endif 127190e1b1cSEnji Cooper #endif 12857718be8SEnji Cooper } 12957718be8SEnji Cooper ATF_TC_BODY(mutex2, tc) 13057718be8SEnji Cooper { 13157718be8SEnji Cooper int count, count2; 13257718be8SEnji Cooper pthread_t new; 13357718be8SEnji Cooper void *joinval; 13457718be8SEnji Cooper 13557718be8SEnji Cooper printf("1: Mutex-test 2\n"); 13657718be8SEnji Cooper 137190e1b1cSEnji Cooper #ifdef __NetBSD__ 13857718be8SEnji Cooper #if defined(__powerpc__) 13957718be8SEnji Cooper atf_tc_expect_timeout("PR port-powerpc/44387"); 14057718be8SEnji Cooper #endif 141190e1b1cSEnji Cooper #endif 14257718be8SEnji Cooper 14357718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL)); 14457718be8SEnji Cooper 14557718be8SEnji Cooper global_x = 0; 14657718be8SEnji Cooper count = count2 = 10000000; 14757718be8SEnji Cooper 14857718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 14957718be8SEnji Cooper PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex2_threadfunc, &count2)); 15057718be8SEnji Cooper 15157718be8SEnji Cooper printf("1: Thread %p\n", pthread_self()); 15257718be8SEnji Cooper 15357718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 15457718be8SEnji Cooper 15557718be8SEnji Cooper while (count--) { 15657718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 15757718be8SEnji Cooper global_x++; 15857718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 15957718be8SEnji Cooper } 16057718be8SEnji Cooper 16157718be8SEnji Cooper PTHREAD_REQUIRE(pthread_join(new, &joinval)); 16257718be8SEnji Cooper 16357718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 16457718be8SEnji Cooper printf("1: Thread joined. X was %d. Return value (long) was %ld\n", 16557718be8SEnji Cooper global_x, (long)joinval); 16657718be8SEnji Cooper ATF_REQUIRE_EQ(global_x, 20000000); 16757718be8SEnji Cooper 168190e1b1cSEnji Cooper #ifdef __NetBSD__ 16957718be8SEnji Cooper #if defined(__powerpc__) 17057718be8SEnji Cooper /* XXX force a timeout in ppc case since an un-triggered race 17157718be8SEnji Cooper otherwise looks like a "failure" */ 17257718be8SEnji Cooper /* We sleep for longer than the timeout to make ATF not 17357718be8SEnji Cooper complain about unexpected success */ 17457718be8SEnji Cooper sleep(41); 17557718be8SEnji Cooper #endif 176190e1b1cSEnji Cooper #endif 17757718be8SEnji Cooper } 17857718be8SEnji Cooper 17957718be8SEnji Cooper static void * 18057718be8SEnji Cooper mutex3_threadfunc(void *arg) 18157718be8SEnji Cooper { 18257718be8SEnji Cooper long count = *(int *)arg; 18357718be8SEnji Cooper 18457718be8SEnji Cooper printf("2: Second thread (%p). Count is %ld\n", pthread_self(), count); 18557718be8SEnji Cooper 18657718be8SEnji Cooper while (count--) { 18757718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex)); 18857718be8SEnji Cooper global_x++; 18957718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex)); 19057718be8SEnji Cooper } 19157718be8SEnji Cooper 19257718be8SEnji Cooper return (void *)count; 19357718be8SEnji Cooper } 19457718be8SEnji Cooper 19557718be8SEnji Cooper ATF_TC(mutex3); 19657718be8SEnji Cooper ATF_TC_HEAD(mutex3, tc) 19757718be8SEnji Cooper { 19857718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Checks mutexes using a static " 19957718be8SEnji Cooper "initializer"); 200190e1b1cSEnji Cooper #ifdef __NetBSD__ 20157718be8SEnji Cooper #if defined(__powerpc__) 20257718be8SEnji Cooper atf_tc_set_md_var(tc, "timeout", "40"); 20357718be8SEnji Cooper #endif 204190e1b1cSEnji Cooper #endif 20557718be8SEnji Cooper } 20657718be8SEnji Cooper ATF_TC_BODY(mutex3, tc) 20757718be8SEnji Cooper { 20857718be8SEnji Cooper int count, count2; 20957718be8SEnji Cooper pthread_t new; 21057718be8SEnji Cooper void *joinval; 21157718be8SEnji Cooper 21257718be8SEnji Cooper printf("1: Mutex-test 3\n"); 21357718be8SEnji Cooper 214190e1b1cSEnji Cooper #ifdef __NetBSD__ 21557718be8SEnji Cooper #if defined(__powerpc__) 21657718be8SEnji Cooper atf_tc_expect_timeout("PR port-powerpc/44387"); 21757718be8SEnji Cooper #endif 218190e1b1cSEnji Cooper #endif 21957718be8SEnji Cooper 22057718be8SEnji Cooper global_x = 0; 22157718be8SEnji Cooper count = count2 = 10000000; 22257718be8SEnji Cooper 22357718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex)); 22457718be8SEnji Cooper PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex3_threadfunc, &count2)); 22557718be8SEnji Cooper 22657718be8SEnji Cooper printf("1: Thread %p\n", pthread_self()); 22757718be8SEnji Cooper 22857718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex)); 22957718be8SEnji Cooper 23057718be8SEnji Cooper while (count--) { 23157718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex)); 23257718be8SEnji Cooper global_x++; 23357718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex)); 23457718be8SEnji Cooper } 23557718be8SEnji Cooper 23657718be8SEnji Cooper PTHREAD_REQUIRE(pthread_join(new, &joinval)); 23757718be8SEnji Cooper 23857718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex)); 23957718be8SEnji Cooper printf("1: Thread joined. X was %d. Return value (long) was %ld\n", 24057718be8SEnji Cooper global_x, (long)joinval); 24157718be8SEnji Cooper ATF_REQUIRE_EQ(global_x, 20000000); 24257718be8SEnji Cooper 243190e1b1cSEnji Cooper #ifdef __NetBSD__ 24457718be8SEnji Cooper #if defined(__powerpc__) 24557718be8SEnji Cooper /* XXX force a timeout in ppc case since an un-triggered race 24657718be8SEnji Cooper otherwise looks like a "failure" */ 24757718be8SEnji Cooper /* We sleep for longer than the timeout to make ATF not 24857718be8SEnji Cooper complain about unexpected success */ 24957718be8SEnji Cooper sleep(41); 25057718be8SEnji Cooper #endif 251190e1b1cSEnji Cooper #endif 25257718be8SEnji Cooper } 25357718be8SEnji Cooper 25457718be8SEnji Cooper static void * 25557718be8SEnji Cooper mutex4_threadfunc(void *arg) 25657718be8SEnji Cooper { 25757718be8SEnji Cooper int *param; 25857718be8SEnji Cooper 25957718be8SEnji Cooper printf("2: Second thread.\n"); 26057718be8SEnji Cooper 26157718be8SEnji Cooper param = arg; 26257718be8SEnji Cooper printf("2: Locking mutex\n"); 26357718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 26457718be8SEnji Cooper printf("2: Got mutex. *param = %d\n", *param); 26557718be8SEnji Cooper (*param)++; 26657718be8SEnji Cooper 26757718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 26857718be8SEnji Cooper 26957718be8SEnji Cooper return param; 27057718be8SEnji Cooper } 27157718be8SEnji Cooper 27257718be8SEnji Cooper ATF_TC(mutex4); 27357718be8SEnji Cooper ATF_TC_HEAD(mutex4, tc) 27457718be8SEnji Cooper { 27557718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Checks mutexes"); 27657718be8SEnji Cooper } 27757718be8SEnji Cooper ATF_TC_BODY(mutex4, tc) 27857718be8SEnji Cooper { 27957718be8SEnji Cooper int x; 28057718be8SEnji Cooper pthread_t new; 28157718be8SEnji Cooper pthread_mutexattr_t mattr; 28257718be8SEnji Cooper void *joinval; 28357718be8SEnji Cooper 28457718be8SEnji Cooper printf("1: Mutex-test 4\n"); 28557718be8SEnji Cooper 28657718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutexattr_init(&mattr)); 28757718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE)); 28857718be8SEnji Cooper 28957718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_init(&mutex, &mattr)); 29057718be8SEnji Cooper 29157718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutexattr_destroy(&mattr)); 29257718be8SEnji Cooper 29357718be8SEnji Cooper x = 1; 29457718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 29557718be8SEnji Cooper PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex4_threadfunc, &x)); 29657718be8SEnji Cooper 29757718be8SEnji Cooper printf("1: Before recursively acquiring the mutex.\n"); 29857718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 29957718be8SEnji Cooper 30057718be8SEnji Cooper printf("1: Before releasing the mutex once.\n"); 30157718be8SEnji Cooper sleep(2); 30257718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 30357718be8SEnji Cooper printf("1: After releasing the mutex once.\n"); 30457718be8SEnji Cooper 30557718be8SEnji Cooper x = 20; 30657718be8SEnji Cooper 30757718be8SEnji Cooper printf("1: Before releasing the mutex twice.\n"); 30857718be8SEnji Cooper sleep(2); 30957718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 31057718be8SEnji Cooper printf("1: After releasing the mutex twice.\n"); 31157718be8SEnji Cooper 31257718be8SEnji Cooper PTHREAD_REQUIRE(pthread_join(new, &joinval)); 31357718be8SEnji Cooper 31457718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 31557718be8SEnji Cooper printf("1: Thread joined. X was %d. Return value (int) was %d\n", 31657718be8SEnji Cooper x, *(int *)joinval); 31757718be8SEnji Cooper ATF_REQUIRE_EQ(x, 21); 31857718be8SEnji Cooper ATF_REQUIRE_EQ(*(int *)joinval, 21); 31957718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 32057718be8SEnji Cooper } 32157718be8SEnji Cooper 322*640235e2SEnji Cooper #ifdef __NetBSD__ 323*640235e2SEnji Cooper static pthread_mutexattr_t attr5; 324*640235e2SEnji Cooper static pthread_mutex_t mutex5; 325*640235e2SEnji Cooper static int min_fifo_prio, max_fifo_prio; 326*640235e2SEnji Cooper 327*640235e2SEnji Cooper static void * 328*640235e2SEnji Cooper child_func(void* arg) 329*640235e2SEnji Cooper { 330*640235e2SEnji Cooper int res; 331*640235e2SEnji Cooper 332*640235e2SEnji Cooper printf("child is waiting\n"); 333*640235e2SEnji Cooper res = _sched_protect(-2); 334*640235e2SEnji Cooper ATF_REQUIRE_EQ_MSG(res, -1, "sched_protect returned %d", res); 335*640235e2SEnji Cooper ATF_REQUIRE_EQ(errno, ENOENT); 336*640235e2SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&mutex5)); 337*640235e2SEnji Cooper printf("child is owning resource\n"); 338*640235e2SEnji Cooper res = _sched_protect(-2); 339*640235e2SEnji Cooper ATF_REQUIRE_EQ(res, max_fifo_prio); 340*640235e2SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex5)); 341*640235e2SEnji Cooper printf("child is done\n"); 342*640235e2SEnji Cooper 343*640235e2SEnji Cooper return 0; 344*640235e2SEnji Cooper } 345*640235e2SEnji Cooper 346*640235e2SEnji Cooper ATF_TC(mutex5); 347*640235e2SEnji Cooper ATF_TC_HEAD(mutex5, tc) 348*640235e2SEnji Cooper { 349*640235e2SEnji Cooper atf_tc_set_md_var(tc, "descr", "Checks mutexes for priority setting"); 350*640235e2SEnji Cooper atf_tc_set_md_var(tc, "require.user", "root"); 351*640235e2SEnji Cooper } 352*640235e2SEnji Cooper 353*640235e2SEnji Cooper ATF_TC_BODY(mutex5, tc) 354*640235e2SEnji Cooper { 355*640235e2SEnji Cooper int res; 356*640235e2SEnji Cooper struct sched_param param; 357*640235e2SEnji Cooper pthread_t child; 358*640235e2SEnji Cooper 359*640235e2SEnji Cooper min_fifo_prio = sched_get_priority_min(SCHED_FIFO); 360*640235e2SEnji Cooper max_fifo_prio = sched_get_priority_max(SCHED_FIFO); 361*640235e2SEnji Cooper printf("min prio for FIFO = %d\n", min_fifo_prio); 362*640235e2SEnji Cooper param.sched_priority = min_fifo_prio; 363*640235e2SEnji Cooper 364*640235e2SEnji Cooper /* = 0 OTHER, 1 FIFO, 2 RR, -1 NONE */ 365*640235e2SEnji Cooper res = sched_setscheduler(getpid(), SCHED_FIFO, ¶m); 366*640235e2SEnji Cooper printf("previous policy used = %d\n", res); 367*640235e2SEnji Cooper 368*640235e2SEnji Cooper res = sched_getscheduler(getpid()); 369*640235e2SEnji Cooper ATF_REQUIRE_EQ_MSG(res, SCHED_FIFO, "sched %d != FIFO %d", res, 370*640235e2SEnji Cooper SCHED_FIFO); 371*640235e2SEnji Cooper 372*640235e2SEnji Cooper PTHREAD_REQUIRE(pthread_mutexattr_init(&attr5)); 373*640235e2SEnji Cooper PTHREAD_REQUIRE(pthread_mutexattr_setprotocol(&attr5, 374*640235e2SEnji Cooper PTHREAD_PRIO_PROTECT)); 375*640235e2SEnji Cooper PTHREAD_REQUIRE(pthread_mutexattr_setprioceiling(&attr5, 376*640235e2SEnji Cooper max_fifo_prio)); 377*640235e2SEnji Cooper 378*640235e2SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_init(&mutex5, &attr5)); 379*640235e2SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&mutex5)); 380*640235e2SEnji Cooper printf("enter critical section for main\n"); 381*640235e2SEnji Cooper PTHREAD_REQUIRE(pthread_create(&child, NULL, child_func, NULL)); 382*640235e2SEnji Cooper printf("main starts to sleep\n"); 383*640235e2SEnji Cooper sleep(10); 384*640235e2SEnji Cooper printf("main completes\n"); 385*640235e2SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex5)); 386*640235e2SEnji Cooper PTHREAD_REQUIRE(pthread_join(child, NULL)); 387*640235e2SEnji Cooper } 388*640235e2SEnji Cooper 389*640235e2SEnji Cooper static pthread_mutex_t mutex6; 390*640235e2SEnji Cooper static int start = 0; 391*640235e2SEnji Cooper static uintmax_t high_cnt = 0, low_cnt = 0, MAX_LOOP = 100000000; 392*640235e2SEnji Cooper 393*640235e2SEnji Cooper static void * 394*640235e2SEnji Cooper high_prio(void* arg) 395*640235e2SEnji Cooper { 396*640235e2SEnji Cooper struct sched_param param; 397*640235e2SEnji Cooper int policy; 398*640235e2SEnji Cooper param.sched_priority = min_fifo_prio + 10; 399*640235e2SEnji Cooper pthread_t childid = pthread_self(); 400*640235e2SEnji Cooper 401*640235e2SEnji Cooper PTHREAD_REQUIRE(pthread_setschedparam(childid, 1, ¶m)); 402*640235e2SEnji Cooper PTHREAD_REQUIRE(pthread_getschedparam(childid, &policy, ¶m)); 403*640235e2SEnji Cooper printf("high protect = %d, prio = %d\n", 404*640235e2SEnji Cooper _sched_protect(-2), param.sched_priority); 405*640235e2SEnji Cooper ATF_REQUIRE_EQ(policy, 1); 406*640235e2SEnji Cooper printf("high prio = %d\n", param.sched_priority); 407*640235e2SEnji Cooper sleep(1); 408*640235e2SEnji Cooper long tmp = 0; 409*640235e2SEnji Cooper for (int i = 0; i < 20; i++) { 410*640235e2SEnji Cooper while (high_cnt < MAX_LOOP) { 411*640235e2SEnji Cooper tmp += (123456789 % 1234) * (987654321 % 54321); 412*640235e2SEnji Cooper high_cnt += 1; 413*640235e2SEnji Cooper } 414*640235e2SEnji Cooper high_cnt = 0; 415*640235e2SEnji Cooper sleep(1); 416*640235e2SEnji Cooper } 417*640235e2SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&mutex6)); 418*640235e2SEnji Cooper if (start == 0) start = 2; 419*640235e2SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex6)); 420*640235e2SEnji Cooper 421*640235e2SEnji Cooper return 0; 422*640235e2SEnji Cooper } 423*640235e2SEnji Cooper 424*640235e2SEnji Cooper static void * 425*640235e2SEnji Cooper low_prio(void* arg) 426*640235e2SEnji Cooper { 427*640235e2SEnji Cooper struct sched_param param; 428*640235e2SEnji Cooper int policy; 429*640235e2SEnji Cooper param.sched_priority = min_fifo_prio; 430*640235e2SEnji Cooper pthread_t childid = pthread_self(); 431*640235e2SEnji Cooper int res = _sched_protect(max_fifo_prio); 432*640235e2SEnji Cooper ATF_REQUIRE_EQ(res, 0); 433*640235e2SEnji Cooper PTHREAD_REQUIRE(pthread_setschedparam(childid, 1, ¶m)); 434*640235e2SEnji Cooper PTHREAD_REQUIRE(pthread_getschedparam(childid, &policy, ¶m)); 435*640235e2SEnji Cooper printf("low protect = %d, prio = %d\n", _sched_protect(-2), 436*640235e2SEnji Cooper param.sched_priority); 437*640235e2SEnji Cooper ATF_REQUIRE_EQ(policy, 1); 438*640235e2SEnji Cooper printf("low prio = %d\n", param.sched_priority); 439*640235e2SEnji Cooper sleep(1); 440*640235e2SEnji Cooper long tmp = 0; 441*640235e2SEnji Cooper for (int i = 0; i < 20; i++) { 442*640235e2SEnji Cooper while (low_cnt < MAX_LOOP) { 443*640235e2SEnji Cooper tmp += (123456789 % 1234) * (987654321 % 54321); 444*640235e2SEnji Cooper low_cnt += 1; 445*640235e2SEnji Cooper } 446*640235e2SEnji Cooper low_cnt = 0; 447*640235e2SEnji Cooper sleep(1); 448*640235e2SEnji Cooper } 449*640235e2SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&mutex6)); 450*640235e2SEnji Cooper if (start == 0) 451*640235e2SEnji Cooper start = 1; 452*640235e2SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex6)); 453*640235e2SEnji Cooper 454*640235e2SEnji Cooper return 0; 455*640235e2SEnji Cooper } 456*640235e2SEnji Cooper 457*640235e2SEnji Cooper ATF_TC(mutex6); 458*640235e2SEnji Cooper ATF_TC_HEAD(mutex6, tc) 459*640235e2SEnji Cooper { 460*640235e2SEnji Cooper atf_tc_set_md_var(tc, "descr", 461*640235e2SEnji Cooper "Checks scheduling for priority ceiling"); 462*640235e2SEnji Cooper atf_tc_set_md_var(tc, "require.user", "root"); 463*640235e2SEnji Cooper } 464*640235e2SEnji Cooper 465*640235e2SEnji Cooper /* 466*640235e2SEnji Cooper * 1. main thread sets itself to be a realtime task and launched two tasks, 467*640235e2SEnji Cooper * one has higher priority and the other has lower priority. 468*640235e2SEnji Cooper * 2. each child thread(low and high priority thread) sets its scheduler and 469*640235e2SEnji Cooper * priority. 470*640235e2SEnji Cooper * 3. each child thread did several rounds of computation, after each round it 471*640235e2SEnji Cooper * sleep 1 second. 472*640235e2SEnji Cooper * 4. the child thread with low priority will call _sched_protect to increase 473*640235e2SEnji Cooper * its protect priority. 474*640235e2SEnji Cooper * 5. We verify the thread with low priority runs first. 475*640235e2SEnji Cooper * 476*640235e2SEnji Cooper * Why does it work? From the main thread, we launched the high 477*640235e2SEnji Cooper * priority thread first. This gives this thread the benefit of 478*640235e2SEnji Cooper * starting first. The low priority thread did not call _sched_protect(2). 479*640235e2SEnji Cooper * The high priority thread should finish the task first. After each 480*640235e2SEnji Cooper * round of computation, we call sleep, to put the task into the 481*640235e2SEnji Cooper * sleep queue, and wake up again after the timer expires. This 482*640235e2SEnji Cooper * gives the scheduler the chance to decide which task to run. So, 483*640235e2SEnji Cooper * the thread with real high priority will always block the thread 484*640235e2SEnji Cooper * with real low priority. 485*640235e2SEnji Cooper * 486*640235e2SEnji Cooper */ 487*640235e2SEnji Cooper ATF_TC_BODY(mutex6, tc) 488*640235e2SEnji Cooper { 489*640235e2SEnji Cooper struct sched_param param; 490*640235e2SEnji Cooper int res; 491*640235e2SEnji Cooper pthread_t high, low; 492*640235e2SEnji Cooper 493*640235e2SEnji Cooper min_fifo_prio = sched_get_priority_min(SCHED_FIFO); 494*640235e2SEnji Cooper max_fifo_prio = sched_get_priority_max(SCHED_FIFO); 495*640235e2SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL)); 496*640235e2SEnji Cooper printf("min_fifo_prio = %d, max_fifo_info = %d\n", min_fifo_prio, 497*640235e2SEnji Cooper max_fifo_prio); 498*640235e2SEnji Cooper 499*640235e2SEnji Cooper param.sched_priority = min_fifo_prio; 500*640235e2SEnji Cooper res = sched_setscheduler(getpid(), SCHED_FIFO, ¶m); 501*640235e2SEnji Cooper printf("previous policy used = %d\n", res); 502*640235e2SEnji Cooper 503*640235e2SEnji Cooper res = sched_getscheduler(getpid()); 504*640235e2SEnji Cooper ATF_REQUIRE_EQ(res, 1); 505*640235e2SEnji Cooper PTHREAD_REQUIRE(pthread_create(&high, NULL, high_prio, NULL)); 506*640235e2SEnji Cooper PTHREAD_REQUIRE(pthread_create(&low, NULL, low_prio, NULL)); 507*640235e2SEnji Cooper sleep(5); 508*640235e2SEnji Cooper PTHREAD_REQUIRE(pthread_join(low, NULL)); 509*640235e2SEnji Cooper PTHREAD_REQUIRE(pthread_join(high, NULL)); 510*640235e2SEnji Cooper 511*640235e2SEnji Cooper ATF_REQUIRE_EQ(start, 1); 512*640235e2SEnji Cooper } 513*640235e2SEnji Cooper #endif 514*640235e2SEnji Cooper 515*640235e2SEnji Cooper ATF_TC(mutexattr1); 516*640235e2SEnji Cooper ATF_TC_HEAD(mutexattr1, tc) 517*640235e2SEnji Cooper { 518*640235e2SEnji Cooper atf_tc_set_md_var(tc, "descr", "Checks mutexattr"); 519*640235e2SEnji Cooper } 520*640235e2SEnji Cooper 521*640235e2SEnji Cooper ATF_TC_BODY(mutexattr1, tc) 522*640235e2SEnji Cooper { 523*640235e2SEnji Cooper pthread_mutexattr_t mattr; 524*640235e2SEnji Cooper int protocol, target; 525*640235e2SEnji Cooper 526*640235e2SEnji Cooper PTHREAD_REQUIRE(pthread_mutexattr_init(&mattr)); 527*640235e2SEnji Cooper 528*640235e2SEnji Cooper target = PTHREAD_PRIO_NONE; 529*640235e2SEnji Cooper PTHREAD_REQUIRE(pthread_mutexattr_setprotocol(&mattr, target)); 530*640235e2SEnji Cooper PTHREAD_REQUIRE(pthread_mutexattr_getprotocol(&mattr, &protocol)); 531*640235e2SEnji Cooper ATF_REQUIRE_EQ(protocol, target); 532*640235e2SEnji Cooper 533*640235e2SEnji Cooper /* 534*640235e2SEnji Cooper target = PTHREAD_PRIO_INHERIT; 535*640235e2SEnji Cooper PTHREAD_REQUIRE(pthread_mutexattr_setprotocol(&mattr, target)); 536*640235e2SEnji Cooper PTHREAD_REQUIRE(pthread_mutexattr_getprotocol(&mattr, &protocol)); 537*640235e2SEnji Cooper ATF_REQUIRE_EQ(protocol, target); 538*640235e2SEnji Cooper */ 539*640235e2SEnji Cooper 540*640235e2SEnji Cooper target = PTHREAD_PRIO_PROTECT; 541*640235e2SEnji Cooper PTHREAD_REQUIRE(pthread_mutexattr_setprotocol(&mattr, target)); 542*640235e2SEnji Cooper PTHREAD_REQUIRE(pthread_mutexattr_getprotocol(&mattr, &protocol)); 543*640235e2SEnji Cooper ATF_REQUIRE_EQ(protocol, target); 544*640235e2SEnji Cooper } 545*640235e2SEnji Cooper 546*640235e2SEnji Cooper ATF_TC(mutexattr2); 547*640235e2SEnji Cooper ATF_TC_HEAD(mutexattr2, tc) 548*640235e2SEnji Cooper { 549*640235e2SEnji Cooper atf_tc_set_md_var(tc, "descr", "Checks mutexattr"); 550*640235e2SEnji Cooper } 551*640235e2SEnji Cooper 552*640235e2SEnji Cooper ATF_TC_BODY(mutexattr2, tc) 553*640235e2SEnji Cooper { 554*640235e2SEnji Cooper pthread_mutexattr_t mattr; 555*640235e2SEnji Cooper 556*640235e2SEnji Cooper PTHREAD_REQUIRE(pthread_mutexattr_init(&mattr)); 557*640235e2SEnji Cooper int max_prio = sched_get_priority_max(SCHED_FIFO); 558*640235e2SEnji Cooper int min_prio = sched_get_priority_min(SCHED_FIFO); 559*640235e2SEnji Cooper for (int i = min_prio; i <= max_prio; i++) { 560*640235e2SEnji Cooper int prioceiling; 561*640235e2SEnji Cooper PTHREAD_REQUIRE(pthread_mutexattr_setprioceiling(&mattr, i)); 562*640235e2SEnji Cooper PTHREAD_REQUIRE(pthread_mutexattr_getprioceiling(&mattr, 563*640235e2SEnji Cooper &prioceiling)); 564*640235e2SEnji Cooper ATF_REQUIRE_EQ(i, prioceiling); 565*640235e2SEnji Cooper } 566*640235e2SEnji Cooper } 567*640235e2SEnji Cooper 56857718be8SEnji Cooper ATF_TP_ADD_TCS(tp) 56957718be8SEnji Cooper { 57057718be8SEnji Cooper ATF_TP_ADD_TC(tp, mutex1); 57157718be8SEnji Cooper ATF_TP_ADD_TC(tp, mutex2); 57257718be8SEnji Cooper ATF_TP_ADD_TC(tp, mutex3); 57357718be8SEnji Cooper ATF_TP_ADD_TC(tp, mutex4); 574*640235e2SEnji Cooper #ifdef __NetBSD__ 575*640235e2SEnji Cooper ATF_TP_ADD_TC(tp, mutex5); 576*640235e2SEnji Cooper ATF_TP_ADD_TC(tp, mutex6); 577*640235e2SEnji Cooper #endif 578*640235e2SEnji Cooper ATF_TP_ADD_TC(tp, mutexattr1); 579*640235e2SEnji Cooper ATF_TP_ADD_TC(tp, mutexattr2); 58057718be8SEnji Cooper 58157718be8SEnji Cooper return atf_no_error(); 58257718be8SEnji Cooper } 583