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;