From c7dbd5e7686bbb065dfe2a74b92f4d9463ddfa80 Mon Sep 17 00:00:00 2001 From: Mitch Hayenga Date: Tue, 8 Jan 2013 08:54:07 -0500 Subject: [PATCH] mem: Make LL/SC locks fine grained The current implementation in gem5 just keeps a list of locks per cacheline. Due to this, a store to a non-overlapping portion of the cacheline can cause an LL/SC pair to fail. This patch simply adds an address range to the lock structure, so that the lock is only invalidated if the store overlaps the lock range. --- src/mem/cache/blk.hh | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/src/mem/cache/blk.hh b/src/mem/cache/blk.hh index 3557bc489..80216ff89 100644 --- a/src/mem/cache/blk.hh +++ b/src/mem/cache/blk.hh @@ -127,15 +127,30 @@ class CacheBlk class Lock { public: int contextId; // locking context + Addr lowAddr; // low address of lock range + Addr highAddr; // high address of lock range // check for matching execution context bool matchesContext(Request *req) { - return (contextId == req->contextId()); + Addr req_low = req->getPaddr(); + Addr req_high = req_low + req->getSize() -1; + return (contextId == req->contextId()) && + (req_low >= lowAddr) && (req_high <= highAddr); + } + + bool overlapping(Request *req) + { + Addr req_low = req->getPaddr(); + Addr req_high = req_low + req->getSize() - 1; + + return (req_low <= highAddr) && (req_high >= lowAddr); } Lock(Request *req) - : contextId(req->contextId()) + : contextId(req->contextId()), + lowAddr(req->getPaddr()), + highAddr(lowAddr + req->getSize() - 1) { } }; @@ -255,7 +270,23 @@ class CacheBlk * Clear the list of valid load locks. Should be called whenever * block is written to or invalidated. */ - void clearLoadLocks() { lockList.clear(); } + void clearLoadLocks(Request *req = NULL) + { + if (!req) { + // No request, invaldate all locks to this line + lockList.clear(); + } else { + // Only invalidate locks that overlap with this request + std::list::iterator lock_itr = lockList.begin(); + while (lock_itr != lockList.end()) { + if (lock_itr->overlapping(req)) { + lock_itr = lockList.erase(lock_itr); + } else { + ++lock_itr; + } + } + } + } /** * Handle interaction of load-locked operations and stores. @@ -283,12 +314,12 @@ class CacheBlk } req->setExtraData(success ? 1 : 0); - clearLoadLocks(); + clearLoadLocks(req); return success; } else { // for *all* stores (conditional or otherwise) we have to // clear the list of load-locks as they're all invalid now. - clearLoadLocks(); + clearLoadLocks(req); return true; } }