session UPDATE use monotonic clock if possible
Even for cond vars using the clock pthread wait
func variants.
Refs cesnet/netopeer2#1338
diff --git a/CMakeModules/UseCompat.cmake b/CMakeModules/UseCompat.cmake
index 7d7a338..3d8ad7a 100644
--- a/CMakeModules/UseCompat.cmake
+++ b/CMakeModules/UseCompat.cmake
@@ -6,7 +6,7 @@
# Additionally, "compat.h" include directory is added and can be included.
#
# Author Michal Vasko <mvasko@cesnet.cz>
-# Copyright (c) 2021 CESNET, z.s.p.o.
+# Copyright (c) 2021 - 2023 CESNET, z.s.p.o.
#
# This source code is licensed under BSD 3-Clause License (the "License").
# You may not use this file except in compliance with the License.
@@ -15,7 +15,6 @@
# https://opensource.org/licenses/BSD-3-Clause
#
include(CheckSymbolExists)
-include(CheckFunctionExists)
include(CheckIncludeFile)
include(TestBigEndian)
if(POLICY CMP0075)
@@ -29,6 +28,26 @@
list(APPEND CMAKE_REQUIRED_DEFINITIONS -D__BSD_VISIBLE=1)
set(CMAKE_REQUIRED_LIBRARIES pthread)
+ check_symbol_exists(_POSIX_TIMERS "unistd.h" HAVE_CLOCK)
+ if(NOT HAVE_CLOCK)
+ message(FATAL_ERROR "Missing support for clock_gettime() and similar functions!")
+ endif()
+
+ check_symbol_exists(pthread_mutex_timedlock "pthread.h" HAVE_PTHREAD_MUTEX_TIMEDLOCK)
+ check_symbol_exists(pthread_mutex_clocklock "pthread.h" HAVE_PTHREAD_MUTEX_CLOCKLOCK)
+ check_symbol_exists(pthread_rwlock_clockrdlock "pthread.h" HAVE_PTHREAD_RWLOCK_CLOCKRDLOCK)
+ check_symbol_exists(pthread_rwlock_clockwrlock "pthread.h" HAVE_PTHREAD_RWLOCK_CLOCKWRLOCK)
+ check_symbol_exists(pthread_cond_clockwait "pthread.h" HAVE_PTHREAD_COND_CLOCKWAIT)
+ if(HAVE_PTHREAD_MUTEX_CLOCKLOCK)
+ # can use CLOCK_MONOTONIC only if we have pthread_mutex_clocklock()
+ check_symbol_exists(_POSIX_MONOTONIC_CLOCK "unistd.h" HAVE_CLOCK_MONOTONIC)
+ endif()
+ if(HAVE_CLOCK_MONOTONIC)
+ set(COMPAT_CLOCK_ID "CLOCK_MONOTONIC")
+ else()
+ set(COMPAT_CLOCK_ID "CLOCK_REALTIME")
+ endif()
+
check_symbol_exists(vdprintf "stdio.h;stdarg.h" HAVE_VDPRINTF)
check_symbol_exists(asprintf "stdio.h" HAVE_ASPRINTF)
check_symbol_exists(vasprintf "stdio.h" HAVE_VASPRINTF)
@@ -41,8 +60,6 @@
check_symbol_exists(get_current_dir_name "unistd.h" HAVE_GET_CURRENT_DIR_NAME)
- check_function_exists(pthread_mutex_timedlock HAVE_PTHREAD_MUTEX_TIMEDLOCK)
-
TEST_BIG_ENDIAN(IS_BIG_ENDIAN)
check_include_file("stdatomic.h" HAVE_STDATOMIC)
diff --git a/compat/compat.c b/compat/compat.c
index bf75c74..4491680 100644
--- a/compat/compat.c
+++ b/compat/compat.c
@@ -3,7 +3,7 @@
* @author Michal Vasko <mvasko@cesnet.cz>
* @brief compatibility functions
*
- * Copyright (c) 2021 CESNET, z.s.p.o.
+ * Copyright (c) 2021 - 2023 CESNET, z.s.p.o.
*
* This source code is licensed under BSD 3-Clause License (the "License").
* You may not use this file except in compliance with the License.
@@ -28,6 +28,100 @@
#include <time.h>
#include <unistd.h>
+#ifndef HAVE_PTHREAD_MUTEX_TIMEDLOCK
+int
+pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *abstime)
+{
+ int64_t nsec_diff;
+ int32_t diff;
+ struct timespec cur, dur;
+ int rc;
+
+ /* try to acquire the lock and, if we fail, sleep for 5ms. */
+ while ((rc = pthread_mutex_trylock(mutex)) == EBUSY) {
+ /* get time */
+ clock_gettime(COMPAT_CLOCK_ID, &cur);
+
+ /* get time diff */
+ nsec_diff = 0;
+ nsec_diff += (((int64_t)abstime->tv_sec) - ((int64_t)cur.tv_sec)) * 1000000000L;
+ nsec_diff += ((int64_t)abstime->tv_nsec) - ((int64_t)cur.tv_nsec);
+ diff = (nsec_diff ? nsec_diff / 1000000L : 0);
+
+ if (diff < 1) {
+ /* timeout */
+ break;
+ } else if (diff < 5) {
+ /* sleep until timeout */
+ dur.tv_sec = 0;
+ dur.tv_nsec = (long)diff * 1000000;
+ } else {
+ /* sleep 5 ms */
+ dur.tv_sec = 0;
+ dur.tv_nsec = 5000000;
+ }
+
+ nanosleep(&dur, NULL);
+ }
+
+ return rc;
+}
+
+#endif
+
+#ifndef HAVE_PTHREAD_MUTEX_CLOCKLOCK
+int
+pthread_mutex_clocklock(pthread_mutex_t *mutex, clockid_t clockid, const struct timespec *abstime)
+{
+ /* only real time supported without this function */
+ if (clockid != CLOCK_REALTIME) {
+ return EINVAL;
+ }
+
+ return pthread_mutex_timedlock(mutex, abstime);
+}
+
+#endif
+
+#ifndef HAVE_PTHREAD_RWLOCK_CLOCKRDLOCK
+int
+pthread_rwlock_clockrdlock(pthread_rwlock_t *rwlock, clockid_t clockid, const struct timespec *abstime)
+{
+ /* only real time supported without this function */
+ if (clockid != CLOCK_REALTIME) {
+ return EINVAL;
+ }
+
+ return pthread_rwlock_timedrdlock(rwlock, abstime);
+}
+
+#endif
+
+#ifndef HAVE_PTHREAD_RWLOCK_CLOCKWRLOCK
+int
+pthread_rwlock_clockwrlock(pthread_rwlock_t *rwlock, clockid_t clockid, const struct timespec *abstime)
+{
+ /* only real time supported without this function */
+ if (clockid != CLOCK_REALTIME) {
+ return EINVAL;
+ }
+
+ return pthread_rwlock_timedwrlock(rwlock, abstime);
+}
+
+#endif
+
+#ifndef HAVE_PTHREAD_COND_CLOCKWAIT
+int
+pthread_cond_clockwait(pthread_cond_t *cond, pthread_mutex_t *mutex, clockid_t UNUSED(clockid),
+ const struct timespec *abstime)
+{
+ /* assume the correct clock is set during cond init */
+ return pthread_cond_timedwait(cond, mutex, abstime);
+}
+
+#endif
+
#ifndef HAVE_VDPRINTF
int
vdprintf(int fd, const char *format, va_list ap)
@@ -199,52 +293,3 @@
}
#endif
-
-#ifndef HAVE_PTHREAD_MUTEX_TIMEDLOCK
-int
-pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *abstime)
-{
- int64_t nsec_diff;
- int32_t diff;
- struct timespec cur, dur;
- int rc;
-
- /* try to acquire the lock and, if we fail, sleep for 5ms. */
- while ((rc = pthread_mutex_trylock(mutex)) == EBUSY) {
- /* get real time */
-#ifdef CLOCK_REALTIME
- clock_gettime(CLOCK_REALTIME, &cur);
-#else
- struct timeval tv;
-
- gettimeofday(&tv, NULL);
- cur.tv_sec = (time_t)tv.tv_sec;
- cur.tv_nsec = 1000L * (long)tv.tv_usec;
-#endif
-
- /* get time diff */
- nsec_diff = 0;
- nsec_diff += (((int64_t)abstime->tv_sec) - ((int64_t)cur.tv_sec)) * 1000000000L;
- nsec_diff += ((int64_t)abstime->tv_nsec) - ((int64_t)cur.tv_nsec);
- diff = (nsec_diff ? nsec_diff / 1000000L : 0);
-
- if (diff < 1) {
- /* timeout */
- break;
- } else if (diff < 5) {
- /* sleep until timeout */
- dur.tv_sec = 0;
- dur.tv_nsec = (long)diff * 1000000;
- } else {
- /* sleep 5 ms */
- dur.tv_sec = 0;
- dur.tv_nsec = 5000000;
- }
-
- nanosleep(&dur, NULL);
- }
-
- return rc;
-}
-
-#endif
diff --git a/compat/compat.h.in b/compat/compat.h.in
index acc5fc7..61a2a23 100644
--- a/compat/compat.h.in
+++ b/compat/compat.h.in
@@ -3,7 +3,7 @@
* @author Michal Vasko <mvasko@cesnet.cz>
* @brief compatibility functions header
*
- * Copyright (c) 2021 CESNET, z.s.p.o.
+ * Copyright (c) 2021 - 2023 CESNET, z.s.p.o.
*
* This source code is licensed under BSD 3-Clause License (the "License").
* You may not use this file except in compliance with the License.
@@ -15,6 +15,7 @@
#ifndef _COMPAT_H_
#define _COMPAT_H_
+#include <alloca.h>
#include <limits.h>
#include <pthread.h>
#include <stdarg.h>
@@ -48,6 +49,13 @@
# define _PACKED
#endif
+#define COMPAT_CLOCK_ID @COMPAT_CLOCK_ID@
+#cmakedefine HAVE_PTHREAD_MUTEX_TIMEDLOCK
+#cmakedefine HAVE_PTHREAD_MUTEX_CLOCKLOCK
+#cmakedefine HAVE_PTHREAD_RWLOCK_CLOCKRDLOCK
+#cmakedefine HAVE_PTHREAD_RWLOCK_CLOCKWRLOCK
+#cmakedefine HAVE_PTHREAD_COND_CLOCKWAIT
+
#cmakedefine HAVE_VDPRINTF
#cmakedefine HAVE_ASPRINTF
#cmakedefine HAVE_VASPRINTF
@@ -57,7 +65,6 @@
#cmakedefine HAVE_STRDUPA
#cmakedefine HAVE_STRCHRNUL
#cmakedefine HAVE_GET_CURRENT_DIR_NAME
-#cmakedefine HAVE_PTHREAD_MUTEX_TIMEDLOCK
#ifndef bswap64
#define bswap64(val) \
@@ -87,6 +94,10 @@
# define ATOMIC_T atomic_uint_fast32_t
# define ATOMIC_T_MAX UINT_FAST32_MAX
+# define ATOMIC64_T atomic_uint_fast64_t
+# define ATOMIC64_T_MAX UINT_FAST64_MAX
+
+# define ATOMIC_PTR_T atomic_uintptr_t
# define ATOMIC_STORE_RELAXED(var, x) atomic_store_explicit(&(var), x, memory_order_relaxed)
# define ATOMIC_LOAD_RELAXED(var) atomic_load_explicit(&(var), memory_order_relaxed)
@@ -94,11 +105,20 @@
# define ATOMIC_ADD_RELAXED(var, x) atomic_fetch_add_explicit(&(var), x, memory_order_relaxed)
# define ATOMIC_DEC_RELAXED(var) atomic_fetch_sub_explicit(&(var), 1, memory_order_relaxed)
# define ATOMIC_SUB_RELAXED(var, x) atomic_fetch_sub_explicit(&(var), x, memory_order_relaxed)
+# define ATOMIC_COMPARE_EXCHANGE_RELAXED(var, exp, des, result) \
+ result = atomic_compare_exchange_strong_explicit(&(var), &(exp), des, memory_order_relaxed, memory_order_relaxed)
+
+# define ATOMIC_PTR_STORE_RELAXED(var, x) atomic_store_explicit(&(var), (uintptr_t)(x), memory_order_relaxed)
+# define ATOMIC_PTR_LOAD_RELAXED(var) ((void *)atomic_load_explicit(&(var), memory_order_relaxed))
#else
# include <stdint.h>
# define ATOMIC_T uint32_t
# define ATOMIC_T_MAX UINT32_MAX
+# define ATOMIC64_T uint64_t
+# define ATOMIC64_T_MAX UINT64_MAX
+
+# define ATOMIC_PTR_T void *
# define ATOMIC_STORE_RELAXED(var, x) ((var) = (x))
# define ATOMIC_LOAD_RELAXED(var) (var)
@@ -106,6 +126,35 @@
# define ATOMIC_ADD_RELAXED(var, x) __sync_fetch_and_add(&(var), x)
# define ATOMIC_DEC_RELAXED(var) __sync_fetch_and_sub(&(var), 1)
# define ATOMIC_SUB_RELAXED(var, x) __sync_fetch_and_sub(&(var), x)
+# define ATOMIC_COMPARE_EXCHANGE_RELAXED(var, exp, des, result) \
+ { \
+ ATOMIC_T __old = __sync_val_compare_and_swap(&(var), exp, des); \
+ result = ATOMIC_LOAD_RELAXED(__old) == ATOMIC_LOAD_RELAXED(exp) ? 1 : 0; \
+ ATOMIC_STORE_RELAXED(exp, ATOMIC_LOAD_RELAXED(__old)); \
+ }
+
+# define ATOMIC_PTR_STORE_RELAXED(var, x) ((var) = (x))
+# define ATOMIC_PTR_LOAD_RELAXED(var) (var)
+#endif
+
+#ifndef HAVE_PTHREAD_MUTEX_TIMEDLOCK
+int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *abstime);
+#endif
+
+#ifndef HAVE_PTHREAD_MUTEX_CLOCKLOCK
+int pthread_mutex_clocklock(pthread_mutex_t *mutex, clockid_t clockid, const struct timespec *abstime);
+#endif
+
+#ifndef HAVE_PTHREAD_RWLOCK_CLOCKRDLOCK
+int pthread_rwlock_clockrdlock(pthread_rwlock_t *rwlock, clockid_t clockid, const struct timespec *abstime);
+#endif
+
+#ifndef HAVE_PTHREAD_RWLOCK_CLOCKWRLOCK
+int pthread_rwlock_clockwrlock(pthread_rwlock_t *rwlock, clockid_t clockid, const struct timespec *abstime);
+#endif
+
+#ifndef HAVE_PTHREAD_COND_CLOCKWAIT
+int pthread_cond_clockwait(pthread_cond_t *cond, pthread_mutex_t *mutex, clockid_t clockid, const struct timespec *abstime);
#endif
#ifndef HAVE_VDPRINTF
@@ -151,8 +200,4 @@
char *get_current_dir_name(void);
#endif
-#ifndef HAVE_PTHREAD_MUTEX_TIMEDLOCK
-int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *abstime);
-#endif
-
#endif /* _COMPAT_H_ */
diff --git a/src/io.c b/src/io.c
index 5b2ed8b..d0c4c5c 100644
--- a/src/io.c
+++ b/src/io.c
@@ -105,7 +105,7 @@
return 0;
}
- nc_gettimespec_mono_add(&ts_inact_timeout, inact_timeout);
+ nc_timeouttime_get(&ts_inact_timeout, inact_timeout);
do {
interrupted = 0;
switch (session->ti_type) {
@@ -210,8 +210,8 @@
if (!interrupted) {
usleep(NC_TIMEOUT_STEP);
}
- if ((nc_difftimespec_mono_cur(&ts_inact_timeout) < 1) || (nc_difftimespec_mono_cur(ts_act_timeout) < 1)) {
- if (nc_difftimespec_mono_cur(&ts_inact_timeout) < 1) {
+ if ((nc_timeouttime_cur_diff(&ts_inact_timeout) < 1) || (nc_timeouttime_cur_diff(ts_act_timeout) < 1)) {
+ if (nc_timeouttime_cur_diff(&ts_inact_timeout) < 1) {
ERR(session, "Inactive read timeout elapsed.");
} else {
ERR(session, "Active read timeout elapsed.");
@@ -225,7 +225,7 @@
readd += r;
/* reset inactive timeout */
- nc_gettimespec_mono_add(&ts_inact_timeout, inact_timeout);
+ nc_timeouttime_get(&ts_inact_timeout, inact_timeout);
}
} while (readd < count);
@@ -360,7 +360,7 @@
goto cleanup;
}
- nc_gettimespec_mono_add(&ts_act_timeout, NC_READ_ACT_TIMEOUT * 1000);
+ nc_timeouttime_get(&ts_act_timeout, NC_READ_ACT_TIMEOUT * 1000);
if (!io_locked) {
/* SESSION IO LOCK */
diff --git a/src/session.c b/src/session.c
index 274c40d..8ebb83a 100644
--- a/src/session.c
+++ b/src/session.c
@@ -4,7 +4,7 @@
* @brief libnetconf2 - general session functions
*
* @copyright
- * Copyright (c) 2015 - 2021 CESNET, z.s.p.o.
+ * Copyright (c) 2015 - 2023 CESNET, z.s.p.o.
*
* This source code is licensed under BSD 3-Clause License (the "License").
* You may not use this file except in compliance with the License.
@@ -56,112 +56,55 @@
extern struct nc_server_opts server_opts;
-int
-nc_gettimespec_real_add(struct timespec *ts, uint32_t msec)
+void
+nc_timeouttime_get(struct timespec *ts, uint32_t add_ms)
{
-#ifdef CLOCK_REALTIME
+ if (clock_gettime(COMPAT_CLOCK_ID, ts) == -1) {
+ ERR(NULL, "clock_gettime() failed (%s).", strerror(errno));
+ return;
+ }
+
+ if (!add_ms) {
+ return;
+ }
+
+ assert((ts->tv_nsec >= 0) && (ts->tv_nsec < 1000000000L));
+
+ ts->tv_sec += add_ms / 1000;
+ ts->tv_nsec += (add_ms % 1000) * 1000000L;
+
+ if (ts->tv_nsec >= 1000000000L) {
+ ++ts->tv_sec;
+ ts->tv_nsec -= 1000000000L;
+ } else if (ts->tv_nsec < 0) {
+ --ts->tv_sec;
+ ts->tv_nsec += 1000000000L;
+ }
+
+ assert((ts->tv_nsec >= 0) && (ts->tv_nsec < 1000000000L));
+}
+
+int32_t
+nc_timeouttime_cur_diff(const struct timespec *ts)
+{
+ struct timespec cur;
+ int64_t nsec_diff = 0;
+
+ nc_timeouttime_get(&cur, 0);
+
+ nsec_diff += (((int64_t)ts->tv_sec) - ((int64_t)cur.tv_sec)) * 1000000000L;
+ nsec_diff += ((int64_t)ts->tv_nsec) - ((int64_t)cur.tv_nsec);
+
+ return nsec_diff / 1000000L;
+}
+
+void
+nc_realtime_get(struct timespec *ts)
+{
if (clock_gettime(CLOCK_REALTIME, ts)) {
- return -1;
+ ERR(NULL, "clock_gettime() failed (%s).", strerror(errno));
+ return;
}
-#else
- int rc;
- struct timeval tv;
-
- rc = gettimeofday(&tv, NULL);
- if (rc) {
- return -1;
- } else {
- ts->tv_sec = (time_t)tv.tv_sec;
- ts->tv_nsec = 1000L * (long)tv.tv_usec;
- }
-#endif
-
- if (!msec) {
- return 0;
- }
-
- assert((ts->tv_nsec >= 0) && (ts->tv_nsec < 1000000000L));
-
- ts->tv_sec += msec / 1000;
- ts->tv_nsec += (msec % 1000) * 1000000L;
-
- if (ts->tv_nsec >= 1000000000L) {
- ++ts->tv_sec;
- ts->tv_nsec -= 1000000000L;
- } else if (ts->tv_nsec < 0) {
- --ts->tv_sec;
- ts->tv_nsec += 1000000000L;
- }
-
- assert((ts->tv_nsec >= 0) && (ts->tv_nsec < 1000000000L));
- return 0;
-}
-
-int
-nc_gettimespec_mono_add(struct timespec *ts, uint32_t msec)
-{
-#ifdef CLOCK_MONOTONIC_RAW
- if (clock_gettime(CLOCK_MONOTONIC_RAW, ts)) {
- return -1;
- }
-#elif defined (CLOCK_MONOTONIC)
- if (clock_gettime(CLOCK_MONOTONIC, ts)) {
- return -1;
- }
-#else
- /* no monotonic clock available, return real time */
- if (nc_gettimespec_real_add(ts, 0)) {
- return -1;
- }
-#endif
-
- if (!msec) {
- return 0;
- }
-
- assert((ts->tv_nsec >= 0) && (ts->tv_nsec < 1000000000L));
-
- ts->tv_sec += msec / 1000;
- ts->tv_nsec += (msec % 1000) * 1000000L;
-
- if (ts->tv_nsec >= 1000000000L) {
- ++ts->tv_sec;
- ts->tv_nsec -= 1000000000L;
- } else if (ts->tv_nsec < 0) {
- --ts->tv_sec;
- ts->tv_nsec += 1000000000L;
- }
-
- assert((ts->tv_nsec >= 0) && (ts->tv_nsec < 1000000000L));
- return 0;
-}
-
-int32_t
-nc_difftimespec_real_cur(const struct timespec *ts)
-{
- struct timespec cur;
- int64_t nsec_diff = 0;
-
- nc_gettimespec_real_add(&cur, 0);
-
- nsec_diff += (((int64_t)ts->tv_sec) - ((int64_t)cur.tv_sec)) * 1000000000L;
- nsec_diff += ((int64_t)ts->tv_nsec) - ((int64_t)cur.tv_nsec);
-
- return nsec_diff / 1000000L;
-}
-
-int32_t
-nc_difftimespec_mono_cur(const struct timespec *ts)
-{
- struct timespec cur;
- int64_t nsec_diff = 0;
-
- nc_gettimespec_mono_add(&cur, 0);
-
- nsec_diff += (((int64_t)ts->tv_sec) - ((int64_t)cur.tv_sec)) * 1000000000L;
- nsec_diff += ((int64_t)ts->tv_nsec) - ((int64_t)cur.tv_nsec);
-
- return nsec_diff / 1000000L;
}
const char *
@@ -277,13 +220,14 @@
}
if (timeout > 0) {
- nc_gettimespec_real_add(&ts_timeout, timeout);
+ nc_timeouttime_get(&ts_timeout, timeout);
/* LOCK */
- ret = pthread_mutex_timedlock(&session->opts.server.rpc_lock, &ts_timeout);
+ ret = pthread_mutex_clocklock(&session->opts.server.rpc_lock, COMPAT_CLOCK_ID, &ts_timeout);
if (!ret) {
while (session->opts.server.rpc_inuse) {
- ret = pthread_cond_timedwait(&session->opts.server.rpc_cond, &session->opts.server.rpc_lock, &ts_timeout);
+ ret = pthread_cond_clockwait(&session->opts.server.rpc_cond, &session->opts.server.rpc_lock,
+ COMPAT_CLOCK_ID, &ts_timeout);
if (ret) {
pthread_mutex_unlock(&session->opts.server.rpc_lock);
break;
@@ -353,10 +297,10 @@
assert(session->opts.server.rpc_inuse);
if (timeout > 0) {
- nc_gettimespec_real_add(&ts_timeout, timeout);
+ nc_timeouttime_get(&ts_timeout, timeout);
/* LOCK */
- ret = pthread_mutex_timedlock(&session->opts.server.rpc_lock, &ts_timeout);
+ ret = pthread_mutex_clocklock(&session->opts.server.rpc_lock, COMPAT_CLOCK_ID, &ts_timeout);
} else if (!timeout) {
/* LOCK */
ret = pthread_mutex_trylock(&session->opts.server.rpc_lock);
@@ -396,9 +340,9 @@
struct timespec ts_timeout;
if (timeout > 0) {
- nc_gettimespec_real_add(&ts_timeout, timeout);
+ nc_timeouttime_get(&ts_timeout, timeout);
- ret = pthread_mutex_timedlock(session->io_lock, &ts_timeout);
+ ret = pthread_mutex_clocklock(session->io_lock, COMPAT_CLOCK_ID, &ts_timeout);
} else if (!timeout) {
ret = pthread_mutex_trylock(session->io_lock);
} else { /* timeout == -1 */
@@ -445,14 +389,14 @@
if (*timeout > 0) {
/* get current time */
- nc_gettimespec_real_add(&ts_start, 0);
+ nc_timeouttime_get(&ts_start, 0);
- nc_gettimespec_real_add(&ts_timeout, *timeout);
+ nc_timeouttime_get(&ts_timeout, *timeout);
- ret = pthread_mutex_timedlock(&session->opts.client.msgs_lock, &ts_timeout);
+ ret = pthread_mutex_clocklock(&session->opts.client.msgs_lock, COMPAT_CLOCK_ID, &ts_timeout);
if (!ret) {
/* update timeout based on what was elapsed */
- diff_msec = nc_difftimespec_real_cur(&ts_start);
+ diff_msec = nc_timeouttime_cur_diff(&ts_start);
*timeout -= diff_msec;
}
} else if (!*timeout) {
@@ -868,10 +812,10 @@
ATOMIC_STORE_RELAXED(session->opts.client.ntf_thread_running, 0);
/* wait for them */
- nc_gettimespec_mono_add(&ts, NC_SESSION_FREE_LOCK_TIMEOUT);
+ nc_timeouttime_get(&ts, NC_SESSION_FREE_LOCK_TIMEOUT);
while (ATOMIC_LOAD_RELAXED(session->opts.client.ntf_thread_count)) {
usleep(NC_TIMEOUT_STEP);
- if (nc_difftimespec_mono_cur(&ts) < 1) {
+ if (nc_timeouttime_cur_diff(&ts) < 1) {
ERR(session, "Waiting for notification thread exit failed (timed out).");
break;
}
@@ -972,12 +916,12 @@
if ((session->side == NC_SERVER) && (session->flags & NC_SESSION_CH_THREAD)) {
pthread_cond_signal(&session->opts.server.ch_cond);
- nc_gettimespec_real_add(&ts, NC_SESSION_FREE_LOCK_TIMEOUT);
+ nc_timeouttime_get(&ts, NC_SESSION_FREE_LOCK_TIMEOUT);
/* wait for CH thread to actually wake up and terminate */
r = 0;
while (!r && (session->flags & NC_SESSION_CH_THREAD)) {
- r = pthread_cond_timedwait(&session->opts.server.ch_cond, &session->opts.server.ch_lock, &ts);
+ r = pthread_cond_clockwait(&session->opts.server.ch_cond, &session->opts.server.ch_lock, COMPAT_CLOCK_ID, &ts);
}
if (r) {
ERR(session, "Waiting for Call Home thread failed (%s).", strerror(r));
diff --git a/src/session_client_ssh.c b/src/session_client_ssh.c
index bd172e8..647a526 100644
--- a/src/session_client_ssh.c
+++ b/src/session_client_ssh.c
@@ -1176,10 +1176,10 @@
ssh_sess = session->ti.libssh.session;
- nc_gettimespec_mono_add(&ts_timeout, NC_TRANSPORT_TIMEOUT);
+ nc_timeouttime_get(&ts_timeout, NC_TRANSPORT_TIMEOUT);
while ((ret = ssh_connect(ssh_sess)) == SSH_AGAIN) {
usleep(NC_TIMEOUT_STEP);
- if (nc_difftimespec_mono_cur(&ts_timeout) < 1) {
+ if (nc_timeouttime_cur_diff(&ts_timeout) < 1) {
break;
}
}
@@ -1198,11 +1198,11 @@
}
if (timeout > -1) {
- nc_gettimespec_mono_add(&ts_timeout, timeout);
+ nc_timeouttime_get(&ts_timeout, timeout);
}
while ((ret_auth = ssh_userauth_none(ssh_sess, NULL)) == SSH_AUTH_AGAIN) {
usleep(NC_TIMEOUT_STEP);
- if ((timeout > -1) && (nc_difftimespec_mono_cur(&ts_timeout) < 1)) {
+ if ((timeout > -1) && (nc_timeouttime_cur_diff(&ts_timeout) < 1)) {
break;
}
}
@@ -1272,11 +1272,11 @@
}
if (timeout > -1) {
- nc_gettimespec_mono_add(&ts_timeout, timeout);
+ nc_timeouttime_get(&ts_timeout, timeout);
}
while ((ret_auth = ssh_userauth_password(ssh_sess, session->username, s)) == SSH_AUTH_AGAIN) {
usleep(NC_TIMEOUT_STEP);
- if ((timeout > -1) && (nc_difftimespec_mono_cur(&ts_timeout) < 1)) {
+ if ((timeout > -1) && (nc_timeouttime_cur_diff(&ts_timeout) < 1)) {
break;
}
}
@@ -1290,13 +1290,13 @@
VRB(session, "Keyboard-interactive authentication.");
if (timeout > -1) {
- nc_gettimespec_mono_add(&ts_timeout, timeout);
+ nc_timeouttime_get(&ts_timeout, timeout);
}
while (((ret_auth = ssh_userauth_kbdint(ssh_sess, NULL, NULL)) == SSH_AUTH_INFO) ||
(ret_auth == SSH_AUTH_AGAIN)) {
if (ret_auth == SSH_AUTH_AGAIN) {
usleep(NC_TIMEOUT_STEP);
- if ((timeout > -1) && (nc_difftimespec_mono_cur(&ts_timeout) < 1)) {
+ if ((timeout > -1) && (nc_timeouttime_cur_diff(&ts_timeout) < 1)) {
break;
}
continue;
@@ -1323,7 +1323,7 @@
break;
}
if (timeout > -1) {
- nc_gettimespec_mono_add(&ts_timeout, timeout);
+ nc_timeouttime_get(&ts_timeout, timeout);
}
}
break;
@@ -1354,11 +1354,11 @@
}
if (timeout > -1) {
- nc_gettimespec_mono_add(&ts_timeout, timeout);
+ nc_timeouttime_get(&ts_timeout, timeout);
}
while ((ret_auth = ssh_userauth_try_publickey(ssh_sess, NULL, pubkey)) == SSH_AUTH_AGAIN) {
usleep(NC_TIMEOUT_STEP);
- if ((timeout > -1) && (nc_difftimespec_mono_cur(&ts_timeout) < 1)) {
+ if ((timeout > -1) && (nc_timeouttime_cur_diff(&ts_timeout) < 1)) {
break;
}
}
@@ -1390,11 +1390,11 @@
}
if (timeout > -1) {
- nc_gettimespec_mono_add(&ts_timeout, timeout);
+ nc_timeouttime_get(&ts_timeout, timeout);
}
while ((ret_auth = ssh_userauth_publickey(ssh_sess, NULL, privkey)) == SSH_AUTH_AGAIN) {
usleep(NC_TIMEOUT_STEP);
- if ((timeout > -1) && (nc_difftimespec_mono_cur(&ts_timeout) < 1)) {
+ if ((timeout > -1) && (nc_timeouttime_cur_diff(&ts_timeout) < 1)) {
break;
}
}
@@ -1458,12 +1458,12 @@
/* open a channel */
if (timeout > -1) {
- nc_gettimespec_mono_add(&ts_timeout, timeout);
+ nc_timeouttime_get(&ts_timeout, timeout);
}
session->ti.libssh.channel = ssh_channel_new(ssh_sess);
while ((ret = ssh_channel_open_session(session->ti.libssh.channel)) == SSH_AGAIN) {
usleep(NC_TIMEOUT_STEP);
- if ((timeout > -1) && (nc_difftimespec_mono_cur(&ts_timeout) < 1)) {
+ if ((timeout > -1) && (nc_timeouttime_cur_diff(&ts_timeout) < 1)) {
break;
}
}
@@ -1481,11 +1481,11 @@
/* execute the NETCONF subsystem on the channel */
if (timeout > -1) {
- nc_gettimespec_mono_add(&ts_timeout, timeout);
+ nc_timeouttime_get(&ts_timeout, timeout);
}
while ((ret = ssh_channel_request_subsystem(session->ti.libssh.channel, "netconf")) == SSH_AGAIN) {
usleep(NC_TIMEOUT_STEP);
- if ((timeout > -1) && (nc_difftimespec_mono_cur(&ts_timeout) < 1)) {
+ if ((timeout > -1) && (nc_timeouttime_cur_diff(&ts_timeout) < 1)) {
break;
}
}
diff --git a/src/session_client_tls.c b/src/session_client_tls.c
index add5871..73f8cee 100644
--- a/src/session_client_tls.c
+++ b/src/session_client_tls.c
@@ -707,11 +707,11 @@
SSL_set_mode(session->ti.tls, SSL_MODE_AUTO_RETRY);
/* connect and perform the handshake */
- nc_gettimespec_mono_add(&ts_timeout, NC_TRANSPORT_TIMEOUT);
+ nc_timeouttime_get(&ts_timeout, NC_TRANSPORT_TIMEOUT);
tlsauth_ch = 0;
while (((ret = SSL_connect(session->ti.tls)) != 1) && (SSL_get_error(session->ti.tls, ret) == SSL_ERROR_WANT_READ)) {
usleep(NC_TIMEOUT_STEP);
- if (nc_difftimespec_mono_cur(&ts_timeout) < 1) {
+ if (nc_timeouttime_cur_diff(&ts_timeout) < 1) {
ERR(NULL, "SSL connect timeout.");
goto fail;
}
@@ -822,12 +822,12 @@
/* connect and perform the handshake */
if (timeout > -1) {
- nc_gettimespec_mono_add(&ts_timeout, timeout);
+ nc_timeouttime_get(&ts_timeout, timeout);
}
tlsauth_ch = 1;
while (((ret = SSL_connect(tls)) == -1) && (SSL_get_error(tls, ret) == SSL_ERROR_WANT_READ)) {
usleep(NC_TIMEOUT_STEP);
- if ((timeout > -1) && (nc_difftimespec_mono_cur(&ts_timeout) < 1)) {
+ if ((timeout > -1) && (nc_timeouttime_cur_diff(&ts_timeout) < 1)) {
ERR(NULL, "SSL connect timeout.");
goto cleanup;
}
diff --git a/src/session_p.h b/src/session_p.h
index 71f30da..aaa6cbc 100644
--- a/src/session_p.h
+++ b/src/session_p.h
@@ -540,40 +540,27 @@
NC_MSG_TYPE nc_send_msg_io(struct nc_session *session, int io_timeout, struct lyd_node *op);
/**
- * @brief Get the current real time if available and optionally add some time to it.
+ * @brief Get current clock (uses COMPAT_CLOCK_ID) time with an offset.
*
- * @param[in,out] ts Timespec structure holding time.
- * @param[in] msec Time in milliseconds to be added.
- * @return 0 on success;
- * @return -1 on error.
+ * @param[out] ts Current time offset by @p add_ms.
+ * @param[in] add_ms Number of milliseconds to add.
*/
-int nc_gettimespec_real_add(struct timespec *ts, uint32_t msec);
+void nc_timeouttime_get(struct timespec *ts, uint32_t add_ms);
/**
- * @brief Get the current monotonic time if available and optionally add some time to it.
- *
- * @param[in,out] ts Timespec structure holding time.
- * @param[in] msec Time in milliseconds to be added.
- * @return 0 on success;
- * @return -1 on error.
- */
-int nc_gettimespec_mono_add(struct timespec *ts, uint32_t msec);
-
-/**
- * @brief Get real time difference based on the current time.
+ * @brief Get time difference based on the current time (uses COMPAT_CLOCK_ID).
*
* @param[in] ts Timespec structure holding real time from which the current time is going to be subtracted.
* @return Time difference in milliseconds.
*/
-int32_t nc_difftimespec_real_cur(const struct timespec *ts);
+int32_t nc_timeouttime_cur_diff(const struct timespec *ts);
/**
- * @brief Get monotonic time difference based on the current time.
+ * @brief Get current CLOCK_REALTIME time.
*
- * @param[in] ts Timespec structure holding monotonic time from which the current time is going to be subtracted.
- * @return Time difference in milliseconds.
+ * @param[out] ts Current real time.
*/
-int32_t nc_difftimespec_mono_cur(const struct timespec *ts);
+void nc_realtime_get(struct timespec *ts);
const char *nc_keytype2str(NC_SSH_KEY_TYPE type);
diff --git a/src/session_server.c b/src/session_server.c
index 00ec005..55d249d 100644
--- a/src/session_server.c
+++ b/src/session_server.c
@@ -941,9 +941,9 @@
return msgtype;
}
- nc_gettimespec_mono_add(&ts_cur, 0);
+ nc_timeouttime_get(&ts_cur, 0);
(*session)->opts.server.last_rpc = ts_cur.tv_sec;
- nc_gettimespec_real_add(&ts_cur, 0);
+ nc_realtime_get(&ts_cur);
(*session)->opts.server.session_start = ts_cur.tv_sec;
(*session)->status = NC_STATUS_RUNNING;
@@ -1021,10 +1021,10 @@
int ret;
struct timespec ts;
- nc_gettimespec_real_add(&ts, NC_PS_LOCK_TIMEOUT);
+ nc_timeouttime_get(&ts, NC_PS_LOCK_TIMEOUT);
/* LOCK */
- ret = pthread_mutex_timedlock(&ps->lock, &ts);
+ ret = pthread_mutex_clocklock(&ps->lock, COMPAT_CLOCK_ID, &ts);
if (ret) {
ERR(NULL, "%s: failed to lock a pollsession (%s).", func, strerror(ret));
return -1;
@@ -1044,9 +1044,9 @@
/* is it our turn? */
while (ps->queue[ps->queue_begin] != *id) {
- nc_gettimespec_real_add(&ts, NC_PS_QUEUE_TIMEOUT);
+ nc_timeouttime_get(&ts, NC_PS_QUEUE_TIMEOUT);
- ret = pthread_cond_timedwait(&ps->cond, &ps->lock, &ts);
+ ret = pthread_cond_clockwait(&ps->cond, &ps->lock, COMPAT_CLOCK_ID, &ts);
if (ret) {
/**
* This may happen when another thread releases the lock and broadcasts the condition
@@ -1077,10 +1077,10 @@
int ret;
struct timespec ts;
- nc_gettimespec_real_add(&ts, NC_PS_LOCK_TIMEOUT);
+ nc_timeouttime_get(&ts, NC_PS_LOCK_TIMEOUT);
/* LOCK */
- ret = pthread_mutex_timedlock(&ps->lock, &ts);
+ ret = pthread_mutex_clocklock(&ps->lock, COMPAT_CLOCK_ID, &ts);
if (ret) {
ERR(NULL, "%s: failed to lock a pollsession (%s).", func, strerror(ret));
ret = -1;
@@ -1736,9 +1736,9 @@
}
/* fill timespecs */
- nc_gettimespec_mono_add(&ts_cur, 0);
+ nc_timeouttime_get(&ts_cur, 0);
if (timeout > -1) {
- nc_gettimespec_mono_add(&ts_timeout, timeout);
+ nc_timeouttime_get(&ts_timeout, timeout);
}
/* poll all the sessions one-by-one */
@@ -1832,7 +1832,7 @@
if (ret == NC_PSPOLL_TIMEOUT) {
usleep(NC_TIMEOUT_STEP);
- if ((timeout > -1) && (nc_difftimespec_mono_cur(&ts_timeout) < 1)) {
+ if ((timeout > -1) && (nc_timeouttime_cur_diff(&ts_timeout) < 1)) {
/* final timeout */
break;
}
@@ -2590,9 +2590,9 @@
return msgtype;
}
- nc_gettimespec_mono_add(&ts_cur, 0);
+ nc_timeouttime_get(&ts_cur, 0);
(*session)->opts.server.last_rpc = ts_cur.tv_sec;
- nc_gettimespec_real_add(&ts_cur, 0);
+ nc_realtime_get(&ts_cur);
(*session)->opts.server.session_start = ts_cur.tv_sec;
(*session)->status = NC_STATUS_RUNNING;
@@ -3395,9 +3395,9 @@
goto fail;
}
- nc_gettimespec_mono_add(&ts_cur, 0);
+ nc_timeouttime_get(&ts_cur, 0);
(*session)->opts.server.last_rpc = ts_cur.tv_sec;
- nc_gettimespec_real_add(&ts_cur, 0);
+ nc_realtime_get(&ts_cur);
(*session)->opts.server.session_start = ts_cur.tv_sec;
(*session)->status = NC_STATUS_RUNNING;
@@ -3473,10 +3473,10 @@
}
do {
- nc_gettimespec_real_add(&ts, NC_CH_NO_ENDPT_WAIT);
+ nc_timeouttime_get(&ts, NC_CH_NO_ENDPT_WAIT);
/* CH COND WAIT */
- r = pthread_cond_timedwait(&session->opts.server.ch_cond, &session->opts.server.ch_lock, &ts);
+ r = pthread_cond_clockwait(&session->opts.server.ch_cond, &session->opts.server.ch_lock, COMPAT_CLOCK_ID, &ts);
if (!r) {
/* we were woken up, something probably happened */
if (session->status != NC_STATUS_RUNNING) {
@@ -3505,7 +3505,7 @@
idle_timeout = 0;
}
- nc_gettimespec_mono_add(&ts, 0);
+ nc_timeouttime_get(&ts, 0);
if (!nc_session_get_notif_status(session) && idle_timeout && (ts.tv_sec >= session->opts.server.last_rpc + idle_timeout)) {
VRB(session, "Call Home client \"%s\": session idle timeout elapsed.", client->name);
session->status = NC_STATUS_INVALID;
diff --git a/src/session_server_ssh.c b/src/session_server_ssh.c
index 9907a33..db45b42 100644
--- a/src/session_server_ssh.c
+++ b/src/session_server_ssh.c
@@ -1099,7 +1099,7 @@
}
if (opts->auth_timeout) {
- nc_gettimespec_mono_add(&ts_timeout, opts->auth_timeout * 1000);
+ nc_timeouttime_get(&ts_timeout, opts->auth_timeout * 1000);
}
/* get user's replies */
@@ -1116,7 +1116,7 @@
}
usleep(NC_TIMEOUT_STEP);
- } while ((opts->auth_timeout) && (nc_difftimespec_mono_cur(&ts_timeout) >= 1));
+ } while ((opts->auth_timeout) && (nc_timeouttime_cur_diff(&ts_timeout) >= 1));
if (!reply) {
ERR(NULL, "Authentication timeout.");
@@ -1684,7 +1684,7 @@
}
if (timeout > -1) {
- nc_gettimespec_mono_add(&ts_timeout, timeout);
+ nc_timeouttime_get(&ts_timeout, timeout);
}
while (1) {
if (!nc_session_is_connected(session)) {
@@ -1704,7 +1704,7 @@
}
usleep(NC_TIMEOUT_STEP);
- if ((timeout > -1) && (nc_difftimespec_mono_cur(&ts_timeout) < 1)) {
+ if ((timeout > -1) && (nc_timeouttime_cur_diff(&ts_timeout) < 1)) {
/* timeout */
ERR(session, "Failed to start \"netconf\" SSH subsystem for too long, disconnecting.");
break;
@@ -1794,7 +1794,7 @@
/* authenticate */
if (opts->auth_timeout) {
- nc_gettimespec_mono_add(&ts_timeout, opts->auth_timeout * 1000);
+ nc_timeouttime_get(&ts_timeout, opts->auth_timeout * 1000);
}
while (1) {
if (!nc_session_is_connected(session)) {
@@ -1820,7 +1820,7 @@
}
usleep(NC_TIMEOUT_STEP);
- if ((opts->auth_timeout) && (nc_difftimespec_mono_cur(&ts_timeout) < 1)) {
+ if ((opts->auth_timeout) && (nc_timeouttime_cur_diff(&ts_timeout) < 1)) {
/* timeout */
break;
}
@@ -1882,12 +1882,12 @@
ssh_set_blocking(session->ti.libssh.session, 0);
if (timeout > -1) {
- nc_gettimespec_mono_add(&ts_timeout, timeout);
+ nc_timeouttime_get(&ts_timeout, timeout);
}
while ((r = ssh_handle_key_exchange(session->ti.libssh.session)) == SSH_AGAIN) {
/* this tends to take longer */
usleep(NC_TIMEOUT_STEP * 20);
- if ((timeout > -1) && (nc_difftimespec_mono_cur(&ts_timeout) < 1)) {
+ if ((timeout > -1) && (nc_timeouttime_cur_diff(&ts_timeout) < 1)) {
break;
}
}
@@ -1973,9 +1973,9 @@
return msgtype;
}
- nc_gettimespec_real_add(&ts_cur, 0);
+ nc_realtime_get(&ts_cur);
new_session->opts.server.session_start = ts_cur.tv_sec;
- nc_gettimespec_mono_add(&ts_cur, 0);
+ nc_timeouttime_get(&ts_cur, 0);
new_session->opts.server.last_rpc = ts_cur.tv_sec;
new_session->status = NC_STATUS_RUNNING;
*session = new_session;
@@ -2044,9 +2044,9 @@
return msgtype;
}
- nc_gettimespec_real_add(&ts_cur, 0);
+ nc_realtime_get(&ts_cur);
new_session->opts.server.session_start = ts_cur.tv_sec;
- nc_gettimespec_mono_add(&ts_cur, 0);
+ nc_timeouttime_get(&ts_cur, 0);
new_session->opts.server.last_rpc = ts_cur.tv_sec;
new_session->status = NC_STATUS_RUNNING;
*session = new_session;
diff --git a/src/session_server_tls.c b/src/session_server_tls.c
index 80513d9..040836f 100644
--- a/src/session_server_tls.c
+++ b/src/session_server_tls.c
@@ -2002,11 +2002,11 @@
pthread_setspecific(verify_key, session);
if (timeout > -1) {
- nc_gettimespec_mono_add(&ts_timeout, timeout);
+ nc_timeouttime_get(&ts_timeout, timeout);
}
while (((ret = SSL_accept(session->ti.tls)) == -1) && (SSL_get_error(session->ti.tls, ret) == SSL_ERROR_WANT_READ)) {
usleep(NC_TIMEOUT_STEP);
- if ((timeout > -1) && (nc_difftimespec_mono_cur(&ts_timeout) < 1)) {
+ if ((timeout > -1) && (nc_timeouttime_cur_diff(&ts_timeout) < 1)) {
ERR(session, "SSL accept timeout.");
return 0;
}