This patch to libgo includes the TLS size in the requested stack size of
a new thread, if possible.  This relies on the glibc-specific (and
undocumented) _dl_get_tls_static_info call.  This is particularly
necessary when using glibc, because glibc removes the static TLS size
from the requested stack space, and gives an error if there is not
enough space.  That means that a program that has a lot of TLS variables
will fail bizarrely, or worse may simply get a stack overflow
segmentation violation at runtime.  This patch is far from perfect, but
at least works around that problem for such programs.  Bootstrapped and
ran Go testsuite on x86_64-unknown-linux-gnu.  Committed to mainline and
4.7 branch.

Ian

Index: libgo/configure.ac
===================================================================
--- libgo/configure.ac	(revision 187020)
+++ libgo/configure.ac	(working copy)
@@ -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)
+AC_CHECK_FUNCS(strerror_r strsignal wait4 mincore setenv _dl_get_tls_static_info)
 AM_CONDITIONAL(HAVE_STRERROR_R, test "$ac_cv_func_strerror_r" = yes)
 AM_CONDITIONAL(HAVE_WAIT4, test "$ac_cv_func_wait4" = yes)
 
Index: libgo/runtime/proc.c
===================================================================
--- libgo/runtime/proc.c	(revision 187854)
+++ libgo/runtime/proc.c	(working copy)
@@ -1105,6 +1105,7 @@ runtime_newm(void)
 	M *m;
 	pthread_attr_t attr;
 	pthread_t tid;
+	size_t stacksize;
 
 	m = runtime_malloc(sizeof(M));
 	mcommoninit(m);
@@ -1118,7 +1119,31 @@ runtime_newm(void)
 #ifndef PTHREAD_STACK_MIN
 #define PTHREAD_STACK_MIN 8192
 #endif
-	if(pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN) != 0)
+
+	stacksize = PTHREAD_STACK_MIN;
+
+#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
+
+	if(pthread_attr_setstacksize(&attr, stacksize) != 0)
 		runtime_throw("pthread_attr_setstacksize");
 
 	if(pthread_create(&tid, &attr, runtime_mstart, m) != 0)

Reply via email to