Skip to content

Commit bada673

Browse files
committed
fix race for acquire parent handle on chained items
1 parent dfd5695 commit bada673

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
@@ -379,6 +379,35 @@ class FOLLY_PACK_ATTR RefcountWithFlags {
379379

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

383412
bool isMoving() const noexcept {
384413
auto raw = getRaw();

0 commit comments

Comments
 (0)