Home | History | Annotate | Download | only in timers
      1 /* Clocksource change test
      2  *		by: john stultz (johnstul (at) us.ibm.com)
      3  *		(C) Copyright IBM 2012
      4  *		Licensed under the GPLv2
      5  *
      6  *  NOTE: This is a meta-test which quickly changes the clocksourc and
      7  *  then uses other tests to detect problems. Thus this test requires
      8  *  that the inconsistency-check and nanosleep tests be present in the
      9  *  same directory it is run from.
     10  *
     11  *  To build:
     12  *	$ gcc clocksource-switch.c -o clocksource-switch -lrt
     13  *
     14  *   This program is free software: you can redistribute it and/or modify
     15  *   it under the terms of the GNU General Public License as published by
     16  *   the Free Software Foundation, either version 2 of the License, or
     17  *   (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 of
     21  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     22  *   GNU General Public License for more details.
     23  */
     24 
     25 
     26 #include <stdio.h>
     27 #include <unistd.h>
     28 #include <stdlib.h>
     29 #include <sys/time.h>
     30 #include <sys/timex.h>
     31 #include <time.h>
     32 #include <sys/types.h>
     33 #include <sys/stat.h>
     34 #include <fcntl.h>
     35 #include <string.h>
     36 #include <sys/wait.h>
     37 #ifdef KTEST
     38 #include "../kselftest.h"
     39 #else
     40 static inline int ksft_exit_pass(void)
     41 {
     42 	exit(0);
     43 }
     44 static inline int ksft_exit_fail(void)
     45 {
     46 	exit(1);
     47 }
     48 #endif
     49 
     50 
     51 int get_clocksources(char list[][30])
     52 {
     53 	int fd, i;
     54 	size_t size;
     55 	char buf[512];
     56 	char *head, *tmp;
     57 
     58 	fd = open("/sys/devices/system/clocksource/clocksource0/available_clocksource", O_RDONLY);
     59 
     60 	size = read(fd, buf, 512);
     61 
     62 	close(fd);
     63 
     64 	for (i = 0; i < 30; i++)
     65 		list[i][0] = '\0';
     66 
     67 	head = buf;
     68 	i = 0;
     69 	while (head - buf < size) {
     70 		/* Find the next space */
     71 		for (tmp = head; *tmp != ' '; tmp++) {
     72 			if (*tmp == '\n')
     73 				break;
     74 			if (*tmp == '\0')
     75 				break;
     76 		}
     77 		*tmp = '\0';
     78 		strcpy(list[i], head);
     79 		head = tmp + 1;
     80 		i++;
     81 	}
     82 
     83 	return i-1;
     84 }
     85 
     86 int get_cur_clocksource(char *buf, size_t size)
     87 {
     88 	int fd;
     89 
     90 	fd = open("/sys/devices/system/clocksource/clocksource0/current_clocksource", O_RDONLY);
     91 
     92 	size = read(fd, buf, size);
     93 
     94 	return 0;
     95 }
     96 
     97 int change_clocksource(char *clocksource)
     98 {
     99 	int fd;
    100 	ssize_t size;
    101 
    102 	fd = open("/sys/devices/system/clocksource/clocksource0/current_clocksource", O_WRONLY);
    103 
    104 	if (fd < 0)
    105 		return -1;
    106 
    107 	size = write(fd, clocksource, strlen(clocksource));
    108 
    109 	if (size < 0)
    110 		return -1;
    111 
    112 	close(fd);
    113 	return 0;
    114 }
    115 
    116 
    117 int run_tests(int secs)
    118 {
    119 	int ret;
    120 	char buf[255];
    121 
    122 	sprintf(buf, "./inconsistency-check -t %i", secs);
    123 	ret = system(buf);
    124 	if (ret)
    125 		return ret;
    126 	ret = system("./nanosleep");
    127 	return ret;
    128 }
    129 
    130 
    131 char clocksource_list[10][30];
    132 
    133 int main(int argv, char **argc)
    134 {
    135 	char orig_clk[512];
    136 	int count, i, status;
    137 	pid_t pid;
    138 
    139 	get_cur_clocksource(orig_clk, 512);
    140 
    141 	count = get_clocksources(clocksource_list);
    142 
    143 	if (change_clocksource(clocksource_list[0])) {
    144 		printf("Error: You probably need to run this as root\n");
    145 		return -1;
    146 	}
    147 
    148 	/* Check everything is sane before we start switching asyncrhonously */
    149 	for (i = 0; i < count; i++) {
    150 		printf("Validating clocksource %s\n", clocksource_list[i]);
    151 		if (change_clocksource(clocksource_list[i])) {
    152 			status = -1;
    153 			goto out;
    154 		}
    155 		if (run_tests(5)) {
    156 			status = -1;
    157 			goto out;
    158 		}
    159 	}
    160 
    161 
    162 	printf("Running Asyncrhonous Switching Tests...\n");
    163 	pid = fork();
    164 	if (!pid)
    165 		return run_tests(60);
    166 
    167 	while (pid != waitpid(pid, &status, WNOHANG))
    168 		for (i = 0; i < count; i++)
    169 			if (change_clocksource(clocksource_list[i])) {
    170 				status = -1;
    171 				goto out;
    172 			}
    173 out:
    174 	change_clocksource(orig_clk);
    175 
    176 	if (status)
    177 		return ksft_exit_fail();
    178 	return ksft_exit_pass();
    179 }
    180