]> Cypherpunks repositories - gostls13.git/commitdiff
runtime/cgo: use free TLS slot on Android Q
authorElias Naur <mail@eliasnaur.com>
Fri, 29 Mar 2019 11:13:02 +0000 (12:13 +0100)
committerElias Naur <mail@eliasnaur.com>
Fri, 29 Mar 2019 17:16:54 +0000 (17:16 +0000)
Android assumes pthread tls keys correspond to some offset from the
TLS base. This is about to change in a future version of Android.
Fortunately, Android Q leaves a slot open for use to use, TLS_SLOT_APP.

Fixes #29674

Change-Id: Id6ba19afacdfed9b262453714715435e2544185f
Reviewed-on: https://go-review.googlesource.com/c/go/+/170117
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/runtime/cgo/gcc_android.c

index 44bd550a7ce9160731f18f15527b8cb0afef4dd3..a626cd06818691ed6bfdeb5761eeffeae9c5e91e 100644 (file)
@@ -5,6 +5,7 @@
 #include <stdarg.h>
 #include <android/log.h>
 #include <pthread.h>
+#include <dlfcn.h>
 #include "libcgo.h"
 
 void
@@ -34,6 +35,9 @@ fatalf(const char* format, ...)
 // Truncated to a different magic value on 32-bit; that's ok.
 #define magic1 (0x23581321345589ULL)
 
+// From https://android.googlesource.com/platform/bionic/+/refs/heads/master/libc/private/bionic_asm_tls.h#69.
+#define TLS_SLOT_APP 2
+
 // inittls allocates a thread-local storage slot for g.
 //
 // It finds the first available slot using pthread_key_create and uses
@@ -43,6 +47,22 @@ inittls(void **tlsg, void **tlsbase)
 {
        pthread_key_t k;
        int i, err;
+       void *handle, *get_ver;
+
+       // Check for Android Q where we can use the free TLS_SLOT_APP slot.
+       handle = dlopen(NULL, RTLD_LAZY);
+       if (handle == NULL) {
+               fatalf("inittls: failed to dlopen main program");
+               return;
+       }
+       // android_get_device_api_level is introduced in Android Q, so its mere presence
+       // is enough.
+       get_ver = dlsym(handle, "android_get_device_api_level");
+       dlclose(handle);
+       if (get_ver != NULL) {
+               *tlsg = (void *)(TLS_SLOT_APP*sizeof(void *));
+               return;
+       }
 
        err = pthread_key_create(&k, nil);
        if(err != 0) {
@@ -60,7 +80,7 @@ inittls(void **tlsg, void **tlsbase)
                        return;
                }
        }
-       fatalf("could not find pthread key");
+       fatalf("inittls: could not find pthread key");
 }
 
 void (*x_cgo_inittls)(void **tlsg, void **tlsbase) = inittls;