* [LTP] [PATCH v2] syscalls: Add timer measurement library
@ 2017-06-14 12:42 Cyril Hrubis
2017-06-16 13:56 ` Jan Stancek
0 siblings, 1 reply; 7+ messages in thread
From: Cyril Hrubis @ 2017-06-14 12:42 UTC (permalink / raw)
To: ltp
This commit adds a timer measurement library, mostly based on changes
done to the pselect01.c test and changes all tests that measure timer
precision to use it.
The timer testcases that measure timeouts now just define sampling function and
optional setup and cleanup. The rest of the functionality is implemented in the
lib/tst_timer_test.c library. This change not only removes fair amount of
duplicated code but also allows us to tune thresholds and define testcases in a
single place for all testcases.
The timer measurement library also supports for passing sleep time and
number of iterations as a command-line parameters, can print nifty
frequency plot into the terminal, as well as save test measurements into
a text file.
Signed-off-by: Cyril Hrubis <chrubis@suse.cz>
---
The changes from the v1:
* Fixed the outliners calculation not to overflow the sample array
* Moved the sample function to tst_test structure
- now the testcases define tst_test structure
- the tst_test structure is then passed to
the timer test setup function and is modified there
- this seems to be the easiest solution I could come
up with
* The timer test library now sets timeout in a case that
that we request single test, the timeout is set to 110%
of the requested runtime which fixes timeouts if the requested
time multiplied by iterations yields more than default
timeout value
FYI this conflicts with the saturated timer conversions patch, I will apply
this one over the saturated one while dropping changes from tst_timer.h from
this one.
include/tst_test.h | 7 +-
include/tst_timer.h | 26 ++
include/tst_timer_test.h | 57 +++
lib/tst_test.c | 40 +-
lib/tst_timer_test.c | 450 +++++++++++++++++++++
runtest/syscalls | 1 +
testcases/kernel/syscalls/.gitignore | 1 +
.../syscalls/clock_nanosleep/clock_nanosleep01.c | 67 +--
.../syscalls/clock_nanosleep/clock_nanosleep02.c | 49 +++
.../kernel/syscalls/epoll_wait/epoll_wait02.c | 125 ++----
testcases/kernel/syscalls/futex/futex_wait05.c | 61 +--
testcases/kernel/syscalls/nanosleep/nanosleep01.c | 56 +--
testcases/kernel/syscalls/poll/poll02.c | 104 ++---
testcases/kernel/syscalls/pselect/pselect01.c | 159 ++------
testcases/kernel/syscalls/select/select04.c | 103 ++---
15 files changed, 779 insertions(+), 527 deletions(-)
create mode 100644 include/tst_timer_test.h
create mode 100644 lib/tst_timer_test.c
create mode 100644 testcases/kernel/syscalls/clock_nanosleep/clock_nanosleep02.c
diff --git a/include/tst_test.h b/include/tst_test.h
index 666109550..8a575fc0a 100644
--- a/include/tst_test.h
+++ b/include/tst_test.h
@@ -145,6 +145,9 @@ struct tst_test {
void (*test)(unsigned int test_nr);
void (*test_all)(void);
+ /* Sampling function for timer measurement testcases */
+ int (*sample)(int clk_id, long long usec);
+
/* NULL terminated array of resource file names */
const char *const *resource_files;
};
@@ -179,12 +182,12 @@ extern int TEST_ERRNO;
const char *tst_strerrno(int err);
const char *tst_strsig(int sig);
+void tst_set_timeout(unsigned int timeout);
+
#ifndef TST_NO_DEFAULT_MAIN
static struct tst_test test;
-void tst_set_timeout(unsigned int timeout);
-
int main(int argc, char *argv[])
{
tst_run_tcases(argc, argv, &test);
diff --git a/include/tst_timer.h b/include/tst_timer.h
index f0a10bd45..0448f4428 100644
--- a/include/tst_timer.h
+++ b/include/tst_timer.h
@@ -77,6 +77,32 @@ static inline struct timeval tst_us_to_timeval(long long us)
}
/*
+ * Converts ms to struct timespec
+ */
+static inline struct timespec tst_ms_to_timespec(long long us)
+{
+ struct timespec ret;
+
+ ret.tv_sec = us / 1000;
+ ret.tv_nsec = (us % 1000) * 1000000;
+
+ return ret;
+}
+
+/*
+ * Converts us to struct timespec
+ */
+static inline struct timespec tst_us_to_timespec(long long us)
+{
+ struct timespec ret;
+
+ ret.tv_sec = us / 1000000;
+ ret.tv_nsec = (us % 1000000) * 1000;
+
+ return ret;
+}
+
+/*
* Comparsions
*/
static inline int tst_timespec_lt(struct timespec t1, struct timespec t2)
diff --git a/include/tst_timer_test.h b/include/tst_timer_test.h
new file mode 100644
index 000000000..59931d3f6
--- /dev/null
+++ b/include/tst_timer_test.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017 Cyril Hrubis <chrubis@suse.cz>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+ /*
+
+ Timer measuring library.
+
+ The test is supposed to define sampling function and set it in the tst_test
+ structure the rest of the work is then done by the library.
+
+ int sample(int clk_id, long long usec)
+ {
+ // Any setup done here
+
+ tst_timer_start(clk_id);
+ // Call that is being measured sleeps for usec
+ tst_timer_stop();
+ tst_timer_sample();
+
+ // Any cleanup done here
+
+ // Non-zero return exits the test
+ }
+
+ struct tst_test test = {
+ .tid = "syscall_name()",
+ .sample = sample,
+ };
+
+ */
+
+#ifndef TST_TIMER_TEST__
+#define TST_TIMER_TEST__
+
+#include "tst_test.h"
+#include "tst_timer.h"
+
+void tst_timer_sample(void);
+
+# ifdef TST_NO_DEFAULT_MAIN
+struct tst_test *tst_timer_test_setup(struct tst_test *test);
+# endif /* TST_NO_DEFAULT_MAIN */
+#endif /* TST_TIMER_TEST__ */
diff --git a/lib/tst_test.c b/lib/tst_test.c
index 794aa8555..16ea64fe9 100644
--- a/lib/tst_test.c
+++ b/lib/tst_test.c
@@ -30,6 +30,7 @@
#include "tst_device.h"
#include "lapi/futex.h"
#include "tst_ansi_color.h"
+#include "tst_timer_test.h"
#include "old_resource.h"
#include "old_device.h"
@@ -635,25 +636,44 @@ static const char *get_tid(char *argv[])
static struct tst_device tdev;
struct tst_device *tst_device;
-static void do_setup(int argc, char *argv[])
+static void assert_test_fn(void)
{
- if (!tst_test)
- tst_brk(TBROK, "No tests to run");
+ int cnt = 0;
- if (!tst_test->tid)
- tst_test->tid = get_tid(argv);
+ if (tst_test->test)
+ cnt++;
- if (!tst_test->test && !tst_test->test_all)
+ if (tst_test->test_all)
+ cnt++;
+
+ if (tst_test->sample)
+ cnt++;
+
+ if (!cnt)
tst_brk(TBROK, "No test function speficied");
- if (tst_test->test && tst_test->test_all)
- tst_brk(TBROK, "You can define either test() or test_all()");
+ if (cnt != 1)
+ tst_brk(TBROK, "You can define only one test function");
if (tst_test->test && !tst_test->tcnt)
tst_brk(TBROK, "Number of tests (tcnt) must not be > 0");
- if (tst_test->test_all && tst_test->tcnt)
- tst_brk(TBROK, "You can't define tcnt for test_all()");
+ if (!tst_test->test && tst_test->tcnt)
+ tst_brk(TBROK, "You can define tcnt only for test()");
+}
+
+static void do_setup(int argc, char *argv[])
+{
+ if (!tst_test)
+ tst_brk(TBROK, "No tests to run");
+
+ assert_test_fn();
+
+ if (tst_test->sample)
+ tst_test = tst_timer_test_setup(tst_test);
+
+ if (!tst_test->tid)
+ tst_test->tid = get_tid(argv);
if (tst_test->needs_root && geteuid() != 0)
tst_brk(TCONF, "Test needs to be run as root");
diff --git a/lib/tst_timer_test.c b/lib/tst_timer_test.c
new file mode 100644
index 000000000..fb920db18
--- /dev/null
+++ b/lib/tst_timer_test.c
@@ -0,0 +1,450 @@
+/*
+ * Copyright (c) 2017 Cyril Hrubis <chrubis@suse.cz>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/prctl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+
+#define TST_NO_DEFAULT_MAIN
+#include "tst_test.h"
+#include "tst_timer_test.h"
+
+#define MAX_SAMPLES 500
+
+static const char *scall;
+static void (*setup)(void);
+static void (*cleanup)(void);
+static int (*sample)(int clk_id, long long usec);
+static struct tst_test *test;
+
+static long long *samples;
+static unsigned int cur_sample;
+static unsigned int monotonic_resolution;
+static unsigned int timerslack;
+
+static char *print_frequency_plot;
+static char *file_name;
+static char *str_sleep_time;
+static char *str_sample_cnt;
+static int sleep_time = -1;
+static int sample_cnt;
+
+static void print_line(char c, int len)
+{
+ while (len-- > 0)
+ fputc(c, stderr);
+}
+
+static unsigned int ceilu(float f)
+{
+ if (f - (int)f > 0)
+ return (unsigned int)f + 1;
+
+ return (unsigned int)f;
+}
+
+static unsigned int flooru(float f)
+{
+ return (unsigned int)f;
+}
+
+static float bucket_len(unsigned int bucket, unsigned int max_bucket,
+ unsigned int cols)
+{
+ return 1.00 * bucket * cols / max_bucket;
+}
+
+static const char *table_heading = " Time: us ";
+
+/*
+ * Line Header: '10023 | '
+ */
+static unsigned int header_len(long long max_sample)
+{
+ unsigned int l = 1;
+
+ while (max_sample/=10)
+ l++;
+
+ return MAX(strlen(table_heading) + 2, l + 3);
+}
+
+static void frequency_plot(void)
+{
+ unsigned int cols = 80;
+ unsigned int rows = 20;
+ unsigned int i, buckets[rows];
+ long long max_sample = samples[0];
+ long long min_sample = samples[cur_sample-1];
+ unsigned int line_header_len = header_len(max_sample);
+ unsigned int plot_line_len = cols - line_header_len;
+ unsigned int bucket_size;
+
+ memset(buckets, 0, sizeof(buckets));
+
+ /*
+ * We work with discrete data buckets smaller than 1 does not make
+ * sense as well as it's a good idea to keep buckets integer sized
+ * to avoid scaling artifacts.
+ */
+ bucket_size = MAX(1u, ceilu(1.00 * (max_sample - min_sample)/(rows-1)));
+
+ for (i = 0; i < cur_sample; i++) {
+ unsigned int bucket;
+ bucket = flooru(1.00 * (samples[i] - min_sample)/bucket_size);
+ buckets[bucket]++;
+ }
+
+ unsigned int max_bucket = buckets[0];
+ for (i = 1; i < rows; i++)
+ max_bucket = MAX(max_bucket, buckets[i]);
+
+ fprintf(stderr, "\n%*s| Frequency\n", line_header_len - 2, table_heading);
+
+ print_line('-', cols);
+ fputc('\n', stderr);
+
+ unsigned int l, r;
+
+ for (l = 0; l < rows; l++) {
+ if (buckets[l])
+ break;
+ }
+
+ for (r = rows-1; r > l; r--) {
+ if (buckets[r])
+ break;
+ }
+
+ for (i = l; i <= r; i++) {
+ float len = bucket_len(buckets[i], max_bucket, plot_line_len);
+
+ fprintf(stderr, "%*lli | ",
+ line_header_len - 3, min_sample + bucket_size*i);
+ print_line('*', len);
+
+ if ((len - (int)len) >= 0.5)
+ fputc('+', stderr);
+ else if ((len - (int)len) >= 0.25)
+ fputc('-', stderr);
+ else if (len < 0.25 && buckets[i])
+ fputc('.', stderr);
+
+ fputc('\n', stderr);
+ }
+
+ print_line('-', cols);
+ fputc('\n', stderr);
+
+ float scale = 1.00 * plot_line_len / max_bucket;
+
+ fprintf(stderr,
+ "%*uus | 1 sample = %.5f '*', %.5f '+', %.5f '-', non-zero '.'\n",
+ line_header_len - 5, bucket_size, scale, scale * 2, scale * 4);
+
+ fputc('\n', stderr);
+}
+
+void tst_timer_sample(void)
+{
+ samples[cur_sample++] = tst_timer_elapsed_us();
+}
+
+static int cmp(const void *a, const void *b)
+{
+ const long long *aa = a, *bb = b;
+
+ return *aa < *bb;
+}
+
+/*
+ * The threshold per one syscall is computed as a sum of:
+ *
+ * 250 us - accomodates for context switches, etc.
+ * 2*monotonic_resolution - accomodates for granurality of the CLOCK_MONOTONIC
+ * slack_per_scall - max of 0.1% of the sleep capped on 100ms or
+ * current->timer_slack_ns, which is slack allowed
+ * in kernel
+ *
+ * We also allow for outliners, i.e. add some number to the threshold in case
+ * that the number of iteration is small. For large enoung number of iterations
+ * outliners are discarded and averaged out.
+ */
+static long long compute_threshold(long long requested_us,
+ unsigned int nsamples)
+{
+ unsigned int slack_per_scall = MIN(100000, requested_us / 1000);
+
+ slack_per_scall = MAX(slack_per_scall, timerslack);
+
+ return (250 + 2 * monotonic_resolution + slack_per_scall) * nsamples
+ + 3000/nsamples;
+}
+
+/*
+ * Returns number of samples to discard.
+ *
+ * We set it to either at least 1 if number of samples > 1 or 5%.
+ */
+static unsigned int compute_discard(unsigned int nsamples)
+{
+ if (nsamples == 1)
+ return 0;
+
+ return MAX(1u, nsamples / 20);
+}
+
+static void write_to_file(void)
+{
+ unsigned int i;
+ FILE *f;
+
+ if (!file_name)
+ return;
+
+ f = fopen(file_name, "w");
+
+ if (!f) {
+ tst_res(TWARN | TERRNO,
+ "Failed to open '%s'", file_name);
+ return;
+ }
+
+ for (i = 0; i < cur_sample; i++)
+ fprintf(f, "%lli\n", samples[i]);
+
+ if (fclose(f)) {
+ tst_res(TWARN | TERRNO,
+ "Failed to close file '%s'", file_name);
+ }
+}
+
+
+/*
+ * Timer testing function.
+ *
+ * What we do here is:
+ *
+ * * Take nsamples measurements of the timer function, the function
+ * to be sampled is defined in the the actual test.
+ *
+ * * We sort the array of samples, then:
+ *
+ * - look for outliners which are samples where the sleep time has exceeded
+ * requested sleep time by an order of magnitude and,@the same time, are
+ * greater than clock resolution multiplied by three.
+ *
+ * - check for samples where the call has woken up too early which is a plain
+ * old bug
+ *
+ * - then we compute truncated mean and compare that with the requested sleep
+ * time increased by a threshold
+ */
+void do_timer_test(long long usec, unsigned int nsamples)
+{
+ long long trunc_mean, median;
+ unsigned int discard = compute_discard(nsamples);
+ unsigned int keep_samples = nsamples - discard;
+ long long threshold = compute_threshold(usec, keep_samples);
+ unsigned int i;
+ int failed = 0;
+
+ tst_res(TINFO,
+ "%s sleeping for %llius %u iterations, threshold %.2fus",
+ scall, usec, nsamples, 1.00 * threshold / (keep_samples));
+
+ cur_sample = 0;
+ for (i = 0; i < nsamples; i++) {
+ if (sample(CLOCK_MONOTONIC, usec)) {
+ tst_res(TINFO, "sampling function failed, exitting");
+ return;
+ }
+ }
+
+ qsort(samples, nsamples, sizeof(samples[0]), cmp);
+
+ write_to_file();
+
+ for (i = 0; samples[i] > 10 * usec && i < nsamples; i++) {
+ if (samples[i] <= 3 * monotonic_resolution)
+ break;
+ }
+
+ if (i > 0) {
+ tst_res(TINFO, "Found %i outliners in [%lli,%lli] range",
+ i, samples[0], samples[i-1]);
+ }
+
+ for (i = nsamples - 1; samples[i] < usec; i--);
+
+ if (i < nsamples - 1) {
+ tst_res(TFAIL, "%s woken up early %u times range: [%lli,%lli]",
+ scall, nsamples - 1 - i,
+ samples[i+1], samples[nsamples-1]);
+ failed = 1;
+ }
+
+ median = samples[nsamples/2];
+
+ trunc_mean = 0;
+
+ for (i = discard; i < nsamples; i++)
+ trunc_mean += samples[i];
+
+ tst_res(TINFO,
+ "min %llius, max %llius, median %llius, trunc mean %.2fus (discarded %u)",
+ samples[nsamples-1], samples[0], median,
+ 1.00 * trunc_mean / keep_samples, discard);
+
+ if (trunc_mean > (nsamples - discard) * usec + threshold) {
+ tst_res(TFAIL, "%s slept for too long", scall);
+
+ if (!print_frequency_plot)
+ frequency_plot();
+
+ failed = 1;
+ }
+
+ if (print_frequency_plot)
+ frequency_plot();
+
+ if (!failed)
+ tst_res(TPASS, "Measured times are within thresholds");
+}
+
+static void parse_timer_opts(void);
+
+static void timer_setup(void)
+{
+ struct timespec t;
+ int ret;
+
+ clock_getres(CLOCK_MONOTONIC, &t);
+
+ tst_res(TINFO, "CLOCK_MONOTONIC resolution %lins", (long)t.tv_nsec);
+
+ monotonic_resolution = t.tv_nsec / 1000;
+
+ ret = prctl(PR_GET_TIMERSLACK);
+ if (ret < 0) {
+ tst_res(TINFO, "prctl(PR_GET_TIMERSLACK) = -1, using 50us");
+ timerslack = 50;
+ } else {
+ timerslack = ret / 1000;
+ tst_res(TINFO, "prctl(PR_GET_TIMERSLACK) = %ius", timerslack);
+ }
+
+ parse_timer_opts();
+
+ samples = SAFE_MALLOC(sizeof(long long) * MAX(MAX_SAMPLES, sample_cnt));
+
+ if (setup)
+ setup();
+}
+
+static void timer_cleanup(void)
+{
+ free(samples);
+
+ if (cleanup)
+ cleanup();
+}
+
+static struct tst_timer_tcase {
+ long long usec;
+ unsigned int samples;
+} tcases[] = {
+ {1000, 500},
+ {2000, 500},
+ {5000, 300},
+ {10000, 100},
+ {25000, 50},
+ {100000, 10},
+ {1000000, 2},
+};
+
+static void timer_test_fn(unsigned int n)
+{
+ do_timer_test(tcases[n].usec, tcases[n].samples);
+}
+
+static void single_timer_test(void)
+{
+ do_timer_test(sleep_time, sample_cnt);
+}
+
+static struct tst_option options[] = {
+ {"p", &print_frequency_plot, "-p Print frequency plot"},
+ {"s:", &str_sleep_time, "-s us Sleep time"},
+ {"n:", &str_sample_cnt, "-n uint Number of samples to take"},
+ {"f:", &file_name, "-f fname Write measured samples into a file"},
+ {NULL, NULL, NULL}
+};
+
+static void parse_timer_opts(void)
+{
+ if (str_sleep_time) {
+ if (tst_parse_int(str_sleep_time, &sleep_time, 0, INT_MAX)) {
+ tst_brk(TBROK,
+ "Invalid sleep time '%s'", str_sleep_time);
+ }
+ }
+
+ if (str_sample_cnt) {
+ if (tst_parse_int(str_sample_cnt, &sample_cnt, 1, INT_MAX)) {
+ tst_brk(TBROK,
+ "Invalid sample count '%s'", str_sample_cnt);
+ }
+ }
+
+ if (str_sleep_time || str_sample_cnt) {
+ if (sleep_time < 0)
+ sleep_time = 10000;
+
+ if (!sample_cnt)
+ sample_cnt = 500;
+
+ long long timeout = sleep_time * sample_cnt / 1000000;
+
+ tst_set_timeout(timeout + timeout/10);
+
+ test->test_all = single_timer_test;
+ test->test = NULL;
+ test->tcnt = 0;
+ }
+}
+
+struct tst_test *tst_timer_test_setup(struct tst_test *timer_test)
+{
+ setup = timer_test->setup;
+ cleanup = timer_test->cleanup;
+ scall = timer_test->tid;
+ sample = timer_test->sample;
+
+ timer_test->tid = NULL;
+ timer_test->setup = timer_setup;
+ timer_test->cleanup = timer_cleanup;
+ timer_test->test = timer_test_fn;
+ timer_test->tcnt = ARRAY_SIZE(tcases);
+ timer_test->sample = NULL;
+ timer_test->options = options;
+
+ test = timer_test;
+
+ return timer_test;
+}
diff --git a/runtest/syscalls b/runtest/syscalls
index 32c65c60a..4bca483dd 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -74,6 +74,7 @@ chroot04 chroot04
clock_getres01 clock_getres01
clock_nanosleep01 clock_nanosleep01
+clock_nanosleep02 clock_nanosleep02
clock_nanosleep2_01 clock_nanosleep2_01
clone01 clone01
diff --git a/testcases/kernel/syscalls/.gitignore b/testcases/kernel/syscalls/.gitignore
index 03178db02..05c3dc503 100644
--- a/testcases/kernel/syscalls/.gitignore
+++ b/testcases/kernel/syscalls/.gitignore
@@ -53,6 +53,7 @@
/chroot/chroot04
/clock_getres/clock_getres01
/clock_nanosleep/clock_nanosleep01
+/clock_nanosleep/clock_nanosleep02
/clock_nanosleep2/clock_nanosleep2_01
/clone/clone01
/clone/clone02
diff --git a/testcases/kernel/syscalls/clock_nanosleep/clock_nanosleep01.c b/testcases/kernel/syscalls/clock_nanosleep/clock_nanosleep01.c
index a4458e898..20a54dc87 100644
--- a/testcases/kernel/syscalls/clock_nanosleep/clock_nanosleep01.c
+++ b/testcases/kernel/syscalls/clock_nanosleep/clock_nanosleep01.c
@@ -27,8 +27,6 @@
#include "tst_timer.h"
#include "tst_test.h"
-#define MAX_MSEC_DIFF 20
-
static void sighandler(int sig LTP_ATTRIBUTE_UNUSED)
{
}
@@ -58,22 +56,6 @@ struct test_case {
static struct test_case tcase[] = {
{
- .clk_id = CLOCK_REALTIME,
- TYPE_NAME(NORMAL),
- .flags = 0,
- .rq = (struct timespec) {.tv_sec = 0, .tv_nsec = 500000000},
- .exp_ret = 0,
- .exp_err = 0,
- },
- {
- .clk_id = CLOCK_MONOTONIC,
- TYPE_NAME(NORMAL),
- .flags = 0,
- .rq = (struct timespec) {.tv_sec = 0, .tv_nsec = 500000000},
- .exp_ret = 0,
- .exp_err = 0,
- },
- {
TYPE_NAME(NORMAL),
.clk_id = CLOCK_REALTIME,
.flags = 0,
@@ -110,60 +92,45 @@ static struct test_case tcase[] = {
void setup(void)
{
SAFE_SIGNAL(SIGINT, sighandler);
- tst_timer_check(CLOCK_MONOTONIC);
}
static void do_test(unsigned int i)
{
struct test_case *tc = &tcase[i];
struct timespec rm = {0};
- long long elapsed_ms, expect_ms, remain_ms = 0;
pid_t pid = 0;
tst_res(TINFO, "case %s", tc->desc);
- /* setup */
if (tc->ttype == SEND_SIGINT)
pid = create_sig_proc(SIGINT, 40, 500000);
- /* test */
- tst_timer_start(CLOCK_MONOTONIC);
TEST(clock_nanosleep(tc->clk_id, tc->flags, &tc->rq, &rm));
- tst_timer_stop();
- elapsed_ms = tst_timer_elapsed_ms();
- expect_ms = tst_timespec_to_ms(tc->rq);
- if (tc->ttype == SEND_SIGINT) {
- tst_res(TINFO, "remain time: %lds %ldns", rm.tv_sec, rm.tv_nsec);
- remain_ms = tst_timespec_to_ms(rm);
- }
-
- /* cleanup */
if (pid) {
SAFE_KILL(pid, SIGTERM);
SAFE_WAIT(NULL);
}
- /* result check */
- if (!TEST_RETURN && (elapsed_ms < expect_ms - MAX_MSEC_DIFF
- || elapsed_ms > expect_ms + MAX_MSEC_DIFF)) {
-
- tst_res(TFAIL| TTERRNO, "The clock_nanosleep() haven't slept correctly,"
- " measured %lldms, expected %lldms +- %d",
- elapsed_ms, expect_ms, MAX_MSEC_DIFF);
- return;
- }
+ if (tc->ttype == SEND_SIGINT) {
+ long long expect_ms = tst_timespec_to_ms(tc->rq);
+ long long remain_ms = tst_timespec_to_ms(rm);
- if (tc->ttype == SEND_SIGINT && !rm.tv_sec && !rm.tv_nsec) {
- tst_res(TFAIL | TTERRNO, "The clock_nanosleep() haven't updated"
- " timestamp with remaining time");
- return;
- }
+ tst_res(TINFO, "remain time: %lds %ldns", rm.tv_sec, rm.tv_nsec);
- if (tc->ttype == SEND_SIGINT && remain_ms > expect_ms) {
- tst_res(TFAIL| TTERRNO, "remaining time > requested time (%lld > %lld)",
- remain_ms, expect_ms);
- return;
+ if (!rm.tv_sec && !rm.tv_nsec) {
+ tst_res(TFAIL | TTERRNO,
+ "The clock_nanosleep() haven't updated"
+ " timestamp with remaining time");
+ return;
+ }
+
+ if (remain_ms > expect_ms) {
+ tst_res(TFAIL| TTERRNO,
+ "remaining time > requested time (%lld > %lld)",
+ remain_ms, expect_ms);
+ return;
+ }
}
if (TEST_RETURN != tc->exp_ret) {
diff --git a/testcases/kernel/syscalls/clock_nanosleep/clock_nanosleep02.c b/testcases/kernel/syscalls/clock_nanosleep/clock_nanosleep02.c
new file mode 100644
index 000000000..f114013ac
--- /dev/null
+++ b/testcases/kernel/syscalls/clock_nanosleep/clock_nanosleep02.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2017 Cyril Hrubis <chrubis@suse.cz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/*
+ * Test Description:
+ * clock_nanosleep() should return with value 0 and the process should be
+ * suspended for time specified by timespec structure.
+ */
+
+#include <errno.h>
+#include "tst_timer_test.h"
+
+int sample_fn(int clk_id, long long usec)
+{
+ struct timespec t = tst_us_to_timespec(usec);
+
+ tst_timer_start(clk_id);
+ TEST(clock_nanosleep(clk_id, 0, &t, NULL));
+ tst_timer_stop();
+ tst_timer_sample();
+
+ if (TEST_RETURN != 0) {
+ tst_res(TFAIL | TERRNO,
+ "nanosleep() returned %li", TEST_RETURN);
+ return 1;
+ }
+
+ return 0;
+}
+
+static struct tst_test test = {
+ .tid = "nanosleep()",
+ .sample = sample_fn,
+};
diff --git a/testcases/kernel/syscalls/epoll_wait/epoll_wait02.c b/testcases/kernel/syscalls/epoll_wait/epoll_wait02.c
index a32e82e23..aa1bd0dd5 100644
--- a/testcases/kernel/syscalls/epoll_wait/epoll_wait02.c
+++ b/testcases/kernel/syscalls/epoll_wait/epoll_wait02.c
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2016 Fujitsu Ltd.
- * Author: Guangwen Feng <fenggw-fnst@cn.fujitsu.com>
+ * Author: Guangwen Feng <fenggw-fnst@cn.fujitsu.com>
+ * Copyright (c) 2017 Cyril Hrubis <chrubis@suse.cz>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,7 +18,6 @@
*/
/*
- * Description:
* Check that epoll_wait(2) timeouts correctly.
*/
@@ -25,121 +25,60 @@
#include <unistd.h>
#include <errno.h>
-#include "test.h"
-#include "safe_macros.h"
-
-char *TCID = "epoll_wait02";
-int TST_TOTAL = 1;
+#include "tst_timer_test.h"
static int epfd, fds[2];
-static char *opt_sleep_ms;
static struct epoll_event epevs[1] = {
- {.events = EPOLLIN}
-};
-
-static option_t opts[] = {
- {"s:", NULL, &opt_sleep_ms},
- {NULL, NULL, NULL}
+ {.events = EPOLLIN}
};
-static void setup(void);
-static void cleanup(void);
-static void help(void);
-
-int main(int ac, char **av)
+int sample_fn(int clk_id, long long usec)
{
- int lc, threshold;
- long long elapsed_ms, sleep_ms = 100;
-
- tst_parse_opts(ac, av, opts, help);
-
- if (opt_sleep_ms) {
- sleep_ms = atoll(opt_sleep_ms);
-
- if (sleep_ms == 0) {
- tst_brkm(TBROK, NULL,
- "Invalid timeout '%s'", opt_sleep_ms);
- }
- }
-
- threshold = sleep_ms / 100 + 10;
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- tst_count = 0;
+ unsigned int sleep_ms = usec / 1000;
- tst_timer_start(CLOCK_MONOTONIC);
- TEST(epoll_wait(epfd, epevs, 1, sleep_ms));
- tst_timer_stop();
+ tst_timer_start(clk_id);
+ TEST(epoll_wait(epfd, epevs, 1, sleep_ms));
+ tst_timer_stop();
+ tst_timer_sample();
- if (TEST_RETURN == -1) {
- tst_resm(TFAIL | TTERRNO, "epoll_wait() failed");
- continue;
- }
-
- if (TEST_RETURN != 0) {
- tst_resm(TFAIL, "epoll_wait() returned %li, expected 0",
- TEST_RETURN);
- continue;
- }
-
- elapsed_ms = tst_timer_elapsed_ms();
-
- if (elapsed_ms < sleep_ms) {
- tst_resm(TFAIL, "epoll_wait() woken up too early %llims, "
- "expected %llims", elapsed_ms, sleep_ms);
- continue;
- }
-
- if (elapsed_ms - sleep_ms > threshold) {
- tst_resm(TFAIL, "epoll_wait() slept too long %llims, "
- "expected %llims, threshold %i",
- elapsed_ms, sleep_ms, threshold);
- continue;
- }
-
- tst_resm(TPASS, "epoll_wait() slept %llims, expected %llims, "
- "threshold %i", elapsed_ms, sleep_ms, threshold);
+ if (TEST_RETURN != 0) {
+ tst_res(TFAIL | TTERRNO,
+ "epoll_wait() returned %li", TEST_RETURN);
+ return 1;
}
- cleanup();
- tst_exit();
+ return 0;
}
static void setup(void)
{
- tst_timer_check(CLOCK_MONOTONIC);
-
- SAFE_PIPE(NULL, fds);
+ SAFE_PIPE(fds);
epfd = epoll_create(1);
- if (epfd == -1) {
- tst_brkm(TBROK | TERRNO, cleanup,
- "failed to create epoll instance");
- }
+ if (epfd == -1)
+ tst_brk(TBROK | TERRNO, "epoll_create()");
epevs[0].data.fd = fds[0];
- if (epoll_ctl(epfd, EPOLL_CTL_ADD, fds[0], &epevs[0])) {
- tst_brkm(TBROK | TERRNO, cleanup,
- "failed to register epoll target");
- }
+ if (epoll_ctl(epfd, EPOLL_CTL_ADD, fds[0], &epevs[0]))
+ tst_brk(TBROK | TERRNO, "epoll_clt(..., EPOLL_CTL_ADD, ...)");
}
static void cleanup(void)
{
- if (epfd > 0 && close(epfd))
- tst_resm(TWARN | TERRNO, "failed to close epfd");
+ if (epfd > 0)
+ SAFE_CLOSE(epfd);
- if (close(fds[0]))
- tst_resm(TWARN | TERRNO, "close(fds[0]) failed");
+ if (fds[0] > 0)
+ SAFE_CLOSE(fds[0]);
- if (close(fds[1]))
- tst_resm(TWARN | TERRNO, "close(fds[1]) failed");
+ if (fds[1] > 0)
+ SAFE_CLOSE(fds[1]);
}
-static void help(void)
-{
- printf(" -s epoll_wait() timeout length in ms\n");
-}
+static struct tst_test test = {
+ .tid = "epoll_wait()",
+ .sample = sample_fn,
+ .setup = setup,
+ .cleanup = cleanup,
+};
diff --git a/testcases/kernel/syscalls/futex/futex_wait05.c b/testcases/kernel/syscalls/futex/futex_wait05.c
index 6b99cede1..f6b0aa15e 100644
--- a/testcases/kernel/syscalls/futex/futex_wait05.c
+++ b/testcases/kernel/syscalls/futex/futex_wait05.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz>
+ * Copyright (C) 2015-2017 Cyril Hrubis <chrubis@suse.cz>
*
* Licensed under the GNU GPLv2 or later.
* This program is free software; you can redistribute it and/or modify
@@ -23,64 +23,35 @@
#include <errno.h>
-#include "test.h"
+#include "tst_timer_test.h"
#include "futextest.h"
-#define TRESHOLD_US 100000
-
-const char *TCID="futex_wait05";
-const int TST_TOTAL=1;
-
-static void verify_futex_wait(clock_t clk_id, int fflags)
+int sample_fn(int clk_id, long long usec)
{
- struct timespec to = {.tv_sec = 0, .tv_nsec = 100010000};
+ struct timespec to = tst_us_to_timespec(usec);
futex_t futex = FUTEX_INITIALIZER;
tst_timer_start(clk_id);
- TEST(futex_wait(&futex, futex, &to, fflags));
+ TEST(futex_wait(&futex, futex, &to, 0));
tst_timer_stop();
+ tst_timer_sample();
if (TEST_RETURN != -1) {
- tst_resm(TFAIL, "futex_wait() returned %li, expected -1",
+ tst_res(TFAIL, "futex_wait() returned %li, expected -1",
TEST_RETURN);
- return;
+ return 1;
}
if (TEST_ERRNO != ETIMEDOUT) {
-
- tst_resm(TFAIL | TTERRNO, "expected errno=%s",
- tst_strerrno(ETIMEDOUT));
- return;
- }
-
- if (tst_timespec_lt(tst_timer_elapsed(), to)) {
- tst_resm(TFAIL,
- "futex_wait() woken up prematurely %llius, expected %llius",
- tst_timer_elapsed_us(), tst_timespec_to_us(to));
- return;
- }
-
- if (tst_timespec_diff_us(tst_timer_elapsed(), to) > TRESHOLD_US) {
- tst_resm(TFAIL,
- "futex_wait() waited too long %llius, expected %llius",
- tst_timer_elapsed_us(), tst_timespec_to_us(to));
- return;
+ tst_res(TFAIL | TTERRNO, "expected errno=%s",
+ tst_strerrno(ETIMEDOUT));
+ return 1;
}
- tst_resm(TPASS, "futex_wait() waited %llius, expected %llius",
- tst_timer_elapsed_us(), tst_timespec_to_us(to));
+ return 0;
}
-int main(int argc, char *argv[])
-{
- int lc;
-
- tst_timer_check(CLOCK_MONOTONIC);
-
- tst_parse_opts(argc, argv, NULL, NULL);
-
- for (lc = 0; TEST_LOOPING(lc); lc++)
- verify_futex_wait(CLOCK_MONOTONIC, 0);
-
- tst_exit();
-}
+static struct tst_test test = {
+ .tid = "futex_wait()",
+ .sample = sample_fn,
+};
diff --git a/testcases/kernel/syscalls/nanosleep/nanosleep01.c b/testcases/kernel/syscalls/nanosleep/nanosleep01.c
index 4d9d083b1..6d90a60c3 100644
--- a/testcases/kernel/syscalls/nanosleep/nanosleep01.c
+++ b/testcases/kernel/syscalls/nanosleep/nanosleep01.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) International Business Machines Corp., 2001
* 07/2001 Ported by Wayne Boyer
- * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz>
+ * Copyright (C) 2015-2017 Cyril Hrubis <chrubis@suse.cz>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,56 +19,34 @@
*/
/*
- * Test Name: nanosleep01
- *
* Test Description:
* nanosleep() should return with value 0 and the process should be
* suspended for time specified by timespec structure.
*/
#include <errno.h>
-#include "test.h"
-
-char *TCID = "nanosleep01";
-int TST_TOTAL = 1;
-static void setup(void);
+#include "tst_timer_test.h"
-int main(int ac, char **av)
+int sample_fn(int clk_id, long long usec)
{
- int lc;
- struct timespec timereq = {.tv_sec = 2, .tv_nsec = 9999};
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
+ struct timespec t = tst_us_to_timespec(usec);
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- tst_timer_start(CLOCK_MONOTONIC);
- TEST(nanosleep(&timereq, NULL));
- tst_timer_stop();
+ tst_timer_start(clk_id);
+ TEST(nanosleep(&t, NULL));
+ tst_timer_stop();
+ tst_timer_sample();
- if (TEST_RETURN == -1) {
- tst_resm(TFAIL | TERRNO, "nanosleep() failed");
- continue;
- }
-
- if (tst_timespec_lt(tst_timer_elapsed(), timereq)) {
- tst_resm(TFAIL,
- "nanosleep() suspended for %lli us, expected %lli",
- tst_timer_elapsed_us(), tst_timespec_to_us(timereq));
- } else {
- tst_resm(TPASS, "nanosleep() suspended for %lli us",
- tst_timer_elapsed_us());
- }
+ if (TEST_RETURN != 0) {
+ tst_res(TFAIL | TERRNO,
+ "nanosleep() returned %li", TEST_RETURN);
+ return 1;
}
- tst_exit();
+ return 0;
}
-static void setup(void)
-{
- tst_sig(FORK, DEF_HANDLER, NULL);
- tst_timer_check(CLOCK_MONOTONIC);
- TEST_PAUSE;
-}
+static struct tst_test test = {
+ .tid = "nanosleep()",
+ .sample = sample_fn,
+};
diff --git a/testcases/kernel/syscalls/poll/poll02.c b/testcases/kernel/syscalls/poll/poll02.c
index 66affed01..0aa228c6b 100644
--- a/testcases/kernel/syscalls/poll/poll02.c
+++ b/testcases/kernel/syscalls/poll/poll02.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz>
+ * Copyright (C) 2015-2017 Cyril Hrubis <chrubis@suse.cz>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,105 +19,53 @@
/*
* Check that poll() timeouts correctly.
*/
-#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <sys/poll.h>
-#include "test.h"
-#include "safe_macros.h"
-
-char *TCID = "poll02";
-int TST_TOTAL = 1;
-
-static char *opt_sleep_ms;
-
-static option_t opts[] = {
- {"s:", NULL, &opt_sleep_ms},
- {NULL, NULL, NULL},
-};
-
-static void help(void);
-static void setup(void);
-static void cleanup(void);
+#include "tst_timer_test.h"
static int fds[2];
-int main(int ac, char **av)
+int sample_fn(int clk_id, long long usec)
{
- int lc, treshold;
- long long elapsed_ms, sleep_ms = 100;
+ unsigned int sleep_ms = usec / 1000;
- tst_parse_opts(ac, av, opts, help);
+ struct pollfd pfds[] = {
+ {.fd = fds[0], .events = POLLIN}
+ };
- if (opt_sleep_ms) {
- sleep_ms = atoll(opt_sleep_ms);
+ tst_timer_start(clk_id);
+ TEST(poll(pfds, 1, sleep_ms));
+ tst_timer_stop();
+ tst_timer_sample();
- if (sleep_ms == 0)
- tst_brkm(TBROK, NULL, "Invalid timeout '%s'", opt_sleep_ms);
+ if (TEST_RETURN != 0) {
+ tst_res(TFAIL | TTERRNO, "poll() returned %li", TEST_RETURN);
+ return 1;
}
- treshold = sleep_ms / 100 + 10;
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- struct pollfd pfds[] = {
- {.fd = fds[0], .events = POLLIN}
- };
-
- tst_timer_start(CLOCK_MONOTONIC);
- TEST(poll(pfds, 1, sleep_ms));
- tst_timer_stop();
-
- if (TEST_RETURN != 0) {
- tst_resm(TFAIL, "poll() haven't timeouted ret=%li",
- TEST_RETURN);
- continue;
- }
-
- elapsed_ms = tst_timer_elapsed_ms();
-
- if (elapsed_ms < sleep_ms) {
- tst_resm(TFAIL,
- "poll() woken up too early %llims, expected %llims",
- elapsed_ms, sleep_ms);
- continue;
- }
-
- if (elapsed_ms - sleep_ms > treshold) {
- tst_resm(TFAIL,
- "poll() slept too long %llims, expected %llims, threshold %i",
- elapsed_ms, sleep_ms, treshold);
- continue;
- }
-
- tst_resm(TPASS, "poll() slept %llims, expected %llims, treshold %i",
- elapsed_ms, sleep_ms, treshold);
- }
-
- cleanup();
- tst_exit();
+ return 0;
}
static void setup(void)
{
- tst_timer_check(CLOCK_MONOTONIC);
-
- SAFE_PIPE(NULL, fds);
+ SAFE_PIPE(fds);
}
static void cleanup(void)
{
- if (close(fds[0]))
- tst_resm(TWARN | TERRNO, "close(fds[0]) failed");
+ if (fds[0] > 0)
+ SAFE_CLOSE(fds[0]);
- if (close(fds[1]))
- tst_resm(TWARN | TERRNO, "close(fds[1]) failed");
+ if (fds[1] > 0)
+ SAFE_CLOSE(fds[1]);
}
-static void help(void)
-{
- printf(" -s poll() timeout lenght in ms\n");
-}
+static struct tst_test test = {
+ .tid = "poll()",
+ .sample = sample_fn,
+ .setup = setup,
+ .cleanup = cleanup,
+};
diff --git a/testcases/kernel/syscalls/pselect/pselect01.c b/testcases/kernel/syscalls/pselect/pselect01.c
index 1e8eccecb..a2b53398a 100644
--- a/testcases/kernel/syscalls/pselect/pselect01.c
+++ b/testcases/kernel/syscalls/pselect/pselect01.c
@@ -1,152 +1,49 @@
/*
- * Copyright (c) International Business Machines Corp., 2005
- * Copyright (c) Wipro Technologies Ltd, 2005. All Rights Reserved.
+ * Copyright (c) 2017 Cyril Hrubis <chrubis@suse.cz>
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * AUTHORS:
- * Prashant P Yendigeri <prashant.yendigeri@wipro.com>
- * Robbie Williamson <robbiew@us.ibm.com>
- *
- * DESCRIPTION
- * This is a Phase I test for the pselect01(2) system call.
- * It is intended to provide a limited exposure of the system call.
- *
- **********************************************************/
-
-#include <stdio.h>
-#include <fcntl.h>
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
-#include <time.h>
-#include <unistd.h>
#include <errno.h>
-#include "tst_test.h"
-#include "tst_timer.h"
-
-struct tcase {
- struct timespec tv;
- unsigned int iterations;
-};
-
-static unsigned int monotonic_resolution;
-
-static struct tcase tcases[] = {
- {{0, 1000000}, 500},
- {{0, 2000000}, 500},
- {{0, 10000000}, 300},
- {{0, 100000000}, 1},
- {{1, 0}, 1},
-};
-
-/*
- * The threshold per one syscall is computed as a sum of:
- *
- * 250 us - accomodates for context switches, etc.
- * 2*monotonic_resolution - accomodates for granurality of the CLOCK_MONOTONIC
- * slack_per_scall - 0.1% of the sleep capped on 100ms
- * which is slack allowed in kernel
- *
- * We also allow for outliners, i.e. add some number to the threshold in case
- * that the number of iteration is small. For large enoung number of iterations
- * outliners are averaged out.
- */
-static int compute_threshold(long long requested_us, unsigned int iterations)
-{
- unsigned int slack_per_scall = MIN(100000, requested_us / 1000);
-
- return (250 + 2 * monotonic_resolution + slack_per_scall) * iterations
- + (iterations > 1 ? 0 : 1500);
-}
+#include "tst_timer_test.h"
-static void verify_pselect(unsigned int n)
+int sample_fn(int clk_id, long long usec)
{
fd_set readfds;
- struct timespec tv;
- long long requested_us, slept_us = 0;
- unsigned int i;
- int threshold;
- struct tcase *t = &tcases[n];
+ struct timespec tv = tst_us_to_timespec(usec);
- tst_res(TINFO, "pselect() sleeping for %li secs %li nsec %i iterations",
- t->tv.tv_sec, t->tv.tv_nsec, t->iterations);
+ FD_ZERO(&readfds);
+ FD_SET(0, &readfds);
- for (i = 0; i < t->iterations; i++) {
- long long elapsed_us;
+ tst_timer_start(clk_id);
+ TEST(pselect(0, &readfds, NULL, NULL, &tv, NULL));
+ tst_timer_stop();
+ tst_timer_sample();
- FD_ZERO(&readfds);
- FD_SET(0, &readfds);
-
- tv = t->tv;
-
- tst_timer_start(CLOCK_MONOTONIC);
- pselect(0, &readfds, NULL, NULL, &tv, NULL);
- tst_timer_stop();
-
- elapsed_us = tst_timer_elapsed_us();
-
- if (elapsed_us >= 10 * tst_timespec_to_us(t->tv)
- && elapsed_us > 3 * monotonic_resolution) {
- tst_res(TINFO,
- "Found outliner took %lli us, expected %lli us",
- elapsed_us, tst_timespec_to_us(t->tv));
- }
-
- slept_us += elapsed_us;
- }
-
- requested_us = tst_timespec_to_us(t->tv) * t->iterations;
- threshold = compute_threshold(tst_timespec_to_us(t->tv), t->iterations);
-
- if (t->iterations > 1) {
- tst_res(TINFO, "Mean sleep time %.2f us, expected %lli us, threshold %.2f",
- 1.00 * slept_us / t->iterations,
- tst_timespec_to_us(t->tv), 1.00 * threshold / t->iterations);
- }
-
- if (slept_us < requested_us) {
- tst_res(TFAIL,
- "pselect() woken up too early %llius, expected %llius",
- slept_us, requested_us);
- return;
- }
-
- if (slept_us - requested_us > threshold) {
- tst_res(TFAIL,
- "pselect() slept for too long %llius, expected %llius, threshold %i",
- slept_us, requested_us, threshold);
- return;
+ if (TEST_RETURN != 0) {
+ tst_res(TFAIL | TTERRNO,
+ "pselect() returned %li on timeout", TEST_RETURN);
+ return 1;
}
- tst_res(TPASS, "pselect() slept for %llius, requested %llius, treshold %i",
- slept_us, requested_us, threshold);
-}
-
-static void setup(void)
-{
- struct timespec t;
-
- clock_getres(CLOCK_MONOTONIC, &t);
-
- tst_res(TINFO, "CLOCK_MONOTONIC resolution %li ns", (long)t.tv_nsec);
-
- monotonic_resolution = t.tv_nsec / 1000;
+ return 0;
}
static struct tst_test test = {
- .test = verify_pselect,
- .setup = setup,
- .tcnt = ARRAY_SIZE(tcases),
+ .tid = "pselect()",
+ .sample = sample_fn,
};
diff --git a/testcases/kernel/syscalls/select/select04.c b/testcases/kernel/syscalls/select/select04.c
index 76253c4ba..14317851b 100644
--- a/testcases/kernel/syscalls/select/select04.c
+++ b/testcases/kernel/syscalls/select/select04.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz>
+ * Copyright (C) 2015-2017 Cyril Hrubis <chrubis@suse.cz>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -25,104 +25,49 @@
#include <sys/types.h>
#include <fcntl.h>
-#include "test.h"
-#include "safe_macros.h"
-
-char *TCID = "select04";
-int TST_TOTAL = 1;
-
-static char *opt_sleep_us;
-
-static option_t opts[] = {
- {"s:", NULL, &opt_sleep_us},
- {NULL, NULL, NULL},
-};
-
-static void help(void);
-static void setup(void);
-static void cleanup(void);
+#include "tst_timer_test.h"
static int fds[2];
-int main(int ac, char **av)
+static int sample_fn(int clk_id, long long usec)
{
- int lc, treshold;
- long long elapsed_us, sleep_us = 100000;
- struct timeval timeout;
+ struct timeval timeout = tst_us_to_timeval(usec);
fd_set sfds;
- tst_parse_opts(ac, av, opts, help);
-
- if (opt_sleep_us) {
- sleep_us = atoll(opt_sleep_us);
-
- if (sleep_us == 0) {
- tst_brkm(TBROK, NULL, "Invalid timeout '%s'",
- opt_sleep_us);
- }
- }
-
- treshold = sleep_us / 100 + 20000;
-
- setup();
-
FD_ZERO(&sfds);
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- FD_SET(fds[0], &sfds);
- timeout = tst_us_to_timeval(sleep_us);
-
- tst_timer_start(CLOCK_MONOTONIC);
- TEST(select(1, &sfds, NULL, NULL, &timeout));
- tst_timer_stop();
-
- if (TEST_RETURN != 0) {
- tst_resm(TFAIL, "select() haven't timeouted ret=%li",
- TEST_RETURN);
- continue;
- }
-
- elapsed_us = tst_timer_elapsed_us();
-
- if (elapsed_us < sleep_us) {
- tst_resm(TFAIL,
- "select() woken up too early %llius, expected %llius",
- elapsed_us, sleep_us);
- continue;
- }
+ FD_SET(fds[0], &sfds);
- if (elapsed_us - sleep_us > treshold) {
- tst_resm(TFAIL,
- "select() slept too long %llius, expected %llius, threshold %i",
- elapsed_us, sleep_us, treshold);
- continue;
- }
+ tst_timer_start(clk_id);
+ TEST(select(1, &sfds, NULL, NULL, &timeout));
+ tst_timer_stop();
+ tst_timer_sample();
- tst_resm(TPASS, "select() slept %llius, expected %llius, treshold %i",
- elapsed_us, sleep_us, treshold);
+ if (TEST_RETURN != 0) {
+ tst_res(TFAIL | TTERRNO, "select() returned %li", TEST_RETURN);
+ return 1;
}
- cleanup();
- tst_exit();
+ return 0;
}
static void setup(void)
{
- tst_timer_check(CLOCK_MONOTONIC);
-
- SAFE_PIPE(NULL, fds);
+ SAFE_PIPE(fds);
}
static void cleanup(void)
{
- if (close(fds[0]))
- tst_resm(TWARN | TERRNO, "close(fds[0]) failed");
+ if (fds[0] > 0)
+ SAFE_CLOSE(fds[0]);
- if (close(fds[1]))
- tst_resm(TWARN | TERRNO, "close(fds[1]) failed");
+ if (fds[1] > 0)
+ SAFE_CLOSE(fds[1]);
}
-static void help(void)
-{
- printf(" -s select() timeout lenght in us\n");
-}
+static struct tst_test test = {
+ .tid = "select()",
+ .sample = sample_fn,
+ .setup = setup,
+ .cleanup = cleanup,
+};
--
2.13.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [LTP] [PATCH v2] syscalls: Add timer measurement library
2017-06-14 12:42 [LTP] [PATCH v2] syscalls: Add timer measurement library Cyril Hrubis
@ 2017-06-16 13:56 ` Jan Stancek
2017-06-19 13:26 ` Cyril Hrubis
2017-06-20 11:49 ` Cyril Hrubis
0 siblings, 2 replies; 7+ messages in thread
From: Jan Stancek @ 2017-06-16 13:56 UTC (permalink / raw)
To: ltp
----- Original Message -----
> This commit adds a timer measurement library, mostly based on changes
> done to the pselect01.c test and changes all tests that measure timer
> precision to use it.
>
> The timer testcases that measure timeouts now just define sampling function
> and
> optional setup and cleanup. The rest of the functionality is implemented in
> the
> lib/tst_timer_test.c library. This change not only removes fair amount of
> duplicated code but also allows us to tune thresholds and define testcases in
> a
> single place for all testcases.
>
> The timer measurement library also supports for passing sleep time and
> number of iterations as a command-line parameters, can print nifty
> frequency plot into the terminal, as well as save test measurements into
> a text file.
>
> Signed-off-by: Cyril Hrubis <chrubis@suse.cz>
> ---
>
> The changes from the v1:
>
> * Fixed the outliners calculation not to overflow the sample array
>
> * Moved the sample function to tst_test structure
> - now the testcases define tst_test structure
> - the tst_test structure is then passed to
> the timer test setup function and is modified there
> - this seems to be the easiest solution I could come
> up with
>
> * The timer test library now sets timeout in a case that
> that we request single test, the timeout is set to 110%
> of the requested runtime which fixes timeouts if the requested
> time multiplied by iterations yields more than default
> timeout value
Hi,
as approach it looks OK to me. Couple notes below:
- error: ‘PR_GET_TIMERSLACK’ undeclared (first use in this function)
Old ditros don't have this define.
- clock_getres/clock_gettime requires -rt for glibc < 2.17
On RHEL5/6 I had to modify these Makefiles:
# modified: include/mk/testcases.mk
# modified: lib/newlib_tests/Makefile
# modified: lib/tests/Makefile
# modified: testcases/kernel/containers/netns/Makefile
# modified: testcases/kernel/containers/share/Makefile
- threshold might be too low for some systems
The data I sent in:
http://lists.linux.it/pipermail/ltp/2017-June/004705.html
was from a quite beefy system, and it sometimes went over
250us threshold.
Should we increase threshold? The formula is based on comment
for select(), but we are applying this to other syscalls as well.
We used to do 1%, now it's more strict with just 0.1%.
Should we use RT priority?
Should we set CPU affinity to only single CPU?
It fails easily on my laptop (i7-6820HQ CPU @ 2.70GHz) atm.:
tst_timer_test.c:269: INFO: pselect() sleeping for 25000us 50 iterations, threshold 301.29us
tst_timer_test.c:312: INFO: min 25063us, max 25586us, median 25293us, trunc mean 25303.85us (discarded 2)
tst_timer_test.c:315: FAIL: pselect() slept for too long
Time: us | Frequency
--------------------------------------------------------------------------------
25063 | *******************-
25091 | ************************-
25119 | *****************************
25147 |
25175 | *********+
25203 | **************+
25231 | ****+
25259 | **************+
25287 | *********+
25315 | *********+
25343 | ****+
25371 | *********+
25399 |
25427 |
25455 | ****+
25483 | ********************************************************************
25511 | **************+
25539 |
25567 | ****+
--------------------------------------------------------------------------------
28us | 1 sample = 4.85714 '*', 9.71429 '+', 19.42857 '-', non-zero '.'
Regards,
Jan
^ permalink raw reply [flat|nested] 7+ messages in thread
* [LTP] [PATCH v2] syscalls: Add timer measurement library
2017-06-16 13:56 ` Jan Stancek
@ 2017-06-19 13:26 ` Cyril Hrubis
2017-06-20 7:51 ` Jan Stancek
2017-06-20 11:49 ` Cyril Hrubis
1 sibling, 1 reply; 7+ messages in thread
From: Cyril Hrubis @ 2017-06-19 13:26 UTC (permalink / raw)
To: ltp
Hi!
> - error: ???PR_GET_TIMERSLACK??? undeclared (first use in this function)
> Old ditros don't have this define.
What about ifdefing it around as:
diff --git a/lib/tst_timer_test.c b/lib/tst_timer_test.c
index 7566180c3..74157dbce 100644
--- a/lib/tst_timer_test.c
+++ b/lib/tst_timer_test.c
@@ -333,6 +333,7 @@ static void timer_setup(void)
monotonic_resolution = t.tv_nsec / 1000;
+#ifdef PR_GET_TIMERSLACK
ret = prctl(PR_GET_TIMERSLACK);
if (ret < 0) {
tst_res(TINFO, "prctl(PR_GET_TIMERSLACK) = -1, using 50us");
@@ -341,6 +342,10 @@ static void timer_setup(void)
timerslack = ret / 1000;
tst_res(TINFO, "prctl(PR_GET_TIMERSLACK) = %ius", timerslack);
}
+#else
+ tst_res(TINFO, "PR_GET_TIMERSLACK not defined, using 50us");
+ timerslack = 50;
+#endif /* PR_GET_TIMERSLACK */
> - clock_getres/clock_gettime requires -rt for glibc < 2.17
> On RHEL5/6 I had to modify these Makefiles:
> # modified: include/mk/testcases.mk
> # modified: lib/newlib_tests/Makefile
> # modified: lib/tests/Makefile
> # modified: testcases/kernel/containers/netns/Makefile
> # modified: testcases/kernel/containers/share/Makefile
Ah right, will fix that in v3.
> - threshold might be too low for some systems
> The data I sent in:
> http://lists.linux.it/pipermail/ltp/2017-June/004705.html
> was from a quite beefy system, and it sometimes went over
> 250us threshold.
That is something I left for discussion after we agree on the test API.
> Should we increase threshold? The formula is based on comment
> for select(), but we are applying this to other syscalls as well.
> We used to do 1%, now it's more strict with just 0.1%.
Well, if you look at man prctl and the PR_SET_TIMERSLACK it explicitly states
that the value is used for select, poll, epoll, nanosleep and futex.
The select and *poll family all use the same function with a formula we copy in
the test library. The futex seems to use only the timerslack value, so we are
less strict for that case and likely for the nanosleep calls, though I haven't
checked that part of the kernel to make sure that the slack is used there. We
may as well modify the threshold based on the scall name we get if you think
that it's worth the additional complexity.
> Should we use RT priority?
> Should we set CPU affinity to only single CPU?
I would rather increase the thresholds a bit than change the test to test in a
this kind of artificial scenario. Or even better we may try to run the test
twice with a stricter threshold for RT thread pinned to a single CPU.
> It fails easily on my laptop (i7-6820HQ CPU @ 2.70GHz) atm.:
>
> tst_timer_test.c:269: INFO: pselect() sleeping for 25000us 50 iterations, threshold 301.29us
> tst_timer_test.c:312: INFO: min 25063us, max 25586us, median 25293us, trunc mean 25303.85us (discarded 2)
> tst_timer_test.c:315: FAIL: pselect() slept for too long
>
> Time: us | Frequency
> --------------------------------------------------------------------------------
> 25063 | *******************-
> 25091 | ************************-
> 25119 | *****************************
> 25147 |
> 25175 | *********+
> 25203 | **************+
> 25231 | ****+
> 25259 | **************+
> 25287 | *********+
> 25315 | *********+
> 25343 | ****+
> 25371 | *********+
> 25399 |
> 25427 |
> 25455 | ****+
> 25483 | ********************************************************************
> 25511 | **************+
> 25539 |
> 25567 | ****+
> --------------------------------------------------------------------------------
> 28us | 1 sample = 4.85714 '*', 9.71429 '+', 19.42857 '-', non-zero '.'
Was that under a load or on an idle machine?
Anyway I'm OK with increasing the thresholds, the question is how much. For
this particular case it's failing just by a tiny little bit. Do you see any
failures if the static part of the treshold gets increased from 250 to 350 or
do we need even more?
--
Cyril Hrubis
chrubis@suse.cz
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [LTP] [PATCH v2] syscalls: Add timer measurement library
2017-06-19 13:26 ` Cyril Hrubis
@ 2017-06-20 7:51 ` Jan Stancek
0 siblings, 0 replies; 7+ messages in thread
From: Jan Stancek @ 2017-06-20 7:51 UTC (permalink / raw)
To: ltp
----- Original Message -----
> Hi!
> > - error: ???PR_GET_TIMERSLACK??? undeclared (first use in this function)
> > Old ditros don't have this define.
>
> What about ifdefing it around as:
>
> diff --git a/lib/tst_timer_test.c b/lib/tst_timer_test.c
> index 7566180c3..74157dbce 100644
> --- a/lib/tst_timer_test.c
> +++ b/lib/tst_timer_test.c
> @@ -333,6 +333,7 @@ static void timer_setup(void)
>
> monotonic_resolution = t.tv_nsec / 1000;
>
> +#ifdef PR_GET_TIMERSLACK
> ret = prctl(PR_GET_TIMERSLACK);
> if (ret < 0) {
> tst_res(TINFO, "prctl(PR_GET_TIMERSLACK) = -1, using 50us");
> @@ -341,6 +342,10 @@ static void timer_setup(void)
> timerslack = ret / 1000;
> tst_res(TINFO, "prctl(PR_GET_TIMERSLACK) = %ius",
> timerslack);
> }
> +#else
> + tst_res(TINFO, "PR_GET_TIMERSLACK not defined, using 50us");
> + timerslack = 50;
> +#endif /* PR_GET_TIMERSLACK */
Fine by me.
>
>
> > - clock_getres/clock_gettime requires -rt for glibc < 2.17
> > On RHEL5/6 I had to modify these Makefiles:
> > # modified: include/mk/testcases.mk
> > # modified: lib/newlib_tests/Makefile
> > # modified: lib/tests/Makefile
> > # modified: testcases/kernel/containers/netns/Makefile
> > # modified: testcases/kernel/containers/share/Makefile
>
> Ah right, will fix that in v3.
>
> > - threshold might be too low for some systems
> > The data I sent in:
> > http://lists.linux.it/pipermail/ltp/2017-June/004705.html
> > was from a quite beefy system, and it sometimes went over
> > 250us threshold.
>
> That is something I left for discussion after we agree on the test API.
>
> > Should we increase threshold? The formula is based on comment
> > for select(), but we are applying this to other syscalls as well.
> > We used to do 1%, now it's more strict with just 0.1%.
>
> Well, if you look at man prctl and the PR_SET_TIMERSLACK it explicitly states
> that the value is used for select, poll, epoll, nanosleep and futex.
>
> The select and *poll family all use the same function with a formula we copy
> in
> the test library. The futex seems to use only the timerslack value, so we are
> less strict for that case and likely for the nanosleep calls, though I
> haven't
> checked that part of the kernel to make sure that the slack is used there. We
> may as well modify the threshold based on the scall name we get if you think
> that it's worth the additional complexity.
>
> > Should we use RT priority?
> > Should we set CPU affinity to only single CPU?
>
> I would rather increase the thresholds a bit than change the test to test in
> a
> this kind of artificial scenario.
OK.
> Or even better we may try to run the test
> twice with a stricter threshold for RT thread pinned to a single CPU.
>
> > It fails easily on my laptop (i7-6820HQ CPU @ 2.70GHz) atm.:
> >
> > tst_timer_test.c:269: INFO: pselect() sleeping for 25000us 50 iterations,
> > threshold 301.29us
> > tst_timer_test.c:312: INFO: min 25063us, max 25586us, median 25293us, trunc
> > mean 25303.85us (discarded 2)
> > tst_timer_test.c:315: FAIL: pselect() slept for too long
> >
> > Time: us | Frequency
> > --------------------------------------------------------------------------------
> > 25063 | *******************-
> > 25091 | ************************-
> > 25119 | *****************************
> > 25147 |
> > 25175 | *********+
> > 25203 | **************+
> > 25231 | ****+
> > 25259 | **************+
> > 25287 | *********+
> > 25315 | *********+
> > 25343 | ****+
> > 25371 | *********+
> > 25399 |
> > 25427 |
> > 25455 | ****+
> > 25483 |
> > ********************************************************************
> > 25511 | **************+
> > 25539 |
> > 25567 | ****+
> > --------------------------------------------------------------------------------
> > 28us | 1 sample = 4.85714 '*', 9.71429 '+', 19.42857 '-', non-zero '.'
>
> Was that under a load or on an idle machine?
Idle, but not in performance mode.
>
> Anyway I'm OK with increasing the thresholds, the question is how much. For
> this particular case it's failing just by a tiny little bit. Do you see any
> failures if the static part of the treshold gets increased from 250 to 350 or
> do we need even more?
I'd go with 400, I'm bit paranoid that with all HW available we still find
some corner cases.
Regards,
Jan
^ permalink raw reply [flat|nested] 7+ messages in thread
* [LTP] [PATCH v2] syscalls: Add timer measurement library
2017-06-16 13:56 ` Jan Stancek
2017-06-19 13:26 ` Cyril Hrubis
@ 2017-06-20 11:49 ` Cyril Hrubis
2017-06-20 12:33 ` Cyril Hrubis
1 sibling, 1 reply; 7+ messages in thread
From: Cyril Hrubis @ 2017-06-20 11:49 UTC (permalink / raw)
To: ltp
Hi!
> - clock_getres/clock_gettime requires -rt for glibc < 2.17
> On RHEL5/6 I had to modify these Makefiles:
> # modified: include/mk/testcases.mk
> # modified: lib/newlib_tests/Makefile
> # modified: lib/tests/Makefile
> # modified: testcases/kernel/containers/netns/Makefile
> # modified: testcases/kernel/containers/share/Makefile
Hrm, looks like we have the very same problem as we had with the
mq_open() either we link everything with -lrt or figure out how to
separate the timer library and link it only with the timer testcases.
The problem here is that we call a funcition from the timer library from
the main library. And we cannot use weak stubs since we link statically.
Thinking of it using raw clock_* syscalls to avoid the dependency is not
a good option either since these are VDSO. These could still be reached
via syscall() it would be only slower and possibly broken since glibc
defaults to VDSO...
Or do you have a better idea how to avoid linking whole LTP with -lrt?
--
Cyril Hrubis
chrubis@suse.cz
^ permalink raw reply [flat|nested] 7+ messages in thread
* [LTP] [PATCH v2] syscalls: Add timer measurement library
2017-06-20 11:49 ` Cyril Hrubis
@ 2017-06-20 12:33 ` Cyril Hrubis
2017-06-20 13:02 ` Jan Stancek
0 siblings, 1 reply; 7+ messages in thread
From: Cyril Hrubis @ 2017-06-20 12:33 UTC (permalink / raw)
To: ltp
Hi!
What about this patch:
From 5cc450f19eb526cb19c33f4f13796e3c2a6f0bff Mon Sep 17 00:00:00 2001
From: Cyril Hrubis <chrubis@suse.cz>
Date: Tue, 20 Jun 2017 14:33:59 +0200
Subject: [PATCH] Fix clock_gettime linking problems.
---
include/tst_clocks.h | 29 +++++++++++++++++++++++++++++
lib/tst_clocks.c | 37 +++++++++++++++++++++++++++++++++++++
lib/tst_timer.c | 13 +++++++------
lib/tst_timer_test.c | 3 ++-
4 files changed, 75 insertions(+), 7 deletions(-)
create mode 100644 include/tst_clocks.h
create mode 100644 lib/tst_clocks.c
diff --git a/include/tst_clocks.h b/include/tst_clocks.h
new file mode 100644
index 0000000..ee2f645
--- /dev/null
+++ b/include/tst_clocks.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2017 Cyril Hrubis <chrubis@suse.cz>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * clock_gettime() and clock_getres() functions
+ */
+
+#ifndef TST_CLOCKS__
+#define TST_CLOCKS__
+
+int tst_clock_getres(clockid_t clk_id, struct timespec *res);
+
+int tst_clock_gettime(clockid_t clk_id, struct timespec *ts);
+
+#endif /* TST_CLOCKS__ */
diff --git a/lib/tst_clocks.c b/lib/tst_clocks.c
new file mode 100644
index 0000000..87413a3
--- /dev/null
+++ b/lib/tst_clocks.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2017 Cyril Hrubis <chrubis@suse.cz>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * clock_gettime() and clock_getres() functions
+ */
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <time.h>
+#include <sys/syscall.h>
+
+#include "tst_clocks.h"
+
+int tst_clock_getres(clockid_t clk_id, struct timespec *res)
+{
+ return syscall(SYS_clock_getres, clk_id, res);
+}
+
+int tst_clock_gettime(clockid_t clk_id, struct timespec *ts)
+{
+ return syscall(SYS_clock_gettime, clk_id, ts);
+}
diff --git a/lib/tst_timer.c b/lib/tst_timer.c
index bd3f277..afdb441 100644
--- a/lib/tst_timer.c
+++ b/lib/tst_timer.c
@@ -25,6 +25,7 @@
#include "test.h"
#include "tst_timer.h"
+#include "tst_clocks.h"
#include "lapi/posix_clocks.h"
static struct timespec start_time, stop_time;
@@ -56,7 +57,7 @@ static const char *clock_name(clockid_t clk_id)
void tst_timer_check(clockid_t clk_id)
{
- if (clock_gettime(clk_id, &start_time)) {
+ if (tst_clock_gettime(clk_id, &start_time)) {
if (errno == EINVAL) {
tst_brkm(TCONF, NULL,
"Clock id %s(%u) not supported by kernel",
@@ -64,7 +65,7 @@ void tst_timer_check(clockid_t clk_id)
return;
}
- tst_brkm(TBROK | TERRNO, NULL, "clock_gettime() failed");
+ tst_brkm(TBROK | TERRNO, NULL, "tst_clock_gettime() failed");
}
}
@@ -72,14 +73,14 @@ void tst_timer_start(clockid_t clk_id)
{
clock_id = clk_id;
- if (clock_gettime(clock_id, &start_time))
- tst_resm(TWARN | TERRNO, "clock_gettime() failed");
+ if (tst_clock_gettime(clock_id, &start_time))
+ tst_resm(TWARN | TERRNO, "tst_clock_gettime() failed");
}
void tst_timer_stop(void)
{
- if (clock_gettime(clock_id, &stop_time))
- tst_resm(TWARN | TERRNO, "clock_gettime() failed");
+ if (tst_clock_gettime(clock_id, &stop_time))
+ tst_resm(TWARN | TERRNO, "tst_clock_gettime() failed");
}
struct timespec tst_timer_elapsed(void)
diff --git a/lib/tst_timer_test.c b/lib/tst_timer_test.c
index 4627a4e..8921547 100644
--- a/lib/tst_timer_test.c
+++ b/lib/tst_timer_test.c
@@ -23,6 +23,7 @@
#define TST_NO_DEFAULT_MAIN
#include "tst_test.h"
#include "tst_timer_test.h"
+#include "tst_clocks.h"
#define MAX_SAMPLES 500
@@ -339,7 +340,7 @@ static void timer_setup(void)
struct timespec t;
int ret;
- clock_getres(CLOCK_MONOTONIC, &t);
+ tst_clock_getres(CLOCK_MONOTONIC, &t);
tst_res(TINFO, "CLOCK_MONOTONIC resolution %lins", (long)t.tv_nsec);
--
1.7.10.4
--
Cyril Hrubis
chrubis@suse.cz
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [LTP] [PATCH v2] syscalls: Add timer measurement library
2017-06-20 12:33 ` Cyril Hrubis
@ 2017-06-20 13:02 ` Jan Stancek
0 siblings, 0 replies; 7+ messages in thread
From: Jan Stancek @ 2017-06-20 13:02 UTC (permalink / raw)
To: ltp
----- Original Message -----
> From: "Cyril Hrubis" <chrubis@suse.cz>
> To: "Jan Stancek" <jstancek@redhat.com>
> Cc: ltp@lists.linux.it
> Sent: Tuesday, 20 June, 2017 2:33:58 PM
> Subject: Re: [LTP] [PATCH v2] syscalls: Add timer measurement library
>
> Hi!
> What about this patch:
>
> From 5cc450f19eb526cb19c33f4f13796e3c2a6f0bff Mon Sep 17 00:00:00 2001
> From: Cyril Hrubis <chrubis@suse.cz>
> Date: Tue, 20 Jun 2017 14:33:59 +0200
> Subject: [PATCH] Fix clock_gettime linking problems.
>
Works for me. Nothing else comes to my mind, either syscalls
or linking everything with -rt.
Only potential issue I can think of is parameter padding needed
in syscall() for some architectures with 32-bit userspace.
With clockid_t defined as int, I think we should be fine.
Regards,
Jan
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2017-06-20 13:02 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-06-14 12:42 [LTP] [PATCH v2] syscalls: Add timer measurement library Cyril Hrubis
2017-06-16 13:56 ` Jan Stancek
2017-06-19 13:26 ` Cyril Hrubis
2017-06-20 7:51 ` Jan Stancek
2017-06-20 11:49 ` Cyril Hrubis
2017-06-20 12:33 ` Cyril Hrubis
2017-06-20 13:02 ` Jan Stancek
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox