* src/mm/cacao-gc/gc.c (gc_global_lock): Removed obsolete global lock.
authorMichael Starzinger <michi@complang.tuwien.ac.at>
Sat, 13 Oct 2007 11:16:56 +0000 (13:16 +0200)
committerMichael Starzinger <michi@complang.tuwien.ac.at>
Sat, 13 Oct 2007 11:16:56 +0000 (13:16 +0200)
(gc_collect): Use GC mutex as global gc lock.
(gc_reference_register_intern, gc_reference_unregister_intern): Use GC mutex to
lock the reference lists.

* src/mm/cacao-gc/gc.h (GC_MUTEX_LOCK, GC_MUTEX_UNLOCK): Added macros.

* src/threads/native/threads.c [ENABLE_GC_CACAO] (mutex_gc): Added GC mutex.
[ENABLE_GC_CACAO] (threads_mutex_gc_lock, threads_mutex_gc_unlock): Implemented.

* src/threads/threads-common.h [ENABLE_GC_CACAO]
(threads_mutex_gc_lock, threads_mutex_gc_unlock): Added prototypes.

src/mm/cacao-gc/gc.c
src/mm/cacao-gc/gc.h
src/threads/native/threads.c
src/threads/threads-common.h

index 61490282d522f78b0c6d5b0552e5fdc2fee31613..dc4487c1a060cc406069062a8c756790739ff73e 100644 (file)
@@ -56,10 +56,6 @@ bool gc_notify_finalizer;
 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;
@@ -101,12 +97,6 @@ void gc_init(u4 heapmaxsize, u4 heapstartsize)
        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))
@@ -124,8 +114,12 @@ void gc_init(u4 heapmaxsize, u4 heapstartsize)
 
 /* 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)
 
 *******************************************************************************/
 
@@ -133,57 +127,81 @@ static void gc_reference_register_intern(list_t *list, java_object_t **ref, int3
 {
        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)
@@ -223,7 +241,7 @@ void gc_collect(s4 level)
 #endif
 
        /* enter the global gc lock */
-       LOCK_MONITOR_ENTER(gc_global_lock);
+       GC_MUTEX_LOCK;
 
        /* remember start of dump memory area */
        dumpsize = dump_size();
@@ -367,7 +385,7 @@ void gc_collect(s4 level)
     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();
index b8eeab691437ef0a4734a675ff666ee06bb6ad7e..68fbefd59c7befe0c0340f57edc977234ad59183 100644 (file)
@@ -135,6 +135,17 @@ struct list_gcref_entry_t {
 };
 
 
+/* Global GC mutext stuff *****************************************************/
+
+#if defined(ENABLE_THREADS)
+# define GC_MUTEX_LOCK   threads_mutex_gc_lock()
+# define GC_MUTEX_UNLOCK threads_mutex_gc_unlock()
+#else
+# define GC_MUTEX_LOCK
+# define GC_MUTEX_UNLOCK
+#endif
+
+
 /* No-Thread specific stuff ***************************************************/
 
 #if defined(ENABLE_THREADS)
index f4ba1a098708f3a22ce6c04d64b9c8e0482e6da3..f64af9fec18536acbbabc9a864ca641a5ce523f7 100644 (file)
@@ -235,6 +235,11 @@ static pthread_mutex_t mutex_threads_list;
 /* 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;
@@ -786,6 +791,12 @@ void threads_impl_preinit(void)
        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);
@@ -831,6 +842,37 @@ void threads_list_unlock(void)
 }
 
 
+/* 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.
index 3cea52547ab049b548479f225eea472d64f6df50..f744afbbd2a1e641291ac17638a012c3a5b8886b 100644 (file)
@@ -151,6 +151,11 @@ void          threads_impl_preinit(void);
 void          threads_list_lock(void);
 void          threads_list_unlock(void);
 
+#if defined(ENABLE_GC_CACAO)
+void          threads_mutex_gc_lock(void);
+void          threads_mutex_gc_unlock(void);
+#endif
+
 void          threads_mutex_join_lock(void);
 void          threads_mutex_join_unlock(void);