Source file
src/runtime/mpagecache.go
1
2
3
4
5 package runtime
6
7 import (
8 "runtime/internal/sys"
9 "unsafe"
10 )
11
12 const pageCachePages = 8 * unsafe.Sizeof(pageCache{}.cache)
13
14
15
16
17
18 type pageCache struct {
19 base uintptr
20 cache uint64
21 scav uint64
22 }
23
24
25 func (c *pageCache) empty() bool {
26 return c.cache == 0
27 }
28
29
30
31
32
33
34
35
36
37 func (c *pageCache) alloc(npages uintptr) (uintptr, uintptr) {
38 if c.cache == 0 {
39 return 0, 0
40 }
41 if npages == 1 {
42 i := uintptr(sys.TrailingZeros64(c.cache))
43 scav := (c.scav >> i) & 1
44 c.cache &^= 1 << i
45 c.scav &^= 1 << i
46 return c.base + i*pageSize, uintptr(scav) * pageSize
47 }
48 return c.allocN(npages)
49 }
50
51
52
53
54
55
56
57 func (c *pageCache) allocN(npages uintptr) (uintptr, uintptr) {
58 i := findBitRange64(c.cache, uint(npages))
59 if i >= 64 {
60 return 0, 0
61 }
62 mask := ((uint64(1) << npages) - 1) << i
63 scav := sys.OnesCount64(c.scav & mask)
64 c.cache &^= mask
65 c.scav &^= mask
66 return c.base + uintptr(i*pageSize), uintptr(scav) * pageSize
67 }
68
69
70
71
72
73
74
75
76
77
78 func (c *pageCache) flush(p *pageAlloc) {
79 assertLockHeld(p.mheapLock)
80
81 if c.empty() {
82 return
83 }
84 ci := chunkIndex(c.base)
85 pi := chunkPageIndex(c.base)
86
87
88
89 for i := uint(0); i < 64; i++ {
90 if c.cache&(1<<i) != 0 {
91 p.chunkOf(ci).free1(pi + i)
92
93
94 p.scav.index.free(ci, pi+i, 1)
95 }
96 if c.scav&(1<<i) != 0 {
97 p.chunkOf(ci).scavenged.setRange(pi+i, 1)
98 }
99 }
100
101
102
103 if b := (offAddr{c.base}); b.lessThan(p.searchAddr) {
104 p.searchAddr = b
105 }
106 p.update(c.base, pageCachePages, false, false)
107 *c = pageCache{}
108 }
109
110
111
112
113
114
115
116
117
118
119 func (p *pageAlloc) allocToCache() pageCache {
120 assertLockHeld(p.mheapLock)
121
122
123
124 if chunkIndex(p.searchAddr.addr()) >= p.end {
125 return pageCache{}
126 }
127 c := pageCache{}
128 ci := chunkIndex(p.searchAddr.addr())
129 var chunk *pallocData
130 if p.summary[len(p.summary)-1][ci] != 0 {
131
132 chunk = p.chunkOf(ci)
133 j, _ := chunk.find(1, chunkPageIndex(p.searchAddr.addr()))
134 if j == ^uint(0) {
135 throw("bad summary data")
136 }
137 c = pageCache{
138 base: chunkBase(ci) + alignDown(uintptr(j), 64)*pageSize,
139 cache: ^chunk.pages64(j),
140 scav: chunk.scavenged.block64(j),
141 }
142 } else {
143
144
145 addr, _ := p.find(1)
146 if addr == 0 {
147
148
149 p.searchAddr = maxSearchAddr()
150 return pageCache{}
151 }
152 ci = chunkIndex(addr)
153 chunk = p.chunkOf(ci)
154 c = pageCache{
155 base: alignDown(addr, 64*pageSize),
156 cache: ^chunk.pages64(chunkPageIndex(addr)),
157 scav: chunk.scavenged.block64(chunkPageIndex(addr)),
158 }
159 }
160
161
162
163 cpi := chunkPageIndex(c.base)
164 chunk.allocPages64(cpi, c.cache)
165 chunk.scavenged.clearBlock64(cpi, c.cache&c.scav )
166
167
168 p.update(c.base, pageCachePages, false, true)
169
170
171 p.scav.index.alloc(ci, uint(sys.OnesCount64(c.cache)))
172
173
174
175
176
177
178
179
180
181 p.searchAddr = offAddr{c.base + pageSize*(pageCachePages-1)}
182 return c
183 }
184
View as plain text