Home | History | Annotate | Line # | Download | only in librt
      1 /* $NetBSD: t_sched.c,v 1.6 2017/12/24 17:37:23 christos Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2011 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Jukka Ruohonen.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 #include <sys/cdefs.h>
     32 __RCSID("$NetBSD: t_sched.c,v 1.6 2017/12/24 17:37:23 christos Exp $");
     33 
     34 #include <sys/param.h>	/* PRI_NONE */
     35 #include <sched.h>
     36 #include <limits.h>
     37 #include <unistd.h>
     38 
     39 #include <atf-c.h>
     40 
     41 static void	 sched_priority_set(int, int);
     42 
     43 ATF_TC(sched_getparam);
     44 ATF_TC_HEAD(sched_getparam, tc)
     45 {
     46 	atf_tc_set_md_var(tc, "descr", "A basic test of sched_getparam(3)");
     47 }
     48 
     49 ATF_TC_BODY(sched_getparam, tc)
     50 {
     51 	struct sched_param s1, s2;
     52 	pid_t p = getpid();
     53 
     54 	/*
     55 	 * IEEE Std 1003.1-2008: if the supplied pid is zero,
     56 	 * the parameters for the calling process are returned.
     57 	 */
     58 	ATF_REQUIRE(sched_getparam(0, &s1) == 0);
     59 	ATF_REQUIRE(sched_getparam(p, &s2) == 0);
     60 
     61 	ATF_CHECK_EQ(s1.sched_priority, s2.sched_priority);
     62 
     63 	/*
     64 	 * The behavior is undefined but should error
     65 	 * out in case the supplied PID is negative.
     66 	 */
     67 	ATF_REQUIRE(sched_getparam(-1, &s1) != 0);
     68 }
     69 
     70 ATF_TC(sched_priority);
     71 ATF_TC_HEAD(sched_priority, tc)
     72 {
     73 	atf_tc_set_md_var(tc, "descr", "Test sched(3) priority ranges");
     74 }
     75 
     76 ATF_TC_BODY(sched_priority, tc)
     77 {
     78 	static const int pol[3] = { SCHED_OTHER, SCHED_FIFO, SCHED_RR };
     79 	int pmax, pmin;
     80 	size_t i;
     81 
     82 	/*
     83 	 * Test that bogus values error out.
     84 	 */
     85 	if (INT_MAX > SCHED_RR)
     86 		ATF_REQUIRE(sched_get_priority_max(INT_MAX) != 0);
     87 
     88 	if (-INT_MAX < SCHED_OTHER)
     89 		ATF_REQUIRE(sched_get_priority_max(-INT_MAX) != 0);
     90 
     91 	/*
     92 	 * Test that we have a valid range.
     93 	 */
     94 	for (i = 0; i < __arraycount(pol); i++) {
     95 
     96 		pmax = sched_get_priority_max(pol[i]);
     97 		pmin = sched_get_priority_min(pol[i]);
     98 		if (pol[i] == SCHED_OTHER) {
     99 			ATF_REQUIRE(pmax == PRI_NONE);
    100 			ATF_REQUIRE(pmin == PRI_NONE);
    101 		} else {
    102 			ATF_REQUIRE(pmax != -1);
    103 			ATF_REQUIRE(pmin != -1);
    104 			ATF_REQUIRE(pmax > pmin);
    105 		}
    106 	}
    107 }
    108 
    109 static void
    110 sched_priority_set(int pri, int pol)
    111 {
    112 	struct sched_param sched;
    113 
    114 	sched.sched_priority = pri;
    115 
    116 	ATF_REQUIRE(pri >= 0);
    117 	ATF_REQUIRE(sched_setscheduler(0, pol, &sched) == 0);
    118 
    119 	/*
    120 	 * Test that the policy was changed.
    121 	 */
    122 	ATF_CHECK_EQ(sched_getscheduler(0), pol);
    123 
    124 	/*
    125 	 * And that sched_getparam(3) returns the new priority.
    126 	 */
    127 	sched.sched_priority = -1;
    128 
    129 	ATF_REQUIRE(sched_getparam(0, &sched) == 0);
    130 	ATF_CHECK_EQ(sched.sched_priority, pri);
    131 }
    132 
    133 ATF_TC(sched_setscheduler_1);
    134 ATF_TC_HEAD(sched_setscheduler_1, tc)
    135 {
    136 	atf_tc_set_md_var(tc, "descr", "sched_setscheduler(3), max, RR");
    137 	atf_tc_set_md_var(tc, "require.user", "root");
    138 }
    139 
    140 ATF_TC_BODY(sched_setscheduler_1, tc)
    141 {
    142 	int pri;
    143 
    144 	pri = sched_get_priority_max(SCHED_RR);
    145 	sched_priority_set(pri, SCHED_RR);
    146 }
    147 
    148 ATF_TC(sched_setscheduler_2);
    149 ATF_TC_HEAD(sched_setscheduler_2, tc)
    150 {
    151 	atf_tc_set_md_var(tc, "descr", "sched_setscheduler(3), min, RR");
    152 	atf_tc_set_md_var(tc, "require.user", "root");
    153 }
    154 
    155 ATF_TC_BODY(sched_setscheduler_2, tc)
    156 {
    157 	int pri;
    158 
    159 	pri = sched_get_priority_min(SCHED_RR);
    160 	sched_priority_set(pri, SCHED_RR);
    161 }
    162 
    163 ATF_TC(sched_setscheduler_3);
    164 ATF_TC_HEAD(sched_setscheduler_3, tc)
    165 {
    166 	atf_tc_set_md_var(tc, "descr", "sched_setscheduler(3), max, FIFO");
    167 	atf_tc_set_md_var(tc, "require.user", "root");
    168 }
    169 
    170 ATF_TC_BODY(sched_setscheduler_3, tc)
    171 {
    172 	int pri;
    173 
    174 	pri = sched_get_priority_max(SCHED_FIFO);
    175 	sched_priority_set(pri, SCHED_FIFO);
    176 }
    177 
    178 ATF_TC(sched_setscheduler_4);
    179 ATF_TC_HEAD(sched_setscheduler_4, tc)
    180 {
    181 	atf_tc_set_md_var(tc, "descr", "sched_setscheduler(3), min, FIFO");
    182 	atf_tc_set_md_var(tc, "require.user", "root");
    183 }
    184 
    185 ATF_TC_BODY(sched_setscheduler_4, tc)
    186 {
    187 	int pri;
    188 
    189 	pri = sched_get_priority_min(SCHED_FIFO);
    190 	sched_priority_set(pri, SCHED_FIFO);
    191 }
    192 
    193 ATF_TC(sched_rr_get_interval_1);
    194 ATF_TC_HEAD(sched_rr_get_interval_1, tc)
    195 {
    196 	atf_tc_set_md_var(tc, "descr", "Test sched_rr_get_interval(3), #1"
    197 	    " (PR lib/44768)");
    198 	atf_tc_set_md_var(tc, "require.user", "root");
    199 }
    200 
    201 ATF_TC_BODY(sched_rr_get_interval_1, tc)
    202 {
    203 	struct timespec tv;
    204 	int pri;
    205 
    206 	pri = sched_get_priority_min(SCHED_RR);
    207 	sched_priority_set(pri, SCHED_RR);
    208 
    209 	/*
    210 	 * This should fail with ESRCH for invalid PID.
    211 	 */
    212 	ATF_REQUIRE(sched_rr_get_interval(-INT_MAX, &tv) != 0);
    213 }
    214 
    215 ATF_TC(sched_rr_get_interval_2);
    216 ATF_TC_HEAD(sched_rr_get_interval_2, tc)
    217 {
    218 	atf_tc_set_md_var(tc, "descr", "Test sched_rr_get_interval(3), #2");
    219 	atf_tc_set_md_var(tc, "require.user", "root");
    220 }
    221 
    222 ATF_TC_BODY(sched_rr_get_interval_2, tc)
    223 {
    224 	struct timespec tv1, tv2;
    225 	int pri;
    226 
    227 	pri = sched_get_priority_min(SCHED_RR);
    228 	sched_priority_set(pri, SCHED_RR);
    229 
    230 	tv1.tv_sec = tv2.tv_sec = -1;
    231 	tv1.tv_nsec = tv2.tv_nsec = -1;
    232 
    233 	ATF_REQUIRE(sched_rr_get_interval(0, &tv1) == 0);
    234 	ATF_REQUIRE(sched_rr_get_interval(getpid(), &tv2) == 0);
    235 
    236 	ATF_REQUIRE(tv1.tv_sec != -1);
    237 	ATF_REQUIRE(tv2.tv_sec != -1);
    238 
    239 	ATF_REQUIRE(tv1.tv_nsec != -1);
    240 	ATF_REQUIRE(tv2.tv_nsec != -1);
    241 
    242 	ATF_REQUIRE(tv1.tv_sec == tv2.tv_sec);
    243 	ATF_REQUIRE(tv1.tv_nsec == tv2.tv_nsec);
    244 }
    245 
    246 ATF_TP_ADD_TCS(tp)
    247 {
    248 
    249 	ATF_TP_ADD_TC(tp, sched_getparam);
    250 	ATF_TP_ADD_TC(tp, sched_priority);
    251 
    252 	ATF_TP_ADD_TC(tp, sched_setscheduler_1);
    253 	ATF_TP_ADD_TC(tp, sched_setscheduler_2);
    254 	ATF_TP_ADD_TC(tp, sched_setscheduler_3);
    255 	ATF_TP_ADD_TC(tp, sched_setscheduler_4);
    256 
    257 	ATF_TP_ADD_TC(tp, sched_rr_get_interval_1);
    258 	ATF_TP_ADD_TC(tp, sched_rr_get_interval_2);
    259 
    260 	return atf_no_error();
    261 }
    262