1 /* 2 * Copyright (c) Crackerjack Project., 2007-2008 ,Hitachi, Ltd 3 * Author(s): Takahiro Yasui <takahiro.yasui.mp (at) hitachi.com>, 4 * Yumiko Sugita <yumiko.sugita.yf (at) hitachi.com>, 5 * Satoshi Fujiwara <sa-fuji (at) 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 "linux_syscall_numbers.h" 26 #include "tst_sig_proc.h" 27 #include "tst_timer.h" 28 #include "tst_test.h" 29 30 #define MAX_MSEC_DIFF 20 31 32 static void sighandler(int sig LTP_ATTRIBUTE_UNUSED) 33 { 34 } 35 36 enum test_type { 37 NORMAL, 38 SEND_SIGINT, 39 }; 40 41 #define TYPE_NAME(x) .ttype = x, .desc = #x 42 43 struct test_case { 44 clockid_t clk_id; /* clock_* clock type parameter */ 45 int ttype; /* test type (enum) */ 46 const char *desc; /* test description (name) */ 47 int flags; /* clock_nanosleep flags parameter */ 48 struct timespec rq; 49 int exp_ret; 50 int exp_err; 51 }; 52 53 /* 54 * test status of errors on man page 55 * EINTR v (function was interrupted by a signal) 56 * EINVAL v (invalid tv_nsec, etc.) 57 */ 58 59 static struct test_case tcase[] = { 60 { 61 .clk_id = CLOCK_REALTIME, 62 TYPE_NAME(NORMAL), 63 .flags = 0, 64 .rq = (struct timespec) {.tv_sec = 0, .tv_nsec = 500000000}, 65 .exp_ret = 0, 66 .exp_err = 0, 67 }, 68 { 69 .clk_id = CLOCK_MONOTONIC, 70 TYPE_NAME(NORMAL), 71 .flags = 0, 72 .rq = (struct timespec) {.tv_sec = 0, .tv_nsec = 500000000}, 73 .exp_ret = 0, 74 .exp_err = 0, 75 }, 76 { 77 TYPE_NAME(NORMAL), 78 .clk_id = CLOCK_REALTIME, 79 .flags = 0, 80 .rq = (struct timespec) {.tv_sec = 0, .tv_nsec = -1}, 81 .exp_ret = EINVAL, 82 .exp_err = 0, 83 }, 84 { 85 TYPE_NAME(NORMAL), 86 .clk_id = CLOCK_REALTIME, 87 .flags = 0, 88 .rq = (struct timespec) {.tv_sec = 0, .tv_nsec = 1000000000}, 89 .exp_ret = EINVAL, 90 .exp_err = 0, 91 }, 92 { 93 TYPE_NAME(NORMAL), 94 .clk_id = CLOCK_THREAD_CPUTIME_ID, 95 .flags = 0, 96 .rq = (struct timespec) {.tv_sec = 0, .tv_nsec = 500000000}, 97 .exp_ret = EINVAL, 98 .exp_err = 0, 99 }, 100 { 101 TYPE_NAME(SEND_SIGINT), 102 .clk_id = CLOCK_REALTIME, 103 .flags = 0, 104 .rq = (struct timespec) {.tv_sec = 10, .tv_nsec = 0}, 105 .exp_ret = EINTR, 106 .exp_err = 0, 107 }, 108 }; 109 110 void setup(void) 111 { 112 SAFE_SIGNAL(SIGINT, sighandler); 113 tst_timer_check(CLOCK_MONOTONIC); 114 } 115 116 static void do_test(unsigned int i) 117 { 118 struct test_case *tc = &tcase[i]; 119 struct timespec rm = {0}; 120 long long elapsed_ms, expect_ms, remain_ms = 0; 121 pid_t pid = 0; 122 123 tst_res(TINFO, "case %s", tc->desc); 124 125 /* setup */ 126 if (tc->ttype == SEND_SIGINT) 127 pid = create_sig_proc(SIGINT, 40, 500000); 128 129 /* test */ 130 tst_timer_start(CLOCK_MONOTONIC); 131 TEST(clock_nanosleep(tc->clk_id, tc->flags, &tc->rq, &rm)); 132 tst_timer_stop(); 133 elapsed_ms = tst_timer_elapsed_ms(); 134 expect_ms = tst_timespec_to_ms(tc->rq); 135 136 if (tc->ttype == SEND_SIGINT) { 137 tst_res(TINFO, "remain time: %lds %ldns", rm.tv_sec, rm.tv_nsec); 138 remain_ms = tst_timespec_to_ms(rm); 139 } 140 141 /* cleanup */ 142 if (pid) { 143 SAFE_KILL(pid, SIGTERM); 144 SAFE_WAIT(NULL); 145 } 146 147 /* result check */ 148 if (!TEST_RETURN && (elapsed_ms < expect_ms - MAX_MSEC_DIFF 149 || elapsed_ms > expect_ms + MAX_MSEC_DIFF)) { 150 151 tst_res(TFAIL| TTERRNO, "The clock_nanosleep() haven't slept correctly," 152 " measured %lldms, expected %lldms +- %d", 153 elapsed_ms, expect_ms, MAX_MSEC_DIFF); 154 return; 155 } 156 157 if (tc->ttype == SEND_SIGINT && !rm.tv_sec && !rm.tv_nsec) { 158 tst_res(TFAIL | TTERRNO, "The clock_nanosleep() haven't updated" 159 " timestamp with remaining time"); 160 return; 161 } 162 163 if (tc->ttype == SEND_SIGINT && remain_ms > expect_ms) { 164 tst_res(TFAIL| TTERRNO, "remaining time > requested time (%lld > %lld)", 165 remain_ms, expect_ms); 166 return; 167 } 168 169 if (TEST_RETURN != tc->exp_ret) { 170 tst_res(TFAIL | TTERRNO, "returned %ld, expected %d," 171 " expected errno: %s (%d)", TEST_RETURN, 172 tc->exp_ret, tst_strerrno(tc->exp_err), tc->exp_err); 173 return; 174 } 175 176 tst_res(TPASS, "returned %s (%ld)", 177 tst_strerrno(TEST_RETURN), TEST_RETURN); 178 } 179 180 static struct tst_test test = { 181 .tid = "clock_nanosleep01", 182 .tcnt = ARRAY_SIZE(tcase), 183 .test = do_test, 184 .setup = setup, 185 .forks_child = 1, 186 }; 187