tsan_interceptors.cc revision f110e356170fbe990b99c0939d77eeaa89b25497
14f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov//===-- tsan_interceptors.cc ----------------------------------------------===//
27ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//
37ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//                     The LLVM Compiler Infrastructure
47ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//
57ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// This file is distributed under the University of Illinois Open Source
67ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// License. See LICENSE.TXT for details.
77ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//
87ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//===----------------------------------------------------------------------===//
97ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//
107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// This file is a part of ThreadSanitizer (TSan), a race detector.
117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//
128530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany// FIXME: move as many interceptors as possible into
138530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany// sanitizer_common/sanitizer_common_interceptors.h
147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//===----------------------------------------------------------------------===//
157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
16fce5bd4cc29fddb5e8f0cb9c12df7c10187a991dDmitry Vyukov#include "sanitizer_common/sanitizer_atomic.h"
17230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov#include "sanitizer_common/sanitizer_libc.h"
1847b1634df012507799eb39aa17d4022d748ba67bAlexey Samsonov#include "sanitizer_common/sanitizer_placement_new.h"
197eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov#include "sanitizer_common/sanitizer_stacktrace.h"
2036decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov#include "interception/interception.h"
217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_interface.h"
227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_platform.h"
234f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov#include "tsan_rtl.h"
247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_mman.h"
25c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov#include "tsan_fd.h"
267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyusing namespace __tsan;  // NOLINT
287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
29e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukovconst int kSigCount = 128;
30e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov
31e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukovstruct my_siginfo_t {
32e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  int opaque[128];
33e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov};
34e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov
357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystruct sigset_t {
36e294d09d45aa97d1d2c8ee237ee2ac225442d330Dmitry Vyukov  u64 val[1024 / 8 / sizeof(u64)];
377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany};
387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystruct ucontext_t {
40a5562db12c5331433407ac21602086f34561c25cDmitry Vyukov  uptr opaque[117];
417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany};
427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" int pthread_attr_init(void *attr);
447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" int pthread_attr_destroy(void *attr);
457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" int pthread_attr_getdetachstate(void *attr, int *v);
467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" int pthread_attr_setstacksize(void *attr, uptr stacksize);
477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" int pthread_attr_getstacksize(void *attr, uptr *stacksize);
487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" int pthread_key_create(unsigned *key, void (*destructor)(void* v));
497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" int pthread_setspecific(unsigned key, const void *v);
507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" int pthread_mutexattr_gettype(void *a, int *type);
517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" int pthread_yield();
527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset);
537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" int sigfillset(sigset_t *set);
547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void *pthread_self();
557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void _exit(int status);
567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" int *__errno_location();
57f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukovextern "C" int fileno_unlocked(void *stream);
5831c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukovextern "C" void *__libc_malloc(uptr size);
5931c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukovextern "C" void *__libc_calloc(uptr size, uptr n);
6031c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukovextern "C" void *__libc_realloc(void *ptr, uptr size);
6131c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukovextern "C" void __libc_free(void *ptr);
627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst int PTHREAD_MUTEX_RECURSIVE = 1;
637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst int PTHREAD_MUTEX_RECURSIVE_NP = 1;
647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst int kPthreadAttrSize = 56;
657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst int EINVAL = 22;
667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst int EBUSY = 16;
677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst int EPOLL_CTL_ADD = 1;
68d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukovconst int SIGILL = 4;
69d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukovconst int SIGABRT = 6;
70d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukovconst int SIGFPE = 8;
71d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukovconst int SIGSEGV = 11;
72d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukovconst int SIGPIPE = 13;
73d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukovconst int SIGBUS = 7;
747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid *const MAP_FAILED = (void*)-1;
757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst int PTHREAD_BARRIER_SERIAL_THREAD = -1;
767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst int MAP_FIXED = 0x10;
777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanytypedef long long_t;  // NOLINT
787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
790ce948e0887e2c23c6510c32a639da9730bbce25Alexander Potapenko// From /usr/include/unistd.h
800ce948e0887e2c23c6510c32a639da9730bbce25Alexander Potapenko# define F_ULOCK 0      /* Unlock a previously locked region.  */
810ce948e0887e2c23c6510c32a639da9730bbce25Alexander Potapenko# define F_LOCK  1      /* Lock a region for exclusive use.  */
820ce948e0887e2c23c6510c32a639da9730bbce25Alexander Potapenko# define F_TLOCK 2      /* Test and lock a region for exclusive use.  */
830ce948e0887e2c23c6510c32a639da9730bbce25Alexander Potapenko# define F_TEST  3      /* Test a region for other processes locks.  */
840ce948e0887e2c23c6510c32a639da9730bbce25Alexander Potapenko
857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanytypedef void (*sighandler_t)(int sig);
867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
877a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov#define errno (*__errno_location())
887a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov
897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystruct sigaction_t {
907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  union {
917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    sighandler_t sa_handler;
927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    void (*sa_sigaction)(int sig, my_siginfo_t *siginfo, void *uctx);
937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  };
947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  sigset_t sa_mask;
957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int sa_flags;
967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  void (*sa_restorer)();
977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany};
987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst sighandler_t SIG_DFL = (sighandler_t)0;
1007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst sighandler_t SIG_IGN = (sighandler_t)1;
101d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukovconst sighandler_t SIG_ERR = (sighandler_t)-1;
1027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst int SA_SIGINFO = 4;
1037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst int SIG_SETMASK = 2;
1047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1057eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonovnamespace std {
1067eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonovstruct nothrow_t {};
1077eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov}  // namespace std
1087eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov
1097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic sigaction_t sigactions[kSigCount];
1107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
111e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukovnamespace __tsan {
112e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukovstruct SignalDesc {
113e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  bool armed;
114e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  bool sigaction;
115e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  my_siginfo_t siginfo;
116e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  ucontext_t ctx;
117e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov};
118e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov
119e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukovstruct SignalContext {
120ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  int in_blocking_func;
121e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  int int_signal_send;
122e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  int pending_signal_count;
123e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  SignalDesc pending_signals[kSigCount];
124e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov};
125ba5e99668e3030cc5bab357a04271a1bdbac209cAlexey Samsonov}  // namespace __tsan
126e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov
127e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukovstatic SignalContext *SigCtx(ThreadState *thr) {
128e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  SignalContext *ctx = (SignalContext*)thr->signal_ctx;
1291fc03d50a87302689482efa24b045a393097b6c3Dmitry Vyukov  if (ctx == 0 && thr->is_alive) {
130e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov    ScopedInRtl in_rtl;
131c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov    ctx = (SignalContext*)MmapOrDie(sizeof(*ctx), "SignalContext");
132c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov    MemoryResetRange(thr, (uptr)&SigCtx, (uptr)ctx, sizeof(*ctx));
133e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov    thr->signal_ctx = ctx;
134e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  }
135e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  return ctx;
136e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov}
137e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov
1387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic unsigned g_thread_finalize_key;
1397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
14036decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukovclass ScopedInterceptor {
14136decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov public:
14236decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov  ScopedInterceptor(ThreadState *thr, const char *fname, uptr pc);
14336decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov  ~ScopedInterceptor();
14436decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov private:
14536decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov  ThreadState *const thr_;
14636decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov  const int in_rtl_;
14736decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov};
14836decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov
1494f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey SamsonovScopedInterceptor::ScopedInterceptor(ThreadState *thr, const char *fname,
1504f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov                                     uptr pc)
1514f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov    : thr_(thr)
1524f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov    , in_rtl_(thr->in_rtl) {
1534f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov  if (thr_->in_rtl == 0) {
1544f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov    Initialize(thr);
1554f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov    FuncEntry(thr, pc);
1564f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov    thr_->in_rtl++;
1574f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov    DPrintf("#%d: intercept %s()\n", thr_->tid, fname);
1584f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov  } else {
1594f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov    thr_->in_rtl++;
1607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
16105906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov}
16205906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov
1634f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey SamsonovScopedInterceptor::~ScopedInterceptor() {
1644f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov  thr_->in_rtl--;
1654f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov  if (thr_->in_rtl == 0) {
1664f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov    FuncExit(thr_);
167ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov    ProcessPendingSignals(thr_);
1684f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov  }
1694f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov  CHECK_EQ(in_rtl_, thr_->in_rtl);
17005906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov}
17105906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov
17236decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov#define SCOPED_INTERCEPTOR_RAW(func, ...) \
17336decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov    ThreadState *thr = cur_thread(); \
17436decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov    StatInc(thr, StatInterceptor); \
17536decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov    StatInc(thr, StatInt_##func); \
17636decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov    const uptr caller_pc = GET_CALLER_PC(); \
17736decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov    ScopedInterceptor si(thr, #func, caller_pc); \
178d2f08ffcb97726452f4ba11c199a1e06dc2a7e54Alexey Samsonov    const uptr pc = __sanitizer::StackTrace::GetPreviousInstructionPc( \
179d2f08ffcb97726452f4ba11c199a1e06dc2a7e54Alexey Samsonov        __sanitizer::StackTrace::GetCurrentPc()); \
18036decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov    (void)pc; \
18136decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov/**/
18236decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov
18336decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov#define SCOPED_TSAN_INTERCEPTOR(func, ...) \
18436decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov    SCOPED_INTERCEPTOR_RAW(func, __VA_ARGS__); \
18536decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov    if (REAL(func) == 0) { \
18636decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov      Printf("FATAL: ThreadSanitizer: failed to intercept %s\n", #func); \
18736decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov      Die(); \
18836decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov    } \
18936decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov    if (thr->in_rtl > 1) \
19036decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov      return REAL(func)(__VA_ARGS__); \
19136decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov/**/
19236decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov
19336decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov#define TSAN_INTERCEPTOR(ret, func, ...) INTERCEPTOR(ret, func, __VA_ARGS__)
19436decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov#define TSAN_INTERCEPT(func) INTERCEPT_FUNCTION(func)
19536decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov
196ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov#define BLOCK_REAL(name) (BlockingCall(thr), REAL(name))
197ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov
198ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukovstruct BlockingCall {
199b717f4d415cafbb8526bb33f737b9c07409a73bbAlexey Samsonov  explicit BlockingCall(ThreadState *thr)
200ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov      : ctx(SigCtx(thr)) {
201ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov    ctx->in_blocking_func++;
202ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  }
203ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov
204ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  ~BlockingCall() {
205ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov    ctx->in_blocking_func--;
206ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  }
207ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov
208ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  SignalContext *ctx;
209ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov};
210ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov
211848531192777acecf79747dc7c1ffeedf5c1da9fDmitry VyukovTSAN_INTERCEPTOR(unsigned, sleep, unsigned sec) {
212848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(sleep, sec);
213ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  unsigned res = BLOCK_REAL(sleep)(sec);
214848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  AfterSleep(thr, pc);
215848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  return res;
216848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov}
217848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov
218848531192777acecf79747dc7c1ffeedf5c1da9fDmitry VyukovTSAN_INTERCEPTOR(int, usleep, long_t usec) {
219848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(usleep, usec);
220ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  int res = BLOCK_REAL(usleep)(usec);
221848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  AfterSleep(thr, pc);
222848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  return res;
223848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov}
224848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov
225848531192777acecf79747dc7c1ffeedf5c1da9fDmitry VyukovTSAN_INTERCEPTOR(int, nanosleep, void *req, void *rem) {
226848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(nanosleep, req, rem);
227ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  int res = BLOCK_REAL(nanosleep)(req, rem);
228848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  AfterSleep(thr, pc);
229848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  return res;
230848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov}
231848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov
2327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyclass AtExitContext {
2337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany public:
2347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  AtExitContext()
2357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    : mtx_(MutexTypeAtExit, StatMtxAtExit)
2367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    , pos_() {
2377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
2387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  typedef void(*atexit_t)();
2407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
24131c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  int atexit(ThreadState *thr, uptr pc, bool is_on_exit,
24231c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov             atexit_t f, void *arg) {
2437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    Lock l(&mtx_);
2447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    if (pos_ == kMaxAtExit)
2457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      return 1;
2467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    Release(thr, pc, (uptr)this);
2477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    stack_[pos_] = f;
24831c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov    args_[pos_] = arg;
24931c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov    is_on_exits_[pos_] = is_on_exit;
2507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    pos_++;
2517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return 0;
2527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
2537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  void exit(ThreadState *thr, uptr pc) {
2557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    CHECK_EQ(thr->in_rtl, 0);
2567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    for (;;) {
2577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      atexit_t f = 0;
25831c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov      void *arg = 0;
25931c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov      bool is_on_exit = false;
2607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      {
2617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany        Lock l(&mtx_);
2627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany        if (pos_) {
2637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany          pos_--;
2647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany          f = stack_[pos_];
26531c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov          arg = args_[pos_];
26631c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov          is_on_exit = is_on_exits_[pos_];
2677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany          ScopedInRtl in_rtl;
2687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany          Acquire(thr, pc, (uptr)this);
2697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany        }
2707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      }
2717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      if (f == 0)
2727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany        break;
2737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      DPrintf("#%d: executing atexit func %p\n", thr->tid, f);
2747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      CHECK_EQ(thr->in_rtl, 0);
27531c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov      if (is_on_exit)
27631c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov        ((void(*)(int status, void *arg))f)(0, arg);
27731c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov      else
27831c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov        ((void(*)(void *arg, void *dso))f)(arg, 0);
2797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    }
2807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
2817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany private:
2837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  static const int kMaxAtExit = 128;
2847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Mutex mtx_;
2857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  atexit_t stack_[kMaxAtExit];
28631c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  void *args_[kMaxAtExit];
28731c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  bool is_on_exits_[kMaxAtExit];
2887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int pos_;
2897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany};
2907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic AtExitContext *atexit_ctx;
2927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void finalize(void *arg) {
2947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ThreadState * thr = cur_thread();
2957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  uptr pc = 0;
2967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  atexit_ctx->exit(thr, pc);
2977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int status = Finalize(cur_thread());
298b7b6b1cd9df0c954b1f890fcebf373db984923b3Dmitry Vyukov  if (status)
299b7b6b1cd9df0c954b1f890fcebf373db984923b3Dmitry Vyukov    _exit(status);
3007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3027ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, atexit, void (*f)()) {
30331c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  if (cur_thread()->in_symbolizer)
30431c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov    return 0;
3057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(atexit, f);
30631c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  return atexit_ctx->atexit(thr, pc, false, (void(*)())f, 0);
30731c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov}
30831c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov
30931c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry VyukovTSAN_INTERCEPTOR(int, on_exit, void(*f)(int, void*), void *arg) {
31031c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  if (cur_thread()->in_symbolizer)
31131c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov    return 0;
31231c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(on_exit, f, arg);
31331c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  return atexit_ctx->atexit(thr, pc, true, (void(*)())f, arg);
31431c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov}
31531c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov
31631c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry VyukovTSAN_INTERCEPTOR(int, __cxa_atexit, void (*f)(void *a), void *arg, void *dso) {
31731c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  if (cur_thread()->in_symbolizer)
31831c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov    return 0;
31931c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(__cxa_atexit, f, arg, dso);
32031c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  if (dso)
32131c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov    return REAL(__cxa_atexit)(f, arg, dso);
32231c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  return atexit_ctx->atexit(thr, pc, false, (void(*)())f, arg);
3237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
325f037f565b2e02878ceb6e7b49647e814e2990ef5Dmitry VyukovTSAN_INTERCEPTOR(void, longjmp, void *env, int val) {
326f037f565b2e02878ceb6e7b49647e814e2990ef5Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(longjmp, env, val);
327b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov  Printf("ThreadSanitizer: longjmp() is not supported\n");
328f037f565b2e02878ceb6e7b49647e814e2990ef5Dmitry Vyukov  Die();
329f037f565b2e02878ceb6e7b49647e814e2990ef5Dmitry Vyukov}
330f037f565b2e02878ceb6e7b49647e814e2990ef5Dmitry Vyukov
331f037f565b2e02878ceb6e7b49647e814e2990ef5Dmitry VyukovTSAN_INTERCEPTOR(void, siglongjmp, void *env, int val) {
332f037f565b2e02878ceb6e7b49647e814e2990ef5Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(siglongjmp, env, val);
333b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov  Printf("ThreadSanitizer: siglongjmp() is not supported\n");
334f037f565b2e02878ceb6e7b49647e814e2990ef5Dmitry Vyukov  Die();
335f037f565b2e02878ceb6e7b49647e814e2990ef5Dmitry Vyukov}
336f037f565b2e02878ceb6e7b49647e814e2990ef5Dmitry Vyukov
3377ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, malloc, uptr size) {
33831c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  if (cur_thread()->in_symbolizer)
33931c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov    return __libc_malloc(size);
34005906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov  void *p = 0;
34105906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov  {
34205906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov    SCOPED_INTERCEPTOR_RAW(malloc, size);
34305906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov    p = user_alloc(thr, pc, size);
34405906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov  }
34505906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov  invoke_malloc_hook(p, size);
34605906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov  return p;
3477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
34907ba8ef44deb54baa9307298fbffe25ddb30c362Dmitry VyukovTSAN_INTERCEPTOR(void*, __libc_memalign, uptr align, uptr sz) {
35007ba8ef44deb54baa9307298fbffe25ddb30c362Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(__libc_memalign, align, sz);
351543b94a5cd102c0795b44d78234d5458eed2c75eDmitry Vyukov  return user_alloc(thr, pc, sz, align);
35207ba8ef44deb54baa9307298fbffe25ddb30c362Dmitry Vyukov}
35307ba8ef44deb54baa9307298fbffe25ddb30c362Dmitry Vyukov
3547ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, calloc, uptr size, uptr n) {
35531c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  if (cur_thread()->in_symbolizer)
35631c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov    return __libc_calloc(size, n);
35765199f1b253c4bfb225805629217acb8f0b1e185Kostya Serebryany  if (__sanitizer::CallocShouldReturnNullDueToOverflow(size, n)) return 0;
35805906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov  void *p = 0;
35905906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov  {
36005906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov    SCOPED_INTERCEPTOR_RAW(calloc, size, n);
36105906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov    p = user_alloc(thr, pc, n * size);
3620ce948e0887e2c23c6510c32a639da9730bbce25Alexander Potapenko    if (p) internal_memset(p, 0, n * size);
36305906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov  }
36405906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov  invoke_malloc_hook(p, n * size);
3657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return p;
3667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3687ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, realloc, void *p, uptr size) {
36931c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  if (cur_thread()->in_symbolizer)
37031c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov    return __libc_realloc(p, size);
37105906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov  if (p)
37205906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov    invoke_free_hook(p);
37305906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov  {
37405906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov    SCOPED_INTERCEPTOR_RAW(realloc, p, size);
37505906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov    p = user_realloc(thr, pc, p, size);
37605906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov  }
37705906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov  invoke_malloc_hook(p, size);
37805906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov  return p;
3797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3817ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void, free, void *p) {
3827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (p == 0)
3837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
38431c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  if (cur_thread()->in_symbolizer)
38531c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov    return __libc_free(p);
38605906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov  invoke_free_hook(p);
3877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_INTERCEPTOR_RAW(free, p);
3887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  user_free(thr, pc, p);
3897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3917ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void, cfree, void *p) {
3927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (p == 0)
3937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
39431c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  if (cur_thread()->in_symbolizer)
39531c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov    return __libc_free(p);
39605906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov  invoke_free_hook(p);
3977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_INTERCEPTOR_RAW(cfree, p);
3987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  user_free(thr, pc, p);
3997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
4007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
4018a6b5e551ab8a331f7e7bc4bfcd74926fbffa3f6Alexey SamsonovTSAN_INTERCEPTOR(uptr, malloc_usable_size, void *p) {
4028a6b5e551ab8a331f7e7bc4bfcd74926fbffa3f6Alexey Samsonov  SCOPED_INTERCEPTOR_RAW(malloc_usable_size, p);
4038a6b5e551ab8a331f7e7bc4bfcd74926fbffa3f6Alexey Samsonov  return user_alloc_usable_size(thr, pc, p);
4048a6b5e551ab8a331f7e7bc4bfcd74926fbffa3f6Alexey Samsonov}
4058a6b5e551ab8a331f7e7bc4bfcd74926fbffa3f6Alexey Samsonov
4067eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov#define OPERATOR_NEW_BODY(mangled_name) \
40731c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  if (cur_thread()->in_symbolizer) \
40831c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov    return __libc_malloc(size); \
4097eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov  void *p = 0; \
4107eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov  {  \
4117eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov    SCOPED_INTERCEPTOR_RAW(mangled_name, size); \
4127eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov    p = user_alloc(thr, pc, size); \
4137eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov  }  \
4147eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov  invoke_malloc_hook(p, size);  \
4157eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov  return p;
4167eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov
4177eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonovvoid *operator new(__sanitizer::uptr size) {
4187eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov  OPERATOR_NEW_BODY(_Znwm);
4197eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov}
4207eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonovvoid *operator new[](__sanitizer::uptr size) {
4217eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov  OPERATOR_NEW_BODY(_Znam);
4227eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov}
4237eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonovvoid *operator new(__sanitizer::uptr size, std::nothrow_t const&) {
4247eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov  OPERATOR_NEW_BODY(_ZnwmRKSt9nothrow_t);
4257eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov}
4267eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonovvoid *operator new[](__sanitizer::uptr size, std::nothrow_t const&) {
4277eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov  OPERATOR_NEW_BODY(_ZnamRKSt9nothrow_t);
4287eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov}
4297eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov
4307eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov#define OPERATOR_DELETE_BODY(mangled_name) \
4317eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov  if (ptr == 0) return;  \
43231c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  if (cur_thread()->in_symbolizer) \
43331c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov    return __libc_free(ptr); \
4347eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov  invoke_free_hook(ptr);  \
4357eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov  SCOPED_INTERCEPTOR_RAW(mangled_name, ptr);  \
4367eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov  user_free(thr, pc, ptr);
4377eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov
4387eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonovvoid operator delete(void *ptr) {
4397eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov  OPERATOR_DELETE_BODY(_ZdlPv);
4407eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov}
4417eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonovvoid operator delete[](void *ptr) {
4427eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov  OPERATOR_DELETE_BODY(_ZdlPvRKSt9nothrow_t);
4437eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov}
4447eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonovvoid operator delete(void *ptr, std::nothrow_t const&) {
4457eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov  OPERATOR_DELETE_BODY(_ZdaPv);
4467eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov}
4477eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonovvoid operator delete[](void *ptr, std::nothrow_t const&) {
4487eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov  OPERATOR_DELETE_BODY(_ZdaPvRKSt9nothrow_t);
4497eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov}
4507eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov
451d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry VyukovTSAN_INTERCEPTOR(uptr, strlen, const char *s) {
4527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(strlen, s);
453d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov  uptr len = internal_strlen(s);
4547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)s, len + 1, false);
4557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return len;
4567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
4577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
458065c4ac846589d04436cb7f19f938ff42035313eDmitry VyukovTSAN_INTERCEPTOR(void*, memset, void *dst, int v, uptr size) {
459065c4ac846589d04436cb7f19f938ff42035313eDmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(memset, dst, v, size);
4607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)dst, size, true);
461065c4ac846589d04436cb7f19f938ff42035313eDmitry Vyukov  return internal_memset(dst, v, size);
4627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
4637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
464065c4ac846589d04436cb7f19f938ff42035313eDmitry VyukovTSAN_INTERCEPTOR(void*, memcpy, void *dst, const void *src, uptr size) {
465065c4ac846589d04436cb7f19f938ff42035313eDmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(memcpy, dst, src, size);
4667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)dst, size, true);
4677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)src, size, false);
468065c4ac846589d04436cb7f19f938ff42035313eDmitry Vyukov  return internal_memcpy(dst, src, size);
4697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
4707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
471065c4ac846589d04436cb7f19f938ff42035313eDmitry VyukovTSAN_INTERCEPTOR(int, memcmp, const void *s1, const void *s2, uptr n) {
472065c4ac846589d04436cb7f19f938ff42035313eDmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(memcmp, s1, s2, n);
473d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov  int res = 0;
474d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov  uptr len = 0;
475d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov  for (; len < n; len++) {
476d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov    if ((res = ((unsigned char*)s1)[len] - ((unsigned char*)s2)[len]))
477d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov      break;
478d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov  }
479d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov  MemoryAccessRange(thr, pc, (uptr)s1, len < n ? len + 1 : n, false);
480d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov  MemoryAccessRange(thr, pc, (uptr)s2, len < n ? len + 1 : n, false);
481d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov  return res;
482d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov}
483d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov
4847ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, strcmp, const char *s1, const char *s2) {
4857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(strcmp, s1, s2);
4867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  uptr len = 0;
4877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  for (; s1[len] && s2[len]; len++) {
4887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    if (s1[len] != s2[len])
4897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      break;
4907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
4917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)s1, len + 1, false);
4927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)s2, len + 1, false);
4937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return s1[len] - s2[len];
4947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
4957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
4967ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr n) {
4977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(strncmp, s1, s2, n);
4987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  uptr len = 0;
4997d38634b30beed9bed44dfa6cb8e977ec51d7c6cDmitry Vyukov  for (; len < n && s1[len] && s2[len]; len++) {
5007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    if (s1[len] != s2[len])
5017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      break;
5027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
5037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)s1, len < n ? len + 1 : n, false);
5047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)s2, len < n ? len + 1 : n, false);
5057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return len == n ? 0 : s1[len] - s2[len];
5067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5087ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, memchr, void *s, int c, uptr n) {
5097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(memchr, s, c, n);
5107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  void *res = REAL(memchr)(s, c, n);
5117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  uptr len = res ? (char*)res - (char*)s + 1 : n;
5127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)s, len, false);
5137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
5147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5167ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, memrchr, char *s, int c, uptr n) {
5177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(memrchr, s, c, n);
5187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)s, n, false);
5197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return REAL(memrchr)(s, c, n);
5207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5227ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, memmove, void *dst, void *src, uptr n) {
5237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(memmove, dst, src, n);
5247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)dst, n, true);
5257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)src, n, false);
5267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return REAL(memmove)(dst, src, n);
5277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
529d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry VyukovTSAN_INTERCEPTOR(char*, strchr, char *s, int c) {
5307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(strchr, s, c);
531d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov  char *res = REAL(strchr)(s, c);
532d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov  uptr len = res ? (char*)res - (char*)s + 1 : internal_strlen(s) + 1;
5337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)s, len, false);
5347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
5357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
537d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry VyukovTSAN_INTERCEPTOR(char*, strchrnul, char *s, int c) {
5387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(strchrnul, s, c);
539d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov  char *res = REAL(strchrnul)(s, c);
5407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  uptr len = (char*)res - (char*)s + 1;
5417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)s, len, false);
5427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
5437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
545d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry VyukovTSAN_INTERCEPTOR(char*, strrchr, char *s, int c) {
5467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(strrchr, s, c);
547d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov  MemoryAccessRange(thr, pc, (uptr)s, internal_strlen(s) + 1, false);
5487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return REAL(strrchr)(s, c);
5497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
551d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry VyukovTSAN_INTERCEPTOR(char*, strcpy, char *dst, const char *src) {  // NOLINT
5527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(strcpy, dst, src);  // NOLINT
553d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov  uptr srclen = internal_strlen(src);
5547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)dst, srclen + 1, true);
5557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)src, srclen + 1, false);
5567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return REAL(strcpy)(dst, src);  // NOLINT
5577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
559d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry VyukovTSAN_INTERCEPTOR(char*, strncpy, char *dst, char *src, uptr n) {
5607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(strncpy, dst, src, n);
561b93c3d5badc4066120edf3ed1c515cdd516a8776Kostya Serebryany  uptr srclen = internal_strnlen(src, n);
5627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)dst, n, true);
5637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)src, min(srclen + 1, n), false);
5647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return REAL(strncpy)(dst, src, n);
5657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5677ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(const char*, strstr, const char *s1, const char *s2) {
5687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(strstr, s1, s2);
5697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  const char *res = REAL(strstr)(s1, s2);
570d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov  uptr len1 = internal_strlen(s1);
571d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov  uptr len2 = internal_strlen(s2);
5727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)s1, len1 + 1, false);
5737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)s2, len2 + 1, false);
5747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
5757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic bool fix_mmap_addr(void **addr, long_t sz, int flags) {
5787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (*addr) {
5797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    if (!IsAppMem((uptr)*addr) || !IsAppMem((uptr)*addr + sz - 1)) {
5807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      if (flags & MAP_FIXED) {
5817a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov        errno = EINVAL;
5827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany        return false;
5837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      } else {
5847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany        *addr = 0;
5857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      }
5867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    }
5877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
5887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return true;
5897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5917ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, mmap, void *addr, long_t sz, int prot,
5927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany                         int flags, int fd, unsigned off) {
5937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(mmap, addr, sz, prot, flags, fd, off);
5947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (!fix_mmap_addr(&addr, sz, flags))
5957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return MAP_FAILED;
5967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  void *res = REAL(mmap)(addr, sz, prot, flags, fd, off);
5977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res != MAP_FAILED) {
598c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov    if (fd > 0)
599c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov      FdAccess(thr, pc, fd);
6007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    MemoryResetRange(thr, pc, (uptr)res, sz);
6017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
6027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
6037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
6047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6057ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, mmap64, void *addr, long_t sz, int prot,
6067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany                           int flags, int fd, u64 off) {
6077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(mmap64, addr, sz, prot, flags, fd, off);
6087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (!fix_mmap_addr(&addr, sz, flags))
6097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return MAP_FAILED;
6107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  void *res = REAL(mmap64)(addr, sz, prot, flags, fd, off);
6117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res != MAP_FAILED) {
612c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov    if (fd > 0)
613c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov      FdAccess(thr, pc, fd);
6147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    MemoryResetRange(thr, pc, (uptr)res, sz);
6157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
6167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
6177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
6187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6197ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, munmap, void *addr, long_t sz) {
6207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(munmap, addr, sz);
6217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(munmap)(addr, sz);
6227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
6237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
6247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6257ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, memalign, uptr align, uptr sz) {
6267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(memalign, align, sz);
6272e87051d136db3150a3ca322d8862f92b0a684bbDmitry Vyukov  return user_alloc(thr, pc, sz, align);
6287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
6297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6307ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, valloc, uptr sz) {
6317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(valloc, sz);
632f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany  return user_alloc(thr, pc, sz, GetPageSizeCached());
6337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
6347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6357ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, pvalloc, uptr sz) {
6367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pvalloc, sz);
637f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany  sz = RoundUp(sz, GetPageSizeCached());
638f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany  return user_alloc(thr, pc, sz, GetPageSizeCached());
6397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
6407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6417ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, posix_memalign, void **memptr, uptr align, uptr sz) {
6427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(posix_memalign, memptr, align, sz);
6432e87051d136db3150a3ca322d8862f92b0a684bbDmitry Vyukov  *memptr = user_alloc(thr, pc, sz, align);
6447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return 0;
6457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
6467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// Used in thread-safe function static initialization.
6481ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukovextern "C" int INTERFACE_ATTRIBUTE __cxa_guard_acquire(atomic_uint32_t *g) {
6491ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov  SCOPED_INTERCEPTOR_RAW(__cxa_guard_acquire, g);
6501ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov  for (;;) {
6511ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov    u32 cmp = atomic_load(g, memory_order_acquire);
6521ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov    if (cmp == 0) {
6531ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov      if (atomic_compare_exchange_strong(g, &cmp, 1<<16, memory_order_relaxed))
6541ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov        return 1;
6551ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov    } else if (cmp == 1) {
6561ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov      Acquire(thr, pc, (uptr)g);
6571ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov      return 0;
6581ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov    } else {
6591ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov      internal_sched_yield();
6601ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov    }
6617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
6627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
6637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6641ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukovextern "C" void INTERFACE_ATTRIBUTE __cxa_guard_release(atomic_uint32_t *g) {
6651ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov  SCOPED_INTERCEPTOR_RAW(__cxa_guard_release, g);
6661ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov  Release(thr, pc, (uptr)g);
6671ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov  atomic_store(g, 1, memory_order_release);
6681ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov}
6691ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov
6701ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukovextern "C" void INTERFACE_ATTRIBUTE __cxa_guard_abort(atomic_uint32_t *g) {
6711ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov  SCOPED_INTERCEPTOR_RAW(__cxa_guard_abort, g);
6721ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov  atomic_store(g, 0, memory_order_relaxed);
6737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
6747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void thread_finalize(void *v) {
6767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  uptr iter = (uptr)v;
6777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (iter > 1) {
6787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    if (pthread_setspecific(g_thread_finalize_key, (void*)(iter - 1))) {
679b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov      Printf("ThreadSanitizer: failed to set thread key\n");
6807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      Die();
6817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    }
6827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
6837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
6847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  {
6857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    ScopedInRtl in_rtl;
686e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov    ThreadState *thr = cur_thread();
687e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov    ThreadFinish(thr);
6881fc03d50a87302689482efa24b045a393097b6c3Dmitry Vyukov    SignalContext *sctx = thr->signal_ctx;
6891fc03d50a87302689482efa24b045a393097b6c3Dmitry Vyukov    if (sctx) {
6901fc03d50a87302689482efa24b045a393097b6c3Dmitry Vyukov      thr->signal_ctx = 0;
691c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov      UnmapOrDie(sctx, sizeof(*sctx));
6921fc03d50a87302689482efa24b045a393097b6c3Dmitry Vyukov    }
6937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
6947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
6957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystruct ThreadParam {
6987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  void* (*callback)(void *arg);
6997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  void *param;
7007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  atomic_uintptr_t tid;
7017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany};
7027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
7037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void *__tsan_thread_start_func(void *arg) {
7047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ThreadParam *p = (ThreadParam*)arg;
7057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  void* (*callback)(void *arg) = p->callback;
7067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  void *param = p->param;
7077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int tid = 0;
7087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  {
7097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    ThreadState *thr = cur_thread();
7107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    ScopedInRtl in_rtl;
7117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    if (pthread_setspecific(g_thread_finalize_key, (void*)4)) {
712b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov      Printf("ThreadSanitizer: failed to set thread key\n");
7137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      Die();
7147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    }
7157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    while ((tid = atomic_load(&p->tid, memory_order_acquire)) == 0)
7167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      pthread_yield();
7177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    atomic_store(&p->tid, 0, memory_order_release);
7187dccf3f92a867f917ad19f9a6b37bcf93e64b35bDmitry Vyukov    ThreadStart(thr, tid, GetTid());
7197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    CHECK_EQ(thr->in_rtl, 1);
7207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
7217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  void *res = callback(param);
7227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // Prevent the callback from being tail called,
7237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // it mixes up stack traces.
7247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  volatile int foo = 42;
7257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  foo++;
7267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
7277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
7287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
7297ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_create,
7307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    void *th, void *attr, void *(*callback)(void*), void * param) {
7317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_create, th, attr, callback, param);
732f110e356170fbe990b99c0939d77eeaa89b25497Alexey Samsonov  __sanitizer_pthread_attr_t myattr;
7337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (attr == 0) {
7347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    pthread_attr_init(&myattr);
7357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    attr = &myattr;
7367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
7377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int detached = 0;
7387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  pthread_attr_getdetachstate(attr, &detached);
7397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  uptr stacksize = 0;
7407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  pthread_attr_getstacksize(attr, &stacksize);
7417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // We place the huge ThreadState object into TLS, account for that.
7427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  const uptr minstacksize = GetTlsSize() + 128*1024;
7437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (stacksize < minstacksize) {
744e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov    DPrintf("ThreadSanitizer: stacksize %zu->%zu\n", stacksize, minstacksize);
7457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    pthread_attr_setstacksize(attr, minstacksize);
7467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
7477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ThreadParam p;
7487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  p.callback = callback;
7497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  p.param = param;
7507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  atomic_store(&p.tid, 0, memory_order_relaxed);
7517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_create)(th, attr, __tsan_thread_start_func, &p);
7527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
75364310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    int tid = ThreadCreate(thr, pc, *(uptr*)th, detached);
7547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    CHECK_NE(tid, 0);
7557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    atomic_store(&p.tid, tid, memory_order_release);
7567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    while (atomic_load(&p.tid, memory_order_acquire) != 0)
7577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      pthread_yield();
7587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
7597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (attr == &myattr)
7607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    pthread_attr_destroy(&myattr);
7617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
7627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
7637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
7647ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_join, void *th, void **ret) {
7657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_join, th, ret);
7667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int tid = ThreadTid(thr, pc, (uptr)th);
767ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  int res = BLOCK_REAL(pthread_join)(th, ret);
7687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
76964310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    ThreadJoin(thr, pc, tid);
7707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
7717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
7727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
7737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
7747ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_detach, void *th) {
7757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_detach, th);
7767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int tid = ThreadTid(thr, pc, (uptr)th);
7777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_detach)(th);
7787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
77964310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    ThreadDetach(thr, pc, tid);
7807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
7817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
7827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
7837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
7847ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_mutex_init, void *m, void *a) {
7857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_mutex_init, m, a);
7867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_mutex_init)(m, a);
7877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
7887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    bool recursive = false;
7897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    if (a) {
7907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      int type = 0;
7917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      if (pthread_mutexattr_gettype(a, &type) == 0)
7927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany        recursive = (type == PTHREAD_MUTEX_RECURSIVE
7937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany            || type == PTHREAD_MUTEX_RECURSIVE_NP);
7947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    }
795c20e9ba760a93706c9160133cdcce62194f9694fDmitry Vyukov    MutexCreate(thr, pc, (uptr)m, false, recursive, false);
7967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
7977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
7987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
7997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
8007ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_mutex_destroy, void *m) {
8017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_mutex_destroy, m);
8027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_mutex_destroy)(m);
8037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0 || res == EBUSY) {
80464310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    MutexDestroy(thr, pc, (uptr)m);
8057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
8067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
8077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
8087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
8097ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_mutex_lock, void *m) {
8107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_mutex_lock, m);
8117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_mutex_lock)(m);
8127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
81364310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    MutexLock(thr, pc, (uptr)m);
8147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
8157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
8167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
8177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
8187ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_mutex_trylock, void *m) {
8197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_mutex_trylock, m);
8207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_mutex_trylock)(m);
8217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
82264310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    MutexLock(thr, pc, (uptr)m);
8237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
8247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
8257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
8267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
8277ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_mutex_timedlock, void *m, void *abstime) {
8287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_mutex_timedlock, m, abstime);
8297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_mutex_timedlock)(m, abstime);
8307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
83164310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    MutexLock(thr, pc, (uptr)m);
8327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
8337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
8347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
8357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
8367ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_mutex_unlock, void *m) {
8377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_mutex_unlock, m);
83864310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov  MutexUnlock(thr, pc, (uptr)m);
8397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_mutex_unlock)(m);
8407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
8417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
8427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
8437ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_spin_init, void *m, int pshared) {
8447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_spin_init, m, pshared);
8457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_spin_init)(m, pshared);
8467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
847c20e9ba760a93706c9160133cdcce62194f9694fDmitry Vyukov    MutexCreate(thr, pc, (uptr)m, false, false, false);
8487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
8497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
8507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
8517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
8527ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_spin_destroy, void *m) {
8537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_spin_destroy, m);
8547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_spin_destroy)(m);
8557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
85664310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    MutexDestroy(thr, pc, (uptr)m);
8577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
8587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
8597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
8607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
8617ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_spin_lock, void *m) {
8627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_spin_lock, m);
8637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_spin_lock)(m);
8647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
86564310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    MutexLock(thr, pc, (uptr)m);
8667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
8677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
8687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
8697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
8707ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_spin_trylock, void *m) {
8717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_spin_trylock, m);
8727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_spin_trylock)(m);
8737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
87464310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    MutexLock(thr, pc, (uptr)m);
8757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
8767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
8777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
8787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
8797ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_spin_unlock, void *m) {
8807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_spin_unlock, m);
88164310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov  MutexUnlock(thr, pc, (uptr)m);
8827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_spin_unlock)(m);
8837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
8847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
8857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
8867ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_rwlock_init, void *m, void *a) {
8877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_init, m, a);
8887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_rwlock_init)(m, a);
8897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
890c20e9ba760a93706c9160133cdcce62194f9694fDmitry Vyukov    MutexCreate(thr, pc, (uptr)m, true, false, false);
8917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
8927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
8937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
8947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
8957ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_rwlock_destroy, void *m) {
8967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_destroy, m);
8977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_rwlock_destroy)(m);
8987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
89964310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    MutexDestroy(thr, pc, (uptr)m);
9007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
9017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
9027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
9037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
9047ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_rwlock_rdlock, void *m) {
9057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_rdlock, m);
9067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_rwlock_rdlock)(m);
9077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
90864310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    MutexReadLock(thr, pc, (uptr)m);
9097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
9107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
9117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
9127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
9137ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_rwlock_tryrdlock, void *m) {
9147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_tryrdlock, m);
9157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_rwlock_tryrdlock)(m);
9167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
91764310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    MutexReadLock(thr, pc, (uptr)m);
9187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
9197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
9207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
9217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
9227ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_rwlock_timedrdlock, void *m, void *abstime) {
9237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_timedrdlock, m, abstime);
9247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_rwlock_timedrdlock)(m, abstime);
9257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
92664310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    MutexReadLock(thr, pc, (uptr)m);
9277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
9287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
9297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
9307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
9317ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_rwlock_wrlock, void *m) {
9327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_wrlock, m);
9337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_rwlock_wrlock)(m);
9347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
93564310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    MutexLock(thr, pc, (uptr)m);
9367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
9377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
9387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
9397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
9407ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_rwlock_trywrlock, void *m) {
9417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_trywrlock, m);
9427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_rwlock_trywrlock)(m);
9437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
94464310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    MutexLock(thr, pc, (uptr)m);
9457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
9467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
9477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
9487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
9497ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_rwlock_timedwrlock, void *m, void *abstime) {
9507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_timedwrlock, m, abstime);
9517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_rwlock_timedwrlock)(m, abstime);
9527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
95364310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    MutexLock(thr, pc, (uptr)m);
9547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
9557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
9567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
9577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
9587ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_rwlock_unlock, void *m) {
9597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_unlock, m);
96064310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov  MutexReadOrWriteUnlock(thr, pc, (uptr)m);
9617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_rwlock_unlock)(m);
9627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
9637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
9647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
965703e4e4a133aa6585361a2c6130cfc2874efff75Dmitry Vyukov// libpthread.so contains several versions of pthread_cond_init symbol.
966703e4e4a133aa6585361a2c6130cfc2874efff75Dmitry Vyukov// When we just dlsym() it, we get the wrong (old) version.
967c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov/*
9687ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_cond_init, void *c, void *a) {
9697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_cond_init, c, a);
9707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_cond_init)(c, a);
9717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
9727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
973c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov*/
9747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
9757ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_cond_destroy, void *c) {
9767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_cond_destroy, c);
9777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_cond_destroy)(c);
9787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
9797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
9807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
9817ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_cond_signal, void *c) {
9827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_cond_signal, c);
9837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_cond_signal)(c);
9847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
9857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
9867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
9877ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_cond_broadcast, void *c) {
9887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_cond_broadcast, c);
9897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_cond_broadcast)(c);
9907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
9917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
9927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
9937ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_cond_wait, void *c, void *m) {
9947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_cond_wait, c, m);
99564310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov  MutexUnlock(thr, pc, (uptr)m);
9967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_cond_wait)(c, m);
99764310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov  MutexLock(thr, pc, (uptr)m);
9987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
9997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
10007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
10017ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_cond_timedwait, void *c, void *m, void *abstime) {
10027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_cond_timedwait, c, m, abstime);
100364310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov  MutexUnlock(thr, pc, (uptr)m);
10047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_cond_timedwait)(c, m, abstime);
100564310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov  MutexLock(thr, pc, (uptr)m);
10067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
10077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
10087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
10097ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_barrier_init, void *b, void *a, unsigned count) {
10107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_barrier_init, b, a, count);
1011334553ec45d8982df45a6f5e656e068142ecde3fDmitry Vyukov  MemoryWrite(thr, pc, (uptr)b, kSizeLog1);
10127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_barrier_init)(b, a, count);
10137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
10147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
10157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
10167ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_barrier_destroy, void *b) {
10177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_barrier_destroy, b);
1018334553ec45d8982df45a6f5e656e068142ecde3fDmitry Vyukov  MemoryWrite(thr, pc, (uptr)b, kSizeLog1);
10197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_barrier_destroy)(b);
10207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
10217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
10227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
10237ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_barrier_wait, void *b) {
10247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_barrier_wait, b);
102564310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov  Release(thr, pc, (uptr)b);
1026334553ec45d8982df45a6f5e656e068142ecde3fDmitry Vyukov  MemoryRead(thr, pc, (uptr)b, kSizeLog1);
10277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_barrier_wait)(b);
1028334553ec45d8982df45a6f5e656e068142ecde3fDmitry Vyukov  MemoryRead(thr, pc, (uptr)b, kSizeLog1);
10297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0 || res == PTHREAD_BARRIER_SERIAL_THREAD) {
103064310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    Acquire(thr, pc, (uptr)b);
10317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
10327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
10337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
10347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
10357ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) {
10367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_once, o, f);
10377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (o == 0 || f == 0)
10387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return EINVAL;
10397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  atomic_uint32_t *a = static_cast<atomic_uint32_t*>(o);
10407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  u32 v = atomic_load(a, memory_order_acquire);
10417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (v == 0 && atomic_compare_exchange_strong(a, &v, 1,
10427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany                                               memory_order_relaxed)) {
10437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    const int old_in_rtl = thr->in_rtl;
10447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    thr->in_rtl = 0;
10457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    (*f)();
10467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    CHECK_EQ(thr->in_rtl, 0);
10477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    thr->in_rtl = old_in_rtl;
104864310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    Release(thr, pc, (uptr)o);
10497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    atomic_store(a, 2, memory_order_release);
10507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  } else {
10517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    while (v != 2) {
10527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      pthread_yield();
10537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      v = atomic_load(a, memory_order_acquire);
10547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    }
105564310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    Acquire(thr, pc, (uptr)o);
10567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
10577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return 0;
10587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
10597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
10607ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, sem_init, void *s, int pshared, unsigned value) {
10617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(sem_init, s, pshared, value);
10627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(sem_init)(s, pshared, value);
10637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
10647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
10657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
10667ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, sem_destroy, void *s) {
10677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(sem_destroy, s);
10687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(sem_destroy)(s);
10697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
10707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
10717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
10727ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, sem_wait, void *s) {
10737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(sem_wait, s);
1074ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  int res = BLOCK_REAL(sem_wait)(s);
10757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
107664310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    Acquire(thr, pc, (uptr)s);
10777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
10787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
10797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
10807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
10817ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, sem_trywait, void *s) {
10827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(sem_trywait, s);
1083ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  int res = BLOCK_REAL(sem_trywait)(s);
10847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
108564310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    Acquire(thr, pc, (uptr)s);
10867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
10877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
10887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
10897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
10907ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, sem_timedwait, void *s, void *abstime) {
10917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(sem_timedwait, s, abstime);
1092ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  int res = BLOCK_REAL(sem_timedwait)(s, abstime);
10937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
109464310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    Acquire(thr, pc, (uptr)s);
10957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
10967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
10977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
10987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
10997ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, sem_post, void *s) {
11007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(sem_post, s);
110164310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov  Release(thr, pc, (uptr)s);
11027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(sem_post)(s);
11037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
11047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
11057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
11067ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, sem_getvalue, void *s, int *sval) {
11077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(sem_getvalue, s, sval);
11087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(sem_getvalue)(s, sval);
11097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
111064310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    Acquire(thr, pc, (uptr)s);
11117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
11127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
11137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
11147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
111561ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, __xstat, int version, const char *path, void *buf) {
111661ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(__xstat, version, path, buf);
111761ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  return REAL(__xstat)(version, path, buf);
111861ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov}
111961ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov
112061ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, stat, const char *path, void *buf) {
112161ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(__xstat, 0, path, buf);
112261ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  return REAL(__xstat)(0, path, buf);
112361ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov}
112461ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov
112561ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, __xstat64, int version, const char *path, void *buf) {
112661ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(__xstat64, version, path, buf);
112761ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  return REAL(__xstat64)(version, path, buf);
112861ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov}
112961ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov
113061ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, stat64, const char *path, void *buf) {
113161ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(__xstat64, 0, path, buf);
113261ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  return REAL(__xstat64)(0, path, buf);
113361ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov}
113461ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov
113561ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, __lxstat, int version, const char *path, void *buf) {
113661ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(__lxstat, version, path, buf);
113761ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  return REAL(__lxstat)(version, path, buf);
113861ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov}
113961ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov
114061ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, lstat, const char *path, void *buf) {
114161ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(__lxstat, 0, path, buf);
114261ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  return REAL(__lxstat)(0, path, buf);
114361ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov}
114461ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov
114561ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, __lxstat64, int version, const char *path, void *buf) {
114661ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(__lxstat64, version, path, buf);
114761ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  return REAL(__lxstat64)(version, path, buf);
114861ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov}
114961ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov
115061ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, lstat64, const char *path, void *buf) {
115161ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(__lxstat64, 0, path, buf);
115261ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  return REAL(__lxstat64)(0, path, buf);
115361ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov}
115461ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov
115561ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, __fxstat, int version, int fd, void *buf) {
115661ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(__fxstat, version, fd, buf);
1157c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov  if (fd > 0)
1158c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov    FdAccess(thr, pc, fd);
115961ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  return REAL(__fxstat)(version, fd, buf);
116061ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov}
116161ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov
116261ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, fstat, int fd, void *buf) {
116361ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(__fxstat, 0, fd, buf);
1164c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov  if (fd > 0)
1165c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov    FdAccess(thr, pc, fd);
116661ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  return REAL(__fxstat)(0, fd, buf);
116761ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov}
116861ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov
116961ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, __fxstat64, int version, int fd, void *buf) {
117061ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(__fxstat64, version, fd, buf);
1171c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov  if (fd > 0)
1172c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov    FdAccess(thr, pc, fd);
117361ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  return REAL(__fxstat64)(version, fd, buf);
117461ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov}
117561ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov
117661ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, fstat64, int fd, void *buf) {
117761ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(__fxstat64, 0, fd, buf);
1178c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov  if (fd > 0)
1179c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov    FdAccess(thr, pc, fd);
118061ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  return REAL(__fxstat64)(0, fd, buf);
118161ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov}
118261ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov
1183ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry VyukovTSAN_INTERCEPTOR(int, open, const char *name, int flags, int mode) {
1184ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(open, name, flags, mode);
1185ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  int fd = REAL(open)(name, flags, mode);
1186ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  if (fd >= 0)
118768230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov    FdFileCreate(thr, pc, fd);
1188ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  return fd;
1189ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov}
1190ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov
1191c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry VyukovTSAN_INTERCEPTOR(int, open64, const char *name, int flags, int mode) {
1192c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(open64, name, flags, mode);
1193c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  int fd = REAL(open64)(name, flags, mode);
1194c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  if (fd >= 0)
1195c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov    FdFileCreate(thr, pc, fd);
1196c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  return fd;
1197c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov}
1198c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov
1199ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry VyukovTSAN_INTERCEPTOR(int, creat, const char *name, int mode) {
1200ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(creat, name, mode);
1201ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  int fd = REAL(creat)(name, mode);
1202ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  if (fd >= 0)
120368230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov    FdFileCreate(thr, pc, fd);
1204ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  return fd;
1205ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov}
1206ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov
1207c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry VyukovTSAN_INTERCEPTOR(int, creat64, const char *name, int mode) {
1208c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(creat64, name, mode);
1209c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  int fd = REAL(creat64)(name, mode);
1210c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  if (fd >= 0)
1211c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov    FdFileCreate(thr, pc, fd);
1212c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  return fd;
1213c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov}
1214c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov
1215ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry VyukovTSAN_INTERCEPTOR(int, dup, int oldfd) {
1216ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(dup, oldfd);
1217ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  int newfd = REAL(dup)(oldfd);
1218b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (oldfd >= 0 && newfd >= 0 && newfd != oldfd)
1219ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov    FdDup(thr, pc, oldfd, newfd);
1220ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  return newfd;
1221ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov}
1222ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov
1223ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry VyukovTSAN_INTERCEPTOR(int, dup2, int oldfd, int newfd) {
1224ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(dup2, oldfd, newfd);
1225ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  int newfd2 = REAL(dup2)(oldfd, newfd);
1226b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (oldfd >= 0 && newfd2 >= 0 && newfd2 != oldfd)
1227ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov    FdDup(thr, pc, oldfd, newfd2);
1228ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  return newfd2;
1229ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov}
1230ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov
1231ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry VyukovTSAN_INTERCEPTOR(int, dup3, int oldfd, int newfd, int flags) {
1232ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(dup3, oldfd, newfd, flags);
1233ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  int newfd2 = REAL(dup3)(oldfd, newfd, flags);
1234b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (oldfd >= 0 && newfd2 >= 0 && newfd2 != oldfd)
1235ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov    FdDup(thr, pc, oldfd, newfd2);
1236ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  return newfd2;
1237ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov}
1238ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov
123968230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry VyukovTSAN_INTERCEPTOR(int, eventfd, unsigned initval, int flags) {
124068230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(eventfd, initval, flags);
124168230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  int fd = REAL(eventfd)(initval, flags);
124268230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  if (fd >= 0)
124368230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov    FdEventCreate(thr, pc, fd);
124468230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  return fd;
124568230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov}
124668230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov
124745d4324bf5b0ec282f0a8f96312233e09a882502Dmitry VyukovTSAN_INTERCEPTOR(int, signalfd, int fd, void *mask, int flags) {
124845d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(signalfd, fd, mask, flags);
1249b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (fd >= 0)
1250b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov    FdClose(thr, pc, fd);
125145d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov  fd = REAL(signalfd)(fd, mask, flags);
125245d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov  if (fd >= 0)
125345d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov    FdSignalCreate(thr, pc, fd);
125445d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov  return fd;
125545d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov}
125645d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov
1257b75c67b495ca13801cc629b2c2c9dd0010e54739Dmitry VyukovTSAN_INTERCEPTOR(int, inotify_init, int fake) {
1258b75c67b495ca13801cc629b2c2c9dd0010e54739Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(inotify_init, fake);
1259b75c67b495ca13801cc629b2c2c9dd0010e54739Dmitry Vyukov  int fd = REAL(inotify_init)(fake);
126045d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov  if (fd >= 0)
126145d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov    FdInotifyCreate(thr, pc, fd);
126245d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov  return fd;
126345d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov}
126445d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov
126545d4324bf5b0ec282f0a8f96312233e09a882502Dmitry VyukovTSAN_INTERCEPTOR(int, inotify_init1, int flags) {
126645d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(inotify_init1, flags);
126745d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov  int fd = REAL(inotify_init1)(flags);
126845d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov  if (fd >= 0)
126945d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov    FdInotifyCreate(thr, pc, fd);
127045d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov  return fd;
127145d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov}
127245d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov
127368230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry VyukovTSAN_INTERCEPTOR(int, socket, int domain, int type, int protocol) {
127468230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(socket, domain, type, protocol);
127568230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  int fd = REAL(socket)(domain, type, protocol);
127668230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  if (fd >= 0)
127768230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov    FdSocketCreate(thr, pc, fd);
127868230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  return fd;
127968230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov}
128068230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov
1281983518e360a179d92bdbddebe05a87db3c6cc3c0Dmitry VyukovTSAN_INTERCEPTOR(int, socketpair, int domain, int type, int protocol, int *fd) {
1282983518e360a179d92bdbddebe05a87db3c6cc3c0Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(socketpair, domain, type, protocol, fd);
1283983518e360a179d92bdbddebe05a87db3c6cc3c0Dmitry Vyukov  int res = REAL(socketpair)(domain, type, protocol, fd);
1284983518e360a179d92bdbddebe05a87db3c6cc3c0Dmitry Vyukov  if (res == 0 && fd[0] >= 0 && fd[1] >= 0)
1285983518e360a179d92bdbddebe05a87db3c6cc3c0Dmitry Vyukov    FdPipeCreate(thr, pc, fd[0], fd[1]);
1286983518e360a179d92bdbddebe05a87db3c6cc3c0Dmitry Vyukov  return res;
1287983518e360a179d92bdbddebe05a87db3c6cc3c0Dmitry Vyukov}
1288983518e360a179d92bdbddebe05a87db3c6cc3c0Dmitry Vyukov
128968230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry VyukovTSAN_INTERCEPTOR(int, connect, int fd, void *addr, unsigned addrlen) {
129068230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(connect, fd, addr, addrlen);
1291ed513f69b8017a69214509105e7ec59fec77b468Dmitry Vyukov  FdSocketConnecting(thr, pc, fd);
129268230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  int res = REAL(connect)(fd, addr, addrlen);
1293b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (res == 0 && fd >= 0)
129468230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov    FdSocketConnect(thr, pc, fd);
129568230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  return res;
129668230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov}
129768230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov
129852c70e5818727521b89f7fc95a2a383df8985ca6Dmitry VyukovTSAN_INTERCEPTOR(int, bind, int fd, void *addr, unsigned addrlen) {
129952c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(bind, fd, addr, addrlen);
130052c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov  int res = REAL(bind)(fd, addr, addrlen);
130152c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov  if (fd > 0 && res == 0)
130252c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov    FdAccess(thr, pc, fd);
130352c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov  return res;
130452c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov}
130552c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov
130652c70e5818727521b89f7fc95a2a383df8985ca6Dmitry VyukovTSAN_INTERCEPTOR(int, listen, int fd, int backlog) {
130752c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(listen, fd, backlog);
130852c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov  int res = REAL(listen)(fd, backlog);
130952c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov  if (fd > 0 && res == 0)
131052c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov    FdAccess(thr, pc, fd);
131152c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov  return res;
131252c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov}
131352c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov
131468230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry VyukovTSAN_INTERCEPTOR(int, accept, int fd, void *addr, unsigned *addrlen) {
131568230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(accept, fd, addr, addrlen);
131668230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  int fd2 = REAL(accept)(fd, addr, addrlen);
1317b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (fd >= 0 && fd2 >= 0)
131868230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov    FdSocketAccept(thr, pc, fd, fd2);
131968230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  return fd2;
132068230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov}
132168230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov
132268230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry VyukovTSAN_INTERCEPTOR(int, accept4, int fd, void *addr, unsigned *addrlen, int f) {
132368230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(accept4, fd, addr, addrlen, f);
132468230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  int fd2 = REAL(accept4)(fd, addr, addrlen, f);
1325b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (fd >= 0 && fd2 >= 0)
132668230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov    FdSocketAccept(thr, pc, fd, fd2);
132768230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  return fd2;
132868230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov}
132968230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov
133068230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry VyukovTSAN_INTERCEPTOR(int, epoll_create, int size) {
133168230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(epoll_create, size);
133268230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  int fd = REAL(epoll_create)(size);
133368230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  if (fd >= 0)
133468230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov    FdPollCreate(thr, pc, fd);
133568230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  return fd;
133668230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov}
133768230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov
133868230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry VyukovTSAN_INTERCEPTOR(int, epoll_create1, int flags) {
133968230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(epoll_create1, flags);
134068230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  int fd = REAL(epoll_create1)(flags);
134168230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  if (fd >= 0)
134268230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov    FdPollCreate(thr, pc, fd);
134368230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  return fd;
134468230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov}
134568230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov
1346ddeb2c354235818494d86827e88a0c2fa44bebccDmitry VyukovTSAN_INTERCEPTOR(int, close, int fd) {
1347ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(close, fd);
1348c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  if (fd >= 0)
1349c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov    FdClose(thr, pc, fd);
1350ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov  return REAL(close)(fd);
1351ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov}
1352ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov
1353c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry VyukovTSAN_INTERCEPTOR(int, __close, int fd) {
1354c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(__close, fd);
1355c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  if (fd >= 0)
1356c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov    FdClose(thr, pc, fd);
1357c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  return REAL(__close)(fd);
1358c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov}
1359c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov
136003f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov// glibc guts
136103f224835f46801a0e22cc2951d21b67304e0457Dmitry VyukovTSAN_INTERCEPTOR(void, __res_iclose, void *state, bool free_addr) {
136203f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(__res_iclose, state, free_addr);
136303f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov  int fds[64];
136403f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov  int cnt = ExtractResolvFDs(state, fds, ARRAY_SIZE(fds));
136503f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov  for (int i = 0; i < cnt; i++) {
136603f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov    if (fds[i] > 0)
136703f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov      FdClose(thr, pc, fds[i]);
136803f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov  }
136903f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov  REAL(__res_iclose)(state, free_addr);
137003f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov}
137103f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov
137201e96987f557524a351b9f2229e7c920cdb96aadDmitry VyukovTSAN_INTERCEPTOR(int, pipe, int *pipefd) {
1373ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(pipe, pipefd);
1374ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov  int res = REAL(pipe)(pipefd);
1375b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (res == 0 && pipefd[0] >= 0 && pipefd[1] >= 0)
137668230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov    FdPipeCreate(thr, pc, pipefd[0], pipefd[1]);
137701e96987f557524a351b9f2229e7c920cdb96aadDmitry Vyukov  return res;
1378ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov}
1379ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov
138001e96987f557524a351b9f2229e7c920cdb96aadDmitry VyukovTSAN_INTERCEPTOR(int, pipe2, int *pipefd, int flags) {
1381ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(pipe2, pipefd, flags);
1382ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov  int res = REAL(pipe2)(pipefd, flags);
1383b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (res == 0 && pipefd[0] >= 0 && pipefd[1] >= 0)
138468230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov    FdPipeCreate(thr, pc, pipefd[0], pipefd[1]);
1385ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov  return res;
1386ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov}
1387ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov
13887ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(long_t, readv, int fd, void *vec, int cnt) {
13897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(readv, fd, vec, cnt);
13907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(readv)(fd, vec, cnt);
1391b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (res >= 0 && fd >= 0) {
13923f4e6d9b75fb3f7f2674a31008738cfda9cda9edDmitry Vyukov    FdAcquire(thr, pc, fd);
13937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
13947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
13957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
13967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
13977ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(long_t, preadv64, int fd, void *vec, int cnt, u64 off) {
13987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(preadv64, fd, vec, cnt, off);
13997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(preadv64)(fd, vec, cnt, off);
1400b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (res >= 0 && fd >= 0) {
14013f4e6d9b75fb3f7f2674a31008738cfda9cda9edDmitry Vyukov    FdAcquire(thr, pc, fd);
14027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
14037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
14047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
14057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
14067ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(long_t, writev, int fd, void *vec, int cnt) {
14077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(writev, fd, vec, cnt);
1408b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (fd >= 0)
1409b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov    FdRelease(thr, pc, fd);
14107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(writev)(fd, vec, cnt);
14117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
14127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
14137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
14147ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(long_t, pwritev64, int fd, void *vec, int cnt, u64 off) {
14157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pwritev64, fd, vec, cnt, off);
1416b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (fd >= 0)
1417b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov    FdRelease(thr, pc, fd);
14187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pwritev64)(fd, vec, cnt, off);
14197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
14207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
14217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
14227ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(long_t, send, int fd, void *buf, long_t len, int flags) {
14237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(send, fd, buf, len, flags);
1424b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (fd >= 0)
1425b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov    FdRelease(thr, pc, fd);
14267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(send)(fd, buf, len, flags);
14277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
14287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
14297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
14307ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(long_t, sendmsg, int fd, void *msg, int flags) {
14317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(sendmsg, fd, msg, flags);
1432b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (fd >= 0)
1433b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov    FdRelease(thr, pc, fd);
14347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(sendmsg)(fd, msg, flags);
14357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
14367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
14377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
14387ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(long_t, recv, int fd, void *buf, long_t len, int flags) {
14397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(recv, fd, buf, len, flags);
14407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(recv)(fd, buf, len, flags);
1441b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (res >= 0 && fd >= 0) {
14423f4e6d9b75fb3f7f2674a31008738cfda9cda9edDmitry Vyukov    FdAcquire(thr, pc, fd);
14437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
14447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
14457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
14467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
14477ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(long_t, recvmsg, int fd, void *msg, int flags) {
14487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(recvmsg, fd, msg, flags);
14497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(recvmsg)(fd, msg, flags);
1450b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (res >= 0 && fd >= 0) {
14513f4e6d9b75fb3f7f2674a31008738cfda9cda9edDmitry Vyukov    FdAcquire(thr, pc, fd);
14527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
14537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
14547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
14557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
14567ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, unlink, char *path) {
14577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(unlink, path);
1458c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  Release(thr, pc, File2addr(path));
14597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(unlink)(path);
14607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
14617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
14627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
14637ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, fopen, char *path, char *mode) {
14647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(fopen, path, mode);
14657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  void *res = REAL(fopen)(path, mode);
1466c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  Acquire(thr, pc, File2addr(path));
1467c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  if (res) {
1468f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov    int fd = fileno_unlocked(res);
1469c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov    if (fd >= 0)
1470c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov      FdFileCreate(thr, pc, fd);
1471c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  }
1472c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  return res;
1473c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov}
1474c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov
1475c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry VyukovTSAN_INTERCEPTOR(void*, freopen, char *path, char *mode, void *stream) {
1476c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(freopen, path, mode, stream);
1477c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  if (stream) {
1478f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov    int fd = fileno_unlocked(stream);
1479c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov    if (fd >= 0)
1480c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov      FdClose(thr, pc, fd);
1481c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  }
1482c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  void *res = REAL(freopen)(path, mode, stream);
1483c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  Acquire(thr, pc, File2addr(path));
1484c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  if (res) {
1485f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov    int fd = fileno_unlocked(res);
1486c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov    if (fd >= 0)
1487c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov      FdFileCreate(thr, pc, fd);
1488c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  }
1489c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  return res;
1490c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov}
1491c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov
1492c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry VyukovTSAN_INTERCEPTOR(int, fclose, void *stream) {
1493f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov  {
1494f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov    SCOPED_TSAN_INTERCEPTOR(fclose, stream);
1495f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov    if (stream) {
1496f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov      int fd = fileno_unlocked(stream);
1497f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov      if (fd >= 0)
1498f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov        FdClose(thr, pc, fd);
1499f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov    }
1500c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  }
1501f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov  return REAL(fclose)(stream);
15027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
15037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
15047ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(uptr, fread, void *ptr, uptr size, uptr nmemb, void *f) {
1505f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov  {
1506f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov    SCOPED_TSAN_INTERCEPTOR(fread, ptr, size, nmemb, f);
1507f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov    MemoryAccessRange(thr, pc, (uptr)ptr, size * nmemb, true);
1508f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov  }
15097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return REAL(fread)(ptr, size, nmemb, f);
15107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
15117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
15127ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(uptr, fwrite, const void *p, uptr size, uptr nmemb, void *f) {
1513f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov  {
1514f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov    SCOPED_TSAN_INTERCEPTOR(fwrite, p, size, nmemb, f);
1515f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov    MemoryAccessRange(thr, pc, (uptr)p, size * nmemb, false);
1516f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov  }
15177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return REAL(fwrite)(p, size, nmemb, f);
15187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
15197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
15207ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, puts, const char *s) {
15217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(puts, s);
1522d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov  MemoryAccessRange(thr, pc, (uptr)s, internal_strlen(s), false);
15237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return REAL(puts)(s);
15247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
15257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
15267ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, rmdir, char *path) {
15277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(rmdir, path);
1528c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  Release(thr, pc, Dir2addr(path));
15297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(rmdir)(path);
15307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
15317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
15327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
15337ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, opendir, char *path) {
15347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(opendir, path);
15357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  void *res = REAL(opendir)(path);
1536c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  if (res != 0)
1537c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov    Acquire(thr, pc, Dir2addr(path));
15387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
15397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
15407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
15417ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, epoll_ctl, int epfd, int op, int fd, void *ev) {
15427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(epoll_ctl, epfd, op, fd, ev);
1543b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (op == EPOLL_CTL_ADD && epfd >= 0) {
15443f4e6d9b75fb3f7f2674a31008738cfda9cda9edDmitry Vyukov    FdRelease(thr, pc, epfd);
15457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
15467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(epoll_ctl)(epfd, op, fd, ev);
1547f5d4273457ca3d26e6cf658b266cd61062a65101Dmitry Vyukov  if (fd >= 0)
1548f5d4273457ca3d26e6cf658b266cd61062a65101Dmitry Vyukov    FdAccess(thr, pc, fd);
15497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
15507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
15517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
15527ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, epoll_wait, int epfd, void *ev, int cnt, int timeout) {
15537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(epoll_wait, epfd, ev, cnt, timeout);
1554ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  int res = BLOCK_REAL(epoll_wait)(epfd, ev, cnt, timeout);
1555b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (res > 0 && epfd >= 0) {
15563f4e6d9b75fb3f7f2674a31008738cfda9cda9edDmitry Vyukov    FdAcquire(thr, pc, epfd);
15577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
15587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
15597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
15607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1561ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry VyukovTSAN_INTERCEPTOR(int, poll, void *fds, long_t nfds, int timeout) {
1562ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(poll, fds, nfds, timeout);
1563ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  int res = BLOCK_REAL(poll)(fds, nfds, timeout);
1564ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  return res;
1565ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov}
1566ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov
1567d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukovstatic void ALWAYS_INLINE rtl_generic_sighandler(bool sigact, int sig,
1568d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov    my_siginfo_t *info, void *ctx) {
15697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ThreadState *thr = cur_thread();
1570e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  SignalContext *sctx = SigCtx(thr);
1571d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  // Don't mess with synchronous signals.
15721fc03d50a87302689482efa24b045a393097b6c3Dmitry Vyukov  if (sig == SIGSEGV || sig == SIGBUS || sig == SIGILL ||
15731fc03d50a87302689482efa24b045a393097b6c3Dmitry Vyukov      sig == SIGABRT || sig == SIGFPE || sig == SIGPIPE ||
1574ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov      // If we are sending signal to ourselves, we must process it now.
1575ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov      (sctx && sig == sctx->int_signal_send) ||
15760bf04eab1910cc8bf622c20ba08c339dc25e297eDmitry Vyukov      // If we are in blocking function, we can safely process it now
15770bf04eab1910cc8bf622c20ba08c339dc25e297eDmitry Vyukov      // (but check if we are in a recursive interceptor,
15780bf04eab1910cc8bf622c20ba08c339dc25e297eDmitry Vyukov      // i.e. pthread_join()->munmap()).
157980d46a2fbc0ae5086511a91119a6e28883b9f880Dmitry Vyukov      (sctx && sctx->in_blocking_func == 1 && thr->in_rtl == 1)) {
1580d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov    CHECK(thr->in_rtl == 0 || thr->in_rtl == 1);
1581d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov    int in_rtl = thr->in_rtl;
1582d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov    thr->in_rtl = 0;
1583d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov    CHECK_EQ(thr->in_signal_handler, false);
1584d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov    thr->in_signal_handler = true;
1585d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov    if (sigact)
1586d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov      sigactions[sig].sa_sigaction(sig, info, ctx);
1587d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov    else
1588d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov      sigactions[sig].sa_handler(sig);
1589d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov    CHECK_EQ(thr->in_signal_handler, true);
1590d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov    thr->in_signal_handler = false;
1591d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov    thr->in_rtl = in_rtl;
1592d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov    return;
1593d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  }
1594d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov
15951fc03d50a87302689482efa24b045a393097b6c3Dmitry Vyukov  if (sctx == 0)
15961fc03d50a87302689482efa24b045a393097b6c3Dmitry Vyukov    return;
1597e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  SignalDesc *signal = &sctx->pending_signals[sig];
15987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (signal->armed == false) {
15997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    signal->armed = true;
1600d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov    signal->sigaction = sigact;
1601d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov    if (info)
16026e4815579e5b48b48de092afcc3b092dfb97df5cDmitry Vyukov      internal_memcpy(&signal->siginfo, info, sizeof(*info));
1603a5562db12c5331433407ac21602086f34561c25cDmitry Vyukov    if (ctx)
16046e4815579e5b48b48de092afcc3b092dfb97df5cDmitry Vyukov      internal_memcpy(&signal->ctx, ctx, sizeof(signal->ctx));
1605e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov    sctx->pending_signal_count++;
16067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
16077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
16087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1609d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukovstatic void rtl_sighandler(int sig) {
1610d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  rtl_generic_sighandler(false, sig, 0, 0);
1611d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov}
1612d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov
16137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void rtl_sigaction(int sig, my_siginfo_t *info, void *ctx) {
1614d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  rtl_generic_sighandler(true, sig, info, ctx);
16157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
16167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
16177ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, sigaction, int sig, sigaction_t *act, sigaction_t *old) {
16187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(sigaction, sig, act, old);
1619d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  if (old)
16206e4815579e5b48b48de092afcc3b092dfb97df5cDmitry Vyukov    internal_memcpy(old, &sigactions[sig], sizeof(*old));
1621d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  if (act == 0)
1622d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov    return 0;
16236e4815579e5b48b48de092afcc3b092dfb97df5cDmitry Vyukov  internal_memcpy(&sigactions[sig], act, sizeof(*act));
16246e4815579e5b48b48de092afcc3b092dfb97df5cDmitry Vyukov  sigaction_t newact;
16256e4815579e5b48b48de092afcc3b092dfb97df5cDmitry Vyukov  internal_memcpy(&newact, act, sizeof(newact));
1626b4b9fa707324095e3590a57963fd754d7a4dd40eDmitry Vyukov  sigfillset(&newact.sa_mask);
1627d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  if (act->sa_handler != SIG_IGN && act->sa_handler != SIG_DFL) {
16287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    if (newact.sa_flags & SA_SIGINFO)
16297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      newact.sa_sigaction = rtl_sigaction;
16307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    else
16317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      newact.sa_handler = rtl_sighandler;
1632d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  }
1633d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  int res = REAL(sigaction)(sig, &newact, 0);
1634d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  return res;
1635d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov}
1636d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov
1637d91d06794506f10fb7599a2b835222fba29394e0Dmitry VyukovTSAN_INTERCEPTOR(sighandler_t, signal, int sig, sighandler_t h) {
16382135d8a7f4ba30fe35ed02d5e6ffd59a95b26219Alexey Samsonov  sigaction_t act;
1639d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  act.sa_handler = h;
164088207ab15125e2f1e9b3d541b735b2b8aba9b6d9Alexey Samsonov  REAL(memset)(&act.sa_mask, -1, sizeof(act.sa_mask));
1641d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  act.sa_flags = 0;
16422135d8a7f4ba30fe35ed02d5e6ffd59a95b26219Alexey Samsonov  sigaction_t old;
1643d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  int res = sigaction(sig, &act, &old);
1644d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  if (res)
1645d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov    return SIG_ERR;
1646d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  return old.sa_handler;
1647d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov}
1648d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov
1649d91d06794506f10fb7599a2b835222fba29394e0Dmitry VyukovTSAN_INTERCEPTOR(int, raise, int sig) {
1650d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(raise, sig);
1651e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  SignalContext *sctx = SigCtx(thr);
16521fc03d50a87302689482efa24b045a393097b6c3Dmitry Vyukov  CHECK_NE(sctx, 0);
1653e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  int prev = sctx->int_signal_send;
1654e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  sctx->int_signal_send = sig;
1655d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  int res = REAL(raise)(sig);
1656e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  CHECK_EQ(sctx->int_signal_send, sig);
1657e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  sctx->int_signal_send = prev;
1658d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  return res;
1659d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov}
1660d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov
1661d91d06794506f10fb7599a2b835222fba29394e0Dmitry VyukovTSAN_INTERCEPTOR(int, kill, int pid, int sig) {
1662d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(kill, pid, sig);
1663e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  SignalContext *sctx = SigCtx(thr);
16641fc03d50a87302689482efa24b045a393097b6c3Dmitry Vyukov  CHECK_NE(sctx, 0);
1665e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  int prev = sctx->int_signal_send;
1666d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  if (pid == GetPid()) {
1667e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov    sctx->int_signal_send = sig;
1668d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  }
1669d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  int res = REAL(kill)(pid, sig);
1670d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  if (pid == GetPid()) {
1671e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov    CHECK_EQ(sctx->int_signal_send, sig);
1672e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov    sctx->int_signal_send = prev;
1673d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  }
1674d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  return res;
1675d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov}
1676d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov
1677d91d06794506f10fb7599a2b835222fba29394e0Dmitry VyukovTSAN_INTERCEPTOR(int, pthread_kill, void *tid, int sig) {
1678d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(pthread_kill, tid, sig);
1679e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  SignalContext *sctx = SigCtx(thr);
16801fc03d50a87302689482efa24b045a393097b6c3Dmitry Vyukov  CHECK_NE(sctx, 0);
1681e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  int prev = sctx->int_signal_send;
1682d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  if (tid == pthread_self()) {
1683e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov    sctx->int_signal_send = sig;
1684d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  }
1685d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  int res = REAL(pthread_kill)(tid, sig);
1686d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  if (tid == pthread_self()) {
1687e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov    CHECK_EQ(sctx->int_signal_send, sig);
1688e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov    sctx->int_signal_send = prev;
16897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
16907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
16917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
16927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1693ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry VyukovTSAN_INTERCEPTOR(int, gettimeofday, void *tv, void *tz) {
1694ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(gettimeofday, tv, tz);
1695ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  // It's intercepted merely to process pending signals.
1696ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  return REAL(gettimeofday)(tv, tz);
1697ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov}
1698ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov
169992733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov// Linux kernel has a bug that leads to kernel deadlock if a process
170092733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov// maps TBs of memory and then calls mlock().
170192733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukovstatic void MlockIsUnsupported() {
170292733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov  static atomic_uint8_t printed;
170392733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov  if (atomic_exchange(&printed, 1, memory_order_relaxed))
170492733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov    return;
170592733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov  Printf("INFO: ThreadSanitizer ignores mlock/mlockall/munlock/munlockall\n");
170692733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov}
170792733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov
170892733f94292cd36795238e1a6ed0a99a1dc0454dDmitry VyukovTSAN_INTERCEPTOR(int, mlock, const void *addr, uptr len) {
170992733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov  MlockIsUnsupported();
171092733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov  return 0;
171192733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov}
171292733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov
171392733f94292cd36795238e1a6ed0a99a1dc0454dDmitry VyukovTSAN_INTERCEPTOR(int, munlock, const void *addr, uptr len) {
171492733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov  MlockIsUnsupported();
171592733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov  return 0;
171692733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov}
171792733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov
171892733f94292cd36795238e1a6ed0a99a1dc0454dDmitry VyukovTSAN_INTERCEPTOR(int, mlockall, int flags) {
171992733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov  MlockIsUnsupported();
172092733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov  return 0;
172192733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov}
172292733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov
172392733f94292cd36795238e1a6ed0a99a1dc0454dDmitry VyukovTSAN_INTERCEPTOR(int, munlockall, void) {
172492733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov  MlockIsUnsupported();
172592733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov  return 0;
172692733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov}
172792733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov
1728b75c67b495ca13801cc629b2c2c9dd0010e54739Dmitry VyukovTSAN_INTERCEPTOR(int, fork, int fake) {
1729b75c67b495ca13801cc629b2c2c9dd0010e54739Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(fork, fake);
17304554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov  // It's intercepted merely to process pending signals.
1731b75c67b495ca13801cc629b2c2c9dd0010e54739Dmitry Vyukov  int pid = REAL(fork)(fake);
17324554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov  if (pid == 0) {
17334554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov    // child
17344554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov    FdOnFork(thr, pc);
17354554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov  } else if (pid > 0) {
17364554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov    // parent
17374554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov  }
17384554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov  return pid;
17394554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov}
17404554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov
1741996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanovstruct TsanInterceptorContext {
1742996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  ThreadState *thr;
1743996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  const uptr caller_pc;
1744996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  const uptr pc;
1745996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov};
1746996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov
1747996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
1748996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov    MemoryAccessRange(((TsanInterceptorContext*)ctx)->thr,  \
1749996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov                      ((TsanInterceptorContext*)ctx)->pc,   \
1750996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov                      (uptr)ptr, size, true)
1751996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size)       \
1752996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov    MemoryAccessRange(((TsanInterceptorContext*)ctx)->thr,  \
1753996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov                      ((TsanInterceptorContext*)ctx)->pc,   \
1754996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov                      (uptr)ptr, size, false)
1755996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
1756996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov    SCOPED_TSAN_INTERCEPTOR(func, __VA_ARGS__) \
1757996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov    TsanInterceptorContext _ctx = {thr, caller_pc, pc}; \
175882a9080eaff95d69b270cd863e9df63e3b4e59adEvgeniy Stepanov    ctx = (void*)&_ctx; \
175982a9080eaff95d69b270cd863e9df63e3b4e59adEvgeniy Stepanov    (void)ctx;
1760996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
1761996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov    FdAcquire(((TsanInterceptorContext*)ctx)->thr, pc, fd)
1762996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
1763996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov    FdRelease(((TsanInterceptorContext*)ctx)->thr, pc, fd)
1764996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \
1765996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov    ThreadSetName(((TsanInterceptorContext*)ctx)->thr, name)
17664f32c0beaa83ffbb84db23d2e6205bee57c39ce1Evgeniy Stepanov#include "sanitizer_common/sanitizer_common_interceptors.inc"
1767c8033193376c3326478a345c4ae6633d4d2862c6Kostya Serebryany
1768ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukovnamespace __tsan {
1769ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov
1770ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukovvoid ProcessPendingSignals(ThreadState *thr) {
17717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK_EQ(thr->in_rtl, 0);
1772e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  SignalContext *sctx = SigCtx(thr);
17731fc03d50a87302689482efa24b045a393097b6c3Dmitry Vyukov  if (sctx == 0 || sctx->pending_signal_count == 0 || thr->in_signal_handler)
17747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
1775158c6ac3bb46753db217f9c2c73485811a3a1890Dmitry Vyukov  Context *ctx = CTX();
17767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->in_signal_handler = true;
1777e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  sctx->pending_signal_count = 0;
17787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // These are too big for stack.
17797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  static THREADLOCAL sigset_t emptyset, oldset;
17807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  sigfillset(&emptyset);
17817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  pthread_sigmask(SIG_SETMASK, &emptyset, &oldset);
17827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  for (int sig = 0; sig < kSigCount; sig++) {
1783e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov    SignalDesc *signal = &sctx->pending_signals[sig];
17847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    if (signal->armed) {
17857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      signal->armed = false;
1786d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov      if (sigactions[sig].sa_handler != SIG_DFL
1787d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov          && sigactions[sig].sa_handler != SIG_IGN) {
17887a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov        // Insure that the handler does not spoil errno.
17897a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov        const int saved_errno = errno;
17907a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov        errno = 0;
1791d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov        if (signal->sigaction)
1792a5562db12c5331433407ac21602086f34561c25cDmitry Vyukov          sigactions[sig].sa_sigaction(sig, &signal->siginfo, &signal->ctx);
1793d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov        else
1794d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov          sigactions[sig].sa_handler(sig);
17958a326776e41dc68c810ba3719a24328de517d8f9Dmitry Vyukov        if (flags()->report_bugs && errno != 0) {
17967a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov          ScopedInRtl in_rtl;
17974f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov          __tsan::StackTrace stack;
17987a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov          uptr pc = signal->sigaction ?
17997a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov              (uptr)sigactions[sig].sa_sigaction :
18007a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov              (uptr)sigactions[sig].sa_handler;
18017a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov          stack.Init(&pc, 1);
1802fb917e9069ea44f7103f50c658be84a8f66de56cDmitry Vyukov          Lock l(&ctx->thread_mtx);
18037a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov          ScopedReport rep(ReportTypeErrnoInSignal);
1804158c6ac3bb46753db217f9c2c73485811a3a1890Dmitry Vyukov          if (!IsFiredSuppression(ctx, rep, stack)) {
1805158c6ac3bb46753db217f9c2c73485811a3a1890Dmitry Vyukov            rep.AddStack(&stack);
1806158c6ac3bb46753db217f9c2c73485811a3a1890Dmitry Vyukov            OutputReport(ctx, rep, rep.GetReport()->stacks[0]);
1807158c6ac3bb46753db217f9c2c73485811a3a1890Dmitry Vyukov          }
18087a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov        }
18097a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov        errno = saved_errno;
1810d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov      }
18117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    }
18127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
18137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  pthread_sigmask(SIG_SETMASK, &oldset, 0);
18147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK_EQ(thr->in_signal_handler, true);
18157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->in_signal_handler = false;
18167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
18177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
181891ac008b435b879bb366bcf9516c53f2d07c30b1Dmitry Vyukovstatic void unreachable() {
181991ac008b435b879bb366bcf9516c53f2d07c30b1Dmitry Vyukov  Printf("FATAL: ThreadSanitizer: unreachable called\n");
182091ac008b435b879bb366bcf9516c53f2d07c30b1Dmitry Vyukov  Die();
182191ac008b435b879bb366bcf9516c53f2d07c30b1Dmitry Vyukov}
182291ac008b435b879bb366bcf9516c53f2d07c30b1Dmitry Vyukov
18237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid InitializeInterceptors() {
18247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK_GT(cur_thread()->in_rtl, 0);
18257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
18267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // We need to setup it early, because functions like dlsym() can call it.
1827065c4ac846589d04436cb7f19f938ff42035313eDmitry Vyukov  REAL(memset) = internal_memset;
1828065c4ac846589d04436cb7f19f938ff42035313eDmitry Vyukov  REAL(memcpy) = internal_memcpy;
1829065c4ac846589d04436cb7f19f938ff42035313eDmitry Vyukov  REAL(memcmp) = internal_memcmp;
18307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1831c8033193376c3326478a345c4ae6633d4d2862c6Kostya Serebryany  SANITIZER_COMMON_INTERCEPTORS_INIT;
1832c8033193376c3326478a345c4ae6633d4d2862c6Kostya Serebryany
1833f037f565b2e02878ceb6e7b49647e814e2990ef5Dmitry Vyukov  TSAN_INTERCEPT(longjmp);
1834f037f565b2e02878ceb6e7b49647e814e2990ef5Dmitry Vyukov  TSAN_INTERCEPT(siglongjmp);
1835f037f565b2e02878ceb6e7b49647e814e2990ef5Dmitry Vyukov
18367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(malloc);
183707ba8ef44deb54baa9307298fbffe25ddb30c362Dmitry Vyukov  TSAN_INTERCEPT(__libc_memalign);
18387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(calloc);
18397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(realloc);
18407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(free);
18417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(cfree);
18427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(mmap);
18437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(mmap64);
18447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(munmap);
18457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(memalign);
18467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(valloc);
18477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pvalloc);
18487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(posix_memalign);
18497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
18507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(strlen);
18517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(memset);
18527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(memcpy);
18537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(strcmp);
18547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(memchr);
18557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(memrchr);
18567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(memmove);
18577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(memcmp);
18587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(strchr);
18597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(strchrnul);
18607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(strrchr);
18617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(strncmp);
18627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(strcpy);  // NOLINT
18637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(strncpy);
18647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(strstr);
18657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
18667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_create);
18677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_join);
18687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_detach);
18697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
18707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_mutex_init);
18717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_mutex_destroy);
18727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_mutex_lock);
18737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_mutex_trylock);
18747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_mutex_timedlock);
18757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_mutex_unlock);
18767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
18777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_spin_init);
18787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_spin_destroy);
18797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_spin_lock);
18807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_spin_trylock);
18817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_spin_unlock);
18827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
18837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_rwlock_init);
18847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_rwlock_destroy);
18857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_rwlock_rdlock);
18867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_rwlock_tryrdlock);
18877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_rwlock_timedrdlock);
18887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_rwlock_wrlock);
18897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_rwlock_trywrlock);
18907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_rwlock_timedwrlock);
18917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_rwlock_unlock);
18927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1893c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  // TSAN_INTERCEPT(pthread_cond_init);
18947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_cond_destroy);
18957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_cond_signal);
18967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_cond_broadcast);
18977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_cond_wait);
18987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_cond_timedwait);
18997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
19007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_barrier_init);
19017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_barrier_destroy);
19027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_barrier_wait);
19037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
19047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_once);
19057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
19067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(sem_init);
19077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(sem_destroy);
19087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(sem_wait);
19097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(sem_trywait);
19107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(sem_timedwait);
19117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(sem_post);
19127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(sem_getvalue);
19137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
191461ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  TSAN_INTERCEPT(stat);
191561ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  TSAN_INTERCEPT(__xstat);
191661ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  TSAN_INTERCEPT(stat64);
191761ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  TSAN_INTERCEPT(__xstat64);
191861ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  TSAN_INTERCEPT(lstat);
191961ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  TSAN_INTERCEPT(__lxstat);
192061ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  TSAN_INTERCEPT(lstat64);
192161ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  TSAN_INTERCEPT(__lxstat64);
192261ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  TSAN_INTERCEPT(fstat);
192361ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  TSAN_INTERCEPT(__fxstat);
192461ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  TSAN_INTERCEPT(fstat64);
192561ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  TSAN_INTERCEPT(__fxstat64);
1926ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  TSAN_INTERCEPT(open);
1927c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  TSAN_INTERCEPT(open64);
1928ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  TSAN_INTERCEPT(creat);
1929c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  TSAN_INTERCEPT(creat64);
1930ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  TSAN_INTERCEPT(dup);
1931ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  TSAN_INTERCEPT(dup2);
1932ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  TSAN_INTERCEPT(dup3);
193368230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  TSAN_INTERCEPT(eventfd);
193445d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov  TSAN_INTERCEPT(signalfd);
193545d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov  TSAN_INTERCEPT(inotify_init);
193645d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov  TSAN_INTERCEPT(inotify_init1);
193768230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  TSAN_INTERCEPT(socket);
1938983518e360a179d92bdbddebe05a87db3c6cc3c0Dmitry Vyukov  TSAN_INTERCEPT(socketpair);
193968230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  TSAN_INTERCEPT(connect);
194052c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov  TSAN_INTERCEPT(bind);
194152c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov  TSAN_INTERCEPT(listen);
194268230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  TSAN_INTERCEPT(accept);
194368230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  TSAN_INTERCEPT(accept4);
194468230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  TSAN_INTERCEPT(epoll_create);
194568230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  TSAN_INTERCEPT(epoll_create1);
1946ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov  TSAN_INTERCEPT(close);
194703f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov  TSAN_INTERCEPT(__close);
194803f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov  TSAN_INTERCEPT(__res_iclose);
1949ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov  TSAN_INTERCEPT(pipe);
1950ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov  TSAN_INTERCEPT(pipe2);
1951ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov
19527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(readv);
19537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(preadv64);
19547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(writev);
19557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pwritev64);
19567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(send);
19577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(sendmsg);
19587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(recv);
19597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(recvmsg);
19607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
19617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(unlink);
19627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(fopen);
1963c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  TSAN_INTERCEPT(freopen);
1964c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  TSAN_INTERCEPT(fclose);
19657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(fread);
19667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(fwrite);
19677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(puts);
19687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(rmdir);
19697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(opendir);
19707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
19717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(epoll_ctl);
19727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(epoll_wait);
1973ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  TSAN_INTERCEPT(poll);
19747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
19757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(sigaction);
1976d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  TSAN_INTERCEPT(signal);
1977d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  TSAN_INTERCEPT(raise);
1978d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  TSAN_INTERCEPT(kill);
1979d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  TSAN_INTERCEPT(pthread_kill);
1980848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  TSAN_INTERCEPT(sleep);
1981848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  TSAN_INTERCEPT(usleep);
1982848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  TSAN_INTERCEPT(nanosleep);
1983aad173b2f1dae9f88bbffd217ebd46ed1f020bcbDmitry Vyukov  TSAN_INTERCEPT(gettimeofday);
19847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
198592733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov  TSAN_INTERCEPT(mlock);
198692733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov  TSAN_INTERCEPT(munlock);
198792733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov  TSAN_INTERCEPT(mlockall);
198892733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov  TSAN_INTERCEPT(munlockall);
198992733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov
19904554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov  TSAN_INTERCEPT(fork);
199131c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  TSAN_INTERCEPT(on_exit);
199231c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  TSAN_INTERCEPT(__cxa_atexit);
19934554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov
199491ac008b435b879bb366bcf9516c53f2d07c30b1Dmitry Vyukov  // Need to setup it, because interceptors check that the function is resolved.
199591ac008b435b879bb366bcf9516c53f2d07c30b1Dmitry Vyukov  // But atexit is emitted directly into the module, so can't be resolved.
199691ac008b435b879bb366bcf9516c53f2d07c30b1Dmitry Vyukov  REAL(atexit) = (int(*)(void(*)()))unreachable;
19977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  atexit_ctx = new(internal_alloc(MBlockAtExit, sizeof(AtExitContext)))
19987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      AtExitContext();
19997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
200031c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  if (REAL(__cxa_atexit)(&finalize, 0, 0)) {
2001b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov    Printf("ThreadSanitizer: failed to setup atexit callback\n");
20027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    Die();
20037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
20047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
20057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) {
2006b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov    Printf("ThreadSanitizer: failed to create thread key\n");
20077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    Die();
20087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
20093f4e6d9b75fb3f7f2674a31008738cfda9cda9edDmitry Vyukov
20103f4e6d9b75fb3f7f2674a31008738cfda9cda9edDmitry Vyukov  FdInit();
20117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
20127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
201326127735454fddae3495794f38189d57dde6510fDmitry Vyukovvoid internal_start_thread(void(*func)(void *arg), void *arg) {
201426127735454fddae3495794f38189d57dde6510fDmitry Vyukov  void *th;
201526127735454fddae3495794f38189d57dde6510fDmitry Vyukov  REAL(pthread_create)(&th, 0, (void*(*)(void *arg))func, arg);
201626127735454fddae3495794f38189d57dde6510fDmitry Vyukov  REAL(pthread_detach)(th);
201726127735454fddae3495794f38189d57dde6510fDmitry Vyukov}
201826127735454fddae3495794f38189d57dde6510fDmitry Vyukov
20197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}  // namespace __tsan
2020