@@ -421,16 +421,17 @@ func bgscavenge(c chan int) {
421
421
//
422
422
// Returns the amount of memory scavenged in bytes.
423
423
//
424
- // s.mheapLock must not be locked.
424
+ // If locked == false, s.mheapLock must not be locked. If locked == true,
425
+ // s.mheapLock must be locked.
425
426
//
426
427
// Must run on the system stack because scavengeOne must run on the
427
428
// system stack.
428
429
//
429
430
//go:systemstack
430
- func (s * pageAlloc ) scavenge (nbytes uintptr ) uintptr {
431
+ func (s * pageAlloc ) scavenge (nbytes uintptr , locked bool ) uintptr {
431
432
released := uintptr (0 )
432
433
for released < nbytes {
433
- r := s .scavengeOne (nbytes - released )
434
+ r := s .scavengeOne (nbytes - released , locked )
434
435
if r == 0 {
435
436
// Nothing left to scavenge! Give up.
436
437
break
@@ -457,11 +458,14 @@ func (s *pageAlloc) resetScavengeAddr() {
457
458
//
458
459
// Should it exhaust the heap, it will return 0 and set s.scavAddr to minScavAddr.
459
460
//
460
- // s.mheapLock must not be locked. Must be run on the system stack because it
461
- // acquires the heap lock.
461
+ // If locked == false, s.mheapLock must not be locked.
462
+ // If locked == true, s.mheapLock must be locked.
463
+ //
464
+ // Must be run on the system stack because it either acquires the heap lock
465
+ // or executes with the heap lock acquired.
462
466
//
463
467
//go:systemstack
464
- func (s * pageAlloc ) scavengeOne (max uintptr ) uintptr {
468
+ func (s * pageAlloc ) scavengeOne (max uintptr , locked bool ) uintptr {
465
469
// Calculate the maximum number of pages to scavenge.
466
470
//
467
471
// This should be alignUp(max, pageSize) / pageSize but max can and will
@@ -483,10 +487,22 @@ func (s *pageAlloc) scavengeOne(max uintptr) uintptr {
483
487
minPages = 1
484
488
}
485
489
486
- lock (s .mheapLock )
490
+ // Helpers for locking and unlocking only if locked == false.
491
+ lockHeap := func () {
492
+ if ! locked {
493
+ lock (s .mheapLock )
494
+ }
495
+ }
496
+ unlockHeap := func () {
497
+ if ! locked {
498
+ unlock (s .mheapLock )
499
+ }
500
+ }
501
+
502
+ lockHeap ()
487
503
top := chunkIndex (s .scavAddr )
488
504
if top < s .start {
489
- unlock ( s . mheapLock )
505
+ unlockHeap ( )
490
506
return 0
491
507
}
492
508
@@ -498,10 +514,10 @@ func (s *pageAlloc) scavengeOne(max uintptr) uintptr {
498
514
// If we found something, scavenge it and return!
499
515
if npages != 0 {
500
516
s .scavengeRangeLocked (ci , base , npages )
501
- unlock ( s . mheapLock )
517
+ unlockHeap ( )
502
518
return uintptr (npages ) * pageSize
503
519
}
504
- unlock ( s . mheapLock )
520
+ unlockHeap ( )
505
521
506
522
// Slow path: iterate optimistically looking for any free and unscavenged page.
507
523
// If we think we see something, stop and verify it!
@@ -528,30 +544,30 @@ func (s *pageAlloc) scavengeOne(max uintptr) uintptr {
528
544
}
529
545
530
546
// We found a candidate, so let's lock and verify it.
531
- lock ( s . mheapLock )
547
+ lockHeap ( )
532
548
533
549
// Find, verify, and scavenge if we can.
534
550
chunk := & s .chunks [i ]
535
551
base , npages := chunk .findScavengeCandidate (pallocChunkPages - 1 , minPages , maxPages )
536
552
if npages > 0 {
537
553
// We found memory to scavenge! Mark the bits and report that up.
538
554
s .scavengeRangeLocked (i , base , npages )
539
- unlock ( s . mheapLock )
555
+ unlockHeap ( )
540
556
return uintptr (npages ) * pageSize
541
557
}
542
558
543
559
// We were fooled, let's take this opportunity to move the scavAddr
544
560
// all the way down to where we searched as scavenged for future calls
545
561
// and keep iterating.
546
562
s .scavAddr = chunkBase (i - 1 ) + pallocChunkPages * pageSize - 1
547
- unlock ( s . mheapLock )
563
+ unlockHeap ( )
548
564
}
549
565
550
- lock ( s . mheapLock )
566
+ lockHeap ( )
551
567
// We couldn't find anything, so signal that there's nothing left
552
568
// to scavenge.
553
569
s .scavAddr = minScavAddr
554
- unlock ( s . mheapLock )
570
+ unlockHeap ( )
555
571
556
572
return 0
557
573
}
0 commit comments