posix-threads.cc (park): Rewrite code to handle time.
2009-11-17 Andrew Haley <aph@redhat.com> * posix-threads.cc (park): Rewrite code to handle time. Move mutex lock before the call to compare_and_swap to avoid a race condition. Add some assertions. (unpark): Add an assertion. (init): Move here from posix-threads.h. * include/posix-threads.h (destroy): removed. From-SVN: r154265
This commit is contained in:
parent
37740cd3af
commit
6bab028494
|
@ -1,3 +1,13 @@
|
||||||
|
2009-11-17 Andrew Haley <aph@redhat.com>
|
||||||
|
|
||||||
|
* posix-threads.cc (park): Rewrite code to handle time.
|
||||||
|
Move mutex lock before the call to compare_and_swap to avoid a
|
||||||
|
race condition.
|
||||||
|
Add some assertions.
|
||||||
|
(unpark): Add an assertion.
|
||||||
|
(init): Move here from posix-threads.h.
|
||||||
|
* include/posix-threads.h (destroy): removed.
|
||||||
|
|
||||||
2009-11-13 Eric Botcazou <ebotcazou@adacore.com>
|
2009-11-13 Eric Botcazou <ebotcazou@adacore.com>
|
||||||
|
|
||||||
* exception.cc (PERSONALITY_FUNCTION): Fix oversight.
|
* exception.cc (PERSONALITY_FUNCTION): Fix oversight.
|
||||||
|
|
|
@ -374,13 +374,6 @@ struct ParkHelper
|
||||||
void unpark ();
|
void unpark ();
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void
|
|
||||||
ParkHelper::init ()
|
|
||||||
{
|
|
||||||
pthread_mutex_init (&mutex, NULL);
|
|
||||||
pthread_cond_init (&cond, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
ParkHelper::destroy ()
|
ParkHelper::destroy ()
|
||||||
{
|
{
|
||||||
|
|
|
@ -366,8 +366,9 @@ ParkHelper::unpark ()
|
||||||
(ptr, Thread::THREAD_PARK_PARKED, Thread::THREAD_PARK_RUNNING))
|
(ptr, Thread::THREAD_PARK_PARKED, Thread::THREAD_PARK_RUNNING))
|
||||||
{
|
{
|
||||||
pthread_mutex_lock (&mutex);
|
pthread_mutex_lock (&mutex);
|
||||||
pthread_cond_signal (&cond);
|
int result = pthread_cond_signal (&cond);
|
||||||
pthread_mutex_unlock (&mutex);
|
pthread_mutex_unlock (&mutex);
|
||||||
|
JvAssert (result == 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,6 +381,14 @@ ParkHelper::deactivate ()
|
||||||
permit = ::java::lang::Thread::THREAD_PARK_DEAD;
|
permit = ::java::lang::Thread::THREAD_PARK_DEAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ParkHelper::init ()
|
||||||
|
{
|
||||||
|
pthread_mutex_init (&mutex, NULL);
|
||||||
|
pthread_cond_init (&cond, NULL);
|
||||||
|
permit = ::java::lang::Thread::THREAD_PARK_RUNNING;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Blocks the thread until a matching _Jv_ThreadUnpark() occurs, the
|
* Blocks the thread until a matching _Jv_ThreadUnpark() occurs, the
|
||||||
* thread is interrupted or the optional timeout expires. If an
|
* thread is interrupted or the optional timeout expires. If an
|
||||||
|
@ -407,32 +416,44 @@ ParkHelper::park (jboolean isAbsolute, jlong time)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
jlong millis = 0, nanos = 0;
|
|
||||||
|
|
||||||
if (time)
|
if (time)
|
||||||
{
|
{
|
||||||
|
unsigned long long seconds;
|
||||||
|
unsigned long usec;
|
||||||
|
|
||||||
if (isAbsolute)
|
if (isAbsolute)
|
||||||
{
|
{
|
||||||
millis = time;
|
ts.tv_sec = time / 1000;
|
||||||
nanos = 0;
|
ts.tv_nsec = (time % 1000) * 1000 * 1000;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
millis = java::lang::System::currentTimeMillis();
|
|
||||||
nanos = time;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (millis > 0 || nanos > 0)
|
|
||||||
{
|
{
|
||||||
// Calculate the abstime corresponding to the timeout.
|
// Calculate the abstime corresponding to the timeout.
|
||||||
// Everything is in milliseconds.
|
jlong nanos = time;
|
||||||
//
|
jlong millis = 0;
|
||||||
// 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 timespec.
|
|
||||||
|
|
||||||
unsigned long long m = (unsigned long long)millis;
|
// For better accuracy, should use pthread_condattr_setclock
|
||||||
unsigned long long seconds = m / 1000;
|
// and clock_gettime.
|
||||||
|
#ifdef HAVE_GETTIMEOFDAY
|
||||||
|
timeval tv;
|
||||||
|
gettimeofday (&tv, NULL);
|
||||||
|
usec = tv.tv_usec;
|
||||||
|
seconds = tv.tv_sec;
|
||||||
|
#else
|
||||||
|
unsigned long long startTime
|
||||||
|
= java::lang::System::currentTimeMillis();
|
||||||
|
seconds = startTime / 1000;
|
||||||
|
/* Assume we're about half-way through this millisecond. */
|
||||||
|
usec = (startTime % 1000) * 1000 + 500;
|
||||||
|
#endif
|
||||||
|
/* These next two statements cannot overflow. */
|
||||||
|
usec += nanos / 1000;
|
||||||
|
usec += (millis % 1000) * 1000;
|
||||||
|
/* These two statements could overflow only if tv.tv_sec was
|
||||||
|
insanely large. */
|
||||||
|
seconds += millis / 1000;
|
||||||
|
seconds += usec / 1000000;
|
||||||
|
|
||||||
ts.tv_sec = seconds;
|
ts.tv_sec = seconds;
|
||||||
if (ts.tv_sec < 0 || (unsigned long long)ts.tv_sec != seconds)
|
if (ts.tv_sec < 0 || (unsigned long long)ts.tv_sec != seconds)
|
||||||
|
@ -442,29 +463,30 @@ ParkHelper::park (jboolean isAbsolute, jlong time)
|
||||||
millis = nanos = 0;
|
millis = nanos = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
/* This next statement also cannot overflow. */
|
||||||
m %= 1000;
|
ts.tv_nsec = (usec % 1000000) * 1000 + (nanos % 1000);
|
||||||
ts.tv_nsec = m * 1000000 + (unsigned long long)nanos;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pthread_mutex_lock (&mutex);
|
||||||
if (compare_and_swap
|
if (compare_and_swap
|
||||||
(ptr, Thread::THREAD_PARK_RUNNING, Thread::THREAD_PARK_PARKED))
|
(ptr, Thread::THREAD_PARK_RUNNING, Thread::THREAD_PARK_PARKED))
|
||||||
{
|
{
|
||||||
pthread_mutex_lock (&mutex);
|
int result = 0;
|
||||||
if (millis == 0 && nanos == 0)
|
|
||||||
pthread_cond_wait (&cond, &mutex);
|
if (! time)
|
||||||
|
result = pthread_cond_wait (&cond, &mutex);
|
||||||
else
|
else
|
||||||
pthread_cond_timedwait (&cond, &mutex, &ts);
|
result = pthread_cond_timedwait (&cond, &mutex, &ts);
|
||||||
pthread_mutex_unlock (&mutex);
|
|
||||||
|
JvAssert (result == 0 || result == ETIMEDOUT);
|
||||||
|
|
||||||
/* If we were unparked by some other thread, this will already
|
/* If we were unparked by some other thread, this will already
|
||||||
be in state THREAD_PARK_RUNNING. If we timed out, we have to
|
be in state THREAD_PARK_RUNNING. If we timed out or were
|
||||||
do it ourself. */
|
interrupted, we have to do it ourself. */
|
||||||
compare_and_swap
|
permit = Thread::THREAD_PARK_RUNNING;
|
||||||
(ptr, Thread::THREAD_PARK_PARKED, Thread::THREAD_PARK_RUNNING);
|
|
||||||
}
|
}
|
||||||
|
pthread_mutex_unlock (&mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
Loading…
Reference in New Issue