@@ -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)
@@ -532,6 +530,9 @@ class MapAllocatorCache {
532
530
Entries[LRUHead].Prev = static_cast <u16>(FreeIndex);
533
531
}
534
532
533
+ if (LastUnreleasedEntry == CachedBlock::InvalidEntry)
534
+ LastUnreleasedEntry = static_cast <u16>(FreeIndex);
535
+
535
536
Entries[FreeIndex] = Entry;
536
537
Entries[FreeIndex].Next = LRUHead;
537
538
Entries[FreeIndex].Prev = CachedBlock::InvalidEntry;
@@ -549,6 +550,9 @@ class MapAllocatorCache {
549
550
550
551
Entries[I].invalidate ();
551
552
553
+ if (I == LastUnreleasedEntry)
554
+ LastUnreleasedEntry = Entries[LastUnreleasedEntry].Prev ;
555
+
552
556
if (I == LRUHead)
553
557
LRUHead = Entries[I].Next ;
554
558
else
@@ -590,35 +594,37 @@ class MapAllocatorCache {
590
594
}
591
595
}
592
596
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
- }
597
+ inline void release (CachedBlock &Entry) {
598
+ DCHECK (Entry.Time != 0 );
601
599
Entry.MemMap .releaseAndZeroPagesToOS (Entry.CommitBase , Entry.CommitSize );
602
600
Entry.Time = 0 ;
603
601
}
604
602
605
603
void releaseOlderThan (u64 Time) EXCLUDES(Mutex) {
606
604
ScopedLock L (Mutex);
607
- if (!EntriesCount || OldestTime == 0 || OldestTime > Time )
605
+ if (!EntriesCount)
608
606
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
607
608
+ for (uptr I = 0 ; I < Config::getQuarantineSize (); I++) {
609
+ CachedBlock &ReleaseEntry = Quarantine[I];
610
+ if (!ReleaseEntry.isValid () || ReleaseEntry.Time > Time ||
611
+ !ReleaseEntry.Time )
612
+ continue ;
613
+ release (ReleaseEntry);
614
+ }
615
+
616
+ // Release oldest entries first by releasing from decommit base
617
+ while (LastUnreleasedEntry != CachedBlock::InvalidEntry &&
618
+ Entries[LastUnreleasedEntry].Time <= Time) {
619
+ release (Entries[LastUnreleasedEntry]);
620
+ LastUnreleasedEntry = Entries[LastUnreleasedEntry].Prev ;
621
+ }
622
+ }
616
623
HybridMutex Mutex;
617
624
u32 EntriesCount GUARDED_BY (Mutex) = 0;
618
625
u32 QuarantinePos GUARDED_BY (Mutex) = 0;
619
626
atomic_u32 MaxEntriesCount = {};
620
627
atomic_uptr MaxEntrySize = {};
621
- u64 OldestTime GUARDED_BY (Mutex) = 0;
622
628
atomic_s32 ReleaseToOsIntervalMs = {};
623
629
u32 CallsToRetrieve GUARDED_BY (Mutex) = 0;
624
630
u32 SuccessfulRetrieves GUARDED_BY (Mutex) = 0;
@@ -633,6 +639,9 @@ class MapAllocatorCache {
633
639
u16 LRUTail GUARDED_BY (Mutex) = 0;
634
640
// The AvailableHead is the top of the stack of available entries
635
641
u16 AvailableHead GUARDED_BY (Mutex) = 0;
642
+ // The LastUnreleasedEntry is the least recently used entry that has not
643
+ // been released
644
+ u16 LastUnreleasedEntry GUARDED_BY (Mutex) = 0;
636
645
};
637
646
638
647
template <typename Config> class MapAllocator {
0 commit comments