* [LTP] [PATCH] add clock_gettime04
@ 2014-09-10 12:46 Jan Stancek
2014-09-10 15:18 ` chrubis
0 siblings, 1 reply; 3+ messages in thread
From: Jan Stancek @ 2014-09-10 12:46 UTC (permalink / raw)
To: ltp-list
Add regression test for commit:
commit 4036ac1567834222fc763ab18e3e17df93b4eaaf
Author: Mike Galbraith <umgwanakikbuti@gmail.com>
Date: Tue Jun 24 07:49:40 2014 +0200
sched: Fix clock_gettime(CLOCK_[PROCESS/THREAD]_CPUTIME_ID) monotonicity
Cpu time returned by clock_gettime for thread specific clock prior to
this commit is not monotonic.
Signed-off-by: Jan Stancek <jstancek@redhat.com>
---
runtest/timers | 1 +
testcases/kernel/timers/clock_gettime/.gitignore | 1 +
.../kernel/timers/clock_gettime/clock_gettime04.c | 208 ++++++++++++++++++++
3 files changed, 210 insertions(+), 0 deletions(-)
create mode 100644 testcases/kernel/timers/clock_gettime/clock_gettime04.c
diff --git a/runtest/timers b/runtest/timers
index a58ac57..daa617f 100644
--- a/runtest/timers
+++ b/runtest/timers
@@ -1,6 +1,7 @@
#DESCRIPTION:Posix Timer Tests
clock_gettime02 clock_gettime02
clock_gettime03 clock_gettime03
+clock_gettime04 clock_gettime04
clock_settime02 clock_settime02
clock_settime03 clock_settime03
timer_create02 timer_create02
diff --git a/testcases/kernel/timers/clock_gettime/.gitignore b/testcases/kernel/timers/clock_gettime/.gitignore
index 004e742..4f17c8b 100644
--- a/testcases/kernel/timers/clock_gettime/.gitignore
+++ b/testcases/kernel/timers/clock_gettime/.gitignore
@@ -1,2 +1,3 @@
/clock_gettime02
/clock_gettime03
+/clock_gettime04
diff --git a/testcases/kernel/timers/clock_gettime/clock_gettime04.c b/testcases/kernel/timers/clock_gettime/clock_gettime04.c
new file mode 100644
index 0000000..9d1cb55
--- /dev/null
+++ b/testcases/kernel/timers/clock_gettime/clock_gettime04.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) Linux Test Project, 2014
+ *
+ * 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 Library General Public License for more details.
+ */
+/*
+ * This is a regression test for bug fixed by:
+ * commit 4036ac1567834222fc763ab18e3e17df93b4eaaf
+ * Author: Mike Galbraith <umgwanakikbuti@gmail.com>
+ * Date: Tue Jun 24 07:49:40 2014 +0200
+ * sched: Fix clock_gettime(CLOCK_[PROCESS/THREAD]_CPUTIME_ID) monotonicity
+ *
+ * cpu time returned by clock_gettime for thread specific clock prior to
+ * this commit is not monotonic.
+ */
+
+#include <pthread.h>
+#include <inttypes.h>
+#include <errno.h>
+
+#include "test.h"
+#include "usctest.h"
+#include "safe_macros.h"
+
+#define DEFAULT_TEST_TIME 4
+#define THREAD_COUNT 8
+#define NANOSECS_PER_SEC 1000000000
+
+#define SAFE_PTHREAD(fn, ...) do { \
+ int ret = fn(__VA_ARGS__); \
+ if (ret) { \
+ TEST_ERRNO = ret; \
+ tst_brkm(TBROK | TTERRNO, cleanup, #fn); \
+ } \
+} while (0)
+
+char *TCID = "clock_gettime04";
+int TST_TOTAL = 1;
+
+static volatile sig_atomic_t done_testing;
+static int opt_testtime;
+static char *opt_testtimestr;
+static option_t options[] = {
+ {"T:", &opt_testtime, &opt_testtimestr},
+ {NULL, NULL, NULL}
+};
+static pthread_mutex_t exit_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static void setup(void);
+static void cleanup(void);
+
+static void sigproc(int sig)
+{
+ (void) sig;
+ done_testing = 1;
+}
+
+int64_t get_thread_cpu_time(pthread_t thread)
+{
+ clockid_t clockid;
+ int ret;
+ struct timespec tp;
+
+ SAFE_PTHREAD(pthread_getcpuclockid, thread, &clockid);
+
+ ret = clock_gettime(clockid, &tp);
+ if (ret)
+ tst_brkm(TBROK | TERRNO, cleanup, "clock_gettime: %d", ret);
+
+ return (tp.tv_sec * NANOSECS_PER_SEC) + tp.tv_nsec;
+}
+
+static void *child(void *arg)
+{
+ struct timespec tim;
+ int64_t t, t_last = 0;
+ int check_own_cpu_time = *(int *)arg;
+
+ tim.tv_sec = 0;
+ tim.tv_nsec = 5000;
+
+ while (!done_testing) {
+ nanosleep(&tim, NULL);
+
+ if (!check_own_cpu_time)
+ continue;
+
+ t = get_thread_cpu_time(pthread_self());
+ if (t < t_last) {
+ tst_resm(TFAIL, "t: %" PRId64 " < t_last: %"
+ PRId64, t, t_last);
+ done_testing = 2;
+ } else {
+ t_last = t;
+ }
+ }
+
+ SAFE_PTHREAD(pthread_mutex_lock, &exit_mutex);
+ SAFE_PTHREAD(pthread_mutex_unlock, &exit_mutex);
+
+ return NULL;
+}
+
+static void test(int seconds)
+{
+ int i, child_check_cpu_time[] = { 0, 1 };
+ pthread_t thread[THREAD_COUNT];
+ clockid_t clockid[THREAD_COUNT];
+ int64_t thread_time[THREAD_COUNT], cur_time;
+
+ done_testing = 0;
+ alarm(seconds);
+
+ /* create children and make every 2nd child check its own
+ * cpu time as well. */
+ for (i = 0; i < THREAD_COUNT; i++) {
+ SAFE_PTHREAD(pthread_create, &thread[i], NULL, child,
+ &child_check_cpu_time[i % 2]);
+ SAFE_PTHREAD(pthread_getcpuclockid, thread[i], &clockid[i]);
+ tst_resm(TINFO, "thread no.: %d clockid: %d", i, clockid[i]);
+ }
+
+ for (i = 0; i < THREAD_COUNT; i++)
+ thread_time[i] = get_thread_cpu_time(thread[i]);
+
+ SAFE_PTHREAD(pthread_mutex_lock, &exit_mutex);
+
+ /* check periodically that cpu time of each thread
+ * doesn't go backwards */
+ while (!done_testing) {
+ for (i = 0; i < THREAD_COUNT; i++) {
+ cur_time = get_thread_cpu_time(thread[i]);
+ if (cur_time < thread_time[i]) {
+ tst_resm(TFAIL, "cpu clock time went backwards "
+ "thread no. %d, clock id: %d"
+ " previous value: %" PRId64
+ " current value: %" PRId64,
+ i, clockid[i], thread_time[i],
+ cur_time);
+ done_testing = 2;
+ break;
+ }
+ thread_time[i] = cur_time;
+ }
+ }
+
+ /* allow children to exit now */
+ SAFE_PTHREAD(pthread_mutex_unlock, &exit_mutex);
+
+ for (i = 0; i < THREAD_COUNT; i++)
+ SAFE_PTHREAD(pthread_join, thread[i], NULL);
+
+ if (done_testing == 1)
+ tst_resm(TPASS, "Test completed, cpu times of all "
+ "thread clocks were monotonic");
+}
+
+int main(int argc, char *argv[])
+{
+ int testtime = DEFAULT_TEST_TIME;
+ const char *msg = NULL;
+
+ msg = parse_opts(argc, argv, options, NULL);
+ if (msg)
+ tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
+
+ if (opt_testtime) {
+ testtime = atoi(opt_testtimestr);
+ if (testtime <= 0) {
+ tst_brkm(TBROK, NULL, "Invalid arg for -T: %s",
+ opt_testtimestr);
+ }
+ }
+
+ setup();
+
+ test(testtime);
+
+ cleanup();
+ tst_exit();
+}
+
+static void setup(void)
+{
+ struct sigaction sa;
+
+ TEST_PAUSE;
+
+ sigemptyset(&sa.sa_mask);
+ sa.sa_handler = sigproc;
+ sa.sa_flags = 0;
+
+ if (sigaction(SIGALRM, &sa, 0) == -1)
+ tst_brkm(TBROK | TERRNO, NULL, "sigaction() failed");
+}
+
+static void cleanup(void)
+{
+ TEST_CLEANUP;
+}
--
1.7.1
------------------------------------------------------------------------------
Want excitement?
Manually upgrade your production database.
When you want reliability, choose Perforce
Perforce version control. Predictably reliable.
http://pubads.g.doubleclick.net/gampad/clk?id=157508191&iu=/4140/ostg.clktrk
_______________________________________________
Ltp-list mailing list
Ltp-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ltp-list
^ permalink raw reply related [flat|nested] 3+ messages in thread* Re: [LTP] [PATCH] add clock_gettime04
2014-09-10 12:46 [LTP] [PATCH] add clock_gettime04 Jan Stancek
@ 2014-09-10 15:18 ` chrubis
[not found] ` <1162485694.20768561.1410363325469.JavaMail.zimbra@redhat.com>
0 siblings, 1 reply; 3+ messages in thread
From: chrubis @ 2014-09-10 15:18 UTC (permalink / raw)
To: Jan Stancek; +Cc: ltp-list
Hi!
> +#define SAFE_PTHREAD(fn, ...) do { \
> + int ret = fn(__VA_ARGS__); \
> + if (ret) { \
> + TEST_ERRNO = ret; \
> + tst_brkm(TBROK | TTERRNO, cleanup, #fn); \
^
We have TRERRNO for the case of pthread
functions.
> + } \
> +} while (0)
> +
> +char *TCID = "clock_gettime04";
> +int TST_TOTAL = 1;
> +
> +static volatile sig_atomic_t done_testing;
> +static int opt_testtime;
> +static char *opt_testtimestr;
> +static option_t options[] = {
> + {"T:", &opt_testtime, &opt_testtimestr},
There is no need to use both opt_testtime and opt_testtimestr, you can
do just:
if (opt_testtimestr) {
...
}
> + {NULL, NULL, NULL}
> +};
> +static pthread_mutex_t exit_mutex = PTHREAD_MUTEX_INITIALIZER;
> +
> +static void setup(void);
> +static void cleanup(void);
> +
> +static void sigproc(int sig)
> +{
> + (void) sig;
> + done_testing = 1;
> +}
Shouldn't we rather do:
if (!done_testing)
done_testing = 1;
Because as far as I can see the alarm may stil fire between
one of the threads set done_testing to 2 and the if (done_testing == 1)
message.
> +int64_t get_thread_cpu_time(pthread_t thread)
> +{
> + clockid_t clockid;
> + int ret;
> + struct timespec tp;
> +
> + SAFE_PTHREAD(pthread_getcpuclockid, thread, &clockid);
> +
> + ret = clock_gettime(clockid, &tp);
> + if (ret)
> + tst_brkm(TBROK | TERRNO, cleanup, "clock_gettime: %d", ret);
> +
> + return (tp.tv_sec * NANOSECS_PER_SEC) + tp.tv_nsec;
> +}
> +
> +static void *child(void *arg)
> +{
> + struct timespec tim;
> + int64_t t, t_last = 0;
> + int check_own_cpu_time = *(int *)arg;
> +
> + tim.tv_sec = 0;
> + tim.tv_nsec = 5000;
> +
> + while (!done_testing) {
> + nanosleep(&tim, NULL);
> +
> + if (!check_own_cpu_time)
> + continue;
> +
> + t = get_thread_cpu_time(pthread_self());
> + if (t < t_last) {
> + tst_resm(TFAIL, "t: %" PRId64 " < t_last: %"
> + PRId64, t, t_last);
> + done_testing = 2;
> + } else {
> + t_last = t;
> + }
> + }
> +
> + SAFE_PTHREAD(pthread_mutex_lock, &exit_mutex);
> + SAFE_PTHREAD(pthread_mutex_unlock, &exit_mutex);
> +
> + return NULL;
> +}
> +
> +static void test(int seconds)
> +{
> + int i, child_check_cpu_time[] = { 0, 1 };
> + pthread_t thread[THREAD_COUNT];
> + clockid_t clockid[THREAD_COUNT];
> + int64_t thread_time[THREAD_COUNT], cur_time;
> +
> + done_testing = 0;
> + alarm(seconds);
> +
> + /* create children and make every 2nd child check its own
> + * cpu time as well. */
> + for (i = 0; i < THREAD_COUNT; i++) {
> + SAFE_PTHREAD(pthread_create, &thread[i], NULL, child,
> + &child_check_cpu_time[i % 2]);
> + SAFE_PTHREAD(pthread_getcpuclockid, thread[i], &clockid[i]);
> + tst_resm(TINFO, "thread no.: %d clockid: %d", i, clockid[i]);
> + }
> +
> + for (i = 0; i < THREAD_COUNT; i++)
> + thread_time[i] = get_thread_cpu_time(thread[i]);
> +
> + SAFE_PTHREAD(pthread_mutex_lock, &exit_mutex);
Hmm, shouldn't this mutex be locked before we create the threads
because otherwise some threads may have exited allready.
> + /* check periodically that cpu time of each thread
> + * doesn't go backwards */
> + while (!done_testing) {
> + for (i = 0; i < THREAD_COUNT; i++) {
> + cur_time = get_thread_cpu_time(thread[i]);
> + if (cur_time < thread_time[i]) {
> + tst_resm(TFAIL, "cpu clock time went backwards "
> + "thread no. %d, clock id: %d"
> + " previous value: %" PRId64
> + " current value: %" PRId64,
> + i, clockid[i], thread_time[i],
> + cur_time);
> + done_testing = 2;
> + break;
> + }
> + thread_time[i] = cur_time;
> + }
> + }
> +
> + /* allow children to exit now */
> + SAFE_PTHREAD(pthread_mutex_unlock, &exit_mutex);
> +
> + for (i = 0; i < THREAD_COUNT; i++)
> + SAFE_PTHREAD(pthread_join, thread[i], NULL);
> +
> + if (done_testing == 1)
> + tst_resm(TPASS, "Test completed, cpu times of all "
> + "thread clocks were monotonic");
> +}
> +
> +int main(int argc, char *argv[])
> +{
> + int testtime = DEFAULT_TEST_TIME;
> + const char *msg = NULL;
> +
> + msg = parse_opts(argc, argv, options, NULL);
> + if (msg)
> + tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
> +
> + if (opt_testtime) {
> + testtime = atoi(opt_testtimestr);
> + if (testtime <= 0) {
> + tst_brkm(TBROK, NULL, "Invalid arg for -T: %s",
> + opt_testtimestr);
> + }
> + }
> +
> + setup();
> +
> + test(testtime);
Shouldn't the test(testtime) be still inside the for () loop with
TEST_LOOPING() because otherwise the test will gladly accept and ignore
the standard parameters (-i -I etc).
Otherwise it looks OK to me.
--
Cyril Hrubis
chrubis@suse.cz
------------------------------------------------------------------------------
Want excitement?
Manually upgrade your production database.
When you want reliability, choose Perforce
Perforce version control. Predictably reliable.
http://pubads.g.doubleclick.net/gampad/clk?id=157508191&iu=/4140/ostg.clktrk
_______________________________________________
Ltp-list mailing list
Ltp-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ltp-list
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2014-09-10 16:32 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-09-10 12:46 [LTP] [PATCH] add clock_gettime04 Jan Stancek
2014-09-10 15:18 ` chrubis
[not found] ` <1162485694.20768561.1410363325469.JavaMail.zimbra@redhat.com>
2014-09-10 16:32 ` chrubis
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox