From: Ivan Maidanski Date: Wed, 27 Sep 2017 23:06:31 +0000 (+0300) Subject: Support GC_init (and get_stack_base) from non-main thread on FreeBSD X-Git-Tag: v7.6.2~55 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6f57a9df0969aba4fe28fd7ec6f218de0d7f8488;p=gc Support GC_init (and get_stack_base) from non-main thread on FreeBSD (Cherry-pick commits 49d7fe7, 39ca0b5 from 'master' branch.) Issue #180 (bdwgc). Now GC_get_[main_]stack_base uses pthread_attr_get_np() and pthread_attr_getstack() to determine the stack base address. * include/private/gcconfig.h [(FREEBSD && __GLIBC__ || LINUX || PLATFORM_ANDROID) && !NO_PTHREAD_GETATTR_NP] (HAVE_PTHREAD_GETATTR_NP): New macro. * include/private/gcconfig.h [FREEBSD && !__GLIBC__ && !NO_PTHREAD_ATTR_GET_NP] (HAVE_PTHREAD_NP_H, HAVE_PTHREAD_ATTR_GET_NP): Likewise. * os_dep.c [(HAVE_PTHREAD_ATTR_GET_NP || HAVE_PTHREAD_GETATTR_NP) && (THREADS || USE_GET_STACKBASE_FOR_MAIN) && HAVE_PTHREAD_NP_H]: Include pthread_np.h. * os_dep.c [!BEOS && !AMIGA && !OS2 && !MSWIN32 && !MSWINCE && !CYGWIN32 && !GC_OPENBSD_THREADS] (include pthread.h, GC_get_main_stack_base): Check presence of HAVE_PTHREAD_ATTR_GET_NP, HAVE_PTHREAD_GETATTR_NP macros instead of LINUX, PLATFORM_ANDROID, NO_PTHREAD_GETATTR_NP. * os_dep.c [HAVE_PTHREAD_GETATTR_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 [!HAVE_GET_STACK_BASE] (GC_get_stack_base): Check presence of THREADS, HAVE_PTHREAD_ATTR_GET_NP, HAVE_PTHREAD_GETATTR_NP, HAVE_PTHREAD_NP_H macros instead of GC_LINUX_THREADS, PLATFORM_ANDROID, NO_PTHREAD_GETATTR_NP. * os_dep.c [HAVE_PTHREAD_GETATTR_NP && THREADS && !HAVE_GET_STACK_BASE] (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. --- diff --git a/include/private/gcconfig.h b/include/private/gcconfig.h index ebe7298b..df00dfa0 100644 --- a/include/private/gcconfig.h +++ b/include/private/gcconfig.h @@ -3033,6 +3033,17 @@ # define USE_GET_STACKBASE_FOR_MAIN #endif +/* Outline pthread primitives to use in GC_get_[main_]stack_base. */ +#if ((defined(FREEBSD) && defined(__GLIBC__)) /* kFreeBSD */ \ + || defined(LINUX) || defined(PLATFORM_ANDROID)) \ + && !defined(NO_PTHREAD_GETATTR_NP) +# define HAVE_PTHREAD_GETATTR_NP 1 +#elif defined(FREEBSD) && !defined(__GLIBC__) \ + && !defined(NO_PTHREAD_ATTR_GET_NP) +# define HAVE_PTHREAD_NP_H 1 /* requires include pthread_np.h */ +# define HAVE_PTHREAD_ATTR_GET_NP 1 +#endif + #if defined(UNIX_LIKE) && defined(THREADS) && !defined(NO_CANCEL_SAFE) \ && !defined(PLATFORM_ANDROID) /* Make the code cancellation-safe. This basically means that we */ diff --git a/os_dep.c b/os_dep.c index ac809163..a352b1c0 100644 --- a/os_dep.c +++ b/os_dep.c @@ -1182,8 +1182,12 @@ 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(HAVE_PTHREAD_ATTR_GET_NP) || defined(HAVE_PTHREAD_GETATTR_NP)) \ + && (defined(THREADS) || defined(USE_GET_STACKBASE_FOR_MAIN)) # include +# ifdef HAVE_PTHREAD_NP_H +# include /* for pthread_attr_get_np() */ +# endif # elif defined(DARWIN) && !defined(NO_PTHREAD_GET_STACKADDR_NP) /* We could use pthread_get_stackaddr_np even in case of a */ /* single-threaded gclib (there is no -lpthread on Darwin). */ @@ -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(HAVE_PTHREAD_ATTR_GET_NP) \ + || defined(HAVE_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 HAVE_PTHREAD_ATTR_GET_NP + if (pthread_attr_init(&attr) == 0 + && (pthread_attr_get_np(pthread_self(), &attr) == 0 + ? TRUE : (pthread_attr_destroy(&attr), FALSE))) +# else /* HAVE_PTHREAD_GETATTR_NP */ + 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,11 +1280,12 @@ 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(HAVE_PTHREAD_ATTR_GET_NP) || defined(HAVE_PTHREAD_GETATTR_NP)) \ + && defined(THREADS) && !defined(HAVE_GET_STACK_BASE) # include - /* extern int pthread_getattr_np(pthread_t, pthread_attr_t *); */ +# ifdef HAVE_PTHREAD_NP_H +# include +# endif GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *b) { @@ -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 HAVE_PTHREAD_ATTR_GET_NP + 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 /* HAVE_PTHREAD_GETATTR_NP */ + 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"); } @@ -1321,7 +1344,7 @@ GC_INNER size_t GC_page_size = 0; return GC_SUCCESS; } # define HAVE_GET_STACK_BASE -#endif /* GC_LINUX_THREADS */ +#endif /* THREADS && (HAVE_PTHREAD_ATTR_GET_NP || HAVE_PTHREAD_GETATTR_NP) */ #if defined(GC_DARWIN_THREADS) && !defined(NO_PTHREAD_GET_STACKADDR_NP) # include