aboutsummaryrefslogtreecommitdiff
path: root/libjava
diff options
context:
space:
mode:
Diffstat (limited to 'libjava')
-rw-r--r--libjava/ChangeLog6
-rw-r--r--libjava/posix-threads.cc29
2 files changed, 30 insertions, 5 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index 82aceeb..73eadf4 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -1,3 +1,9 @@
+2005-11-25 Andrew Haley <aph@redhat.com>
+
+ PR libgcj/25016
+ * posix-threads.cc (_Jv_CondWait): Rewrite calculation of the
+ struct timespec we pass to pthread_cond_timedwait.
+
2005-11-25 Ranjit Mathew <rmathew@gcc.gnu.org>
* testsuite/libjava.jacks/jacks.xfail: Remove
diff --git a/libjava/posix-threads.cc b/libjava/posix-threads.cc
index a596c77..042370f 100644
--- a/libjava/posix-threads.cc
+++ b/libjava/posix-threads.cc
@@ -92,14 +92,33 @@ _Jv_CondWait (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu,
return _JV_NOT_OWNER;
struct timespec ts;
- jlong m, startTime;
if (millis > 0 || nanos > 0)
{
- startTime = java::lang::System::currentTimeMillis();
- m = millis + startTime;
- ts.tv_sec = m / 1000;
- ts.tv_nsec = ((m % 1000) * 1000000) + nanos;
+ // Calculate the abstime corresponding to the timeout.
+ // Everything is in milliseconds.
+ //
+ // We use `unsigned long long' rather than jlong because our
+ // caller may pass up to Long.MAX_VALUE millis. This would
+ // overflow the range of a jlong when added to the current time.
+
+ unsigned long long startTime
+ = (unsigned long long)java::lang::System::currentTimeMillis();
+ unsigned long long m = (unsigned long long)millis + startTime;
+ unsigned long long seconds = m / 1000;
+
+ ts.tv_sec = seconds;
+ if (ts.tv_sec < 0 || (unsigned long long)ts.tv_sec != seconds)
+ {
+ // We treat a timeout that won't fit into a struct timespec
+ // as a wait forever.
+ millis = nanos = 0;
+ }
+ else
+ {
+ m %= 1000;
+ ts.tv_nsec = m * 1000000 + (unsigned long long)nanos;
+ }
}
_Jv_Thread_t *current = _Jv_ThreadCurrentData ();