summaryrefslogtreecommitdiff
path: root/libgo/go/runtime/lfstack.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/runtime/lfstack.go')
-rw-r--r--libgo/go/runtime/lfstack.go50
1 files changed, 50 insertions, 0 deletions
diff --git a/libgo/go/runtime/lfstack.go b/libgo/go/runtime/lfstack.go
new file mode 100644
index 0000000000..2f2958c886
--- /dev/null
+++ b/libgo/go/runtime/lfstack.go
@@ -0,0 +1,50 @@
+// Copyright 2012 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.
+
+// Lock-free stack.
+// Initialize head to 0, compare with 0 to test for emptiness.
+// The stack does not keep pointers to nodes,
+// so they can be garbage collected if there are no other pointers to nodes.
+// The following code runs only in non-preemptible contexts.
+
+package runtime
+
+import (
+ "runtime/internal/atomic"
+ "unsafe"
+)
+
+// Temporary for C code to call:
+//go:linkname lfstackpush runtime.lfstackpush
+//go:linkname lfstackpop runtime.lfstackpop
+
+func lfstackpush(head *uint64, node *lfnode) {
+ node.pushcnt++
+ new := lfstackPack(node, node.pushcnt)
+ if node1 := lfstackUnpack(new); node1 != node {
+ print("runtime: lfstackpush invalid packing: node=", node, " cnt=", hex(node.pushcnt), " packed=", hex(new), " -> node=", node1, "\n")
+ throw("lfstackpush")
+ }
+ for {
+ old := atomic.Load64(head)
+ node.next = old
+ if atomic.Cas64(head, old, new) {
+ break
+ }
+ }
+}
+
+func lfstackpop(head *uint64) unsafe.Pointer {
+ for {
+ old := atomic.Load64(head)
+ if old == 0 {
+ return nil
+ }
+ node := lfstackUnpack(old)
+ next := atomic.Load64(&node.next)
+ if atomic.Cas64(head, old, next) {
+ return unsafe.Pointer(node)
+ }
+ }
+}