sal: fix watch/breakpoint perf implementation

This commit changes the entities in a ResultSet from listener indexes
(into ListenerManagers m_BufferList) to BaseListener pointers, as
ListenerManager::makeActive(BaseListener*) (called from
FastBreakpoints/Watchpoints.ah) may invalidate indexes temporarily
stored in a ResultSet.  The issue occurs when multiple breakpoints
(watchpoints) fire at the same time, and one added more recently than
the others occupies the largest index position in m_BufferList.

Although this issue is extremely rare and was only observed in a few
corner cases up to now, it may have falsified results in the past.

Change-Id: I7b788a06d412f15700ca75f56f2be5d3b78465fa
This commit is contained in:
Horst Schirmeier
2015-01-13 19:09:54 +01:00
parent 32e8a679b5
commit c4d44aeb0c
5 changed files with 9 additions and 8 deletions

View File

@ -16,7 +16,7 @@ ResultSet& PerfVectorBreakpoints::gather(BPEvent* pData)
// Update trigger IPtr:
pLi->setTriggerInstructionPointer(pData->getTriggerInstructionPointer());
pLi->setTriggerCPU(pData->getTriggerCPU());
res.add(*it);
res.add(pLi);
}
}
return res;

View File

@ -44,14 +44,15 @@ public:
* Results (= indices of matching listeners) returned by the "gather"-method,
* see below. (This class can be seen as a "temporary fire-list".)
*/
class BaseListener;
class ResultSet {
private:
std::vector<index_t> m_Res; //!< vector of matching listener indices
std::vector<BaseListener *> m_Res; //!< vector of pointers to matching listeners
public:
ResultSet() { }
bool hasMore() const { return !m_Res.empty(); }
index_t getNext() { index_t idx = m_Res.back(); m_Res.pop_back(); return idx; }
void add(index_t idx) { m_Res.push_back(idx); }
BaseListener *getNext() { BaseListener *l = m_Res.back(); m_Res.pop_back(); return l; }
void add(BaseListener *l) { m_Res.push_back(l); }
size_t size() const { return m_Res.size(); }
void clear() { m_Res.clear(); }
};

View File

@ -65,12 +65,12 @@ aspect FastBreakpoints {
// Check for matching BPSingleListeners:
fail::ResultSet& res1 = ref.getSingleListeners().gather(&tmp);
while (res1.hasMore())
ref.makeActive(ref.dereference(res1.getNext()));
ref.makeActive(res1.getNext());
// Check for matching BPRangeListeners:
fail::ResultSet& res2 = ref.getRangeListeners().gather(&tmp);
while (res2.hasMore())
ref.makeActive(ref.dereference(res2.getNext()));
ref.makeActive(res2.getNext());
ref.triggerActiveListeners();
}

View File

@ -64,7 +64,7 @@ aspect FastWatchpoints {
// Check for matching MemAccessListener:
fail::ResultSet& res = ref.getMemoryListeners().gather(&tmp);
while (res.hasMore())
ref.makeActive(ref.dereference(res.getNext()));
ref.makeActive(res.getNext());
ref.triggerActiveListeners();
}

View File

@ -20,7 +20,7 @@ ResultSet& PerfVectorWatchpoints::gather(MemAccessEvent* pData)
pmal->setTriggerWidth(pData->getTriggerWidth());
pmal->setTriggerAccessType(pData->getTriggerAccessType());
pmal->setTriggerCPU(pData->getTriggerCPU());
res.add(*it);
res.add(pmal);
}
}
return res;