aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/lfstack_test.go
diff options
context:
space:
mode:
authorKeith Randall <khr@golang.org>2022-11-08 17:48:48 -0800
committerKeith Randall <khr@golang.org>2022-11-17 23:12:04 +0000
commitd6171c9be2a4bd2801841aa006702886c476f217 (patch)
tree9d1c4a24f0a80b3354ccaeb8c4064a35380acf1b /src/runtime/lfstack_test.go
parent3e5c2c155645ebaed62e4481430c455045b0fff5 (diff)
downloadgo-d6171c9be2a4bd2801841aa006702886c476f217.tar.xz
runtime: fix conflict between lfstack and checkptr
lfstack does very unsafe things. In particular, it will not work with nodes that live on the heap. In normal use by the runtime, that is the case (it is only used for gc work bufs). But the lfstack test does use heap objects. It goes through some hoops to prevent premature deallocation, but those hoops are not enough to convince -d=checkptr that everything is ok. Instead, allocate the test objects outside the heap, like the runtime does for all of its lfstack usage. Remove the lifetime workaround from the test. Reported in https://groups.google.com/g/golang-nuts/c/psjrUV2ZKyI Change-Id: If611105eab6c823a4d6c105938ce145ed731781d Reviewed-on: https://go-review.googlesource.com/c/go/+/448899 Reviewed-by: Austin Clements <austin@google.com> Reviewed-by: Keith Randall <khr@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Keith Randall <khr@golang.org>
Diffstat (limited to 'src/runtime/lfstack_test.go')
-rw-r--r--src/runtime/lfstack_test.go31
1 files changed, 14 insertions, 17 deletions
diff --git a/src/runtime/lfstack_test.go b/src/runtime/lfstack_test.go
index d0a1b6ba06..e36297e541 100644
--- a/src/runtime/lfstack_test.go
+++ b/src/runtime/lfstack_test.go
@@ -16,6 +16,17 @@ type MyNode struct {
data int
}
+// allocMyNode allocates nodes that are stored in an lfstack
+// outside the Go heap.
+// We require lfstack objects to live outside the heap so that
+// checkptr passes on the unsafe shenanigans used.
+func allocMyNode(data int) *MyNode {
+ n := (*MyNode)(PersistentAlloc(unsafe.Sizeof(MyNode{})))
+ LFNodeValidate(&n.LFNode)
+ n.data = data
+ return n
+}
+
func fromMyNode(node *MyNode) *LFNode {
return (*LFNode)(unsafe.Pointer(node))
}
@@ -30,22 +41,17 @@ func TestLFStack(t *testing.T) {
stack := new(uint64)
global = stack // force heap allocation
- // Need to keep additional references to nodes, the stack is not all that type-safe.
- var nodes []*MyNode
-
// Check the stack is initially empty.
if LFStackPop(stack) != nil {
t.Fatalf("stack is not empty")
}
// Push one element.
- node := &MyNode{data: 42}
- nodes = append(nodes, node)
+ node := allocMyNode(42)
LFStackPush(stack, fromMyNode(node))
// Push another.
- node = &MyNode{data: 43}
- nodes = append(nodes, node)
+ node = allocMyNode(43)
LFStackPush(stack, fromMyNode(node))
// Pop one element.
@@ -75,8 +81,6 @@ func TestLFStack(t *testing.T) {
}
}
-var stress []*MyNode
-
func TestLFStackStress(t *testing.T) {
const K = 100
P := 4 * GOMAXPROCS(-1)
@@ -86,15 +90,11 @@ func TestLFStackStress(t *testing.T) {
}
// Create 2 stacks.
stacks := [2]*uint64{new(uint64), new(uint64)}
- // Need to keep additional references to nodes,
- // the lock-free stack is not type-safe.
- stress = nil
// Push K elements randomly onto the stacks.
sum := 0
for i := 0; i < K; i++ {
sum += i
- node := &MyNode{data: i}
- stress = append(stress, node)
+ node := allocMyNode(i)
LFStackPush(stacks[i%2], fromMyNode(node))
}
c := make(chan bool, P)
@@ -134,7 +134,4 @@ func TestLFStackStress(t *testing.T) {
if sum2 != sum {
t.Fatalf("Wrong sum %d/%d", sum2, sum)
}
-
- // Let nodes be collected now.
- stress = nil
}