1/* 2 * Copyright (c) Crackerjack Project., 2007-2008 ,Hitachi, Ltd 3 * Author(s): Takahiro Yasui <takahiro.yasui.mp@hitachi.com>, 4 * Yumiko Sugita <yumiko.sugita.yf@hitachi.com>, 5 * Satoshi Fujiwara <sa-fuji@sdl.hitachi.co.jp> 6 * Copyright (c) 2016 Linux Test Project 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of 11 * the License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it would be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write the Free Software Foundation, 20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 */ 22 23#include <limits.h> 24 25#include "lapi/syscalls.h" 26#include "tst_sig_proc.h" 27#include "tst_timer.h" 28#include "tst_test.h" 29 30static void sighandler(int sig LTP_ATTRIBUTE_UNUSED) 31{ 32} 33 34enum test_type { 35 NORMAL, 36 SEND_SIGINT, 37}; 38 39#define TYPE_NAME(x) .ttype = x, .desc = #x 40 41struct test_case { 42 clockid_t clk_id; /* clock_* clock type parameter */ 43 int ttype; /* test type (enum) */ 44 const char *desc; /* test description (name) */ 45 int flags; /* clock_nanosleep flags parameter */ 46 struct timespec rq; 47 int exp_ret; 48 int exp_err; 49}; 50 51/* 52 * test status of errors on man page 53 * EINTR v (function was interrupted by a signal) 54 * EINVAL v (invalid tv_nsec, etc.) 55 */ 56 57static struct test_case tcase[] = { 58 { 59 TYPE_NAME(NORMAL), 60 .clk_id = CLOCK_REALTIME, 61 .flags = 0, 62 .rq = (struct timespec) {.tv_sec = 0, .tv_nsec = -1}, 63 .exp_ret = EINVAL, 64 .exp_err = 0, 65 }, 66 { 67 TYPE_NAME(NORMAL), 68 .clk_id = CLOCK_REALTIME, 69 .flags = 0, 70 .rq = (struct timespec) {.tv_sec = 0, .tv_nsec = 1000000000}, 71 .exp_ret = EINVAL, 72 .exp_err = 0, 73 }, 74 { 75 TYPE_NAME(NORMAL), 76 .clk_id = CLOCK_THREAD_CPUTIME_ID, 77 .flags = 0, 78 .rq = (struct timespec) {.tv_sec = 0, .tv_nsec = 500000000}, 79 .exp_ret = EINVAL, 80 .exp_err = 0, 81 }, 82 { 83 TYPE_NAME(SEND_SIGINT), 84 .clk_id = CLOCK_REALTIME, 85 .flags = 0, 86 .rq = (struct timespec) {.tv_sec = 10, .tv_nsec = 0}, 87 .exp_ret = EINTR, 88 .exp_err = 0, 89 }, 90}; 91 92void setup(void) 93{ 94 SAFE_SIGNAL(SIGINT, sighandler); 95} 96 97static void do_test(unsigned int i) 98{ 99 struct test_case *tc = &tcase[i]; 100 struct timespec rm = {0}; 101 pid_t pid = 0; 102 103 tst_res(TINFO, "case %s", tc->desc); 104 105 if (tc->ttype == SEND_SIGINT) 106 pid = create_sig_proc(SIGINT, 40, 500000); 107 108 TEST(clock_nanosleep(tc->clk_id, tc->flags, &tc->rq, &rm)); 109 110 if (pid) { 111 SAFE_KILL(pid, SIGTERM); 112 SAFE_WAIT(NULL); 113 } 114 115 if (tc->ttype == SEND_SIGINT) { 116 long long expect_ms = tst_timespec_to_ms(tc->rq); 117 long long remain_ms = tst_timespec_to_ms(rm); 118 119 tst_res(TINFO, "remain time: %lds %ldns", rm.tv_sec, rm.tv_nsec); 120 121 if (!rm.tv_sec && !rm.tv_nsec) { 122 tst_res(TFAIL | TTERRNO, 123 "The clock_nanosleep() haven't updated" 124 " timestamp with remaining time"); 125 return; 126 } 127 128 if (remain_ms > expect_ms) { 129 tst_res(TFAIL| TTERRNO, 130 "remaining time > requested time (%lld > %lld)", 131 remain_ms, expect_ms); 132 return; 133 } 134 } 135 136 if (TEST_RETURN != tc->exp_ret) { 137 tst_res(TFAIL | TTERRNO, "returned %ld, expected %d," 138 " expected errno: %s (%d)", TEST_RETURN, 139 tc->exp_ret, tst_strerrno(tc->exp_err), tc->exp_err); 140 return; 141 } 142 143 tst_res(TPASS, "returned %s (%ld)", 144 tst_strerrno(TEST_RETURN), TEST_RETURN); 145} 146 147static struct tst_test test = { 148 .tcnt = ARRAY_SIZE(tcase), 149 .test = do_test, 150 .setup = setup, 151 .forks_child = 1, 152}; 153