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.
This commit is contained in:
Mitch Hayenga 2013-01-08 08:54:07 -05:00
parent dc4a0aa2fa
commit c7dbd5e768

41
src/mem/cache/blk.hh vendored
View file

@ -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<Lock>::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;
}
}