]> granicus.if.org Git - gc/commitdiff
Use heap-allocated memory for local mark stack of non-marker thread
authorIvan Maidanski <ivmai@mail.ru>
Tue, 1 Aug 2017 22:13:37 +0000 (01:13 +0300)
committerIvan Maidanski <ivmai@mail.ru>
Wed, 2 Aug 2017 07:32:17 +0000 (10:32 +0300)
Issue #159 (bdwgc).

The memory is allocated using GET_MEM to avoid to make sure that
it is not accidentally scanned by the collector.

* include/private/gcconfig.h [!PARALLEL_MARK && THREADS]
(MIN_STACK_SIZE): Do not define.
* include/private/gcconfig.h [PARALLEL_MARK] (MIN_STACK_SIZE): Add
comment.
* mark.c [PARALLEL_MARK] (main_local_mark_stack): New static variable.
* mark.c [PARALLEL_MARK] (GC_wait_for_markers_init): Declare bytes_to_get
local variable; allocate local mark stack (using GET_MEM) and set
main_local_mark_stack (if not yet allocated by the parent process).
* mark [PARALLEL_MARK] (GC_do_parallel_mark): Remove local_mark_stack
huge local variable; use main_local_mark_stack instead of
local_mark_stack.
* pthread_support.c [GC_ASSERTIONS] (WRAP_FUNC(pthread_create)): Use
hard-coded value (65536) instead of MIN_STACK_SIZE in GC_ASSERT.
* tests/test.c [GC_PTHREADS && DEFAULT_STACK_MAYBE_SMALL]
(fork_a_thread): Do not set stack size for the created threads.
* tests/test.c [GC_PTHREADS] (main): Do not check
DEFAULT_STACK_MAYBE_SMALL.

include/private/gcconfig.h
mark.c
pthread_support.c
tests/test.c

index 39bc96a48e4fb088e5768b3596cd5952f9482ea2..8f7f42fcb319f41504037052527458570516b973 100644 (file)
 #endif
 
 #ifdef PARALLEL_MARK
+  /* The minimum stack size for a marker thread. */
 # define MIN_STACK_SIZE (8 * HBLKSIZE * sizeof(word))
-#elif defined(THREADS)
-# define MIN_STACK_SIZE 65536
 #endif
 
 #if defined(UNIX_LIKE) && defined(THREADS) && !defined(NO_CANCEL_SAFE) \
diff --git a/mark.c b/mark.c
index 17fb511e275062e5dd27f83faa88efeb8d25d928..179cfb579753f4b0e1c9fe6b23acc587d6f4944f 100644 (file)
--- a/mark.c
+++ b/mark.c
@@ -929,6 +929,8 @@ STATIC unsigned GC_active_count = 0;    /* Number of active helpers.    */
 
 GC_INNER word GC_mark_no = 0;
 
+static mse *main_local_mark_stack;
+
 #ifdef LINT2
 # define LOCAL_MARK_STACK_SIZE (HBLKSIZE / 8)
 #else
@@ -947,6 +949,21 @@ GC_INNER void GC_wait_for_markers_init(void)
   if (GC_markers_m1 == 0)
     return;
 
+  /* Allocate the local mark stack for the thread that holds GC lock.   */
+# ifndef CAN_HANDLE_FORK
+    GC_ASSERT(NULL == main_local_mark_stack);
+# else
+    if (NULL == main_local_mark_stack)
+# endif
+  {
+    size_t bytes_to_get =
+                ROUNDUP_PAGESIZE_IF_MMAP(LOCAL_MARK_STACK_SIZE * sizeof(mse));
+    main_local_mark_stack = (mse *)GET_MEM(bytes_to_get);
+    if (NULL == main_local_mark_stack)
+      ABORT("Insufficient memory for main local_mark_stack");
+    GC_add_to_our_memory((ptr_t)main_local_mark_stack, bytes_to_get);
+  }
+
   /* Reuse marker lock and builders count to synchronize        */
   /* marker threads startup.                                    */
   GC_acquire_mark_lock();
@@ -1188,9 +1205,6 @@ STATIC void GC_mark_local(mse *local_mark_stack, int id)
 /* empty.                                       */
 STATIC void GC_do_parallel_mark(void)
 {
-    mse local_mark_stack[LOCAL_MARK_STACK_SIZE];
-                /* Note: local_mark_stack is quite big (up to 128 KiB). */
-
     GC_acquire_mark_lock();
     GC_ASSERT(I_HOLD_LOCK());
     /* This could be a GC_ASSERT, but it seems safer to keep it on      */
@@ -1206,7 +1220,7 @@ STATIC void GC_do_parallel_mark(void)
     GC_release_mark_lock();
     GC_notify_all_marker();
         /* Wake up potential helpers.   */
-    GC_mark_local(local_mark_stack, 0);
+    GC_mark_local(main_local_mark_stack, 0);
     GC_acquire_mark_lock();
     GC_help_wanted = FALSE;
     /* Done; clean up.  */
index 6f80a41caaa31a5334a90361b5c80b16c17679cf..cb31824a419efc41776a7c386e2dbba537e07cfb 100644 (file)
@@ -1789,7 +1789,7 @@ GC_API int WRAP_FUNC(pthread_create)(pthread_t *new_thread,
 #           endif
             stack_size = 1000000;
         }
-        GC_ASSERT(stack_size >= MIN_STACK_SIZE);
+        GC_ASSERT(stack_size >= 65536);
         /* Our threads may need to do some work for the GC.     */
         /* Ridiculously small threads won't work, and they      */
         /* probably wouldn't work anyway.                       */
index 4604ca776d022b0aa962d23864176dee6e76ab66..be7d57a57ac3293e5f38a7c5e444d5e4ca0a66c4 100644 (file)
@@ -537,25 +537,8 @@ void check_marks_int_list(sexpr x)
     {
       pthread_t t;
       int code;
-#     ifdef DEFAULT_STACK_MAYBE_SMALL
-        pthread_attr_t attr;
 
-        code = pthread_attr_init(&attr);
-        if (code != 0) {
-          GC_printf("pthread_attr_init failed, error=%d\n", code);
-          FAIL;
-        }
-        code = pthread_attr_setstacksize(&attr, MIN_STACK_SIZE);
-        if (code != 0) {
-          GC_printf("pthread_attr_setstacksize(MIN_STACK_SIZE) failed,"
-                    " error=%d\n", code);
-          FAIL;
-        }
-        code = pthread_create(&t, &attr, tiny_reverse_test, 0);
-        (void)pthread_attr_destroy(&attr);
-#     else
-        code = pthread_create(&t, NULL, tiny_reverse_test, 0);
-#     endif
+      code = pthread_create(&t, NULL, tiny_reverse_test, 0);
       if (code != 0) {
         GC_printf("Small thread creation failed %d\n", code);
         FAIL;
@@ -2201,7 +2184,7 @@ int main(void)
     }
 #   if defined(GC_IRIX_THREADS) || defined(GC_FREEBSD_THREADS) \
         || defined(GC_DARWIN_THREADS) || defined(GC_AIX_THREADS) \
-        || defined(GC_OPENBSD_THREADS) || defined(DEFAULT_STACK_MAYBE_SMALL)
+        || defined(GC_OPENBSD_THREADS)
         if ((code = pthread_attr_setstacksize(&attr, 1000 * 1024)) != 0) {
           GC_printf("pthread_attr_setstacksize failed, error=%d\n", code);
           FAIL;