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]

Patch: finalizer thread - please comment


Java requires that finalizers be run in their own thread.  Actually I
think it requires that a finalizer be run when no user-visible locks
are held; this amounts to the same thing.

The appended patch implements this.  It builds and checks fine on x86
RH Linux 6.2.

If I check this in it will break the no-thread build.  What should we
do about this?  I can think of a few things.

One idea would be to lazily create the new thread insie
FinalizerThread itself.  Then we could catch an exception when the
thread is made (and change no-threads.cc to throw an exception) and
just run finalizers in the main thread (or not run them at all, which
might be more correct).

There are other choices too.  For instance we could simply deprecate
the no-thread build.

Other ideas?

Tom

Index: ChangeLog
from  Tom Tromey  <tromey@redhat.com>
	* 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/04 14:40:45
@@ -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/04 14:40:48
@@ -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: 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/04 14:40:48
@@ -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: 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 Thu Oct 4 07:40:49 2001
@@ -0,0 +1,60 @@
+// 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.
+  private static final Object lock = new Object ();
+
+  public FinalizerThread ()
+  {
+    super ();
+    setDaemon (true);
+  }
+
+  // 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 ()
+  {
+    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/04 14:40:49
@@ -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,15 @@
     this.args = args;
     this.is_jar = is_jar;
   }
-  
+
   public void run()
   {
+    // Start the GC finalizer thread.
+    new FinalizerThread ().start ();
+
     if (is_jar)
       klass_name = getMain(klass_name);
-    
+
     if (klass == null)
       {
         try
@@ -50,7 +53,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/04 14:40:50
@@ -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]