...
Source file
src/runtime/mpallocbits.go
Documentation: runtime
1
2
3
4
5 package runtime
6
7 import (
8 "runtime/internal/sys"
9 )
10
11
12 type pageBits [pallocChunkPages / 64]uint64
13
14
15 func (b *pageBits) get(i uint) uint {
16 return uint((b[i/64] >> (i % 64)) & 1)
17 }
18
19
20 func (b *pageBits) block64(i uint) uint64 {
21 return b[i/64]
22 }
23
24
25 func (b *pageBits) set(i uint) {
26 b[i/64] |= 1 << (i % 64)
27 }
28
29
30 func (b *pageBits) setRange(i, n uint) {
31 _ = b[i/64]
32 if n == 1 {
33
34 b.set(i)
35 return
36 }
37
38 j := i + n - 1
39 if i/64 == j/64 {
40 b[i/64] |= ((uint64(1) << n) - 1) << (i % 64)
41 return
42 }
43 _ = b[j/64]
44
45 b[i/64] |= ^uint64(0) << (i % 64)
46 for k := i/64 + 1; k < j/64; k++ {
47 b[k] = ^uint64(0)
48 }
49
50 b[j/64] |= (uint64(1) << (j%64 + 1)) - 1
51 }
52
53
54 func (b *pageBits) setAll() {
55 for i := range b {
56 b[i] = ^uint64(0)
57 }
58 }
59
60
61 func (b *pageBits) clear(i uint) {
62 b[i/64] &^= 1 << (i % 64)
63 }
64
65
66 func (b *pageBits) clearRange(i, n uint) {
67 _ = b[i/64]
68 if n == 1 {
69
70 b.clear(i)
71 return
72 }
73
74 j := i + n - 1
75 if i/64 == j/64 {
76 b[i/64] &^= ((uint64(1) << n) - 1) << (i % 64)
77 return
78 }
79 _ = b[j/64]
80
81 b[i/64] &^= ^uint64(0) << (i % 64)
82 for k := i/64 + 1; k < j/64; k++ {
83 b[k] = 0
84 }
85
86 b[j/64] &^= (uint64(1) << (j%64 + 1)) - 1
87 }
88
89
90 func (b *pageBits) clearAll() {
91 for i := range b {
92 b[i] = 0
93 }
94 }
95
96
97
98 func (b *pageBits) popcntRange(i, n uint) (s uint) {
99 if n == 1 {
100 return uint((b[i/64] >> (i % 64)) & 1)
101 }
102 _ = b[i/64]
103 j := i + n - 1
104 if i/64 == j/64 {
105 return uint(sys.OnesCount64((b[i/64] >> (i % 64)) & ((1 << n) - 1)))
106 }
107 _ = b[j/64]
108 s += uint(sys.OnesCount64(b[i/64] >> (i % 64)))
109 for k := i/64 + 1; k < j/64; k++ {
110 s += uint(sys.OnesCount64(b[k]))
111 }
112 s += uint(sys.OnesCount64(b[j/64] & ((1 << (j%64 + 1)) - 1)))
113 return
114 }
115
116
117
118
119
120
121 type pallocBits pageBits
122
123
124 func (b *pallocBits) summarize() pallocSum {
125 var start, max, cur uint
126 const notSetYet = ^uint(0)
127 start = notSetYet
128 for i := 0; i < len(b); i++ {
129 x := b[i]
130 if x == 0 {
131 cur += 64
132 continue
133 }
134 t := uint(sys.TrailingZeros64(x))
135 l := uint(sys.LeadingZeros64(x))
136
137
138 cur += t
139 if start == notSetYet {
140 start = cur
141 }
142 if cur > max {
143 max = cur
144 }
145
146 cur = l
147 }
148 if start == notSetYet {
149
150 const n = uint(64 * len(b))
151 return packPallocSum(n, n, n)
152 }
153 if cur > max {
154 max = cur
155 }
156 if max >= 64-2 {
157
158 return packPallocSum(start, max, cur)
159 }
160
161
162 outer:
163 for i := 0; i < len(b); i++ {
164 x := b[i]
165
166
167
168
169
170
171
172 x >>= sys.TrailingZeros64(x) & 63
173 if x&(x+1) == 0 {
174 continue
175 }
176
177
178
179 p := max
180 k := uint(1)
181 for {
182
183 for p > 0 {
184 if p <= k {
185
186 x |= x >> (p & 63)
187 if x&(x+1) == 0 {
188 continue outer
189 }
190 break
191 }
192
193 x |= x >> (k & 63)
194 if x&(x+1) == 0 {
195 continue outer
196 }
197 p -= k
198
199
200 k *= 2
201 }
202
203
204 j := uint(sys.TrailingZeros64(^x))
205 x >>= j & 63
206 j = uint(sys.TrailingZeros64(x))
207 x >>= j & 63
208 max += j
209 if x&(x+1) == 0 {
210 continue outer
211 }
212 p = j
213 }
214 }
215 return packPallocSum(start, max, cur)
216 }
217
218
219
220
221
222
223
224
225
226
227 func (b *pallocBits) find(npages uintptr, searchIdx uint) (uint, uint) {
228 if npages == 1 {
229 addr := b.find1(searchIdx)
230 return addr, addr
231 } else if npages <= 64 {
232 return b.findSmallN(npages, searchIdx)
233 }
234 return b.findLargeN(npages, searchIdx)
235 }
236
237
238
239
240
241 func (b *pallocBits) find1(searchIdx uint) uint {
242 _ = b[0]
243 for i := searchIdx / 64; i < uint(len(b)); i++ {
244 x := b[i]
245 if ^x == 0 {
246 continue
247 }
248 return i*64 + uint(sys.TrailingZeros64(^x))
249 }
250 return ^uint(0)
251 }
252
253
254
255
256
257
258
259
260
261
262
263 func (b *pallocBits) findSmallN(npages uintptr, searchIdx uint) (uint, uint) {
264 end, newSearchIdx := uint(0), ^uint(0)
265 for i := searchIdx / 64; i < uint(len(b)); i++ {
266 bi := b[i]
267 if ^bi == 0 {
268 end = 0
269 continue
270 }
271
272
273 if newSearchIdx == ^uint(0) {
274
275
276 newSearchIdx = i*64 + uint(sys.TrailingZeros64(^bi))
277 }
278 start := uint(sys.TrailingZeros64(bi))
279 if end+start >= uint(npages) {
280 return i*64 - end, newSearchIdx
281 }
282
283 j := findBitRange64(^bi, uint(npages))
284 if j < 64 {
285 return i*64 + j, newSearchIdx
286 }
287 end = uint(sys.LeadingZeros64(bi))
288 }
289 return ^uint(0), newSearchIdx
290 }
291
292
293
294
295
296
297
298
299
300
301
302 func (b *pallocBits) findLargeN(npages uintptr, searchIdx uint) (uint, uint) {
303 start, size, newSearchIdx := ^uint(0), uint(0), ^uint(0)
304 for i := searchIdx / 64; i < uint(len(b)); i++ {
305 x := b[i]
306 if x == ^uint64(0) {
307 size = 0
308 continue
309 }
310 if newSearchIdx == ^uint(0) {
311
312
313 newSearchIdx = i*64 + uint(sys.TrailingZeros64(^x))
314 }
315 if size == 0 {
316 size = uint(sys.LeadingZeros64(x))
317 start = i*64 + 64 - size
318 continue
319 }
320 s := uint(sys.TrailingZeros64(x))
321 if s+size >= uint(npages) {
322 size += s
323 return start, newSearchIdx
324 }
325 if s < 64 {
326 size = uint(sys.LeadingZeros64(x))
327 start = i*64 + 64 - size
328 continue
329 }
330 size += 64
331 }
332 if size < uint(npages) {
333 return ^uint(0), newSearchIdx
334 }
335 return start, newSearchIdx
336 }
337
338
339 func (b *pallocBits) allocRange(i, n uint) {
340 (*pageBits)(b).setRange(i, n)
341 }
342
343
344 func (b *pallocBits) allocAll() {
345 (*pageBits)(b).setAll()
346 }
347
348
349 func (b *pallocBits) free1(i uint) {
350 (*pageBits)(b).clear(i)
351 }
352
353
354 func (b *pallocBits) free(i, n uint) {
355 (*pageBits)(b).clearRange(i, n)
356 }
357
358
359 func (b *pallocBits) freeAll() {
360 (*pageBits)(b).clearAll()
361 }
362
363
364
365
366 func (b *pallocBits) pages64(i uint) uint64 {
367 return (*pageBits)(b).block64(i)
368 }
369
370
371
372
373
374 func findBitRange64(c uint64, n uint) uint {
375
376
377
378 p := n - 1
379 k := uint(1)
380 for p > 0 {
381 if p <= k {
382
383 c &= c >> (p & 63)
384 break
385 }
386
387 c &= c >> (k & 63)
388 if c == 0 {
389 return 64
390 }
391 p -= k
392
393
394 k *= 2
395 }
396
397
398
399 return uint(sys.TrailingZeros64(c))
400 }
401
402
403
404
405
406
407
408
409 type pallocData struct {
410 pallocBits
411 scavenged pageBits
412 }
413
414
415
416 func (m *pallocData) allocRange(i, n uint) {
417
418 m.pallocBits.allocRange(i, n)
419 m.scavenged.clearRange(i, n)
420 }
421
422
423
424 func (m *pallocData) allocAll() {
425
426 m.pallocBits.allocAll()
427 m.scavenged.clearAll()
428 }
429
View as plain text