1*3b0a9131SEnji Cooper /* $NetBSD: t_timer_create.c,v 1.5 2017/01/16 16:32:13 christos Exp $ */ 257718be8SEnji Cooper 357718be8SEnji Cooper /*- 457718be8SEnji Cooper * Copyright (c) 2010 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 <atf-c.h> 3057718be8SEnji Cooper #include <errno.h> 3157718be8SEnji Cooper #include <stdio.h> 3257718be8SEnji Cooper #include <signal.h> 3357718be8SEnji Cooper #include <string.h> 3457718be8SEnji Cooper #include <time.h> 3557718be8SEnji Cooper #include <unistd.h> 3657718be8SEnji Cooper 3757718be8SEnji Cooper static timer_t t; 3857718be8SEnji Cooper static bool fail = true; 3957718be8SEnji Cooper 4057718be8SEnji Cooper static void 4130f77229SEnji Cooper timer_signal_handler(int signo, siginfo_t *si, void *osi __unused) 4257718be8SEnji Cooper { 4357718be8SEnji Cooper timer_t *tp; 4457718be8SEnji Cooper 4557718be8SEnji Cooper tp = si->si_value.sival_ptr; 4657718be8SEnji Cooper 4757718be8SEnji Cooper if (*tp == t && signo == SIGALRM) 4857718be8SEnji Cooper fail = false; 4957718be8SEnji Cooper 5057718be8SEnji Cooper (void)fprintf(stderr, "%s: %s\n", __func__, strsignal(signo)); 5157718be8SEnji Cooper } 5257718be8SEnji Cooper 5357718be8SEnji Cooper static void 5457718be8SEnji Cooper timer_signal_create(clockid_t cid, bool expire) 5557718be8SEnji Cooper { 5657718be8SEnji Cooper struct itimerspec tim; 5757718be8SEnji Cooper struct sigaction act; 5857718be8SEnji Cooper struct sigevent evt; 5957718be8SEnji Cooper sigset_t set; 6057718be8SEnji Cooper 6157718be8SEnji Cooper t = 0; 6257718be8SEnji Cooper fail = true; 6357718be8SEnji Cooper 6457718be8SEnji Cooper (void)memset(&evt, 0, sizeof(struct sigevent)); 6557718be8SEnji Cooper (void)memset(&act, 0, sizeof(struct sigaction)); 6657718be8SEnji Cooper (void)memset(&tim, 0, sizeof(struct itimerspec)); 6757718be8SEnji Cooper 6857718be8SEnji Cooper /* 6957718be8SEnji Cooper * Set handler. 7057718be8SEnji Cooper */ 7157718be8SEnji Cooper act.sa_flags = SA_SIGINFO; 7257718be8SEnji Cooper act.sa_sigaction = timer_signal_handler; 7357718be8SEnji Cooper 7457718be8SEnji Cooper ATF_REQUIRE(sigemptyset(&set) == 0); 7557718be8SEnji Cooper ATF_REQUIRE(sigemptyset(&act.sa_mask) == 0); 7657718be8SEnji Cooper 7757718be8SEnji Cooper /* 7857718be8SEnji Cooper * Block SIGALRM while configuring the timer. 7957718be8SEnji Cooper */ 8057718be8SEnji Cooper ATF_REQUIRE(sigaction(SIGALRM, &act, NULL) == 0); 8157718be8SEnji Cooper ATF_REQUIRE(sigaddset(&set, SIGALRM) == 0); 8257718be8SEnji Cooper ATF_REQUIRE(sigprocmask(SIG_SETMASK, &set, NULL) == 0); 8357718be8SEnji Cooper 8457718be8SEnji Cooper /* 8557718be8SEnji Cooper * Create the timer (SIGEV_SIGNAL). 8657718be8SEnji Cooper */ 8757718be8SEnji Cooper evt.sigev_signo = SIGALRM; 8857718be8SEnji Cooper evt.sigev_value.sival_ptr = &t; 8957718be8SEnji Cooper evt.sigev_notify = SIGEV_SIGNAL; 9057718be8SEnji Cooper 9157718be8SEnji Cooper ATF_REQUIRE(timer_create(cid, &evt, &t) == 0); 9257718be8SEnji Cooper 9357718be8SEnji Cooper /* 9457718be8SEnji Cooper * Start the timer. After this, unblock the signal. 9557718be8SEnji Cooper */ 9657718be8SEnji Cooper tim.it_value.tv_sec = expire ? 5 : 1; 9757718be8SEnji Cooper tim.it_value.tv_nsec = 0; 9857718be8SEnji Cooper 9957718be8SEnji Cooper ATF_REQUIRE(timer_settime(t, 0, &tim, NULL) == 0); 10057718be8SEnji Cooper 10157718be8SEnji Cooper (void)sigprocmask(SIG_UNBLOCK, &set, NULL); 10257718be8SEnji Cooper (void)sleep(2); 10357718be8SEnji Cooper 10457718be8SEnji Cooper if (expire) { 10557718be8SEnji Cooper if (!fail) 10657718be8SEnji Cooper atf_tc_fail("timer fired too soon"); 10757718be8SEnji Cooper } else { 10857718be8SEnji Cooper if (fail) 10957718be8SEnji Cooper atf_tc_fail("timer failed to fire"); 11057718be8SEnji Cooper } 11157718be8SEnji Cooper 11257718be8SEnji Cooper ATF_REQUIRE(timer_delete(t) == 0); 11357718be8SEnji Cooper } 11457718be8SEnji Cooper 115f21e85a0SJohn Baldwin #ifdef __FreeBSD__ 116f21e85a0SJohn Baldwin static void 117f21e85a0SJohn Baldwin timer_callback(union sigval value) 118f21e85a0SJohn Baldwin { 119f21e85a0SJohn Baldwin timer_t *tp; 120f21e85a0SJohn Baldwin 121f21e85a0SJohn Baldwin tp = value.sival_ptr; 122f21e85a0SJohn Baldwin 123f21e85a0SJohn Baldwin if (*tp == t) 124f21e85a0SJohn Baldwin fail = false; 125f21e85a0SJohn Baldwin } 126f21e85a0SJohn Baldwin 127f21e85a0SJohn Baldwin static void 128f21e85a0SJohn Baldwin timer_thread_create(clockid_t cid, bool expire) 129f21e85a0SJohn Baldwin { 130f21e85a0SJohn Baldwin struct itimerspec tim; 131f21e85a0SJohn Baldwin struct sigevent evt; 132f21e85a0SJohn Baldwin 133f21e85a0SJohn Baldwin t = 0; 134f21e85a0SJohn Baldwin fail = true; 135f21e85a0SJohn Baldwin 136f21e85a0SJohn Baldwin (void)memset(&evt, 0, sizeof(struct sigevent)); 137f21e85a0SJohn Baldwin (void)memset(&tim, 0, sizeof(struct itimerspec)); 138f21e85a0SJohn Baldwin 139f21e85a0SJohn Baldwin /* 140f21e85a0SJohn Baldwin * Create the timer (SIGEV_THREAD). 141f21e85a0SJohn Baldwin */ 142f21e85a0SJohn Baldwin evt.sigev_notify_function = timer_callback; 143f21e85a0SJohn Baldwin evt.sigev_value.sival_ptr = &t; 144f21e85a0SJohn Baldwin evt.sigev_notify = SIGEV_THREAD; 145f21e85a0SJohn Baldwin 146f21e85a0SJohn Baldwin ATF_REQUIRE(timer_create(cid, &evt, &t) == 0); 147f21e85a0SJohn Baldwin 148f21e85a0SJohn Baldwin /* 149f21e85a0SJohn Baldwin * Start the timer. 150f21e85a0SJohn Baldwin */ 151f21e85a0SJohn Baldwin tim.it_value.tv_sec = expire ? 5 : 1; 152f21e85a0SJohn Baldwin tim.it_value.tv_nsec = 0; 153f21e85a0SJohn Baldwin 154f21e85a0SJohn Baldwin ATF_REQUIRE(timer_settime(t, 0, &tim, NULL) == 0); 155f21e85a0SJohn Baldwin 156f21e85a0SJohn Baldwin (void)sleep(2); 157f21e85a0SJohn Baldwin 158f21e85a0SJohn Baldwin if (expire) { 159f21e85a0SJohn Baldwin if (!fail) 160f21e85a0SJohn Baldwin atf_tc_fail("timer fired too soon"); 161f21e85a0SJohn Baldwin } else { 162f21e85a0SJohn Baldwin if (fail) 163f21e85a0SJohn Baldwin atf_tc_fail("timer failed to fire"); 164f21e85a0SJohn Baldwin } 165f21e85a0SJohn Baldwin 166f21e85a0SJohn Baldwin ATF_REQUIRE(timer_delete(t) == 0); 167f21e85a0SJohn Baldwin } 168f21e85a0SJohn Baldwin #endif 169f21e85a0SJohn Baldwin 17057718be8SEnji Cooper ATF_TC(timer_create_err); 17157718be8SEnji Cooper ATF_TC_HEAD(timer_create_err, tc) 17257718be8SEnji Cooper { 17357718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", 17457718be8SEnji Cooper "Check errors from timer_create(2) (PR lib/42434"); 17557718be8SEnji Cooper } 17657718be8SEnji Cooper 17757718be8SEnji Cooper ATF_TC_BODY(timer_create_err, tc) 17857718be8SEnji Cooper { 17957718be8SEnji Cooper struct sigevent ev; 18057718be8SEnji Cooper 18157718be8SEnji Cooper (void)memset(&ev, 0, sizeof(struct sigevent)); 18257718be8SEnji Cooper 18357718be8SEnji Cooper errno = 0; 18457718be8SEnji Cooper ev.sigev_signo = -1; 18557718be8SEnji Cooper ev.sigev_notify = SIGEV_SIGNAL; 18657718be8SEnji Cooper 18757718be8SEnji Cooper ATF_REQUIRE_ERRNO(EINVAL, timer_create(CLOCK_REALTIME, &ev, &t) == -1); 18857718be8SEnji Cooper 18957718be8SEnji Cooper errno = 0; 19057718be8SEnji Cooper ev.sigev_signo = SIGUSR1; 19157718be8SEnji Cooper ev.sigev_notify = SIGEV_THREAD + 100; 19257718be8SEnji Cooper 19357718be8SEnji Cooper ATF_REQUIRE_ERRNO(EINVAL, timer_create(CLOCK_REALTIME, &ev, &t) == -1); 19457718be8SEnji Cooper } 19557718be8SEnji Cooper 19657718be8SEnji Cooper ATF_TC(timer_create_real); 19757718be8SEnji Cooper ATF_TC_HEAD(timer_create_real, tc) 19857718be8SEnji Cooper { 19957718be8SEnji Cooper 20057718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", 20157718be8SEnji Cooper "Checks timer_create(2) with CLOCK_REALTIME and sigevent(3), " 20257718be8SEnji Cooper "SIGEV_SIGNAL"); 20357718be8SEnji Cooper } 20457718be8SEnji Cooper 20557718be8SEnji Cooper ATF_TC_BODY(timer_create_real, tc) 20657718be8SEnji Cooper { 20757718be8SEnji Cooper timer_signal_create(CLOCK_REALTIME, false); 20857718be8SEnji Cooper } 20957718be8SEnji Cooper 21057718be8SEnji Cooper ATF_TC(timer_create_mono); 21157718be8SEnji Cooper ATF_TC_HEAD(timer_create_mono, tc) 21257718be8SEnji Cooper { 21357718be8SEnji Cooper 21457718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", 21557718be8SEnji Cooper "Checks timer_create(2) with CLOCK_MONOTONIC and sigevent(3), " 21657718be8SEnji Cooper "SIGEV_SIGNAL"); 21757718be8SEnji Cooper } 21857718be8SEnji Cooper 21957718be8SEnji Cooper ATF_TC_BODY(timer_create_mono, tc) 22057718be8SEnji Cooper { 22157718be8SEnji Cooper timer_signal_create(CLOCK_MONOTONIC, false); 22257718be8SEnji Cooper } 22357718be8SEnji Cooper 22457718be8SEnji Cooper ATF_TC(timer_create_real_expire); 22557718be8SEnji Cooper ATF_TC_HEAD(timer_create_real_expire, tc) 22657718be8SEnji Cooper { 22757718be8SEnji Cooper 22857718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", 22957718be8SEnji Cooper "Checks timer_create(2) with CLOCK_REALTIME and sigevent(3), " 23057718be8SEnji Cooper "SIGEV_SIGNAL, with expiration"); 23157718be8SEnji Cooper } 23257718be8SEnji Cooper 23357718be8SEnji Cooper ATF_TC_BODY(timer_create_real_expire, tc) 23457718be8SEnji Cooper { 23557718be8SEnji Cooper timer_signal_create(CLOCK_REALTIME, true); 23657718be8SEnji Cooper } 23757718be8SEnji Cooper 23857718be8SEnji Cooper ATF_TC(timer_create_mono_expire); 23957718be8SEnji Cooper ATF_TC_HEAD(timer_create_mono_expire, tc) 24057718be8SEnji Cooper { 24157718be8SEnji Cooper 24257718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", 24357718be8SEnji Cooper "Checks timer_create(2) with CLOCK_MONOTONIC and sigevent(3), " 24457718be8SEnji Cooper "SIGEV_SIGNAL, with expiration"); 24557718be8SEnji Cooper } 24657718be8SEnji Cooper 24757718be8SEnji Cooper ATF_TC_BODY(timer_create_mono_expire, tc) 24857718be8SEnji Cooper { 24957718be8SEnji Cooper timer_signal_create(CLOCK_MONOTONIC, true); 25057718be8SEnji Cooper } 25157718be8SEnji Cooper 252f21e85a0SJohn Baldwin ATF_TC(timer_thread_create_real); 253f21e85a0SJohn Baldwin ATF_TC_HEAD(timer_thread_create_real, tc) 254f21e85a0SJohn Baldwin { 255f21e85a0SJohn Baldwin 256f21e85a0SJohn Baldwin atf_tc_set_md_var(tc, "descr", 257f21e85a0SJohn Baldwin "Checks timer_create(2) with CLOCK_REALTIME and sigevent(3), " 258f21e85a0SJohn Baldwin "SIGEV_THREAD"); 259f21e85a0SJohn Baldwin } 260f21e85a0SJohn Baldwin 261f21e85a0SJohn Baldwin #ifdef __FreeBSD__ 262f21e85a0SJohn Baldwin ATF_TC_BODY(timer_thread_create_real, tc) 263f21e85a0SJohn Baldwin { 264f21e85a0SJohn Baldwin timer_thread_create(CLOCK_REALTIME, false); 265f21e85a0SJohn Baldwin } 266f21e85a0SJohn Baldwin 267f21e85a0SJohn Baldwin ATF_TC(timer_thread_create_mono); 268f21e85a0SJohn Baldwin ATF_TC_HEAD(timer_thread_create_mono, tc) 269f21e85a0SJohn Baldwin { 270f21e85a0SJohn Baldwin 271f21e85a0SJohn Baldwin atf_tc_set_md_var(tc, "descr", 272f21e85a0SJohn Baldwin "Checks timer_create(2) with CLOCK_MONOTONIC and sigevent(3), " 273f21e85a0SJohn Baldwin "SIGEV_THREAD"); 274f21e85a0SJohn Baldwin } 275f21e85a0SJohn Baldwin 276f21e85a0SJohn Baldwin ATF_TC_BODY(timer_thread_create_mono, tc) 277f21e85a0SJohn Baldwin { 278f21e85a0SJohn Baldwin timer_thread_create(CLOCK_MONOTONIC, false); 279f21e85a0SJohn Baldwin } 280f21e85a0SJohn Baldwin 281f21e85a0SJohn Baldwin ATF_TC(timer_thread_create_real_expire); 282f21e85a0SJohn Baldwin ATF_TC_HEAD(timer_thread_create_real_expire, tc) 283f21e85a0SJohn Baldwin { 284f21e85a0SJohn Baldwin 285f21e85a0SJohn Baldwin atf_tc_set_md_var(tc, "descr", 286f21e85a0SJohn Baldwin "Checks timer_create(2) with CLOCK_REALTIME and sigevent(3), " 287f21e85a0SJohn Baldwin "SIGEV_THREAD, with expiration"); 288f21e85a0SJohn Baldwin } 289f21e85a0SJohn Baldwin 290f21e85a0SJohn Baldwin ATF_TC_BODY(timer_thread_create_real_expire, tc) 291f21e85a0SJohn Baldwin { 292f21e85a0SJohn Baldwin timer_thread_create(CLOCK_REALTIME, true); 293f21e85a0SJohn Baldwin } 294f21e85a0SJohn Baldwin 295f21e85a0SJohn Baldwin ATF_TC(timer_thread_create_mono_expire); 296f21e85a0SJohn Baldwin ATF_TC_HEAD(timer_thread_create_mono_expire, tc) 297f21e85a0SJohn Baldwin { 298f21e85a0SJohn Baldwin 299f21e85a0SJohn Baldwin atf_tc_set_md_var(tc, "descr", 300f21e85a0SJohn Baldwin "Checks timer_create(2) with CLOCK_MONOTONIC and sigevent(3), " 301f21e85a0SJohn Baldwin "SIGEV_THREAD, with expiration"); 302f21e85a0SJohn Baldwin } 303f21e85a0SJohn Baldwin 304f21e85a0SJohn Baldwin ATF_TC_BODY(timer_thread_create_mono_expire, tc) 305f21e85a0SJohn Baldwin { 306f21e85a0SJohn Baldwin timer_thread_create(CLOCK_MONOTONIC, true); 307f21e85a0SJohn Baldwin } 308f21e85a0SJohn Baldwin #endif 309f21e85a0SJohn Baldwin 31057718be8SEnji Cooper ATF_TP_ADD_TCS(tp) 31157718be8SEnji Cooper { 31257718be8SEnji Cooper 31357718be8SEnji Cooper ATF_TP_ADD_TC(tp, timer_create_err); 31457718be8SEnji Cooper ATF_TP_ADD_TC(tp, timer_create_real); 31557718be8SEnji Cooper ATF_TP_ADD_TC(tp, timer_create_mono); 31657718be8SEnji Cooper ATF_TP_ADD_TC(tp, timer_create_real_expire); 31757718be8SEnji Cooper ATF_TP_ADD_TC(tp, timer_create_mono_expire); 318f21e85a0SJohn Baldwin #ifdef __FreeBSD__ 319f21e85a0SJohn Baldwin ATF_TP_ADD_TC(tp, timer_thread_create_real); 320f21e85a0SJohn Baldwin ATF_TP_ADD_TC(tp, timer_thread_create_mono); 321f21e85a0SJohn Baldwin ATF_TP_ADD_TC(tp, timer_thread_create_real_expire); 322f21e85a0SJohn Baldwin ATF_TP_ADD_TC(tp, timer_thread_create_mono_expire); 323f21e85a0SJohn Baldwin #endif 32457718be8SEnji Cooper 32557718be8SEnji Cooper return atf_no_error(); 32657718be8SEnji Cooper } 327