/* src/threads/lock.cpp - lock implementation
- Copyright (C) 1996-2005, 2006, 2007, 2008, 2010
+ Copyright (C) 1996-2011
CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
*******************************************************************************/
#if defined(ENABLE_GC_BOEHM)
-static void lock_record_finalizer(void *object, void *p);
+static void lock_record_finalizer(java_handle_t *object, void *p);
#endif
static lock_record_t *lock_hashtable_get(java_handle_t* o)
#if defined(ENABLE_GC_BOEHM)
/* register new finalizer to clean up the lock record */
- GC_finalization_proc ofinal = 0;
- GC_REGISTER_FINALIZER_UNREACHABLE(LLNI_DIRECT(o), lock_record_finalizer, 0, &ofinal, 0);
-
- /* There was a finalizer -- reinstall it. We do not want to disrupt the
- normal finalizer operation. We hold the monitor on this object, so
- this is thread-safe. */
- if (ofinal)
- GC_REGISTER_FINALIZER_NO_ORDER(LLNI_DIRECT(o), ofinal, 0, 0, 0);
+ Finalizer::attach_custom_finalizer(o, lock_record_finalizer, 0);
#endif
/* enter it in the hashtable */
return lr;
}
-/* lock_schedule_lockrecord_removal ********************************************
-
- Gives the locking system a chance to schedule the removal of an unused lock
- record. This function is called after an object's finalizer has run.
-
- IN:
- o....the object which has been finalized
-
-*******************************************************************************/
-
-#if defined(ENABLE_GC_BOEHM)
-void lock_schedule_lockrecord_removal(java_handle_t *o)
-{
- Lockword lockword(*lock_lockword_get(o));
- if (!lockword.is_fat_lock())
- /* there is no lock record */
- return;
-
- /* register new finalizer to clean up the lock record */
- GC_REGISTER_FINALIZER_UNREACHABLE(LLNI_DIRECT(o), lock_record_finalizer, 0, 0, 0);
-}
-#endif
-
-
/* lock_hashtable_remove *******************************************************
Remove the lock record for the given object from the hashtable
*******************************************************************************/
-static void lock_record_finalizer(void *object, void *p)
+static void lock_record_finalizer(java_handle_t *o, void *p)
{
- java_handle_t *o;
+#if !defined(NDEBUG)
classinfo *c;
- o = (java_handle_t *) object;
-
-#if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
- /* XXX this is only a dirty hack to make Boehm work with handles */
-
- o = LLNI_WRAP((java_object_t *) o);
-#endif
-
LLNI_class_get(o, c);
-#if !defined(NDEBUG)
if (opt_DebugFinalizer) {
log_start();
- log_print("[finalizer lockrecord: o=%p p=%p class=", object, p);
+ log_print("[finalizer lockrecord: o=%p p=%p class=", o, p);
class_print(c);
log_print("]");
log_finish();
-/* src/vm/finalizer.c - finalizer linked list and thread
+/* src/vm/finalizer.cpp - finalizer linked list and thread
- Copyright (C) 1996-2005, 2006, 2007, 2008
+ Copyright (C) 1996-2011
CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/jit/asmpart.h"
+#include "finalizer.hpp"
+
+#include <map>
+
+#if defined(ENABLE_GC_BOEHM)
+# include "mm/boehm-gc/include/gc.h"
+#endif
/* global variables ***********************************************************/
static Condition *finalizer_thread_cond;
#endif
-#if defined(__cplusplus)
extern "C" {
-#endif
/* finalizer_init **************************************************************
exceptions_clear_exception();
#if defined(ENABLE_GC_BOEHM)
- lock_schedule_lockrecord_removal(h);
+ Finalizer::reinstall_custom_finalizer(h);
#endif
}
-#if defined(__cplusplus)
+}
+
+#if defined(ENABLE_GC_BOEHM)
+
+struct FinalizerData {
+ Finalizer::FinalizerFunc f;
+ void *data;
+ FinalizerData(Finalizer::FinalizerFunc f, void *data): f(f), data(data) { }
+};
+
+Mutex final_mutex;
+// final_map contains registered custom finalizers for a given Java
+// object. Must be accessed with held final_mutex.
+std::multimap<java_handle_t *, FinalizerData> final_map;
+
+static void custom_finalizer_handler(void *object, void *data)
+{
+ typedef std::multimap<java_handle_t *, FinalizerData>::iterator MI;
+ java_handle_t *hdl = (java_handle_t *) object;
+ MutexLocker l(final_mutex);
+ MI it_first = final_map.lower_bound(hdl), it = it_first;
+ assert(it->first == hdl);
+ for (; it->first == hdl; ++it) {
+ final_mutex.unlock();
+ it->second.f(hdl, it->second.data);
+ final_mutex.lock();
+ }
+ final_map.erase(it_first, it);
+}
+
+/* attach_custom_finalizer *****************************************************
+
+ Register a custom handler that is run when the object becomes
+ unreachable. This is intended for internal cleanup actions. If the
+ handler already exists, it is not registered again, and its data
+ pointer is returned.
+
+*******************************************************************************/
+
+void *Finalizer::attach_custom_finalizer(java_handle_t *h, Finalizer::FinalizerFunc f, void *data)
+{
+ MutexLocker l(final_mutex);
+
+ GC_finalization_proc ofinal = 0;
+ void *odata = 0;
+
+ GC_REGISTER_FINALIZER_UNREACHABLE(LLNI_DIRECT(h), custom_finalizer_handler, 0, &ofinal, &odata);
+
+ /* There was a finalizer -- reinstall it. We do not want to
+ disrupt the normal finalizer operation. This is thread-safe
+ because the other finalizer is only installed at object
+ creation time. */
+ if (ofinal && ofinal != custom_finalizer_handler)
+ GC_REGISTER_FINALIZER_NO_ORDER(LLNI_DIRECT(h), ofinal, odata, 0, 0);
+
+ typedef std::multimap<java_handle_t *, FinalizerData>::iterator MI;
+ std::pair<MI, MI> r = final_map.equal_range(h);
+ for (MI it = r.first; it != r.second; ++it)
+ if (it->second.f == f)
+ return it->second.data;
+ final_map.insert(r.first, std::make_pair(h, FinalizerData(f, data)));
+ return data;
+}
+
+/* reinstall_custom_finalizer **************************************************
+
+ Arranges for the custom finalizers to be called after the Java
+ finalizer, possibly much later, because the object needs to become
+ unreachable.
+
+*******************************************************************************/
+
+void Finalizer::reinstall_custom_finalizer(java_handle_t *h)
+{
+ MutexLocker l(final_mutex);
+ std::multimap<java_handle_t *, FinalizerData>::iterator it = final_map.find(h);
+ if (it == final_map.end())
+ return;
+
+ GC_REGISTER_FINALIZER_UNREACHABLE(LLNI_DIRECT(h), custom_finalizer_handler, 0, 0, 0);
}
#endif
* Emacs will automagically detect them.
* ---------------------------------------------------------------------
* Local variables:
- * mode: c
+ * mode: c++
* indent-tabs-mode: t
* c-basic-offset: 4
* tab-width: 4