Skip to content

Commit 807dbda

Browse files
byrnedjvinser52
authored andcommitted
fix race for acquire parent handle on chained items
1 parent 468ea4f commit 807dbda

File tree

4 files changed

+41
-14
lines changed

4 files changed

+41
-14
lines changed

cachelib/allocator/CacheAllocator-inl.h

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2639,20 +2639,12 @@ bool CacheAllocator<CacheTrait>::moveForSlabRelease(
26392639
const auto allocInfo = allocator_->getAllocInfo(oldItem.getMemory());
26402640
if (chainedItem) {
26412641
newItemHdl.reset();
2642-
auto ref = parentItem->unmarkMoving();
2643-
if (UNLIKELY(ref == 0)) {
2644-
wakeUpWaiters(*parentItem, {});
2645-
const auto res =
2646-
releaseBackToAllocator(*parentItem, RemoveContext::kNormal, false);
2647-
XDCHECK(res == ReleaseRes::kReleased);
2648-
return true;
2649-
} else {
2650-
XDCHECK_NE(ref, 0);
2651-
auto parentHdl = acquire(parentItem);
2652-
if (parentHdl) {
2653-
wakeUpWaiters(*parentItem, std::move(parentHdl));
2654-
}
2655-
}
2642+
auto ref = parentItem->unmarkMovingAndIncRef();
2643+
XDCHECK_NE(ref, 0);
2644+
auto parentHdl = acquire(parentItem);
2645+
XDCHECK(parentHdl);
2646+
parentHdl->decRef();
2647+
wakeUpWaiters(*parentItem, std::move(parentHdl));
26562648
} else {
26572649
auto ref = unmarkMovingAndWakeUpWaiters(oldItem, std::move(newItemHdl));
26582650
XDCHECK(ref == 0);

cachelib/allocator/CacheItem-inl.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,11 @@ RefcountWithFlags::Value CacheItem<CacheTrait>::unmarkMoving() noexcept {
247247
return ref_.unmarkMoving();
248248
}
249249

250+
template <typename CacheTrait>
251+
RefcountWithFlags::Value CacheItem<CacheTrait>::unmarkMovingAndIncRef() noexcept {
252+
return ref_.unmarkMovingAndIncRef();
253+
}
254+
250255
template <typename CacheTrait>
251256
bool CacheItem<CacheTrait>::isMoving() const noexcept {
252257
return ref_.isMoving();

cachelib/allocator/CacheItem.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,7 @@ class CACHELIB_PACKED_ATTR CacheItem {
380380
*/
381381
bool markMoving();
382382
RefcountWithFlags::Value unmarkMoving() noexcept;
383+
RefcountWithFlags::Value unmarkMovingAndIncRef() noexcept;
383384
bool isMoving() const noexcept;
384385
bool isOnlyMoving() const noexcept;
385386

cachelib/allocator/Refcount.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,35 @@ class FOLLY_PACK_ATTR RefcountWithFlags {
384384

385385
return retValue & kRefMask;
386386
}
387+
388+
/*
389+
* this is used when we immediately call acquire after unmarking
390+
* moving - this is currently done in the case of moving a
391+
* chained item when the parent is unmarked moving and we
392+
* need to wake up the waiters with the parent handle BUT
393+
* we don't want the parent item to be marked moving/exclusive
394+
* between unmarking moving and acquire - so we do not
395+
* modify the refcount (moving state = exclusive bit set and refcount == 1)
396+
*/
397+
Value unmarkMovingAndIncRef() noexcept {
398+
XDCHECK(isMoving());
399+
auto predicate = [](const Value curValue) {
400+
XDCHECK((curValue & kAccessRefMask) != 0);
401+
return true;
402+
};
403+
404+
Value retValue;
405+
auto newValue = [&retValue](const Value curValue) {
406+
retValue =
407+
(curValue) & ~getAdminRef<kExclusive>();
408+
return retValue;
409+
};
410+
411+
auto updated = atomicUpdateValue(predicate, newValue);
412+
XDCHECK(updated);
413+
414+
return retValue & kRefMask;
415+
}
387416

388417
bool isMoving() const noexcept {
389418
auto raw = getRaw();

0 commit comments

Comments
 (0)