tsan: store sync objects in memory block headers + delete them when the block is freed

llvm-svn: 161959
This commit is contained in:
Dmitry Vyukov 2012-08-15 17:27:20 +00:00
parent b6f46c1af9
commit 1c0b3c6b84
3 changed files with 67 additions and 3 deletions

View File

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

View File

@ -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);
}

View File

@ -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;
{