]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: use fixed TLS offsets on darwin/amd64 and darwin/386
authorKeith Randall <khr@golang.org>
Mon, 9 Apr 2018 23:00:54 +0000 (16:00 -0700)
committerKeith Randall <khr@golang.org>
Tue, 10 Apr 2018 14:28:39 +0000 (14:28 +0000)
Fixes #23617

Note that this CL does not affect darwin/arm and darwin/arm64,
still TBD what, if anything, needs to be done for those.

Change-Id: Ie1ee02a9f4d4d1fb9cd5dc432d900f926cc157db
Reviewed-on: https://go-review.googlesource.com/105975
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/cmd/link/internal/ld/sym.go
src/runtime/cgo/gcc_darwin_386.c
src/runtime/cgo/gcc_darwin_amd64.c
src/runtime/sys_darwin_386.s
src/runtime/sys_darwin_amd64.s

index 6f019de8cc072cc9c272e8a123056c938bf0b30c..7bc57eff8d931117c2d186537f63308ac1729ce6 100644 (file)
@@ -113,24 +113,30 @@ func (ctxt *Link) computeTLSOffset() {
 
                /*
                 * OS X system constants - offset from 0(GS) to our TLS.
-                * Explained in src/runtime/cgo/gcc_darwin_*.c.
                 */
        case objabi.Hdarwin:
                switch ctxt.Arch.Family {
                default:
                        log.Fatalf("unknown thread-local storage offset for darwin/%s", ctxt.Arch.Name)
 
-               case sys.ARM:
-                       ctxt.Tlsoffset = 0 // dummy value, not needed
+                       /*
+                        * For x86, Apple has reserved a slot in the TLS for Go. See issue 23617.
+                        * That slot is at offset 0x30 on amd64, and 0x18 on 386.
+                        * The slot will hold the G pointer.
+                        * These constants should match those in runtime/sys_darwin_{386,amd64}.s
+                        * and runtime/cgo/gcc_darwin_{386,amd64}.c.
+                        */
+               case sys.I386:
+                       ctxt.Tlsoffset = 0x18
 
                case sys.AMD64:
-                       ctxt.Tlsoffset = 0x8a0
+                       ctxt.Tlsoffset = 0x30
 
-               case sys.ARM64:
+               case sys.ARM:
                        ctxt.Tlsoffset = 0 // dummy value, not needed
 
-               case sys.I386:
-                       ctxt.Tlsoffset = 0x468
+               case sys.ARM64:
+                       ctxt.Tlsoffset = 0 // dummy value, not needed
                }
        }
 
index 7d3c55cd56e423bd15cbb6c5d61ab9edb21ca592..c947f23073e197cc0093569c337cdde6d8674999 100644 (file)
@@ -9,89 +9,6 @@
 #include "libcgo_unix.h"
 
 static void* threadentry(void*);
-static pthread_key_t k1;
-
-#define magic1 (0x23581321U)
-
-static void
-inittls(void)
-{
-       uint32 x;
-       pthread_key_t tofree[128], k;
-       int i, ntofree;
-
-       /*
-        * Allocate thread-local storage slot for g.
-        * The key numbers start at 0x100, and we expect to be
-        * one of the early calls to pthread_key_create, so we
-        * should be able to get a pretty low number.
-        *
-        * In Darwin/386 pthreads, %gs points at the thread
-        * structure, and each key is an index into the thread-local
-        * storage array that begins at offset 0x48 within in that structure.
-        * It may happen that we are not quite the first function to try
-        * to allocate thread-local storage keys, so instead of depending
-        * on getting 0x100, we try for 0x108, allocating keys until
-        * we get the one we want and then freeing the ones we didn't want.
-        *
-        * Thus the final offset to use in %gs references is
-        * 0x48+4*0x108 = 0x468.
-        *
-        * The linker and runtime hard-code this constant offset
-        * from %gs where we expect to find g.
-        * Known to src/cmd/link/internal/ld/sym.go:/0x468
-        * and to src/runtime/sys_darwin_386.s:/0x468
-        *
-        * This is truly disgusting and a bit fragile, but taking care
-        * of it here protects the rest of the system from damage.
-        * The alternative would be to use a global variable that
-        * held the offset and refer to that variable each time we
-        * need a %gs variable (g).  That approach would
-        * 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.
-        */
-       ntofree = 0;
-       for(;;) {
-               if(pthread_key_create(&k, nil) != 0) {
-                       fprintf(stderr, "runtime/cgo: pthread_key_create failed\n");
-                       abort();
-               }
-               pthread_setspecific(k, (void*)magic1);
-               asm volatile("movl %%gs:0x468, %0" : "=r"(x));
-               pthread_setspecific(k, 0);
-               if(x == magic1) {
-                       k1 = k;
-                       break;
-               }
-               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;
-       }
-
-       /*
-        * We got the key we wanted.  Free the others.
-        */
-       for(i=0; i<ntofree; i++)
-               pthread_key_delete(tofree[i]);
-}
 
 void
 x_cgo_init(G *g)
@@ -103,8 +20,6 @@ x_cgo_init(G *g)
        pthread_attr_getstacksize(&attr, &size);
        g->stacklo = (uintptr)&attr - size + 4096;
        pthread_attr_destroy(&attr);
-
-       inittls();
 }
 
 
@@ -142,10 +57,9 @@ threadentry(void *v)
        ts = *(ThreadStart*)v;
        free(v);
 
-       if (pthread_setspecific(k1, (void*)ts.g) != 0) {
-               fprintf(stderr, "runtime/cgo: pthread_setspecific failed\n");
-               abort();
-       }
+       // Move the g pointer into the slot reserved in thread local storage.
+       // Constant must match the one in cmd/link/internal/ld/sym.go.
+       asm volatile("movq %0, %%gs:0x18" :: "r"(ts.g));
 
        crosscall_386(ts.fn);
        return nil;
index c57608c6757649014cb2797a7ec8f6b2330fc2eb..51410d50269dafd1d5ee4c34294d08b1984a48eb 100644 (file)
@@ -9,60 +9,6 @@
 #include "libcgo_unix.h"
 
 static void* threadentry(void*);
-static pthread_key_t k1;
-
-#define magic1 (0x23581321345589ULL)
-
-static void
-inittls(void)
-{
-       uint64 x;
-       pthread_key_t tofree[128], k;
-       int i, ntofree;
-
-       /*
-        * Same logic, code as darwin_386.c:/inittls, except that words
-        * are 8 bytes long now, and the thread-local storage starts
-        * at 0x60 on Leopard / Snow Leopard. So the offset is
-        * 0x60+8*0x108 = 0x8a0.
-        *
-        * The linker and runtime hard-code this constant offset
-        * from %gs where we expect to find g.
-        * Known to src/cmd/link/internal/ld/sym.go:/0x8a0
-        * and to src/runtime/sys_darwin_amd64.s:/0x8a0
-        *
-        * As disgusting as on the 386; same justification.
-        */
-       ntofree = 0;
-       for(;;) {
-               if(pthread_key_create(&k, nil) != 0) {
-                       fprintf(stderr, "runtime/cgo: pthread_key_create failed\n");
-                       abort();
-               }
-               pthread_setspecific(k, (void*)magic1);
-               asm volatile("movq %%gs:0x8a0, %0" : "=r"(x));
-               pthread_setspecific(k, 0);
-               if(x == magic1) {
-                       k1 = k;
-                       break;
-               }
-               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;
-       }
-
-       /*
-        * We got the key we wanted.  Free the others.
-        */
-       for(i=0; i<ntofree; i++)
-               pthread_key_delete(tofree[i]);
-}
 
 void
 x_cgo_init(G *g)
@@ -74,8 +20,6 @@ x_cgo_init(G *g)
        pthread_attr_getstacksize(&attr, &size);
        g->stacklo = (uintptr)&attr - size + 4096;
        pthread_attr_destroy(&attr);
-
-       inittls();
 }
 
 
@@ -113,10 +57,9 @@ threadentry(void *v)
        ts = *(ThreadStart*)v;
        free(v);
 
-       if (pthread_setspecific(k1, (void*)ts.g) != 0) {
-               fprintf(stderr, "runtime/cgo: pthread_setspecific failed\n");
-               abort();
-       }
+       // Move the g pointer into the slot reserved in thread local storage.
+       // Constant must match the one in cmd/link/internal/ld/sym.go.
+       asm volatile("movq %0, %%gs:0x30" :: "r"(ts.g));
 
        crosscall_amd64(ts.fn);
        return nil;
index 3b5ed44724d1982961af5127e516cb8db28d92ac..3831ba5a795fe123cd687708dd8c3ae04eaf4773 100644 (file)
@@ -525,15 +525,14 @@ TEXT runtime·setldt(SB),NOSPLIT,$32
         * When linking against the system libraries,
         * we use its pthread_create and let it set up %gs
         * for us.  When we do that, the private storage
-        * we get is not at 0(GS) but at 0x468(GS).
-        * 8l rewrites 0(TLS) into 0x468(GS) for us.
+        * we get is not at 0(GS) but at 0x18(GS).
+        * The linker rewrites 0(TLS) into 0x18(GS) for us.
         * To accommodate that rewrite, we translate the
-        * address and limit here so that 0x468(GS) maps to 0(address).
+        * address here so that 0x18(GS) maps to 0(address).
         *
-        * See cgo/gcc_darwin_386.c:/468 for the derivation
-        * of the constant.
+        * Constant must match the one in cmd/link/internal/ld/sym.go.
         */
-       SUBL    $0x468, BX
+       SUBL    $0x18, BX
 
        /*
         * Must set up as USER_CTHREAD segment because
index ab57843dfaf8d02f1a3ef7352e8c85c00ebbab29..7a4f8ba39a0ffe88231d52f1c79ab5176fe02f85 100644 (file)
@@ -569,11 +569,10 @@ TEXT runtime·mach_semaphore_signal_all(SB),NOSPLIT,$0
 // set tls base to DI
 TEXT runtime·settls(SB),NOSPLIT,$32
        /*
-       * Same as in sys_darwin_386.s:/ugliness, different constant.
-       * See cgo/gcc_darwin_amd64.c for the derivation
-       * of the constant.
-       */
-       SUBQ $0x8a0, DI
+        * Same as in sys_darwin_386.s, but a different constant.
+        * Constant must match the one in cmd/link/internal/ld/sym.go.
+        */
+       SUBQ $0x30, DI
 
        MOVL    $(0x3000000+3), AX      // thread_fast_set_cthread_self - machdep call #3
        SYSCALL