summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAustin Clements <austin@google.com>2014-11-19 11:30:58 -0500
committerAustin Clements <austin@google.com>2014-11-19 11:30:58 -0500
commitc2f443bf7b05a302c662c52a77dc8111471ff65c (patch)
tree04416a2dfe3568ebfebc3acfbf7584ebfce155cc
parentb6b7df49714b59954c25fe3ff891a2c0183251aa (diff)
downloadgo-c2f443bf7b05a302c662c52a77dc8111471ff65c.tar.gz
[dev.cc] runtime: allow more address bits in lfstack on Power64
Previously, lfstack assumed Linux limited user space addresses to 43 bits on Power64 based on a paper from 2001. It turns out the limit is now 46 bits, so lfstack was truncating pointers. Raise the limit to 48 bits (for some future proofing and to make it match amd64) and add a self-test that will fail in a useful way if ever unpack(pack(x)) != x. With this change, dev.cc passes all.bash on power64le. LGTM=rsc R=rsc CC=golang-codereviews https://codereview.appspot.com/174430043
-rw-r--r--src/runtime/lfstack.go4
-rw-r--r--src/runtime/lfstack_linux_power64x.go20
2 files changed, 17 insertions, 7 deletions
diff --git a/src/runtime/lfstack.go b/src/runtime/lfstack.go
index 4a20fff9d..8a36a67b3 100644
--- a/src/runtime/lfstack.go
+++ b/src/runtime/lfstack.go
@@ -12,6 +12,10 @@ import "unsafe"
func lfstackpush(head *uint64, node *lfnode) {
node.pushcnt++
new := lfstackPack(node, node.pushcnt)
+ if node1, _ := lfstackUnpack(new); node1 != node {
+ println("runtime: lfstackpush invalid packing: node=", node, " cnt=", hex(node.pushcnt), " packed=", hex(new), " -> node=", node1, "\n")
+ gothrow("lfstackpush")
+ }
for {
old := atomicload64(head)
node.next, _ = lfstackUnpack(old)
diff --git a/src/runtime/lfstack_linux_power64x.go b/src/runtime/lfstack_linux_power64x.go
index 7a122bf92..89e389fc7 100644
--- a/src/runtime/lfstack_linux_power64x.go
+++ b/src/runtime/lfstack_linux_power64x.go
@@ -9,18 +9,24 @@ package runtime
import "unsafe"
-// On Power64, Linux limits the user address space to 43 bits.
-// (https://www.kernel.org/doc/ols/2001/ppc64.pdf)
-// In addition to the 21 bits taken from the top, we can take 3 from the
-// bottom, because node must be pointer-aligned, giving a total of 24 bits
+// On Power64, Linux limits the user address space to 46 bits (see
+// TASK_SIZE_USER64 in the Linux kernel). This has grown over time,
+// so here we allow 48 bit addresses.
+//
+// In addition to the 16 bits taken from the top, we can take 3 from the
+// bottom, because node must be pointer-aligned, giving a total of 19 bits
// of count.
+const (
+ addrBits = 48
+ cntBits = 64 - addrBits + 3
+)
func lfstackPack(node *lfnode, cnt uintptr) uint64 {
- return uint64(uintptr(unsafe.Pointer(node)))<<21 | uint64(cnt&(1<<24-1))
+ return uint64(uintptr(unsafe.Pointer(node)))<<(64-addrBits) | uint64(cnt&(1<<cntBits-1))
}
func lfstackUnpack(val uint64) (node *lfnode, cnt uintptr) {
- node = (*lfnode)(unsafe.Pointer(uintptr(val >> 24 << 3)))
- cnt = uintptr(val & (1<<24 - 1))
+ node = (*lfnode)(unsafe.Pointer(uintptr(val >> cntBits << 3)))
+ cnt = uintptr(val & (1<<cntBits - 1))
return
}