summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2012-12-18 12:20:55 +0000
committerDmitry Vyukov <dvyukov@google.com>2012-12-18 12:20:55 +0000
commite3178e8fab67e77165978006928228f9be2ce30d (patch)
treef98c01295712a7ea1dd5371cc6e1545dedd22e2c /lib
parent0b1137574d93882f1e1ba4f463139345cec7afce (diff)
tsan: add io_sync flag that controls amount of IO synchronization
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@170427 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/tsan/rtl/tsan_fd.cc13
-rw-r--r--lib/tsan/rtl/tsan_flags.cc8
-rw-r--r--lib/tsan/rtl/tsan_flags.h5
3 files changed, 24 insertions, 2 deletions
diff --git a/lib/tsan/rtl/tsan_fd.cc b/lib/tsan/rtl/tsan_fd.cc
index 4431097e1..7428596b1 100644
--- a/lib/tsan/rtl/tsan_fd.cc
+++ b/lib/tsan/rtl/tsan_fd.cc
@@ -92,7 +92,15 @@ static void init(ThreadState *thr, uptr pc, int fd, FdSync *s) {
// See e.g. libc __res_iclose().
if (d->sync)
unref(thr, pc, d->sync);
- d->sync = s;
+ if (flags()->io_sync == 0) {
+ unref(thr, pc, s);
+ d->sync = 0;
+ } else if (flags()->io_sync == 1) {
+ d->sync = s;
+ } else if (flags()->io_sync == 2) {
+ unref(thr, pc, s);
+ d->sync = &fdctx.globsync;
+ }
d->creation_tid = thr->tid;
d->creation_stack = CurrentStackId(thr, pc);
// To catch races between fd usage and open.
@@ -171,8 +179,9 @@ void FdDup(ThreadState *thr, uptr pc, int oldfd, int newfd) {
void FdPipeCreate(ThreadState *thr, uptr pc, int rfd, int wfd) {
DPrintf("#%d: FdCreatePipe(%d, %d)\n", thr->tid, rfd, wfd);
FdSync *s = allocsync();
- init(thr, pc, rfd, s);
+ init(thr, pc, rfd, ref(s));
init(thr, pc, wfd, ref(s));
+ unref(thr, pc, s);
}
void FdEventCreate(ThreadState *thr, uptr pc, int fd) {
diff --git a/lib/tsan/rtl/tsan_flags.cc b/lib/tsan/rtl/tsan_flags.cc
index 25c370f03..88c4bb6a2 100644
--- a/lib/tsan/rtl/tsan_flags.cc
+++ b/lib/tsan/rtl/tsan_flags.cc
@@ -58,6 +58,7 @@ void InitializeFlags(Flags *f, const char *env) {
f->running_on_valgrind = false;
f->external_symbolizer_path = "";
f->history_size = kGoMode ? 1 : 2; // There are a lot of goroutines in Go.
+ f->io_sync = 1;
// Let a frontend override.
OverrideFlags(f);
@@ -83,6 +84,7 @@ void InitializeFlags(Flags *f, const char *env) {
ParseFlag(env, &f->stop_on_start, "stop_on_start");
ParseFlag(env, &f->external_symbolizer_path, "external_symbolizer_path");
ParseFlag(env, &f->history_size, "history_size");
+ ParseFlag(env, &f->io_sync, "io_sync");
if (!f->report_bugs) {
f->report_thread_leaks = false;
@@ -95,6 +97,12 @@ void InitializeFlags(Flags *f, const char *env) {
" (must be [0..7])\n");
Die();
}
+
+ if (f->io_sync < 0 || f->io_sync > 2) {
+ Printf("ThreadSanitizer: incorrect value for io_sync"
+ " (must be [0..2])\n");
+ Die();
+ }
}
} // namespace __tsan
diff --git a/lib/tsan/rtl/tsan_flags.h b/lib/tsan/rtl/tsan_flags.h
index 2fdcc2f1b..6547911ec 100644
--- a/lib/tsan/rtl/tsan_flags.h
+++ b/lib/tsan/rtl/tsan_flags.h
@@ -77,6 +77,11 @@ struct Flags {
// the amount of memory accesses, up to history_size=7 that amounts to
// 4M memory accesses. The default value is 2 (128K memory accesses).
int history_size;
+ // Controls level of synchronization implied by IO operations.
+ // 0 - no synchronization
+ // 1 - reasonable level of synchronization (write->read)
+ // 2 - global synchronization of all IO operations
+ int io_sync;
};
Flags *flags();