Source file
src/runtime/export_test.go
1
2
3
4
5
6
7 package runtime
8
9 import (
10 "internal/abi"
11 "internal/goarch"
12 "internal/goos"
13 "internal/runtime/atomic"
14 "internal/runtime/gc"
15 "internal/runtime/maps"
16 "internal/runtime/sys"
17 "unsafe"
18 )
19
20 var Fadd64 = fadd64
21 var Fsub64 = fsub64
22 var Fmul64 = fmul64
23 var Fdiv64 = fdiv64
24 var F64to32 = f64to32
25 var F32to64 = f32to64
26 var Fcmp64 = fcmp64
27 var Fintto64 = fintto64
28 var F64toint = f64toint
29
30 var Entersyscall = entersyscall
31 var Exitsyscall = exitsyscall
32 var LockedOSThread = lockedOSThread
33 var Xadduintptr = atomic.Xadduintptr
34
35 var ReadRandomFailed = &readRandomFailed
36
37 var Fastlog2 = fastlog2
38
39 var ParseByteCount = parseByteCount
40
41 var Nanotime = nanotime
42 var Cputicks = cputicks
43 var CyclesPerSecond = pprof_cyclesPerSecond
44 var NetpollBreak = netpollBreak
45 var Usleep = usleep
46
47 var PhysPageSize = physPageSize
48 var PhysHugePageSize = physHugePageSize
49
50 var NetpollGenericInit = netpollGenericInit
51
52 var Memmove = memmove
53 var MemclrNoHeapPointers = memclrNoHeapPointers
54
55 var CgoCheckPointer = cgoCheckPointer
56
57 const CrashStackImplemented = crashStackImplemented
58
59 const TracebackInnerFrames = tracebackInnerFrames
60 const TracebackOuterFrames = tracebackOuterFrames
61
62 var LockPartialOrder = lockPartialOrder
63
64 type TimeTimer = timeTimer
65
66 type LockRank lockRank
67
68 func (l LockRank) String() string {
69 return lockRank(l).String()
70 }
71
72 const PreemptMSupported = preemptMSupported
73
74 type LFNode struct {
75 Next uint64
76 Pushcnt uintptr
77 }
78
79 func LFStackPush(head *uint64, node *LFNode) {
80 (*lfstack)(head).push((*lfnode)(unsafe.Pointer(node)))
81 }
82
83 func LFStackPop(head *uint64) *LFNode {
84 return (*LFNode)((*lfstack)(head).pop())
85 }
86 func LFNodeValidate(node *LFNode) {
87 lfnodeValidate((*lfnode)(unsafe.Pointer(node)))
88 }
89
90 func Netpoll(delta int64) {
91 systemstack(func() {
92 netpoll(delta)
93 })
94 }
95
96 func PointerMask(x any) (ret []byte) {
97 systemstack(func() {
98 ret = pointerMask(x)
99 })
100 return
101 }
102
103 func RunSchedLocalQueueTest() {
104 pp := new(p)
105 gs := make([]g, len(pp.runq))
106 Escape(gs)
107 for i := 0; i < len(pp.runq); i++ {
108 if g, _ := runqget(pp); g != nil {
109 throw("runq is not empty initially")
110 }
111 for j := 0; j < i; j++ {
112 runqput(pp, &gs[i], false)
113 }
114 for j := 0; j < i; j++ {
115 if g, _ := runqget(pp); g != &gs[i] {
116 print("bad element at iter ", i, "/", j, "\n")
117 throw("bad element")
118 }
119 }
120 if g, _ := runqget(pp); g != nil {
121 throw("runq is not empty afterwards")
122 }
123 }
124 }
125
126 func RunSchedLocalQueueStealTest() {
127 p1 := new(p)
128 p2 := new(p)
129 gs := make([]g, len(p1.runq))
130 Escape(gs)
131 for i := 0; i < len(p1.runq); i++ {
132 for j := 0; j < i; j++ {
133 gs[j].sig = 0
134 runqput(p1, &gs[j], false)
135 }
136 gp := runqsteal(p2, p1, true)
137 s := 0
138 if gp != nil {
139 s++
140 gp.sig++
141 }
142 for {
143 gp, _ = runqget(p2)
144 if gp == nil {
145 break
146 }
147 s++
148 gp.sig++
149 }
150 for {
151 gp, _ = runqget(p1)
152 if gp == nil {
153 break
154 }
155 gp.sig++
156 }
157 for j := 0; j < i; j++ {
158 if gs[j].sig != 1 {
159 print("bad element ", j, "(", gs[j].sig, ") at iter ", i, "\n")
160 throw("bad element")
161 }
162 }
163 if s != i/2 && s != i/2+1 {
164 print("bad steal ", s, ", want ", i/2, " or ", i/2+1, ", iter ", i, "\n")
165 throw("bad steal")
166 }
167 }
168 }
169
170 func RunSchedLocalQueueEmptyTest(iters int) {
171
172
173
174
175 done := make(chan bool, 1)
176 p := new(p)
177 gs := make([]g, 2)
178 Escape(gs)
179 ready := new(uint32)
180 for i := 0; i < iters; i++ {
181 *ready = 0
182 next0 := (i & 1) == 0
183 next1 := (i & 2) == 0
184 runqput(p, &gs[0], next0)
185 go func() {
186 for atomic.Xadd(ready, 1); atomic.Load(ready) != 2; {
187 }
188 if runqempty(p) {
189 println("next:", next0, next1)
190 throw("queue is empty")
191 }
192 done <- true
193 }()
194 for atomic.Xadd(ready, 1); atomic.Load(ready) != 2; {
195 }
196 runqput(p, &gs[1], next1)
197 runqget(p)
198 <-done
199 runqget(p)
200 }
201 }
202
203 var (
204 StringHash = stringHash
205 BytesHash = bytesHash
206 Int32Hash = int32Hash
207 Int64Hash = int64Hash
208 MemHash = memhash
209 MemHash32 = memhash32
210 MemHash64 = memhash64
211 EfaceHash = efaceHash
212 IfaceHash = ifaceHash
213 )
214
215 var UseAeshash = &maps.UseAeshash
216
217 func MemclrBytes(b []byte) {
218 s := (*slice)(unsafe.Pointer(&b))
219 memclrNoHeapPointers(s.array, uintptr(s.len))
220 }
221
222 const HashLoad = hashLoad
223
224
225 func GostringW(w []uint16) (s string) {
226 systemstack(func() {
227 s = gostringw(&w[0])
228 })
229 return
230 }
231
232 var Open = open
233 var Close = closefd
234 var Read = read
235 var Write = write
236
237 func Envs() []string { return envs }
238 func SetEnvs(e []string) { envs = e }
239
240 const PtrSize = goarch.PtrSize
241
242 const ClobberdeadPtr = clobberdeadPtr
243
244 func Clobberfree() bool {
245 return debug.clobberfree != 0
246 }
247
248 var ForceGCPeriod = &forcegcperiod
249
250
251
252
253 func SetTracebackEnv(level string) {
254 setTraceback(level)
255 traceback_env = traceback_cache
256 }
257
258 var ReadUnaligned64 = readUnaligned64
259
260 func CountPagesInUse() (pagesInUse, counted uintptr) {
261 stw := stopTheWorld(stwForTestCountPagesInUse)
262
263 pagesInUse = mheap_.pagesInUse.Load()
264
265 for _, s := range mheap_.allspans {
266 if s.state.get() == mSpanInUse {
267 counted += s.npages
268 }
269 }
270
271 startTheWorld(stw)
272
273 return
274 }
275
276 func Blocksampled(cycles, rate int64) bool { return blocksampled(cycles, rate) }
277
278 func Cheaprand() uint32 { return cheaprand() }
279 func Cheaprand64() int64 { return cheaprand64() }
280 func Fastrand() uint32 { return uint32(rand()) }
281 func Fastrand64() uint64 { return rand() }
282 func Fastrandn(n uint32) uint32 { return randn(n) }
283
284 type ProfBuf profBuf
285
286 func NewProfBuf(hdrsize, bufwords, tags int) *ProfBuf {
287 return (*ProfBuf)(newProfBuf(hdrsize, bufwords, tags))
288 }
289
290 func (p *ProfBuf) Write(tag *unsafe.Pointer, now int64, hdr []uint64, stk []uintptr) {
291 (*profBuf)(p).write(tag, now, hdr, stk)
292 }
293
294 const (
295 ProfBufBlocking = profBufBlocking
296 ProfBufNonBlocking = profBufNonBlocking
297 )
298
299 func (p *ProfBuf) Read(mode profBufReadMode) ([]uint64, []unsafe.Pointer, bool) {
300 return (*profBuf)(p).read(mode)
301 }
302
303 func (p *ProfBuf) Close() {
304 (*profBuf)(p).close()
305 }
306
307 type CPUStats = cpuStats
308
309 func ReadCPUStats() CPUStats {
310 return work.cpuStats
311 }
312
313 func ReadMetricsSlow(memStats *MemStats, samplesp unsafe.Pointer, len, cap int) {
314 stw := stopTheWorld(stwForTestReadMetricsSlow)
315
316
317
318 metricsLock()
319 initMetrics()
320
321 systemstack(func() {
322
323
324 getg().racectx = getg().m.curg.racectx
325
326
327
328
329
330
331 readMetricsLocked(samplesp, len, cap)
332
333
334
335
336
337 readmemstats_m(memStats)
338
339
340
341
342 readMetricsLocked(samplesp, len, cap)
343
344
345 getg().racectx = 0
346 })
347 metricsUnlock()
348
349 startTheWorld(stw)
350 }
351
352 var DoubleCheckReadMemStats = &doubleCheckReadMemStats
353
354
355
356 func ReadMemStatsSlow() (base, slow MemStats) {
357 stw := stopTheWorld(stwForTestReadMemStatsSlow)
358
359
360 systemstack(func() {
361
362 getg().m.mallocing++
363
364 readmemstats_m(&base)
365
366
367
368 slow = base
369 slow.Alloc = 0
370 slow.TotalAlloc = 0
371 slow.Mallocs = 0
372 slow.Frees = 0
373 slow.HeapReleased = 0
374 var bySize [gc.NumSizeClasses]struct {
375 Mallocs, Frees uint64
376 }
377
378
379 for _, s := range mheap_.allspans {
380 if s.state.get() != mSpanInUse {
381 continue
382 }
383 if s.isUnusedUserArenaChunk() {
384 continue
385 }
386 if sizeclass := s.spanclass.sizeclass(); sizeclass == 0 {
387 slow.Mallocs++
388 slow.Alloc += uint64(s.elemsize)
389 } else {
390 slow.Mallocs += uint64(s.allocCount)
391 slow.Alloc += uint64(s.allocCount) * uint64(s.elemsize)
392 bySize[sizeclass].Mallocs += uint64(s.allocCount)
393 }
394 }
395
396
397 var m heapStatsDelta
398 memstats.heapStats.unsafeRead(&m)
399
400
401 var smallFree uint64
402 for i := 0; i < gc.NumSizeClasses; i++ {
403 slow.Frees += m.smallFreeCount[i]
404 bySize[i].Frees += m.smallFreeCount[i]
405 bySize[i].Mallocs += m.smallFreeCount[i]
406 smallFree += m.smallFreeCount[i] * uint64(gc.SizeClassToSize[i])
407 }
408 slow.Frees += m.tinyAllocCount + m.largeFreeCount
409 slow.Mallocs += slow.Frees
410
411 slow.TotalAlloc = slow.Alloc + m.largeFree + smallFree
412
413 for i := range slow.BySize {
414 slow.BySize[i].Mallocs = bySize[i].Mallocs
415 slow.BySize[i].Frees = bySize[i].Frees
416 }
417
418 for i := mheap_.pages.start; i < mheap_.pages.end; i++ {
419 chunk := mheap_.pages.tryChunkOf(i)
420 if chunk == nil {
421 continue
422 }
423 pg := chunk.scavenged.popcntRange(0, pallocChunkPages)
424 slow.HeapReleased += uint64(pg) * pageSize
425 }
426 for _, p := range allp {
427
428 pg := sys.OnesCount64(p.pcache.cache & p.pcache.scav)
429 slow.HeapReleased += uint64(pg) * pageSize
430 }
431
432 getg().m.mallocing--
433 })
434
435 startTheWorld(stw)
436 return
437 }
438
439
440
441
442 func ShrinkStackAndVerifyFramePointers() {
443 before := stackPoisonCopy
444 defer func() { stackPoisonCopy = before }()
445 stackPoisonCopy = 1
446
447 gp := getg()
448 systemstack(func() {
449 shrinkstack(gp)
450 })
451
452
453 FPCallers(make([]uintptr, 1024))
454 }
455
456 type StackPoisonCopyRestore int
457
458 func (s StackPoisonCopyRestore) Restore() { stackPoisonCopy = int(s) }
459
460 func StackPoisonCopy() StackPoisonCopyRestore {
461 before := stackPoisonCopy
462 stackPoisonCopy = 1
463 return StackPoisonCopyRestore(before)
464 }
465
466
467
468
469 func BlockOnSystemStack() {
470 systemstack(blockOnSystemStackInternal)
471 }
472
473 func blockOnSystemStackInternal() {
474 print("x\n")
475 lock(&deadlock)
476 lock(&deadlock)
477 }
478
479 type RWMutex struct {
480 rw rwmutex
481 }
482
483 func (rw *RWMutex) Init() {
484 rw.rw.init(lockRankTestR, lockRankTestRInternal, lockRankTestW)
485 }
486
487 func (rw *RWMutex) RLock() {
488 rw.rw.rlock()
489 }
490
491 func (rw *RWMutex) RUnlock() {
492 rw.rw.runlock()
493 }
494
495 func (rw *RWMutex) Lock() {
496 rw.rw.lock()
497 }
498
499 func (rw *RWMutex) Unlock() {
500 rw.rw.unlock()
501 }
502
503 func LockOSCounts() (external, internal uint32) {
504 gp := getg()
505 if gp.m.lockedExt+gp.m.lockedInt == 0 {
506 if gp.lockedm != 0 {
507 panic("lockedm on non-locked goroutine")
508 }
509 } else {
510 if gp.lockedm == 0 {
511 panic("nil lockedm on locked goroutine")
512 }
513 }
514 return gp.m.lockedExt, gp.m.lockedInt
515 }
516
517
518 func TracebackSystemstack(stk []uintptr, i int) int {
519 if i == 0 {
520 pc, sp := sys.GetCallerPC(), sys.GetCallerSP()
521 var u unwinder
522 u.initAt(pc, sp, 0, getg(), unwindJumpStack)
523 return tracebackPCs(&u, 0, stk)
524 }
525 n := 0
526 systemstack(func() {
527 n = TracebackSystemstack(stk, i-1)
528 })
529 return n
530 }
531
532 func KeepNArenaHints(n int) {
533 hint := mheap_.arenaHints
534 for i := 1; i < n; i++ {
535 hint = hint.next
536 if hint == nil {
537 return
538 }
539 }
540 hint.next = nil
541 }
542
543
544
545
546
547
548
549 func MapNextArenaHint() (start, end uintptr, ok bool) {
550 hint := mheap_.arenaHints
551 addr := hint.addr
552 if hint.down {
553 start, end = addr-heapArenaBytes, addr
554 addr -= physPageSize
555 } else {
556 start, end = addr, addr+heapArenaBytes
557 }
558 got := sysReserve(unsafe.Pointer(addr), physPageSize, "")
559 ok = (addr == uintptr(got))
560 if !ok {
561
562
563 sysUnreserve(got, physPageSize)
564 }
565 return
566 }
567
568 func NextArenaHint() (uintptr, bool) {
569 if mheap_.arenaHints == nil {
570 return 0, false
571 }
572 return mheap_.arenaHints.addr, true
573 }
574
575 type G = g
576
577 type Sudog = sudog
578
579 type XRegPerG = xRegPerG
580
581 func Getg() *G {
582 return getg()
583 }
584
585 func Goid() uint64 {
586 return getg().goid
587 }
588
589 func GIsWaitingOnMutex(gp *G) bool {
590 return readgstatus(gp) == _Gwaiting && gp.waitreason.isMutexWait()
591 }
592
593 var CasGStatusAlwaysTrack = &casgstatusAlwaysTrack
594
595
596 func PanicForTesting(b []byte, i int) byte {
597 return unexportedPanicForTesting(b, i)
598 }
599
600
601 func unexportedPanicForTesting(b []byte, i int) byte {
602 return b[i]
603 }
604
605 func G0StackOverflow() {
606 systemstack(func() {
607 g0 := getg()
608 sp := sys.GetCallerSP()
609
610
611
612 g0.stack.lo = sp - 4096 - stackSystem
613 g0.stackguard0 = g0.stack.lo + stackGuard
614 g0.stackguard1 = g0.stackguard0
615
616 stackOverflow(nil)
617 })
618 }
619
620 func stackOverflow(x *byte) {
621 var buf [256]byte
622 stackOverflow(&buf[0])
623 }
624
625 func RunGetgThreadSwitchTest() {
626
627
628
629
630
631
632 ch := make(chan int)
633 go func(ch chan int) {
634 ch <- 5
635 LockOSThread()
636 }(ch)
637
638 g1 := getg()
639
640
641
642
643
644 <-ch
645
646 g2 := getg()
647 if g1 != g2 {
648 panic("g1 != g2")
649 }
650
651
652
653 g3 := getg()
654 if g1 != g3 {
655 panic("g1 != g3")
656 }
657 }
658
659
660 func Freegc(p unsafe.Pointer, size uintptr, noscan bool) {
661 freegc(p, size, noscan)
662 }
663
664
665 func AssistCredit() int64 {
666 assistG := getg()
667 if assistG.m.curg != nil {
668 assistG = assistG.m.curg
669 }
670 return assistG.gcAssistBytes
671 }
672
673
674 func GcBlackenEnable() bool {
675
676
677
678
679
680 return gcBlackenEnabled != 0
681 }
682
683 const SizeSpecializedMallocEnabled = sizeSpecializedMallocEnabled
684
685 const RuntimeFreegcEnabled = runtimeFreegcEnabled
686
687 const (
688 PageSize = pageSize
689 PallocChunkPages = pallocChunkPages
690 PageAlloc64Bit = pageAlloc64Bit
691 PallocSumBytes = pallocSumBytes
692 )
693
694
695 type PallocSum pallocSum
696
697 func PackPallocSum(start, max, end uint) PallocSum { return PallocSum(packPallocSum(start, max, end)) }
698 func (m PallocSum) Start() uint { return pallocSum(m).start() }
699 func (m PallocSum) Max() uint { return pallocSum(m).max() }
700 func (m PallocSum) End() uint { return pallocSum(m).end() }
701
702
703 type PallocBits pallocBits
704
705 func (b *PallocBits) Find(npages uintptr, searchIdx uint) (uint, uint) {
706 return (*pallocBits)(b).find(npages, searchIdx)
707 }
708 func (b *PallocBits) AllocRange(i, n uint) { (*pallocBits)(b).allocRange(i, n) }
709 func (b *PallocBits) Free(i, n uint) { (*pallocBits)(b).free(i, n) }
710 func (b *PallocBits) Summarize() PallocSum { return PallocSum((*pallocBits)(b).summarize()) }
711 func (b *PallocBits) PopcntRange(i, n uint) uint { return (*pageBits)(b).popcntRange(i, n) }
712
713
714
715 func SummarizeSlow(b *PallocBits) PallocSum {
716 var start, most, end uint
717
718 const N = uint(len(b)) * 64
719 for start < N && (*pageBits)(b).get(start) == 0 {
720 start++
721 }
722 for end < N && (*pageBits)(b).get(N-end-1) == 0 {
723 end++
724 }
725 run := uint(0)
726 for i := uint(0); i < N; i++ {
727 if (*pageBits)(b).get(i) == 0 {
728 run++
729 } else {
730 run = 0
731 }
732 most = max(most, run)
733 }
734 return PackPallocSum(start, most, end)
735 }
736
737
738 func FindBitRange64(c uint64, n uint) uint { return findBitRange64(c, n) }
739
740
741
742 func DiffPallocBits(a, b *PallocBits) []BitRange {
743 ba := (*pageBits)(a)
744 bb := (*pageBits)(b)
745
746 var d []BitRange
747 base, size := uint(0), uint(0)
748 for i := uint(0); i < uint(len(ba))*64; i++ {
749 if ba.get(i) != bb.get(i) {
750 if size == 0 {
751 base = i
752 }
753 size++
754 } else {
755 if size != 0 {
756 d = append(d, BitRange{base, size})
757 }
758 size = 0
759 }
760 }
761 if size != 0 {
762 d = append(d, BitRange{base, size})
763 }
764 return d
765 }
766
767
768
769
770 func StringifyPallocBits(b *PallocBits, r BitRange) string {
771 str := ""
772 for j := r.I; j < r.I+r.N; j++ {
773 if (*pageBits)(b).get(j) != 0 {
774 str += "1"
775 } else {
776 str += "0"
777 }
778 }
779 return str
780 }
781
782
783 type PallocData pallocData
784
785 func (d *PallocData) FindScavengeCandidate(searchIdx uint, min, max uintptr) (uint, uint) {
786 return (*pallocData)(d).findScavengeCandidate(searchIdx, min, max)
787 }
788 func (d *PallocData) AllocRange(i, n uint) { (*pallocData)(d).allocRange(i, n) }
789 func (d *PallocData) ScavengedSetRange(i, n uint) {
790 (*pallocData)(d).scavenged.setRange(i, n)
791 }
792 func (d *PallocData) PallocBits() *PallocBits {
793 return (*PallocBits)(&(*pallocData)(d).pallocBits)
794 }
795 func (d *PallocData) Scavenged() *PallocBits {
796 return (*PallocBits)(&(*pallocData)(d).scavenged)
797 }
798
799
800 func FillAligned(x uint64, m uint) uint64 { return fillAligned(x, m) }
801
802
803 type PageCache pageCache
804
805 const PageCachePages = pageCachePages
806
807 func NewPageCache(base uintptr, cache, scav uint64) PageCache {
808 return PageCache(pageCache{base: base, cache: cache, scav: scav})
809 }
810 func (c *PageCache) Empty() bool { return (*pageCache)(c).empty() }
811 func (c *PageCache) Base() uintptr { return (*pageCache)(c).base }
812 func (c *PageCache) Cache() uint64 { return (*pageCache)(c).cache }
813 func (c *PageCache) Scav() uint64 { return (*pageCache)(c).scav }
814 func (c *PageCache) Alloc(npages uintptr) (uintptr, uintptr) {
815 return (*pageCache)(c).alloc(npages)
816 }
817 func (c *PageCache) Flush(s *PageAlloc) {
818 cp := (*pageCache)(c)
819 sp := (*pageAlloc)(s)
820
821 systemstack(func() {
822
823
824 lock(sp.mheapLock)
825 cp.flush(sp)
826 unlock(sp.mheapLock)
827 })
828 }
829
830
831 type ChunkIdx chunkIdx
832
833
834
835 type PageAlloc pageAlloc
836
837 func (p *PageAlloc) Alloc(npages uintptr) (uintptr, uintptr) {
838 pp := (*pageAlloc)(p)
839
840 var addr, scav uintptr
841 systemstack(func() {
842
843
844 lock(pp.mheapLock)
845 addr, scav = pp.alloc(npages)
846 unlock(pp.mheapLock)
847 })
848 return addr, scav
849 }
850 func (p *PageAlloc) AllocToCache() PageCache {
851 pp := (*pageAlloc)(p)
852
853 var c PageCache
854 systemstack(func() {
855
856
857 lock(pp.mheapLock)
858 c = PageCache(pp.allocToCache())
859 unlock(pp.mheapLock)
860 })
861 return c
862 }
863 func (p *PageAlloc) Free(base, npages uintptr) {
864 pp := (*pageAlloc)(p)
865
866 systemstack(func() {
867
868
869 lock(pp.mheapLock)
870 pp.free(base, npages)
871 unlock(pp.mheapLock)
872 })
873 }
874 func (p *PageAlloc) Bounds() (ChunkIdx, ChunkIdx) {
875 return ChunkIdx((*pageAlloc)(p).start), ChunkIdx((*pageAlloc)(p).end)
876 }
877 func (p *PageAlloc) Scavenge(nbytes uintptr) (r uintptr) {
878 pp := (*pageAlloc)(p)
879 systemstack(func() {
880 r = pp.scavenge(nbytes, nil, true)
881 })
882 return
883 }
884 func (p *PageAlloc) InUse() []AddrRange {
885 ranges := make([]AddrRange, 0, len(p.inUse.ranges))
886 for _, r := range p.inUse.ranges {
887 ranges = append(ranges, AddrRange{r})
888 }
889 return ranges
890 }
891
892
893 func (p *PageAlloc) PallocData(i ChunkIdx) *PallocData {
894 ci := chunkIdx(i)
895 return (*PallocData)((*pageAlloc)(p).tryChunkOf(ci))
896 }
897
898
899 type AddrRange struct {
900 addrRange
901 }
902
903
904 func MakeAddrRange(base, limit uintptr) AddrRange {
905 return AddrRange{makeAddrRange(base, limit)}
906 }
907
908
909 func (a AddrRange) Base() uintptr {
910 return a.addrRange.base.addr()
911 }
912
913
914 func (a AddrRange) Limit() uintptr {
915 return a.addrRange.limit.addr()
916 }
917
918
919 func (a AddrRange) Equals(b AddrRange) bool {
920 return a == b
921 }
922
923
924 func (a AddrRange) Size() uintptr {
925 return a.addrRange.size()
926 }
927
928
929
930
931
932 var testSysStat = &memstats.other_sys
933
934
935 type AddrRanges struct {
936 addrRanges
937 mutable bool
938 }
939
940
941
942
943
944
945
946
947
948
949 func NewAddrRanges() AddrRanges {
950 r := addrRanges{}
951 r.init(testSysStat)
952 return AddrRanges{r, true}
953 }
954
955
956
957
958
959
960 func MakeAddrRanges(a ...AddrRange) AddrRanges {
961
962
963
964
965
966 ranges := make([]addrRange, 0, len(a))
967 total := uintptr(0)
968 for _, r := range a {
969 ranges = append(ranges, r.addrRange)
970 total += r.Size()
971 }
972 return AddrRanges{addrRanges{
973 ranges: ranges,
974 totalBytes: total,
975 sysStat: testSysStat,
976 }, false}
977 }
978
979
980
981 func (a *AddrRanges) Ranges() []AddrRange {
982 result := make([]AddrRange, 0, len(a.addrRanges.ranges))
983 for _, r := range a.addrRanges.ranges {
984 result = append(result, AddrRange{r})
985 }
986 return result
987 }
988
989
990
991 func (a *AddrRanges) FindSucc(base uintptr) int {
992 return a.findSucc(base)
993 }
994
995
996
997
998
999 func (a *AddrRanges) Add(r AddrRange) {
1000 if !a.mutable {
1001 throw("attempt to mutate immutable AddrRanges")
1002 }
1003 a.add(r.addrRange)
1004 }
1005
1006
1007 func (a *AddrRanges) TotalBytes() uintptr {
1008 return a.addrRanges.totalBytes
1009 }
1010
1011
1012 type BitRange struct {
1013 I, N uint
1014 }
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030 func NewPageAlloc(chunks, scav map[ChunkIdx][]BitRange) *PageAlloc {
1031 p := new(pageAlloc)
1032
1033
1034 p.init(new(mutex), testSysStat, true)
1035 lockInit(p.mheapLock, lockRankMheap)
1036 for i, init := range chunks {
1037 addr := chunkBase(chunkIdx(i))
1038
1039
1040 systemstack(func() {
1041 lock(p.mheapLock)
1042 p.grow(addr, pallocChunkBytes)
1043 unlock(p.mheapLock)
1044 })
1045
1046
1047 ci := chunkIndex(addr)
1048 chunk := p.chunkOf(ci)
1049
1050
1051 chunk.scavenged.clearRange(0, pallocChunkPages)
1052
1053
1054
1055
1056 p.scav.index.alloc(ci, pallocChunkPages)
1057 p.scav.index.free(ci, 0, pallocChunkPages)
1058
1059
1060 if scav != nil {
1061 if scvg, ok := scav[i]; ok {
1062 for _, s := range scvg {
1063
1064
1065 if s.N != 0 {
1066 chunk.scavenged.setRange(s.I, s.N)
1067 }
1068 }
1069 }
1070 }
1071
1072
1073 for _, s := range init {
1074
1075
1076 if s.N != 0 {
1077 chunk.allocRange(s.I, s.N)
1078
1079
1080 p.scav.index.alloc(ci, s.N)
1081 }
1082 }
1083
1084
1085 systemstack(func() {
1086 lock(p.mheapLock)
1087 p.update(addr, pallocChunkPages, false, false)
1088 unlock(p.mheapLock)
1089 })
1090 }
1091
1092 return (*PageAlloc)(p)
1093 }
1094
1095
1096
1097
1098 func FreePageAlloc(pp *PageAlloc) {
1099 p := (*pageAlloc)(pp)
1100
1101
1102 if pageAlloc64Bit != 0 {
1103 for l := 0; l < summaryLevels; l++ {
1104
1105
1106
1107
1108 sysUnreserve(unsafe.Pointer(&p.summary[l][0]), uintptr(cap(p.summary[l]))*pallocSumBytes)
1109 }
1110 } else {
1111 resSize := uintptr(0)
1112 for _, s := range p.summary {
1113 resSize += uintptr(cap(s)) * pallocSumBytes
1114 }
1115
1116 sysUnreserve(unsafe.Pointer(&p.summary[0][0]), alignUp(resSize, physPageSize))
1117 }
1118
1119
1120
1121
1122
1123 gcController.mappedReady.Add(-int64(p.summaryMappedReady))
1124 testSysStat.add(-int64(p.summaryMappedReady))
1125
1126
1127
1128
1129
1130 sysUnreserve(unsafe.Pointer(&p.scav.index.chunks[0]), uintptr(cap(p.scav.index.chunks))*unsafe.Sizeof(atomicScavChunkData{}))
1131
1132
1133 for i := range p.chunks {
1134 if x := p.chunks[i]; x != nil {
1135 p.chunks[i] = nil
1136
1137 sysFree(unsafe.Pointer(x), unsafe.Sizeof(*p.chunks[0]), testSysStat)
1138 }
1139 }
1140 }
1141
1142
1143
1144
1145
1146
1147
1148 var BaseChunkIdx = func() ChunkIdx {
1149 var prefix uintptr
1150 if pageAlloc64Bit != 0 {
1151 prefix = 0xc000
1152 } else {
1153 prefix = 0x100
1154 }
1155 baseAddr := prefix * pallocChunkBytes
1156 if goos.IsAix != 0 {
1157 baseAddr += arenaBaseOffset
1158 }
1159 return ChunkIdx(chunkIndex(baseAddr))
1160 }()
1161
1162
1163
1164 func PageBase(c ChunkIdx, pageIdx uint) uintptr {
1165 return chunkBase(chunkIdx(c)) + uintptr(pageIdx)*pageSize
1166 }
1167
1168 type BitsMismatch struct {
1169 Base uintptr
1170 Got, Want uint64
1171 }
1172
1173 func CheckScavengedBitsCleared(mismatches []BitsMismatch) (n int, ok bool) {
1174 ok = true
1175
1176
1177 systemstack(func() {
1178 getg().m.mallocing++
1179
1180
1181 lock(&mheap_.lock)
1182
1183 chunkLoop:
1184 for i := mheap_.pages.start; i < mheap_.pages.end; i++ {
1185 chunk := mheap_.pages.tryChunkOf(i)
1186 if chunk == nil {
1187 continue
1188 }
1189 cb := chunkBase(i)
1190 for j := 0; j < pallocChunkPages/64; j++ {
1191
1192
1193
1194
1195
1196 want := chunk.scavenged[j] &^ chunk.pallocBits[j]
1197 got := chunk.scavenged[j]
1198 if want != got {
1199 ok = false
1200 if n >= len(mismatches) {
1201 break chunkLoop
1202 }
1203 mismatches[n] = BitsMismatch{
1204 Base: cb + uintptr(j)*64*pageSize,
1205 Got: got,
1206 Want: want,
1207 }
1208 n++
1209 }
1210 }
1211 }
1212 unlock(&mheap_.lock)
1213
1214 getg().m.mallocing--
1215 })
1216
1217 if randomizeHeapBase && len(mismatches) > 0 {
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232 affectedArenas := map[arenaIdx]bool{}
1233 for _, mismatch := range mismatches {
1234 if mismatch.Base > 0 {
1235 affectedArenas[arenaIndex(mismatch.Base)] = true
1236 }
1237 }
1238 if len(affectedArenas) == 1 {
1239 ok = true
1240
1241 for i := range n {
1242 mismatches[i] = BitsMismatch{}
1243 }
1244 }
1245 }
1246
1247 return
1248 }
1249
1250 func PageCachePagesLeaked() (leaked uintptr) {
1251 stw := stopTheWorld(stwForTestPageCachePagesLeaked)
1252
1253
1254 deadp := allp[len(allp):cap(allp)]
1255 for _, p := range deadp {
1256
1257
1258 if p != nil {
1259 leaked += uintptr(sys.OnesCount64(p.pcache.cache))
1260 }
1261 }
1262
1263 startTheWorld(stw)
1264 return
1265 }
1266
1267 var ProcYield = procyield
1268 var OSYield = osyield
1269
1270 type Mutex = mutex
1271
1272 var Lock = lock
1273 var Unlock = unlock
1274
1275 var MutexContended = mutexContended
1276
1277 func SemRootLock(addr *uint32) *mutex {
1278 root := semtable.rootFor(addr)
1279 return &root.lock
1280 }
1281
1282 var Semacquire = semacquire
1283 var Semrelease1 = semrelease1
1284
1285 func SemNwait(addr *uint32) uint32 {
1286 root := semtable.rootFor(addr)
1287 return root.nwait.Load()
1288 }
1289
1290 const SemTableSize = semTabSize
1291
1292
1293 type SemTable struct {
1294 semTable
1295 }
1296
1297
1298 func (t *SemTable) Enqueue(addr *uint32) {
1299 s := acquireSudog()
1300 s.releasetime = 0
1301 s.acquiretime = 0
1302 s.ticket = 0
1303 t.semTable.rootFor(addr).queue(addr, s, false)
1304 }
1305
1306
1307
1308
1309 func (t *SemTable) Dequeue(addr *uint32) bool {
1310 s, _, _ := t.semTable.rootFor(addr).dequeue(addr)
1311 if s != nil {
1312 releaseSudog(s)
1313 return true
1314 }
1315 return false
1316 }
1317
1318
1319 type MSpan mspan
1320
1321
1322 func AllocMSpan() *MSpan {
1323 var s *mspan
1324 systemstack(func() {
1325 lock(&mheap_.lock)
1326 s = (*mspan)(mheap_.spanalloc.alloc())
1327 s.init(0, 0)
1328 unlock(&mheap_.lock)
1329 })
1330 return (*MSpan)(s)
1331 }
1332
1333
1334 func FreeMSpan(s *MSpan) {
1335 systemstack(func() {
1336 lock(&mheap_.lock)
1337 mheap_.spanalloc.free(unsafe.Pointer(s))
1338 unlock(&mheap_.lock)
1339 })
1340 }
1341
1342 func MSpanCountAlloc(ms *MSpan, bits []byte) int {
1343 s := (*mspan)(ms)
1344 s.nelems = uint16(len(bits) * 8)
1345 s.gcmarkBits = (*gcBits)(unsafe.Pointer(&bits[0]))
1346 result := s.countAlloc()
1347 s.gcmarkBits = nil
1348 return result
1349 }
1350
1351 const (
1352 TimeHistSubBucketBits = timeHistSubBucketBits
1353 TimeHistNumSubBuckets = timeHistNumSubBuckets
1354 TimeHistNumBuckets = timeHistNumBuckets
1355 TimeHistMinBucketBits = timeHistMinBucketBits
1356 TimeHistMaxBucketBits = timeHistMaxBucketBits
1357 )
1358
1359 type TimeHistogram timeHistogram
1360
1361
1362
1363
1364
1365 func (th *TimeHistogram) Count(bucket, subBucket int) (uint64, bool) {
1366 t := (*timeHistogram)(th)
1367 if bucket < 0 {
1368 return t.underflow.Load(), false
1369 }
1370 i := bucket*TimeHistNumSubBuckets + subBucket
1371 if i >= len(t.counts) {
1372 return t.overflow.Load(), false
1373 }
1374 return t.counts[i].Load(), true
1375 }
1376
1377 func (th *TimeHistogram) Record(duration int64) {
1378 (*timeHistogram)(th).record(duration)
1379 }
1380
1381 var TimeHistogramMetricsBuckets = timeHistogramMetricsBuckets
1382
1383 func SetIntArgRegs(a int) int {
1384 lock(&finlock)
1385 old := intArgRegs
1386 if a >= 0 {
1387 intArgRegs = a
1388 }
1389 unlock(&finlock)
1390 return old
1391 }
1392
1393 func FinalizerGAsleep() bool {
1394 return fingStatus.Load()&fingWait != 0
1395 }
1396
1397
1398
1399
1400 var GCTestMoveStackOnNextCall = gcTestMoveStackOnNextCall
1401
1402
1403
1404 func GCTestIsReachable(ptrs ...unsafe.Pointer) (mask uint64) {
1405 return gcTestIsReachable(ptrs...)
1406 }
1407
1408
1409
1410
1411
1412
1413
1414 func GCTestPointerClass(p unsafe.Pointer) string {
1415 return gcTestPointerClass(p)
1416 }
1417
1418 const Raceenabled = raceenabled
1419
1420 const (
1421 GCBackgroundUtilization = gcBackgroundUtilization
1422 GCGoalUtilization = gcGoalUtilization
1423 DefaultHeapMinimum = defaultHeapMinimum
1424 MemoryLimitHeapGoalHeadroomPercent = memoryLimitHeapGoalHeadroomPercent
1425 MemoryLimitMinHeapGoalHeadroom = memoryLimitMinHeapGoalHeadroom
1426 )
1427
1428 type GCController struct {
1429 gcControllerState
1430 }
1431
1432 func NewGCController(gcPercent int, memoryLimit int64) *GCController {
1433
1434
1435
1436
1437 g := Escape(new(GCController))
1438 g.gcControllerState.test = true
1439 g.init(int32(gcPercent), memoryLimit)
1440 return g
1441 }
1442
1443 func (c *GCController) StartCycle(stackSize, globalsSize uint64, scannableFrac float64, gomaxprocs int) {
1444 trigger, _ := c.trigger()
1445 if c.heapMarked > trigger {
1446 trigger = c.heapMarked
1447 }
1448 c.maxStackScan.Store(stackSize)
1449 c.globalsScan.Store(globalsSize)
1450 c.heapLive.Store(trigger)
1451 c.heapScan.Add(int64(float64(trigger-c.heapMarked) * scannableFrac))
1452 c.startCycle(0, gomaxprocs, gcTrigger{kind: gcTriggerHeap})
1453 }
1454
1455 func (c *GCController) AssistWorkPerByte() float64 {
1456 return c.assistWorkPerByte.Load()
1457 }
1458
1459 func (c *GCController) HeapGoal() uint64 {
1460 return c.heapGoal()
1461 }
1462
1463 func (c *GCController) HeapLive() uint64 {
1464 return c.heapLive.Load()
1465 }
1466
1467 func (c *GCController) HeapMarked() uint64 {
1468 return c.heapMarked
1469 }
1470
1471 func (c *GCController) Triggered() uint64 {
1472 return c.triggered
1473 }
1474
1475 type GCControllerReviseDelta struct {
1476 HeapLive int64
1477 HeapScan int64
1478 HeapScanWork int64
1479 StackScanWork int64
1480 GlobalsScanWork int64
1481 }
1482
1483 func (c *GCController) Revise(d GCControllerReviseDelta) {
1484 c.heapLive.Add(d.HeapLive)
1485 c.heapScan.Add(d.HeapScan)
1486 c.heapScanWork.Add(d.HeapScanWork)
1487 c.stackScanWork.Add(d.StackScanWork)
1488 c.globalsScanWork.Add(d.GlobalsScanWork)
1489 c.revise()
1490 }
1491
1492 func (c *GCController) EndCycle(bytesMarked uint64, assistTime, elapsed int64, gomaxprocs int) {
1493 c.assistTime.Store(assistTime)
1494 c.endCycle(elapsed, gomaxprocs)
1495 c.resetLive(bytesMarked)
1496 c.commit(false)
1497 }
1498
1499 func (c *GCController) AddIdleMarkWorker() bool {
1500 return c.addIdleMarkWorker()
1501 }
1502
1503 func (c *GCController) NeedIdleMarkWorker() bool {
1504 return c.needIdleMarkWorker()
1505 }
1506
1507 func (c *GCController) RemoveIdleMarkWorker() {
1508 c.removeIdleMarkWorker()
1509 }
1510
1511 func (c *GCController) SetMaxIdleMarkWorkers(max int32) {
1512 c.setMaxIdleMarkWorkers(max)
1513 }
1514
1515 var alwaysFalse bool
1516 var escapeSink any
1517
1518 func Escape[T any](x T) T {
1519 if alwaysFalse {
1520 escapeSink = x
1521 }
1522 return x
1523 }
1524
1525
1526 func Acquirem() {
1527 acquirem()
1528 }
1529
1530 func Releasem() {
1531 releasem(getg().m)
1532 }
1533
1534
1535
1536
1537
1538
1539 func GoschedIfBusy() {
1540 goschedIfBusy()
1541 }
1542
1543 type PIController struct {
1544 piController
1545 }
1546
1547 func NewPIController(kp, ti, tt, min, max float64) *PIController {
1548 return &PIController{piController{
1549 kp: kp,
1550 ti: ti,
1551 tt: tt,
1552 min: min,
1553 max: max,
1554 }}
1555 }
1556
1557 func (c *PIController) Next(input, setpoint, period float64) (float64, bool) {
1558 return c.piController.next(input, setpoint, period)
1559 }
1560
1561 const (
1562 CapacityPerProc = capacityPerProc
1563 GCCPULimiterUpdatePeriod = gcCPULimiterUpdatePeriod
1564 )
1565
1566 type GCCPULimiter struct {
1567 limiter gcCPULimiterState
1568 }
1569
1570 func NewGCCPULimiter(now int64, gomaxprocs int32) *GCCPULimiter {
1571
1572
1573
1574
1575 l := Escape(new(GCCPULimiter))
1576 l.limiter.test = true
1577 l.limiter.resetCapacity(now, gomaxprocs)
1578 return l
1579 }
1580
1581 func (l *GCCPULimiter) Fill() uint64 {
1582 return l.limiter.bucket.fill
1583 }
1584
1585 func (l *GCCPULimiter) Capacity() uint64 {
1586 return l.limiter.bucket.capacity
1587 }
1588
1589 func (l *GCCPULimiter) Overflow() uint64 {
1590 return l.limiter.overflow
1591 }
1592
1593 func (l *GCCPULimiter) Limiting() bool {
1594 return l.limiter.limiting()
1595 }
1596
1597 func (l *GCCPULimiter) NeedUpdate(now int64) bool {
1598 return l.limiter.needUpdate(now)
1599 }
1600
1601 func (l *GCCPULimiter) StartGCTransition(enableGC bool, now int64) {
1602 l.limiter.startGCTransition(enableGC, now)
1603 }
1604
1605 func (l *GCCPULimiter) FinishGCTransition(now int64) {
1606 l.limiter.finishGCTransition(now)
1607 }
1608
1609 func (l *GCCPULimiter) Update(now int64) {
1610 l.limiter.update(now)
1611 }
1612
1613 func (l *GCCPULimiter) AddAssistTime(t int64) {
1614 l.limiter.addAssistTime(t)
1615 }
1616
1617 func (l *GCCPULimiter) ResetCapacity(now int64, nprocs int32) {
1618 l.limiter.resetCapacity(now, nprocs)
1619 }
1620
1621 const ScavengePercent = scavengePercent
1622
1623 type Scavenger struct {
1624 Sleep func(int64) int64
1625 Scavenge func(uintptr) (uintptr, int64)
1626 ShouldStop func() bool
1627 GoMaxProcs func() int32
1628
1629 released atomic.Uintptr
1630 scavenger scavengerState
1631 stop chan<- struct{}
1632 done <-chan struct{}
1633 }
1634
1635 func (s *Scavenger) Start() {
1636 if s.Sleep == nil || s.Scavenge == nil || s.ShouldStop == nil || s.GoMaxProcs == nil {
1637 panic("must populate all stubs")
1638 }
1639
1640
1641 s.scavenger.sleepStub = s.Sleep
1642 s.scavenger.scavenge = s.Scavenge
1643 s.scavenger.shouldStop = s.ShouldStop
1644 s.scavenger.gomaxprocs = s.GoMaxProcs
1645
1646
1647 stop := make(chan struct{})
1648 s.stop = stop
1649 done := make(chan struct{})
1650 s.done = done
1651 go func() {
1652
1653 s.scavenger.init()
1654 s.scavenger.park()
1655 for {
1656 select {
1657 case <-stop:
1658 close(done)
1659 return
1660 default:
1661 }
1662 released, workTime := s.scavenger.run()
1663 if released == 0 {
1664 s.scavenger.park()
1665 continue
1666 }
1667 s.released.Add(released)
1668 s.scavenger.sleep(workTime)
1669 }
1670 }()
1671 if !s.BlockUntilParked(1e9 ) {
1672 panic("timed out waiting for scavenger to get ready")
1673 }
1674 }
1675
1676
1677
1678
1679
1680
1681
1682 func (s *Scavenger) BlockUntilParked(timeout int64) bool {
1683
1684
1685
1686
1687
1688 start := nanotime()
1689 for nanotime()-start < timeout {
1690 lock(&s.scavenger.lock)
1691 parked := s.scavenger.parked
1692 unlock(&s.scavenger.lock)
1693 if parked {
1694 return true
1695 }
1696 Gosched()
1697 }
1698 return false
1699 }
1700
1701
1702 func (s *Scavenger) Released() uintptr {
1703 return s.released.Load()
1704 }
1705
1706
1707 func (s *Scavenger) Wake() {
1708 s.scavenger.wake()
1709 }
1710
1711
1712
1713 func (s *Scavenger) Stop() {
1714 lock(&s.scavenger.lock)
1715 parked := s.scavenger.parked
1716 unlock(&s.scavenger.lock)
1717 if !parked {
1718 panic("tried to clean up scavenger that is not parked")
1719 }
1720 close(s.stop)
1721 s.Wake()
1722 <-s.done
1723 }
1724
1725 type ScavengeIndex struct {
1726 i scavengeIndex
1727 }
1728
1729 func NewScavengeIndex(min, max ChunkIdx) *ScavengeIndex {
1730 s := new(ScavengeIndex)
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742 s.i.chunks = make([]atomicScavChunkData, max)
1743 s.i.min.Store(uintptr(min))
1744 s.i.max.Store(uintptr(max))
1745 s.i.minHeapIdx.Store(uintptr(min))
1746 s.i.test = true
1747 return s
1748 }
1749
1750 func (s *ScavengeIndex) Find(force bool) (ChunkIdx, uint) {
1751 ci, off := s.i.find(force)
1752 return ChunkIdx(ci), off
1753 }
1754
1755 func (s *ScavengeIndex) AllocRange(base, limit uintptr) {
1756 sc, ec := chunkIndex(base), chunkIndex(limit-1)
1757 si, ei := chunkPageIndex(base), chunkPageIndex(limit-1)
1758
1759 if sc == ec {
1760
1761 s.i.alloc(sc, ei+1-si)
1762 } else {
1763
1764 s.i.alloc(sc, pallocChunkPages-si)
1765 for c := sc + 1; c < ec; c++ {
1766 s.i.alloc(c, pallocChunkPages)
1767 }
1768 s.i.alloc(ec, ei+1)
1769 }
1770 }
1771
1772 func (s *ScavengeIndex) FreeRange(base, limit uintptr) {
1773 sc, ec := chunkIndex(base), chunkIndex(limit-1)
1774 si, ei := chunkPageIndex(base), chunkPageIndex(limit-1)
1775
1776 if sc == ec {
1777
1778 s.i.free(sc, si, ei+1-si)
1779 } else {
1780
1781 s.i.free(sc, si, pallocChunkPages-si)
1782 for c := sc + 1; c < ec; c++ {
1783 s.i.free(c, 0, pallocChunkPages)
1784 }
1785 s.i.free(ec, 0, ei+1)
1786 }
1787 }
1788
1789 func (s *ScavengeIndex) ResetSearchAddrs() {
1790 for _, a := range []*atomicOffAddr{&s.i.searchAddrBg, &s.i.searchAddrForce} {
1791 addr, marked := a.Load()
1792 if marked {
1793 a.StoreUnmark(addr, addr)
1794 }
1795 a.Clear()
1796 }
1797 s.i.freeHWM = minOffAddr
1798 }
1799
1800 func (s *ScavengeIndex) NextGen() {
1801 s.i.nextGen()
1802 }
1803
1804 func (s *ScavengeIndex) SetEmpty(ci ChunkIdx) {
1805 s.i.setEmpty(chunkIdx(ci))
1806 }
1807
1808 func CheckPackScavChunkData(gen uint32, inUse, lastInUse uint16, flags uint8) bool {
1809 sc0 := scavChunkData{
1810 gen: gen,
1811 inUse: inUse,
1812 lastInUse: lastInUse,
1813 scavChunkFlags: scavChunkFlags(flags),
1814 }
1815 scp := sc0.pack()
1816 sc1 := unpackScavChunkData(scp)
1817 return sc0 == sc1
1818 }
1819
1820 const GTrackingPeriod = gTrackingPeriod
1821
1822 var ZeroBase = unsafe.Pointer(&zerobase)
1823
1824 const UserArenaChunkBytes = userArenaChunkBytes
1825
1826 type UserArena struct {
1827 arena *userArena
1828 }
1829
1830 func NewUserArena() *UserArena {
1831 return &UserArena{newUserArena()}
1832 }
1833
1834 func (a *UserArena) New(out *any) {
1835 i := efaceOf(out)
1836 typ := i._type
1837 if typ.Kind() != abi.Pointer {
1838 panic("new result of non-ptr type")
1839 }
1840 typ = (*ptrtype)(unsafe.Pointer(typ)).Elem
1841 i.data = a.arena.new(typ)
1842 }
1843
1844 func (a *UserArena) Slice(sl any, cap int) {
1845 a.arena.slice(sl, cap)
1846 }
1847
1848 func (a *UserArena) Free() {
1849 a.arena.free()
1850 }
1851
1852 func GlobalWaitingArenaChunks() int {
1853 n := 0
1854 systemstack(func() {
1855 lock(&mheap_.lock)
1856 for s := mheap_.userArena.quarantineList.first; s != nil; s = s.next {
1857 n++
1858 }
1859 unlock(&mheap_.lock)
1860 })
1861 return n
1862 }
1863
1864 func UserArenaClone[T any](s T) T {
1865 return arena_heapify(s).(T)
1866 }
1867
1868 var AlignUp = alignUp
1869
1870 func BlockUntilEmptyFinalizerQueue(timeout int64) bool {
1871 return blockUntilEmptyFinalizerQueue(timeout)
1872 }
1873
1874 func BlockUntilEmptyCleanupQueue(timeout int64) bool {
1875 return gcCleanups.blockUntilEmpty(timeout)
1876 }
1877
1878 func FrameStartLine(f *Frame) int {
1879 return f.startLine
1880 }
1881
1882
1883
1884 func PersistentAlloc(n, align uintptr) unsafe.Pointer {
1885 return persistentalloc(n, align, &memstats.other_sys)
1886 }
1887
1888 const TagAlign = tagAlign
1889
1890
1891
1892 func FPCallers(pcBuf []uintptr) int {
1893 return fpTracebackPCs(unsafe.Pointer(getfp()), pcBuf)
1894 }
1895
1896 const FramePointerEnabled = framepointer_enabled
1897
1898 var (
1899 IsPinned = isPinned
1900 GetPinCounter = pinnerGetPinCounter
1901 )
1902
1903 func SetPinnerLeakPanic(f func()) {
1904 pinnerLeakPanic = f
1905 }
1906 func GetPinnerLeakPanic() func() {
1907 return pinnerLeakPanic
1908 }
1909
1910 var testUintptr uintptr
1911
1912 func MyGenericFunc[T any]() {
1913 systemstack(func() {
1914 testUintptr = 4
1915 })
1916 }
1917
1918 func UnsafePoint(pc uintptr) bool {
1919 fi := findfunc(pc)
1920 v := pcdatavalue(fi, abi.PCDATA_UnsafePoint, pc)
1921 switch v {
1922 case abi.UnsafePointUnsafe:
1923 return true
1924 case abi.UnsafePointSafe:
1925 return false
1926 case abi.UnsafePointRestart1, abi.UnsafePointRestart2, abi.UnsafePointRestartAtEntry:
1927
1928
1929 return false
1930 default:
1931 var buf [20]byte
1932 panic("invalid unsafe point code " + string(itoa(buf[:], uint64(v))))
1933 }
1934 }
1935
1936 type TraceMap struct {
1937 traceMap
1938 }
1939
1940 func (m *TraceMap) PutString(s string) (uint64, bool) {
1941 return m.traceMap.put(unsafe.Pointer(unsafe.StringData(s)), uintptr(len(s)))
1942 }
1943
1944 func (m *TraceMap) Reset() {
1945 m.traceMap.reset()
1946 }
1947
1948 func SetSpinInGCMarkDone(spin bool) {
1949 gcDebugMarkDone.spinAfterRaggedBarrier.Store(spin)
1950 }
1951
1952 func GCMarkDoneRestarted() bool {
1953
1954 mp := acquirem()
1955 if gcphase != _GCoff {
1956 releasem(mp)
1957 return false
1958 }
1959 restarted := gcDebugMarkDone.restartedDueTo27993
1960 releasem(mp)
1961 return restarted
1962 }
1963
1964 func GCMarkDoneResetRestartFlag() {
1965 mp := acquirem()
1966 for gcphase != _GCoff {
1967 releasem(mp)
1968 Gosched()
1969 mp = acquirem()
1970 }
1971 gcDebugMarkDone.restartedDueTo27993 = false
1972 releasem(mp)
1973 }
1974
1975 type BitCursor struct {
1976 b bitCursor
1977 }
1978
1979 func NewBitCursor(buf *byte) BitCursor {
1980 return BitCursor{b: bitCursor{ptr: buf, n: 0}}
1981 }
1982
1983 func (b BitCursor) Write(data *byte, cnt uintptr) {
1984 b.b.write(data, cnt)
1985 }
1986 func (b BitCursor) Offset(cnt uintptr) BitCursor {
1987 return BitCursor{b: b.b.offset(cnt)}
1988 }
1989
1990 const (
1991 BubbleAssocUnbubbled = bubbleAssocUnbubbled
1992 BubbleAssocCurrentBubble = bubbleAssocCurrentBubble
1993 BubbleAssocOtherBubble = bubbleAssocOtherBubble
1994 )
1995
1996 type TraceStackTable traceStackTable
1997
1998 func (t *TraceStackTable) Reset() {
1999 t.tab.reset()
2000 }
2001
2002 func TraceStack(gp *G, tab *TraceStackTable) {
2003 traceStack(0, gp, (*traceStackTable)(tab))
2004 }
2005
2006 var X86HasAVX = &x86HasAVX
2007
2008 var DebugDecorateMappings = &debug.decoratemappings
2009
2010 func SetVMANameSupported() bool { return setVMANameSupported() }
2011
2012 type ListHead struct {
2013 l listHead
2014 }
2015
2016 func (head *ListHead) Init(off uintptr) {
2017 head.l.init(off)
2018 }
2019
2020 type ListNode struct {
2021 l listNode
2022 }
2023
2024 func (head *ListHead) Push(p unsafe.Pointer) {
2025 head.l.push(p)
2026 }
2027
2028 func (head *ListHead) Pop() unsafe.Pointer {
2029 return head.l.pop()
2030 }
2031
2032 func (head *ListHead) Remove(p unsafe.Pointer) {
2033 head.l.remove(p)
2034 }
2035
2036 type ListHeadManual struct {
2037 l listHeadManual
2038 }
2039
2040 func (head *ListHeadManual) Init(off uintptr) {
2041 head.l.init(off)
2042 }
2043
2044 type ListNodeManual struct {
2045 l listNodeManual
2046 }
2047
2048 func (head *ListHeadManual) Push(p unsafe.Pointer) {
2049 head.l.push(p)
2050 }
2051
2052 func (head *ListHeadManual) Pop() unsafe.Pointer {
2053 return head.l.pop()
2054 }
2055
2056 func (head *ListHeadManual) Remove(p unsafe.Pointer) {
2057 head.l.remove(p)
2058 }
2059
2060 func Hexdumper(base uintptr, wordBytes int, mark func(addr uintptr, start func()), data ...[]byte) string {
2061 buf := make([]byte, 0, 2048)
2062 getg().writebuf = buf
2063 h := hexdumper{addr: base, addrBytes: 4, wordBytes: uint8(wordBytes)}
2064 if mark != nil {
2065 h.mark = func(addr uintptr, m hexdumpMarker) {
2066 mark(addr, m.start)
2067 }
2068 }
2069 for _, d := range data {
2070 h.write(d)
2071 }
2072 h.close()
2073 n := len(getg().writebuf)
2074 getg().writebuf = nil
2075 if n == cap(buf) {
2076 panic("Hexdumper buf too small")
2077 }
2078 return string(buf[:n])
2079 }
2080
2081 func HexdumpWords(p, bytes uintptr) string {
2082 buf := make([]byte, 0, 2048)
2083 getg().writebuf = buf
2084 hexdumpWords(p, bytes, nil)
2085 n := len(getg().writebuf)
2086 getg().writebuf = nil
2087 if n == cap(buf) {
2088 panic("HexdumpWords buf too small")
2089 }
2090 return string(buf[:n])
2091 }
2092
2093
2094
2095 func DumpPrintQuoted(s string) string {
2096 gp := getg()
2097 gp.writebuf = make([]byte, 0, 1<<20)
2098 print(quoted(s))
2099 buf := gp.writebuf
2100 gp.writebuf = nil
2101
2102 return string(buf)
2103 }
2104
2105
2106 func DumpPrint[T any](v T) string {
2107 gp := getg()
2108 gp.writebuf = make([]byte, 0, 2048)
2109 print(v)
2110 buf := gp.writebuf
2111 gp.writebuf = nil
2112
2113 return string(buf)
2114 }
2115
2116 var (
2117 Float64Bytes = float64Bytes
2118 Float32Bytes = float32Bytes
2119 Complex128Bytes = complex128Bytes
2120 Complex64Bytes = complex64Bytes
2121 )
2122
2123 func GetScanAlloc() uintptr {
2124 c := getMCache(getg().m)
2125 return c.scanAlloc
2126 }
2127
2128 func MallocGC(size uintptr, typ *abi.Type, needzero bool) unsafe.Pointer {
2129 return mallocgc(size, typ, needzero)
2130 }
2131
2132 func FuncNamePiecesForPrint(name string) (string, string, string, string, string) {
2133 return funcNamePiecesForPrint(name)
2134 }
2135
2136 var InHeapOrStack = inHeapOrStack
2137
View as plain text