Commit f1d55003 authored by Adam Wujek's avatar Adam Wujek 💬

Merge branch 'adam-time'

Replace time() calls with monotinic version from libwr
Fix bug 1164 and similar problems in other programs.

It was possible that SNMP objects in expert branch don't update.
It pop-up in following scenario:
  1. slave switch is started with no ntp configured
  2. read via snmp from slave
  3. master switch is started with no ntp configured
  4. slave sync to master and set it's time, by this system clock on slave is set
     to earlier date
  5. read via snmp from slave will end up in the same results in expert branch of
     the MIB.
Signed-off-by: Adam Wujek's avatarAdam Wujek <adam.wujek@cern.ch>
parents ccdc9a56 035da384
......@@ -217,12 +217,6 @@ interface with gateware is now simpler than it was, but software still
has remnants of old data structure. Also, the multi-threaded approach
is overkill, and the program could benefit from a simplification.
@item Audit all occurrences of the function @i{gettimeofday}. Ofthen it is used
to calculate the time differences. A problem may occur when the switch jump
back in time. Then expected timeout will never expire like in the commit
@t{37bdfd74} @i{userspace/wrsw_hal: bugfix not updating temperatures in
wr_mon/HAL}.
@end itemize
@c ##########################################################################
......
......@@ -8,5 +8,9 @@
void shw_udelay_init(void);
void shw_udelay(uint32_t microseconds);
/* get monotonic number of useconds */
uint64_t get_monotonic_tics(void);
/* get monotonic number of seconds */
time_t get_monotonic_sec(void);
#endif /* __LIBWR_HW_UTIL_H */
......@@ -26,6 +26,7 @@
#include <libwr/shmem.h>
#include <libwr/hal_shmem.h>
#include <libwr/hal_client.h>
#include <libwr/util.h>
#include <net/ethernet.h>
#ifdef NETIF_VERBOSE
......@@ -48,31 +49,22 @@ struct etherpacket {
char data[ETH_DATA_LEN];
};
static uint64_t get_tics(void)
{
struct timezone tz = { 0, 0 };
struct timeval tv;
gettimeofday(&tv, &tz);
return (uint64_t) tv.tv_sec * 1000000ULL + (uint64_t) tv.tv_usec;
}
static inline int tmo_init(struct wr_tmo * tmo, uint32_t milliseconds)
{
tmo->start_tics = get_tics();
tmo->start_tics = get_monotonic_tics();
tmo->timeout = (uint64_t) milliseconds *1000ULL;
return 0;
}
static inline int tmo_restart(struct wr_tmo * tmo)
{
tmo->start_tics = get_tics();
tmo->start_tics = get_monotonic_tics();
return 0;
}
static inline int tmo_expired(struct wr_tmo * tmo)
{
return (get_tics() - tmo->start_tics > tmo->timeout);
return (get_monotonic_tics() - tmo->start_tics > tmo->timeout);
}
// cheks if x is inside range <min, max>
......
......@@ -11,6 +11,7 @@
#include <sys/mman.h>
#include <libwr/shmem.h>
#include <libwr/util.h>
#define SHM_LOCK_TIMEOUT_MS 50 /* in ms */
/* Get wrs shared memory */
/* return NULL and set errno on error */
......@@ -18,7 +19,7 @@ void *wrs_shm_get(enum wrs_shm_name name_id, char *name, unsigned long flags)
{
struct wrs_shm_head *head;
struct stat stbuf;
struct timespec tv1, tv2;
uint64_t tv1, tv2;
void *map;
char fname[64];
int write_access = flags & WRS_SHM_WRITE;
......@@ -54,7 +55,7 @@ void *wrs_shm_get(enum wrs_shm_name name_id, char *name, unsigned long flags)
if (!(flags & WRS_SHM_LOCKED))
return map;
clock_gettime(CLOCK_MONOTONIC, &tv1);
tv1 = get_monotonic_tics();
while (1) {
/* Releasing does not mean initial data is in place! */
/* Read data with wrs_shm_seqbegin and
......@@ -63,10 +64,8 @@ void *wrs_shm_get(enum wrs_shm_name name_id, char *name, unsigned long flags)
return map;
usleep(10 * 1000);
clock_gettime(CLOCK_MONOTONIC, &tv2);
if ((tv2.tv_sec*1000 + tv2.tv_nsec/1000000)
- (tv1.tv_sec*1000 + tv1.tv_nsec/1000000)
< SHM_LOCK_TIMEOUT_MS)
tv2 = get_monotonic_tics();
if (((tv2 - tv1) * 1000) < SHM_LOCK_TIMEOUT_MS)
continue;
errno = ETIMEDOUT;
......@@ -178,12 +177,10 @@ void *wrs_shm_follow(void *headptr, void *ptr)
void wrs_shm_write(void *headptr, int flags)
{
struct wrs_shm_head *head = headptr;
struct timespec tv;
if (flags == WRS_SHM_WRITE_END) {
/* At end-of-writing update the timestamp too */
clock_gettime(CLOCK_MONOTONIC, &tv);
head->stamp = tv.tv_sec;
head->stamp = get_monotonic_sec();
}
head->sequence++;
return;
......@@ -211,10 +208,8 @@ int wrs_shm_seqretry(void *headptr, unsigned start)
int wrs_shm_age(void *headptr)
{
struct wrs_shm_head *head = headptr;
struct timespec tv;
clock_gettime(CLOCK_MONOTONIC, &tv);
return tv.tv_sec - head->stamp;
return get_monotonic_sec() - head->stamp;
}
/* A reader can get the information pointer, for a specific version, or NULL */
......
......@@ -12,14 +12,13 @@ void shw_udelay_init(void)
{
volatile int i;
int j, cur, min = 0;
struct timeval tv1, tv2;
uint64_t tv1, tv2;
for (j = 0; j < 10; j++) {
gettimeofday(&tv1, NULL);
tv1 = get_monotonic_tics();
for (i = 0; i < 100*1000; i++)
;
gettimeofday(&tv2, NULL);
cur = (tv2.tv_sec - tv1.tv_sec) * 1000 * 1000
+ tv2.tv_usec - tv1.tv_usec;
tv2 = get_monotonic_tics();
cur = tv2 - tv1;
/* keep minimum time, assuming we were scheduled-off less */
if (!min || cur < min)
min = cur;
......@@ -52,3 +51,21 @@ void shw_udelay(uint32_t microseconds)
for (i = 0; i < loops_per_msec * microseconds / 1000; i++)
;
}
/* get monotonic number of useconds */
uint64_t get_monotonic_tics(void)
{
struct timespec tv;
clock_gettime(CLOCK_MONOTONIC, &tv);
return (uint64_t) tv.tv_sec * 1000000ULL +
(uint64_t) (tv.tv_nsec / 1000);
}
/* get monotonic number of seconds */
time_t get_monotonic_sec(void)
{
struct timespec tv;
clock_gettime(CLOCK_MONOTONIC, &tv);
return tv.tv_sec;
}
......@@ -29,6 +29,7 @@ SOURCES = \
dot-config.c \
snmp_shmem.c \
snmp_mmap.c \
util.c \
wrsScalar.c \
wrsGeneralStatusGroup.c \
wrsOSStatusGroup.c \
......
../libwr/util.c
\ No newline at end of file
......@@ -518,7 +518,7 @@ time_t wrsBootStatus_data_fill(void)
{
static time_t time_update;
time_t time_cur;
time_cur = time(NULL);
time_cur = get_monotonic_sec();
if (time_update
&& time_cur - time_update < WRSBOOTSTATUS_CACHE_TIMEOUT) {
......
......@@ -17,7 +17,7 @@ time_t wrsCpuLoad_data_fill(void)
struct sysinfo info;
time_cur = time(NULL);
time_cur = get_monotonic_sec();
if (time_update
&& time_cur - time_update < WRSCPULOAD_CACHE_TIMEOUT) {
/* cache not updated, return last update time */
......
......@@ -27,7 +27,7 @@ time_t wrsCurrentTime_data_fill(void)
struct tm tm;
uint64_t wrs_d_current_64;
time_cur = time(NULL);
time_cur = get_monotonic_sec();
if (time_update
&& time_cur - time_update < WRSCURRENTTIME_CACHE_TIMEOUT) {
/* cache not updated, return last update time */
......
......@@ -44,7 +44,7 @@ time_t wrsDiskTable_data_fill(unsigned int *ret_n_rows)
if (ret_n_rows)
*ret_n_rows = n_rows;
time_cur = time(NULL);
time_cur = get_monotonic_sec();
if (time_update
&& time_cur - time_update < WRSDISKTABLE_CACHE_TIMEOUT) {
/* cache not updated, return last update time */
......
......@@ -231,7 +231,7 @@ time_t wrsGeneralStatus_data_fill(void)
WRS_MAIN_SYSTEM_STATUS_BUG;
}
time_update = time(NULL);
time_update = get_monotonic_sec();
/* there was an update, return current time */
return time_update;
......
......@@ -29,7 +29,7 @@ time_t wrsMemory_data_fill(void)
int ret = 0;
char key[41]; /* 1 for null char */
time_cur = time(NULL);
time_cur = get_monotonic_sec();
if (time_update
&& time_cur - time_update < WRSMEMORY_CACHE_TIMEOUT) {
/* cache not updated, return last update time */
......
......@@ -202,7 +202,7 @@ time_t wrsNetworkingStatus_data_fill(void)
/* cache not updated, return last update time */
return time_update;
}
time_update = time(NULL);
time_update = get_monotonic_sec();
if (run_once) {
run_once = 0;
......
......@@ -60,7 +60,7 @@ time_t wrsOSStatus_data_fill(void)
/* cache not updated, return last update time */
return time_update;
}
time_update = time(NULL);
time_update = get_monotonic_sec();
memset(&wrsOSStatus_s, 0, sizeof(wrsOSStatus_s));
/*********************************************************************\
......
......@@ -36,7 +36,7 @@ time_t wrsPortStatusTable_data_fill(unsigned int *n_rows)
if (n_rows)
*n_rows = n_rows_local;
time_cur = time(NULL);
time_cur = get_monotonic_sec();
if (time_update
&& time_cur - time_update < WRSPORTSTATUSTABLE_CACHE_TIMEOUT) {
/* cache not updated, return last update time */
......
......@@ -64,7 +64,7 @@ wrsPstatsTable_data_fill(unsigned int *n_rows)
if (n_rows)
*n_rows = WRS_N_PORTS;
time_cur = time(NULL);
time_cur = get_monotonic_sec();
if (time_update
&& time_cur - time_update < WRSPSTATSTABLE_CACHE_TIMEOUT) {
/* cache not updated, return last update time */
......
......@@ -52,7 +52,7 @@ time_t wrsPtpDataTable_data_fill(unsigned int *n_rows)
if (n_rows)
*n_rows = n_rows_local;
time_cur = time(NULL);
time_cur = get_monotonic_sec();
if (time_update
&& time_cur - time_update < WRSPTPDATATABLE_CACHE_TIMEOUT) {
/* cache not updated, return last update time */
......
......@@ -4,6 +4,7 @@
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include "libwr/util.h"
/* Crap! -- everybody makes them different, and even ppsi::ieee wants them */
#undef FALSE
......
......@@ -27,7 +27,7 @@ time_t wrsSpllStatus_data_fill(void)
static time_t time_update;
time_t time_cur;
time_cur = time(NULL);
time_cur = get_monotonic_sec();
if (time_update
&& time_cur - time_update < WRSSPLLSTATUS_CACHE_TIMEOUT) {
/* cache not updated, return last update time */
......
......@@ -34,7 +34,7 @@ time_t wrsSpllVersion_data_fill(void)
static time_t time_update;
time_t time_cur;
time_cur = time(NULL);
time_cur = get_monotonic_sec();
if (time_update
&& time_cur - time_update < WRSSPLLVERSION_CACHE_TIMEOUT) {
/* cache not updated, return last update time */
......
......@@ -42,7 +42,7 @@ time_t wrsStartCnt_data_fill(void){
time_t time_cur;
time_cur = time(NULL);
time_cur = get_monotonic_sec();
if (time_update
&& time_cur - time_update < WRSSTARTCNT_CACHE_TIMEOUT) {
/* cache not updated, return last update time */
......
......@@ -42,7 +42,7 @@ time_t wrsTemperature_data_fill(void)
time_t time_cur;
static int first_run = 1;
time_cur = time(NULL);
time_cur = get_monotonic_sec();
if (time_update
&& time_cur - time_update < WRSTEMPERATURE_CACHE_TIMEOUT) {
/* cache not updated, return last update time */
......
......@@ -73,7 +73,7 @@ time_t wrsTimingStatus_data_fill(void)
get_wrsPTPFramesFlowing(port_status_nrows);
}
time_update = time(NULL);
time_update = get_monotonic_sec();
/* there was an update, return current time */
return time_update;
}
......
......@@ -82,7 +82,7 @@ time_t wrsVersion_data_fill(void)
static int run_once = 0;
time_t time_cur;
time_cur = time(NULL);
time_cur = get_monotonic_sec();
/* assume that version does not change in runtime */
if (run_once) {
......
......@@ -88,12 +88,12 @@ static int pio_get(int port, int bit)
static void ud(int usecs) /* horrible udelay thing without scheduling */
{
struct timeval tv1, tv2;
gettimeofday(&tv1, NULL);
struct timespec tv1, tv2;
clock_gettime(CLOCK_MONOTONIC, &tv1);
do
gettimeofday(&tv2, NULL);
clock_gettime(CLOCK_MONOTONIC, &tv2);
while ((tv2.tv_sec - tv1.tv_sec) * 1000*1000
+ tv2.tv_usec - tv1.tv_usec < usecs);
+ (tv2.tv_nsec - tv1.tv_nsec) / 1000 < usecs);
}
......
......@@ -17,6 +17,7 @@
#include <libwr/sfp_lib.h>
#include <libwr/config.h>
#include <libwr/hal_shmem.h>
#include <libwr/util.h>
#include "wrsw_hal.h"
#include <rt_ipc.h>
......@@ -214,7 +215,7 @@ static void hal_parse_cmdline(int argc, char *argv[])
int main(int argc, char *argv[])
{
struct timespec t1, t2;
uint64_t t1, t2;
wrs_msg_init(argc, argv);
......@@ -246,15 +247,14 @@ int main(int argc, char *argv[])
* includes some jitter.
*/
clock_gettime(CLOCK_MONOTONIC, &t1);
t1 = get_monotonic_tics();
for (;;) {
int delay_ms;
hal_update_wripc(25 /* max ms delay */);
clock_gettime(CLOCK_MONOTONIC, &t2);
delay_ms = (t2.tv_sec - t1.tv_sec) * 1000;
delay_ms += (t2.tv_nsec - t1.tv_nsec) / 1000 / 1000;
t2 = get_monotonic_tics();
delay_ms = (t2 - t1) * 1000;
if (delay_ms < PORT_FAN_MS_PERIOD)
continue;
......
......@@ -4,6 +4,7 @@
#include <stdio.h>
#include <stdint.h>
#include <sys/time.h>
#include "libwr/util.h"
typedef struct {
int repeat;
......@@ -11,35 +12,26 @@ typedef struct {
uint64_t timeout;
} timeout_t;
static inline uint64_t tm_get_tics(void)
{
struct timezone tz = { 0, 0 };
struct timeval tv;
gettimeofday(&tv, &tz);
return (uint64_t) tv.tv_sec * 1000000ULL + (uint64_t) tv.tv_usec;
}
static inline int tmo_init(timeout_t * tmo, uint32_t milliseconds, int repeat)
{
tmo->repeat = repeat;
tmo->start_tics = tm_get_tics();
tmo->start_tics = get_monotonic_tics();
tmo->timeout = (uint64_t) milliseconds *1000ULL;
return 0;
}
static inline int tmo_restart(timeout_t * tmo)
{
tmo->start_tics = tm_get_tics();
tmo->start_tics = get_monotonic_tics();
return 0;
}
static inline int tmo_expired(timeout_t * tmo)
{
int expired = (tm_get_tics() - tmo->start_tics > tmo->timeout);
int expired = (get_monotonic_tics() - tmo->start_tics > tmo->timeout);
if (tmo->repeat && expired)
tmo->start_tics = tm_get_tics();
tmo->start_tics = get_monotonic_tics();
return expired;
}
......
......@@ -93,14 +93,6 @@ static inline struct rtu_filtering_entry *rtu_fe_clean(
return memset(ent, 0, sizeof(*ent));
}
/**
* \brief Returns number of seconds since the epoch.
*/
static inline unsigned long now(void)
{
return (unsigned long)time(NULL);
}
int rtud_init_exports(void);
void rtud_handle_wripc(void);
......
......@@ -41,6 +41,7 @@
#include <libwr/wrs-msg.h>
#include <libwr/shmem.h>
#include <libwr/rtu_shmem.h>
#include <libwr/util.h>
#include "rtu_fd.h"
#include "rtu_drv.h"
......@@ -298,7 +299,9 @@ int rtu_fd_create_entry(uint8_t mac[ETH_ALEN], uint16_t vid, uint32_t port_mask,
if ((ent->port_mask_dst != mask_dst) || (ent->port_mask_src != mask_src)) { // something new
ent->port_mask_dst = mask_dst;
ent->port_mask_src = mask_src;
ent->last_access_t = now(); //ML: update time always when updating the entry
/* ML: update time always when updating
* the entry */
ent->last_access_t = get_monotonic_sec();
hw_request(HW_WRITE_REQ, ent->addr, ent);
}
/* Case 2: MAC not found */
......@@ -333,7 +336,7 @@ int rtu_fd_create_entry(uint8_t mac[ETH_ALEN], uint16_t vid, uint32_t port_mask,
ent->port_mask_src = 0xFFFFFFFF; //ML: filtering on ingress is optional according to 802.1Q-2012
//by default it should not happen. TODO: add optional config
ent->dynamic = dynamic;
ent->last_access_t = now();
ent->last_access_t = get_monotonic_sec();
mac_copy(ent->mac, mac);
hw_request(HW_WRITE_REQ, eaddr, ent);
}
......@@ -515,7 +518,7 @@ static void rtu_fd_age_update(void)
rtu_read_aging_bitmap(bitmap);
// Update 'last access time' for accessed entries
t = now();
t = get_monotonic_sec();
// HTAB
wrs_shm_write(rtu_port_shmem, WRS_SHM_WRITE_BEGIN);
for (i = 0; i < RTU_ENTRIES / 32; i++)
......@@ -587,7 +590,7 @@ static void rtu_fd_age_out(void)
struct rtu_filtering_entry *ent; /* pointer to scan tables */
unsigned long t; // (secs)
t = now() - aging_time;
t = get_monotonic_sec() - aging_time;
wrs_shm_write(rtu_port_shmem, WRS_SHM_WRITE_BEGIN);
// HTAB
......
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