From 43cbc9430d557a3219ff833751c38132f831036e Mon Sep 17 00:00:00 2001 From: Bryce McKinlay Date: Fri, 24 Dec 1999 01:00:46 +0000 Subject: [PATCH] natObject.cc (notify): Throw message with IllegalMonitorStateException. 1999-12-22 Bryce McKinlay * java/lang/natObject.cc (notify): Throw message with IllegalMonitorStateException. (notifyAll): Ditto. (wait): Ditto. * java/lang/Thread.java (isInterrupted): Don't clear interrupt_flag. (isInterrupted_): New function, which does clear interrupt_flag. (interrupt): Use `isInterrupted_'. * java/lang/natThread.cc (interrupt): Add comment. (join): Set `Prev' in joiner loop. Change various calls to `isInterrupted' to use `isInterrupted_'. * posix-threads.cc (_Jv_CondWait): Allways use pthread_cond_timedwait on linux. Set result to 0 on an interrupt. Test interrupted status of java Thread object directly. FLAG_INTERRUPTED: removed. (_Jv_ThreadStart): Throw OutOfMemoryError if pthread_create fails. (_Jv_ThreadInterrupt): Don't set FLAG_INTERRUPTED. (_Jv_InitThreads): Don't block SIGINT. (_Jv_ThreadWait): Don't configure SIGINT handler. From-SVN: r31082 --- libjava/ChangeLog | 21 +++++++ libjava/java/lang/natObject.cc | 9 ++- libjava/java/lang/natThread.cc | 16 ++++-- libjava/posix-threads.cc | 126 +++++++++++++++++++++++------------------ 4 files changed, 108 insertions(+), 64 deletions(-) diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 4a6a157..cfdd986 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,24 @@ +1999-12-22 Bryce McKinlay + + * java/lang/natObject.cc (notify): Throw message with + IllegalMonitorStateException. + (notifyAll): Ditto. + (wait): Ditto. + * java/lang/Thread.java (isInterrupted): Don't clear interrupt_flag. + (isInterrupted_): New function, which does clear interrupt_flag. + (interrupt): Use `isInterrupted_'. + * java/lang/natThread.cc (interrupt): Add comment. + (join): Set `prev' in joiner loop. + Change various calls to `isInterrupted' to use `isInterrupted_'. + * posix-threads.cc (_Jv_CondWait): Allways use pthread_cond_timedwait + on linux. Set result to 0 on an interrupt. Test interrupted status + of java Thread object directly. + FLAG_INTERRUPTED: removed. + (_Jv_ThreadStart): Throw OutOfMemoryError if pthread_create fails. + (_Jv_ThreadInterrupt): Don't set FLAG_INTERRUPTED. + (_Jv_InitThreads): Don't block SIGINT. + (_Jv_ThreadWait): Don't configure SIGINT handler. + 1999-12-21 Tom Tromey * mauve-libgcj: Added java.lang.reflect.Modifier.toString12. diff --git a/libjava/java/lang/natObject.cc b/libjava/java/lang/natObject.cc index 0ca5a58..3d9f9fb 100644 --- a/libjava/java/lang/natObject.cc +++ b/libjava/java/lang/natObject.cc @@ -175,7 +175,8 @@ java::lang::Object::notify (void) sync_init (); _Jv_SyncInfo *si = (_Jv_SyncInfo *) sync_info; if (_Jv_CondNotify (&si->condition, &si->mutex)) - JvThrow (new IllegalMonitorStateException); + JvThrow (new IllegalMonitorStateException(JvNewStringLatin1 + ("current thread not owner"))); } void @@ -185,7 +186,8 @@ java::lang::Object::notifyAll (void) sync_init (); _Jv_SyncInfo *si = (_Jv_SyncInfo *) sync_info; if (_Jv_CondNotifyAll (&si->condition, &si->mutex)) - JvThrow (new IllegalMonitorStateException); + JvThrow (new IllegalMonitorStateException(JvNewStringLatin1 + ("current thread not owner"))); } void @@ -197,7 +199,8 @@ java::lang::Object::wait (jlong timeout, jint nanos) JvThrow (new IllegalArgumentException); _Jv_SyncInfo *si = (_Jv_SyncInfo *) sync_info; if (_Jv_CondWait (&si->condition, &si->mutex, timeout, nanos)) - JvThrow (new IllegalMonitorStateException); + JvThrow (new IllegalMonitorStateException(JvNewStringLatin1 + ("current thread not owner"))); if (Thread::interrupted()) JvThrow (new InterruptedException); } diff --git a/libjava/java/lang/natThread.cc b/libjava/java/lang/natThread.cc index 4f04363..8239f17 100644 --- a/libjava/java/lang/natThread.cc +++ b/libjava/java/lang/natThread.cc @@ -130,10 +130,13 @@ java::lang::Thread::interrupt (void) // another thread to exit. natThread *nt = (natThread *) data; _Jv_MutexLock (&nt->interrupt_mutex); + // Notify the interrupt condition to interrupt sleep() and join() calls. _Jv_CondNotify (&nt->interrupt_cond, &nt->interrupt_mutex); - _Jv_MutexUnlock (&nt->interrupt_mutex); - + // Send a signal to the target thread to interrupt system calls. On Linux, + // this will also interrupt the target thread from *any* _Jv_CondWait call, + // ie wait(). This behaviour is not portable, however. _Jv_ThreadInterrupt (nt->thread); + _Jv_MutexUnlock (&nt->interrupt_mutex); } void @@ -145,7 +148,7 @@ java::lang::Thread::join (jlong millis, jint nanos) _Jv_Throw (new IllegalArgumentException); Thread *current = currentThread (); - if (current->isInterrupted ()) + if (current->isInterrupted_ ()) _Jv_Throw (new InterruptedException); // Update the list of all threads waiting for this thread to exit. @@ -199,11 +202,12 @@ java::lang::Thread::join (jlong millis, jint nanos) t->next = 0; break; } + prev = t; } JvAssert (t != NULL); _Jv_MonitorExit (this); - if (current->isInterrupted ()) + if (current->isInterrupted_ ()) _Jv_Throw (new InterruptedException); } @@ -240,7 +244,7 @@ java::lang::Thread::sleep (jlong millis, jint nanos) ++nanos; Thread *current = currentThread (); - if (current->isInterrupted ()) + if (current->isInterrupted_ ()) _Jv_Throw (new InterruptedException); // We use a condition variable to implement sleeping so that an @@ -253,7 +257,7 @@ java::lang::Thread::sleep (jlong millis, jint nanos) millis, nanos); } - if (current->isInterrupted ()) + if (current->isInterrupted_ ()) _Jv_Throw (new InterruptedException); } diff --git a/libjava/posix-threads.cc b/libjava/posix-threads.cc index 0a3311d..cf18ace 100644 --- a/libjava/posix-threads.cc +++ b/libjava/posix-threads.cc @@ -27,11 +27,14 @@ extern "C" #include #include #include +#include #include #include #include #include +#include +#include // This is used to implement thread startup. struct starter @@ -58,7 +61,7 @@ static int non_daemon_count; // The signal to use when interrupting a thread. #ifdef LINUX_THREADS - // LinuxThreads usurps both SIGUSR1 and SIGUSR2. + // LinuxThreads (prior to glibc 2.1) usurps both SIGUSR1 and SIGUSR2. # define INTR SIGHUP #else /* LINUX_THREADS */ # define INTR SIGUSR2 @@ -72,8 +75,6 @@ static int non_daemon_count; #define FLAG_START 0x01 // Thread is daemon. #define FLAG_DAEMON 0x02 -// Thread was interrupted by _Jv_ThreadInterrupt. -#define FLAG_INTERRUPTED 0x04 @@ -86,58 +87,82 @@ _Jv_CondWait (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu, int r; pthread_mutex_t *pmu = _Jv_PthreadGetMutex (mu); - struct timespec ts; + struct timespec ts; jlong m, m2, startTime; bool done_sleeping = false; if (millis == 0 && nanos == 0) - r = pthread_cond_wait (cv, pmu); + { +#ifdef LINUX_THREADS + // pthread_cond_timedwait can be interrupted by a signal on linux, while + // pthread_cond_wait can not. So pthread_cond_timedwait() forever. + m = java::lang::Long::MAX_VALUE; + ts.tv_sec = LONG_MAX; + ts.tv_nsec = 0; +#endif + } else { startTime = java::lang::System::currentTimeMillis(); m = millis + startTime; + ts.tv_sec = m / 1000; + ts.tv_nsec = ((m % 1000) * 1000000) + nanos; + } - do - { - ts.tv_sec = m / 1000; - ts.tv_nsec = ((m % 1000) * 1000000) + nanos; + java::lang::Thread *current = _Jv_ThreadCurrent(); + do + { + r = EINTR; + // Check to ensure the thread hasn't already been interrupted. + if (!(current->isInterrupted ())) + { +#ifdef LINUX_THREADS + // FIXME: in theory, interrupt() could be called on this thread + // between the test above and the wait below, resulting in the + // interupt() call failing. I don't see a way to fix this + // without significant changes to the implementation. r = pthread_cond_timedwait (cv, pmu, &ts); - - if (r == EINTR) +#else + if (millis == 0 && nanos == 0) + r = pthread_cond_wait (cv, pmu); + else + r = pthread_cond_timedwait (cv, pmu, &ts); +#endif + } + + if (r == EINTR) + { + /* We were interrupted by a signal. Either this is + because we were interrupted intentionally (i.e. by + Thread.interrupt()) or by the GC if it is + signal-based. */ + if (current->isInterrupted ()) { - /* We were interrupted by a signal. Either this is - because we were interrupted intentionally (i.e. by - Thread.interrupt()) or by the GC if it is - signal-based. */ - _Jv_Thread_t *current = _Jv_ThreadCurrentData(); - if (current->flags & FLAG_INTERRUPTED) + r = 0; + done_sleeping = true; + } + else + { + /* We were woken up by the GC or another signal. */ + m2 = java::lang::System::currentTimeMillis (); + if (m2 >= m) { - current->flags &= ~(FLAG_INTERRUPTED); - done_sleeping = true; - } - else - { - /* We were woken up by the GC or another signal. */ - m2 = java::lang::System::currentTimeMillis (); - if (m2 >= m) - { - r = 0; - done_sleeping = true; - } + r = 0; + done_sleeping = true; } } - else if (r == ETIMEDOUT) - { - /* A timeout is a normal result. */ - r = 0; - done_sleeping = true; - } - else - done_sleeping = true; } - while (! done_sleeping); + else if (r == ETIMEDOUT) + { + /* A timeout is a normal result. */ + r = 0; + done_sleeping = true; + } + else + done_sleeping = true; } + while (! done_sleeping); return r != 0; } @@ -272,20 +297,12 @@ _Jv_InitThreads (void) sigemptyset (&act.sa_mask); act.sa_flags = 0; sigaction (INTR, &act, NULL); - - // Arrange for SIGINT to be blocked to all threads. It is only - // deliverable to the master thread. - sigset_t mask; - sigemptyset (&mask); - sigaddset (&mask, SIGINT); - pthread_sigmask (SIG_BLOCK, &mask, NULL); } void _Jv_ThreadInitData (_Jv_Thread_t **data, java::lang::Thread *) { _Jv_Thread_t *info = new _Jv_Thread_t; - info->flags = 0; // FIXME register a finalizer for INFO here. @@ -361,20 +378,20 @@ _Jv_ThreadStart (java::lang::Thread *thread, _Jv_Thread_t *data, } else data->flags |= FLAG_DAEMON; - pthread_create (&data->thread, &attr, really_start, (void *) info); - + int r = pthread_create (&data->thread, &attr, really_start, (void *) info); + pthread_attr_destroy (&attr); + + if (r) + { + const char* msg = "Cannot create additional threads"; + JvThrow (new java::lang::OutOfMemoryError (JvNewStringUTF (msg))); + } } void _Jv_ThreadWait (void) { - // Arrange for SIGINT to be delivered to the master thread. - sigset_t mask; - sigemptyset (&mask); - sigaddset (&mask, SIGINT); - pthread_sigmask (SIG_UNBLOCK, &mask, NULL); - pthread_mutex_lock (&daemon_mutex); if (non_daemon_count) pthread_cond_wait (&daemon_cond, &daemon_mutex); @@ -384,6 +401,5 @@ _Jv_ThreadWait (void) void _Jv_ThreadInterrupt (_Jv_Thread_t *data) { - data->flags |= FLAG_INTERRUPTED; pthread_kill (data->thread, INTR); } -- 2.7.4