This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
Re: [RFC] Implementing JVMTI's GetThreadState
- From: Tom Tromey <tromey at redhat dot com>
- To: Keith Seitz <keiths at redhat dot com>
- Cc: java-patches at gcc dot gnu dot org
- Date: 20 Apr 2007 12:04:44 -0600
- Subject: Re: [RFC] Implementing JVMTI's GetThreadState
- References: <461D2AED.6020007@redhat.com>
- Reply-to: tromey at redhat dot com
>>>>> "Keith" == Keith Seitz <keiths@redhat.com> writes:
I'm sorry I let this go so long.
Keith> Right now, I have been playing with an implementation which does
Keith> everything except figure out WHY a thread is waiting. My question of
Keith> course: Does anyone see anything more elegant than adding a bunch of
Keith> booleans in LockSupport.park, Object.wait, and Thread.sleep in order
Keith> to divine said information?
We need something similar to implement Thread.getState. I was working
on a patch for this once, I've appended what I had. I doubt it works
or compiles.
Keith> else if (false /*in Object.wait HOW TO DO THIS?*/)
Keith> state |= JVMTI_THREAD_STATE_IN_OBJECT_WAIT;
Isn't this Thread.State.WAITING?
Anyway we can have more states internally than are exposed by
Thread.State. The patch below directly uses the State enum, but it
could just as well use JVMTI values and then do translation in
getState.
What do you think of this?
Note that this patch doesn't address all the places we might block on
I/O. What a pain that will be.
Tom
Index: ChangeLog
from Tom Tromey <tromey@redhat.com>
* include/posix-threads.h (_Jv_MutexLock): Set thread's state.
* posix-threads.cc (_Jv_CondWait): Set thread's state.
* include/jvm.h (class JvSetThreadState): New class.
* java/lang/Thread.java (state): New field.
(getState): Wrote.
* java/lang/natThread.cc (_Jv_ThreadRun): Use
getUncaughtExceptionHandler.
(start): Set state.
(_Jv_AttachCurrentThread): Likewise.
(finish_): Likewise.
(getState): Removed.
Index: include/posix-threads.h
===================================================================
--- include/posix-threads.h (revision 115453)
+++ include/posix-threads.h (working copy)
@@ -1,7 +1,7 @@
// -*- c++ -*-
// posix-threads.h - Defines for using POSIX threads.
-/* Copyright (C) 1998, 1999, 2001, 2003 Free Software Foundation
+/* Copyright (C) 1998, 1999, 2001, 2003, 2006 Free Software Foundation
This file is part of libgcj.
@@ -123,31 +123,7 @@
mu->owner = 0;
}
-inline int
-_Jv_MutexLock (_Jv_Mutex_t *mu)
-{
- pthread_t self = pthread_self ();
- if (mu->owner == self)
- {
- mu->count++;
- }
- else
- {
-# ifdef LOCK_DEBUG
- int result = pthread_mutex_lock (&mu->mutex);
- if (0 != result)
- {
- fprintf(stderr, "Pthread_mutex_lock returned %d\n", result);
- for (;;) {}
- }
-# else
- pthread_mutex_lock (&mu->mutex);
-# endif
- mu->count = 1;
- mu->owner = self;
- }
- return 0;
-}
+extern int _Jv_MutexLock (_Jv_Mutex_t *);
inline int
_Jv_MutexUnlock (_Jv_Mutex_t *mu)
Index: include/jvm.h
===================================================================
--- include/jvm.h (revision 116131)
+++ include/jvm.h (working copy)
@@ -30,6 +30,9 @@
#include <gcj/cni.h>
#include <gcj/field.h>
+#include <java/lang/Thread.h>
+#include <java/lang/Thread$State.h>
+
/* Macro for possible unused arguments. */
#define MAYBE_UNUSED __attribute__((__unused__))
@@ -673,4 +676,27 @@
// A helper function defined in prims.cc.
char* _Jv_PrependVersionedLibdir (char* libpath);
+// Temporarily set the thread's state.
+class JvSetThreadState
+{
+private:
+ ::java::lang::Thread *thread;
+ ::java::lang::Thread$State *saved;
+
+public:
+
+ JvSetThreadState(::java::lang::Thread *cthread,
+ ::java::lang::Thread$State *nstate)
+ : thread (cthread),
+ saved (cthread->state)
+ {
+ thread->state = nstate;
+ }
+
+ ~JvSetThreadState()
+ {
+ thread->state = saved;
+ }
+};
+
#endif /* __JAVA_JVM_H__ */
Index: posix-threads.cc
===================================================================
--- posix-threads.cc (revision 115453)
+++ posix-threads.cc (working copy)
@@ -1,6 +1,6 @@
// posix-threads.cc - interface between libjava and POSIX threads.
-/* Copyright (C) 1998, 1999, 2000, 2001, 2004 Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001, 2004, 2006 Free Software Foundation
This file is part of libgcj.
@@ -78,6 +78,35 @@
+int
+_Jv_MutexLock (_Jv_Mutex_t *mu)
+{
+ pthread_t self = pthread_self ();
+ if (mu->owner == self)
+ {
+ mu->count++;
+ }
+ else
+ {
+ JvSetThreadState holder (_Jv_ThreadCurrent(),
+ ::java::lang::Thread$State::BLOCKED);
+
+# ifdef LOCK_DEBUG
+ int result = pthread_mutex_lock (&mu->mutex);
+ if (0 != result)
+ {
+ fprintf(stderr, "Pthread_mutex_lock returned %d\n", result);
+ for (;;) {}
+ }
+# else
+ pthread_mutex_lock (&mu->mutex);
+# endif
+ mu->count = 1;
+ mu->owner = self;
+ }
+ return 0;
+}
+
// Wait for the condition variable "CV" to be notified.
// Return values:
// 0: the condition was notified, or the timeout expired.
@@ -93,6 +122,7 @@
struct timespec ts;
+ ::java::lang::Thread$State *new_state = ::java::lang::Thread$State::WAITING;
if (millis > 0 || nanos > 0)
{
// Calculate the abstime corresponding to the timeout.
@@ -118,6 +148,7 @@
{
m %= 1000;
ts.tv_nsec = m * 1000000 + (unsigned long long)nanos;
+ new_state = ::java::lang::Thread$State::TIMED_WAITING;
}
}
@@ -134,6 +165,9 @@
return _JV_INTERRUPTED;
}
+ // Set the thread's state.
+ JvSetThreadState holder (current_obj, new_state);
+
// Add this thread to the cv's wait set.
current->next = NULL;
Index: java/lang/Thread.java
===================================================================
--- java/lang/Thread.java (revision 116132)
+++ java/lang/Thread.java (working copy)
@@ -153,6 +153,9 @@
// This describes the top-most interpreter frame for this thread.
RawData interp_frame;
+ // Current state.
+ volatile State state = State.NEW;
+
// Our native data - points to an instance of struct natThread.
private RawDataManaged data;
@@ -997,6 +1000,7 @@
*/
public UncaughtExceptionHandler getUncaughtExceptionHandler()
{
+ // FIXME: if thread is dead, should return null...
return exceptionHandler != null ? exceptionHandler : group;
}
@@ -1147,7 +1151,10 @@
*
* @return the current thread state.
*/
- public native State getState();
+ public State getState()
+ {
+ return state;
+ }
/**
* <p>
Index: java/lang/natThread.cc
===================================================================
--- java/lang/natThread.cc (revision 116132)
+++ java/lang/natThread.cc (working copy)
@@ -18,6 +18,7 @@
#include <gnu/gcj/RawDataManaged.h>
#include <java/lang/Thread.h>
+#include <java/lang/Thread$UncaughtExceptionHandler.h>
#include <java/lang/ThreadGroup.h>
#include <java/lang/IllegalArgumentException.h>
#include <java/lang/IllegalThreadStateException.h>
@@ -227,6 +228,7 @@
{
JvSynchronize sync (this);
alive_flag = false;
+ state = Thread$State::TERMINATED;
}
_Jv_CondNotifyAll (&nt->join_cond, &nt->join_mutex);
@@ -307,7 +309,7 @@
// this results in an uncaught exception, that is ignored.
try
{
- thread->group->uncaughtException (thread, t);
+ thread->getUncaughtExceptionHandler()->uncaughtException (thread, t);
}
catch (java::lang::Throwable *f)
{
@@ -329,6 +331,7 @@
alive_flag = true;
startable_flag = false;
+ state = Thread$State::RUNNABLE;
natThread *nt = (natThread *) data;
_Jv_ThreadStart (this, nt->thread, (_Jv_ThreadStartFunc *) &_Jv_ThreadRun);
}
@@ -385,13 +388,6 @@
_Jv_ThreadYield ();
}
-::java::lang::Thread$State *
-java::lang::Thread::getState()
-{
- // FIXME
- return NULL;
-}
-
JNIEnv *
_Jv_GetCurrentJNIEnv ()
{
@@ -419,6 +415,7 @@
return -1;
thread->startable_flag = false;
thread->alive_flag = true;
+ thread->state = ::java::lang::Thread$State::RUNNABLE;
natThread *nt = (natThread *) thread->data;
_Jv_ThreadRegister (nt->thread);
return 0;