@@ -677,6 +677,16 @@ void CacheAllocator<CacheTrait>::transferChainLocked(WriteHandle& parent,
677677 XDCHECK (curr->isInMMContainer ());
678678 curr->changeKey (newParentPtr);
679679 curr = curr->getNext (compressor_);
680+
681+ if (curr->isMoving ()) {
682+ WriteHandle h;
683+ if (!tryGetHandleWithWaitContextForMovingItem (*curr, h)) {
684+ continue ;
685+ }
686+
687+ // synchronize with eviction
688+ curr = h.get ();
689+ }
680690 }
681691
682692 newParent->markHasChainedItem ();
@@ -809,6 +819,16 @@ CacheAllocator<CacheTrait>::replaceChainedItemLocked(Item& oldItem,
809819 while (curr != nullptr && curr != &oldItem) {
810820 prev = curr;
811821 curr = curr->getNext (compressor_);
822+
823+ if (curr->isMoving ()) {
824+ WriteHandle h;
825+ if (!tryGetHandleWithWaitContextForMovingItem (*curr, h)) {
826+ continue ;
827+ }
828+
829+ // synchronize with eviction
830+ curr = h.get ();
831+ }
812832 }
813833
814834 XDCHECK (curr != nullptr );
@@ -1463,7 +1483,7 @@ bool CacheAllocator<CacheTrait>::moveRegularItem(Item& oldItem,
14631483 }
14641484 newItemHdl.unmarkNascent ();
14651485 return true ;
1466- }
1486+ }
14671487
14681488template <typename CacheTrait>
14691489bool CacheAllocator<CacheTrait>::moveChainedItem(ChainedItem& oldItem,
@@ -1579,7 +1599,7 @@ CacheAllocator<CacheTrait>::findEviction(TierId tid, PoolId pid, ClassId cid) {
15791599
15801600 auto * toRecycle_ = itr.get ();
15811601 auto * candidate_ =
1582- toRecycle_->isChainedItem ()
1602+ toRecycle_->isChainedItem () && lastTier
15831603 ? &toRecycle_->asChainedItem ().getParentItem (compressor_)
15841604 : toRecycle_;
15851605
@@ -1655,8 +1675,22 @@ CacheAllocator<CacheTrait>::findEviction(TierId tid, PoolId pid, ClassId cid) {
16551675 // as exclusive since we will not be moving the item to the next tier
16561676 // but rather just evicting all together, no need to
16571677 // markForEvictionWhenMoving
1658- auto ret = lastTier ? true : candidate->markForEvictionWhenMoving ();
1659- XDCHECK (ret);
1678+
1679+ auto syncItem = candidate;
1680+ if (candidate->isChainedItem () && !lastTier) {
1681+ auto &parent = candidate->asChainedItem ().getParentItem (compressor_);
1682+ if (!parent.markForEviction ()) {
1683+ auto ret = candidate->unmarkMoving ();
1684+ // TODO: cleanup
1685+
1686+ continue ;
1687+ }
1688+
1689+ candidate = &parent;
1690+ } else {
1691+ auto ret = lastTier ? true : candidate->markForEvictionWhenMoving ();
1692+ XDCHECK (ret);
1693+ }
16601694
16611695 unlinkItemForEviction (*candidate);
16621696
@@ -1667,7 +1701,7 @@ CacheAllocator<CacheTrait>::findEviction(TierId tid, PoolId pid, ClassId cid) {
16671701 // wake up any readers that wait for the move to complete
16681702 // it's safe to do now, as we have the item marked exclusive and
16691703 // no other reader can be added to the waiters list
1670- wakeUpWaiters (*candidate , {});
1704+ wakeUpWaiters (*syncItem , {});
16711705
16721706 } else {
16731707 XDCHECK (!evictedToNext->isMarkedForEviction () && !evictedToNext->isMoving ());
@@ -1689,6 +1723,7 @@ CacheAllocator<CacheTrait>::findEviction(TierId tid, PoolId pid, ClassId cid) {
16891723 } else {
16901724 (*stats_.regularItemEvictions )[tid][pid][cid].inc ();
16911725 }
1726+ // TODO: update stats if candidate is child item (and extend for moved items!)
16921727
16931728 if (auto eventTracker = getEventTracker ()) {
16941729 eventTracker->record (AllocatorApiEvent::DRAM_EVICT, candidate->getKey (),
@@ -1761,7 +1796,24 @@ CacheAllocator<CacheTrait>::tryEvictToNextMemoryTier(
17611796 TierId tid, PoolId pid, Item& item, bool fromBgThread) {
17621797 XDCHECK (item.isMoving ());
17631798 XDCHECK (item.getRefCount () == 0 );
1764- if (item.hasChainedItem ()) return WriteHandle{}; // TODO: We do not support ChainedItem yet
1799+ if (item.hasChainedItem ()) {
1800+ TierId nextTier = tid;
1801+ while (++nextTier < getNumTiers ()) {
1802+ auto newItemHdl = allocateNewItemForOldItem (item); // TODO: actually allocate from the nextTierId... (extend allocateNewItemForOldItem to accept tid)
1803+
1804+ if (newItemHdl) {
1805+ XDCHECK_EQ (newItemHdl->getSize (), item.getSize ());
1806+ if (!moveChainedItem (item, newItemHdl)) {
1807+ return WriteHandle{};
1808+ }
1809+ XDCHECK_EQ (newItemHdl->getKey (),item.getKey ());
1810+ item.unmarkMoving ();
1811+ return newItemHdl;
1812+ } else {
1813+ return WriteHandle{};
1814+ }
1815+ }
1816+ }
17651817 if (item.isExpired ()) {
17661818 accessContainer_->remove (item);
17671819 item.unmarkMoving ();
0 commit comments