diff options
Diffstat (limited to 'libgo/go/runtime')
-rw-r--r-- | libgo/go/runtime/extern.go | 12 | ||||
-rw-r--r-- | libgo/go/runtime/internal/atomic/atomic.c | 237 | ||||
-rw-r--r-- | libgo/go/runtime/internal/atomic/atomic_test.go | 67 | ||||
-rw-r--r-- | libgo/go/runtime/internal/atomic/gccgo.go | 59 | ||||
-rw-r--r-- | libgo/go/runtime/internal/atomic/stubs.go | 33 | ||||
-rw-r--r-- | libgo/go/runtime/internal/sys/intrinsics.go | 77 | ||||
-rw-r--r-- | libgo/go/runtime/internal/sys/intrinsics_test.go | 54 | ||||
-rw-r--r-- | libgo/go/runtime/internal/sys/stubs.go | 11 | ||||
-rw-r--r-- | libgo/go/runtime/internal/sys/sys.go | 15 | ||||
-rw-r--r-- | libgo/go/runtime/pprof/pprof.go | 63 | ||||
-rw-r--r-- | libgo/go/runtime/runtime2.go | 6 |
11 files changed, 627 insertions, 7 deletions
diff --git a/libgo/go/runtime/extern.go b/libgo/go/runtime/extern.go index fbbf56ced70..e0c5aacc55a 100644 --- a/libgo/go/runtime/extern.go +++ b/libgo/go/runtime/extern.go @@ -157,6 +157,8 @@ of the run-time system. */ package runtime +import "runtime/internal/sys" + // Gosched yields the processor, allowing other goroutines to run. It does not // suspend the current goroutine, so execution resumes automatically. func Gosched() @@ -282,23 +284,23 @@ func GOROOT() string { if s != "" { return s } - return defaultGoroot + return sys.DefaultGoroot } // Version returns the Go tree's version string. // It is either the commit hash and date at the time of the build or, // when possible, a release tag like "go1.3". func Version() string { - return theVersion + return sys.TheVersion } // GOOS is the running program's operating system target: // one of darwin, freebsd, linux, and so on. -const GOOS string = theGoos +const GOOS string = sys.GOOS // GOARCH is the running program's architecture target: // 386, amd64, arm, or s390x. -const GOARCH string = theGoarch +const GOARCH string = sys.GOARCH // GCCGOTOOLDIR is the Tool Dir for the gccgo build -const GCCGOTOOLDIR string = theGccgoToolDir +const GCCGOTOOLDIR string = sys.GccgoToolDir diff --git a/libgo/go/runtime/internal/atomic/atomic.c b/libgo/go/runtime/internal/atomic/atomic.c new file mode 100644 index 00000000000..3393fbef44e --- /dev/null +++ b/libgo/go/runtime/internal/atomic/atomic.c @@ -0,0 +1,237 @@ +// Copyright 2016 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 <stdint.h> + +#include "runtime.h" + +uint32_t Load (uint32_t *ptr) + __asm__ (GOSYM_PREFIX "runtime_internal_atomic.Load") + __attribute__ ((no_split_stack)); + +uint32_t +Load (uint32_t *ptr) +{ + return __atomic_load_n (ptr, __ATOMIC_ACQUIRE); +} + +void *Loadp (void *ptr) + __asm__ (GOSYM_PREFIX "runtime_internal_atomic.Loadp") + __attribute__ ((no_split_stack)); + +void * +Loadp (void *ptr) +{ + return __atomic_load_n ((void **) ptr, __ATOMIC_ACQUIRE); +} + +uint64_t Load64 (uint64_t *ptr) + __asm__ (GOSYM_PREFIX "runtime_internal_atomic.Load64") + __attribute__ ((no_split_stack)); + +uint64_t +Load64 (uint64_t *ptr) +{ + return __atomic_load_n (ptr, __ATOMIC_ACQUIRE); +} + +uintptr_t Loaduintptr (uintptr_t *ptr) + __asm__ (GOSYM_PREFIX "runtime_internal_atomic.Loaduintptr") + __attribute__ ((no_split_stack)); + +uintptr_t +Loaduintptr (uintptr_t *ptr) +{ + return __atomic_load_n (ptr, __ATOMIC_ACQUIRE); +} + +uintgo Loaduint (uintgo *ptr) + __asm__ (GOSYM_PREFIX "runtime_internal_atomic.Loaduint") + __attribute__ ((no_split_stack)); + +uintgo +Loaduint (uintgo *ptr) +{ + return __atomic_load_n (ptr, __ATOMIC_ACQUIRE); +} + +int64_t Loadint64 (int64_t *ptr) + __asm__ (GOSYM_PREFIX "runtime_internal_atomic.Loadint64") + __attribute__ ((no_split_stack)); + +int64_t +Loadint64 (int64_t *ptr) +{ + return __atomic_load_n (ptr, __ATOMIC_ACQUIRE); +} + +uint32_t Xadd (uint32_t *ptr, int32_t delta) + __asm__ (GOSYM_PREFIX "runtime_internal_atomic.Xadd") + __attribute__ ((no_split_stack)); + +uint32_t +Xadd (uint32_t *ptr, int32_t delta) +{ + return __atomic_add_fetch (ptr, (uint32_t) delta, __ATOMIC_SEQ_CST); +} + +uint64_t Xadd64 (uint64_t *ptr, int64_t delta) + __asm__ (GOSYM_PREFIX "runtime_internal_atomic.Xadd64") + __attribute__ ((no_split_stack)); + +uint64_t +Xadd64 (uint64_t *ptr, int64_t delta) +{ + return __atomic_add_fetch (ptr, (uint64_t) delta, __ATOMIC_SEQ_CST); +} + +uintptr_t Xadduintptr (uintptr_t *ptr, uintptr_t delta) + __asm__ (GOSYM_PREFIX "runtime_internal_atomic.Xadduintptr") + __attribute__ ((no_split_stack)); + +uintptr_t +Xadduintptr (uintptr_t *ptr, uintptr_t delta) +{ + return __atomic_add_fetch (ptr, delta, __ATOMIC_SEQ_CST); +} + +int64_t Xaddint64 (int64_t *ptr, int64_t delta) + __asm__ (GOSYM_PREFIX "runtime_internal_atomic.Xaddint64") + __attribute__ ((no_split_stack)); + +int64_t +Xaddint64 (int64_t *ptr, int64_t delta) +{ + return __atomic_add_fetch (ptr, delta, __ATOMIC_SEQ_CST); +} + +uint32_t Xchg (uint32_t *ptr, uint32_t new) + __asm__ (GOSYM_PREFIX "runtime_internal_atomic.Xchg") + __attribute__ ((no_split_stack)); + +uint32_t +Xchg (uint32_t *ptr, uint32_t new) +{ + return __atomic_exchange_n (ptr, new, __ATOMIC_SEQ_CST); +} + +uint64_t Xchg64 (uint64_t *ptr, uint64_t new) + __asm__ (GOSYM_PREFIX "runtime_internal_atomic.Xchg64") + __attribute__ ((no_split_stack)); + +uint64_t +Xchg64 (uint64_t *ptr, uint64_t new) +{ + return __atomic_exchange_n (ptr, new, __ATOMIC_SEQ_CST); +} + +uintptr_t Xchguintptr (uintptr_t *ptr, uintptr_t new) + __asm__ (GOSYM_PREFIX "runtime_internal_atomic.Xchguintptr") + __attribute__ ((no_split_stack)); + +uintptr_t +Xchguintptr (uintptr_t *ptr, uintptr_t new) +{ + return __atomic_exchange_n (ptr, new, __ATOMIC_SEQ_CST); +} + +void And8 (uint8_t *ptr, uint8_t val) + __asm__ (GOSYM_PREFIX "runtime_internal_atomic.And8") + __attribute__ ((no_split_stack)); + +void +And8 (uint8_t *ptr, uint8_t val) +{ + __atomic_and_fetch (ptr, val, __ATOMIC_SEQ_CST); +} + +void Or8 (uint8_t *ptr, uint8_t val) + __asm__ (GOSYM_PREFIX "runtime_internal_atomic.Or8") + __attribute__ ((no_split_stack)); + +void +Or8 (uint8_t *ptr, uint8_t val) +{ + __atomic_or_fetch (ptr, val, __ATOMIC_SEQ_CST); +} + +_Bool Cas (uint32_t *ptr, uint32_t old, uint32_t new) + __asm__ (GOSYM_PREFIX "runtime_internal_atomic.Cas") + __attribute__ ((no_split_stack)); + +_Bool +Cas (uint32_t *ptr, uint32_t old, uint32_t new) +{ + return __atomic_compare_exchange_n (ptr, &old, new, false, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED); +} + +_Bool Cas64 (uint64_t *ptr, uint64_t old, uint64_t new) + __asm__ (GOSYM_PREFIX "runtime_internal_atomic.Cas64") + __attribute__ ((no_split_stack)); + +_Bool +Cas64 (uint64_t *ptr, uint64_t old, uint64_t new) +{ + return __atomic_compare_exchange_n (ptr, &old, new, false, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED); +} + +_Bool Casp1 (void **ptr, void *old, void *new) + __asm__ (GOSYM_PREFIX "runtime_internal_atomic.Casp1") + __attribute__ ((no_split_stack)); + +_Bool +Casp1 (void **ptr, void *old, void *new) +{ + return __atomic_compare_exchange_n (ptr, &old, new, false, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED); +} + +_Bool Casuintptr (uintptr_t *ptr, uintptr_t old, uintptr_t new) + __asm__ (GOSYM_PREFIX "runtime_internal_atomic.Casuintptr") + __attribute__ ((no_split_stack)); + +_Bool +Casuintptr (uintptr_t *ptr, uintptr_t old, uintptr_t new) +{ + return __atomic_compare_exchange_n (ptr, &old, new, false, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED); +} + +void Store (uint32_t *ptr, uint32_t val) + __asm__ (GOSYM_PREFIX "runtime_internal_atomic.Store") + __attribute__ ((no_split_stack)); + +void +Store (uint32_t *ptr, uint32_t val) +{ + __atomic_store_n (ptr, val, __ATOMIC_SEQ_CST); +} + +void Store64 (uint64_t *ptr, uint64_t val) + __asm__ (GOSYM_PREFIX "runtime_internal_atomic.Store64") + __attribute__ ((no_split_stack)); + +void +Store64 (uint64_t *ptr, uint64_t val) +{ + __atomic_store_n (ptr, val, __ATOMIC_SEQ_CST); +} + +void Storeuintptr (uintptr_t *ptr, uintptr_t val) + __asm__ (GOSYM_PREFIX "runtime_internal_atomic.Storeuintptr") + __attribute__ ((no_split_stack)); + +void +Storeuintptr (uintptr_t *ptr, uintptr_t val) +{ + __atomic_store_n (ptr, val, __ATOMIC_SEQ_CST); +} + +void StorepNoWB (void *ptr, void *val) + __asm__ (GOSYM_PREFIX "runtime_internal_atomic.StorepNoWB") + __attribute__ ((no_split_stack)); + +void +StorepNoWB (void *ptr, void *val) +{ + __atomic_store_n ((void**) ptr, val, __ATOMIC_SEQ_CST); +} diff --git a/libgo/go/runtime/internal/atomic/atomic_test.go b/libgo/go/runtime/internal/atomic/atomic_test.go new file mode 100644 index 00000000000..d5dc552b952 --- /dev/null +++ b/libgo/go/runtime/internal/atomic/atomic_test.go @@ -0,0 +1,67 @@ +// Copyright 2015 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 atomic_test + +import ( + "runtime" + "runtime/internal/atomic" + "testing" + "unsafe" +) + +func runParallel(N, iter int, f func()) { + defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(int(N))) + done := make(chan bool) + for i := 0; i < N; i++ { + go func() { + for j := 0; j < iter; j++ { + f() + } + done <- true + }() + } + for i := 0; i < N; i++ { + <-done + } +} + +func TestXadduintptr(t *testing.T) { + const N = 20 + const iter = 100000 + inc := uintptr(100) + total := uintptr(0) + runParallel(N, iter, func() { + atomic.Xadduintptr(&total, inc) + }) + if want := uintptr(N * iter * inc); want != total { + t.Fatalf("xadduintpr error, want %d, got %d", want, total) + } + total = 0 + runParallel(N, iter, func() { + atomic.Xadduintptr(&total, inc) + atomic.Xadduintptr(&total, uintptr(-int64(inc))) + }) + if total != 0 { + t.Fatalf("xadduintpr total error, want %d, got %d", 0, total) + } +} + +// Tests that xadduintptr correctly updates 64-bit values. The place where +// we actually do so is mstats.go, functions mSysStat{Inc,Dec}. +func TestXadduintptrOnUint64(t *testing.T) { + /* if runtime.BigEndian != 0 { + // On big endian architectures, we never use xadduintptr to update + // 64-bit values and hence we skip the test. (Note that functions + // mSysStat{Inc,Dec} in mstats.go have explicit checks for + // big-endianness.) + return + }*/ + const inc = 100 + val := uint64(0) + atomic.Xadduintptr((*uintptr)(unsafe.Pointer(&val)), inc) + if inc != val { + t.Fatalf("xadduintptr should increase lower-order bits, want %d, got %d", inc, val) + } +} diff --git a/libgo/go/runtime/internal/atomic/gccgo.go b/libgo/go/runtime/internal/atomic/gccgo.go new file mode 100644 index 00000000000..696736465fd --- /dev/null +++ b/libgo/go/runtime/internal/atomic/gccgo.go @@ -0,0 +1,59 @@ +// Copyright 2016 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 atomic + +// Stubs for atomic functions that in gccgo are implemented in C. + +import "unsafe" + +//go:noescape +func Load(ptr *uint32) uint32 + +//go:noescape +func Loadp(ptr unsafe.Pointer) unsafe.Pointer + +//go:noescape +func Load64(ptr *uint64) uint64 + +//go:noescape +func Xadd(ptr *uint32, delta int32) uint32 + +//go:noescape +func Xadd64(ptr *uint64, delta int64) uint64 + +//go:noescape +func Xadduintptr(ptr *uintptr, delta uintptr) uintptr + +//go:noescape +func Xchg(ptr *uint32, new uint32) uint32 + +//go:noescape +func Xchg64(ptr *uint64, new uint64) uint64 + +//go:noescape +func Xchguintptr(ptr *uintptr, new uintptr) uintptr + +//go:noescape +func And8(ptr *uint8, val uint8) + +//go:noescape +func Or8(ptr *uint8, val uint8) + +// NOTE: Do not add atomicxor8 (XOR is not idempotent). + +//go:noescape +func Cas64(ptr *uint64, old, new uint64) bool + +//go:noescape +func Store(ptr *uint32, val uint32) + +//go:noescape +func Store64(ptr *uint64, val uint64) + +// StorepNoWB performs *ptr = val atomically and without a write +// barrier. +// +// NO go:noescape annotation; see atomic_pointer.go. +func StorepNoWB(ptr unsafe.Pointer, val unsafe.Pointer) diff --git a/libgo/go/runtime/internal/atomic/stubs.go b/libgo/go/runtime/internal/atomic/stubs.go new file mode 100644 index 00000000000..497b98046d8 --- /dev/null +++ b/libgo/go/runtime/internal/atomic/stubs.go @@ -0,0 +1,33 @@ +// Copyright 2015 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 atomic + +import "unsafe" + +//go:noescape +func Cas(ptr *uint32, old, new uint32) bool + +// NO go:noescape annotation; see atomic_pointer.go. +func Casp1(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool + +//go:noescape +func Casuintptr(ptr *uintptr, old, new uintptr) bool + +//go:noescape +func Storeuintptr(ptr *uintptr, new uintptr) + +//go:noescape +func Loaduintptr(ptr *uintptr) uintptr + +//go:noescape +func Loaduint(ptr *uint) uint + +// TODO(matloob): Should these functions have the go:noescape annotation? + +//go:noescape +func Loadint64(ptr *int64) int64 + +//go:noescape +func Xaddint64(ptr *int64, delta int64) int64 diff --git a/libgo/go/runtime/internal/sys/intrinsics.go b/libgo/go/runtime/internal/sys/intrinsics.go new file mode 100644 index 00000000000..f33209a8878 --- /dev/null +++ b/libgo/go/runtime/internal/sys/intrinsics.go @@ -0,0 +1,77 @@ +// Copyright 2016 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 sys + +//extern __builtin_ctz +func builtinCtz32(uint32) int32 + +//extern __builtin_ctzll +func builtinCtz64(uint64) int32 + +//go:nosplit + +// Ctz64 counts trailing (low-order) zeroes, +// and if all are zero, then 64. +func Ctz64(x uint64) uint64 { + if x == 0 { + return 64 + } + return uint64(builtinCtz64(x)) +} + +//go:nosplit + +// Ctz32 counts trailing (low-order) zeroes, +// and if all are zero, then 32. +func Ctz32(x uint32) uint32 { + if x == 0 { + return 32 + } + return uint32(builtinCtz32(x)) +} + +//go:nosplit + +// Ctz16 counts trailing (low-order) zeroes, +// and if all are zero, then 16. +func Ctz16(x uint16) uint16 { + if x == 0 { + return 16 + } + return uint16(builtinCtz32(uint32(x))) +} + +//go:nosplit + +// Ctz8 counts trailing (low-order) zeroes, +// and if all are zero, then 8. +func Ctz8(x uint8) uint8 { + if x == 0 { + return 8 + } + return uint8(builtinCtz32(uint32(x))) +} + +//extern __builtin_bswap64 +func bswap64(uint64) uint64 + +//go:nosplit + +// Bswap64 returns its input with byte order reversed +// 0x0102030405060708 -> 0x0807060504030201 +func Bswap64(x uint64) uint64 { + return bswap64(x) +} + +//extern __builtin_bswap32 +func bswap32(uint32) uint32 + +//go:nosplit + +// Bswap32 returns its input with byte order reversed +// 0x01020304 -> 0x04030201 +func Bswap32(x uint32) uint32 { + return bswap32(x) +} diff --git a/libgo/go/runtime/internal/sys/intrinsics_test.go b/libgo/go/runtime/internal/sys/intrinsics_test.go new file mode 100644 index 00000000000..097631bc1e5 --- /dev/null +++ b/libgo/go/runtime/internal/sys/intrinsics_test.go @@ -0,0 +1,54 @@ +package sys_test + +import ( + "runtime/internal/sys" + "testing" +) + +func TestCtz64(t *testing.T) { + for i := uint(0); i <= 64; i++ { + x := uint64(5) << i + if got := sys.Ctz64(x); got != uint64(i) { + t.Errorf("Ctz64(%d)=%d, want %d", x, got, i) + } + } +} +func TestCtz32(t *testing.T) { + for i := uint(0); i <= 32; i++ { + x := uint32(5) << i + if got := sys.Ctz32(x); got != uint32(i) { + t.Errorf("Ctz32(%d)=%d, want %d", x, got, i) + } + } +} +func TestCtz16(t *testing.T) { + for i := uint(0); i <= 16; i++ { + x := uint16(5) << i + if got := sys.Ctz16(x); got != uint16(i) { + t.Errorf("Ctz16(%d)=%d, want %d", x, got, i) + } + } +} +func TestCtz8(t *testing.T) { + for i := uint(0); i <= 8; i++ { + x := uint8(5) << i + if got := sys.Ctz8(x); got != uint8(i) { + t.Errorf("Ctz8(%d)=%d, want %d", x, got, i) + } + } +} + +func TestBswap64(t *testing.T) { + x := uint64(0x1122334455667788) + y := sys.Bswap64(x) + if y != 0x8877665544332211 { + t.Errorf("Bswap(%x)=%x, want 0x8877665544332211", x, y) + } +} +func TestBswap32(t *testing.T) { + x := uint32(0x11223344) + y := sys.Bswap32(x) + if y != 0x44332211 { + t.Errorf("Bswap(%x)=%x, want 0x44332211", x, y) + } +} diff --git a/libgo/go/runtime/internal/sys/stubs.go b/libgo/go/runtime/internal/sys/stubs.go new file mode 100644 index 00000000000..0a94502f32d --- /dev/null +++ b/libgo/go/runtime/internal/sys/stubs.go @@ -0,0 +1,11 @@ +// 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. + +package sys + +// Declarations for runtime services implemented in C or assembly. + +const PtrSize = 4 << (^uintptr(0) >> 63) // unsafe.Sizeof(uintptr(0)) but an ideal const +const RegSize = 4 << (^Uintreg(0) >> 63) // unsafe.Sizeof(uintreg(0)) but an ideal const +const SpAlign = 1*(1-GoarchArm64) + 16*GoarchArm64 // SP alignment: 1 normally, 16 for ARM64 diff --git a/libgo/go/runtime/internal/sys/sys.go b/libgo/go/runtime/internal/sys/sys.go new file mode 100644 index 00000000000..586a763717d --- /dev/null +++ b/libgo/go/runtime/internal/sys/sys.go @@ -0,0 +1,15 @@ +// Copyright 2015 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 sys contains system- and configuration- and architecture-specific +// constants used by the runtime. +package sys + +// The next line makes 'go generate' write the zgen_*.go files with +// per-OS and per-arch information, including constants +// named goos_$GOOS and goarch_$GOARCH for every +// known GOOS and GOARCH. The constant is 1 on the +// current system, 0 otherwise; multiplying by them is +// useful for defining GOOS- or GOARCH-specific constants. +//go:generate go run gengoos.go diff --git a/libgo/go/runtime/pprof/pprof.go b/libgo/go/runtime/pprof/pprof.go index d2e5b63fedb..0a58bafd85f 100644 --- a/libgo/go/runtime/pprof/pprof.go +++ b/libgo/go/runtime/pprof/pprof.go @@ -4,8 +4,69 @@ // Package pprof writes runtime profiling data in the format expected // by the pprof visualization tool. +// +// Profiling a Go program +// +// The first step to profiling a Go program is to enable profiling. +// Support for profiling benchmarks built with the standard testing +// package is built into go test. For example, the following command +// runs benchmarks in the current directory and writes the CPU and +// memory profiles to cpu.prof and mem.prof: +// +// go test -cpuprofile cpu.prof -memprofile mem.prof -bench . +// +// To add equivalent profiling support to a standalone program, add +// code like the following to your main function: +// +// var cpuprofile = flag.String("cpuprofile", "", "write cpu profile `file`") +// var memprofile = flag.String("memprofile", "", "write memory profile to `file`") +// +// func main() { +// flag.Parse() +// if *cpuprofile != "" { +// f, err := os.Create(*cpuprofile) +// if err != nil { +// log.Fatal("could not create CPU profile: ", err) +// } +// if err := pprof.StartCPUProfile(f); err != nil { +// log.Fatal("could not start CPU profile: ", err) +// } +// defer pprof.StopCPUProfile() +// } +// ... +// if *memprofile != "" { +// f, err := os.Create(*memprofile) +// if err != nil { +// log.Fatal("could not create memory profile: ", err) +// } +// runtime.GC() // get up-to-date statistics +// if err := pprof.WriteHeapProfile(f); err != nil { +// log.Fatal("could not write memory profile: ", err) +// } +// f.Close() +// } +// } +// +// There is also a standard HTTP interface to profiling data. Adding +// the following line will install handlers under the /debug/pprof/ +// URL to download live profiles: +// +// import _ "net/http/pprof" +// +// See the net/http/pprof package for more details. +// +// Profiles can then be visualized with the pprof tool: +// +// go tool pprof cpu.prof +// +// There are many commands available from the pprof command line. +// Commonly used commands include "top", which prints a summary of the +// top program hot-spots, and "web", which opens an interactive graph +// of hot-spots and their call graphs. Use "help" for information on +// all pprof commands. +// // For more information about pprof, see -// http://github.com/google/pprof/. +// https://github.com/google/pprof/blob/master/doc/pprof.md. package pprof import ( diff --git a/libgo/go/runtime/runtime2.go b/libgo/go/runtime/runtime2.go index 05ce513aa9a..468d11e8e83 100644 --- a/libgo/go/runtime/runtime2.go +++ b/libgo/go/runtime/runtime2.go @@ -805,7 +805,11 @@ var ( // _ucontext_t is a Go version of the C ucontext_t type, used by getcontext. // _sizeof_ucontext_t is defined by the Makefile from <ucontext.h>. -type _ucontext_t [_sizeof_ucontext_t / unsafe.Sizeof(uintptr(0))]unsafe.Pointer +// On some systems getcontext and friends require a value that is +// aligned to a 16-byte boundary. We implement this by increasing the +// required size and picking an appropriate offset when we use the +// array. +type _ucontext_t [(_sizeof_ucontext_t + 15) / unsafe.Sizeof(unsafe.Pointer(nil))]unsafe.Pointer // traceback is used to collect stack traces from other goroutines. type traceback struct { |