From 073ce37a3aa257e3a6fcdf6ba6ceb859e2c9816f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 12 Feb 2026 21:49:14 +0100 Subject: [PATCH] common/common.c, include/common.h, drivers/adelsystem_cbi.c, drivers/generic_modbus.c: generalize elapsed_since_timeval() [#1938] Closes: #1938 Co-authored-by: Dimitris Economou Signed-off-by: Jim Klimov --- NEWS.adoc | 2 ++ common/common.c | 25 +++++++++++++++++++++++++ drivers/adelsystem_cbi.c | 33 ++------------------------------- drivers/generic_modbus.c | 34 +++------------------------------- include/common.h | 3 +++ 5 files changed, 35 insertions(+), 62 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index 63622e4fe5..35ee829dbf 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -66,6 +66,8 @@ https://github.com/networkupstools/nut/milestone/12 reality agrees with a status reported by device/protocol (if any). This is also a step in direction of eventually providing a common `runtimecal` style fallback to all drivers. [issue #3146, PR #3156] + * Generalize `elapsed_since_timeval()` code, originally repeated in + several modbus drivers. [issue #1938, PR #3321] * Introduced `NOTIFY_STATE_EXTEND_TIMEOUT` option and relevant variables for `upsnotify()` method, so we can tell systemd to not kill the service unit if its shutdown takes long (see also the `SHUTDOWNEXIT` option in diff --git a/common/common.c b/common/common.c index 8ee5a679ba..aec564876c 100644 --- a/common/common.c +++ b/common/common.c @@ -2734,6 +2734,31 @@ double difftimespec(struct timespec x, struct timespec y) } #endif /* HAVE_CLOCK_GETTIME && HAVE_CLOCK_MONOTONIC */ +/* returns the time elapsed since start in milliseconds */ +long elapsed_since_timeval(struct timeval *start) +{ + long rval; + struct timeval end; + + rval = gettimeofday(&end, NULL); + if (rval < 0) { + upslog_with_errno(LOG_ERR, "elapsed_since_timeval"); + } + if (start->tv_usec < end.tv_usec) { + suseconds_t nsec = (end.tv_usec - start->tv_usec) / 1000000 + 1; + end.tv_usec -= 1000000 * nsec; + end.tv_sec += nsec; + } + if (start->tv_usec - end.tv_usec > 1000000) { + suseconds_t nsec = (start->tv_usec - end.tv_usec) / 1000000; + end.tv_usec += 1000000 * nsec; + end.tv_sec -= nsec; + } + rval = (end.tv_sec - start->tv_sec) * 1000 + (end.tv_usec - start->tv_usec) / 1000; + + return rval; +} + /* Help avoid cryptic "upsnotify: notify about state 4 with libsystemd:" * (with only numeric codes) below */ const char *str_upsnotify_state(upsnotify_state_t state) { diff --git a/drivers/adelsystem_cbi.c b/drivers/adelsystem_cbi.c index 3df478a90a..c1254e5858 100644 --- a/drivers/adelsystem_cbi.c +++ b/drivers/adelsystem_cbi.c @@ -34,7 +34,7 @@ #endif #define DRIVER_NAME "NUT ADELSYSTEM DC-UPS CB/CBI driver (libmodbus link type: " NUT_MODBUS_LINKTYPE_STR ")" -#define DRIVER_VERSION "0.07" +#define DRIVER_VERSION "0.08" /* variables */ static modbus_t *mbctx = NULL; /* modbus memory context */ @@ -83,10 +83,6 @@ int register_write(modbus_t *mb, int addr, regtype_t type, void *data); /* instant command triggered by upsd */ int upscmd(const char *cmdname, const char *extra); -/* count the time elapsed since start */ -long time_elapsed(struct timeval *start); - - /* driver description structure */ upsdrv_info_t upsdrv_info = { DRIVER_NAME, @@ -790,31 +786,6 @@ int register_write(modbus_t *mb, int addr, regtype_t type, void *data) return rval; } -/* returns the time elapsed since start in milliseconds */ -long time_elapsed(struct timeval *start) -{ - long rval; - struct timeval end; - - rval = gettimeofday(&end, NULL); - if (rval < 0) { - upslog_with_errno(LOG_ERR, "time_elapsed"); - } - if (start->tv_usec < end.tv_usec) { - suseconds_t nsec = (end.tv_usec - start->tv_usec) / 1000000 + 1; - end.tv_usec -= 1000000 * nsec; - end.tv_sec += nsec; - } - if (start->tv_usec - end.tv_usec > 1000000) { - suseconds_t nsec = (start->tv_usec - end.tv_usec) / 1000000; - end.tv_usec += 1000000 * nsec; - end.tv_sec -= nsec; - } - rval = (end.tv_sec - start->tv_sec) * 1000 + (end.tv_usec - start->tv_usec) / 1000; - - return rval; -} - /* instant command triggered by upsd */ int upscmd(const char *cmdname, const char *extra) { @@ -861,7 +832,7 @@ int upscmd(const char *cmdname, const char *extra) } /* wait for an increasing time interval before sending shutdown command */ - while ((etime = time_elapsed(&start)) < ( FSD_REPEAT_INTRV / cnt)); + while ((etime = elapsed_since_timeval(&start)) < ( FSD_REPEAT_INTRV / cnt)); upsdebugx(2, "ERROR: load.off failed, wait for %lims, retries left: %d", etime, cnt - 1); cnt--; } diff --git a/drivers/generic_modbus.c b/drivers/generic_modbus.c index 0c7877d39a..de3a791f4a 100644 --- a/drivers/generic_modbus.c +++ b/drivers/generic_modbus.c @@ -31,7 +31,7 @@ #endif #define DRIVER_NAME "NUT Generic Modbus driver (libmodbus link type: " NUT_MODBUS_LINKTYPE_STR ")" -#define DRIVER_VERSION "0.09" +#define DRIVER_VERSION "0.10" /* variables */ static modbus_t *mbctx = NULL; /* modbus memory context */ @@ -69,9 +69,6 @@ int upscmd(const char *cmd, const char *arg); /* read signal status */ int get_signal_state(devstate_t state); -/* count the time elapsed since start */ -long time_elapsed(struct timeval *start); - int register_write(modbus_t *mb, int addr, regtype_t type, void *data); /* driver description structure */ @@ -543,31 +540,6 @@ int register_write(modbus_t *mb, int addr, regtype_t type, void *data) return rval; } -/* returns the time elapsed since start in milliseconds */ -long time_elapsed(struct timeval *start) -{ - long rval; - struct timeval end; - - rval = gettimeofday(&end, NULL); - if (rval < 0) { - upslog_with_errno(LOG_ERR, "time_elapsed"); - } - if (start->tv_usec < end.tv_usec) { - suseconds_t nsec = (end.tv_usec - start->tv_usec) / 1000000 + 1; - end.tv_usec -= 1000000 * nsec; - end.tv_sec += nsec; - } - if (start->tv_usec - end.tv_usec > 1000000) { - suseconds_t nsec = (start->tv_usec - end.tv_usec) / 1000000; - end.tv_usec += 1000000 * nsec; - end.tv_sec -= nsec; - } - rval = (end.tv_sec - start->tv_sec) * 1000 + (end.tv_usec - start->tv_usec) / 1000; - - return rval; -} - /* instant command triggered by upsd */ int upscmd(const char *cmd, const char *arg) { @@ -611,7 +583,7 @@ int upscmd(const char *cmd, const char *arg) } /* wait for FSD_pulse_duration ms */ - while ((etime = time_elapsed(&start)) < FSD_pulse_duration); + while ((etime = elapsed_since_timeval(&start)) < FSD_pulse_duration); data = 0 ^ sigar[FSD_T].noro; rval = register_write(mbctx, sigar[FSD_T].addr, sigar[FSD_T].type, &data); @@ -654,7 +626,7 @@ int upscmd(const char *cmd, const char *arg) } /* wait for an increasing time interval before sending shutdown command */ - while ((etime = time_elapsed(&start)) < ( FSD_REPEAT_INTRV / cnt)); + while ((etime = elapsed_since_timeval(&start)) < ( FSD_REPEAT_INTRV / cnt)); upsdebugx(2,"ERROR: load.off failed, wait for %lims, retries left: %d\n", etime, cnt - 1); cnt--; } diff --git a/include/common.h b/include/common.h index 85bb4e8291..a83001b7e9 100644 --- a/include/common.h +++ b/include/common.h @@ -817,6 +817,9 @@ double difftimeval(struct timeval x, struct timeval y); double difftimespec(struct timespec x, struct timespec y); #endif +/* count the time elapsed since start in milliseconds */ +long elapsed_since_timeval(struct timeval *start); + #ifndef HAVE_USLEEP /* int __cdecl usleep(unsigned int useconds); */ /* Note: if we'd need to define an useconds_t for obscure systems,