aboutsummaryrefslogtreecommitdiff
path: root/libgo/runtime
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2012-02-08 05:30:12 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2012-02-08 05:30:12 +0000
commit7f57843fbebc7b50cfad7cc5bd3459a2d1077035 (patch)
treec2a0810ed549d7918e5361e32b62c078b9961ff3 /libgo/runtime
parent3327318150635df73331b0ebdd7b7bc2628b3b21 (diff)
downloadgcc-7f57843fbebc7b50cfad7cc5bd3459a2d1077035.zip
gcc-7f57843fbebc7b50cfad7cc5bd3459a2d1077035.tar.gz
gcc-7f57843fbebc7b50cfad7cc5bd3459a2d1077035.tar.bz2
runtime: System-specific hack fix for x86_64 Solaris 10.
Fixes problem in which setcontext changes all thread-specific information. From-SVN: r183993
Diffstat (limited to 'libgo/runtime')
-rw-r--r--libgo/runtime/proc.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/libgo/runtime/proc.c b/libgo/runtime/proc.c
index 9225f82..04412bd 100644
--- a/libgo/runtime/proc.c
+++ b/libgo/runtime/proc.c
@@ -60,6 +60,54 @@ G runtime_g0; // idle goroutine for m0
static __thread G *g;
static __thread M *m;
+#ifndef SETCONTEXT_CLOBBERS_TLS
+
+static inline void
+initcontext(void)
+{
+}
+
+static inline void
+fixcontext(ucontext_t *c __attribute__ ((unused)))
+{
+}
+
+# else
+
+# if defined(__x86_64__) && defined(__sun__)
+
+// x86_64 Solaris 10 and 11 have a bug: setcontext switches the %fs
+// register to that of the thread which called getcontext. The effect
+// is that the address of all __thread variables changes. This bug
+// also affects pthread_self() and pthread_getspecific. We work
+// around it by clobbering the context field directly to keep %fs the
+// same.
+
+static __thread greg_t fs;
+
+static inline void
+initcontext(void)
+{
+ ucontext_t c;
+
+ getcontext(&c);
+ fs = c.uc_mcontext.gregs[REG_FSBASE];
+}
+
+static inline void
+fixcontext(ucontext_t* c)
+{
+ c->uc_mcontext.gregs[REG_FSBASE] = fs;
+}
+
+# else
+
+# error unknown case for SETCONTEXT_CLOBBERS_TLS
+
+# endif
+
+#endif
+
// We can not always refer to the TLS variables directly. The
// compiler will call tls_get_addr to get the address of the variable,
// and it may hold it in a register across a call to schedule. When
@@ -248,7 +296,9 @@ runtime_gogo(G* newg)
#endif
g = newg;
newg->fromgogo = true;
+ fixcontext(&newg->context);
setcontext(&newg->context);
+ runtime_throw("gogo setcontext returned");
}
// Save context and call fn passing g as a parameter. This is like
@@ -287,6 +337,7 @@ runtime_mcall(void (*pfn)(G*))
m->g0->entry = (byte*)pfn;
m->g0->param = g;
g = m->g0;
+ fixcontext(&m->g0->context);
setcontext(&m->g0->context);
runtime_throw("runtime: mcall function returned");
}
@@ -312,6 +363,8 @@ runtime_schedinit(void)
m->curg = g;
g->m = m;
+ initcontext();
+
m->nomemprof++;
runtime_mallocinit();
mcommoninit(m);
@@ -844,6 +897,8 @@ runtime_mstart(void* mp)
m = (M*)mp;
g = m->g0;
+ initcontext();
+
g->entry = nil;
g->param = nil;