Support GC_init (and get_stack_base) from non-main thread on FreeBSD
authorIvan Maidanski <ivmai@mail.ru>
Wed, 27 Sep 2017 23:06:31 +0000 (02:06 +0300)
committerIvan Maidanski <ivmai@mail.ru>
Wed, 27 Sep 2017 23:06:31 +0000 (02:06 +0300)
Issue #180 (bdwgc).

Now GC_get_[main_]stack_base uses pthread_attr_get_np() and
pthread_attr_getstack() to determine the stack base address.

* os_dep.c [FREEBSD && !NO_PTHREAD_ATTR_GET_NP && (THREADS
|| USE_GET_STACKBASE_FOR_MAIN)]: Include pthread.h and pthread_np.h.
* os_dep.c [FREEBSD && !NO_PTHREAD_ATTR_GET_NP
&& (USE_GET_STACKBASE_FOR_MAIN || THREADS && !REDIRECT_MALLOC)]
(GC_get_main_stack_base): Call pthread_attr_init, pthread_attr_get_np
and pthread_attr_getstack to determine the stack base address of the
current thread (fall back to GC_freebsd_main_stack_base in case of
failure).
* os_dep.c [(GC_FREEBSD_THREADS && !NO_PTHREAD_ATTR_GET_NP]
(GC_get_stack_base): Call pthread_attr_init, pthread_attr_get_np and
pthread_attr_getstack to determine the stack base address of the
current thread.

os_dep.c

index cdd594e..4efd673 100644 (file)
--- a/os_dep.c
+++ b/os_dep.c
@@ -1182,7 +1182,11 @@ GC_INNER size_t GC_page_size = 0;
       && !defined(GC_OPENBSD_THREADS) \
       && (!defined(GC_SOLARIS_THREADS) || defined(_STRICT_STDC))
 
-# if defined(LINUX) && defined(USE_GET_STACKBASE_FOR_MAIN)
+# if defined(FREEBSD) && !defined(NO_PTHREAD_ATTR_GET_NP) \
+     && (defined(THREADS) || defined(USE_GET_STACKBASE_FOR_MAIN))
+#   include <pthread.h>
+#   include <pthread_np.h> /* for pthread_attr_get_np() */
+# elif defined(LINUX) && defined(USE_GET_STACKBASE_FOR_MAIN)
 #   include <pthread.h>
 # elif defined(DARWIN) && !defined(NO_PTHREAD_GET_STACKADDR_NP)
     /* We could use pthread_get_stackaddr_np even in case of a  */
@@ -1195,14 +1199,22 @@ GC_INNER size_t GC_page_size = 0;
   ptr_t GC_get_main_stack_base(void)
   {
     ptr_t result;
-#   if defined(LINUX) && !defined(NO_PTHREAD_GETATTR_NP) \
+#   if ((defined(FREEBSD) && !defined(NO_PTHREAD_ATTR_GET_NP)) \
+        || (defined(LINUX) && !defined(NO_PTHREAD_GETATTR_NP))) \
        && (defined(USE_GET_STACKBASE_FOR_MAIN) \
            || (defined(THREADS) && !defined(REDIRECT_MALLOC)))
       pthread_attr_t attr;
       void *stackaddr;
       size_t size;
 
-      if (pthread_getattr_np(pthread_self(), &attr) == 0) {
+#     ifdef FREEBSD
+        if (pthread_attr_init(&attr) == 0
+            && (pthread_attr_get_np(pthread_self(), &attr) == 0
+                ? TRUE : (pthread_attr_destroy(&attr), FALSE)))
+#     else /* LINUX */
+        if (pthread_getattr_np(pthread_self(), &attr) == 0)
+#     endif
+      {
         if (pthread_attr_getstack(&attr, &stackaddr, &size) == 0
             && stackaddr != NULL) {
           (void)pthread_attr_destroy(&attr);
@@ -1268,8 +1280,9 @@ GC_INNER size_t GC_page_size = 0;
 # define GET_MAIN_STACKBASE_SPECIAL
 #endif /* !AMIGA, !BEOS, !OPENBSD, !OS2, !Windows */
 
-#if (defined(GC_LINUX_THREADS) || defined(PLATFORM_ANDROID)) \
-    && !defined(NO_PTHREAD_GETATTR_NP)
+#if (defined(GC_FREEBSD_THREADS) && !defined(NO_PTHREAD_ATTR_GET_NP)) \
+    || ((defined(GC_LINUX_THREADS) || defined(PLATFORM_ANDROID)) \
+        && !defined(NO_PTHREAD_GETATTR_NP))
 
 # include <pthread.h>
   /* extern int pthread_getattr_np(pthread_t, pthread_attr_t *); */
@@ -1282,10 +1295,20 @@ GC_INNER size_t GC_page_size = 0;
       DCL_LOCK_STATE;
 #   endif
 
-    if (pthread_getattr_np(pthread_self(), &attr) != 0) {
+#   ifdef FREEBSD
+      if (pthread_attr_init(&attr) != 0)
+        ABORT("pthread_attr_init failed");
+      if (pthread_attr_get_np(pthread_self(), &attr) != 0) {
+        WARN("pthread_attr_get_np failed\n", 0);
+        (void)pthread_attr_destroy(&attr);
+        return GC_UNIMPLEMENTED;
+      }
+#   else /* LINUX */
+      if (pthread_getattr_np(pthread_self(), &attr) != 0) {
         WARN("pthread_getattr_np failed\n", 0);
         return GC_UNIMPLEMENTED;
-    }
+      }
+#   endif
     if (pthread_attr_getstack(&attr, &(b -> mem_base), &size) != 0) {
         ABORT("pthread_attr_getstack failed");
     }