From 95963e6294ce3e2e700dea4055fb62b73f23aa95 Mon Sep 17 00:00:00 2001 From: Russ Cox <rsc@golang.org> Date: Thu, 16 Jun 2011 11:10:31 -0400 Subject: [PATCH] runtime/cgo: fix for OS X 10.7 Correct a few error messages (libcgo -> runtime/cgo) and delete old nacl_386.c file too. Fixes #1657. R=iant CC=golang-dev https://golang.org/cl/4603057 --- src/pkg/runtime/cgo/darwin_386.c | 72 +++++++++++++++--------------- src/pkg/runtime/cgo/darwin_amd64.c | 65 +++++++++++---------------- src/pkg/runtime/cgo/nacl_386.c | 19 -------- src/pkg/runtime/cgo/util.c | 2 +- 4 files changed, 64 insertions(+), 94 deletions(-) delete mode 100644 src/pkg/runtime/cgo/nacl_386.c diff --git a/src/pkg/runtime/cgo/darwin_386.c b/src/pkg/runtime/cgo/darwin_386.c index 4fc7eb4e0a..13184f3217 100644 --- a/src/pkg/runtime/cgo/darwin_386.c +++ b/src/pkg/runtime/cgo/darwin_386.c @@ -8,11 +8,13 @@ static void* threadentry(void*); static pthread_key_t k1, k2; +#define magic1 (0x23581321U) + static void inittls(void) { uint32 x, y; - pthread_key_t tofree[16], k; + pthread_key_t tofree[128], k; int i, ntofree; int havek1, havek2; @@ -35,9 +37,8 @@ inittls(void) * 0x48+4*0x108 = 0x468 and 0x48+4*0x109 = 0x46c. * * The linker and runtime hard-code these constant offsets - * from %gs where we expect to find m and g. The code - * below verifies that the constants are correct once it has - * obtained the keys. Known to ../cmd/8l/obj.c:/468 + * from %gs where we expect to find m and g. + * Known to ../cmd/8l/obj.c:/468 * and to ../pkg/runtime/darwin/386/sys.s:/468 * * This is truly disgusting and a bit fragile, but taking care @@ -48,55 +49,54 @@ inittls(void) * require an extra instruction and memory reference in * every stack growth prolog and would also require * rewriting the code that 8c generates for extern registers. + * + * Things get more disgusting on OS X 10.7 Lion. + * The 0x48 base mentioned above is the offset of the tsd + * array within the per-thread structure on Leopard and Snow Leopard. + * On Lion, the base moved a little, so while the math above + * still applies, the base is different. Thus, we cannot + * look for specific key values if we want to build binaries + * that run on both systems. Instead, forget about the + * specific key values and just allocate and initialize per-thread + * storage until we find a key that writes to the memory location + * we want. Then keep that key. */ havek1 = 0; havek2 = 0; ntofree = 0; while(!havek1 || !havek2) { if(pthread_key_create(&k, nil) < 0) { - fprintf(stderr, "libcgo: pthread_key_create failed\n"); + fprintf(stderr, "runtime/cgo: pthread_key_create failed\n"); abort(); } - if(k == 0x108) { + pthread_setspecific(k, (void*)magic1); + asm volatile("movl %%gs:0x468, %0" : "=r"(x)); + asm volatile("movl %%gs:0x46c, %0" : "=r"(y)); + if(x == magic1) { havek1 = 1; k1 = k; - continue; - } - if(k == 0x109) { + } else if(y == magic1) { havek2 = 1; k2 = k; - continue; + } else { + if(ntofree >= nelem(tofree)) { + fprintf(stderr, "runtime/cgo: could not obtain pthread_keys\n"); + fprintf(stderr, "\ttried"); + for(i=0; i<ntofree; i++) + fprintf(stderr, " %#x", (unsigned)tofree[i]); + fprintf(stderr, "\n"); + abort(); + } + tofree[ntofree++] = k; } - if(ntofree >= nelem(tofree)) { - fprintf(stderr, "libcgo: could not obtain pthread_keys\n"); - fprintf(stderr, "\twanted 0x108 and 0x109\n"); - fprintf(stderr, "\tgot"); - for(i=0; i<ntofree; i++) - fprintf(stderr, " %#lx", tofree[i]); - fprintf(stderr, "\n"); - abort(); - } - tofree[ntofree++] = k; + pthread_setspecific(k, 0); } - for(i=0; i<ntofree; i++) - pthread_key_delete(tofree[i]); - /* - * We got the keys we wanted. Make sure that we observe - * updates to k1 at 0x468, to verify that the TLS array - * offset from %gs hasn't changed. + * We got the keys we wanted. Free the others. */ - pthread_setspecific(k1, (void*)0x12345678); - asm volatile("movl %%gs:0x468, %0" : "=r"(x)); - - pthread_setspecific(k1, (void*)0x87654321); - asm volatile("movl %%gs:0x468, %0" : "=r"(y)); - - if(x != 0x12345678 || y != 0x87654321) { - printf("libcgo: thread-local storage %#lx not at %%gs:0x468 - x=%#x y=%#x\n", k1, x, y); - abort(); - } + for(i=0; i<ntofree; i++) + pthread_key_delete(tofree[i]); } static void diff --git a/src/pkg/runtime/cgo/darwin_amd64.c b/src/pkg/runtime/cgo/darwin_amd64.c index 253a1b252c..38cd80a6f9 100644 --- a/src/pkg/runtime/cgo/darwin_amd64.c +++ b/src/pkg/runtime/cgo/darwin_amd64.c @@ -8,24 +8,25 @@ static void* threadentry(void*); static pthread_key_t k1, k2; +#define magic1 (0x23581321345589ULL) + static void inittls(void) { uint64 x, y; - pthread_key_t tofree[16], k; + pthread_key_t tofree[128], k; int i, ntofree; int havek1, havek2; /* * Same logic, code as darwin_386.c:/inittls, except that words - * are 8 bytes long now, and the thread-local storage starts at 0x60. - * So the offsets are + * are 8 bytes long now, and the thread-local storage starts + * at 0x60 on Leopard / Snow Leopard. So the offsets are * 0x60+8*0x108 = 0x8a0 and 0x60+8*0x109 = 0x8a8. * * The linker and runtime hard-code these constant offsets - * from %gs where we expect to find m and g. The code - * below verifies that the constants are correct once it has - * obtained the keys. Known to ../cmd/6l/obj.c:/8a0 + * from %gs where we expect to find m and g. + * Known to ../cmd/6l/obj.c:/8a0 * and to ../pkg/runtime/darwin/amd64/sys.s:/8a0 * * As disgusting as on the 386; same justification. @@ -35,49 +36,37 @@ inittls(void) ntofree = 0; while(!havek1 || !havek2) { if(pthread_key_create(&k, nil) < 0) { - fprintf(stderr, "libcgo: pthread_key_create failed\n"); + fprintf(stderr, "runtime/cgo: pthread_key_create failed\n"); abort(); } - if(k == 0x108) { + pthread_setspecific(k, (void*)magic1); + asm volatile("movq %%gs:0x8a0, %0" : "=r"(x)); + asm volatile("movq %%gs:0x8a8, %0" : "=r"(y)); + if(x == magic1) { havek1 = 1; k1 = k; - continue; - } - if(k == 0x109) { + } else if(y == magic1) { havek2 = 1; k2 = k; - continue; - } - if(ntofree >= nelem(tofree)) { - fprintf(stderr, "libcgo: could not obtain pthread_keys\n"); - fprintf(stderr, "\twanted 0x108 and 0x109\n"); - fprintf(stderr, "\tgot"); - for(i=0; i<ntofree; i++) - fprintf(stderr, " %#x", (unsigned)tofree[i]); - fprintf(stderr, "\n"); - abort(); + } else { + if(ntofree >= nelem(tofree)) { + fprintf(stderr, "runtime/cgo: could not obtain pthread_keys\n"); + fprintf(stderr, "\ttried"); + for(i=0; i<ntofree; i++) + fprintf(stderr, " %#x", (unsigned)tofree[i]); + fprintf(stderr, "\n"); + abort(); + } + tofree[ntofree++] = k; } - tofree[ntofree++] = k; + pthread_setspecific(k, 0); } - for(i=0; i<ntofree; i++) - pthread_key_delete(tofree[i]); - /* - * We got the keys we wanted. Make sure that we observe - * updates to k1 at 0x8a0, to verify that the TLS array - * offset from %gs hasn't changed. + * We got the keys we wanted. Free the others. */ - pthread_setspecific(k1, (void*)0x123456789abcdef0ULL); - asm volatile("movq %%gs:0x8a0, %0" : "=r"(x)); - - pthread_setspecific(k2, (void*)0x0fedcba987654321); - asm volatile("movq %%gs:0x8a8, %0" : "=r"(y)); - - if(x != 0x123456789abcdef0ULL || y != 0x0fedcba987654321) { - printf("libcgo: thread-local storage %#x not at %%gs:0x8a0 - x=%#llx y=%#llx\n", (unsigned)k1, x, y); - abort(); - } + for(i=0; i<ntofree; i++) + pthread_key_delete(tofree[i]); } void diff --git a/src/pkg/runtime/cgo/nacl_386.c b/src/pkg/runtime/cgo/nacl_386.c deleted file mode 100644 index e556c433ce..0000000000 --- a/src/pkg/runtime/cgo/nacl_386.c +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#include "libcgo.h" - -static void -xinitcgo(void) -{ -} - -void (*initcgo)(void) = xinitcgo; - -void -libcgo_sys_thread_start(ThreadStart *ts) -{ - // unimplemented - *(int*)0 = 0; -} diff --git a/src/pkg/runtime/cgo/util.c b/src/pkg/runtime/cgo/util.c index 0eff19aa6d..9d96521f53 100644 --- a/src/pkg/runtime/cgo/util.c +++ b/src/pkg/runtime/cgo/util.c @@ -40,7 +40,7 @@ xlibcgo_thread_start(ThreadStart *arg) /* Make our own copy that can persist after we return. */ ts = malloc(sizeof *ts); if(ts == nil) { - fprintf(stderr, "libcgo: out of memory in thread_start\n"); + fprintf(stderr, "runtime/cgo: out of memory in thread_start\n"); abort(); } *ts = *arg; -- 2.30.9