@@ -318,9 +318,10 @@ class MapAllocatorCache {
318318 }
319319 CachedBlock PrevEntry = Quarantine[QuarantinePos];
320320 Quarantine[QuarantinePos] = Entry;
321- if (OldestTime == 0 )
322- OldestTime = Entry.Time ;
323321 Entry = PrevEntry;
322+ // Set entry time once more to reflect time
323+ // that quarantined memory was placed in the cache
324+ Entry.Time = Time;
324325 }
325326
326327 // All excess entries are evicted from the cache
@@ -331,9 +332,6 @@ class MapAllocatorCache {
331332 }
332333
333334 insert (Entry);
334-
335- if (OldestTime == 0 )
336- OldestTime = Entry.Time ;
337335 } while (0 );
338336
339337 for (MemMapT &EvictMemMap : EvictionMemMaps)
@@ -532,6 +530,9 @@ class MapAllocatorCache {
532530 Entries[LRUHead].Prev = static_cast <u16 >(FreeIndex);
533531 }
534532
533+ if (LastUnreleasedEntry == CachedBlock::InvalidEntry)
534+ LastUnreleasedEntry = static_cast <u16 >(FreeIndex);
535+
535536 Entries[FreeIndex] = Entry;
536537 Entries[FreeIndex].Next = LRUHead;
537538 Entries[FreeIndex].Prev = CachedBlock::InvalidEntry;
@@ -549,6 +550,9 @@ class MapAllocatorCache {
549550
550551 Entries[I].invalidate ();
551552
553+ if (I == LastUnreleasedEntry)
554+ LastUnreleasedEntry = Entries[LastUnreleasedEntry].Prev ;
555+
552556 if (I == LRUHead)
553557 LRUHead = Entries[I].Next ;
554558 else
@@ -590,35 +594,37 @@ class MapAllocatorCache {
590594 }
591595 }
592596
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 );
601599 Entry.MemMap .releaseAndZeroPagesToOS (Entry.CommitBase , Entry.CommitSize );
602600 Entry.Time = 0 ;
603601 }
604602
605603 void releaseOlderThan (u64 Time) EXCLUDES(Mutex) {
606604 ScopedLock L (Mutex);
607- if (!EntriesCount || OldestTime == 0 || OldestTime > Time )
605+ if (!EntriesCount)
608606 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- }
615607
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+ }
616623 HybridMutex Mutex;
617624 u32 EntriesCount GUARDED_BY (Mutex) = 0;
618625 u32 QuarantinePos GUARDED_BY (Mutex) = 0;
619626 atomic_u32 MaxEntriesCount = {};
620627 atomic_uptr MaxEntrySize = {};
621- u64 OldestTime GUARDED_BY (Mutex) = 0;
622628 atomic_s32 ReleaseToOsIntervalMs = {};
623629 u32 CallsToRetrieve GUARDED_BY (Mutex) = 0;
624630 u32 SuccessfulRetrieves GUARDED_BY (Mutex) = 0;
@@ -633,6 +639,9 @@ class MapAllocatorCache {
633639 u16 LRUTail GUARDED_BY (Mutex) = 0;
634640 // The AvailableHead is the top of the stack of available entries
635641 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;
636645};
637646
638647template <typename Config> class MapAllocator {
0 commit comments