2015-03-12 03:40:12 +03:00
/* Demo leapsecond deadlock
* by : John Stultz ( john . stultz @ linaro . org )
* ( C ) Copyright IBM 2012
* ( C ) Copyright 2013 , 2015 Linaro Limited
* Licensed under the GPL
*
* This test demonstrates leapsecond deadlock that is possibe
* on kernels from 2.6 .26 to 3.3 .
*
* WARNING : THIS WILL LIKELY HARDHANG SYSTEMS AND MAY LOSE DATA
* RUN AT YOUR OWN RISK !
* To build :
* $ gcc leapcrash . c - o leapcrash - lrt
*/
# include <stdio.h>
# include <stdlib.h>
# include <time.h>
# include <sys/time.h>
# include <sys/timex.h>
# include <string.h>
# include <signal.h>
# include "../kselftest.h"
/* clear NTP time_status & time_state */
int clear_time_state ( void )
{
struct timex tx ;
int ret ;
/*
* We have to call adjtime twice here , as kernels
* prior to 6 b1859dba01c7 ( included in 3.5 and
* - stable ) , had an issue with the state machine
* and wouldn ' t clear the STA_INS / DEL flag directly .
*/
tx . modes = ADJ_STATUS ;
tx . status = STA_PLL ;
ret = adjtimex ( & tx ) ;
tx . modes = ADJ_STATUS ;
tx . status = 0 ;
ret = adjtimex ( & tx ) ;
return ret ;
}
/* Make sure we cleanup on ctrl-c */
void handler ( int unused )
{
clear_time_state ( ) ;
exit ( 0 ) ;
}
int main ( void )
{
struct timex tx ;
struct timespec ts ;
time_t next_leap ;
int count = 0 ;
setbuf ( stdout , NULL ) ;
signal ( SIGINT , handler ) ;
signal ( SIGKILL , handler ) ;
printf ( " This runs for a few minutes. Press ctrl-c to stop \n " ) ;
clear_time_state ( ) ;
/* Get the current time */
clock_gettime ( CLOCK_REALTIME , & ts ) ;
/* Calculate the next possible leap second 23:59:60 GMT */
next_leap = ts . tv_sec ;
next_leap + = 86400 - ( next_leap % 86400 ) ;
for ( count = 0 ; count < 20 ; count + + ) {
struct timeval tv ;
/* set the time to 2 seconds before the leap */
tv . tv_sec = next_leap - 2 ;
tv . tv_usec = 0 ;
if ( settimeofday ( & tv , NULL ) ) {
printf ( " Error: You're likely not running with proper (ie: root) permissions \n " ) ;
return ksft_exit_fail ( ) ;
}
tx . modes = 0 ;
adjtimex ( & tx ) ;
/* hammer on adjtime w/ STA_INS */
while ( tx . time . tv_sec < next_leap + 1 ) {
/* Set the leap second insert flag */
tx . modes = ADJ_STATUS ;
tx . status = STA_INS ;
adjtimex ( & tx ) ;
}
clear_time_state ( ) ;
printf ( " . " ) ;
2019-05-21 01:37:49 +03:00
fflush ( stdout ) ;
2015-03-12 03:40:12 +03:00
}
printf ( " [OK] \n " ) ;
return ksft_exit_pass ( ) ;
}