Source file
src/runtime/lfstack.go
1
2
3
4
5
6
7 package runtime
8
9 import (
10 "internal/runtime/atomic"
11 "unsafe"
12 )
13
14
15
16
17
18
19
20
21
22 type lfstack uint64
23
24 func (head *lfstack) push(node *lfnode) {
25 node.pushcnt++
26 new := lfstackPack(node, node.pushcnt)
27 for {
28 old := atomic.Load64((*uint64)(head))
29 node.next = old
30 if atomic.Cas64((*uint64)(head), old, new) {
31 break
32 }
33 }
34 }
35
36 func (head *lfstack) pop() unsafe.Pointer {
37 for {
38 old := atomic.Load64((*uint64)(head))
39 if old == 0 {
40 return nil
41 }
42 node := lfstackUnpack(old)
43 next := atomic.Load64(&node.next)
44 if atomic.Cas64((*uint64)(head), old, next) {
45 return unsafe.Pointer(node)
46 }
47 }
48 }
49
50 func (head *lfstack) empty() bool {
51 return atomic.Load64((*uint64)(head)) == 0
52 }
53
54
55
56 func lfnodeValidate(node *lfnode) {
57 if base, _, _ := findObject(uintptr(unsafe.Pointer(node)), 0, 0); base != 0 {
58 throw("lfstack node allocated from the heap")
59 }
60 lfstackPack(node, ^uintptr(0))
61 }
62
63 func lfstackPack(node *lfnode, cnt uintptr) uint64 {
64 return uint64(taggedPointerPack(unsafe.Pointer(node), cnt&(1<<tagBits-1)))
65 }
66
67 func lfstackUnpack(val uint64) *lfnode {
68 return (*lfnode)(taggedPointer(val).pointer())
69 }
70
View as plain text