forked from OSchip/llvm-project
tsan: extend MutexSet to memorize mutex address/stack_id
We currently memorize u64 id + epoch for each mutex. The new tsan runtime will memorize address + stack_id instead. But switching to address + stack_id requires new trace, which in turn requires new MutexSet and some other changes. Extend MutexSet to support both new and old info to break the dependency cycles. The plan is to remove the old info/methods after switching to the new runtime. Reviewed By: vitalybuka, melver Differential Revision: https://reviews.llvm.org/D107910
This commit is contained in:
parent
f52fc591fa
commit
d9afba9000
|
@ -17,7 +17,6 @@ namespace __tsan {
|
|||
const uptr MutexSet::kMaxSize;
|
||||
|
||||
MutexSet::MutexSet() {
|
||||
size_ = 0;
|
||||
internal_memset(&descs_, 0, sizeof(descs_));
|
||||
}
|
||||
|
||||
|
@ -44,9 +43,12 @@ void MutexSet::Add(u64 id, bool write, u64 epoch) {
|
|||
CHECK_EQ(size_, kMaxSize - 1);
|
||||
}
|
||||
// Add new mutex descriptor.
|
||||
descs_[size_].addr = 0;
|
||||
descs_[size_].stack_id = kInvalidStackID;
|
||||
descs_[size_].id = id;
|
||||
descs_[size_].write = write;
|
||||
descs_[size_].epoch = epoch;
|
||||
descs_[size_].seq = seq_++;
|
||||
descs_[size_].count = 1;
|
||||
size_++;
|
||||
}
|
||||
|
@ -70,6 +72,46 @@ void MutexSet::Remove(u64 id) {
|
|||
}
|
||||
}
|
||||
|
||||
void MutexSet::AddAddr(uptr addr, StackID stack_id, bool write) {
|
||||
// Look up existing mutex with the same id.
|
||||
for (uptr i = 0; i < size_; i++) {
|
||||
if (descs_[i].addr == addr) {
|
||||
descs_[i].count++;
|
||||
descs_[i].seq = seq_++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// On overflow, find the oldest mutex and drop it.
|
||||
if (size_ == kMaxSize) {
|
||||
uptr min = 0;
|
||||
for (uptr i = 0; i < size_; i++) {
|
||||
if (descs_[i].seq < descs_[min].seq)
|
||||
min = i;
|
||||
}
|
||||
RemovePos(min);
|
||||
CHECK_EQ(size_, kMaxSize - 1);
|
||||
}
|
||||
// Add new mutex descriptor.
|
||||
descs_[size_].addr = addr;
|
||||
descs_[size_].stack_id = stack_id;
|
||||
descs_[size_].id = 0;
|
||||
descs_[size_].write = write;
|
||||
descs_[size_].epoch = 0;
|
||||
descs_[size_].seq = seq_++;
|
||||
descs_[size_].count = 1;
|
||||
size_++;
|
||||
}
|
||||
|
||||
void MutexSet::DelAddr(uptr addr, bool destroy) {
|
||||
for (uptr i = 0; i < size_; i++) {
|
||||
if (descs_[i].addr == addr) {
|
||||
if (destroy || --descs_[i].count == 0)
|
||||
RemovePos(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MutexSet::RemovePos(uptr i) {
|
||||
CHECK_LT(i, size_);
|
||||
descs_[i] = descs_[size_ - 1];
|
||||
|
|
|
@ -23,9 +23,12 @@ class MutexSet {
|
|||
// The oldest mutexes are discarded on overflow.
|
||||
static const uptr kMaxSize = 16;
|
||||
struct Desc {
|
||||
uptr addr;
|
||||
StackID stack_id;
|
||||
u64 id;
|
||||
u64 epoch;
|
||||
int count;
|
||||
u32 seq;
|
||||
u32 count;
|
||||
bool write;
|
||||
};
|
||||
|
||||
|
@ -34,21 +37,24 @@ class MutexSet {
|
|||
void Add(u64 id, bool write, u64 epoch);
|
||||
void Del(u64 id, bool write);
|
||||
void Remove(u64 id); // Removes the mutex completely (if it's destroyed).
|
||||
void AddAddr(uptr addr, StackID stack_id, bool write);
|
||||
void DelAddr(uptr addr, bool destroy = false);
|
||||
uptr Size() const;
|
||||
Desc Get(uptr i) const;
|
||||
|
||||
MutexSet(const MutexSet& other) { *this = other; }
|
||||
void operator=(const MutexSet &other) {
|
||||
internal_memcpy(this, &other, sizeof(*this));
|
||||
}
|
||||
|
||||
private:
|
||||
#if !SANITIZER_GO
|
||||
uptr size_;
|
||||
u32 seq_ = 0;
|
||||
uptr size_ = 0;
|
||||
Desc descs_[kMaxSize];
|
||||
#endif
|
||||
|
||||
void RemovePos(uptr i);
|
||||
MutexSet(const MutexSet&);
|
||||
#endif
|
||||
};
|
||||
|
||||
// Go does not have mutexes, so do not spend memory and time.
|
||||
|
@ -59,7 +65,8 @@ MutexSet::MutexSet() {}
|
|||
void MutexSet::Add(u64 id, bool write, u64 epoch) {}
|
||||
void MutexSet::Del(u64 id, bool write) {}
|
||||
void MutexSet::Remove(u64 id) {}
|
||||
void MutexSet::RemovePos(uptr i) {}
|
||||
void MutexSet::AddAddr(uptr addr, StackID stack_id, bool write) {}
|
||||
void MutexSet::DelAddr(uptr addr, bool destroy) {}
|
||||
uptr MutexSet::Size() const { return 0; }
|
||||
MutexSet::Desc MutexSet::Get(uptr i) const { return Desc(); }
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue