18c2ecf20Sopenharmony_ci/* Clocksource change test 28c2ecf20Sopenharmony_ci * by: john stultz (johnstul@us.ibm.com) 38c2ecf20Sopenharmony_ci * (C) Copyright IBM 2012 48c2ecf20Sopenharmony_ci * Licensed under the GPLv2 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * NOTE: This is a meta-test which quickly changes the clocksourc and 78c2ecf20Sopenharmony_ci * then uses other tests to detect problems. Thus this test requires 88c2ecf20Sopenharmony_ci * that the inconsistency-check and nanosleep tests be present in the 98c2ecf20Sopenharmony_ci * same directory it is run from. 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * To build: 128c2ecf20Sopenharmony_ci * $ gcc clocksource-switch.c -o clocksource-switch -lrt 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * This program is free software: you can redistribute it and/or modify 158c2ecf20Sopenharmony_ci * it under the terms of the GNU General Public License as published by 168c2ecf20Sopenharmony_ci * the Free Software Foundation, either version 2 of the License, or 178c2ecf20Sopenharmony_ci * (at your option) any later version. 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * This program is distributed in the hope that it will be useful, 208c2ecf20Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 218c2ecf20Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 228c2ecf20Sopenharmony_ci * GNU General Public License for more details. 238c2ecf20Sopenharmony_ci */ 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#include <stdio.h> 278c2ecf20Sopenharmony_ci#include <unistd.h> 288c2ecf20Sopenharmony_ci#include <stdlib.h> 298c2ecf20Sopenharmony_ci#include <sys/time.h> 308c2ecf20Sopenharmony_ci#include <sys/timex.h> 318c2ecf20Sopenharmony_ci#include <time.h> 328c2ecf20Sopenharmony_ci#include <sys/types.h> 338c2ecf20Sopenharmony_ci#include <sys/stat.h> 348c2ecf20Sopenharmony_ci#include <fcntl.h> 358c2ecf20Sopenharmony_ci#include <string.h> 368c2ecf20Sopenharmony_ci#include <sys/wait.h> 378c2ecf20Sopenharmony_ci#include "../kselftest.h" 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ciint get_clocksources(char list[][30]) 418c2ecf20Sopenharmony_ci{ 428c2ecf20Sopenharmony_ci int fd, i; 438c2ecf20Sopenharmony_ci size_t size; 448c2ecf20Sopenharmony_ci char buf[512]; 458c2ecf20Sopenharmony_ci char *head, *tmp; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci fd = open("/sys/devices/system/clocksource/clocksource0/available_clocksource", O_RDONLY); 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci size = read(fd, buf, 512); 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci close(fd); 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci for (i = 0; i < 10; i++) 548c2ecf20Sopenharmony_ci list[i][0] = '\0'; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci head = buf; 578c2ecf20Sopenharmony_ci i = 0; 588c2ecf20Sopenharmony_ci while (head - buf < size) { 598c2ecf20Sopenharmony_ci /* Find the next space */ 608c2ecf20Sopenharmony_ci for (tmp = head; *tmp != ' '; tmp++) { 618c2ecf20Sopenharmony_ci if (*tmp == '\n') 628c2ecf20Sopenharmony_ci break; 638c2ecf20Sopenharmony_ci if (*tmp == '\0') 648c2ecf20Sopenharmony_ci break; 658c2ecf20Sopenharmony_ci } 668c2ecf20Sopenharmony_ci *tmp = '\0'; 678c2ecf20Sopenharmony_ci strcpy(list[i], head); 688c2ecf20Sopenharmony_ci head = tmp + 1; 698c2ecf20Sopenharmony_ci i++; 708c2ecf20Sopenharmony_ci } 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci return i-1; 738c2ecf20Sopenharmony_ci} 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ciint get_cur_clocksource(char *buf, size_t size) 768c2ecf20Sopenharmony_ci{ 778c2ecf20Sopenharmony_ci int fd; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci fd = open("/sys/devices/system/clocksource/clocksource0/current_clocksource", O_RDONLY); 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci size = read(fd, buf, size); 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci return 0; 848c2ecf20Sopenharmony_ci} 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ciint change_clocksource(char *clocksource) 878c2ecf20Sopenharmony_ci{ 888c2ecf20Sopenharmony_ci int fd; 898c2ecf20Sopenharmony_ci ssize_t size; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci fd = open("/sys/devices/system/clocksource/clocksource0/current_clocksource", O_WRONLY); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci if (fd < 0) 948c2ecf20Sopenharmony_ci return -1; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci size = write(fd, clocksource, strlen(clocksource)); 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci if (size < 0) 998c2ecf20Sopenharmony_ci return -1; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci close(fd); 1028c2ecf20Sopenharmony_ci return 0; 1038c2ecf20Sopenharmony_ci} 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ciint run_tests(int secs) 1078c2ecf20Sopenharmony_ci{ 1088c2ecf20Sopenharmony_ci int ret; 1098c2ecf20Sopenharmony_ci char buf[255]; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci sprintf(buf, "./inconsistency-check -t %i", secs); 1128c2ecf20Sopenharmony_ci ret = system(buf); 1138c2ecf20Sopenharmony_ci if (WIFEXITED(ret) && WEXITSTATUS(ret)) 1148c2ecf20Sopenharmony_ci return WEXITSTATUS(ret); 1158c2ecf20Sopenharmony_ci ret = system("./nanosleep"); 1168c2ecf20Sopenharmony_ci return WIFEXITED(ret) ? WEXITSTATUS(ret) : 0; 1178c2ecf20Sopenharmony_ci} 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_cichar clocksource_list[10][30]; 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ciint main(int argv, char **argc) 1238c2ecf20Sopenharmony_ci{ 1248c2ecf20Sopenharmony_ci char orig_clk[512]; 1258c2ecf20Sopenharmony_ci int count, i, status; 1268c2ecf20Sopenharmony_ci pid_t pid; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci get_cur_clocksource(orig_clk, 512); 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci count = get_clocksources(clocksource_list); 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci if (change_clocksource(clocksource_list[0])) { 1338c2ecf20Sopenharmony_ci printf("Error: You probably need to run this as root\n"); 1348c2ecf20Sopenharmony_ci return -1; 1358c2ecf20Sopenharmony_ci } 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci /* Check everything is sane before we start switching asyncrhonously */ 1388c2ecf20Sopenharmony_ci for (i = 0; i < count; i++) { 1398c2ecf20Sopenharmony_ci printf("Validating clocksource %s\n", clocksource_list[i]); 1408c2ecf20Sopenharmony_ci if (change_clocksource(clocksource_list[i])) { 1418c2ecf20Sopenharmony_ci status = -1; 1428c2ecf20Sopenharmony_ci goto out; 1438c2ecf20Sopenharmony_ci } 1448c2ecf20Sopenharmony_ci if (run_tests(5)) { 1458c2ecf20Sopenharmony_ci status = -1; 1468c2ecf20Sopenharmony_ci goto out; 1478c2ecf20Sopenharmony_ci } 1488c2ecf20Sopenharmony_ci } 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci printf("Running Asynchronous Switching Tests...\n"); 1528c2ecf20Sopenharmony_ci pid = fork(); 1538c2ecf20Sopenharmony_ci if (!pid) 1548c2ecf20Sopenharmony_ci return run_tests(60); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci while (pid != waitpid(pid, &status, WNOHANG)) 1578c2ecf20Sopenharmony_ci for (i = 0; i < count; i++) 1588c2ecf20Sopenharmony_ci if (change_clocksource(clocksource_list[i])) { 1598c2ecf20Sopenharmony_ci status = -1; 1608c2ecf20Sopenharmony_ci goto out; 1618c2ecf20Sopenharmony_ci } 1628c2ecf20Sopenharmony_ciout: 1638c2ecf20Sopenharmony_ci change_clocksource(orig_clk); 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci if (status) 1668c2ecf20Sopenharmony_ci return ksft_exit_fail(); 1678c2ecf20Sopenharmony_ci return ksft_exit_pass(); 1688c2ecf20Sopenharmony_ci} 169