summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_fd.cc15
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_fd.h1
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_interceptors.cc15
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_stat.cc1
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_stat.h1
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_sync.cc3
6 files changed, 36 insertions, 0 deletions
diff --git a/compiler-rt/lib/tsan/rtl/tsan_fd.cc b/compiler-rt/lib/tsan/rtl/tsan_fd.cc
index a27bbccba6f..ecd725d15c0 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_fd.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_fd.cc
@@ -114,6 +114,21 @@ void FdInit() {
atomic_store(&fdctx.socksync.rc, (u64)-1, memory_order_relaxed);
}
+void FdOnFork(ThreadState *thr, uptr pc) {
+ // On fork() we need to reset all fd's, because the child is going
+ // close all them, and that will cause races between previous read/write
+ // and the close.
+ for (int l1 = 0; l1 < kTableSizeL1; l1++) {
+ FdDesc *tab = (FdDesc*)atomic_load(&fdctx.tab[l1], memory_order_relaxed);
+ if (tab == 0)
+ break;
+ for (int l2 = 0; l2 < kTableSizeL2; l2++) {
+ FdDesc *d = &tab[l2];
+ MemoryResetRange(thr, pc, (uptr)d, 8);
+ }
+ }
+}
+
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);
diff --git a/compiler-rt/lib/tsan/rtl/tsan_fd.h b/compiler-rt/lib/tsan/rtl/tsan_fd.h
index 8f8bafb4428..3bf2c747b69 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_fd.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_fd.h
@@ -54,6 +54,7 @@ void FdSocketAccept(ThreadState *thr, uptr pc, int fd, int newfd);
void FdSocketConnecting(ThreadState *thr, uptr pc, int fd);
void FdSocketConnect(ThreadState *thr, uptr pc, int fd);
bool FdLocation(uptr addr, int *fd, int *tid, u32 *stack);
+void FdOnFork(ThreadState *thr, uptr pc);
uptr File2addr(char *path);
uptr Dir2addr(char *path);
diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc
index cacad2c82ed..da7356cad6f 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc
@@ -1617,6 +1617,19 @@ TSAN_INTERCEPTOR(int, munlockall, void) {
return 0;
}
+TSAN_INTERCEPTOR(int, fork) {
+ SCOPED_TSAN_INTERCEPTOR(fork);
+ // It's intercepted merely to process pending signals.
+ int pid = REAL(fork)();
+ if (pid == 0) {
+ // child
+ FdOnFork(thr, pc);
+ } else if (pid > 0) {
+ // parent
+ }
+ return pid;
+}
+
namespace __tsan {
void ProcessPendingSignals(ThreadState *thr) {
@@ -1826,6 +1839,8 @@ void InitializeInterceptors() {
TSAN_INTERCEPT(mlockall);
TSAN_INTERCEPT(munlockall);
+ TSAN_INTERCEPT(fork);
+
// Need to setup it, because interceptors check that the function is resolved.
// But atexit is emitted directly into the module, so can't be resolved.
REAL(atexit) = (int(*)(void(*)()))unreachable;
diff --git a/compiler-rt/lib/tsan/rtl/tsan_stat.cc b/compiler-rt/lib/tsan/rtl/tsan_stat.cc
index 3fa8a03ee19..4bfc9625a0f 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_stat.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_stat.cc
@@ -234,6 +234,7 @@ void StatOutput(u64 *stat) {
name[StatInt_usleep] = " usleep ";
name[StatInt_nanosleep] = " nanosleep ";
name[StatInt_gettimeofday] = " gettimeofday ";
+ name[StatInt_fork] = " fork ";
name[StatAnnotation] = "Dynamic annotations ";
name[StatAnnotateHappensBefore] = " HappensBefore ";
diff --git a/compiler-rt/lib/tsan/rtl/tsan_stat.h b/compiler-rt/lib/tsan/rtl/tsan_stat.h
index 64b12a6628f..9c3c95aa221 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_stat.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_stat.h
@@ -233,6 +233,7 @@ enum StatType {
StatInt_usleep,
StatInt_nanosleep,
StatInt_gettimeofday,
+ StatInt_fork,
// Dynamic annotations.
StatAnnotation,
diff --git a/compiler-rt/lib/tsan/rtl/tsan_sync.cc b/compiler-rt/lib/tsan/rtl/tsan_sync.cc
index 38ecc6e8c5f..8951325462e 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_sync.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_sync.cc
@@ -60,6 +60,9 @@ SyncVar* SyncTab::GetIfExistsAndLock(uptr addr, bool write_lock) {
SyncVar* SyncTab::GetAndLock(ThreadState *thr, uptr pc,
uptr addr, bool write_lock, bool create) {
#ifndef TSAN_GO
+ // Here we ask only PrimaryAllocator, because
+ // SecondaryAllocator::PointerIsMine() is slow and we have fallback on
+ // the hashmap anyway.
if (PrimaryAllocator::PointerIsMine((void*)addr)) {
MBlock *b = user_mblock(thr, (void*)addr);
Lock l(&b->mtx);
OpenPOWER on IntegriCloud