diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2012-12-18 06:57:34 +0000 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2012-12-18 06:57:34 +0000 |
| commit | 6d315cbcc336eb4d1c3e05e1456acd90978df6f1 (patch) | |
| tree | 4638371d77d253e3848d92b475540452c7795780 /compiler-rt/lib/tsan/rtl/tsan_fd.cc | |
| parent | c0699854dd46e8ae6ca87695922f6fb5927e93b1 (diff) | |
| download | bcm5719-llvm-6d315cbcc336eb4d1c3e05e1456acd90978df6f1.tar.gz bcm5719-llvm-6d315cbcc336eb4d1c3e05e1456acd90978df6f1.zip | |
tsan: describe "file descriptor" location
llvm-svn: 170417
Diffstat (limited to 'compiler-rt/lib/tsan/rtl/tsan_fd.cc')
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_fd.cc | 155 |
1 files changed, 91 insertions, 64 deletions
diff --git a/compiler-rt/lib/tsan/rtl/tsan_fd.cc b/compiler-rt/lib/tsan/rtl/tsan_fd.cc index cb91c413166..4431097e168 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_fd.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_fd.cc @@ -21,154 +21,181 @@ const int kTableSizeL1 = 1024; const int kTableSizeL2 = 1024; const int kTableSize = kTableSizeL1 * kTableSizeL2; -struct FdDesc { +struct FdSync { atomic_uint64_t rc; }; +struct FdDesc { + FdSync *sync; + int creation_tid; + u32 creation_stack; +}; + struct FdContext { atomic_uintptr_t tab[kTableSizeL1]; // Addresses used for synchronization. - FdDesc globdesc; - FdDesc filedesc; - FdDesc sockdesc; + FdSync globsync; + FdSync filesync; + FdSync socksync; u64 connectsync; }; static FdContext fdctx; -static FdDesc *allocdesc() { - FdDesc *pd = (FdDesc*)internal_alloc(MBlockFD, sizeof(FdDesc)); - atomic_store(&pd->rc, 1, memory_order_relaxed); - return pd; +static FdSync *allocsync() { + FdSync *s = (FdSync*)internal_alloc(MBlockFD, sizeof(FdSync)); + atomic_store(&s->rc, 1, memory_order_relaxed); + return s; } -static FdDesc *ref(FdDesc *pd) { - if (pd && atomic_load(&pd->rc, memory_order_relaxed) != (u64)-1) - atomic_fetch_add(&pd->rc, 1, memory_order_relaxed); - return pd; +static FdSync *ref(FdSync *s) { + if (s && atomic_load(&s->rc, memory_order_relaxed) != (u64)-1) + atomic_fetch_add(&s->rc, 1, memory_order_relaxed); + return s; } -static void unref(ThreadState *thr, uptr pc, FdDesc *pd) { - if (pd && atomic_load(&pd->rc, memory_order_relaxed) != (u64)-1) { - if (atomic_fetch_sub(&pd->rc, 1, memory_order_acq_rel) == 1) { - CHECK_NE(pd, &fdctx.globdesc); - CHECK_NE(pd, &fdctx.filedesc); - CHECK_NE(pd, &fdctx.sockdesc); - SyncVar *s = CTX()->synctab.GetAndRemove(thr, pc, (uptr)pd); - if (s) - DestroyAndFree(s); - internal_free(pd); +static void unref(ThreadState *thr, uptr pc, FdSync *s) { + if (s && atomic_load(&s->rc, memory_order_relaxed) != (u64)-1) { + if (atomic_fetch_sub(&s->rc, 1, memory_order_acq_rel) == 1) { + CHECK_NE(s, &fdctx.globsync); + CHECK_NE(s, &fdctx.filesync); + CHECK_NE(s, &fdctx.socksync); + SyncVar *v = CTX()->synctab.GetAndRemove(thr, pc, (uptr)s); + if (v) + DestroyAndFree(v); + internal_free(s); } } } -static FdDesc **fdaddr(ThreadState *thr, uptr pc, int fd) { +static FdDesc *fddesc(ThreadState *thr, uptr pc, int fd) { CHECK_LT(fd, kTableSize); atomic_uintptr_t *pl1 = &fdctx.tab[fd / kTableSizeL2]; uptr l1 = atomic_load(pl1, memory_order_consume); if (l1 == 0) { - uptr size = kTableSizeL2 * sizeof(uptr); + uptr size = kTableSizeL2 * sizeof(FdDesc); void *p = internal_alloc(MBlockFD, size); internal_memset(p, 0, size); - MemoryResetRange(thr, (uptr)&fdaddr, (uptr)p, size); + MemoryResetRange(thr, (uptr)&fddesc, (uptr)p, size); if (atomic_compare_exchange_strong(pl1, &l1, (uptr)p, memory_order_acq_rel)) l1 = (uptr)p; else internal_free(p); } - return &((FdDesc**)l1)[fd % kTableSizeL2]; // NOLINT + return &((FdDesc*)l1)[fd % kTableSizeL2]; // NOLINT } // pd must be already ref'ed. -static void init(ThreadState *thr, uptr pc, int fd, FdDesc *d) { - FdDesc **pd = fdaddr(thr, pc, fd); +static void init(ThreadState *thr, uptr pc, int fd, FdSync *s) { + FdDesc *d = fddesc(thr, pc, fd); // As a matter of fact, we don't intercept all close calls. // See e.g. libc __res_iclose(). - if (*pd) - unref(thr, pc, *pd); - *pd = d; + if (d->sync) + unref(thr, pc, d->sync); + d->sync = s; + d->creation_tid = thr->tid; + d->creation_stack = CurrentStackId(thr, pc); // To catch races between fd usage and open. - MemoryRangeImitateWrite(thr, pc, (uptr)pd, 8); + MemoryRangeImitateWrite(thr, pc, (uptr)d, 8); } void FdInit() { - atomic_store(&fdctx.globdesc.rc, (u64)-1, memory_order_relaxed); - atomic_store(&fdctx.filedesc.rc, (u64)-1, memory_order_relaxed); - atomic_store(&fdctx.sockdesc.rc, (u64)-1, memory_order_relaxed); + atomic_store(&fdctx.globsync.rc, (u64)-1, memory_order_relaxed); + atomic_store(&fdctx.filesync.rc, (u64)-1, memory_order_relaxed); + atomic_store(&fdctx.socksync.rc, (u64)-1, memory_order_relaxed); +} + +bool FdLocation(uptr addr, int *fd, int *tid, u32 *stack) { + for (int l1 = 0; l1 < kTableSizeL1; l1++) { + FdDesc *tab = (FdDesc*)atomic_load(&fdctx.tab[l1], memory_order_relaxed); + if (tab == 0) + break; + if (addr >= (uptr)tab && addr < (uptr)(tab + kTableSizeL2)) { + int l2 = (addr - (uptr)tab) / sizeof(FdDesc); + FdDesc *d = &tab[l2]; + *fd = l1 * kTableSizeL1 + l2; + *tid = d->creation_tid; + *stack = d->creation_stack; + return true; + } + } + return false; } void FdAcquire(ThreadState *thr, uptr pc, int fd) { - FdDesc **pd = fdaddr(thr, pc, fd); - FdDesc *d = *pd; - DPrintf("#%d: FdAcquire(%d) -> %p\n", thr->tid, fd, d); - MemoryRead8Byte(thr, pc, (uptr)pd); - if (d) - Acquire(thr, pc, (uptr)d); + FdDesc *d = fddesc(thr, pc, fd); + FdSync *s = d->sync; + DPrintf("#%d: FdAcquire(%d) -> %p\n", thr->tid, fd, s); + MemoryRead8Byte(thr, pc, (uptr)d); + if (s) + Acquire(thr, pc, (uptr)s); } void FdRelease(ThreadState *thr, uptr pc, int fd) { - FdDesc **pd = fdaddr(thr, pc, fd); - FdDesc *d = *pd; - DPrintf("#%d: FdRelease(%d) -> %p\n", thr->tid, fd, d); - if (d) - Release(thr, pc, (uptr)d); - MemoryRead8Byte(thr, pc, (uptr)pd); + FdDesc *d = fddesc(thr, pc, fd); + FdSync *s = d->sync; + DPrintf("#%d: FdRelease(%d) -> %p\n", thr->tid, fd, s); + if (s) + Release(thr, pc, (uptr)s); + MemoryRead8Byte(thr, pc, (uptr)d); } void FdClose(ThreadState *thr, uptr pc, int fd) { DPrintf("#%d: FdClose(%d)\n", thr->tid, fd); - FdDesc **pd = fdaddr(thr, pc, fd); + FdDesc *d = fddesc(thr, pc, fd); // To catch races between fd usage and close. - MemoryWrite8Byte(thr, pc, (uptr)pd); + MemoryWrite8Byte(thr, pc, (uptr)d); // We need to clear it, because if we do not intercept any call out there // that creates fd, we will hit false postives. - MemoryResetRange(thr, pc, (uptr)pd, 8); - unref(thr, pc, *pd); - *pd = 0; + MemoryResetRange(thr, pc, (uptr)d, 8); + unref(thr, pc, d->sync); + d->sync = 0; + d->creation_tid = 0; + d->creation_stack = 0; } void FdFileCreate(ThreadState *thr, uptr pc, int fd) { DPrintf("#%d: FdFileCreate(%d)\n", thr->tid, fd); - init(thr, pc, fd, &fdctx.filedesc); + init(thr, pc, fd, &fdctx.filesync); } void FdDup(ThreadState *thr, uptr pc, int oldfd, int newfd) { DPrintf("#%d: FdDup(%d, %d)\n", thr->tid, oldfd, newfd); // Ignore the case when user dups not yet connected socket. - FdDesc **opd = fdaddr(thr, pc, oldfd); - MemoryRead8Byte(thr, pc, (uptr)opd); + FdDesc *od = fddesc(thr, pc, oldfd); + MemoryRead8Byte(thr, pc, (uptr)od); FdClose(thr, pc, newfd); - init(thr, pc, newfd, ref(*opd)); + init(thr, pc, newfd, ref(od->sync)); } void FdPipeCreate(ThreadState *thr, uptr pc, int rfd, int wfd) { DPrintf("#%d: FdCreatePipe(%d, %d)\n", thr->tid, rfd, wfd); - FdDesc *d = allocdesc(); - init(thr, pc, rfd, d); - init(thr, pc, wfd, ref(d)); + FdSync *s = allocsync(); + init(thr, pc, rfd, s); + init(thr, pc, wfd, ref(s)); } void FdEventCreate(ThreadState *thr, uptr pc, int fd) { DPrintf("#%d: FdEventCreate(%d)\n", thr->tid, fd); - init(thr, pc, fd, allocdesc()); + init(thr, pc, fd, allocsync()); } void FdPollCreate(ThreadState *thr, uptr pc, int fd) { DPrintf("#%d: FdPollCreate(%d)\n", thr->tid, fd); - init(thr, pc, fd, allocdesc()); + init(thr, pc, fd, allocsync()); } void FdSocketCreate(ThreadState *thr, uptr pc, int fd) { DPrintf("#%d: FdSocketCreate(%d)\n", thr->tid, fd); // It can be a UDP socket. - init(thr, pc, fd, &fdctx.sockdesc); + init(thr, pc, fd, &fdctx.socksync); } void FdSocketAccept(ThreadState *thr, uptr pc, int fd, int newfd) { DPrintf("#%d: FdSocketAccept(%d, %d)\n", thr->tid, fd, newfd); // Synchronize connect->accept. Acquire(thr, pc, (uptr)&fdctx.connectsync); - init(thr, pc, newfd, &fdctx.sockdesc); + init(thr, pc, newfd, &fdctx.socksync); } void FdSocketConnecting(ThreadState *thr, uptr pc, int fd) { @@ -179,7 +206,7 @@ void FdSocketConnecting(ThreadState *thr, uptr pc, int fd) { void FdSocketConnect(ThreadState *thr, uptr pc, int fd) { DPrintf("#%d: FdSocketConnect(%d)\n", thr->tid, fd); - init(thr, pc, fd, &fdctx.sockdesc); + init(thr, pc, fd, &fdctx.socksync); } uptr File2addr(char *path) { |

