...
Source file
src/runtime/trace2map.go
Documentation: runtime
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package runtime
19
20 import (
21 "runtime/internal/atomic"
22 "runtime/internal/sys"
23 "unsafe"
24 )
25
26 type traceMap struct {
27 lock mutex
28 seq atomic.Uint64
29 mem traceRegionAlloc
30 tab [1 << 13]atomic.UnsafePointer
31 }
32
33 type traceMapNode struct {
34 _ sys.NotInHeap
35 link atomic.UnsafePointer
36 hash uintptr
37 id uint64
38 data []byte
39 }
40
41
42 func (n *traceMapNode) next() *traceMapNode {
43 return (*traceMapNode)(n.link.Load())
44 }
45
46
47
48 func (tab *traceMap) stealID() uint64 {
49 return tab.seq.Add(1)
50 }
51
52
53
54
55
56
57
58 func (tab *traceMap) put(data unsafe.Pointer, size uintptr) (uint64, bool) {
59 if size == 0 {
60 return 0, false
61 }
62 hash := memhash(data, 0, size)
63
64 if id := tab.find(data, size, hash); id != 0 {
65 return id, false
66 }
67
68
69 var id uint64
70 var added bool
71 systemstack(func() {
72 lock(&tab.lock)
73 if id = tab.find(data, size, hash); id != 0 {
74 unlock(&tab.lock)
75 return
76 }
77
78 id = tab.seq.Add(1)
79 vd := tab.newTraceMapNode(data, size, hash, id)
80
81
82
83
84
85
86 part := int(hash % uintptr(len(tab.tab)))
87 vd.link.StoreNoWB(tab.tab[part].Load())
88 tab.tab[part].StoreNoWB(unsafe.Pointer(vd))
89 unlock(&tab.lock)
90
91 added = true
92 })
93 return id, added
94 }
95
96
97
98
99 func (tab *traceMap) find(data unsafe.Pointer, size, hash uintptr) uint64 {
100 part := int(hash % uintptr(len(tab.tab)))
101 for vd := tab.bucket(part); vd != nil; vd = vd.next() {
102
103
104 if vd.hash == hash && uintptr(len(vd.data)) == size {
105 if memequal(unsafe.Pointer(&vd.data[0]), data, size) {
106 return vd.id
107 }
108 }
109 }
110 return 0
111 }
112
113
114 func (tab *traceMap) bucket(part int) *traceMapNode {
115 return (*traceMapNode)(tab.tab[part].Load())
116 }
117
118 func (tab *traceMap) newTraceMapNode(data unsafe.Pointer, size, hash uintptr, id uint64) *traceMapNode {
119
120 sl := notInHeapSlice{
121 array: tab.mem.alloc(size),
122 len: int(size),
123 cap: int(size),
124 }
125 memmove(unsafe.Pointer(sl.array), data, size)
126
127
128 meta := (*traceMapNode)(unsafe.Pointer(tab.mem.alloc(unsafe.Sizeof(traceMapNode{}))))
129 *(*notInHeapSlice)(unsafe.Pointer(&meta.data)) = sl
130 meta.id = id
131 meta.hash = hash
132 return meta
133 }
134
135
136
137
138
139
140 func (tab *traceMap) reset() {
141 assertLockHeld(&tab.lock)
142 tab.mem.drop()
143 tab.seq.Store(0)
144
145
146
147
148
149
150 memclrNoHeapPointers(unsafe.Pointer(&tab.tab), unsafe.Sizeof(tab.tab))
151 }
152
View as plain text