2015-03-11 17:40:10 -07:00
/* Clocksource change test
* by : john stultz ( johnstul @ us . ibm . com )
* ( 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>
# include "../kselftest.h"
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 ) ;
2017-08-23 18:07:05 +02:00
for ( i = 0 ; i < 10 ; i + + )
2015-03-11 17:40:10 -07:00
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 ;
2015-09-21 15:33:41 +02:00
ssize_t size ;
2015-03-11 17:40:10 -07:00
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 ;
}
}
2017-04-12 14:48:17 +01:00
printf ( " Running Asynchronous Switching Tests... \n " ) ;
2015-03-11 17:40:10 -07:00
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 ( ) ;
}