New API standalone functions to acquire and release the allocator lock
authorIvan Maidanski <ivmai@mail.ru>
Thu, 30 May 2019 19:53:12 +0000 (22:53 +0300)
committerIvan Maidanski <ivmai@mail.ru>
Thu, 30 May 2019 19:53:12 +0000 (22:53 +0300)
Issue #282 (bdwgc).

Public GC_alloc_lock() and GC_alloc_unlock() are introduced to simplify
dealing with the GC lock compared to GC_call_with_alloc_lock().

* include/gc.h [GC_THREADS] (GC_alloc_lock, GC_alloc_unlock): Declare
new API function.
* include/gc.h [!GC_THREADS] (GC_alloc_lock, GC_alloc_unlock): Define
as a no-op macro.
* misc.c [THREADS] (GC_alloc_lock, GC_alloc_unlock): Define API
function.
* tests/test.c (reachable_objs_count_enumerator): Remove function.
* tests/test.c (check_heap_stats): Call GC_alloc_lock(); call
GC_enumerate_reachable_objects_inner() directly; call GC_alloc_unlock().

include/gc.h
misc.c
tests/test.c

index a7164c3..4afcf75 100644 (file)
@@ -1403,6 +1403,18 @@ typedef GC_word GC_hidden_pointer;
 # define REVEAL_POINTER(p) GC_REVEAL_POINTER(p)
 #endif
 
+/* The routines to acquire/release the allocator lock.                  */
+/* The lock is not reentrant.  GC_alloc_unlock() should not be called   */
+/* unless the lock is acquired by the current thread.                   */
+#ifdef GC_THREADS
+  GC_API void GC_CALL GC_alloc_lock(void);
+  GC_API void GC_CALL GC_alloc_unlock(void);
+#else
+  /* No need for real locking if the client is single-threaded.         */
+# define GC_alloc_lock() (void)0
+# define GC_alloc_unlock() (void)0
+#endif /* !GC_THREADS */
+
 typedef void * (GC_CALLBACK * GC_fn_type)(void * /* client_data */);
 GC_API void * GC_CALL GC_call_with_alloc_lock(GC_fn_type /* fn */,
                                 void * /* client_data */) GC_ATTR_NONNULL(1);
diff --git a/misc.c b/misc.c
index 322422f..15570ca 100644 (file)
--- a/misc.c
+++ b/misc.c
@@ -2310,6 +2310,18 @@ GC_API GC_word GC_CALL GC_get_gc_no(void)
     return GC_parallel;
   }
 
+  GC_API void GC_CALL GC_alloc_lock(void)
+  {
+    DCL_LOCK_STATE;
+    LOCK();
+  }
+
+  GC_API void GC_CALL GC_alloc_unlock(void)
+  {
+    /* no DCL_LOCK_STATE */
+    UNLOCK();
+  }
+
   GC_INNER GC_on_thread_event_proc GC_on_thread_event = 0;
 
   GC_API void GC_CALL GC_set_on_thread_event(GC_on_thread_event_proc fn)
index c533800..79c8d4d 100644 (file)
@@ -1648,12 +1648,6 @@ void GC_CALLBACK reachable_objs_counter(void *obj, size_t size,
   (*(unsigned *)pcounter)++;
 }
 
-void * GC_CALLBACK reachable_objs_count_enumerator(void *pcounter)
-{
-  GC_enumerate_reachable_objects_inner(reachable_objs_counter, pcounter);
-  return NULL;
-}
-
 #define NUMBER_ROUND_UP(v, bound) ((((v) + (bound) - 1) / (bound)) * (bound))
 
 void check_heap_stats(void)
@@ -1733,8 +1727,9 @@ void check_heap_stats(void)
           FAIL;
         }
       }
-    (void)GC_call_with_alloc_lock(reachable_objs_count_enumerator,
-                                  &obj_count);
+    GC_alloc_lock();
+    GC_enumerate_reachable_objects_inner(reachable_objs_counter, &obj_count);
+    GC_alloc_unlock();
     GC_printf("Completed %u tests\n", n_tests);
     GC_printf("Allocated %d collectable objects\n", (int)collectable_count);
     GC_printf("Allocated %d uncollectable objects\n",