...
Source file src/pkg/runtime/mgclarge.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 package runtime
36
37 import (
38 "unsafe"
39 )
40
41
42 type mTreap struct {
43 treap *treapNode
44 unscavHugePages uintptr
45 }
46
47
48 type treapNode struct {
49 right *treapNode
50 left *treapNode
51 parent *treapNode
52 key uintptr
53 span *mspan
54 maxPages uintptr
55 priority uint32
56 types treapIterFilter
57 }
58
59
60
61
62
63
64 func (t *treapNode) updateInvariants() bool {
65 m, i := t.maxPages, t.types
66 t.maxPages = t.span.npages
67 t.types = t.span.treapFilter()
68 if t.left != nil {
69 t.types |= t.left.types
70 if t.maxPages < t.left.maxPages {
71 t.maxPages = t.left.maxPages
72 }
73 }
74 if t.right != nil {
75 t.types |= t.right.types
76 if t.maxPages < t.right.maxPages {
77 t.maxPages = t.right.maxPages
78 }
79 }
80 return m != t.maxPages || i != t.types
81 }
82
83
84
85
86
87
88
89 func (t *treapNode) findMinimal(f treapIterFilter) *treapNode {
90 if t == nil || !f.matches(t.types) {
91 return nil
92 }
93 for t != nil {
94 if t.left != nil && f.matches(t.left.types) {
95 t = t.left
96 } else if f.matches(t.span.treapFilter()) {
97 break
98 } else if t.right != nil && f.matches(t.right.types) {
99 t = t.right
100 } else {
101 println("runtime: f=", f)
102 throw("failed to find minimal node matching filter")
103 }
104 }
105 return t
106 }
107
108
109
110
111
112
113
114 func (t *treapNode) findMaximal(f treapIterFilter) *treapNode {
115 if t == nil || !f.matches(t.types) {
116 return nil
117 }
118 for t != nil {
119 if t.right != nil && f.matches(t.right.types) {
120 t = t.right
121 } else if f.matches(t.span.treapFilter()) {
122 break
123 } else if t.left != nil && f.matches(t.left.types) {
124 t = t.left
125 } else {
126 println("runtime: f=", f)
127 throw("failed to find minimal node matching filter")
128 }
129 }
130 return t
131 }
132
133
134
135 func (t *treapNode) pred(f treapIterFilter) *treapNode {
136 if t.left != nil && f.matches(t.left.types) {
137
138
139 return t.left.findMaximal(f)
140 }
141
142 p := t
143 t = t.parent
144 for t != nil {
145
146
147 if t.right == p {
148 if f.matches(t.span.treapFilter()) {
149
150
151
152 return t
153 } else if t.left != nil && f.matches(t.left.types) {
154
155
156 return t.left.findMaximal(f)
157 }
158 }
159 p = t
160 t = t.parent
161 }
162
163
164
165
166 return nil
167 }
168
169
170
171 func (t *treapNode) succ(f treapIterFilter) *treapNode {
172
173 if t.right != nil && f.matches(t.right.types) {
174 return t.right.findMinimal(f)
175 }
176 p := t
177 t = t.parent
178 for t != nil {
179 if t.left == p {
180 if f.matches(t.span.treapFilter()) {
181 return t
182 } else if t.right != nil && f.matches(t.right.types) {
183 return t.right.findMinimal(f)
184 }
185 }
186 p = t
187 t = t.parent
188 }
189 return nil
190 }
191
192
193
194 func (t *treapNode) isSpanInTreap(s *mspan) bool {
195 if t == nil {
196 return false
197 }
198 return t.span == s || t.left.isSpanInTreap(s) || t.right.isSpanInTreap(s)
199 }
200
201
202
203
204
205 func (t *treapNode) walkTreap(fn func(tn *treapNode)) {
206 if t == nil {
207 return
208 }
209 fn(t)
210 t.left.walkTreap(fn)
211 t.right.walkTreap(fn)
212 }
213
214
215
216 func checkTreapNode(t *treapNode) {
217 if t == nil {
218 return
219 }
220 if t.span.next != nil || t.span.prev != nil || t.span.list != nil {
221 throw("span may be on an mSpanList while simultaneously in the treap")
222 }
223 if t.span.base() != t.key {
224 println("runtime: checkTreapNode treapNode t=", t, " t.key=", t.key,
225 "t.span.base()=", t.span.base())
226 throw("why does span.base() and treap.key do not match?")
227 }
228 if t.left != nil && t.key < t.left.key {
229 throw("found out-of-order spans in treap (left child has greater base address)")
230 }
231 if t.right != nil && t.key > t.right.key {
232 throw("found out-of-order spans in treap (right child has lesser base address)")
233 }
234 }
235
236
237
238
239
240 func (t *treapNode) validateInvariants() (uintptr, treapIterFilter) {
241 if t == nil {
242 return 0, 0
243 }
244 leftMax, leftTypes := t.left.validateInvariants()
245 rightMax, rightTypes := t.right.validateInvariants()
246 max := t.span.npages
247 if leftMax > max {
248 max = leftMax
249 }
250 if rightMax > max {
251 max = rightMax
252 }
253 if max != t.maxPages {
254 println("runtime: t.maxPages=", t.maxPages, "want=", max)
255 throw("maxPages invariant violated in treap")
256 }
257 typ := t.span.treapFilter() | leftTypes | rightTypes
258 if typ != t.types {
259 println("runtime: t.types=", t.types, "want=", typ)
260 throw("types invariant violated in treap")
261 }
262 return max, typ
263 }
264
265
266
267
268
269
270
271
272
273 type treapIterType uint8
274
275 const (
276 treapIterScav treapIterType = 1 << iota
277 treapIterHuge
278 treapIterBits = iota
279 )
280
281
282
283
284
285
286
287
288
289
290
291
292
293 type treapIterFilter uint32
294
295
296 const treapFilterAll = ^treapIterFilter(0)
297
298
299
300
301 func treapFilter(mask, match treapIterType) treapIterFilter {
302 allow := treapIterFilter(0)
303 for i := treapIterType(0); i < 1<<treapIterBits; i++ {
304 if mask&i == match {
305 allow |= 1 << i
306 }
307 }
308 return allow
309 }
310
311
312 func (f treapIterFilter) matches(m treapIterFilter) bool {
313 return f&m != 0
314 }
315
316
317
318 func (s *mspan) treapFilter() treapIterFilter {
319 have := treapIterType(0)
320 if s.scavenged {
321 have |= treapIterScav
322 }
323 if s.hugePages() > 0 {
324 have |= treapIterHuge
325 }
326 return treapIterFilter(uint32(1) << (0x1f & have))
327 }
328
329
330
331
332
333
334
335 type treapIter struct {
336 f treapIterFilter
337 t *treapNode
338 }
339
340
341
342 func (i *treapIter) span() *mspan {
343 return i.t.span
344 }
345
346
347
348 func (i *treapIter) valid() bool {
349 return i.t != nil
350 }
351
352
353
354 func (i treapIter) next() treapIter {
355 i.t = i.t.succ(i.f)
356 return i
357 }
358
359
360
361 func (i treapIter) prev() treapIter {
362 i.t = i.t.pred(i.f)
363 return i
364 }
365
366
367
368 func (root *mTreap) start(mask, match treapIterType) treapIter {
369 f := treapFilter(mask, match)
370 return treapIter{f, root.treap.findMinimal(f)}
371 }
372
373
374
375 func (root *mTreap) end(mask, match treapIterType) treapIter {
376 f := treapFilter(mask, match)
377 return treapIter{f, root.treap.findMaximal(f)}
378 }
379
380
381
382
383
384
385
386
387 func (root *mTreap) mutate(i treapIter, fn func(span *mspan)) {
388 s := i.span()
389
390 hpages := s.hugePages()
391 scavenged := s.scavenged
392
393 fn(s)
394
395 if !scavenged {
396 mheap_.free.unscavHugePages -= hpages
397 }
398 if !s.scavenged {
399 mheap_.free.unscavHugePages += s.hugePages()
400 }
401
402 i.t.key = s.base()
403
404
405
406
407
408 t := i.t
409 for t != nil && t.updateInvariants() {
410 t = t.parent
411 }
412 }
413
414
415 func (root *mTreap) insert(span *mspan) {
416 if !span.scavenged {
417 root.unscavHugePages += span.hugePages()
418 }
419 base := span.base()
420 var last *treapNode
421 pt := &root.treap
422 for t := *pt; t != nil; t = *pt {
423 last = t
424 if t.key < base {
425 pt = &t.right
426 } else if t.key > base {
427 pt = &t.left
428 } else {
429 throw("inserting span already in treap")
430 }
431 }
432
433
434
435
436
437
438
439
440
441
442 t := (*treapNode)(mheap_.treapalloc.alloc())
443 t.key = span.base()
444 t.priority = fastrand()
445 t.span = span
446 t.maxPages = span.npages
447 t.types = span.treapFilter()
448 t.parent = last
449 *pt = t
450
451
452 i := t
453 for i.parent != nil && i.parent.updateInvariants() {
454 i = i.parent
455 }
456
457
458 for t.parent != nil && t.parent.priority > t.priority {
459 if t != nil && t.span.base() != t.key {
460 println("runtime: insert t=", t, "t.key=", t.key)
461 println("runtime: t.span=", t.span, "t.span.base()=", t.span.base())
462 throw("span and treap node base addresses do not match")
463 }
464 if t.parent.left == t {
465 root.rotateRight(t.parent)
466 } else {
467 if t.parent.right != t {
468 throw("treap insert finds a broken treap")
469 }
470 root.rotateLeft(t.parent)
471 }
472 }
473 }
474
475 func (root *mTreap) removeNode(t *treapNode) {
476 if !t.span.scavenged {
477 root.unscavHugePages -= t.span.hugePages()
478 }
479 if t.span.base() != t.key {
480 throw("span and treap node base addresses do not match")
481 }
482
483 for t.right != nil || t.left != nil {
484 if t.right == nil || t.left != nil && t.left.priority < t.right.priority {
485 root.rotateRight(t)
486 } else {
487 root.rotateLeft(t)
488 }
489 }
490
491 if t.parent != nil {
492 p := t.parent
493 if p.left == t {
494 p.left = nil
495 } else {
496 p.right = nil
497 }
498
499 for p != nil && p.updateInvariants() {
500 p = p.parent
501 }
502 } else {
503 root.treap = nil
504 }
505
506 mheap_.treapalloc.free(unsafe.Pointer(t))
507 }
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531 func (root *mTreap) find(npages uintptr) treapIter {
532 t := root.treap
533 for t != nil {
534 if t.span == nil {
535 throw("treap node with nil span found")
536 }
537
538
539
540
541 if t.left != nil && t.left.maxPages >= npages {
542 t = t.left
543 } else if t.span.npages >= npages {
544
545
546 break
547 } else if t.right != nil && t.right.maxPages >= npages {
548 t = t.right
549 } else {
550 t = nil
551 }
552 }
553 return treapIter{treapFilterAll, t}
554 }
555
556
557
558
559
560 func (root *mTreap) removeSpan(span *mspan) {
561 base := span.base()
562 t := root.treap
563 for t.span != span {
564 if t.key < base {
565 t = t.right
566 } else if t.key > base {
567 t = t.left
568 }
569 }
570 root.removeNode(t)
571 }
572
573
574
575
576
577 func (root *mTreap) erase(i treapIter) {
578 root.removeNode(i.t)
579 }
580
581
582
583 func (root *mTreap) rotateLeft(x *treapNode) {
584
585 p := x.parent
586 a, y := x.left, x.right
587 b, c := y.left, y.right
588
589 y.left = x
590 x.parent = y
591 y.right = c
592 if c != nil {
593 c.parent = y
594 }
595 x.left = a
596 if a != nil {
597 a.parent = x
598 }
599 x.right = b
600 if b != nil {
601 b.parent = x
602 }
603
604 y.parent = p
605 if p == nil {
606 root.treap = y
607 } else if p.left == x {
608 p.left = y
609 } else {
610 if p.right != x {
611 throw("large span treap rotateLeft")
612 }
613 p.right = y
614 }
615
616 x.updateInvariants()
617 y.updateInvariants()
618 }
619
620
621
622 func (root *mTreap) rotateRight(y *treapNode) {
623
624 p := y.parent
625 x, c := y.left, y.right
626 a, b := x.left, x.right
627
628 x.left = a
629 if a != nil {
630 a.parent = x
631 }
632 x.right = y
633 y.parent = x
634 y.left = b
635 if b != nil {
636 b.parent = y
637 }
638 y.right = c
639 if c != nil {
640 c.parent = y
641 }
642
643 x.parent = p
644 if p == nil {
645 root.treap = x
646 } else if p.left == y {
647 p.left = x
648 } else {
649 if p.right != y {
650 throw("large span treap rotateRight")
651 }
652 p.right = x
653 }
654
655 y.updateInvariants()
656 x.updateInvariants()
657 }
658
View as plain text