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]

Re: Patch: finalizer thread - please comment


Thanks everybody for the responses.  I've updated the finalizer thread
patch so that the no-gc case will work.  I'll do a no-thread build to
test it before I check it in.

>> One idea would be to lazily create the new thread insie
>> FinalizerThread itself.

Bryce> Thats probibly a good idea anyway - starting the Finalization
Bryce> thread from FirstThread isn't right because it won't get
Bryce> started if the runtime is started via invocation. Another
Bryce> option would be to start it in _Jv_CreateJavaVM, which should
Bryce> be run regardless of how the runtime is invoked.

One reason to do it from _Jv_CreateJavaVM is that I don't know what to
do if we get an error when creating the thread lazily, whereas if we
get an error at startup we can just propagate the exception and die.

Bryce> You should probibly also set a thread name in the constructor,
Bryce> so it shows up in stack traces etc.

Thanks, done.

I've appended the new patch.  Please tell me what you think.

Tom

Index: ChangeLog
from  Tom Tromey  <tromey@redhat.com>

	* prims.cc: Include VirtualMachineError.h, FinalizerThread.h.
	(_Jv_CreateJavaVM): Start the finalizer thread.
	* no-threads.cc: Include InternalError.h.
	(_Jv_ThreadInitData): Throw InternalError if thread already
	running.
	(_Jv_ThreadStart): Throw InternalError.
	* Makefile.in: Rebuilt.
	* Makefile.am (ordinary_java_source_files): Added
	FinalizerThread.java.
	* include/jvm.h (_Jv_GCInitializeFinalizers): Declare.
	* boehm.cc (_Jv_GCInitializeFinalizers): New function.
	* posix-threads.cc (_Jv_InitThreads): Call
	_Jv_GCInitializeFinalizers.
	Include FinalizerThread.h.
	* gnu/gcj/runtime/FirstThread.java (run): Start finalizer thread.
	* gnu/gcj/runtime/FinalizerThread.java: New file.

Index: Makefile.am
===================================================================
RCS file: /cvs/gcc/gcc/libjava/Makefile.am,v
retrieving revision 1.174
diff -u -r1.174 Makefile.am
--- Makefile.am 2001/10/02 22:49:53 1.174
+++ Makefile.am 2001/10/05 14:53:38
@@ -1137,6 +1137,7 @@
 gnu/gcj/protocol/jar/Connection.java \
 gnu/gcj/protocol/jar/Handler.java \
 gnu/gcj/runtime/FileDeleter.java \
+gnu/gcj/runtime/FinalizerThread.java \
 gnu/gcj/runtime/FirstThread.java \
 gnu/gcj/runtime/SharedLibLoader.java \
 gnu/gcj/runtime/VMClassLoader.java \
Index: boehm.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/boehm.cc,v
retrieving revision 1.28
diff -u -r1.28 boehm.cc
--- boehm.cc 2001/10/02 14:31:42 1.28
+++ boehm.cc 2001/10/05 14:53:41
@@ -544,6 +544,13 @@
 #endif /* JV_HASH_SYNCHRONIZATION */
 
 void
+_Jv_GCInitializeFinalizers (void (*notifier) (void))
+{
+  GC_finalize_on_demand = 1;
+  GC_finalizer_notifier = notifier;
+}
+
+void
 _Jv_GCRegisterDisappearingLink (jobject *objp)
 {
   GC_general_register_disappearing_link ((GC_PTR *) objp, (GC_PTR) *objp);
Index: no-threads.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/no-threads.cc,v
retrieving revision 1.7
diff -u -r1.7 no-threads.cc
--- no-threads.cc 2001/09/21 07:46:32 1.7
+++ no-threads.cc 2001/10/05 14:53:41
@@ -1,6 +1,6 @@
 // no-thread.cc - Implementation of `no threads' threads.
 
-/* Copyright (C) 1998, 1999  Free Software Foundation
+/* Copyright (C) 1998, 1999, 2001  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -13,6 +13,7 @@
 #include <gcj/cni.h>
 #include <jvm.h>
 #include <java/lang/Thread.h>
+#include <java/lang/InternalError.h>
 
 java::lang::Thread *_Jv_OnlyThread = NULL;
 
@@ -22,7 +23,7 @@
   // Don't use JvAssert, since we want this to fail even when compiled
   // without assertions.
   if (_Jv_OnlyThread)
-    JvFail ("only thread already running");
+    throw new java::lang::InternalError (JvNewStringLatin1 ("only thread already running"));
   _Jv_OnlyThread = thread;
   return NULL;
 }
@@ -30,5 +31,5 @@
 void
 _Jv_ThreadStart (java::lang::Thread *, _Jv_Thread_t *, _Jv_ThreadStartFunc *)
 {
-  JvFail ("Thread.start called but threads not available");
+  throw new java::lang::InternalError (JvNewStringLatin1 ("Thread.start called but threads not available"));
 }
Index: posix-threads.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/posix-threads.cc,v
retrieving revision 1.28
diff -u -r1.28 posix-threads.cc
--- posix-threads.cc 2001/09/21 04:23:31 1.28
+++ posix-threads.cc 2001/10/05 14:53:41
@@ -31,6 +31,7 @@
 #include <java/lang/System.h>
 #include <java/lang/Long.h>
 #include <java/lang/OutOfMemoryError.h>
+#include <gnu/gcj/runtime/FinalizerThread.h>
 
 // This is used to implement thread startup.
 struct starter
@@ -291,6 +292,8 @@
   sigemptyset (&act.sa_mask);
   act.sa_flags = 0;
   sigaction (INTR, &act, NULL);
+
+  _Jv_GCInitializeFinalizers (&::gnu::gcj::runtime::FinalizerThread::finalizerReady);
 }
 
 _Jv_Thread_t *
Index: prims.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/prims.cc,v
retrieving revision 1.59
diff -u -r1.59 prims.cc
--- prims.cc 2001/10/02 13:44:31 1.59
+++ prims.cc 2001/10/05 14:53:42
@@ -53,7 +53,6 @@
 #include <java/lang/String.h>
 #include <java/lang/Thread.h>
 #include <java/lang/ThreadGroup.h>
-#include <gnu/gcj/runtime/FirstThread.h>
 #include <java/lang/ArrayIndexOutOfBoundsException.h>
 #include <java/lang/ArithmeticException.h>
 #include <java/lang/ClassFormatError.h>
@@ -64,7 +63,10 @@
 #include <java/lang/reflect/Modifier.h>
 #include <java/io/PrintStream.h>
 #include <java/lang/UnsatisfiedLinkError.h>
+#include <java/lang/VirtualMachineError.h>
 #include <gnu/gcj/runtime/VMClassLoader.h>
+#include <gnu/gcj/runtime/FinalizerThread.h>
+#include <gnu/gcj/runtime/FirstThread.h>
 
 #ifdef USE_LTDL
 #include <ltdl.h>
@@ -893,6 +895,19 @@
 #endif
 
   _Jv_JNI_Init ();
+
+  // Start the GC finalizer thread.  A VirtualMachineError can be
+  // thrown by the runtime if, say, threads aren't available.  In this
+  // case finalizers simply won't run.
+  try
+    {
+      using namespace gnu::gcj::runtime;
+      FinalizerThread *ft = new FinalizerThread ();
+      ft->start ();
+    }
+  catch (java::lang::VirtualMachineError *ignore)
+    {
+    }
 
   return 0;
 }
Index: gnu/gcj/runtime/FinalizerThread.java
===================================================================
RCS file: FinalizerThread.java
diff -N FinalizerThread.java
--- /dev/null	Tue May  5 13:32:27 1998
+++ gnu/gcj/runtime/FinalizerThread.java Fri Oct 5 07:53:42 2001
@@ -0,0 +1,72 @@
+// FinalizerThread.java -- Thread in which finalizers are run.
+
+/* Copyright (C) 2001  Free Software Foundation
+
+   This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
+details.  */
+
+package gnu.gcj.runtime;
+
+/**
+ * @author Tom Tromey <tromey@redhat.com>
+ * @date October 3, 2001
+ */
+public final class FinalizerThread extends Thread
+{
+  // Finalizers must be run in a thread with no Java-visible locks
+  // held.  This qualifies because we don't make the lock visible.
+  // If this is null then that means there is no finalizer thread --
+  // for instance, we could be running on a no-thread system.  In this
+  // case we run finalizers in the caller's thread.
+  private static final Object lock;
+
+  public FinalizerThread ()
+  {
+    super ("LibgcjInternalFinalizerThread");
+    setDaemon (true);
+    // Creating multiple such threads is invalid.
+    if (lock != null)
+      throw new InternalError ("multiple finalizer threads not allowed");
+    lock = new Object ();
+  }
+
+  // This is called by the runtime when a finalizer is ready to be
+  // run.  It simply wakes up the finalizer thread.
+  public static void finalizerReady ()
+  {
+    if (lock == null)
+      Runtime.getRuntime ().runFinalization ();
+    else
+      {
+	synchronized (lock)
+	  {
+	    lock.notify ();
+	  }
+      }
+  }
+
+  public void run ()
+  {
+    // Wait on a lock.  Whenever we wake up, try to invoke the
+    // finalizers.
+    synchronized (lock)
+      {
+	while (true)
+	  {
+	    try
+	      {
+		lock.wait ();
+	      }
+	    catch (InterruptedException _)
+	      {
+		// Just ignore it.  It doesn't hurt to run finalizers
+		// when none are pending.
+	      }
+	    Runtime.getRuntime ().runFinalization ();
+	  }
+      }
+  }
+}
Index: gnu/gcj/runtime/FirstThread.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/gcj/runtime/FirstThread.java,v
retrieving revision 1.9
diff -u -r1.9 FirstThread.java
--- gnu/gcj/runtime/FirstThread.java 2001/08/26 11:30:08 1.9
+++ gnu/gcj/runtime/FirstThread.java 2001/10/05 14:53:42
@@ -1,6 +1,6 @@
 // FirstThread.java - Implementation of very first thread.
 
-/* Copyright (C) 1998, 1999, 2000  Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -33,12 +33,12 @@
     this.args = args;
     this.is_jar = is_jar;
   }
-  
+
   public void run()
   {
     if (is_jar)
       klass_name = getMain(klass_name);
-    
+
     if (klass == null)
       {
         try
@@ -50,7 +50,7 @@
 	    throw new NoClassDefFoundError(klass_name);
 	  }
       }
-    
+
     call_main();
   }
 
Index: include/jvm.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/include/jvm.h,v
retrieving revision 1.41
diff -u -r1.41 jvm.h
--- include/jvm.h 2001/10/02 14:31:45 1.41
+++ include/jvm.h 2001/10/05 14:53:43
@@ -157,6 +157,9 @@
    memory.  */
 void *_Jv_MallocUnchecked (jsize size) __attribute__((__malloc__));
 
+/* Initialize finalizers.  The argument is a function to be called
+   when a finalizer is ready to be run.  */
+void _Jv_GCInitializeFinalizers (void (*notifier) (void));
 /* Run finalizers for objects ready to be finalized..  */
 void _Jv_RunFinalizers (void);
 /* Run all finalizers.  Should be called only before exit.  */


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