Commit 9cf86c46 authored by Sven Meier's avatar Sven Meier Committed by Adam Wujek

ppsi & utc_leap_test: added utc leap second test tool and updated utc handling in ppsi

parent 51fb63e0
ppsi @ b2f4280d
Subproject commit c0c600ecb8c8b79f1a80a6f4a652b94773e9dcf3
Subproject commit b2f4280d7386dd936e0b62712955d6e5e31d2e94
......@@ -10,6 +10,7 @@ TOOLS += wrs_status_led
TOOLS += mkpasswd
TOOLS += wrs_sfp_dump
TOOLS += wrs_throttling
TOOLS += utc_leap_test
PPSI_CONFIG = ../ppsi/include/generated/autoconf.h
WR_INSTALL_ROOT ?= /usr/lib/white-rabbit
......
/* This is just a subset of wr_date, user to test on the host */
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <getopt.h>
#include <fcntl.h>
#include <time.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/timex.h>
#ifndef MOD_TAI
#define MOD_TAI 0x80
#endif
int opt_verbose = 1;
char *prgname;
static void unix_time_clear_utc_flags(void)
{
struct timex t;
/*
* We have to call adjtime twice here, as kernels
* prior to 6b1859dba01c7 (included in 3.5 and
* -stable), had an issue with the state machine
* and wouldn't clear the STA_INS/DEL flag directly.
*/
t.modes = ADJ_STATUS;
t.status = STA_PLL;
adjtimex(&t);
/* Clear maxerror, as it can cause UNSYNC to be set */
t.modes = ADJ_MAXERROR;
t.maxerror = 0;
adjtimex(&t);
/* Clear the status */
t.modes = ADJ_STATUS;
t.status = 0;
adjtimex(&t);
}
static int unix_time_get_utc_time(int *hours, int *minutes, int *seconds)
{
int ret;
struct timex t;
time_t now;
struct tm *date;
/* Get the UTC time */
memset(&t, 0, sizeof(t));
ret = adjtimex(&t);
if (ret >= 0) {
now = t.time.tv_sec;
/* use gmtime for correct leap handling */
date = gmtime(&now);
*hours = date->tm_hour;
*minutes = date->tm_min;
*seconds = date->tm_sec;
return 0;
} else {
*hours = 0;
*minutes = 0;
*seconds = 0;
return -1;
}
return -1;
}
static int unix_time_get_utc_offset(int *offset, int *leap59, int *leap61)
{
int ret;
struct timex t;
int hours, minutes, seconds;
unix_time_get_utc_time(&hours, &minutes, &seconds);
/*
* Get the UTC/TAI difference
*/
memset(&t, 0, sizeof(t));
ret = adjtimex(&t);
if (ret >= 0) {
if (hours >= 12) {
if ((t.status & STA_INS) == STA_INS) {
*leap59 = 0;
*leap61 = 1;
} else if ((t.status & STA_DEL) == STA_DEL) {
*leap59 = 1;
*leap61 = 0;
} else {
*leap59 = 0;
*leap61 = 0;
}
} else {
unix_time_clear_utc_flags();
*leap59 = 0;
*leap61 = 0;
}
/*
* Our WRS kernel has tai support, but our compiler does not.
* We are 32-bit only, and we know for sure that tai is
* exactly after stbcnt. It's a bad hack, but it works
*/
*offset = *((int *)(&t.stbcnt) + 1);
return 0;
} else {
*leap59 = 0;
*leap61 = 0;
*offset = 0;
return -1;
}
}
static int unix_time_set_utc_offset(int offset, int leap59, int leap61)
{
struct timex t;
int ret;
unix_time_clear_utc_flags();
/* get the current flags first */
memset(&t, 0, sizeof(t));
ret = adjtimex(&t);
if (ret >= 0) {
if (leap59) {
t.modes = MOD_STATUS;
t.status |= STA_DEL;
t.status &= ~STA_INS;
printf("set leap59 flag\n");
} else if (leap61) {
t.modes = MOD_STATUS;
t.status |= STA_INS;
t.status &= ~STA_DEL;
printf("set leap61 flag\n");
} else {
t.modes = MOD_STATUS;
t.status &= ~STA_INS;
t.status &= ~STA_DEL;
printf("set no leap flags\n");
}
if (adjtimex(&t) < 0) {
printf("set UTC flags failed\n");
return -1;
}
} else
printf("get UTC flags failed\n");
t.modes = MOD_TAI;
t.constant = offset;
if (adjtimex(&t) < 0) {
printf("set UTC offset failed\n");
return -1;
} else
printf("set UTC offset to: %i\n", offset);
return 0;
}
int main(int argc, char **argv)
{
int i, j;
int offset, leap59, leap61;
int hours, minutes, seconds;
struct timespec tp;
for (j=0; j<3; j++) {
/* Get the UTC time */
unix_time_get_utc_time(&hours, &minutes, &seconds);
unix_time_get_utc_offset(&offset, &leap59, &leap61);
printf("current time %d:%d:%d, offset=%d, l59=%d, l61=%d\n", hours, minutes, seconds, offset, leap59, leap61);
/* Set time to 30. June 2017 23:59:50 */
tp.tv_sec = 1498867190;
tp.tv_nsec = 0;
clock_settime(CLOCK_REALTIME, &tp);
/* Get the UTC time */
unix_time_get_utc_time(&hours, &minutes, &seconds);
unix_time_get_utc_offset(&offset, &leap59, &leap61);
printf("new current time %d:%d:%d, offset=%d, l59=%d, l61=%d\n", hours, minutes, seconds, offset, leap59, leap61);
if (j == 0) {
/* Set leap61 and UTC offset to 37 */
offset = 37;
leap59 = 0;
leap61 = 1;
unix_time_set_utc_offset(offset, leap59, leap61);
} else if (j == 1) {
/* Set leap59 and UTC offset to 37 */
offset = 37;
leap59 = 1;
leap61 = 0;
unix_time_set_utc_offset(offset, leap59, leap61);
} else {
/* Set no leaps and UTC offset to 37 */
offset = 37;
leap59 = 0;
leap61 = 0;
unix_time_set_utc_offset(offset, leap59, leap61);
}
/* Get the UTC time */
unix_time_get_utc_offset(&offset, &leap59, &leap61);
printf("new current time after offset and leap %d:%d:%d, offset=%d, l59=%d, l61=%d\n", hours, minutes, seconds, offset, leap59, leap61);
unix_time_get_utc_time(&hours, &minutes, &seconds);
for (i=0; i< 20; i++)
{
unix_time_get_utc_offset(&offset, &leap59, &leap61);
printf("new current time after offset and leap %d:%d:%d, offset=%d, l59=%d, l61=%d\n", hours, minutes, seconds, offset, leap59, leap61);
unix_time_get_utc_time(&hours, &minutes, &seconds);
sleep(1);
}
}
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment