/* Leap second test * by: john stultz (johnstul@us.ibm.com) * (C) Copyright IBM 2012 * Licensed under the GPL */ #include #include #include #include #define CALLS_PER_LOOP 64 #define NSEC_PER_SEC 1000000000ULL /* returns 1 if a <= b, 0 otherwise */ static inline int in_order(struct timespec a, struct timespec b) { if(a.tv_sec < b.tv_sec) return 1; if(a.tv_sec > b.tv_sec) return 0; if(a.tv_nsec > b.tv_nsec) return 0; return 1; } int main(void) { struct timeval tv; struct timex tx; struct timespec list[CALLS_PER_LOOP]; int i, inconsistent; int clock_type = CLOCK_REALTIME; long now, then; /* Get the current time */ gettimeofday(&tv, NULL); /* Calculate the next leap second */ tv.tv_sec += 86400 - tv.tv_sec % 86400; /* Set the time to be 10 seconds from that time */ tv.tv_sec -= 10; settimeofday(&tv, NULL); /* Set the leap second insert flag */ tx.modes = ADJ_STATUS; tx.status = STA_INS; adjtimex(&tx); clock_gettime(clock_type, &list[0]); now = then = list[0].tv_sec; while(now - then < 30){ inconsistent = 0; /* Fill list */ for(i=0; i < CALLS_PER_LOOP; i++) clock_gettime(clock_type, &list[i]); /* Check for inconsistencies */ for(i=0; i < CALLS_PER_LOOP-1; i++) if(!in_order(list[i],list[i+1])) inconsistent = i; /* display inconsistency */ if(inconsistent){ unsigned long long delta; for(i=0; i < CALLS_PER_LOOP; i++){ if(i == inconsistent) printf("--------------------\n"); printf("%lu:%lu\n",list[i].tv_sec, list[i].tv_nsec); if(i == inconsistent + 1 ) printf("--------------------\n"); } delta = list[inconsistent].tv_sec*NSEC_PER_SEC; delta += list[inconsistent].tv_nsec; delta -= list[inconsistent+1].tv_sec*NSEC_PER_SEC; delta -= list[inconsistent+1].tv_nsec; printf("Delta: %llu ns\n", delta); fflush(0); break; } now = list[0].tv_sec; } /* clear TIME_WAIT */ tx.modes = ADJ_STATUS; tx.status = 0; adjtimex(&tx); return 0; }