1 1.5 riastrad /* $NetBSD: t_getitimer.c,v 1.5 2024/12/19 20:07:16 riastradh Exp $ */ 2 1.1 jruoho 3 1.1 jruoho /*- 4 1.1 jruoho * Copyright (c) 2011 The NetBSD Foundation, Inc. 5 1.1 jruoho * All rights reserved. 6 1.1 jruoho * 7 1.1 jruoho * This code is derived from software contributed to The NetBSD Foundation 8 1.1 jruoho * by Jukka Ruohonen. 9 1.1 jruoho * 10 1.1 jruoho * Redistribution and use in source and binary forms, with or without 11 1.1 jruoho * modification, are permitted provided that the following conditions 12 1.1 jruoho * are met: 13 1.1 jruoho * 1. Redistributions of source code must retain the above copyright 14 1.1 jruoho * notice, this list of conditions and the following disclaimer. 15 1.1 jruoho * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 jruoho * notice, this list of conditions and the following disclaimer in the 17 1.1 jruoho * documentation and/or other materials provided with the distribution. 18 1.1 jruoho * 19 1.1 jruoho * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 jruoho * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 jruoho * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 jruoho * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 jruoho * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 jruoho * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 jruoho * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 jruoho * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 jruoho * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 jruoho * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 jruoho * POSSIBILITY OF SUCH DAMAGE. 30 1.1 jruoho */ 31 1.1 jruoho #include <sys/cdefs.h> 32 1.5 riastrad __RCSID("$NetBSD: t_getitimer.c,v 1.5 2024/12/19 20:07:16 riastradh Exp $"); 33 1.1 jruoho 34 1.1 jruoho #include <sys/time.h> 35 1.1 jruoho 36 1.1 jruoho #include <atf-c.h> 37 1.1 jruoho #include <errno.h> 38 1.1 jruoho #include <limits.h> 39 1.1 jruoho #include <signal.h> 40 1.1 jruoho #include <string.h> 41 1.1 jruoho #include <unistd.h> 42 1.1 jruoho 43 1.5 riastrad #include "h_macros.h" 44 1.5 riastrad 45 1.5 riastrad static sig_atomic_t fired; 46 1.5 riastrad static void sighandler(int); 47 1.1 jruoho 48 1.1 jruoho static void 49 1.1 jruoho sighandler(int signo) 50 1.1 jruoho { 51 1.1 jruoho 52 1.1 jruoho if (signo == SIGALRM || signo == SIGVTALRM) 53 1.5 riastrad fired = 1; 54 1.1 jruoho } 55 1.1 jruoho 56 1.1 jruoho ATF_TC(getitimer_empty); 57 1.1 jruoho ATF_TC_HEAD(getitimer_empty, tc) 58 1.1 jruoho { 59 1.1 jruoho atf_tc_set_md_var(tc, "descr", "getitimer(2) before setitimer(2)"); 60 1.1 jruoho } 61 1.1 jruoho 62 1.1 jruoho ATF_TC_BODY(getitimer_empty, tc) 63 1.1 jruoho { 64 1.1 jruoho struct itimerval it; 65 1.1 jruoho 66 1.1 jruoho /* 67 1.1 jruoho * Verify that the passed structure remains 68 1.1 jruoho * empty after calling getitimer(2) but before 69 1.1 jruoho * actually arming the timer with setitimer(2). 70 1.1 jruoho */ 71 1.1 jruoho (void)memset(&it, 0, sizeof(struct itimerval)); 72 1.1 jruoho 73 1.1 jruoho ATF_REQUIRE(getitimer(ITIMER_REAL, &it) == 0); 74 1.1 jruoho 75 1.1 jruoho if (it.it_value.tv_sec != 0 || it.it_value.tv_usec != 0) 76 1.1 jruoho goto fail; 77 1.1 jruoho 78 1.1 jruoho ATF_REQUIRE(getitimer(ITIMER_VIRTUAL, &it) == 0); 79 1.1 jruoho 80 1.1 jruoho if (it.it_value.tv_sec != 0 || it.it_value.tv_usec != 0) 81 1.1 jruoho goto fail; 82 1.1 jruoho 83 1.1 jruoho ATF_REQUIRE(getitimer(ITIMER_PROF, &it) == 0); 84 1.1 jruoho 85 1.1 jruoho if (it.it_value.tv_sec != 0 || it.it_value.tv_usec != 0) 86 1.1 jruoho goto fail; 87 1.1 jruoho 88 1.1 jruoho return; 89 1.1 jruoho 90 1.1 jruoho fail: 91 1.4 andvar atf_tc_fail("getitimer(2) modified the timer before it was armed"); 92 1.1 jruoho } 93 1.1 jruoho 94 1.1 jruoho ATF_TC(getitimer_err); 95 1.1 jruoho ATF_TC_HEAD(getitimer_err, tc) 96 1.1 jruoho { 97 1.1 jruoho atf_tc_set_md_var(tc, "descr", "Test errors from getitimer(2)"); 98 1.1 jruoho } 99 1.1 jruoho 100 1.1 jruoho ATF_TC_BODY(getitimer_err, tc) 101 1.1 jruoho { 102 1.1 jruoho struct itimerval it; 103 1.1 jruoho 104 1.1 jruoho errno = 0; 105 1.1 jruoho ATF_REQUIRE_ERRNO(EINVAL, getitimer(-1, &it) == -1); 106 1.1 jruoho 107 1.1 jruoho errno = 0; 108 1.1 jruoho ATF_REQUIRE_ERRNO(EINVAL, getitimer(INT_MAX, &it) == -1); 109 1.1 jruoho 110 1.1 jruoho errno = 0; 111 1.1 jruoho ATF_REQUIRE_ERRNO(EFAULT, getitimer(ITIMER_REAL, (void *)-1) == -1); 112 1.1 jruoho } 113 1.1 jruoho 114 1.1 jruoho ATF_TC(setitimer_basic); 115 1.1 jruoho ATF_TC_HEAD(setitimer_basic, tc) 116 1.1 jruoho { 117 1.1 jruoho atf_tc_set_md_var(tc, "descr", "A basic test of setitimer(2)"); 118 1.1 jruoho } 119 1.1 jruoho 120 1.1 jruoho ATF_TC_BODY(setitimer_basic, tc) 121 1.1 jruoho { 122 1.1 jruoho struct itimerval it; 123 1.1 jruoho 124 1.1 jruoho it.it_value.tv_sec = 0; 125 1.1 jruoho it.it_value.tv_usec = 100; 126 1.1 jruoho 127 1.1 jruoho it.it_interval.tv_sec = 0; 128 1.1 jruoho it.it_interval.tv_usec = 0; 129 1.1 jruoho 130 1.5 riastrad fired = 0; 131 1.1 jruoho ATF_REQUIRE(signal(SIGALRM, sighandler) != SIG_ERR); 132 1.1 jruoho ATF_REQUIRE(setitimer(ITIMER_REAL, &it, NULL) == 0); 133 1.1 jruoho 134 1.1 jruoho /* 135 1.1 jruoho * Although the interaction between 136 1.1 jruoho * setitimer(2) and sleep(3) can be 137 1.1 jruoho * unspecified, it is assumed that one 138 1.1 jruoho * second suspension will be enough for 139 1.1 jruoho * the timer to fire. 140 1.1 jruoho */ 141 1.1 jruoho (void)sleep(1); 142 1.1 jruoho 143 1.5 riastrad if (!fired) 144 1.1 jruoho atf_tc_fail("timer did not fire"); 145 1.1 jruoho } 146 1.1 jruoho 147 1.1 jruoho ATF_TC(setitimer_err); 148 1.1 jruoho ATF_TC_HEAD(setitimer_err, tc) 149 1.1 jruoho { 150 1.2 christos atf_tc_set_md_var(tc, "descr", "Test errors from setitimer(2)" 151 1.2 christos " (PR standards/44927)"); 152 1.1 jruoho } 153 1.1 jruoho 154 1.1 jruoho ATF_TC_BODY(setitimer_err, tc) 155 1.1 jruoho { 156 1.1 jruoho struct itimerval it, ot; 157 1.1 jruoho 158 1.1 jruoho errno = 0; 159 1.1 jruoho ATF_REQUIRE_ERRNO(EINVAL, setitimer(-1, &it, &ot) == -1); 160 1.1 jruoho 161 1.1 jruoho errno = 0; 162 1.1 jruoho ATF_REQUIRE_ERRNO(EINVAL, setitimer(INT_MAX, &it, &ot) == -1); 163 1.1 jruoho 164 1.1 jruoho errno = 0; 165 1.1 jruoho ATF_REQUIRE_ERRNO(EFAULT, setitimer(ITIMER_REAL,(void*)-1, &ot) == -1); 166 1.1 jruoho } 167 1.1 jruoho 168 1.1 jruoho ATF_TC(setitimer_old); 169 1.1 jruoho ATF_TC_HEAD(setitimer_old, tc) 170 1.1 jruoho { 171 1.1 jruoho atf_tc_set_md_var(tc, "descr", "Test old values from setitimer(2)"); 172 1.1 jruoho } 173 1.1 jruoho 174 1.1 jruoho ATF_TC_BODY(setitimer_old, tc) 175 1.1 jruoho { 176 1.1 jruoho struct itimerval it, ot; 177 1.1 jruoho 178 1.1 jruoho /* 179 1.3 gson * Make two calls; the second one should store the old 180 1.3 gson * timer value which should be the same as that set in 181 1.3 gson * the first call, or slightly less due to time passing 182 1.3 gson * between the two calls. 183 1.1 jruoho */ 184 1.1 jruoho it.it_value.tv_sec = 4; 185 1.3 gson it.it_value.tv_usec = 999999; 186 1.1 jruoho 187 1.1 jruoho it.it_interval.tv_sec = 0; 188 1.1 jruoho it.it_interval.tv_usec = 0; 189 1.1 jruoho 190 1.1 jruoho ATF_REQUIRE(setitimer(ITIMER_REAL, &it, &ot) == 0); 191 1.1 jruoho 192 1.1 jruoho it.it_value.tv_sec = 2; 193 1.1 jruoho it.it_value.tv_usec = 1; 194 1.1 jruoho 195 1.1 jruoho it.it_interval.tv_sec = 0; 196 1.1 jruoho it.it_interval.tv_usec = 0; 197 1.1 jruoho 198 1.1 jruoho ATF_REQUIRE(setitimer(ITIMER_REAL, &it, &ot) == 0); 199 1.1 jruoho 200 1.3 gson /* Check seconds only as microseconds may have decremented */ 201 1.3 gson if (ot.it_value.tv_sec != 4) 202 1.1 jruoho atf_tc_fail("setitimer(2) did not store old values"); 203 1.1 jruoho } 204 1.1 jruoho 205 1.5 riastrad ATF_TC(setitimer_invalidtime); 206 1.5 riastrad ATF_TC_HEAD(setitimer_invalidtime, tc) 207 1.5 riastrad { 208 1.5 riastrad atf_tc_set_md_var(tc, "descr", "Test invalid values in setitimer(2)"); 209 1.5 riastrad } 210 1.5 riastrad 211 1.5 riastrad ATF_TC_BODY(setitimer_invalidtime, tc) 212 1.5 riastrad { 213 1.5 riastrad const struct itimerval it[] = { 214 1.5 riastrad [0] = { .it_value = {-1, 0} }, 215 1.5 riastrad [1] = { .it_value = {0, -1} }, 216 1.5 riastrad [2] = { .it_value = {0, 1000001} }, 217 1.5 riastrad [3] = { .it_value = {1, 0}, .it_interval = {-1, 0} }, 218 1.5 riastrad [4] = { .it_value = {1, 0}, .it_interval = {0, -1} }, 219 1.5 riastrad [5] = { .it_value = {1, 0}, .it_interval = {0, 1000001} }, 220 1.5 riastrad }; 221 1.5 riastrad sigset_t sigs, mask; 222 1.5 riastrad unsigned i; 223 1.5 riastrad 224 1.5 riastrad RL(sigemptyset(&sigs)); 225 1.5 riastrad RL(sigaddset(&sigs, SIGALRM)); 226 1.5 riastrad RL(sigprocmask(SIG_BLOCK, &sigs, &mask)); 227 1.5 riastrad 228 1.5 riastrad for (i = 0; i < __arraycount(it); i++) { 229 1.5 riastrad fprintf(stderr, "case %u\n", i); 230 1.5 riastrad ATF_CHECK_ERRNO(EINVAL, 231 1.5 riastrad setitimer(ITIMER_REAL, &it[i], NULL) == -1); 232 1.5 riastrad } 233 1.5 riastrad 234 1.5 riastrad /* Wait up to 2sec to make sure no timer got set anyway. */ 235 1.5 riastrad ATF_CHECK_ERRNO(EAGAIN, 236 1.5 riastrad sigtimedwait(&sigs, NULL, &(const struct timespec){2, 0}) == -1); 237 1.5 riastrad RL(sigprocmask(SIG_SETMASK, &mask, NULL)); 238 1.5 riastrad } 239 1.5 riastrad 240 1.1 jruoho ATF_TP_ADD_TCS(tp) 241 1.1 jruoho { 242 1.1 jruoho 243 1.1 jruoho ATF_TP_ADD_TC(tp, getitimer_empty); 244 1.1 jruoho ATF_TP_ADD_TC(tp, getitimer_err); 245 1.1 jruoho ATF_TP_ADD_TC(tp, setitimer_basic); 246 1.1 jruoho ATF_TP_ADD_TC(tp, setitimer_err); 247 1.1 jruoho ATF_TP_ADD_TC(tp, setitimer_old); 248 1.5 riastrad ATF_TP_ADD_TC(tp, setitimer_invalidtime); 249 1.1 jruoho 250 1.1 jruoho return atf_no_error(); 251 1.1 jruoho } 252