Skip to content

Commit fc768e8

Browse files
igchorguptask
authored andcommitted
critical section inside combined_lock
1 parent d98757a commit fc768e8

File tree

7 files changed

+71
-28
lines changed

7 files changed

+71
-28
lines changed

cachelib/allocator/CacheAllocator-inl.h

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1562,26 +1562,39 @@ CacheAllocator<CacheTrait>::findEviction(TierId tid, PoolId pid, ClassId cid) {
15621562
// Keep searching for a candidate until we were able to evict it
15631563
// or until the search limit has been exhausted
15641564
unsigned int searchTries = 0;
1565-
auto itr = mmContainer.getEvictionIterator();
15661565
while ((config_.evictionSearchTries == 0 ||
1567-
config_.evictionSearchTries > searchTries) &&
1568-
itr) {
1566+
config_.evictionSearchTries > searchTries)) {
15691567
++searchTries;
15701568

1571-
Item* toRecycle = itr.get();
1569+
Item* toRecycle = nullptr;
1570+
Item* candidate = nullptr;
15721571

1573-
Item* candidate =
1574-
toRecycle->isChainedItem()
1575-
? &toRecycle->asChainedItem().getParentItem(compressor_)
1576-
: toRecycle;
1572+
mmContainer.withEvictionIterator([this, &candidate, &toRecycle, &searchTries](auto &&itr){
1573+
while ((config_.evictionSearchTries == 0 ||
1574+
config_.evictionSearchTries > searchTries) && itr) {
1575+
++searchTries;
15771576

1578-
// make sure no other thead is evicting the item
1579-
if (candidate->getRefCount() != 0 || !candidate->markMoving()) {
1580-
++itr;
1577+
auto *toRecycle_ = itr.get();
1578+
auto *candidate_ = toRecycle_->isChainedItem()
1579+
? &toRecycle_->asChainedItem().getParentItem(compressor_)
1580+
: toRecycle_;
1581+
1582+
// make sure no other thead is evicting the item
1583+
if (candidate_->getRefCount() == 0 && candidate_->markMoving()) {
1584+
toRecycle = toRecycle_;
1585+
candidate = candidate_;
1586+
return;
1587+
}
1588+
1589+
++itr;
1590+
}
1591+
});
1592+
1593+
if (!toRecycle)
15811594
continue;
1582-
}
1583-
1584-
itr.destroy();
1595+
1596+
XDCHECK(toRecycle);
1597+
XDCHECK(candidate);
15851598

15861599
// for chained items, the ownership of the parent can change. We try to
15871600
// evict what we think as parent and see if the eviction of parent
@@ -1635,8 +1648,6 @@ CacheAllocator<CacheTrait>::findEviction(TierId tid, PoolId pid, ClassId cid) {
16351648
return toRecycle;
16361649
}
16371650
}
1638-
1639-
itr.resetToBegin();
16401651
}
16411652
return nullptr;
16421653
}

cachelib/allocator/MM2Q-inl.h

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -250,22 +250,21 @@ MM2Q::Container<T, HookPtr>::getEvictionIterator() const noexcept {
250250
// arbitrary amount of time outside a lambda-friendly piece of code (eg. they
251251
// can return the iterator from functions, pass it to functions, etc)
252252
//
253-
// it would be theoretically possible to refactor this interface into
254-
// something like the following to allow combining
255-
//
256-
// mm2q.withEvictionIterator([&](auto iterator) {
257-
// // user code
258-
// });
259-
//
260-
// at the time of writing it is unclear if the gains from combining are
261-
// reasonable justification for the codemod required to achieve combinability
262-
// as we don't expect this critical section to be the hotspot in user code.
263-
// This is however subject to change at some time in the future as and when
264-
// this assertion becomes false.
253+
// to get advantage of combining, use withEvictionIterator
265254
LockHolder l(*lruMutex_);
266255
return Iterator{std::move(l), lru_.rbegin()};
267256
}
268257

258+
template <typename T, MM2Q::Hook<T> T::*HookPtr>
259+
template <typename F>
260+
void
261+
MM2Q::Container<T, HookPtr>::withEvictionIterator(F&& fun) {
262+
lruMutex_->lock_combine([this, &fun]() {
263+
fun(Iterator{LockHolder{}, lru_.rbegin()});
264+
});
265+
}
266+
267+
269268
template <typename T, MM2Q::Hook<T> T::*HookPtr>
270269
void MM2Q::Container<T, HookPtr>::removeLocked(T& node,
271270
bool doRebalance) noexcept {

cachelib/allocator/MM2Q.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,11 @@ class MM2Q {
447447
// container and only one such iterator can exist at a time
448448
Iterator getEvictionIterator() const noexcept;
449449

450+
// Execute provided function under container lock. Function gets
451+
// iterator passed as parameter.
452+
template <typename F>
453+
void withEvictionIterator(F&& f);
454+
450455
// get the current config as a copy
451456
Config getConfig() const;
452457

cachelib/allocator/MMLru-inl.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,15 @@ MMLru::Container<T, HookPtr>::getEvictionIterator() const noexcept {
218218
return Iterator{std::move(l), lru_.rbegin()};
219219
}
220220

221+
template <typename T, MMLru::Hook<T> T::*HookPtr>
222+
template <typename F>
223+
void
224+
MMLru::Container<T, HookPtr>::withEvictionIterator(F&& fun) {
225+
lruMutex_->lock_combine([this, &fun]() {
226+
fun(Iterator{LockHolder{}, lru_.rbegin()});
227+
});
228+
}
229+
221230
template <typename T, MMLru::Hook<T> T::*HookPtr>
222231
void MMLru::Container<T, HookPtr>::ensureNotInsertionPoint(T& node) noexcept {
223232
// If we are removing the insertion point node, grow tail before we remove

cachelib/allocator/MMLru.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,11 @@ class MMLru {
332332
// container and only one such iterator can exist at a time
333333
Iterator getEvictionIterator() const noexcept;
334334

335+
// Execute provided function under container lock. Function gets
336+
// iterator passed as parameter.
337+
template <typename F>
338+
void withEvictionIterator(F&& f);
339+
335340
// get copy of current config
336341
Config getConfig() const;
337342

cachelib/allocator/MMTinyLFU-inl.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,15 @@ MMTinyLFU::Container<T, HookPtr>::getEvictionIterator() const noexcept {
220220
return Iterator{std::move(l), *this};
221221
}
222222

223+
template <typename T, MMTinyLFU::Hook<T> T::*HookPtr>
224+
template <typename F>
225+
void
226+
MMTinyLFU::Container<T, HookPtr>::withEvictionIterator(F&& fun) {
227+
LockHolder l(lruMutex_);
228+
fun(Iterator{LockHolder{}, *this});
229+
}
230+
231+
223232
template <typename T, MMTinyLFU::Hook<T> T::*HookPtr>
224233
void MMTinyLFU::Container<T, HookPtr>::removeLocked(T& node) noexcept {
225234
if (isTiny(node)) {

cachelib/allocator/MMTinyLFU.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,11 @@ class MMTinyLFU {
491491
// container and only one such iterator can exist at a time
492492
Iterator getEvictionIterator() const noexcept;
493493

494+
// Execute provided function under container lock. Function gets
495+
// iterator passed as parameter.
496+
template <typename F>
497+
void withEvictionIterator(F&& f);
498+
494499
// for saving the state of the lru
495500
//
496501
// precondition: serialization must happen without any reader or writer

0 commit comments

Comments
 (0)