[llvm-commits] [compiler-rt] r169970 - in /compiler-rt/trunk/lib/tsan: lit_tests/fd_dup_norace.cc rtl/tsan_interceptors.cc rtl/tsan_mman.h rtl/tsan_stat.cc rtl/tsan_stat.h
Alexey Samsonov
samsonov at google.com
Wed Dec 12 04:08:09 PST 2012
On Wed, Dec 12, 2012 at 3:59 PM, Dmitry Vyukov <dvyukov at google.com> wrote:
> Author: dvyukov
> Date: Wed Dec 12 05:59:30 2012
> New Revision: 169970
>
> URL: http://llvm.org/viewvc/llvm-project?rev=169970&view=rev
> Log:
> tsan: more precise handling of IO synchronization
>
> Added:
> compiler-rt/trunk/lib/tsan/lit_tests/fd_dup_norace.cc
> Modified:
> compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
> compiler-rt/trunk/lib/tsan/rtl/tsan_mman.h
> compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc
> compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h
>
> Added: compiler-rt/trunk/lib/tsan/lit_tests/fd_dup_norace.cc
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/fd_dup_norace.cc?rev=169970&view=auto
>
> ==============================================================================
> --- compiler-rt/trunk/lib/tsan/lit_tests/fd_dup_norace.cc (added)
> +++ compiler-rt/trunk/lib/tsan/lit_tests/fd_dup_norace.cc Wed Dec 12
> 05:59:30 2012
> @@ -0,0 +1,33 @@
> +// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
> +#include <pthread.h>
> +#include <stdio.h>
> +#include <unistd.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <fcntl.h>
> +
> +int fds[2];
> +
> +void *Thread1(void *x) {
> + char buf;
> + read(fds[0], &buf, 1);
> + close(fds[0]);
> + return 0;
> +}
> +
> +void *Thread2(void *x) {
> + close(fds[1]);
> + return 0;
> +}
> +
> +int main() {
> + fds[0] = open("/dev/random", O_RDONLY);
> + fds[1] = dup2(fds[0], 100);
> + pthread_t t[2];
> + pthread_create(&t[0], NULL, Thread1, NULL);
> + pthread_create(&t[1], NULL, Thread2, NULL);
> + pthread_join(t[0], NULL);
> + pthread_join(t[1], NULL);
> +}
> +
> +// CHECK-NOT: WARNING: ThreadSanitizer: data race
>
> Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc?rev=169970&r1=169969&r2=169970&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc (original)
> +++ compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc Wed Dec 12
> 05:59:30 2012
> @@ -22,6 +22,7 @@
> #include "tsan_platform.h"
> #include "tsan_rtl.h"
> #include "tsan_mman.h"
> +#include "tsan_fd.h"
>
svn add?
>
> using namespace __tsan; // NOLINT
>
> @@ -54,6 +55,7 @@
> extern "C" void _exit(int status);
> extern "C" int __cxa_atexit(void (*func)(void *arg), void *arg, void
> *dso);
> extern "C" int *__errno_location();
> +extern "C" int fileno(void *stream);
> const int PTHREAD_MUTEX_RECURSIVE = 1;
> const int PTHREAD_MUTEX_RECURSIVE_NP = 1;
> const int kPthreadAttrSize = 56;
> @@ -128,10 +130,8 @@
> SignalContext *ctx = (SignalContext*)thr->signal_ctx;
> if (ctx == 0 && thr->is_alive) {
> ScopedInRtl in_rtl;
> - ctx = (SignalContext*)internal_alloc(
> - MBlockSignal, sizeof(*ctx));
> - MemoryResetRange(thr, 0, (uptr)ctx, sizeof(*ctx));
> - internal_memset(ctx, 0, sizeof(*ctx));
> + ctx = (SignalContext*)MmapOrDie(sizeof(*ctx), "SignalContext");
> + MemoryResetRange(thr, (uptr)&SigCtx, (uptr)ctx, sizeof(*ctx));
> thr->signal_ctx = ctx;
> }
> return ctx;
> @@ -310,216 +310,6 @@
> Die();
> }
>
> -enum FdType {
> - FdGlobal, // Something we don't know about, global sync.
> - FdNone, // Does not require any sync.
> - FdFile,
> - FdSock,
> - FdPipe,
> - FdEvent, // see eventfd()
> - FdPoll
> -};
> -
> -struct FdDesc {
> - FdType type;
> - u64 sync;
> -};
> -
> -struct FdContext {
> - static const int kMaxFds = 10 * 1024; // Everything else is synced
> globally.
> - FdDesc desc[kMaxFds];
> - // Addresses used for synchronization.
> - u64 fdglobal;
> - u64 fdfile;
> - u64 fdsock;
> - u64 fdpipe;
> - u64 fdpoll;
> - u64 fdevent;
> -};
> -
> -static FdContext fdctx;
> -
> -static void FdInit() {
> - fdctx.desc[0].type = FdNone;
> - fdctx.desc[1].type = FdNone;
> - fdctx.desc[2].type = FdNone;
> -}
> -
> -static void *FdAddr(int fd) {
> - if (fd >= FdContext::kMaxFds)
> - return &fdctx.fdglobal;
> - FdDesc *desc = &fdctx.desc[fd];
> - if (desc->type == FdNone)
> - return 0;
> - if (desc->type == FdGlobal)
> - return &fdctx.fdglobal;
> - if (desc->type == FdFile)
> - return &fdctx.fdfile;
> - if (desc->type == FdSock)
> - return &fdctx.fdsock;
> - if (desc->type == FdPipe)
> - return &fdctx.fdpipe;
> - if (desc->type == FdEvent)
> - return &fdctx.fdevent;
> - if (desc->type == FdPoll)
> - return &fdctx.fdpoll;
> - CHECK(0);
> - return 0;
> -}
> -
> -static void FdAcquire(ThreadState *thr, uptr pc, int fd) {
> - void *addr = FdAddr(fd);
> - DPrintf("#%d: FdAcquire(%d) -> %p\n", thr->tid, fd, addr);
> - if (addr)
> - Acquire(thr, pc, (uptr)addr);
> - if (fd < FdContext::kMaxFds)
> - MemoryRead8Byte(thr, pc, (uptr)&fdctx.desc[fd].sync);
> -}
> -
> -static void FdRelease(ThreadState *thr, uptr pc, int fd) {
> - void *addr = FdAddr(fd);
> - DPrintf("#%d: FdRelease(%d) -> %p\n", thr->tid, fd, addr);
> - if (addr)
> - Release(thr, pc, (uptr)addr);
> - if (fd < FdContext::kMaxFds)
> - MemoryRead8Byte(thr, pc, (uptr)&fdctx.desc[fd].sync);
> -}
> -
> -static void FdClose(ThreadState *thr, uptr pc, int fd) {
> - if (fd >= FdContext::kMaxFds)
> - return;
> - FdDesc *desc = &fdctx.desc[fd];
> - SyncVar *s = CTX()->synctab.GetAndRemove(thr, pc, (uptr)&desc->sync);
> - if (s)
> - DestroyAndFree(s);
> - // FIXME(dvyukov): change to FdNone once we handle all fd operations.
> - desc->type = FdGlobal;
> - // To catch races between fd usage and close.
> - MemoryWrite8Byte(thr, pc, (uptr)&desc->sync);
> - // 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)&desc->sync, sizeof(desc->sync));
> -}
> -
> -static void FdFileCreate(ThreadState *thr, uptr pc, int fd) {
> - if (fd >= FdContext::kMaxFds)
> - return;
> - FdDesc *desc = &fdctx.desc[fd];
> - desc->type = FdFile;
> - // To catch races between fd usage and open.
> - MemoryRangeImitateWrite(thr, pc, (uptr)&desc->sync, sizeof(desc->sync));
> -}
> -
> -static void FdDup(ThreadState *thr, uptr pc, int oldfd, int newfd) {
> - if (oldfd >= FdContext::kMaxFds || newfd >= FdContext::kMaxFds) {
> - if (oldfd < FdContext::kMaxFds) {
> - // FIXME(dvyukov): here we lose old sync object associated with the
> fd,
> - // this can lead to false positives.
> - FdDesc *odesc = &fdctx.desc[oldfd];
> - odesc->type = FdGlobal;
> - }
> - if (newfd < FdContext::kMaxFds) {
> - FdClose(thr, pc, newfd);
> - FdDesc *ndesc = &fdctx.desc[newfd];
> - ndesc->type = FdGlobal;
> - }
> - return;
> - }
> -
> - FdClose(thr, pc, newfd);
> - FdDesc *ndesc = &fdctx.desc[newfd];
> - ndesc->type = FdFile;
> - // To catch races between fd usage and open.
> - MemoryRangeImitateWrite(thr, pc, (uptr)&ndesc->sync,
> sizeof(ndesc->sync));
> -}
> -
> -static void FdPipeCreate(ThreadState *thr, uptr pc, int rfd, int wfd) {
> - if (rfd >= FdContext::kMaxFds || wfd >= FdContext::kMaxFds) {
> - if (rfd < FdContext::kMaxFds) {
> - FdDesc *rdesc = &fdctx.desc[rfd];
> - rdesc->type = FdGlobal;
> - }
> - if (wfd < FdContext::kMaxFds) {
> - FdDesc *wdesc = &fdctx.desc[wfd];
> - wdesc->type = FdGlobal;
> - }
> - return;
> - }
> -
> - FdDesc *rdesc = &fdctx.desc[rfd];
> - rdesc->type = FdPipe;
> - // To catch races between fd usage and open.
> - MemoryRangeImitateWrite(thr, pc, (uptr)&rdesc->sync,
> sizeof(rdesc->sync));
> -
> - FdDesc *wdesc = &fdctx.desc[wfd];
> - wdesc->type = FdPipe;
> - // To catch races between fd usage and open.
> - MemoryRangeImitateWrite(thr, pc, (uptr)&wdesc->sync,
> sizeof(rdesc->sync));
> -
> - DPrintf("#%d: FdCreatePipe(%d, %d)\n", thr->tid, rfd, wfd);
> -}
> -
> -static void FdEventCreate(ThreadState *thr, uptr pc, int fd) {
> - if (fd >= FdContext::kMaxFds)
> - return;
> - FdDesc *desc = &fdctx.desc[fd];
> - desc->type = FdEvent;
> - // To catch races between fd usage and open.
> - MemoryRangeImitateWrite(thr, pc, (uptr)&desc->sync, sizeof(desc->sync));
> -}
> -
> -static void FdPollCreate(ThreadState *thr, uptr pc, int fd) {
> - if (fd >= FdContext::kMaxFds)
> - return;
> - FdDesc *desc = &fdctx.desc[fd];
> - desc->type = FdPoll;
> - // To catch races between fd usage and open.
> - MemoryRangeImitateWrite(thr, pc, (uptr)&desc->sync, sizeof(desc->sync));
> -}
> -
> -static void FdSocketCreate(ThreadState *thr, uptr pc, int fd) {
> - if (fd >= FdContext::kMaxFds)
> - return;
> - FdDesc *desc = &fdctx.desc[fd];
> - // It can be UDP socket, let's assume they are not used for
> synchronization.
> - desc->type = FdNone;
> - // To catch races between fd usage and open.
> - MemoryRangeImitateWrite(thr, pc, (uptr)&desc->sync, sizeof(desc->sync));
> -}
> -
> -static void FdSocketAccept(ThreadState *thr, uptr pc, int fd, int newfd) {
> - if (fd < FdContext::kMaxFds) {
> - FdDesc *desc = &fdctx.desc[fd];
> - desc->type = FdNone;
> - MemoryRead8Byte(thr, pc, (uptr)&desc->sync);
> - }
> - if (newfd < FdContext::kMaxFds) {
> - FdDesc *desc = &fdctx.desc[newfd];
> - desc->type = FdSock;
> - MemoryWrite8Byte(thr, pc, (uptr)&desc->sync);
> - }
> -}
> -
> -static void FdSocketConnect(ThreadState *thr, uptr pc, int fd) {
> - if (fd >= FdContext::kMaxFds)
> - return;
> - FdDesc *desc = &fdctx.desc[fd];
> - desc->type = FdSock;
> - MemoryWrite8Byte(thr, pc, (uptr)&desc->sync);
> -}
> -
> -static uptr file2addr(char *path) {
> - (void)path;
> - static u64 addr;
> - return (uptr)&addr;
> -}
> -
> -static uptr dir2addr(char *path) {
> - (void)path;
> - static u64 addr;
> - return (uptr)&addr;
> -}
> -
> TSAN_INTERCEPTOR(void*, malloc, uptr size) {
> void *p = 0;
> {
> @@ -850,7 +640,7 @@
> SignalContext *sctx = thr->signal_ctx;
> if (sctx) {
> thr->signal_ctx = 0;
> - internal_free(sctx);
> + UnmapOrDie(sctx, sizeof(*sctx));
> }
> }
> }
> @@ -1124,11 +914,13 @@
> return res;
> }
>
> +/*
> TSAN_INTERCEPTOR(int, pthread_cond_init, void *c, void *a) {
> SCOPED_TSAN_INTERCEPTOR(pthread_cond_init, c, a);
> int res = REAL(pthread_cond_init)(c, a);
> return res;
> }
> +*/
>
> TSAN_INTERCEPTOR(int, pthread_cond_destroy, void *c) {
> SCOPED_TSAN_INTERCEPTOR(pthread_cond_destroy, c);
> @@ -1278,6 +1070,14 @@
> return fd;
> }
>
> +TSAN_INTERCEPTOR(int, open64, const char *name, int flags, int mode) {
> + SCOPED_TSAN_INTERCEPTOR(open64, name, flags, mode);
> + int fd = REAL(open64)(name, flags, mode);
> + if (fd >= 0)
> + FdFileCreate(thr, pc, fd);
> + return fd;
> +}
> +
> TSAN_INTERCEPTOR(int, creat, const char *name, int mode) {
> SCOPED_TSAN_INTERCEPTOR(creat, name, mode);
> int fd = REAL(creat)(name, mode);
> @@ -1286,6 +1086,14 @@
> return fd;
> }
>
> +TSAN_INTERCEPTOR(int, creat64, const char *name, int mode) {
> + SCOPED_TSAN_INTERCEPTOR(creat64, name, mode);
> + int fd = REAL(creat64)(name, mode);
> + if (fd >= 0)
> + FdFileCreate(thr, pc, fd);
> + return fd;
> +}
> +
> TSAN_INTERCEPTOR(int, dup, int oldfd) {
> SCOPED_TSAN_INTERCEPTOR(dup, oldfd);
> int newfd = REAL(dup)(oldfd);
> @@ -1368,10 +1176,18 @@
>
> TSAN_INTERCEPTOR(int, close, int fd) {
> SCOPED_TSAN_INTERCEPTOR(close, fd);
> - FdClose(thr, pc, fd);
> + if (fd >= 0)
> + FdClose(thr, pc, fd);
> return REAL(close)(fd);
> }
>
> +TSAN_INTERCEPTOR(int, __close, int fd) {
> + SCOPED_TSAN_INTERCEPTOR(__close, fd);
> + if (fd >= 0)
> + FdClose(thr, pc, fd);
> + return REAL(__close)(fd);
> +}
> +
> TSAN_INTERCEPTOR(int, pipe, int *pipefd) {
> SCOPED_TSAN_INTERCEPTOR(pipe, pipefd);
> int res = REAL(pipe)(pipefd);
> @@ -1502,7 +1318,7 @@
>
> TSAN_INTERCEPTOR(int, unlink, char *path) {
> SCOPED_TSAN_INTERCEPTOR(unlink, path);
> - Release(thr, pc, file2addr(path));
> + Release(thr, pc, File2addr(path));
> int res = REAL(unlink)(path);
> return res;
> }
> @@ -1510,7 +1326,40 @@
> TSAN_INTERCEPTOR(void*, fopen, char *path, char *mode) {
> SCOPED_TSAN_INTERCEPTOR(fopen, path, mode);
> void *res = REAL(fopen)(path, mode);
> - Acquire(thr, pc, file2addr(path));
> + Acquire(thr, pc, File2addr(path));
> + if (res) {
> + int fd = fileno(res);
> + if (fd >= 0)
> + FdFileCreate(thr, pc, fd);
> + }
> + return res;
> +}
> +
> +TSAN_INTERCEPTOR(void*, freopen, char *path, char *mode, void *stream) {
> + SCOPED_TSAN_INTERCEPTOR(freopen, path, mode, stream);
> + if (stream) {
> + int fd = fileno(stream);
> + if (fd >= 0)
> + FdClose(thr, pc, fd);
> + }
> + void *res = REAL(freopen)(path, mode, stream);
> + Acquire(thr, pc, File2addr(path));
> + if (res) {
> + int fd = fileno(res);
> + if (fd >= 0)
> + FdFileCreate(thr, pc, fd);
> + }
> + return res;
> +}
> +
> +TSAN_INTERCEPTOR(int, fclose, void *stream) {
> + SCOPED_TSAN_INTERCEPTOR(fclose, stream);
> + if (stream) {
> + int fd = fileno(stream);
> + if (fd >= 0)
> + FdClose(thr, pc, fd);
> + }
> + int res = REAL(fclose)(stream);
> return res;
> }
>
> @@ -1534,7 +1383,7 @@
>
> TSAN_INTERCEPTOR(int, rmdir, char *path) {
> SCOPED_TSAN_INTERCEPTOR(rmdir, path);
> - Release(thr, pc, dir2addr(path));
> + Release(thr, pc, Dir2addr(path));
> int res = REAL(rmdir)(path);
> return res;
> }
> @@ -1542,7 +1391,8 @@
> TSAN_INTERCEPTOR(void*, opendir, char *path) {
> SCOPED_TSAN_INTERCEPTOR(opendir, path);
> void *res = REAL(opendir)(path);
> - Acquire(thr, pc, dir2addr(path));
> + if (res != 0)
> + Acquire(thr, pc, Dir2addr(path));
> return res;
> }
>
> @@ -1853,7 +1703,7 @@
> TSAN_INTERCEPT(pthread_rwlock_timedwrlock);
> TSAN_INTERCEPT(pthread_rwlock_unlock);
>
> - TSAN_INTERCEPT(pthread_cond_init);
> + // TSAN_INTERCEPT(pthread_cond_init);
> TSAN_INTERCEPT(pthread_cond_destroy);
> TSAN_INTERCEPT(pthread_cond_signal);
> TSAN_INTERCEPT(pthread_cond_broadcast);
> @@ -1875,7 +1725,9 @@
> TSAN_INTERCEPT(sem_getvalue);
>
> TSAN_INTERCEPT(open);
> + TSAN_INTERCEPT(open64);
> TSAN_INTERCEPT(creat);
> + TSAN_INTERCEPT(creat64);
> TSAN_INTERCEPT(dup);
> TSAN_INTERCEPT(dup2);
> TSAN_INTERCEPT(dup3);
> @@ -1907,6 +1759,8 @@
>
> TSAN_INTERCEPT(unlink);
> TSAN_INTERCEPT(fopen);
> + TSAN_INTERCEPT(freopen);
> + TSAN_INTERCEPT(fclose);
> TSAN_INTERCEPT(fread);
> TSAN_INTERCEPT(fwrite);
> TSAN_INTERCEPT(puts);
>
> Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_mman.h
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_mman.h?rev=169970&r1=169969&r2=169970&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/tsan/rtl/tsan_mman.h (original)
> +++ compiler-rt/trunk/lib/tsan/rtl/tsan_mman.h Wed Dec 12 05:59:30 2012
> @@ -59,6 +59,7 @@
> MBlockSuppression,
> MBlockExpectRace,
> MBlockSignal,
> + MBlockFD,
>
> // This must be the last.
> MBlockTypeCount
>
> Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc?rev=169970&r1=169969&r2=169970&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc (original)
> +++ compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc Wed Dec 12 05:59:30 2012
> @@ -182,7 +182,9 @@
> name[StatInt_sem_post] = " sem_post
> ";
> name[StatInt_sem_getvalue] = " sem_getvalue
> ";
> name[StatInt_open] = " open
> ";
> + name[StatInt_open64] = " open64
> ";
> name[StatInt_creat] = " creat
> ";
> + name[StatInt_creat64] = " creat64
> ";
> name[StatInt_dup] = " dup
> ";
> name[StatInt_dup2] = " dup2
> ";
> name[StatInt_dup3] = " dup3
> ";
> @@ -194,6 +196,7 @@
> name[StatInt_epoll_create] = " epoll_create
> ";
> name[StatInt_epoll_create1] = " epoll_create1
> ";
> name[StatInt_close] = " close
> ";
> + name[StatInt___close] = " __close
> ";
> name[StatInt_pipe] = " pipe
> ";
> name[StatInt_pipe2] = " pipe2
> ";
> name[StatInt_read] = " read
> ";
> @@ -212,6 +215,8 @@
> name[StatInt_recvmsg] = " recvmsg
> ";
> name[StatInt_unlink] = " unlink
> ";
> name[StatInt_fopen] = " fopen
> ";
> + name[StatInt_freopen] = " freopen
> ";
> + name[StatInt_fclose] = " fclose
> ";
> name[StatInt_fread] = " fread
> ";
> name[StatInt_fwrite] = " fwrite
> ";
> name[StatInt_puts] = " puts
> ";
>
> Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h?rev=169970&r1=169969&r2=169970&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h (original)
> +++ compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h Wed Dec 12 05:59:30 2012
> @@ -177,7 +177,9 @@
> StatInt_sem_post,
> StatInt_sem_getvalue,
> StatInt_open,
> + StatInt_open64,
> StatInt_creat,
> + StatInt_creat64,
> StatInt_dup,
> StatInt_dup2,
> StatInt_dup3,
> @@ -189,6 +191,7 @@
> StatInt_epoll_create,
> StatInt_epoll_create1,
> StatInt_close,
> + StatInt___close,
> StatInt_pipe,
> StatInt_pipe2,
> StatInt_read,
> @@ -207,6 +210,8 @@
> StatInt_recvmsg,
> StatInt_unlink,
> StatInt_fopen,
> + StatInt_freopen,
> + StatInt_fclose,
> StatInt_fread,
> StatInt_fwrite,
> StatInt_puts,
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
--
Alexey Samsonov, MSK
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20121212/bc84d055/attachment.html>
More information about the llvm-commits
mailing list