Back to home page

OSCL-LXR

 
 

    


0001 /* Clocksource change test
0002  *      by: john stultz (johnstul@us.ibm.com)
0003  *      (C) Copyright IBM 2012
0004  *      Licensed under the GPLv2
0005  *
0006  *  NOTE: This is a meta-test which quickly changes the clocksource and
0007  *  then uses other tests to detect problems. Thus this test requires
0008  *  that the inconsistency-check and nanosleep tests be present in the
0009  *  same directory it is run from.
0010  *
0011  *  To build:
0012  *  $ gcc clocksource-switch.c -o clocksource-switch -lrt
0013  *
0014  *   This program is free software: you can redistribute it and/or modify
0015  *   it under the terms of the GNU General Public License as published by
0016  *   the Free Software Foundation, either version 2 of the License, or
0017  *   (at your option) any later version.
0018  *
0019  *   This program is distributed in the hope that it will be useful,
0020  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
0021  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0022  *   GNU General Public License for more details.
0023  */
0024 
0025 
0026 #include <fcntl.h>
0027 #include <stdio.h>
0028 #include <stdlib.h>
0029 #include <string.h>
0030 #include <sys/stat.h>
0031 #include <sys/time.h>
0032 #include <sys/timex.h>
0033 #include <sys/types.h>
0034 #include <sys/wait.h>
0035 #include <time.h>
0036 #include <unistd.h>
0037 #include "../kselftest.h"
0038 
0039 
0040 int get_clocksources(char list[][30])
0041 {
0042     int fd, i;
0043     size_t size;
0044     char buf[512];
0045     char *head, *tmp;
0046 
0047     fd = open("/sys/devices/system/clocksource/clocksource0/available_clocksource", O_RDONLY);
0048 
0049     size = read(fd, buf, 512);
0050 
0051     close(fd);
0052 
0053     for (i = 0; i < 10; i++)
0054         list[i][0] = '\0';
0055 
0056     head = buf;
0057     i = 0;
0058     while (head - buf < size) {
0059         /* Find the next space */
0060         for (tmp = head; *tmp != ' '; tmp++) {
0061             if (*tmp == '\n')
0062                 break;
0063             if (*tmp == '\0')
0064                 break;
0065         }
0066         *tmp = '\0';
0067         strcpy(list[i], head);
0068         head = tmp + 1;
0069         i++;
0070     }
0071 
0072     return i-1;
0073 }
0074 
0075 int get_cur_clocksource(char *buf, size_t size)
0076 {
0077     int fd;
0078 
0079     fd = open("/sys/devices/system/clocksource/clocksource0/current_clocksource", O_RDONLY);
0080 
0081     size = read(fd, buf, size);
0082 
0083     return 0;
0084 }
0085 
0086 int change_clocksource(char *clocksource)
0087 {
0088     int fd;
0089     ssize_t size;
0090 
0091     fd = open("/sys/devices/system/clocksource/clocksource0/current_clocksource", O_WRONLY);
0092 
0093     if (fd < 0)
0094         return -1;
0095 
0096     size = write(fd, clocksource, strlen(clocksource));
0097 
0098     if (size < 0)
0099         return -1;
0100 
0101     close(fd);
0102     return 0;
0103 }
0104 
0105 
0106 int run_tests(int secs)
0107 {
0108     int ret;
0109     char buf[255];
0110 
0111     sprintf(buf, "./inconsistency-check -t %i", secs);
0112     ret = system(buf);
0113     if (WIFEXITED(ret) && WEXITSTATUS(ret))
0114         return WEXITSTATUS(ret);
0115     ret = system("./nanosleep");
0116     return WIFEXITED(ret) ? WEXITSTATUS(ret) : 0;
0117 }
0118 
0119 
0120 char clocksource_list[10][30];
0121 
0122 int main(int argc, char **argv)
0123 {
0124     char orig_clk[512];
0125     int count, i, status, opt;
0126     int do_sanity_check = 1;
0127     int runtime = 60;
0128     pid_t pid;
0129 
0130     /* Process arguments */
0131     while ((opt = getopt(argc, argv, "st:")) != -1) {
0132         switch (opt) {
0133         case 's':
0134             do_sanity_check = 0;
0135             break;
0136         case 't':
0137             runtime = atoi(optarg);
0138             break;
0139         default:
0140             printf("Usage: %s [-s] [-t <secs>]\n", argv[0]);
0141             printf("    -s: skip sanity checks\n");
0142             printf("    -t: Number of seconds to run\n");
0143             exit(-1);
0144         }
0145     }
0146 
0147     get_cur_clocksource(orig_clk, 512);
0148 
0149     count = get_clocksources(clocksource_list);
0150 
0151     if (change_clocksource(clocksource_list[0])) {
0152         printf("Error: You probably need to run this as root\n");
0153         return -1;
0154     }
0155 
0156     /* Check everything is sane before we start switching asynchronously */
0157     if (do_sanity_check) {
0158         for (i = 0; i < count; i++) {
0159             printf("Validating clocksource %s\n",
0160                 clocksource_list[i]);
0161             if (change_clocksource(clocksource_list[i])) {
0162                 status = -1;
0163                 goto out;
0164             }
0165             if (run_tests(5)) {
0166                 status = -1;
0167                 goto out;
0168             }
0169         }
0170     }
0171 
0172     printf("Running Asynchronous Switching Tests...\n");
0173     pid = fork();
0174     if (!pid)
0175         return run_tests(runtime);
0176 
0177     while (pid != waitpid(pid, &status, WNOHANG))
0178         for (i = 0; i < count; i++)
0179             if (change_clocksource(clocksource_list[i])) {
0180                 status = -1;
0181                 goto out;
0182             }
0183 out:
0184     change_clocksource(orig_clk);
0185 
0186     /* Print at the end to not mix output with child process */
0187     ksft_print_header();
0188     ksft_set_plan(1);
0189     ksft_test_result(!status, "clocksource-switch\n");
0190     ksft_exit(!status);
0191 }