diff options
Diffstat (limited to 'tools/testing/selftests/timers/clocksource-switch.c')
| -rw-r--r-- | tools/testing/selftests/timers/clocksource-switch.c | 179 | 
1 files changed, 179 insertions, 0 deletions
diff --git a/tools/testing/selftests/timers/clocksource-switch.c b/tools/testing/selftests/timers/clocksource-switch.c new file mode 100644 index 000000000000..627ec7425f78 --- /dev/null +++ b/tools/testing/selftests/timers/clocksource-switch.c @@ -0,0 +1,179 @@ +/* Clocksource change test + *		by: john stultz ([email protected]) + *		(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 <unistd.h> +#include <stdlib.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> +#ifdef KTEST +#include "../kselftest.h" +#else +static inline int ksft_exit_pass(void) +{ +	exit(0); +} +static inline int ksft_exit_fail(void) +{ +	exit(1); +} +#endif + + +int get_clocksources(char list[][30]) +{ +	int fd, i; +	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; + +	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; +	size_t size; + +	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; + +	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); + +	if (status) +		return ksft_exit_fail(); +	return ksft_exit_pass(); +}  |