Adds the clocksource-switch tests which continually switches the
current clocksource between all the available ones, watching for
any timekeeping inconsistencies.

Cc: Shuah Khan <shua...@osg.samsung.com>
Cc: Prarit Bhargava <pra...@redhat.com>
Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Richard Cochran <richardcoch...@gmail.com>
Signed-off-by: John Stultz <john.stu...@linaro.org>
---
 tools/testing/selftests/timers/Makefile            |   3 +-
 .../testing/selftests/timers/clocksource-switch.c  | 165 +++++++++++++++++++++
 2 files changed, 167 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/timers/clocksource-switch.c

diff --git a/tools/testing/selftests/timers/Makefile 
b/tools/testing/selftests/timers/Makefile
index 68b5253..d50a1ef 100644
--- a/tools/testing/selftests/timers/Makefile
+++ b/tools/testing/selftests/timers/Makefile
@@ -2,7 +2,7 @@ CFLAGS += -O3 -Wl,-no-as-needed
 LDFLAGS += -lrt -lpthread
 bins = posix_timers nanosleep inconsistency-check nsleep-lat raw_skew \
        set-timer-lat threadtest mqueue-lat valid-adjtimex \
-       alarmtimer-suspend change_skew skew_consistency
+       alarmtimer-suspend change_skew skew_consistency clocksource-switch \
 
 all: ${bins}
 
@@ -26,6 +26,7 @@ run_destructive_tests: run_tests
        ./valid-adjtimex
        ./change_skew
        ./skew_consistency
+       ./clocksource-switch
 
 clean:
        rm -f ${bins}
diff --git a/tools/testing/selftests/timers/clocksource-switch.c 
b/tools/testing/selftests/timers/clocksource-switch.c
new file mode 100644
index 0000000..0b36cae
--- /dev/null
+++ b/tools/testing/selftests/timers/clocksource-switch.c
@@ -0,0 +1,165 @@
+/* Clocksource change test
+ *             by: john stultz (johns...@us.ibm.com)
+ *             (C) Copyright IBM 2012
+ *             Licensed under the GPLv2
+ *
+ *  NOTE: This is a meta-test which quickly changes the clocksourc and
+ *  then uses other tests to detect problems. Thus this test requires
+ *  that the inconsistency-check and nanosleep tests be present in the
+ *  same directory it is run from.
+ *
+ *  To build:
+ *     $ gcc clocksource-switch.c -o clocksource-switch -lrt
+ *
+ *   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.
+ */
+
+
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/timex.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/wait.h>
+
+
+int get_clocksources(char list[][30])
+{
+       int fd, i, count;
+       size_t size;
+       char buf[512];
+       char *head, *tmp;
+
+       fd = 
open("/sys/devices/system/clocksource/clocksource0/available_clocksource", 
O_RDONLY);
+
+       size = read(fd, buf, 512);
+
+       close(fd);
+
+       for (i = 0; i < 30; i++)
+               list[i][0] = '\0';
+
+       head = buf;
+       i = 0;
+       while (head - buf < size) {
+               /* Find the next space */
+               for (tmp = head; *tmp != ' '; tmp++) {
+                       if (*tmp == '\n')
+                               break;
+                       if (*tmp == '\0')
+                               break;
+               }
+               *tmp = '\0';
+               strcpy(list[i], head);
+               head = tmp + 1;
+               i++;
+       }
+
+       return i-1;
+}
+
+int get_cur_clocksource(char *buf, size_t size)
+{
+       int fd, i, count;
+       char *head, *tmp;
+
+       fd = 
open("/sys/devices/system/clocksource/clocksource0/current_clocksource", 
O_RDONLY);
+
+       size = read(fd, buf, size);
+
+       return 0;
+}
+
+int change_clocksource(char *clocksource)
+{
+       int fd, ret, count;
+       size_t size;
+       char buf[512];
+       char *head, *tmp;
+
+       fd = 
open("/sys/devices/system/clocksource/clocksource0/current_clocksource", 
O_WRONLY);
+
+       if (fd < 0)
+               return -1;
+
+       size = write(fd, clocksource, strlen(clocksource));
+
+       if (size < 0)
+               return -1;
+
+       close(fd);
+       return 0;
+}
+
+
+int run_tests(int secs)
+{
+       int ret;
+       char buf[255];
+
+       sprintf(buf, "./inconsistency-check -t %i", secs);
+       ret = system(buf);
+       if (ret)
+               return ret;
+       ret = system("./nanosleep");
+       return ret;
+}
+
+
+char clocksource_list[10][30];
+
+int main(int argv, char **argc)
+{
+       char orig_clk[512];
+       int count, i, status;
+       pid_t pid, w;
+
+       get_cur_clocksource(orig_clk, 512);
+
+       count = get_clocksources(clocksource_list);
+
+       if (change_clocksource(clocksource_list[0])) {
+               printf("Error: You probably need to run this as root\n");
+               return -1;
+       }
+
+       /* Check everything is sane before we start switching asyncrhonously */
+       for (i = 0; i < count; i++) {
+               printf("Validating clocksource %s\n", clocksource_list[i]);
+               if (change_clocksource(clocksource_list[i])) {
+                       status = -1;
+                       goto out;
+               }
+               if (run_tests(5)) {
+                       status = -1;
+                       goto out;
+               }
+       }
+
+
+       printf("Running Asyncrhonous Switching Tests...\n");
+       pid = fork();
+       if (!pid)
+               return run_tests(60);
+
+       while (pid != waitpid(pid, &status, WNOHANG))
+               for (i = 0; i < count; i++)
+                       if (change_clocksource(clocksource_list[i])) {
+                               status = -1;
+                               goto out;
+                       }
+out:
+       change_clocksource(orig_clk);
+       return status;
+}
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to