0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042 #include <stdio.h>
0043 #include <stdlib.h>
0044 #include <time.h>
0045 #include <sys/time.h>
0046 #include <sys/timex.h>
0047 #include <sys/errno.h>
0048 #include <string.h>
0049 #include <signal.h>
0050 #include <unistd.h>
0051 #include "../kselftest.h"
0052
0053 #define NSEC_PER_SEC 1000000000ULL
0054 #define CLOCK_TAI 11
0055
0056 time_t next_leap;
0057 int error_found;
0058
0059
0060 static inline int in_order(struct timespec a, struct timespec b)
0061 {
0062 if (a.tv_sec < b.tv_sec)
0063 return 1;
0064 if (a.tv_sec > b.tv_sec)
0065 return 0;
0066 if (a.tv_nsec > b.tv_nsec)
0067 return 0;
0068 return 1;
0069 }
0070
0071 struct timespec timespec_add(struct timespec ts, unsigned long long ns)
0072 {
0073 ts.tv_nsec += ns;
0074 while (ts.tv_nsec >= NSEC_PER_SEC) {
0075 ts.tv_nsec -= NSEC_PER_SEC;
0076 ts.tv_sec++;
0077 }
0078 return ts;
0079 }
0080
0081 char *time_state_str(int state)
0082 {
0083 switch (state) {
0084 case TIME_OK: return "TIME_OK";
0085 case TIME_INS: return "TIME_INS";
0086 case TIME_DEL: return "TIME_DEL";
0087 case TIME_OOP: return "TIME_OOP";
0088 case TIME_WAIT: return "TIME_WAIT";
0089 case TIME_BAD: return "TIME_BAD";
0090 }
0091 return "ERROR";
0092 }
0093
0094
0095 int clear_time_state(void)
0096 {
0097 struct timex tx;
0098 int ret;
0099
0100
0101
0102
0103
0104
0105
0106 tx.modes = ADJ_STATUS;
0107 tx.status = STA_PLL;
0108 ret = adjtimex(&tx);
0109
0110
0111 tx.modes = ADJ_MAXERROR;
0112 tx.maxerror = 0;
0113 ret = adjtimex(&tx);
0114
0115
0116 tx.modes = ADJ_STATUS;
0117 tx.status = 0;
0118 ret = adjtimex(&tx);
0119
0120 return ret;
0121 }
0122
0123
0124 void handler(int unused)
0125 {
0126 clear_time_state();
0127 exit(0);
0128 }
0129
0130 void sigalarm(int signo)
0131 {
0132 struct timex tx;
0133 int ret;
0134
0135 tx.modes = 0;
0136 ret = adjtimex(&tx);
0137
0138 if (tx.time.tv_sec < next_leap) {
0139 printf("Error: Early timer expiration! (Should be %ld)\n", next_leap);
0140 error_found = 1;
0141 printf("adjtimex: %10ld sec + %6ld us (%i)\t%s\n",
0142 tx.time.tv_sec,
0143 tx.time.tv_usec,
0144 tx.tai,
0145 time_state_str(ret));
0146 }
0147 if (ret != TIME_WAIT) {
0148 printf("Error: Timer seeing incorrect NTP state? (Should be TIME_WAIT)\n");
0149 error_found = 1;
0150 printf("adjtimex: %10ld sec + %6ld us (%i)\t%s\n",
0151 tx.time.tv_sec,
0152 tx.time.tv_usec,
0153 tx.tai,
0154 time_state_str(ret));
0155 }
0156 }
0157
0158
0159
0160 void test_hrtimer_failure(void)
0161 {
0162 struct timespec now, target;
0163
0164 clock_gettime(CLOCK_REALTIME, &now);
0165 target = timespec_add(now, NSEC_PER_SEC/2);
0166 clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &target, NULL);
0167 clock_gettime(CLOCK_REALTIME, &now);
0168
0169 if (!in_order(target, now)) {
0170 printf("ERROR: hrtimer early expiration failure observed.\n");
0171 error_found = 1;
0172 }
0173 }
0174
0175 int main(int argc, char **argv)
0176 {
0177 timer_t tm1;
0178 struct itimerspec its1;
0179 struct sigevent se;
0180 struct sigaction act;
0181 int signum = SIGRTMAX;
0182 int settime = 1;
0183 int tai_time = 0;
0184 int insert = 1;
0185 int iterations = 10;
0186 int opt;
0187
0188
0189 while ((opt = getopt(argc, argv, "sti:")) != -1) {
0190 switch (opt) {
0191 case 'w':
0192 printf("Only setting leap-flag, not changing time. It could take up to a day for leap to trigger.\n");
0193 settime = 0;
0194 break;
0195 case 'i':
0196 iterations = atoi(optarg);
0197 break;
0198 case 't':
0199 tai_time = 1;
0200 break;
0201 default:
0202 printf("Usage: %s [-w] [-i <iterations>]\n", argv[0]);
0203 printf(" -w: Set flag and wait for leap second each iteration");
0204 printf(" (default sets time to right before leapsecond)\n");
0205 printf(" -i: Number of iterations (-1 = infinite, default is 10)\n");
0206 printf(" -t: Print TAI time\n");
0207 exit(-1);
0208 }
0209 }
0210
0211
0212 if (tai_time) {
0213 struct timespec ts;
0214
0215 if (clock_gettime(CLOCK_TAI, &ts)) {
0216 printf("System doesn't support CLOCK_TAI\n");
0217 ksft_exit_fail();
0218 }
0219 }
0220
0221 signal(SIGINT, handler);
0222 signal(SIGKILL, handler);
0223
0224
0225 sigfillset(&act.sa_mask);
0226 act.sa_flags = 0;
0227 act.sa_handler = sigalarm;
0228 sigaction(signum, &act, NULL);
0229
0230 if (iterations < 0)
0231 printf("This runs continuously. Press ctrl-c to stop\n");
0232 else
0233 printf("Running for %i iterations. Press ctrl-c to stop\n", iterations);
0234
0235 printf("\n");
0236 while (1) {
0237 int ret;
0238 struct timespec ts;
0239 struct timex tx;
0240 time_t now;
0241
0242
0243 clock_gettime(CLOCK_REALTIME, &ts);
0244
0245
0246 next_leap = ts.tv_sec;
0247 next_leap += 86400 - (next_leap % 86400);
0248
0249 if (settime) {
0250 struct timeval tv;
0251
0252 tv.tv_sec = next_leap - 10;
0253 tv.tv_usec = 0;
0254 settimeofday(&tv, NULL);
0255 printf("Setting time to %s", ctime(&tv.tv_sec));
0256 }
0257
0258
0259 clear_time_state();
0260
0261
0262 tx.modes = ADJ_STATUS;
0263 if (insert)
0264 tx.status = STA_INS;
0265 else
0266 tx.status = STA_DEL;
0267 ret = adjtimex(&tx);
0268 if (ret < 0) {
0269 printf("Error: Problem setting STA_INS/STA_DEL!: %s\n",
0270 time_state_str(ret));
0271 return ksft_exit_fail();
0272 }
0273
0274
0275 tx.modes = 0;
0276 ret = adjtimex(&tx);
0277 if (tx.status != STA_INS && tx.status != STA_DEL) {
0278 printf("Error: STA_INS/STA_DEL not set!: %s\n",
0279 time_state_str(ret));
0280 return ksft_exit_fail();
0281 }
0282
0283 if (tai_time) {
0284 printf("Using TAI time,"
0285 " no inconsistencies should be seen!\n");
0286 }
0287
0288 printf("Scheduling leap second for %s", ctime(&next_leap));
0289
0290
0291 printf("Setting timer for %ld - %s", next_leap, ctime(&next_leap));
0292 memset(&se, 0, sizeof(se));
0293 se.sigev_notify = SIGEV_SIGNAL;
0294 se.sigev_signo = signum;
0295 se.sigev_value.sival_int = 0;
0296 if (timer_create(CLOCK_REALTIME, &se, &tm1) == -1) {
0297 printf("Error: timer_create failed\n");
0298 return ksft_exit_fail();
0299 }
0300 its1.it_value.tv_sec = next_leap;
0301 its1.it_value.tv_nsec = 0;
0302 its1.it_interval.tv_sec = 0;
0303 its1.it_interval.tv_nsec = 0;
0304 timer_settime(tm1, TIMER_ABSTIME, &its1, NULL);
0305
0306
0307 ts.tv_sec = next_leap - 3;
0308 ts.tv_nsec = 0;
0309
0310
0311 while (clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &ts, NULL))
0312 printf("Something woke us up, returning to sleep\n");
0313
0314
0315 tx.modes = 0;
0316 ret = adjtimex(&tx);
0317 if (tx.status != STA_INS && tx.status != STA_DEL) {
0318 printf("Something cleared STA_INS/STA_DEL, setting it again.\n");
0319 tx.modes = ADJ_STATUS;
0320 if (insert)
0321 tx.status = STA_INS;
0322 else
0323 tx.status = STA_DEL;
0324 ret = adjtimex(&tx);
0325 }
0326
0327
0328 now = tx.time.tv_sec;
0329 while (now < next_leap + 2) {
0330 char buf[26];
0331 struct timespec tai;
0332 int ret;
0333
0334 tx.modes = 0;
0335 ret = adjtimex(&tx);
0336
0337 if (tai_time) {
0338 clock_gettime(CLOCK_TAI, &tai);
0339 printf("%ld sec, %9ld ns\t%s\n",
0340 tai.tv_sec,
0341 tai.tv_nsec,
0342 time_state_str(ret));
0343 } else {
0344 ctime_r(&tx.time.tv_sec, buf);
0345 buf[strlen(buf)-1] = 0;
0346
0347 printf("%s + %6ld us (%i)\t%s\n",
0348 buf,
0349 tx.time.tv_usec,
0350 tx.tai,
0351 time_state_str(ret));
0352 }
0353 now = tx.time.tv_sec;
0354
0355 ts.tv_sec = 0;
0356 ts.tv_nsec = NSEC_PER_SEC / 2;
0357 clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);
0358 }
0359
0360 insert = !insert;
0361
0362
0363 test_hrtimer_failure();
0364
0365 printf("Leap complete\n");
0366 if (error_found) {
0367 printf("Errors observed\n");
0368 clear_time_state();
0369 return ksft_exit_fail();
0370 }
0371 printf("\n");
0372 if ((iterations != -1) && !(--iterations))
0373 break;
0374 }
0375
0376 clear_time_state();
0377 return ksft_exit_pass();
0378 }