15bccfe41SJohn Stultz /* Leap second stress test 25bccfe41SJohn Stultz * by: John Stultz (john.stultz@linaro.org) 35bccfe41SJohn Stultz * (C) Copyright IBM 2012 45bccfe41SJohn Stultz * (C) Copyright 2013, 2015 Linaro Limited 55bccfe41SJohn Stultz * Licensed under the GPLv2 65bccfe41SJohn Stultz * 75bccfe41SJohn Stultz * This test signals the kernel to insert a leap second 85bccfe41SJohn Stultz * every day at midnight GMT. This allows for stessing the 95bccfe41SJohn Stultz * kernel's leap-second behavior, as well as how well applications 105bccfe41SJohn Stultz * handle the leap-second discontinuity. 115bccfe41SJohn Stultz * 125bccfe41SJohn Stultz * Usage: leap-a-day [-s] [-i <num>] 135bccfe41SJohn Stultz * 145bccfe41SJohn Stultz * Options: 155bccfe41SJohn Stultz * -s: Each iteration, set the date to 10 seconds before midnight GMT. 165bccfe41SJohn Stultz * This speeds up the number of leapsecond transitions tested, 175bccfe41SJohn Stultz * but because it calls settimeofday frequently, advancing the 185bccfe41SJohn Stultz * time by 24 hours every ~16 seconds, it may cause application 195bccfe41SJohn Stultz * disruption. 205bccfe41SJohn Stultz * 215bccfe41SJohn Stultz * -i: Number of iterations to run (default: infinite) 225bccfe41SJohn Stultz * 235bccfe41SJohn Stultz * Other notes: Disabling NTP prior to running this is advised, as the two 245bccfe41SJohn Stultz * may conflict in their commands to the kernel. 255bccfe41SJohn Stultz * 265bccfe41SJohn Stultz * To build: 275bccfe41SJohn Stultz * $ gcc leap-a-day.c -o leap-a-day -lrt 285bccfe41SJohn Stultz * 295bccfe41SJohn Stultz * This program is free software: you can redistribute it and/or modify 305bccfe41SJohn Stultz * it under the terms of the GNU General Public License as published by 315bccfe41SJohn Stultz * the Free Software Foundation, either version 2 of the License, or 325bccfe41SJohn Stultz * (at your option) any later version. 335bccfe41SJohn Stultz * 345bccfe41SJohn Stultz * This program is distributed in the hope that it will be useful, 355bccfe41SJohn Stultz * but WITHOUT ANY WARRANTY; without even the implied warranty of 365bccfe41SJohn Stultz * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 375bccfe41SJohn Stultz * GNU General Public License for more details. 385bccfe41SJohn Stultz */ 395bccfe41SJohn Stultz 405bccfe41SJohn Stultz 415bccfe41SJohn Stultz 425bccfe41SJohn Stultz #include <stdio.h> 435bccfe41SJohn Stultz #include <stdlib.h> 445bccfe41SJohn Stultz #include <time.h> 455bccfe41SJohn Stultz #include <sys/time.h> 465bccfe41SJohn Stultz #include <sys/timex.h> 470c4a5fc9SJohn Stultz #include <sys/errno.h> 485bccfe41SJohn Stultz #include <string.h> 495bccfe41SJohn Stultz #include <signal.h> 505bccfe41SJohn Stultz #include <unistd.h> 515bccfe41SJohn Stultz #ifdef KTEST 525bccfe41SJohn Stultz #include "../kselftest.h" 535bccfe41SJohn Stultz #else 545bccfe41SJohn Stultz static inline int ksft_exit_pass(void) 555bccfe41SJohn Stultz { 565bccfe41SJohn Stultz exit(0); 575bccfe41SJohn Stultz } 585bccfe41SJohn Stultz static inline int ksft_exit_fail(void) 595bccfe41SJohn Stultz { 605bccfe41SJohn Stultz exit(1); 615bccfe41SJohn Stultz } 625bccfe41SJohn Stultz #endif 635bccfe41SJohn Stultz 645bccfe41SJohn Stultz #define NSEC_PER_SEC 1000000000ULL 655bccfe41SJohn Stultz #define CLOCK_TAI 11 665bccfe41SJohn Stultz 670c4a5fc9SJohn Stultz time_t next_leap; 680c4a5fc9SJohn Stultz int error_found; 690c4a5fc9SJohn Stultz 705bccfe41SJohn Stultz /* returns 1 if a <= b, 0 otherwise */ 715bccfe41SJohn Stultz static inline int in_order(struct timespec a, struct timespec b) 725bccfe41SJohn Stultz { 735bccfe41SJohn Stultz if (a.tv_sec < b.tv_sec) 745bccfe41SJohn Stultz return 1; 755bccfe41SJohn Stultz if (a.tv_sec > b.tv_sec) 765bccfe41SJohn Stultz return 0; 775bccfe41SJohn Stultz if (a.tv_nsec > b.tv_nsec) 785bccfe41SJohn Stultz return 0; 795bccfe41SJohn Stultz return 1; 805bccfe41SJohn Stultz } 815bccfe41SJohn Stultz 825bccfe41SJohn Stultz struct timespec timespec_add(struct timespec ts, unsigned long long ns) 835bccfe41SJohn Stultz { 845bccfe41SJohn Stultz ts.tv_nsec += ns; 855bccfe41SJohn Stultz while (ts.tv_nsec >= NSEC_PER_SEC) { 865bccfe41SJohn Stultz ts.tv_nsec -= NSEC_PER_SEC; 875bccfe41SJohn Stultz ts.tv_sec++; 885bccfe41SJohn Stultz } 895bccfe41SJohn Stultz return ts; 905bccfe41SJohn Stultz } 915bccfe41SJohn Stultz 925bccfe41SJohn Stultz char *time_state_str(int state) 935bccfe41SJohn Stultz { 945bccfe41SJohn Stultz switch (state) { 955bccfe41SJohn Stultz case TIME_OK: return "TIME_OK"; 965bccfe41SJohn Stultz case TIME_INS: return "TIME_INS"; 975bccfe41SJohn Stultz case TIME_DEL: return "TIME_DEL"; 985bccfe41SJohn Stultz case TIME_OOP: return "TIME_OOP"; 995bccfe41SJohn Stultz case TIME_WAIT: return "TIME_WAIT"; 1005bccfe41SJohn Stultz case TIME_BAD: return "TIME_BAD"; 1015bccfe41SJohn Stultz } 1025bccfe41SJohn Stultz return "ERROR"; 1035bccfe41SJohn Stultz } 1045bccfe41SJohn Stultz 1055bccfe41SJohn Stultz /* clear NTP time_status & time_state */ 1065bccfe41SJohn Stultz int clear_time_state(void) 1075bccfe41SJohn Stultz { 1085bccfe41SJohn Stultz struct timex tx; 1095bccfe41SJohn Stultz int ret; 1105bccfe41SJohn Stultz 1115bccfe41SJohn Stultz /* 1125bccfe41SJohn Stultz * We have to call adjtime twice here, as kernels 1135bccfe41SJohn Stultz * prior to 6b1859dba01c7 (included in 3.5 and 1145bccfe41SJohn Stultz * -stable), had an issue with the state machine 1155bccfe41SJohn Stultz * and wouldn't clear the STA_INS/DEL flag directly. 1165bccfe41SJohn Stultz */ 1175bccfe41SJohn Stultz tx.modes = ADJ_STATUS; 1185bccfe41SJohn Stultz tx.status = STA_PLL; 1195bccfe41SJohn Stultz ret = adjtimex(&tx); 1205bccfe41SJohn Stultz 1215bccfe41SJohn Stultz /* Clear maxerror, as it can cause UNSYNC to be set */ 1225bccfe41SJohn Stultz tx.modes = ADJ_MAXERROR; 1235bccfe41SJohn Stultz tx.maxerror = 0; 1245bccfe41SJohn Stultz ret = adjtimex(&tx); 1255bccfe41SJohn Stultz 1265bccfe41SJohn Stultz /* Clear the status */ 1275bccfe41SJohn Stultz tx.modes = ADJ_STATUS; 1285bccfe41SJohn Stultz tx.status = 0; 1295bccfe41SJohn Stultz ret = adjtimex(&tx); 1305bccfe41SJohn Stultz 1315bccfe41SJohn Stultz return ret; 1325bccfe41SJohn Stultz } 1335bccfe41SJohn Stultz 1345bccfe41SJohn Stultz /* Make sure we cleanup on ctrl-c */ 1355bccfe41SJohn Stultz void handler(int unused) 1365bccfe41SJohn Stultz { 1375bccfe41SJohn Stultz clear_time_state(); 1385bccfe41SJohn Stultz exit(0); 1395bccfe41SJohn Stultz } 1405bccfe41SJohn Stultz 1410c4a5fc9SJohn Stultz void sigalarm(int signo) 1420c4a5fc9SJohn Stultz { 1430c4a5fc9SJohn Stultz struct timex tx; 1440c4a5fc9SJohn Stultz int ret; 1450c4a5fc9SJohn Stultz 1460c4a5fc9SJohn Stultz tx.modes = 0; 1470c4a5fc9SJohn Stultz ret = adjtimex(&tx); 1480c4a5fc9SJohn Stultz 149*51a16c1eSJohn Stultz if (tx.time.tv_sec < next_leap) { 150*51a16c1eSJohn Stultz printf("Error: Early timer expiration! (Should be %ld)\n", next_leap); 151*51a16c1eSJohn Stultz error_found = 1; 152*51a16c1eSJohn Stultz printf("adjtimex: %10ld sec + %6ld us (%i)\t%s\n", 153*51a16c1eSJohn Stultz tx.time.tv_sec, 1540c4a5fc9SJohn Stultz tx.time.tv_usec, 1550c4a5fc9SJohn Stultz tx.tai, 1560c4a5fc9SJohn Stultz time_state_str(ret)); 1570c4a5fc9SJohn Stultz } 1580c4a5fc9SJohn Stultz if (ret != TIME_WAIT) { 159*51a16c1eSJohn Stultz printf("Error: Timer seeing incorrect NTP state? (Should be TIME_WAIT)\n"); 1600c4a5fc9SJohn Stultz error_found = 1; 161*51a16c1eSJohn Stultz printf("adjtimex: %10ld sec + %6ld us (%i)\t%s\n", 162*51a16c1eSJohn Stultz tx.time.tv_sec, 163*51a16c1eSJohn Stultz tx.time.tv_usec, 164*51a16c1eSJohn Stultz tx.tai, 165*51a16c1eSJohn Stultz time_state_str(ret)); 1660c4a5fc9SJohn Stultz } 1670c4a5fc9SJohn Stultz } 1680c4a5fc9SJohn Stultz 1690c4a5fc9SJohn Stultz 1705bccfe41SJohn Stultz /* Test for known hrtimer failure */ 1715bccfe41SJohn Stultz void test_hrtimer_failure(void) 1725bccfe41SJohn Stultz { 1735bccfe41SJohn Stultz struct timespec now, target; 1745bccfe41SJohn Stultz 1755bccfe41SJohn Stultz clock_gettime(CLOCK_REALTIME, &now); 1765bccfe41SJohn Stultz target = timespec_add(now, NSEC_PER_SEC/2); 1775bccfe41SJohn Stultz clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &target, NULL); 1785bccfe41SJohn Stultz clock_gettime(CLOCK_REALTIME, &now); 1795bccfe41SJohn Stultz 1800c4a5fc9SJohn Stultz if (!in_order(target, now)) { 1815bccfe41SJohn Stultz printf("ERROR: hrtimer early expiration failure observed.\n"); 1820c4a5fc9SJohn Stultz error_found = 1; 1830c4a5fc9SJohn Stultz } 1845bccfe41SJohn Stultz } 1855bccfe41SJohn Stultz 1865bccfe41SJohn Stultz int main(int argc, char **argv) 1875bccfe41SJohn Stultz { 1880c4a5fc9SJohn Stultz timer_t tm1; 1890c4a5fc9SJohn Stultz struct itimerspec its1; 1900c4a5fc9SJohn Stultz struct sigevent se; 1910c4a5fc9SJohn Stultz struct sigaction act; 1920c4a5fc9SJohn Stultz int signum = SIGRTMAX; 1935bccfe41SJohn Stultz int settime = 0; 1945bccfe41SJohn Stultz int tai_time = 0; 1955bccfe41SJohn Stultz int insert = 1; 1965bccfe41SJohn Stultz int iterations = -1; 1975bccfe41SJohn Stultz int opt; 1985bccfe41SJohn Stultz 1995bccfe41SJohn Stultz /* Process arguments */ 2005bccfe41SJohn Stultz while ((opt = getopt(argc, argv, "sti:")) != -1) { 2015bccfe41SJohn Stultz switch (opt) { 2025bccfe41SJohn Stultz case 's': 2035bccfe41SJohn Stultz printf("Setting time to speed up testing\n"); 2045bccfe41SJohn Stultz settime = 1; 2055bccfe41SJohn Stultz break; 2065bccfe41SJohn Stultz case 'i': 2075bccfe41SJohn Stultz iterations = atoi(optarg); 2085bccfe41SJohn Stultz break; 2095bccfe41SJohn Stultz case 't': 2105bccfe41SJohn Stultz tai_time = 1; 2115bccfe41SJohn Stultz break; 2125bccfe41SJohn Stultz default: 2135bccfe41SJohn Stultz printf("Usage: %s [-s] [-i <iterations>]\n", argv[0]); 2145bccfe41SJohn Stultz printf(" -s: Set time to right before leap second each iteration\n"); 2155bccfe41SJohn Stultz printf(" -i: Number of iterations\n"); 2165bccfe41SJohn Stultz printf(" -t: Print TAI time\n"); 2175bccfe41SJohn Stultz exit(-1); 2185bccfe41SJohn Stultz } 2195bccfe41SJohn Stultz } 2205bccfe41SJohn Stultz 2215bccfe41SJohn Stultz /* Make sure TAI support is present if -t was used */ 2225bccfe41SJohn Stultz if (tai_time) { 2235bccfe41SJohn Stultz struct timespec ts; 2245bccfe41SJohn Stultz 2255bccfe41SJohn Stultz if (clock_gettime(CLOCK_TAI, &ts)) { 2265bccfe41SJohn Stultz printf("System doesn't support CLOCK_TAI\n"); 2275bccfe41SJohn Stultz ksft_exit_fail(); 2285bccfe41SJohn Stultz } 2295bccfe41SJohn Stultz } 2305bccfe41SJohn Stultz 2315bccfe41SJohn Stultz signal(SIGINT, handler); 2325bccfe41SJohn Stultz signal(SIGKILL, handler); 2335bccfe41SJohn Stultz 2340c4a5fc9SJohn Stultz /* Set up timer signal handler: */ 2350c4a5fc9SJohn Stultz sigfillset(&act.sa_mask); 2360c4a5fc9SJohn Stultz act.sa_flags = 0; 2370c4a5fc9SJohn Stultz act.sa_handler = sigalarm; 2380c4a5fc9SJohn Stultz sigaction(signum, &act, NULL); 2390c4a5fc9SJohn Stultz 2405bccfe41SJohn Stultz if (iterations < 0) 2415bccfe41SJohn Stultz printf("This runs continuously. Press ctrl-c to stop\n"); 2425bccfe41SJohn Stultz else 2435bccfe41SJohn Stultz printf("Running for %i iterations. Press ctrl-c to stop\n", iterations); 2445bccfe41SJohn Stultz 2455bccfe41SJohn Stultz printf("\n"); 2465bccfe41SJohn Stultz while (1) { 2475bccfe41SJohn Stultz int ret; 2485bccfe41SJohn Stultz struct timespec ts; 2495bccfe41SJohn Stultz struct timex tx; 2500c4a5fc9SJohn Stultz time_t now; 2515bccfe41SJohn Stultz 2525bccfe41SJohn Stultz /* Get the current time */ 2535bccfe41SJohn Stultz clock_gettime(CLOCK_REALTIME, &ts); 2545bccfe41SJohn Stultz 2555bccfe41SJohn Stultz /* Calculate the next possible leap second 23:59:60 GMT */ 2565bccfe41SJohn Stultz next_leap = ts.tv_sec; 2575bccfe41SJohn Stultz next_leap += 86400 - (next_leap % 86400); 2585bccfe41SJohn Stultz 2595bccfe41SJohn Stultz if (settime) { 2605bccfe41SJohn Stultz struct timeval tv; 2615bccfe41SJohn Stultz 2625bccfe41SJohn Stultz tv.tv_sec = next_leap - 10; 2635bccfe41SJohn Stultz tv.tv_usec = 0; 2645bccfe41SJohn Stultz settimeofday(&tv, NULL); 2655bccfe41SJohn Stultz printf("Setting time to %s", ctime(&tv.tv_sec)); 2665bccfe41SJohn Stultz } 2675bccfe41SJohn Stultz 2685bccfe41SJohn Stultz /* Reset NTP time state */ 2695bccfe41SJohn Stultz clear_time_state(); 2705bccfe41SJohn Stultz 2715bccfe41SJohn Stultz /* Set the leap second insert flag */ 2725bccfe41SJohn Stultz tx.modes = ADJ_STATUS; 2735bccfe41SJohn Stultz if (insert) 2745bccfe41SJohn Stultz tx.status = STA_INS; 2755bccfe41SJohn Stultz else 2765bccfe41SJohn Stultz tx.status = STA_DEL; 2775bccfe41SJohn Stultz ret = adjtimex(&tx); 2785bccfe41SJohn Stultz if (ret < 0) { 2795bccfe41SJohn Stultz printf("Error: Problem setting STA_INS/STA_DEL!: %s\n", 2805bccfe41SJohn Stultz time_state_str(ret)); 2815bccfe41SJohn Stultz return ksft_exit_fail(); 2825bccfe41SJohn Stultz } 2835bccfe41SJohn Stultz 2845bccfe41SJohn Stultz /* Validate STA_INS was set */ 2855bccfe41SJohn Stultz tx.modes = 0; 2865bccfe41SJohn Stultz ret = adjtimex(&tx); 2875bccfe41SJohn Stultz if (tx.status != STA_INS && tx.status != STA_DEL) { 2885bccfe41SJohn Stultz printf("Error: STA_INS/STA_DEL not set!: %s\n", 2895bccfe41SJohn Stultz time_state_str(ret)); 2905bccfe41SJohn Stultz return ksft_exit_fail(); 2915bccfe41SJohn Stultz } 2925bccfe41SJohn Stultz 2935bccfe41SJohn Stultz if (tai_time) { 2945bccfe41SJohn Stultz printf("Using TAI time," 2955bccfe41SJohn Stultz " no inconsistencies should be seen!\n"); 2965bccfe41SJohn Stultz } 2975bccfe41SJohn Stultz 2985bccfe41SJohn Stultz printf("Scheduling leap second for %s", ctime(&next_leap)); 2995bccfe41SJohn Stultz 3000c4a5fc9SJohn Stultz /* Set up timer */ 301*51a16c1eSJohn Stultz printf("Setting timer for %ld - %s", next_leap, ctime(&next_leap)); 3020c4a5fc9SJohn Stultz memset(&se, 0, sizeof(se)); 3030c4a5fc9SJohn Stultz se.sigev_notify = SIGEV_SIGNAL; 3040c4a5fc9SJohn Stultz se.sigev_signo = signum; 3050c4a5fc9SJohn Stultz se.sigev_value.sival_int = 0; 3060c4a5fc9SJohn Stultz if (timer_create(CLOCK_REALTIME, &se, &tm1) == -1) { 3070c4a5fc9SJohn Stultz printf("Error: timer_create failed\n"); 3080c4a5fc9SJohn Stultz return ksft_exit_fail(); 3090c4a5fc9SJohn Stultz } 3100c4a5fc9SJohn Stultz its1.it_value.tv_sec = next_leap; 3110c4a5fc9SJohn Stultz its1.it_value.tv_nsec = 0; 3120c4a5fc9SJohn Stultz its1.it_interval.tv_sec = 0; 3130c4a5fc9SJohn Stultz its1.it_interval.tv_nsec = 0; 3140c4a5fc9SJohn Stultz timer_settime(tm1, TIMER_ABSTIME, &its1, NULL); 3150c4a5fc9SJohn Stultz 3165bccfe41SJohn Stultz /* Wake up 3 seconds before leap */ 3175bccfe41SJohn Stultz ts.tv_sec = next_leap - 3; 3185bccfe41SJohn Stultz ts.tv_nsec = 0; 3195bccfe41SJohn Stultz 3200c4a5fc9SJohn Stultz 3215bccfe41SJohn Stultz while (clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &ts, NULL)) 3225bccfe41SJohn Stultz printf("Something woke us up, returning to sleep\n"); 3235bccfe41SJohn Stultz 3245bccfe41SJohn Stultz /* Validate STA_INS is still set */ 3255bccfe41SJohn Stultz tx.modes = 0; 3265bccfe41SJohn Stultz ret = adjtimex(&tx); 3275bccfe41SJohn Stultz if (tx.status != STA_INS && tx.status != STA_DEL) { 3285bccfe41SJohn Stultz printf("Something cleared STA_INS/STA_DEL, setting it again.\n"); 3295bccfe41SJohn Stultz tx.modes = ADJ_STATUS; 3305bccfe41SJohn Stultz if (insert) 3315bccfe41SJohn Stultz tx.status = STA_INS; 3325bccfe41SJohn Stultz else 3335bccfe41SJohn Stultz tx.status = STA_DEL; 3345bccfe41SJohn Stultz ret = adjtimex(&tx); 3355bccfe41SJohn Stultz } 3365bccfe41SJohn Stultz 3375bccfe41SJohn Stultz /* Check adjtimex output every half second */ 3385bccfe41SJohn Stultz now = tx.time.tv_sec; 3395bccfe41SJohn Stultz while (now < next_leap + 2) { 3405bccfe41SJohn Stultz char buf[26]; 3415bccfe41SJohn Stultz struct timespec tai; 3420c4a5fc9SJohn Stultz int ret; 3435bccfe41SJohn Stultz 3445bccfe41SJohn Stultz tx.modes = 0; 3455bccfe41SJohn Stultz ret = adjtimex(&tx); 3465bccfe41SJohn Stultz 3475bccfe41SJohn Stultz if (tai_time) { 3485bccfe41SJohn Stultz clock_gettime(CLOCK_TAI, &tai); 3495bccfe41SJohn Stultz printf("%ld sec, %9ld ns\t%s\n", 3505bccfe41SJohn Stultz tai.tv_sec, 3515bccfe41SJohn Stultz tai.tv_nsec, 3525bccfe41SJohn Stultz time_state_str(ret)); 3535bccfe41SJohn Stultz } else { 3545bccfe41SJohn Stultz ctime_r(&tx.time.tv_sec, buf); 3555bccfe41SJohn Stultz buf[strlen(buf)-1] = 0; /*remove trailing\n */ 3565bccfe41SJohn Stultz 3575bccfe41SJohn Stultz printf("%s + %6ld us (%i)\t%s\n", 3585bccfe41SJohn Stultz buf, 3595bccfe41SJohn Stultz tx.time.tv_usec, 3605bccfe41SJohn Stultz tx.tai, 3615bccfe41SJohn Stultz time_state_str(ret)); 3625bccfe41SJohn Stultz } 3635bccfe41SJohn Stultz now = tx.time.tv_sec; 3645bccfe41SJohn Stultz /* Sleep for another half second */ 3655bccfe41SJohn Stultz ts.tv_sec = 0; 3665bccfe41SJohn Stultz ts.tv_nsec = NSEC_PER_SEC / 2; 3675bccfe41SJohn Stultz clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL); 3685bccfe41SJohn Stultz } 3695bccfe41SJohn Stultz /* Switch to using other mode */ 3705bccfe41SJohn Stultz insert = !insert; 3715bccfe41SJohn Stultz 3725bccfe41SJohn Stultz /* Note if kernel has known hrtimer failure */ 3735bccfe41SJohn Stultz test_hrtimer_failure(); 3745bccfe41SJohn Stultz 3750c4a5fc9SJohn Stultz printf("Leap complete\n"); 3760c4a5fc9SJohn Stultz if (error_found) { 3770c4a5fc9SJohn Stultz printf("Errors observed\n"); 3780c4a5fc9SJohn Stultz clear_time_state(); 3790c4a5fc9SJohn Stultz return ksft_exit_fail(); 3800c4a5fc9SJohn Stultz } 3810c4a5fc9SJohn Stultz printf("\n"); 3825bccfe41SJohn Stultz if ((iterations != -1) && !(--iterations)) 3835bccfe41SJohn Stultz break; 3845bccfe41SJohn Stultz } 3855bccfe41SJohn Stultz 3865bccfe41SJohn Stultz clear_time_state(); 3875bccfe41SJohn Stultz return ksft_exit_pass(); 3885bccfe41SJohn Stultz } 389