go/src/runtime/cgo/gcc_android_arm.c
Elias Naur 0476c7a7b5 runtime/cgo: raise the thread-local storage slot search limit on Android
On Android, the thread local offset is found by looping through memory
starting at the TLS base address. The search is limited to
PTHREAD_KEYS_MAX, but issue 19472 made it clear that in some cases, the
slot is located further from the TLS base.

The limit is merely a sanity check in case our assumptions about the
thread-local storage layout are wrong, so this CL raises it to 384, which
is enough for the test case in issue 19472.

Fixes #19472

Change-Id: I89d1db3e9739d3a7fff5548ae487a7483c0a278a
Reviewed-on: https://go-review.googlesource.com/38636
Run-TryBot: Elias Naur <elias.naur@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2017-03-27 08:56:08 +00:00

43 lines
1.2 KiB
C

// Copyright 2014 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 <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <sys/limits.h>
#include "libcgo.h"
#define magic1 (0x23581321U)
// inittls allocates a thread-local storage slot for g.
//
// It finds the first available slot using pthread_key_create and uses
// it as the offset value for runtime.tlsg.
static void
inittls(void **tlsg, void **tlsbase)
{
pthread_key_t k;
int i, err;
err = pthread_key_create(&k, nil);
if(err != 0) {
fatalf("pthread_key_create failed: %d", err);
}
pthread_setspecific(k, (void*)magic1);
// If thread local slots are laid out as we expect, our magic word will
// be located at some low offset from tlsbase. However, just in case something went
// wrong, the search is limited to sensible offsets. PTHREAD_KEYS_MAX was the
// original limit, but issue 19472 made a higher limit necessary.
for (i=0; i<384; i++) {
if (*(tlsbase+i) == (void*)magic1) {
*tlsg = (void*)(i*sizeof(void *));
pthread_setspecific(k, 0);
return;
}
}
fatalf("could not find pthread key");
}
void (*x_cgo_inittls)(void **tlsg, void **tlsbase) = inittls;