#include "vm/types.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "native/llni.h"
#include "toolbox/list.hpp"
#include "vm/exceptions.hpp"
-#include "vm/finalizer.h"
+#include "vm/finalizer.hpp"
#include "vm/global.h"
#include "vm/options.h"
#include "vm/string.hpp"
#if defined(ENABLE_GC_BOEHM)
/* register new finalizer to clean up the lock record */
- GC_REGISTER_FINALIZER(LLNI_DIRECT(o), lock_record_finalizer, 0, 0, 0);
+ 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(LLNI_DIRECT(o), ofinal, 0, 0, 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 *******************************************************
}
#endif
- /* check for a finalizer function */
-
- if (c->finalizer != NULL)
- finalizer_run(object, p);
-
/* remove the lock-record entry from the hashtable and free it */
lock_hashtable_remove(THREADOBJECT, o);
}
+/* sable_flc_waiting ***********************************************************
+
+ Enqueue the current thread on another thread's FLC list. The function
+ blocks until the lock has been inflated by the owning thread.
+
+ The algorithm used to be an almost literal copy from SableVM. The
+ superfluous list traversal in the waiting loop has been removed since,
+ though.
+
+ IN:
+ lockword.....the object's lockword as seen at the first locking attempt
+ t............the current thread
+ o............the object of which to enter the monitor
+
+*******************************************************************************/
+
static void sable_flc_waiting(Lockword *lockword, threadobject *t, java_handle_t *o)
{
int32_t index;
t_other->flc_tail = t;
f = t_other->flc_tail;
- for (;;)
+ // The other thread will clear flc_object.
+ while (t->flc_object)
{
- threadobject *current;
+ // We are not cleared yet -- the other thread cannot have seen
+ // the FLC bit yet.
+ assert(t_other->flc_bit);
// Wait until another thread sees the flc bit and notifies
// us of unlocking.
t->flc_cond->wait(t_other->flc_lock);
-
- if (t_other->flc_tail != f)
- break;
- /* Traverse FLC list looking if we're still there */
- current = t_other->flc_list;
- while (current && current != t)
- current = current->flc_next;
- if (!current)
- /* not in list anymore, can stop waiting */
- break;
-
- /* We are still in the list -- the other thread cannot have seen
- the FLC bit yet */
- assert(t_other->flc_bit);
}
- t->flc_object = NULL; /* for garbage collector? */
t->flc_next = NULL;
}
else
t_other->flc_lock->unlock();
}
+/* notify_flc_waiters **********************************************************
+
+ Traverse the thread's FLC list and inflate all corresponding locks. Notify
+ the associated threads as well.
+
+ IN:
+ t............the current thread
+ o............the object currently being unlocked
+
+*******************************************************************************/
+
static void notify_flc_waiters(threadobject *t, java_handle_t *o)
{
threadobject *current;
// Wake the waiting threads.
current->flc_cond->broadcast();
+ current->flc_object = NULL;
current = current->flc_next;
}