mem: Be less conservative in clearing load locks in the cache

Avoid being overly conservative in clearing load locks in the cache,
and allow writes to the line if they are from the same context. This
is in line with ALPHA and ARM.
This commit is contained in:
Andreas Hansson 2016-02-10 04:08:25 -05:00
parent 92f021cbbe
commit 83a5977481

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

@ -134,8 +134,9 @@ class CacheBlk
Addr lowAddr; // low address of lock range Addr lowAddr; // low address of lock range
Addr highAddr; // high address of lock range Addr highAddr; // high address of lock range
// check for matching execution context // check for matching execution context, and an address that
bool matchesContext(const RequestPtr req) const // is within the lock
bool matches(const RequestPtr req) const
{ {
Addr req_low = req->getPaddr(); Addr req_low = req->getPaddr();
Addr req_high = req_low + req->getSize() -1; Addr req_high = req_low + req->getSize() -1;
@ -143,7 +144,8 @@ class CacheBlk
(req_low >= lowAddr) && (req_high <= highAddr); (req_low >= lowAddr) && (req_high <= highAddr);
} }
bool overlapping(const RequestPtr req) const // check if a request is intersecting and thus invalidating the lock
bool intersects(const RequestPtr req) const
{ {
Addr req_low = req->getPaddr(); Addr req_low = req->getPaddr();
Addr req_high = req_low + req->getSize() - 1; Addr req_high = req_low + req->getSize() - 1;
@ -214,7 +216,7 @@ class CacheBlk
{ {
status = 0; status = 0;
isTouched = false; isTouched = false;
clearLoadLocks(); lockList.clear();
} }
/** /**
@ -246,35 +248,35 @@ class CacheBlk
} }
/** /**
* Track the fact that a local locked was issued to the block. If * Track the fact that a local locked was issued to the
* multiple LLs get issued from the same context we could have * block. Invalidate any previous LL to the same address.
* redundant records on the list, but that's OK, as they'll all
* get blown away at the next store.
*/ */
void trackLoadLocked(PacketPtr pkt) void trackLoadLocked(PacketPtr pkt)
{ {
assert(pkt->isLLSC()); assert(pkt->isLLSC());
auto l = lockList.begin();
while (l != lockList.end()) {
if (l->intersects(pkt->req))
l = lockList.erase(l);
else
++l;
}
lockList.emplace_front(pkt->req); lockList.emplace_front(pkt->req);
} }
/** /**
* Clear the list of valid load locks. Should be called whenever * Clear the any load lock that intersect the request, and is from
* block is written to or invalidated. * a different context.
*/ */
void clearLoadLocks(RequestPtr req = nullptr) void clearLoadLocks(RequestPtr req)
{ {
if (!req) { auto l = lockList.begin();
// No request, invaldate all locks to this line while (l != lockList.end()) {
lockList.clear(); if (l->intersects(req) && l->contextId != req->contextId()) {
l = lockList.erase(l);
} else { } else {
// Only invalidate locks that overlap with this request ++l;
auto lock_itr = lockList.begin();
while (lock_itr != lockList.end()) {
if (lock_itr->overlapping(req)) {
lock_itr = lockList.erase(lock_itr);
} else {
++lock_itr;
}
} }
} }
} }
@ -344,22 +346,27 @@ class CacheBlk
// load locked. // load locked.
bool success = false; bool success = false;
for (const auto& l : lockList) { auto l = lockList.begin();
if (l.matchesContext(req)) { while (l != lockList.end() && !success) {
// it's a store conditional, and as far as the memory if (l->matches(pkt->req)) {
// system can tell, the requesting context's lock is // it's a store conditional, and as far as the
// still valid. // memory system can tell, the requesting
// context's lock is still valid.
success = true; success = true;
break; lockList.erase(l);
} }
++l;
} }
req->setExtraData(success ? 1 : 0); req->setExtraData(success ? 1 : 0);
// clear any intersected locks from other contexts (our LL
// should already have cleared them)
clearLoadLocks(req); clearLoadLocks(req);
return success; return success;
} else { } else {
// for *all* stores (conditional or otherwise) we have to // a normal write, if there is any lock not from this
// clear the list of load-locks as they're all invalid now. // context we clear the list, thus for a private cache we
// never clear locks on normal writes
clearLoadLocks(req); clearLoadLocks(req);
return true; return true;
} }