forked from OSchip/llvm-project
tsan: store sync objects in memory block headers + delete them when the block is freed
llvm-svn: 161959
This commit is contained in:
parent
b6f46c1af9
commit
1c0b3c6b84
|
@ -145,10 +145,11 @@ class SizeClassAllocator64 {
|
|||
region->free_list.append_front(free_list);
|
||||
}
|
||||
|
||||
bool PointerIsMine(void *p) {
|
||||
static bool PointerIsMine(void *p) {
|
||||
return reinterpret_cast<uptr>(p) / kSpaceSize == kSpaceBeg / kSpaceSize;
|
||||
}
|
||||
uptr GetSizeClass(void *p) {
|
||||
|
||||
static uptr GetSizeClass(void *p) {
|
||||
return (reinterpret_cast<uptr>(p) / kRegionSize) % kNumClasses;
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ void *user_alloc(ThreadState *thr, uptr pc, uptr sz, uptr align) {
|
|||
MBlock *b = (MBlock*)allocator()->GetMetaData(p);
|
||||
b->size = sz;
|
||||
if (CTX() && CTX()->initialized) {
|
||||
MemoryResetRange(thr, pc, (uptr)p, sz);
|
||||
MemoryRangeImitateWrite(thr, pc, (uptr)p, sz);
|
||||
}
|
||||
DPrintf("#%d: alloc(%zu) = %p\n", thr->tid, sz, p);
|
||||
SignalUnsafeCall(thr, pc);
|
||||
|
@ -62,6 +62,18 @@ void user_free(ThreadState *thr, uptr pc, void *p) {
|
|||
CHECK_NE(p, (void*)0);
|
||||
DPrintf("#%d: free(%p)\n", thr->tid, p);
|
||||
MBlock *b = (MBlock*)allocator()->GetMetaData(p);
|
||||
if (b->head) {
|
||||
Lock l(&b->mtx);
|
||||
for (SyncVar *s = b->head; s;) {
|
||||
SyncVar *res = s;
|
||||
s = s->next;
|
||||
StatInc(thr, StatSyncDestroyed);
|
||||
res->mtx.Lock();
|
||||
res->mtx.Unlock();
|
||||
DestroyAndFree(res);
|
||||
}
|
||||
b->head = 0;
|
||||
}
|
||||
if (CTX() && CTX()->initialized && thr->in_rtl == 1) {
|
||||
MemoryRangeFreed(thr, pc, (uptr)p, b->size);
|
||||
}
|
||||
|
|
|
@ -47,6 +47,31 @@ SyncTab::~SyncTab() {
|
|||
|
||||
SyncVar* SyncTab::GetAndLock(ThreadState *thr, uptr pc,
|
||||
uptr addr, bool write_lock) {
|
||||
#ifndef TSAN_GO
|
||||
if (PrimaryAllocator::PointerIsMine((void*)addr)) {
|
||||
MBlock *b = user_mblock(thr, (void*)addr);
|
||||
Lock l(&b->mtx);
|
||||
SyncVar *res = 0;
|
||||
for (res = b->head; res; res = res->next) {
|
||||
if (res->addr == addr)
|
||||
break;
|
||||
}
|
||||
if (res == 0) {
|
||||
StatInc(thr, StatSyncCreated);
|
||||
void *mem = internal_alloc(MBlockSync, sizeof(SyncVar));
|
||||
res = new(mem) SyncVar(addr);
|
||||
res->creation_stack.ObtainCurrent(thr, pc);
|
||||
res->next = b->head;
|
||||
b->head = res;
|
||||
}
|
||||
if (write_lock)
|
||||
res->mtx.Lock();
|
||||
else
|
||||
res->mtx.ReadLock();
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
Part *p = &tab_[PartIdx(addr)];
|
||||
{
|
||||
ReadLock l(&p->mtx);
|
||||
|
@ -86,6 +111,32 @@ SyncVar* SyncTab::GetAndLock(ThreadState *thr, uptr pc,
|
|||
}
|
||||
|
||||
SyncVar* SyncTab::GetAndRemove(ThreadState *thr, uptr pc, uptr addr) {
|
||||
#ifndef TSAN_GO
|
||||
if (PrimaryAllocator::PointerIsMine((void*)addr)) {
|
||||
MBlock *b = user_mblock(thr, (void*)addr);
|
||||
SyncVar *res = 0;
|
||||
{
|
||||
Lock l(&b->mtx);
|
||||
SyncVar **prev = &b->head;
|
||||
res = *prev;
|
||||
while (res) {
|
||||
if (res->addr == addr) {
|
||||
*prev = res->next;
|
||||
break;
|
||||
}
|
||||
prev = &res->next;
|
||||
res = *prev;
|
||||
}
|
||||
}
|
||||
if (res) {
|
||||
StatInc(thr, StatSyncDestroyed);
|
||||
res->mtx.Lock();
|
||||
res->mtx.Unlock();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
Part *p = &tab_[PartIdx(addr)];
|
||||
SyncVar *res = 0;
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue