list_t *gc_reflist_strong;
list_t *gc_reflist_weak;
-#if defined(ENABLE_THREADS)
-java_object_t *gc_global_lock;
-#endif
-
#if !defined(ENABLE_THREADS)
executionstate_t *_no_threads_executionstate;
sourcestate_t *_no_threads_sourcestate;
gc_reflist_strong = list_create(OFFSET(list_gcref_entry_t, linkage));
gc_reflist_weak = list_create(OFFSET(list_gcref_entry_t, linkage));
-#if defined(ENABLE_THREADS)
- /* create global gc lock object */
- gc_global_lock = NEW(java_object_t);
- lock_init_object_lock(gc_global_lock);
-#endif
-
/* region for uncollectable objects */
heap_region_sys = NEW(regioninfo_t);
if (!region_create(heap_region_sys, GC_SYS_SIZE))
/* gc_reference_register *******************************************************
- Register an external reference which points onto the Heap and keeps
- objects alive (strong reference).
+ Register an external reference which points onto the Heap. The
+ reference needs to be cleared (set to NULL) when registering and
+ has to be set after it has been registered (to avoid a race condition).
+
+ STRONG REFERENCE: gets updated and keeps objects alive
+ WEAK REFERENCE: only gets updated (or maybe cleared)
*******************************************************************************/
{
list_gcref_entry_t *re;
+ /* the global GC lock also guards the reference lists */
+ GC_MUTEX_LOCK;
+
GC_LOG2( printf("Registering Reference at %p\n", (void *) ref); );
/* the reference needs to be registered before it is set, so make sure the
reference is not yet set */
GC_ASSERT(*ref == NULL);
+#if !defined(NDEBUG)
+ /* check if this reference is already registered */
+ for (re = list_first_unsynced(list); re != NULL; re = list_next_unsynced(list, re)) {
+ if (re->ref == ref)
+ vm_abort("gc_reference_register_intern: reference already registered");
+ }
+#endif
+
+ /* create a new reference entry */
re = NEW(list_gcref_entry_t);
- re->ref = ref;
+ re->ref = ref;
#if !defined(NDEBUG)
- re->reftype = reftype;
+ re->reftype = reftype;
#endif
- list_add_last(list, re);
+ /* add the entry to the given list */
+ list_add_last_unsynced(list, re);
+
+ /* the global GC lock also guards the reference lists */
+ GC_MUTEX_UNLOCK;
+}
+
+void gc_reference_register(java_object_t **ref, int32_t reftype)
+{
+ gc_reference_register_intern(gc_reflist_strong, ref, reftype);
}
+void gc_weakreference_register(java_object_t **ref, int32_t reftype)
+{
+ gc_reference_register_intern(gc_reflist_weak, ref, reftype);
+}
+
+
+/* gc_reference_unregister *****************************************************
+
+ Unregister a previously registered external reference.
+
+*******************************************************************************/
+
static void gc_reference_unregister_intern(list_t *list, java_object_t **ref)
{
list_gcref_entry_t *re;
+ /* the global GC lock also guards the reference lists */
+ GC_MUTEX_LOCK;
+
GC_LOG2( printf("Un-Registering Reference at %p\n", (void *) ref); );
- for (re = list_first(list); re != NULL; re = list_next(list, re)) {
+ /* search for the appropriate reference entry */
+ for (re = list_first_unsynced(list); re != NULL; re = list_next_unsynced(list, re)) {
if (re->ref == ref) {
- list_remove(list, re);
+ /* remove the entry from the given list */
+ list_remove_unsynced(list, re);
+ /* free the reference entry */
FREE(re, list_gcref_entry_t);
break;
}
}
- assert(re != NULL);
-}
-
-void gc_reference_register(java_object_t **ref, int32_t reftype)
-{
-#if defined(ENABLE_THREADS)
- /* XXX dirty hack because threads_init() not yet called */
- if (THREADOBJECT == NULL) {
- GC_LOG( dolog("GC: Unable to register Reference!"); );
- return;
- }
-#endif
-
- gc_reference_register_intern(gc_reflist_strong, ref, reftype);
-}
+ vm_abort("gc_reference_unregister_intern: reference not found");
-void gc_weakreference_register(java_object_t **ref, int32_t reftype)
-{
- gc_reference_register_intern(gc_reflist_weak, ref, reftype);
+ /* the global GC lock also guards the reference lists */
+ GC_MUTEX_UNLOCK;
}
void gc_reference_unregister(java_object_t **ref)
#endif
/* enter the global gc lock */
- LOCK_MONITOR_ENTER(gc_global_lock);
+ GC_MUTEX_LOCK;
/* remember start of dump memory area */
dumpsize = dump_size();
dump_release(dumpsize);
/* leave the global gc lock */
- LOCK_MONITOR_EXIT(gc_global_lock);
+ GC_MUTEX_UNLOCK;
/* XXX move this to an appropriate place */
lock_hashtable_cleanup();
/* global mutex for stop-the-world */
static pthread_mutex_t stopworldlock;
+#if defined(ENABLE_GC_CACAO)
+/* global mutex for the GC */
+static pthread_mutex_t mutex_gc;
+#endif
+
/* global mutex and condition for joining threads on exit */
static pthread_mutex_t mutex_join;
static pthread_cond_t cond_join;
pthread_mutex_init(&mutex_join, NULL);
pthread_cond_init(&cond_join, NULL);
+#if defined(ENABLE_GC_CACAO)
+ /* initialize the GC mutext */
+
+ pthread_mutex_init(&mutex_gc, NULL);
+#endif
+
/* initialize the threads-list mutex */
pthread_mutex_init(&mutex_threads_list, NULL);
}
+/* threads_mutex_gc_lock *******************************************************
+
+ Enter the global GC mutex.
+
+*******************************************************************************/
+
+#if defined(ENABLE_GC_CACAO)
+void threads_mutex_gc_lock(void)
+{
+ if (pthread_mutex_lock(&mutex_gc) != 0)
+ vm_abort("threads_mutex_gc_lock: pthread_mutex_lock failed: %s",
+ strerror(errno));
+}
+#endif
+
+
+/* threads_mutex_gc_unlock *****************************************************
+
+ Leave the global GC mutex.
+
+*******************************************************************************/
+
+#if defined(ENABLE_GC_CACAO)
+void threads_mutex_gc_unlock(void)
+{
+ if (pthread_mutex_unlock(&mutex_gc) != 0)
+ vm_abort("threads_mutex_gc_unlock: pthread_mutex_unlock failed: %s",
+ strerror(errno));
+}
+#endif
+
/* threads_mutex_join_lock *****************************************************
Enter the join mutex.