192 lines · c
1/* Clocksource change test2 * by: john stultz (johnstul@us.ibm.com)3 * (C) Copyright IBM 20124 * Licensed under the GPLv25 *6 * NOTE: This is a meta-test which quickly changes the clocksource and7 * then uses other tests to detect problems. Thus this test requires8 * that the inconsistency-check and nanosleep tests be present in the9 * same directory it is run from.10 *11 * To build:12 * $ gcc clocksource-switch.c -o clocksource-switch -lrt13 *14 * This program is free software: you can redistribute it and/or modify15 * it under the terms of the GNU General Public License as published by16 * the Free Software Foundation, either version 2 of the License, or17 * (at your option) any later version.18 *19 * This program is distributed in the hope that it will be useful,20 * but WITHOUT ANY WARRANTY; without even the implied warranty of21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the22 * GNU General Public License for more details.23 */24 25 26#include <fcntl.h>27#include <stdio.h>28#include <stdlib.h>29#include <string.h>30#include <sys/stat.h>31#include <sys/time.h>32#include <sys/timex.h>33#include <sys/types.h>34#include <sys/wait.h>35#include <time.h>36#include <unistd.h>37#include "../kselftest.h"38 39 40int get_clocksources(char list[][30])41{42 int fd, i;43 size_t size;44 char buf[512];45 char *head, *tmp;46 47 fd = open("/sys/devices/system/clocksource/clocksource0/available_clocksource", O_RDONLY);48 49 size = read(fd, buf, 512);50 51 close(fd);52 53 for (i = 0; i < 10; i++)54 list[i][0] = '\0';55 56 head = buf;57 i = 0;58 while (head - buf < size) {59 /* Find the next space */60 for (tmp = head; *tmp != ' '; tmp++) {61 if (*tmp == '\n')62 break;63 if (*tmp == '\0')64 break;65 }66 *tmp = '\0';67 strcpy(list[i], head);68 head = tmp + 1;69 i++;70 }71 72 return i-1;73}74 75int get_cur_clocksource(char *buf, size_t size)76{77 int fd;78 79 fd = open("/sys/devices/system/clocksource/clocksource0/current_clocksource", O_RDONLY);80 81 size = read(fd, buf, size);82 83 return 0;84}85 86int change_clocksource(char *clocksource)87{88 int fd;89 ssize_t size;90 91 fd = open("/sys/devices/system/clocksource/clocksource0/current_clocksource", O_WRONLY);92 93 if (fd < 0)94 return -1;95 96 size = write(fd, clocksource, strlen(clocksource));97 98 if (size < 0)99 return -1;100 101 close(fd);102 return 0;103}104 105 106int run_tests(int secs)107{108 int ret;109 char buf[255];110 111 sprintf(buf, "./inconsistency-check -t %i", secs);112 ret = system(buf);113 if (WIFEXITED(ret) && WEXITSTATUS(ret))114 return WEXITSTATUS(ret);115 ret = system("./nanosleep");116 return WIFEXITED(ret) ? WEXITSTATUS(ret) : 0;117}118 119 120char clocksource_list[10][30];121 122int main(int argc, char **argv)123{124 char orig_clk[512];125 int count, i, status, opt;126 int do_sanity_check = 1;127 int runtime = 60;128 pid_t pid;129 130 /* Process arguments */131 while ((opt = getopt(argc, argv, "st:")) != -1) {132 switch (opt) {133 case 's':134 do_sanity_check = 0;135 break;136 case 't':137 runtime = atoi(optarg);138 break;139 default:140 printf("Usage: %s [-s] [-t <secs>]\n", argv[0]);141 printf(" -s: skip sanity checks\n");142 printf(" -t: Number of seconds to run\n");143 exit(-1);144 }145 }146 147 get_cur_clocksource(orig_clk, 512);148 149 count = get_clocksources(clocksource_list);150 151 if (change_clocksource(clocksource_list[0])) {152 printf("Error: You probably need to run this as root\n");153 return -1;154 }155 156 /* Check everything is sane before we start switching asynchronously */157 if (do_sanity_check) {158 for (i = 0; i < count; i++) {159 printf("Validating clocksource %s\n",160 clocksource_list[i]);161 if (change_clocksource(clocksource_list[i])) {162 status = -1;163 goto out;164 }165 if (run_tests(5)) {166 status = -1;167 goto out;168 }169 }170 }171 172 printf("Running Asynchronous Switching Tests...\n");173 pid = fork();174 if (!pid)175 return run_tests(runtime);176 177 while (pid != waitpid(pid, &status, WNOHANG))178 for (i = 0; i < count; i++)179 if (change_clocksource(clocksource_list[i])) {180 status = -1;181 goto out;182 }183out:184 change_clocksource(orig_clk);185 186 /* Print at the end to not mix output with child process */187 ksft_print_header();188 ksft_set_plan(1);189 ksft_test_result(!status, "clocksource-switch\n");190 ksft_exit(!status);191}192