@@ -823,28 +823,29 @@ CacheAllocator<CacheTrait>::releaseBackToAllocator(Item& it,
823823
824824 removeFromMMContainer (*head);
825825
826- // If this chained item is marked as exclusive , we will not free it.
827- // We must capture the exclusive state before we do the decRef when
826+ // If this chained item is marked as moving , we will not free it.
827+ // We must capture the moving state before we do the decRef when
828828 // we know the item must still be valid
829- const bool wasExclusive = head->isExclusive ();
829+ const bool wasMoving = head->isMoving ();
830+ XDCHECK (!head->isMarkedForEviction ());
830831
831832 // Decref and check if we were the last reference. Now if the item
832- // was marked exclusive , after decRef, it will be free to be released
833+ // was marked moving , after decRef, it will be free to be released
833834 // by slab release thread
834835 const auto childRef = head->decRef ();
835836
836- // If the item is already exclusive and we already decremented the
837+ // If the item is already moving and we already decremented the
837838 // refcount, we don't need to free this item. We'll let the slab
838839 // release thread take care of that
839- if (!wasExclusive ) {
840+ if (!wasMoving ) {
840841 if (childRef != 0 ) {
841842 throw std::runtime_error (folly::sformat (
842843 " chained item refcount is not zero. We cannot proceed! "
843844 " Ref: {}, Chained Item: {}" ,
844845 childRef, head->toString ()));
845846 }
846847
847- // Item is not exclusive and refcount is 0, we can proceed to
848+ // Item is not moving and refcount is 0, we can proceed to
848849 // free it or recylce the memory
849850 if (head == toRecycle) {
850851 XDCHECK (ReleaseRes::kReleased != res);
@@ -872,9 +873,12 @@ CacheAllocator<CacheTrait>::releaseBackToAllocator(Item& it,
872873}
873874
874875template <typename CacheTrait>
875- void CacheAllocator<CacheTrait>::incRef(Item& it) {
876- it.incRef ();
877- ++handleCount_.tlStats ();
876+ bool CacheAllocator<CacheTrait>::incRef(Item& it) {
877+ if (it.incRef ()) {
878+ ++handleCount_.tlStats ();
879+ return true ;
880+ }
881+ return false ;
878882}
879883
880884template <typename CacheTrait>
@@ -894,7 +898,12 @@ CacheAllocator<CacheTrait>::acquire(Item* it) {
894898
895899 SCOPE_FAIL { stats_.numRefcountOverflow .inc (); };
896900
897- incRef (*it);
901+ if (LIKELY (incRef (*it))) {
902+ return WriteHandle{it, *this };
903+ } else {
904+ // item is being evicted
905+ return WriteHandle{};
906+ }
898907 return WriteHandle{it, *this };
899908}
900909
@@ -1170,7 +1179,7 @@ bool CacheAllocator<CacheTrait>::moveChainedItem(ChainedItem& oldItem,
11701179
11711180 // This item has been unlinked from its parent and we're the only
11721181 // owner of it, so we're done here
1173- if (!oldItem.isInMMContainer () || oldItem.isOnlyExclusive ()) {
1182+ if (!oldItem.isInMMContainer () || oldItem.isOnlyMoving ()) {
11741183 return false ;
11751184 }
11761185
@@ -1201,7 +1210,7 @@ bool CacheAllocator<CacheTrait>::moveChainedItem(ChainedItem& oldItem,
12011210
12021211 // In case someone else had removed this chained item from its parent by now
12031212 // So we check again to see if the it has been unlinked from its parent
1204- if (!oldItem.isInMMContainer () || oldItem.isOnlyExclusive ()) {
1213+ if (!oldItem.isInMMContainer () || oldItem.isOnlyMoving ()) {
12051214 return false ;
12061215 }
12071216
@@ -1217,7 +1226,7 @@ bool CacheAllocator<CacheTrait>::moveChainedItem(ChainedItem& oldItem,
12171226 // parent's chain and the MMContainer.
12181227 auto oldItemHandle =
12191228 replaceChainedItemLocked (oldItem, std::move (newItemHdl), *parentHandle);
1220- XDCHECK (oldItemHandle->isExclusive ());
1229+ XDCHECK (oldItemHandle->isMoving ());
12211230 XDCHECK (!oldItemHandle->isInMMContainer ());
12221231
12231232 return true ;
@@ -1246,7 +1255,7 @@ CacheAllocator<CacheTrait>::findEviction(PoolId pid, ClassId cid) {
12461255 : toRecycle;
12471256
12481257 // make sure no other thead is evicting the item
1249- if (candidate->getRefCount () != 0 || !candidate->markExclusive ()) {
1258+ if (candidate->getRefCount () != 0 || !candidate->markMoving ()) {
12501259 ++itr;
12511260 continue ;
12521261 }
@@ -1261,11 +1270,11 @@ CacheAllocator<CacheTrait>::findEviction(PoolId pid, ClassId cid) {
12611270 ? advanceIteratorAndTryEvictChainedItem (itr)
12621271 : advanceIteratorAndTryEvictRegularItem (mmContainer, itr);
12631272 evictionSuccessful = toReleaseHandle != nullptr ;
1264- // destroy toReleseHandle . The item won't be released to allocator
1265- // since we marked it as exclusive .
1273+ // destroy toReleaseHandle . The item won't be released to allocator
1274+ // since we marked for eviction .
12661275 }
12671276
1268- const auto ref = candidate->unmarkExclusive ();
1277+ const auto ref = candidate->unmarkMoving ();
12691278 if (ref == 0u ) {
12701279 // Invalidate iterator since later on we may use this mmContainer
12711280 // again, which cannot be done unless we drop this iterator
@@ -2352,7 +2361,7 @@ void CacheAllocator<CacheTrait>::releaseSlabImpl(
23522361 // Need to mark an item for release before proceeding
23532362 // If we can't mark as moving, it means the item is already freed
23542363 const bool isAlreadyFreed =
2355- !markExclusiveForSlabRelease (releaseContext, alloc, throttler);
2364+ !markMovingForSlabRelease (releaseContext, alloc, throttler);
23562365 if (isAlreadyFreed) {
23572366 continue ;
23582367 }
@@ -2397,8 +2406,8 @@ bool CacheAllocator<CacheTrait>::moveForSlabRelease(
23972406 stats_.numMoveAttempts .inc ();
23982407
23992408 // Nothing to move and the key is likely also bogus for chained items.
2400- if (oldItem.isOnlyExclusive ()) {
2401- oldItem.unmarkExclusive ();
2409+ if (oldItem.isOnlyMoving ()) {
2410+ oldItem.unmarkMoving ();
24022411 const auto res =
24032412 releaseBackToAllocator (oldItem, RemoveContext::kNormal , false );
24042413 XDCHECK (res == ReleaseRes::kReleased );
@@ -2437,7 +2446,7 @@ bool CacheAllocator<CacheTrait>::moveForSlabRelease(
24372446 // that's identical to this one to replace it. Here we just need to wait
24382447 // until all users have dropped the item handles before we can proceed.
24392448 startTime = util::getCurrentTimeSec ();
2440- while (!oldItem.isOnlyExclusive ()) {
2449+ while (!oldItem.isOnlyMoving ()) {
24412450 throttleWith (throttler, [&] {
24422451 XLOGF (WARN,
24432452 " Spent {} seconds, slab release still waiting for refcount to "
@@ -2491,8 +2500,8 @@ CacheAllocator<CacheTrait>::allocateNewItemForOldItem(const Item& oldItem) {
24912500 return {};
24922501 }
24932502
2494- // Set up the destination for the move. Since oldChainedItem would have
2495- // the exclusive bit set , it won't be picked for eviction.
2503+ // Set up the destination for the move. Since oldChainedItem would be
2504+ // marked as moving , it won't be picked for eviction.
24962505 auto newItemHdl =
24972506 allocateChainedItemInternal (parentHandle, oldChainedItem.getSize ());
24982507 if (!newItemHdl) {
@@ -2544,7 +2553,7 @@ bool CacheAllocator<CacheTrait>::tryMovingForSlabRelease(
25442553 // item is still valid.
25452554 const std::string parentKey =
25462555 oldItem.asChainedItem ().getParentItem (compressor_).getKey ().str ();
2547- if (oldItem.isOnlyExclusive ()) {
2556+ if (oldItem.isOnlyMoving ()) {
25482557 // If chained item no longer has a refcount, its parent is already
25492558 // being released, so we abort this try to moving.
25502559 return false ;
@@ -2574,10 +2583,10 @@ void CacheAllocator<CacheTrait>::evictForSlabRelease(
25742583 stats_.numEvictionAttempts .inc ();
25752584
25762585 // if the item is already in a state where only the exclusive bit is set,
2577- // nothing needs to be done. We simply need to unmark exclusive bit and free
2586+ // nothing needs to be done. We simply need to call unmarkMoving and free
25782587 // the item.
2579- if (item.isOnlyExclusive ()) {
2580- item.unmarkExclusive ();
2588+ if (item.isOnlyMoving ()) {
2589+ item.unmarkMoving ();
25812590 const auto res =
25822591 releaseBackToAllocator (item, RemoveContext::kNormal , false );
25832592 XDCHECK (ReleaseRes::kReleased == res);
@@ -2608,7 +2617,7 @@ void CacheAllocator<CacheTrait>::evictForSlabRelease(
26082617 stats_.numEvictionSuccesses .inc ();
26092618
26102619 // we have the last handle. no longer need to hold on to the exclusive bit
2611- item.unmarkExclusive ();
2620+ item.unmarkMoving ();
26122621
26132622 // manually decrement the refcount to call releaseBackToAllocator
26142623 const auto ref = decRef (*owningHandle);
@@ -2620,7 +2629,7 @@ void CacheAllocator<CacheTrait>::evictForSlabRelease(
26202629 }
26212630
26222631 if (shutDownInProgress_) {
2623- item.unmarkExclusive ();
2632+ item.unmarkMoving ();
26242633 allocator_->abortSlabRelease (ctx);
26252634 throw exception::SlabReleaseAborted (
26262635 folly::sformat (" Slab Release aborted while trying to evict"
@@ -2766,9 +2775,9 @@ CacheAllocator<CacheTrait>::advanceIteratorAndTryEvictChainedItem(
27662775template <typename CacheTrait>
27672776typename CacheAllocator<CacheTrait>::WriteHandle
27682777CacheAllocator<CacheTrait>::evictNormalItemForSlabRelease(Item& item) {
2769- XDCHECK (item.isExclusive ());
2778+ XDCHECK (item.isMoving ());
27702779
2771- if (item.isOnlyExclusive ()) {
2780+ if (item.isOnlyMoving ()) {
27722781 return WriteHandle{};
27732782 }
27742783
@@ -2780,7 +2789,7 @@ CacheAllocator<CacheTrait>::evictNormalItemForSlabRelease(Item& item) {
27802789
27812790 // We remove the item from both access and mm containers. It doesn't matter
27822791 // if someone else calls remove on the item at this moment, the item cannot
2783- // be freed as long as we have the exclusive bit set .
2792+ // be freed as long as it's marked for eviction .
27842793 auto handle = accessContainer_->removeIf (item, std::move (predicate));
27852794
27862795 if (!handle) {
@@ -2804,7 +2813,7 @@ CacheAllocator<CacheTrait>::evictNormalItemForSlabRelease(Item& item) {
28042813template <typename CacheTrait>
28052814typename CacheAllocator<CacheTrait>::WriteHandle
28062815CacheAllocator<CacheTrait>::evictChainedItemForSlabRelease(ChainedItem& child) {
2807- XDCHECK (child.isExclusive ());
2816+ XDCHECK (child.isMoving ());
28082817
28092818 // We have the child marked as moving, but dont know anything about the
28102819 // state of the parent. Unlike the case of regular eviction where we are
@@ -2826,7 +2835,7 @@ CacheAllocator<CacheTrait>::evictChainedItemForSlabRelease(ChainedItem& child) {
28262835 // check if the child is still in mmContainer and the expected parent is
28272836 // valid under the chained item lock.
28282837 if (expectedParent.getKey () != parentKey || !child.isInMMContainer () ||
2829- child.isOnlyExclusive () ||
2838+ child.isOnlyMoving () ||
28302839 &expectedParent != &child.getParentItem (compressor_) ||
28312840 !expectedParent.isAccessible () || !expectedParent.hasChainedItem ()) {
28322841 return {};
@@ -2881,14 +2890,14 @@ CacheAllocator<CacheTrait>::evictChainedItemForSlabRelease(ChainedItem& child) {
28812890
28822891 // In case someone else had removed this chained item from its parent by now
28832892 // So we check again to see if it has been unlinked from its parent
2884- if (!child.isInMMContainer () || child.isOnlyExclusive ()) {
2893+ if (!child.isInMMContainer () || child.isOnlyMoving ()) {
28852894 return {};
28862895 }
28872896
28882897 // check after removing from the MMContainer that the parent is still not
28892898 // being marked as moving. If parent is moving, it will release the child
28902899 // item and we will wait for that.
2891- if (parentHandle->isExclusive ()) {
2900+ if (parentHandle->isMoving ()) {
28922901 return {};
28932902 }
28942903
@@ -2921,7 +2930,7 @@ bool CacheAllocator<CacheTrait>::removeIfExpired(const ReadHandle& handle) {
29212930}
29222931
29232932template <typename CacheTrait>
2924- bool CacheAllocator<CacheTrait>::markExclusiveForSlabRelease (
2933+ bool CacheAllocator<CacheTrait>::markMovingForSlabRelease (
29252934 const SlabReleaseContext& ctx, void * alloc, util::Throttler& throttler) {
29262935 // MemoryAllocator::processAllocForRelease will execute the callback
29272936 // if the item is not already free. So there are three outcomes here:
@@ -2940,7 +2949,7 @@ bool CacheAllocator<CacheTrait>::markExclusiveForSlabRelease(
29402949 // Since this callback is executed, the item is not yet freed
29412950 itemFreed = false ;
29422951 Item* item = static_cast <Item*>(memory);
2943- if (item->markExclusive ()) {
2952+ if (item->markMoving ()) {
29442953 markedMoving = true ;
29452954 }
29462955 };
0 commit comments