@@ -318,9 +318,10 @@ class MapAllocatorCache {
318
318
}
319
319
CachedBlock PrevEntry = Quarantine[QuarantinePos];
320
320
Quarantine[QuarantinePos] = Entry;
321
- if (OldestTime == 0 )
322
- OldestTime = Entry.Time ;
323
321
Entry = PrevEntry;
322
+ // Set entry time once more to reflect time
323
+ // that quarantined memory was placed in the cache
324
+ Entry.Time = Time;
324
325
}
325
326
326
327
// All excess entries are evicted from the cache
@@ -331,9 +332,6 @@ class MapAllocatorCache {
331
332
}
332
333
333
334
insert (Entry);
334
-
335
- if (OldestTime == 0 )
336
- OldestTime = Entry.Time ;
337
335
} while (0 );
338
336
339
337
for (MemMapT &EvictMemMap : EvictionMemMaps)
@@ -514,6 +512,11 @@ class MapAllocatorCache {
514
512
return (EntriesCount >= atomic_load_relaxed (&MaxEntriesCount));
515
513
}
516
514
515
+ inline void advanceDecommitBase () REQUIRES(Mutex) {
516
+ if (DecommitBase != CachedBlock::InvalidEntry)
517
+ DecommitBase = Entries[DecommitBase].Prev ;
518
+ }
519
+
517
520
void insert (const CachedBlock &Entry) REQUIRES(Mutex) {
518
521
DCHECK_LT (EntriesCount, atomic_load_relaxed (&MaxEntriesCount));
519
522
@@ -532,6 +535,9 @@ class MapAllocatorCache {
532
535
Entries[LRUHead].Prev = static_cast <u16>(FreeIndex);
533
536
}
534
537
538
+ if (DecommitBase == CachedBlock::InvalidEntry)
539
+ DecommitBase = static_cast <u16>(FreeIndex);
540
+
535
541
Entries[FreeIndex] = Entry;
536
542
Entries[FreeIndex].Next = LRUHead;
537
543
Entries[FreeIndex].Prev = CachedBlock::InvalidEntry;
@@ -549,6 +555,9 @@ class MapAllocatorCache {
549
555
550
556
Entries[I].invalidate ();
551
557
558
+ if (I == DecommitBase)
559
+ advanceDecommitBase ();
560
+
552
561
if (I == LRUHead)
553
562
LRUHead = Entries[I].Next ;
554
563
else
@@ -590,35 +599,36 @@ class MapAllocatorCache {
590
599
}
591
600
}
592
601
593
- void releaseIfOlderThan (CachedBlock &Entry, u64 Time) REQUIRES(Mutex) {
594
- if (!Entry.isValid () || !Entry.Time )
595
- return ;
596
- if (Entry.Time > Time) {
597
- if (OldestTime == 0 || Entry.Time < OldestTime)
598
- OldestTime = Entry.Time ;
599
- return ;
600
- }
602
+ inline void release (CachedBlock &Entry) {
603
+ DCHECK (Entry.Time != 0 );
601
604
Entry.MemMap .releaseAndZeroPagesToOS (Entry.CommitBase , Entry.CommitSize );
602
605
Entry.Time = 0 ;
603
606
}
604
607
605
608
void releaseOlderThan (u64 Time) EXCLUDES(Mutex) {
606
609
ScopedLock L (Mutex);
607
- if (!EntriesCount || OldestTime == 0 || OldestTime > Time )
610
+ if (!EntriesCount)
608
611
return ;
609
- OldestTime = 0 ;
610
- for (uptr I = 0 ; I < Config::getQuarantineSize (); I++)
611
- releaseIfOlderThan (Quarantine[I], Time);
612
- for (uptr I = 0 ; I < Config::getEntriesArraySize (); I++)
613
- releaseIfOlderThan (Entries[I], Time);
614
- }
615
612
613
+ for (uptr I = 0 ; I < Config::getQuarantineSize (); I++) {
614
+ CachedBlock &ReleaseEntry = Quarantine[I];
615
+ if (!ReleaseEntry.isValid () || ReleaseEntry.Time > Time)
616
+ continue ;
617
+ release (ReleaseEntry);
618
+ }
619
+
620
+ // Release oldest entries first by releasing from decommit base
621
+ while (DecommitBase != CachedBlock::InvalidEntry &&
622
+ Entries[DecommitBase].Time <= Time) {
623
+ release (Entries[DecommitBase]);
624
+ advanceDecommitBase ();
625
+ }
626
+ }
616
627
HybridMutex Mutex;
617
628
u32 EntriesCount GUARDED_BY (Mutex) = 0;
618
629
u32 QuarantinePos GUARDED_BY (Mutex) = 0;
619
630
atomic_u32 MaxEntriesCount = {};
620
631
atomic_uptr MaxEntrySize = {};
621
- u64 OldestTime GUARDED_BY (Mutex) = 0;
622
632
atomic_s32 ReleaseToOsIntervalMs = {};
623
633
u32 CallsToRetrieve GUARDED_BY (Mutex) = 0;
624
634
u32 SuccessfulRetrieves GUARDED_BY (Mutex) = 0;
@@ -633,6 +643,9 @@ class MapAllocatorCache {
633
643
u16 LRUTail GUARDED_BY (Mutex) = 0;
634
644
// The AvailableHead is the top of the stack of available entries
635
645
u16 AvailableHead GUARDED_BY (Mutex) = 0;
646
+ // The DecommitBase is the least recently used entry that has not
647
+ // been released
648
+ u16 DecommitBase GUARDED_BY (Mutex) = 0;
636
649
};
637
650
638
651
template <typename Config> class MapAllocator {
0 commit comments