X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=libjava%2Fposix-threads.cc;h=66693abbc9b5fbbf44052ba567b0d16e658c7178;hb=bcf4f090a1585c088fe6b4f72301252564ead597;hp=6ea724b3be8f51fdc2dd6801ed8f8e19bdf5b2a3;hpb=65bf3316cf384588453604be6b4f0ed3751a8b0f;p=pf3gnuchains%2Fgcc-fork.git diff --git a/libjava/posix-threads.cc b/libjava/posix-threads.cc index 6ea724b3be8..66693abbc9b 100644 --- a/libjava/posix-threads.cc +++ b/libjava/posix-threads.cc @@ -14,6 +14,7 @@ details. */ #include #include "posix.h" +#include "posix-threads.h" // If we're using the Boehm GC, then we need to override some of the // thread primitives. This is fairly gross. @@ -358,15 +359,17 @@ ParkHelper::unpark () if (compare_and_swap (ptr, Thread::THREAD_PARK_RUNNING, Thread::THREAD_PARK_PERMIT)) return; - + /* If this thread is parked, put it into state RUNNING and send it a signal. */ - if (compare_and_swap + if (compare_and_swap (ptr, Thread::THREAD_PARK_PARKED, Thread::THREAD_PARK_RUNNING)) { + int result; pthread_mutex_lock (&mutex); - pthread_cond_signal (&cond); + result = pthread_cond_signal (&cond); pthread_mutex_unlock (&mutex); + JvAssert (result == 0); } } @@ -379,6 +382,14 @@ ParkHelper::deactivate () 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 * thread is interrupted or the optional timeout expires. If an @@ -406,32 +417,44 @@ ParkHelper::park (jboolean isAbsolute, jlong time) return; struct timespec ts; - jlong millis = 0, nanos = 0; if (time) { + unsigned long long seconds; + unsigned long usec; + if (isAbsolute) { - millis = time; - nanos = 0; + ts.tv_sec = time / 1000; + ts.tv_nsec = (time % 1000) * 1000 * 1000; } else { - millis = java::lang::System::currentTimeMillis(); - nanos = time; - } - - if (millis > 0 || nanos > 0) - { // 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 timespec. + jlong nanos = time; + jlong millis = 0; - unsigned long long m = (unsigned long long)millis; - unsigned long long seconds = m / 1000; + // For better accuracy, should use pthread_condattr_setclock + // 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; if (ts.tv_sec < 0 || (unsigned long long)ts.tv_sec != seconds) @@ -441,29 +464,30 @@ ParkHelper::park (jboolean isAbsolute, jlong time) millis = nanos = 0; } else - { - m %= 1000; - ts.tv_nsec = m * 1000000 + (unsigned long long)nanos; - } + /* This next statement also cannot overflow. */ + ts.tv_nsec = (usec % 1000000) * 1000 + (nanos % 1000); } } - + + pthread_mutex_lock (&mutex); if (compare_and_swap (ptr, Thread::THREAD_PARK_RUNNING, Thread::THREAD_PARK_PARKED)) { - pthread_mutex_lock (&mutex); - if (millis == 0 && nanos == 0) - pthread_cond_wait (&cond, &mutex); + int result = 0; + + if (! time) + result = pthread_cond_wait (&cond, &mutex); else - pthread_cond_timedwait (&cond, &mutex, &ts); - pthread_mutex_unlock (&mutex); - + result = pthread_cond_timedwait (&cond, &mutex, &ts); + + JvAssert (result == 0 || result == ETIMEDOUT); + /* If we were unparked by some other thread, this will already - be in state THREAD_PARK_RUNNING. If we timed out, we have to - do it ourself. */ - compare_and_swap - (ptr, Thread::THREAD_PARK_PARKED, Thread::THREAD_PARK_RUNNING); + be in state THREAD_PARK_RUNNING. If we timed out or were + interrupted, we have to do it ourself. */ + permit = Thread::THREAD_PARK_RUNNING; } + pthread_mutex_unlock (&mutex); } static void @@ -472,8 +496,8 @@ handle_intr (int) // Do nothing. } -static void -block_sigchld() +void +_Jv_BlockSigchld() { sigset_t mask; sigemptyset (&mask); @@ -484,6 +508,17 @@ block_sigchld() } void +_Jv_UnBlockSigchld() +{ + sigset_t mask; + sigemptyset (&mask); + sigaddset (&mask, SIGCHLD); + int c = pthread_sigmask (SIG_UNBLOCK, &mask, NULL); + if (c != 0) + JvFail (strerror (c)); +} + +void _Jv_InitThreads (void) { pthread_key_create (&_Jv_ThreadKey, NULL); @@ -501,7 +536,7 @@ _Jv_InitThreads (void) // Block SIGCHLD here to ensure that any non-Java threads inherit the new // signal mask. - block_sigchld(); + _Jv_BlockSigchld(); // Check/set the thread stack size. size_t min_ss = 32 * 1024; @@ -581,7 +616,7 @@ _Jv_ThreadRegister (_Jv_Thread_t *data) } # endif // Block SIGCHLD which is used in natPosixProcess.cc. - block_sigchld(); + _Jv_BlockSigchld(); } void @@ -629,7 +664,7 @@ _Jv_ThreadStart (java::lang::Thread *thread, _Jv_Thread_t *data, // Block SIGCHLD which is used in natPosixProcess.cc. // The current mask is inherited by the child thread. - block_sigchld(); + _Jv_BlockSigchld(); param.sched_priority = thread->getPriority();