Back to home page

OSCL-LXR

 
 

    


0001 /* Demo leapsecond deadlock
0002  *              by: John Stultz (john.stultz@linaro.org)
0003  *              (C) Copyright IBM 2012
0004  *              (C) Copyright 2013, 2015 Linaro Limited
0005  *              Licensed under the GPL
0006  *
0007  * This test demonstrates leapsecond deadlock that is possible
0008  * on kernels from 2.6.26 to 3.3.
0009  *
0010  * WARNING: THIS WILL LIKELY HARD HANG SYSTEMS AND MAY LOSE DATA
0011  * RUN AT YOUR OWN RISK!
0012  *  To build:
0013  *  $ gcc leapcrash.c -o leapcrash -lrt
0014  */
0015 
0016 
0017 
0018 #include <stdio.h>
0019 #include <stdlib.h>
0020 #include <time.h>
0021 #include <sys/time.h>
0022 #include <sys/timex.h>
0023 #include <string.h>
0024 #include <signal.h>
0025 #include "../kselftest.h"
0026 
0027 /* clear NTP time_status & time_state */
0028 int clear_time_state(void)
0029 {
0030     struct timex tx;
0031     int ret;
0032 
0033     /*
0034      * We have to call adjtime twice here, as kernels
0035      * prior to 6b1859dba01c7 (included in 3.5 and
0036      * -stable), had an issue with the state machine
0037      * and wouldn't clear the STA_INS/DEL flag directly.
0038      */
0039     tx.modes = ADJ_STATUS;
0040     tx.status = STA_PLL;
0041     ret = adjtimex(&tx);
0042 
0043     tx.modes = ADJ_STATUS;
0044     tx.status = 0;
0045     ret = adjtimex(&tx);
0046 
0047     return ret;
0048 }
0049 
0050 /* Make sure we cleanup on ctrl-c */
0051 void handler(int unused)
0052 {
0053     clear_time_state();
0054     exit(0);
0055 }
0056 
0057 
0058 int main(void)
0059 {
0060     struct timex tx;
0061     struct timespec ts;
0062     time_t next_leap;
0063     int count = 0;
0064 
0065     setbuf(stdout, NULL);
0066 
0067     signal(SIGINT, handler);
0068     signal(SIGKILL, handler);
0069     printf("This runs for a few minutes. Press ctrl-c to stop\n");
0070 
0071     clear_time_state();
0072 
0073 
0074     /* Get the current time */
0075     clock_gettime(CLOCK_REALTIME, &ts);
0076 
0077     /* Calculate the next possible leap second 23:59:60 GMT */
0078     next_leap = ts.tv_sec;
0079     next_leap += 86400 - (next_leap % 86400);
0080 
0081     for (count = 0; count < 20; count++) {
0082         struct timeval tv;
0083 
0084 
0085         /* set the time to 2 seconds before the leap */
0086         tv.tv_sec = next_leap - 2;
0087         tv.tv_usec = 0;
0088         if (settimeofday(&tv, NULL)) {
0089             printf("Error: You're likely not running with proper (ie: root) permissions\n");
0090             return ksft_exit_fail();
0091         }
0092         tx.modes = 0;
0093         adjtimex(&tx);
0094 
0095         /* hammer on adjtime w/ STA_INS */
0096         while (tx.time.tv_sec < next_leap + 1) {
0097             /* Set the leap second insert flag */
0098             tx.modes = ADJ_STATUS;
0099             tx.status = STA_INS;
0100             adjtimex(&tx);
0101         }
0102         clear_time_state();
0103         printf(".");
0104         fflush(stdout);
0105     }
0106     printf("[OK]\n");
0107     return ksft_exit_pass();
0108 }