mirror of
https://gitlab.com/embeddable-common-lisp/ecl.git
synced 2026-02-16 12:20:43 -08:00
threads.h: use clock_monotonic for timeouts on posix if available
Prevents threads from timing out too early or too late if the system clock is adjusted while waiting.
This commit is contained in:
parent
c1078cda7d
commit
c300f2ee3a
6 changed files with 46 additions and 16 deletions
2
src/aclocal.m4
vendored
2
src/aclocal.m4
vendored
|
|
@ -934,7 +934,7 @@ AC_CHECK_FUNC( [pthread_rwlock_init], [
|
|||
AC_DEFINE([HAVE_POSIX_RWLOCK], [], [HAVE_POSIX_RWLOCK])
|
||||
], [])
|
||||
], [])
|
||||
AC_CHECK_FUNCS([pthread_mutex_timedlock])
|
||||
AC_CHECK_FUNCS([pthread_mutex_timedlock pthread_condattr_setclock])
|
||||
])
|
||||
|
||||
|
||||
|
|
|
|||
11
src/configure
vendored
11
src/configure
vendored
|
|
@ -6233,12 +6233,13 @@ fi
|
|||
|
||||
fi
|
||||
|
||||
for ac_func in pthread_mutex_timedlock
|
||||
for ac_func in pthread_mutex_timedlock pthread_condattr_setclock
|
||||
do :
|
||||
ac_fn_c_check_func "$LINENO" "pthread_mutex_timedlock" "ac_cv_func_pthread_mutex_timedlock"
|
||||
if test "x$ac_cv_func_pthread_mutex_timedlock" = xyes; then :
|
||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
|
||||
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_PTHREAD_MUTEX_TIMEDLOCK 1
|
||||
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
|
|
@ -9664,7 +9665,7 @@ done
|
|||
|
||||
for ac_func in nanosleep alarm times select setenv putenv \
|
||||
lstat mkstemp sigprocmask isatty tzset \
|
||||
gettimeofday getrusage system
|
||||
gettimeofday getrusage system clock_gettime
|
||||
do :
|
||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
|
||||
|
|
|
|||
|
|
@ -754,7 +754,7 @@ dnl !!! end autoscan
|
|||
|
||||
AC_CHECK_FUNCS( [nanosleep alarm times select setenv putenv] \
|
||||
[lstat mkstemp sigprocmask isatty tzset] \
|
||||
[gettimeofday getrusage system] )
|
||||
[gettimeofday getrusage system clock_gettime] )
|
||||
|
||||
AC_CHECK_FUNCS( [expf powf logf sqrtf cosf sinf tanf sinhf coshf tanhf] \
|
||||
[floorf ceilf fabsf frexpf ldexpf log1p log1pf log1pl] \
|
||||
|
|
|
|||
|
|
@ -192,6 +192,9 @@
|
|||
/* Define to 1 if you have the `cimagl' function. */
|
||||
#undef HAVE_CIMAGL
|
||||
|
||||
/* Define to 1 if you have the `clock_gettime' function. */
|
||||
#undef HAVE_CLOCK_GETTIME
|
||||
|
||||
/* Define to 1 if you have the `clog' function. */
|
||||
#undef HAVE_CLOG
|
||||
|
||||
|
|
@ -436,6 +439,9 @@
|
|||
/* Define to 1 if you have the `powf' function. */
|
||||
#undef HAVE_POWF
|
||||
|
||||
/* Define to 1 if you have the `pthread_condattr_setclock' function. */
|
||||
#undef HAVE_PTHREAD_CONDATTR_SETCLOCK
|
||||
|
||||
/* Define to 1 if you have the `pthread_mutex_timedlock' function. */
|
||||
#undef HAVE_PTHREAD_MUTEX_TIMEDLOCK
|
||||
|
||||
|
|
|
|||
|
|
@ -72,6 +72,8 @@
|
|||
#endif
|
||||
/* gettimeofday() and sys/time.h */
|
||||
#undef HAVE_GETTIMEOFDAY
|
||||
/* clock_gettime() */
|
||||
#undef HAVE_CLOCK_GETTIME
|
||||
/* getrusage() and sys/resource.h */
|
||||
#ifndef NACL
|
||||
#undef HAVE_GETRUSAGE
|
||||
|
|
@ -133,6 +135,8 @@
|
|||
#undef HAVE_POSIX_RWLOCK
|
||||
/* whether we have mutex lock operations with timeout */
|
||||
#undef HAVE_PTHREAD_MUTEX_TIMEDLOCK
|
||||
/* whether we can set the clock for timed waits on condition variables */
|
||||
#undef HAVE_PTHREAD_CONDATTR_SETCLOCK
|
||||
/* uname() for system identification */
|
||||
#undef HAVE_UNAME
|
||||
#undef HAVE_UNISTD_H
|
||||
|
|
|
|||
|
|
@ -37,6 +37,12 @@
|
|||
#define ECL_MUTEX_TIMEOUT ETIMEDOUT
|
||||
#define ECL_MUTEX_DEADLOCK EDEADLK
|
||||
|
||||
#if defined(HAVE_PTHREAD_CONDATTR_SETCLOCK) && defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
|
||||
# define COND_VAR_CLOCK CLOCK_MONOTONIC
|
||||
#else
|
||||
# define COND_VAR_CLOCK CLOCK_REALTIME
|
||||
#endif
|
||||
|
||||
/* MUTEX */
|
||||
|
||||
/* Non-recursive locks are only provided as an optimization; on
|
||||
|
|
@ -83,15 +89,21 @@ ecl_mutex_lock(ecl_mutex_t *mutex)
|
|||
/* CONDITION VARIABLE */
|
||||
|
||||
static inline void
|
||||
add_timeout_delta(struct timespec *ts, double seconds)
|
||||
add_timeout_delta(struct timespec *ts, double seconds, clockid_t preferred_clock)
|
||||
{
|
||||
#if defined(HAVE_GETTIMEOFDAY)
|
||||
#if defined(HAVE_CLOCK_GETTIME)
|
||||
clock_gettime(preferred_clock, ts);
|
||||
#elif defined(HAVE_GETTIMEOFDAY)
|
||||
struct timeval tp;
|
||||
|
||||
gettimeofday(&tp, NULL);
|
||||
/* Convert from timeval to timespec */
|
||||
ts->tv_sec = tp.tv_sec;
|
||||
ts->tv_nsec = tp.tv_usec * 1000;
|
||||
#else
|
||||
ts->tv_sec = time(NULL);
|
||||
ts->tv_nsec = 0;
|
||||
#endif
|
||||
|
||||
/* Add `seconds' delta */
|
||||
ts->tv_sec += (time_t)floor(seconds);
|
||||
|
|
@ -100,10 +112,6 @@ add_timeout_delta(struct timespec *ts, double seconds)
|
|||
ts->tv_nsec -= 1e9;
|
||||
ts->tv_sec++;
|
||||
}
|
||||
#else
|
||||
ts->tv_sec = time(NULL) + (time_t)floor(seconds);
|
||||
ts->tv_nsec = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline int
|
||||
|
|
@ -111,7 +119,12 @@ ecl_mutex_timedlock(ecl_mutex_t *mutex, double seconds)
|
|||
{
|
||||
#if defined(HAVE_PTHREAD_MUTEX_TIMEDLOCK)
|
||||
struct timespec ts;
|
||||
add_timeout_delta(&ts, seconds);
|
||||
/* Ideally we would like to use CLOCK_MONOTONIC here to prevent
|
||||
wrong timeouts when the system clock is adjusted while we are
|
||||
waiting. However the posix spec says that pthread_mutex_timedlock
|
||||
always uses CLOCK_REALTIME and does not define a way to set the
|
||||
clock for mutexes. */
|
||||
add_timeout_delta(&ts, seconds, CLOCK_REALTIME);
|
||||
return pthread_mutex_timedlock(mutex, &ts);
|
||||
#else
|
||||
/* Not implemented, see mutex.d for alternative implementation using interrupts */
|
||||
|
|
@ -122,7 +135,13 @@ ecl_mutex_timedlock(ecl_mutex_t *mutex, double seconds)
|
|||
static inline void
|
||||
ecl_cond_var_init(ecl_cond_var_t *cv)
|
||||
{
|
||||
pthread_cond_init(cv, NULL);
|
||||
pthread_condattr_t attr;
|
||||
pthread_condattr_init(&attr);
|
||||
#if defined(HAVE_PTHREAD_CONDATTR_SETCLOCK)
|
||||
pthread_condattr_setclock(&attr, COND_VAR_CLOCK);
|
||||
#endif
|
||||
pthread_cond_init(cv, &attr);
|
||||
pthread_condattr_destroy(&attr);
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
|
@ -141,7 +160,7 @@ static inline int
|
|||
ecl_cond_var_timedwait(ecl_cond_var_t *cv, ecl_mutex_t *mutex, double seconds)
|
||||
{
|
||||
struct timespec ts;
|
||||
add_timeout_delta(&ts, seconds);
|
||||
add_timeout_delta(&ts, seconds, COND_VAR_CLOCK);
|
||||
return pthread_cond_timedwait(cv, mutex, &ts);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue