diff options
author | David Goulet <dgoulet@ev0ke.net> | 2015-01-21 13:18:56 -0500 |
---|---|---|
committer | David Goulet <dgoulet@ev0ke.net> | 2015-01-21 14:29:12 -0500 |
commit | d684dbb0c76c4de0b21fabee99fc08833249bd87 (patch) | |
tree | 62f86dc48ab8f3df15273384906538f981e8bf6e /src/common/compat_pthreads.c | |
parent | 3c8dabf69aa950c2df49f48aebbe02aac5b519f3 (diff) | |
download | tor-d684dbb0c76c4de0b21fabee99fc08833249bd87.tar.gz tor-d684dbb0c76c4de0b21fabee99fc08833249bd87.zip |
Support monotonic time for pthread_cond_timedwait
This is to avoid that the pthread_cond_timedwait() is not affected by time
adjustment which could make the waiting period very long or very short which
is not what we want in any cases.
Signed-off-by: David Goulet <dgoulet@ev0ke.net>
Diffstat (limited to 'src/common/compat_pthreads.c')
-rw-r--r-- | src/common/compat_pthreads.c | 30 |
1 files changed, 28 insertions, 2 deletions
diff --git a/src/common/compat_pthreads.c b/src/common/compat_pthreads.c index c217c5145b..e1d4b0e79b 100644 --- a/src/common/compat_pthreads.c +++ b/src/common/compat_pthreads.c @@ -6,6 +6,7 @@ #include "orconfig.h" #include <pthread.h> #include <signal.h> +#include <time.h> #include "compat.h" #include "torlog.h" @@ -169,8 +170,23 @@ tor_get_thread_id(void) int tor_cond_init(tor_cond_t *cond) { + pthread_condattr_t condattr; + memset(cond, 0, sizeof(tor_cond_t)); - if (pthread_cond_init(&cond->cond, NULL)) { + /* Default condition attribute. Might be used if clock monotonic is + * available else this won't affect anything. */ + if (pthread_condattr_init(&condattr)) { + return -1; + } + +#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) + /* Use monotonic time so when we timedwait() on it, any clock adjustment + * won't affect the timeout value. */ + if (pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC)) { + return -1; + } +#endif + if (pthread_cond_init(&cond->cond, &condattr)) { return -1; } return 0; @@ -209,12 +225,22 @@ tor_cond_wait(tor_cond_t *cond, tor_mutex_t *mutex, const struct timeval *tv) return r ? -1 : 0; } } else { - struct timespec ts; struct timeval tvnow, tvsum; + struct timespec ts; while (1) { +#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) + if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) { + return -1; + } + tvnow.tv_sec = ts.tv_sec; + tvnow.tv_usec = ts.tv_nsec / 1000; + timeradd(tv, &tvnow, &tvsum); +#else if (gettimeofday(&tvnow, NULL) < 0) return -1; timeradd(tv, &tvnow, &tvsum); +#endif /* HAVE_CLOCK_GETTIME, CLOCK_MONOTONIC */ + ts.tv_sec = tvsum.tv_sec; ts.tv_nsec = tvsum.tv_usec * 1000; |