This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFA\JVMTI] Implement GetAllThreads


Hi,

This patch implements the JVMTI GetAllThreads function. Nothing too complicated, finds the root thread group then grabs all the threads under it and allocates an array to send them all back using the pointer passed in by the agent. Not sure if I submitted this a long time ago, but here it is again if I did. Includes a test case which creates 20 new threads then checks to make sure all the threads are found.

Changelog
2007-01-11  Kyle Galloway  <kgallowa@redhat.com>

	* jvmti.cc (_Jv_JVMTI_GetAllThreads): New function.
	* testsuite/libjava.jvmti/getallthreads.java: New test.
	* testsuite/libjava.jvmti/natgetallthreads.cc: Ditto.
	* testsuite/libjava.jvmti/getallthreads.out: Ditto.

Comments, Questions, Concerns?

- Kyle
Index: libjava/testsuite/libjava.jvmti/getallthreads.java
===================================================================
--- libjava/testsuite/libjava.jvmti/getallthreads.java	(revision 0)
+++ libjava/testsuite/libjava.jvmti/getallthreads.java	(revision 0)
@@ -0,0 +1,80 @@
+// Test JVMTI GetAllThreads
+
+import java.util.ArrayList;
+
+public class getallthreads extends Thread
+{
+	 public static int thread_num;
+	 public static ArrayList threads;
+  
+	 public int ex_framesc;
+  public boolean done = false;
+  
+  public static native void do_getallthreads_tests ();
+
+  public void run ()
+	 {
+    ex_frames = thread_num;
+		 thread_num++;
+
+		 if (ex_frames > 0)
+		   {
+        if ((ex_frames % 2) == 0)
+					 placeholder ();
+				 else
+					 natPlaceholder ();
+		   }
+		 else
+      runner ();
+	 }
+
+	 public native void natPlaceholder ();
+	 public native void natRunner ();
+
+	 public void placeholder ()
+	 {
+		 ex_frames--;
+
+		 if (ex_frames > 0)
+		   {
+				 if ((thread_num % 2) == 0)
+					 placeholder ();
+				 else
+					 natPlaceholder ();
+			 }
+		 else
+			 runner ();
+   }
+
+	 public void runner ()
+	 {
+		 done = true;
+		 while (done)
+			yield ();
+	 }
+
+  public static void main (String[] args)
+  {
+    System.out.println ("JVMTI GetAllThreads tests");
+    threads = new ArrayList (20);
+
+		getallthreads t;
+
+		for (int i = 0; i < 20; i++)
+		  {
+				t = new getallthreads ();
+				threads.add (t);
+				t.start ();
+				while (!t.done)
+					yield ();
+			}
+
+		do_getallthreads_tests ();
+
+		for (int i = 0; i < 20; i++)
+		  {
+				t = (getallthreads) threads.get(i);
+				t.done = false;
+			}
+  }
+}
Index: libjava/testsuite/libjava.jvmti/getallthreads.out
===================================================================
--- libjava/testsuite/libjava.jvmti/getallthreads.out	(revision 0)
+++ libjava/testsuite/libjava.jvmti/getallthreads.out	(revision 0)
@@ -0,0 +1,23 @@
+JVMTI GetAllThreads tests
+Found thread 1
+Found thread 2
+Found thread 3
+Found thread 4
+Found thread 5
+Found thread 6
+Found thread 7
+Found thread 8
+Found thread 9
+Found thread 10
+Found thread 11
+Found thread 12
+Found thread 13
+Found thread 14
+Found thread 15
+Found thread 16
+Found thread 17
+Found thread 18
+Found thread 19
+Found thread 20
+Found thread 21
+Found thread 22
Index: libjava/testsuite/libjava.jvmti/natgetallthreads.cc
===================================================================
--- libjava/testsuite/libjava.jvmti/natgetallthreads.cc	(revision 0)
+++ libjava/testsuite/libjava.jvmti/natgetallthreads.cc	(revision 0)
@@ -0,0 +1,55 @@
+#include <gcj/cni.h>
+
+#include <jvm.h>
+#include <jvmti.h>
+#include <stdio.h>
+
+#include "jvmti-int.h"
+#include "getallthreads.h"
+
+void
+getallthreads::natPlaceholder ()
+{
+	 ex_frames--;
+
+	 if (ex_frames > 0)
+	   {
+			 if ((getallthreads::thread_num % 2) == 0)
+			   placeholder ();
+			 else
+				 natPlaceholder ();
+		 }
+	 else
+	   natRunner ();
+}
+
+void
+getallthreads::natRunner ()
+{
+	 done = true;
+	 while (done)
+    yield ();
+}
+
+void
+getallthreads::do_getallthreads_tests ()
+{
+  jvmtiEnv *env;
+  JavaVM *vm = _Jv_GetJavaVM ();
+  vm->GetEnv (reinterpret_cast<void **> (&env), JVMTI_VERSION_1_0);
+
+	 jint num_threads;
+	 jthread *thread_arr;
+
+	 jvmtiError jerr = env->GetAllThreads (&num_threads, &thread_arr);
+	 if (jerr != JVMTI_ERROR_NONE)
+	   {
+		   printf ("Test Failed, JVMTI Error!\n");
+			 return;
+		 }
+	 env->Deallocate (reinterpret_cast<unsigned char *> (thread_arr));
+	
+	 for (int i = 0; i < num_threads; i++)
+  	 printf ("Found thread %d\n", i+1 );
+}
+
Index: libjava/jvmti.cc
===================================================================
--- libjava/jvmti.cc	(revision 120684)
+++ libjava/jvmti.cc	(working copy)
@@ -28,7 +28,9 @@
 #include <java/lang/Class.h>
 #include <java/lang/ClassLoader.h>
 #include <java/lang/Object.h>
+#include <java/lang/OutOfMemoryError.h>
 #include <java/lang/Thread.h>
+#include <java/lang/ThreadGroup.h>
 #include <java/lang/Throwable.h>
 #include <java/lang/VMClassLoader.h>
 #include <java/lang/reflect/Field.h>
@@ -196,6 +198,60 @@
   return JVMTI_ERROR_NONE;
 }
 
+jvmtiError
+_Jv_JVMTI_GetAllThreads(MAYBE_UNUSED jvmtiEnv *env, jint *thread_cnt,
+                        jthread **threads)
+{
+  REQUIRE_PHASE (env, JVMTI_PHASE_LIVE);
+  NULL_CHECK (thread_cnt);
+  NULL_CHECK (threads);
+   
+  using namespace java::lang;
+  Thread *thr = Thread::currentThread ();
+   
+  ThreadGroup *thr_grp = thr->getThreadGroup ();
+  ThreadGroup *parent = thr_grp->getParent ();
+   
+  // Get the root thread group
+  while (parent != NULL)
+  {
+    thr_grp = parent;
+    parent = thr_grp->getParent ();
+  }
+   
+  jint estimate = thr_grp->activeCount ();
+  
+  JArray<Thread *> *thr_arr;
+
+  // Allocate some extra space since threads can be created between calls
+  try
+    { 
+      thr_arr 
+			  = reinterpret_cast<JArray<Thread *> *> (JvNewObjectArray 
+			                                           ((estimate * 2),
+                                                 &Thread::class$, NULL));
+    }
+  catch (java::lang::OutOfMemoryError *err)
+    {
+      return JVMTI_ERROR_OUT_OF_MEMORY;
+    }
+    
+  *thread_cnt = thr_grp->enumerate (thr_arr);
+   
+  jvmtiError jerr = env->Allocate ((jlong) ((*thread_cnt) * sizeof (jthread)),
+                                   (unsigned char **) threads);
+ 
+  if (jerr != JVMTI_ERROR_NONE)
+    return jerr;
+   
+  // Transfer the threads to the result array
+  jthread *tmp_arr = reinterpret_cast<jthread *> (elements (thr_arr));
+ 
+  memcpy ((*threads), tmp_arr, (*thread_cnt));
+   
+  return JVMTI_ERROR_NONE;
+}
+
 static jvmtiError JNICALL
 _Jv_JVMTI_CreateRawMonitor (MAYBE_UNUSED jvmtiEnv *env, const char *name,
 			    jrawMonitorID *result)
@@ -1362,7 +1418,7 @@
   RESERVED,			// reserved1
   _Jv_JVMTI_SetEventNotificationMode, // SetEventNotificationMode
   RESERVED,			// reserved3
-  UNIMPLEMENTED,		// GetAllThreads
+  _Jv_JVMTI_GetAllThreads,		// GetAllThreads
   _Jv_JVMTI_SuspendThread,	// SuspendThread
   _Jv_JVMTI_ResumeThread,	// ResumeThread
   UNIMPLEMENTED,		// StopThread

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]