Home | History | Annotate | Download | only in clock_nanosleep
      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