@@ -247,6 +247,7 @@ class MapAllocatorCache {
247
247
// The cache is initially empty
248
248
LRUHead = CachedBlock::InvalidEntry;
249
249
LRUTail = CachedBlock::InvalidEntry;
250
+ LastUnreleasedEntry = CachedBlock::InvalidEntry;
250
251
251
252
// Available entries will be retrieved starting from the beginning of the
252
253
// Entries array
@@ -321,9 +322,10 @@ class MapAllocatorCache {
321
322
}
322
323
CachedBlock PrevEntry = Quarantine[QuarantinePos];
323
324
Quarantine[QuarantinePos] = Entry;
324
- if (OldestTime == 0 )
325
- OldestTime = Entry.Time ;
326
325
Entry = PrevEntry;
326
+ // Update the entry time to reflect the time that the
327
+ // quarantined memory is placed in the Entries array
328
+ Entry.Time = Time;
327
329
}
328
330
329
331
// All excess entries are evicted from the cache
@@ -334,9 +336,6 @@ class MapAllocatorCache {
334
336
}
335
337
336
338
insert (Entry);
337
-
338
- if (OldestTime == 0 )
339
- OldestTime = Entry.Time ;
340
339
} while (0 );
341
340
342
341
for (MemMapT &EvictMemMap : EvictionMemMaps)
@@ -535,6 +534,9 @@ class MapAllocatorCache {
535
534
Entries[LRUHead].Prev = static_cast <u16>(FreeIndex);
536
535
}
537
536
537
+ if (LastUnreleasedEntry == CachedBlock::InvalidEntry)
538
+ LastUnreleasedEntry = static_cast <u16>(FreeIndex);
539
+
538
540
Entries[FreeIndex] = Entry;
539
541
Entries[FreeIndex].Next = LRUHead;
540
542
Entries[FreeIndex].Prev = CachedBlock::InvalidEntry;
@@ -552,6 +554,9 @@ class MapAllocatorCache {
552
554
553
555
Entries[I].invalidate ();
554
556
557
+ if (I == LastUnreleasedEntry)
558
+ LastUnreleasedEntry = Entries[LastUnreleasedEntry].Prev ;
559
+
555
560
if (I == LRUHead)
556
561
LRUHead = Entries[I].Next ;
557
562
else
@@ -593,35 +598,37 @@ class MapAllocatorCache {
593
598
}
594
599
}
595
600
596
- void releaseIfOlderThan (CachedBlock &Entry, u64 Time) REQUIRES(Mutex) {
597
- if (!Entry.isValid () || !Entry.Time )
598
- return ;
599
- if (Entry.Time > Time) {
600
- if (OldestTime == 0 || Entry.Time < OldestTime)
601
- OldestTime = Entry.Time ;
602
- return ;
603
- }
601
+ inline void release (CachedBlock &Entry) {
602
+ DCHECK (Entry.Time != 0 );
604
603
Entry.MemMap .releaseAndZeroPagesToOS (Entry.CommitBase , Entry.CommitSize );
605
604
Entry.Time = 0 ;
606
605
}
607
606
608
607
void releaseOlderThan (u64 Time) EXCLUDES(Mutex) {
609
608
ScopedLock L (Mutex);
610
- if (!EntriesCount || OldestTime == 0 || OldestTime > Time )
609
+ if (!EntriesCount)
611
610
return ;
612
- OldestTime = 0 ;
613
- for (uptr I = 0 ; I < Config::getQuarantineSize (); I++)
614
- releaseIfOlderThan (Quarantine[I], Time);
615
- for (uptr I = 0 ; I < Config::getEntriesArraySize (); I++)
616
- releaseIfOlderThan (Entries[I], Time);
617
- }
618
611
612
+ for (uptr I = 0 ; I < Config::getQuarantineSize (); I++) {
613
+ CachedBlock &ReleaseEntry = Quarantine[I];
614
+ if (!ReleaseEntry.isValid () || !ReleaseEntry.Time ||
615
+ ReleaseEntry.Time > Time)
616
+ continue ;
617
+ release (ReleaseEntry);
618
+ }
619
+
620
+ // Release oldest entries first by releasing from decommit base
621
+ while (LastUnreleasedEntry != CachedBlock::InvalidEntry &&
622
+ Entries[LastUnreleasedEntry].Time <= Time) {
623
+ release (Entries[LastUnreleasedEntry]);
624
+ LastUnreleasedEntry = Entries[LastUnreleasedEntry].Prev ;
625
+ }
626
+ }
619
627
HybridMutex Mutex;
620
628
u32 EntriesCount GUARDED_BY (Mutex) = 0;
621
629
u32 QuarantinePos GUARDED_BY (Mutex) = 0;
622
630
atomic_u32 MaxEntriesCount = {};
623
631
atomic_uptr MaxEntrySize = {};
624
- u64 OldestTime GUARDED_BY (Mutex) = 0;
625
632
atomic_s32 ReleaseToOsIntervalMs = {};
626
633
u32 CallsToRetrieve GUARDED_BY (Mutex) = 0;
627
634
u32 SuccessfulRetrieves GUARDED_BY (Mutex) = 0;
@@ -636,6 +643,9 @@ class MapAllocatorCache {
636
643
u16 LRUTail GUARDED_BY (Mutex) = 0;
637
644
// The AvailableHead is the top of the stack of available entries
638
645
u16 AvailableHead GUARDED_BY (Mutex) = 0;
646
+ // The LastUnreleasedEntry is the least recently used entry that has not
647
+ // been released
648
+ u16 LastUnreleasedEntry GUARDED_BY (Mutex) = 0;
639
649
};
640
650
641
651
template <typename Config> class MapAllocator {
0 commit comments