summaryrefslogtreecommitdiff
path: root/libgo
diff options
context:
space:
mode:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2012-06-07 00:55:20 +0000
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2012-06-07 00:55:20 +0000
commita01550acfc47492bf127b83b92b14471b020041b (patch)
treedf3ab096fe1132c25cca2f3c18db4ac5133baf52 /libgo
parentfd4076faf16b0590f625bb827449ee78b1b2d99c (diff)
downloadgcc-a01550acfc47492bf127b83b92b14471b020041b.tar.gz
runtime: Use dl_iterate_phdr to get TLS size.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@188290 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgo')
-rw-r--r--libgo/config.h.in6
-rwxr-xr-xlibgo/configure2
-rw-r--r--libgo/configure.ac2
-rw-r--r--libgo/runtime/proc.c89
4 files changed, 63 insertions, 36 deletions
diff --git a/libgo/config.h.in b/libgo/config.h.in
index eb81c9ee715..0aef2ce7b07 100644
--- a/libgo/config.h.in
+++ b/libgo/config.h.in
@@ -21,6 +21,9 @@
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
+/* Define to 1 if you have the `dl_iterate_phdr' function. */
+#undef HAVE_DL_ITERATE_PHDR
+
/* Define to 1 if you have the `epoll_create1' function. */
#undef HAVE_EPOLL_CREATE1
@@ -286,9 +289,6 @@
/* Define to 1 if you have the `wait4' function. */
#undef HAVE_WAIT4
-/* Define to 1 if you have the `_dl_get_tls_static_info' function. */
-#undef HAVE__DL_GET_TLS_STATIC_INFO
-
/* Define if the C++ compiler is configured for setjmp/longjmp exceptions. */
#undef LIBGO_SJLJ_EXCEPTIONS
diff --git a/libgo/configure b/libgo/configure
index be9e510ce25..dc85ccfa9db 100755
--- a/libgo/configure
+++ b/libgo/configure
@@ -14584,7 +14584,7 @@ else
fi
-for ac_func in strerror_r strsignal wait4 mincore setenv _dl_get_tls_static_info
+for ac_func in strerror_r strsignal wait4 mincore setenv dl_iterate_phdr
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
diff --git a/libgo/configure.ac b/libgo/configure.ac
index 03909d6046c..0c0dbdd46a9 100644
--- a/libgo/configure.ac
+++ b/libgo/configure.ac
@@ -481,7 +481,7 @@ fi
AM_CONDITIONAL(HAVE_SYS_MMAN_H, test "$ac_cv_header_sys_mman_h" = yes)
-AC_CHECK_FUNCS(strerror_r strsignal wait4 mincore setenv _dl_get_tls_static_info)
+AC_CHECK_FUNCS(strerror_r strsignal wait4 mincore setenv dl_iterate_phdr)
AM_CONDITIONAL(HAVE_STRERROR_R, test "$ac_cv_func_strerror_r" = yes)
AM_CONDITIONAL(HAVE_WAIT4, test "$ac_cv_func_wait4" = yes)
diff --git a/libgo/runtime/proc.c b/libgo/runtime/proc.c
index 1a605a1921c..e3befbec996 100644
--- a/libgo/runtime/proc.c
+++ b/libgo/runtime/proc.c
@@ -8,6 +8,11 @@
#include <unistd.h>
#include "config.h"
+
+#ifdef HAVE_DL_ITERATE_PHDR
+#include <link.h>
+#endif
+
#include "runtime.h"
#include "arch.h"
#include "defs.h"
@@ -36,12 +41,12 @@ extern void __splitstack_block_signals_context (void *context[10], int *,
#endif
+#ifndef PTHREAD_STACK_MIN
+# define PTHREAD_STACK_MIN 8192
+#endif
+
#if defined(USING_SPLIT_STACK) && defined(LINKER_SUPPORTS_SPLIT_STACK)
-# ifdef PTHREAD_STACK_MIN
-# define StackMin PTHREAD_STACK_MIN
-# else
-# define StackMin 8192
-# endif
+# define StackMin PTHREAD_STACK_MIN
#else
# define StackMin 2 * 1024 * 1024
#endif
@@ -138,6 +143,46 @@ runtime_m(void)
int32 runtime_gcwaiting;
+// The static TLS size. See runtime_newm.
+static int tlssize;
+
+#ifdef HAVE_DL_ITERATE_PHDR
+
+// Called via dl_iterate_phdr.
+
+static int
+addtls(struct dl_phdr_info* info, size_t size __attribute__ ((unused)), void *data)
+{
+ size_t *total = (size_t *)data;
+ unsigned int i;
+
+ for(i = 0; i < info->dlpi_phnum; ++i) {
+ if(info->dlpi_phdr[i].p_type == PT_TLS)
+ *total += info->dlpi_phdr[i].p_memsz;
+ }
+ return 0;
+}
+
+// Set the total TLS size.
+
+static void
+inittlssize()
+{
+ size_t total = 0;
+
+ dl_iterate_phdr(addtls, (void *)&total);
+ tlssize = total;
+}
+
+#else
+
+static void
+inittlssize()
+{
+}
+
+#endif
+
// Go scheduler
//
// The go scheduler's job is to match ready-to-run goroutines (`g's)
@@ -393,6 +438,7 @@ runtime_schedinit(void)
g->m = m;
initcontext();
+ inittlssize();
m->nomemprof++;
runtime_mallocinit();
@@ -1116,34 +1162,15 @@ runtime_newm(void)
if(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
runtime_throw("pthread_attr_setdetachstate");
-#ifndef PTHREAD_STACK_MIN
-#define PTHREAD_STACK_MIN 8192
-#endif
-
stacksize = PTHREAD_STACK_MIN;
-#if 0
-#ifdef HAVE__DL_GET_TLS_STATIC_INFO
- {
- /* On GNU/Linux the static TLS size is taken out of
- the stack size, and we get an error or a crash if
- there is not enough stack space left. Add it back
- in if we can, in case the program uses a lot of TLS
- space. */
-#ifndef internal_function
-#ifdef __i386__
-#define internal_function __attribute__ ((regparm (3), stdcall))
-#else
-#define internal_function
-#endif
-#endif
- extern void _dl_get_tls_static_info(size_t*, size_t*) internal_function;
- size_t tlssize, tlsalign;
- _dl_get_tls_static_info(&tlssize, &tlsalign);
- stacksize += tlssize;
- }
-#endif
-#endif
+ // With glibc before version 2.16 the static TLS size is taken
+ // out of the stack size, and we get an error or a crash if
+ // there is not enough stack space left. Add it back in if we
+ // can, in case the program uses a lot of TLS space. FIXME:
+ // This can be disabled in glibc 2.16 and later, if the bug is
+ // indeed fixed then.
+ stacksize += tlssize;
if(pthread_attr_setstacksize(&attr, stacksize) != 0)
runtime_throw("pthread_attr_setstacksize");