Fix problems with very long timeouts given when waiting on a mutex or
condition variable. The pthread routines now use a timeout of 0xfffffffe
if the user asks for something longer than that otherwise we will wrap
around and actually get a much shorter timeout.
The scheduler has also been changed so that it it now limits itself to
a timeout of 0x7fffffff when working how how long to poll for. This won't
affect how long a thread actually sleeps for as we'll just wind up waiting
a bit more on the next pass round the loop.
This fixes bug 76845.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@2781 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/vg_libpthread.c b/coregrind/vg_libpthread.c
index df06d9c..2cbfe35 100644
--- a/coregrind/vg_libpthread.c
+++ b/coregrind/vg_libpthread.c
@@ -1355,6 +1355,8 @@
struct timeval timeval_now;
unsigned long long int ull_ms_now_after_1970;
unsigned long long int ull_ms_end_after_1970;
+ unsigned long long int ull_ms_now;
+ unsigned long long int ull_ms_end;
vg_pthread_mutex_t* vg_mutex;
CONVERT(mutex, mutex, vg_mutex);
@@ -1373,8 +1375,15 @@
+ ((unsigned long long int)(abstime->tv_nsec / 1000000));
if (ull_ms_end_after_1970 < ull_ms_now_after_1970)
ull_ms_end_after_1970 = ull_ms_now_after_1970;
- ms_end
- = ms_now + (unsigned int)(ull_ms_end_after_1970 - ull_ms_now_after_1970);
+ if (ull_ms_end >= (unsigned long long int)(0xFFFFFFFFUL)) {
+ /* use 0xFFFFFFFEUL because 0xFFFFFFFFUL is reserved for no timeout
+ (the fine difference between a long wait and a possible abort
+ due to a detected deadlock).
+ */
+ ms_end = 0xFFFFFFFEUL;
+ } else {
+ ms_end = (unsigned int)(ull_ms_end);
+ }
VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
VG_USERREQ__PTHREAD_MUTEX_TIMEDLOCK,
vg_mutex, ms_end, 0, 0);
@@ -1518,6 +1527,8 @@
struct timeval timeval_now;
unsigned long long int ull_ms_now_after_1970;
unsigned long long int ull_ms_end_after_1970;
+ unsigned long long int ull_ms_now;
+ unsigned long long int ull_ms_end;
vg_pthread_mutex_t* vg_mutex;
CONVERT(mutex, mutex, vg_mutex);
@@ -1537,8 +1548,17 @@
+ ((unsigned long long int)(abstime->tv_nsec / 1000000));
if (ull_ms_end_after_1970 < ull_ms_now_after_1970)
ull_ms_end_after_1970 = ull_ms_now_after_1970;
- ms_end
- = ms_now + (unsigned int)(ull_ms_end_after_1970 - ull_ms_now_after_1970);
+ ull_ms_now = ((unsigned long long int)(ms_now));
+ ull_ms_end = ull_ms_now + (ull_ms_end_after_1970 - ull_ms_now_after_1970);
+ if (ull_ms_end >= (unsigned long long int)(0xFFFFFFFFUL)) {
+ /* use 0xFFFFFFFEUL because 0xFFFFFFFFUL is reserved for no timeout
+ (the fine difference between a long wait and a possible abort
+ due to a detected deadlock).
+ */
+ ms_end = 0xFFFFFFFEUL;
+ } else {
+ ms_end = (unsigned int)(ull_ms_end);
+ }
VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
VG_USERREQ__PTHREAD_COND_TIMEDWAIT,
cond, vg_mutex, ms_end, 0);
diff --git a/coregrind/vg_scheduler.c b/coregrind/vg_scheduler.c
index 66d638f..02d884d 100644
--- a/coregrind/vg_scheduler.c
+++ b/coregrind/vg_scheduler.c
@@ -614,8 +614,13 @@
}
if (tp != NULL) {
- delta = tp->time - now;
- vg_assert(delta >= 0);
+ vg_assert(tp->time >= now);
+ /* limit the signed int delta to INT_MAX */
+ if ((tp->time - now) <= 0x7FFFFFFFU) {
+ delta = tp->time - now;
+ } else {
+ delta = 0x7FFFFFFF;
+ }
}
if (wicked)
delta = 0;