1*3a6e4efaSriastradh /* $NetBSD: t_getitimer.c,v 1.5 2024/12/19 20:07:16 riastradh Exp $ */ 2068fb4f1Sjruoho 3068fb4f1Sjruoho /*- 4068fb4f1Sjruoho * Copyright (c) 2011 The NetBSD Foundation, Inc. 5068fb4f1Sjruoho * All rights reserved. 6068fb4f1Sjruoho * 7068fb4f1Sjruoho * This code is derived from software contributed to The NetBSD Foundation 8068fb4f1Sjruoho * by Jukka Ruohonen. 9068fb4f1Sjruoho * 10068fb4f1Sjruoho * Redistribution and use in source and binary forms, with or without 11068fb4f1Sjruoho * modification, are permitted provided that the following conditions 12068fb4f1Sjruoho * are met: 13068fb4f1Sjruoho * 1. Redistributions of source code must retain the above copyright 14068fb4f1Sjruoho * notice, this list of conditions and the following disclaimer. 15068fb4f1Sjruoho * 2. Redistributions in binary form must reproduce the above copyright 16068fb4f1Sjruoho * notice, this list of conditions and the following disclaimer in the 17068fb4f1Sjruoho * documentation and/or other materials provided with the distribution. 18068fb4f1Sjruoho * 19068fb4f1Sjruoho * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20068fb4f1Sjruoho * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21068fb4f1Sjruoho * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22068fb4f1Sjruoho * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23068fb4f1Sjruoho * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24068fb4f1Sjruoho * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25068fb4f1Sjruoho * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26068fb4f1Sjruoho * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27068fb4f1Sjruoho * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28068fb4f1Sjruoho * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29068fb4f1Sjruoho * POSSIBILITY OF SUCH DAMAGE. 30068fb4f1Sjruoho */ 31068fb4f1Sjruoho #include <sys/cdefs.h> 32*3a6e4efaSriastradh __RCSID("$NetBSD: t_getitimer.c,v 1.5 2024/12/19 20:07:16 riastradh Exp $"); 33068fb4f1Sjruoho 34068fb4f1Sjruoho #include <sys/time.h> 35068fb4f1Sjruoho 36068fb4f1Sjruoho #include <atf-c.h> 37068fb4f1Sjruoho #include <errno.h> 38068fb4f1Sjruoho #include <limits.h> 39068fb4f1Sjruoho #include <signal.h> 40068fb4f1Sjruoho #include <string.h> 41068fb4f1Sjruoho #include <unistd.h> 42068fb4f1Sjruoho 43*3a6e4efaSriastradh #include "h_macros.h" 44*3a6e4efaSriastradh 45*3a6e4efaSriastradh static sig_atomic_t fired; 46068fb4f1Sjruoho static void sighandler(int); 47068fb4f1Sjruoho 48068fb4f1Sjruoho static void 49068fb4f1Sjruoho sighandler(int signo) 50068fb4f1Sjruoho { 51068fb4f1Sjruoho 52068fb4f1Sjruoho if (signo == SIGALRM || signo == SIGVTALRM) 53*3a6e4efaSriastradh fired = 1; 54068fb4f1Sjruoho } 55068fb4f1Sjruoho 56068fb4f1Sjruoho ATF_TC(getitimer_empty); 57068fb4f1Sjruoho ATF_TC_HEAD(getitimer_empty, tc) 58068fb4f1Sjruoho { 59068fb4f1Sjruoho atf_tc_set_md_var(tc, "descr", "getitimer(2) before setitimer(2)"); 60068fb4f1Sjruoho } 61068fb4f1Sjruoho 62068fb4f1Sjruoho ATF_TC_BODY(getitimer_empty, tc) 63068fb4f1Sjruoho { 64068fb4f1Sjruoho struct itimerval it; 65068fb4f1Sjruoho 66068fb4f1Sjruoho /* 67068fb4f1Sjruoho * Verify that the passed structure remains 68068fb4f1Sjruoho * empty after calling getitimer(2) but before 69068fb4f1Sjruoho * actually arming the timer with setitimer(2). 70068fb4f1Sjruoho */ 71068fb4f1Sjruoho (void)memset(&it, 0, sizeof(struct itimerval)); 72068fb4f1Sjruoho 73068fb4f1Sjruoho ATF_REQUIRE(getitimer(ITIMER_REAL, &it) == 0); 74068fb4f1Sjruoho 75068fb4f1Sjruoho if (it.it_value.tv_sec != 0 || it.it_value.tv_usec != 0) 76068fb4f1Sjruoho goto fail; 77068fb4f1Sjruoho 78068fb4f1Sjruoho ATF_REQUIRE(getitimer(ITIMER_VIRTUAL, &it) == 0); 79068fb4f1Sjruoho 80068fb4f1Sjruoho if (it.it_value.tv_sec != 0 || it.it_value.tv_usec != 0) 81068fb4f1Sjruoho goto fail; 82068fb4f1Sjruoho 83068fb4f1Sjruoho ATF_REQUIRE(getitimer(ITIMER_PROF, &it) == 0); 84068fb4f1Sjruoho 85068fb4f1Sjruoho if (it.it_value.tv_sec != 0 || it.it_value.tv_usec != 0) 86068fb4f1Sjruoho goto fail; 87068fb4f1Sjruoho 88068fb4f1Sjruoho return; 89068fb4f1Sjruoho 90068fb4f1Sjruoho fail: 91e82c4d9bSandvar atf_tc_fail("getitimer(2) modified the timer before it was armed"); 92068fb4f1Sjruoho } 93068fb4f1Sjruoho 94068fb4f1Sjruoho ATF_TC(getitimer_err); 95068fb4f1Sjruoho ATF_TC_HEAD(getitimer_err, tc) 96068fb4f1Sjruoho { 97068fb4f1Sjruoho atf_tc_set_md_var(tc, "descr", "Test errors from getitimer(2)"); 98068fb4f1Sjruoho } 99068fb4f1Sjruoho 100068fb4f1Sjruoho ATF_TC_BODY(getitimer_err, tc) 101068fb4f1Sjruoho { 102068fb4f1Sjruoho struct itimerval it; 103068fb4f1Sjruoho 104068fb4f1Sjruoho errno = 0; 105068fb4f1Sjruoho ATF_REQUIRE_ERRNO(EINVAL, getitimer(-1, &it) == -1); 106068fb4f1Sjruoho 107068fb4f1Sjruoho errno = 0; 108068fb4f1Sjruoho ATF_REQUIRE_ERRNO(EINVAL, getitimer(INT_MAX, &it) == -1); 109068fb4f1Sjruoho 110068fb4f1Sjruoho errno = 0; 111068fb4f1Sjruoho ATF_REQUIRE_ERRNO(EFAULT, getitimer(ITIMER_REAL, (void *)-1) == -1); 112068fb4f1Sjruoho } 113068fb4f1Sjruoho 114068fb4f1Sjruoho ATF_TC(setitimer_basic); 115068fb4f1Sjruoho ATF_TC_HEAD(setitimer_basic, tc) 116068fb4f1Sjruoho { 117068fb4f1Sjruoho atf_tc_set_md_var(tc, "descr", "A basic test of setitimer(2)"); 118068fb4f1Sjruoho } 119068fb4f1Sjruoho 120068fb4f1Sjruoho ATF_TC_BODY(setitimer_basic, tc) 121068fb4f1Sjruoho { 122068fb4f1Sjruoho struct itimerval it; 123068fb4f1Sjruoho 124068fb4f1Sjruoho it.it_value.tv_sec = 0; 125068fb4f1Sjruoho it.it_value.tv_usec = 100; 126068fb4f1Sjruoho 127068fb4f1Sjruoho it.it_interval.tv_sec = 0; 128068fb4f1Sjruoho it.it_interval.tv_usec = 0; 129068fb4f1Sjruoho 130*3a6e4efaSriastradh fired = 0; 131068fb4f1Sjruoho ATF_REQUIRE(signal(SIGALRM, sighandler) != SIG_ERR); 132068fb4f1Sjruoho ATF_REQUIRE(setitimer(ITIMER_REAL, &it, NULL) == 0); 133068fb4f1Sjruoho 134068fb4f1Sjruoho /* 135068fb4f1Sjruoho * Although the interaction between 136068fb4f1Sjruoho * setitimer(2) and sleep(3) can be 137068fb4f1Sjruoho * unspecified, it is assumed that one 138068fb4f1Sjruoho * second suspension will be enough for 139068fb4f1Sjruoho * the timer to fire. 140068fb4f1Sjruoho */ 141068fb4f1Sjruoho (void)sleep(1); 142068fb4f1Sjruoho 143*3a6e4efaSriastradh if (!fired) 144068fb4f1Sjruoho atf_tc_fail("timer did not fire"); 145068fb4f1Sjruoho } 146068fb4f1Sjruoho 147068fb4f1Sjruoho ATF_TC(setitimer_err); 148068fb4f1Sjruoho ATF_TC_HEAD(setitimer_err, tc) 149068fb4f1Sjruoho { 150f6f28fd5Schristos atf_tc_set_md_var(tc, "descr", "Test errors from setitimer(2)" 151f6f28fd5Schristos " (PR standards/44927)"); 152068fb4f1Sjruoho } 153068fb4f1Sjruoho 154068fb4f1Sjruoho ATF_TC_BODY(setitimer_err, tc) 155068fb4f1Sjruoho { 156068fb4f1Sjruoho struct itimerval it, ot; 157068fb4f1Sjruoho 158068fb4f1Sjruoho errno = 0; 159068fb4f1Sjruoho ATF_REQUIRE_ERRNO(EINVAL, setitimer(-1, &it, &ot) == -1); 160068fb4f1Sjruoho 161068fb4f1Sjruoho errno = 0; 162068fb4f1Sjruoho ATF_REQUIRE_ERRNO(EINVAL, setitimer(INT_MAX, &it, &ot) == -1); 163068fb4f1Sjruoho 164068fb4f1Sjruoho errno = 0; 165068fb4f1Sjruoho ATF_REQUIRE_ERRNO(EFAULT, setitimer(ITIMER_REAL,(void*)-1, &ot) == -1); 166068fb4f1Sjruoho } 167068fb4f1Sjruoho 168068fb4f1Sjruoho ATF_TC(setitimer_old); 169068fb4f1Sjruoho ATF_TC_HEAD(setitimer_old, tc) 170068fb4f1Sjruoho { 171068fb4f1Sjruoho atf_tc_set_md_var(tc, "descr", "Test old values from setitimer(2)"); 172068fb4f1Sjruoho } 173068fb4f1Sjruoho 174068fb4f1Sjruoho ATF_TC_BODY(setitimer_old, tc) 175068fb4f1Sjruoho { 176068fb4f1Sjruoho struct itimerval it, ot; 177068fb4f1Sjruoho 178068fb4f1Sjruoho /* 179b9a5a0bbSgson * Make two calls; the second one should store the old 180b9a5a0bbSgson * timer value which should be the same as that set in 181b9a5a0bbSgson * the first call, or slightly less due to time passing 182b9a5a0bbSgson * between the two calls. 183068fb4f1Sjruoho */ 184068fb4f1Sjruoho it.it_value.tv_sec = 4; 185b9a5a0bbSgson it.it_value.tv_usec = 999999; 186068fb4f1Sjruoho 187068fb4f1Sjruoho it.it_interval.tv_sec = 0; 188068fb4f1Sjruoho it.it_interval.tv_usec = 0; 189068fb4f1Sjruoho 190068fb4f1Sjruoho ATF_REQUIRE(setitimer(ITIMER_REAL, &it, &ot) == 0); 191068fb4f1Sjruoho 192068fb4f1Sjruoho it.it_value.tv_sec = 2; 193068fb4f1Sjruoho it.it_value.tv_usec = 1; 194068fb4f1Sjruoho 195068fb4f1Sjruoho it.it_interval.tv_sec = 0; 196068fb4f1Sjruoho it.it_interval.tv_usec = 0; 197068fb4f1Sjruoho 198068fb4f1Sjruoho ATF_REQUIRE(setitimer(ITIMER_REAL, &it, &ot) == 0); 199068fb4f1Sjruoho 200b9a5a0bbSgson /* Check seconds only as microseconds may have decremented */ 201b9a5a0bbSgson if (ot.it_value.tv_sec != 4) 202068fb4f1Sjruoho atf_tc_fail("setitimer(2) did not store old values"); 203068fb4f1Sjruoho } 204068fb4f1Sjruoho 205*3a6e4efaSriastradh ATF_TC(setitimer_invalidtime); 206*3a6e4efaSriastradh ATF_TC_HEAD(setitimer_invalidtime, tc) 207*3a6e4efaSriastradh { 208*3a6e4efaSriastradh atf_tc_set_md_var(tc, "descr", "Test invalid values in setitimer(2)"); 209*3a6e4efaSriastradh } 210*3a6e4efaSriastradh 211*3a6e4efaSriastradh ATF_TC_BODY(setitimer_invalidtime, tc) 212*3a6e4efaSriastradh { 213*3a6e4efaSriastradh const struct itimerval it[] = { 214*3a6e4efaSriastradh [0] = { .it_value = {-1, 0} }, 215*3a6e4efaSriastradh [1] = { .it_value = {0, -1} }, 216*3a6e4efaSriastradh [2] = { .it_value = {0, 1000001} }, 217*3a6e4efaSriastradh [3] = { .it_value = {1, 0}, .it_interval = {-1, 0} }, 218*3a6e4efaSriastradh [4] = { .it_value = {1, 0}, .it_interval = {0, -1} }, 219*3a6e4efaSriastradh [5] = { .it_value = {1, 0}, .it_interval = {0, 1000001} }, 220*3a6e4efaSriastradh }; 221*3a6e4efaSriastradh sigset_t sigs, mask; 222*3a6e4efaSriastradh unsigned i; 223*3a6e4efaSriastradh 224*3a6e4efaSriastradh RL(sigemptyset(&sigs)); 225*3a6e4efaSriastradh RL(sigaddset(&sigs, SIGALRM)); 226*3a6e4efaSriastradh RL(sigprocmask(SIG_BLOCK, &sigs, &mask)); 227*3a6e4efaSriastradh 228*3a6e4efaSriastradh for (i = 0; i < __arraycount(it); i++) { 229*3a6e4efaSriastradh fprintf(stderr, "case %u\n", i); 230*3a6e4efaSriastradh ATF_CHECK_ERRNO(EINVAL, 231*3a6e4efaSriastradh setitimer(ITIMER_REAL, &it[i], NULL) == -1); 232*3a6e4efaSriastradh } 233*3a6e4efaSriastradh 234*3a6e4efaSriastradh /* Wait up to 2sec to make sure no timer got set anyway. */ 235*3a6e4efaSriastradh ATF_CHECK_ERRNO(EAGAIN, 236*3a6e4efaSriastradh sigtimedwait(&sigs, NULL, &(const struct timespec){2, 0}) == -1); 237*3a6e4efaSriastradh RL(sigprocmask(SIG_SETMASK, &mask, NULL)); 238*3a6e4efaSriastradh } 239*3a6e4efaSriastradh 240068fb4f1Sjruoho ATF_TP_ADD_TCS(tp) 241068fb4f1Sjruoho { 242068fb4f1Sjruoho 243068fb4f1Sjruoho ATF_TP_ADD_TC(tp, getitimer_empty); 244068fb4f1Sjruoho ATF_TP_ADD_TC(tp, getitimer_err); 245068fb4f1Sjruoho ATF_TP_ADD_TC(tp, setitimer_basic); 246068fb4f1Sjruoho ATF_TP_ADD_TC(tp, setitimer_err); 247068fb4f1Sjruoho ATF_TP_ADD_TC(tp, setitimer_old); 248*3a6e4efaSriastradh ATF_TP_ADD_TC(tp, setitimer_invalidtime); 249068fb4f1Sjruoho 250068fb4f1Sjruoho return atf_no_error(); 251068fb4f1Sjruoho } 252