diff options
author | Ian Lance Taylor <iant@golang.org> | 2013-03-27 13:27:35 -0700 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2013-03-27 13:27:35 -0700 |
commit | e74e168c8c2607d247dbfbc19f5c17e7906d154e (patch) | |
tree | 2f25e4bebec553130cad87443d74a9d319c0d8e8 /misc | |
parent | f5dffe94e2f6e735aaafae43ad0d51965953a471 (diff) | |
download | go-e74e168c8c2607d247dbfbc19f5c17e7906d154e.tar.gz |
cmd/ld: emit TLS relocations during external linking
This CL was written by rsc. I just tweaked 8l.
This CL adds TLS relocation to the ELF .o file we write during external linking,
so that the host linker (gcc) can decide the final location of m and g.
Similar relocations are not necessary on OS X because we use an alternate
program start-time mechanism to acquire thread-local storage.
Similar relocations are not necessary on ARM or Plan 9 or Windows
because external linking mode is not yet supported on those systems.
On almost all ELF systems, the references we use are like %fs:-0x4 or %gs:-0x4,
which we write in 6a/8a as -0x4(FS) or -0x4(GS). On Linux/ELF, however,
Xen's lack of support for this mode forced us long ago to use a two-instruction
sequence: first we load %gs:0x0 into a register r, and then we use -0x4(r).
(The ELF program loader arranges that %gs:0x0 contains a regular pointer to
that same memory location.) In order to relocate those -0x4(r) references,
the linker must know where they are. This CL adds the equivalent notation
-0x4(r)(GS*1) for this purpose: it assembles to the same encoding as -0x4(r)
but the (GS*1) indicates to the linker that this is one of those thread-local
references that needs relocation.
Thanks to Elias Naur for reminding me about this missing piece and
also for writing the test.
R=r
CC=golang-dev
https://codereview.appspot.com/7891047
Diffstat (limited to 'misc')
-rw-r--r-- | misc/cgo/testtls/tls.go | 28 | ||||
-rw-r--r-- | misc/cgo/testtls/tls_test.go | 13 | ||||
-rw-r--r-- | misc/cgo/testtls/tls_unix.c | 19 |
3 files changed, 60 insertions, 0 deletions
diff --git a/misc/cgo/testtls/tls.go b/misc/cgo/testtls/tls.go new file mode 100644 index 000000000..a9546a61c --- /dev/null +++ b/misc/cgo/testtls/tls.go @@ -0,0 +1,28 @@ +// Copyright 2013 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. + +package cgotlstest + +// #include <pthread.h> +// extern void setTLS(int); +// extern int getTLS(); +import "C" + +import ( + "runtime" + "testing" +) + +func testTLS(t *testing.T) { + var keyVal C.int = 1234 + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + C.setTLS(C.int(keyVal)) + storedVal := C.getTLS() + + if storedVal != keyVal { + t.Fatalf("stored %d want %d", storedVal, keyVal) + } +} diff --git a/misc/cgo/testtls/tls_test.go b/misc/cgo/testtls/tls_test.go new file mode 100644 index 000000000..3076c2d59 --- /dev/null +++ b/misc/cgo/testtls/tls_test.go @@ -0,0 +1,13 @@ +// Copyright 2013 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. + +// +build !windows + +package cgotlstest + +import "testing" + +func TestTLS(t *testing.T) { + testTLS(t) +} diff --git a/misc/cgo/testtls/tls_unix.c b/misc/cgo/testtls/tls_unix.c new file mode 100644 index 000000000..545951631 --- /dev/null +++ b/misc/cgo/testtls/tls_unix.c @@ -0,0 +1,19 @@ +// Copyright 2013 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> + +static __thread int tls; + +void +setTLS(int v) +{ + tls = v; +} + +int +getTLS() +{ + return tls; +} |