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"
1847a0f6edc48eb6dc46b2e1f203d6783fd7e07505Alexey Samsonov#include "sanitizer_common/sanitizer_platform_limits_posix.h"
1947b1634df012507799eb39aa17d4022d748ba67bAlexey Samsonov#include "sanitizer_common/sanitizer_placement_new.h"
207eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov#include "sanitizer_common/sanitizer_stacktrace.h"
2136decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov#include "interception/interception.h"
227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_interface.h"
237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_platform.h"
244f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov#include "tsan_rtl.h"
257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_mman.h"
26c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov#include "tsan_fd.h"
277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyusing namespace __tsan;  // NOLINT
297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
30e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukovconst int kSigCount = 128;
31e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov
32e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukovstruct my_siginfo_t {
33e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  int opaque[128];
34e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov};
35e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov
367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystruct sigset_t {
37e294d09d45aa97d1d2c8ee237ee2ac225442d330Dmitry Vyukov  u64 val[1024 / 8 / sizeof(u64)];
387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany};
397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystruct ucontext_t {
41a5562db12c5331433407ac21602086f34561c25cDmitry Vyukov  uptr opaque[117];
427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany};
437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" int pthread_attr_init(void *attr);
457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" int pthread_attr_destroy(void *attr);
467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" int pthread_attr_getdetachstate(void *attr, int *v);
477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" int pthread_attr_setstacksize(void *attr, uptr stacksize);
487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" int pthread_attr_getstacksize(void *attr, uptr *stacksize);
497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" int pthread_key_create(unsigned *key, void (*destructor)(void* v));
507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" int pthread_setspecific(unsigned key, const void *v);
517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" int pthread_mutexattr_gettype(void *a, int *type);
527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" int pthread_yield();
537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset);
547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" int sigfillset(sigset_t *set);
557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void *pthread_self();
567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void _exit(int status);
577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" int *__errno_location();
58f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukovextern "C" int fileno_unlocked(void *stream);
5931c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukovextern "C" void *__libc_malloc(uptr size);
6031c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukovextern "C" void *__libc_calloc(uptr size, uptr n);
6131c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukovextern "C" void *__libc_realloc(void *ptr, uptr size);
6231c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukovextern "C" void __libc_free(void *ptr);
637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst int PTHREAD_MUTEX_RECURSIVE = 1;
647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst int PTHREAD_MUTEX_RECURSIVE_NP = 1;
657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst int kPthreadAttrSize = 56;
667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst int EINVAL = 22;
677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst int EBUSY = 16;
687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst int EPOLL_CTL_ADD = 1;
69d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukovconst int SIGILL = 4;
70d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukovconst int SIGABRT = 6;
71d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukovconst int SIGFPE = 8;
72d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukovconst int SIGSEGV = 11;
73d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukovconst int SIGPIPE = 13;
74d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukovconst int SIGBUS = 7;
757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid *const MAP_FAILED = (void*)-1;
767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst int PTHREAD_BARRIER_SERIAL_THREAD = -1;
777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst int MAP_FIXED = 0x10;
787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanytypedef long long_t;  // NOLINT
797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
800ce948e0887e2c23c6510c32a639da9730bbce25Alexander Potapenko// From /usr/include/unistd.h
810ce948e0887e2c23c6510c32a639da9730bbce25Alexander Potapenko# define F_ULOCK 0      /* Unlock a previously locked region.  */
820ce948e0887e2c23c6510c32a639da9730bbce25Alexander Potapenko# define F_LOCK  1      /* Lock a region for exclusive use.  */
830ce948e0887e2c23c6510c32a639da9730bbce25Alexander Potapenko# define F_TLOCK 2      /* Test and lock a region for exclusive use.  */
840ce948e0887e2c23c6510c32a639da9730bbce25Alexander Potapenko# define F_TEST  3      /* Test a region for other processes locks.  */
850ce948e0887e2c23c6510c32a639da9730bbce25Alexander Potapenko
867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanytypedef void (*sighandler_t)(int sig);
877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
887a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov#define errno (*__errno_location())
897a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov
907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystruct sigaction_t {
917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  union {
927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    sighandler_t sa_handler;
937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    void (*sa_sigaction)(int sig, my_siginfo_t *siginfo, void *uctx);
947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  };
957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  sigset_t sa_mask;
967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int sa_flags;
977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  void (*sa_restorer)();
987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany};
997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst sighandler_t SIG_DFL = (sighandler_t)0;
1017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst sighandler_t SIG_IGN = (sighandler_t)1;
102d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukovconst sighandler_t SIG_ERR = (sighandler_t)-1;
1037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst int SA_SIGINFO = 4;
1047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst int SIG_SETMASK = 2;
1057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1067eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonovnamespace std {
1077eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonovstruct nothrow_t {};
1087eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov}  // namespace std
1097eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov
1107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic sigaction_t sigactions[kSigCount];
1117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
112e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukovnamespace __tsan {
113e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukovstruct SignalDesc {
114e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  bool armed;
115e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  bool sigaction;
116e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  my_siginfo_t siginfo;
117e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  ucontext_t ctx;
118e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov};
119e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov
120e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukovstruct SignalContext {
121ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  int in_blocking_func;
122e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  int int_signal_send;
123e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  int pending_signal_count;
124e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  SignalDesc pending_signals[kSigCount];
125e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov};
126ba5e99668e3030cc5bab357a04271a1bdbac209cAlexey Samsonov}  // namespace __tsan
127e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov
128e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukovstatic SignalContext *SigCtx(ThreadState *thr) {
129e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  SignalContext *ctx = (SignalContext*)thr->signal_ctx;
1301fc03d50a87302689482efa24b045a393097b6c3Dmitry Vyukov  if (ctx == 0 && thr->is_alive) {
131e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov    ScopedInRtl in_rtl;
132c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov    ctx = (SignalContext*)MmapOrDie(sizeof(*ctx), "SignalContext");
133c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov    MemoryResetRange(thr, (uptr)&SigCtx, (uptr)ctx, sizeof(*ctx));
134e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov    thr->signal_ctx = ctx;
135e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  }
136e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  return ctx;
137e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov}
138e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov
1397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic unsigned g_thread_finalize_key;
1407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
14136decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukovclass ScopedInterceptor {
14236decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov public:
14336decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov  ScopedInterceptor(ThreadState *thr, const char *fname, uptr pc);
14436decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov  ~ScopedInterceptor();
14536decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov private:
14636decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov  ThreadState *const thr_;
14736decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov  const int in_rtl_;
14836decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov};
14936decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov
1504f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey SamsonovScopedInterceptor::ScopedInterceptor(ThreadState *thr, const char *fname,
1514f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov                                     uptr pc)
1524f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov    : thr_(thr)
1534f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov    , in_rtl_(thr->in_rtl) {
1544f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov  if (thr_->in_rtl == 0) {
1554f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov    Initialize(thr);
1564f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov    FuncEntry(thr, pc);
1574f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov    thr_->in_rtl++;
1584f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov    DPrintf("#%d: intercept %s()\n", thr_->tid, fname);
1594f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov  } else {
1604f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov    thr_->in_rtl++;
1617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
16205906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov}
16305906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov
1644f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey SamsonovScopedInterceptor::~ScopedInterceptor() {
1654f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov  thr_->in_rtl--;
1664f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov  if (thr_->in_rtl == 0) {
1674f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov    FuncExit(thr_);
168ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov    ProcessPendingSignals(thr_);
1694f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov  }
1704f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov  CHECK_EQ(in_rtl_, thr_->in_rtl);
17105906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov}
17205906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov
17336decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov#define SCOPED_INTERCEPTOR_RAW(func, ...) \
17436decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov    ThreadState *thr = cur_thread(); \
17536decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov    StatInc(thr, StatInterceptor); \
17636decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov    StatInc(thr, StatInt_##func); \
17736decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov    const uptr caller_pc = GET_CALLER_PC(); \
17836decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov    ScopedInterceptor si(thr, #func, caller_pc); \
179d2f08ffcb97726452f4ba11c199a1e06dc2a7e54Alexey Samsonov    const uptr pc = __sanitizer::StackTrace::GetPreviousInstructionPc( \
180d2f08ffcb97726452f4ba11c199a1e06dc2a7e54Alexey Samsonov        __sanitizer::StackTrace::GetCurrentPc()); \
18136decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov    (void)pc; \
18236decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov/**/
18336decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov
18436decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov#define SCOPED_TSAN_INTERCEPTOR(func, ...) \
18536decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov    SCOPED_INTERCEPTOR_RAW(func, __VA_ARGS__); \
18636decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov    if (REAL(func) == 0) { \
18736decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov      Printf("FATAL: ThreadSanitizer: failed to intercept %s\n", #func); \
18836decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov      Die(); \
18936decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov    } \
19036decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov    if (thr->in_rtl > 1) \
19136decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov      return REAL(func)(__VA_ARGS__); \
19236decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov/**/
19336decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov
19436decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov#define TSAN_INTERCEPTOR(ret, func, ...) INTERCEPTOR(ret, func, __VA_ARGS__)
19536decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov#define TSAN_INTERCEPT(func) INTERCEPT_FUNCTION(func)
19636decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov
197ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov#define BLOCK_REAL(name) (BlockingCall(thr), REAL(name))
198ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov
199ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukovstruct BlockingCall {
200b717f4d415cafbb8526bb33f737b9c07409a73bbAlexey Samsonov  explicit BlockingCall(ThreadState *thr)
201ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov      : ctx(SigCtx(thr)) {
202ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov    ctx->in_blocking_func++;
203ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  }
204ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov
205ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  ~BlockingCall() {
206ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov    ctx->in_blocking_func--;
207ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  }
208ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov
209ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  SignalContext *ctx;
210ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov};
211ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov
212848531192777acecf79747dc7c1ffeedf5c1da9fDmitry VyukovTSAN_INTERCEPTOR(unsigned, sleep, unsigned sec) {
213848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(sleep, sec);
214ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  unsigned res = BLOCK_REAL(sleep)(sec);
215848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  AfterSleep(thr, pc);
216848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  return res;
217848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov}
218848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov
219848531192777acecf79747dc7c1ffeedf5c1da9fDmitry VyukovTSAN_INTERCEPTOR(int, usleep, long_t usec) {
220848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(usleep, usec);
221ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  int res = BLOCK_REAL(usleep)(usec);
222848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  AfterSleep(thr, pc);
223848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  return res;
224848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov}
225848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov
226848531192777acecf79747dc7c1ffeedf5c1da9fDmitry VyukovTSAN_INTERCEPTOR(int, nanosleep, void *req, void *rem) {
227848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(nanosleep, req, rem);
228ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  int res = BLOCK_REAL(nanosleep)(req, rem);
229848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  AfterSleep(thr, pc);
230848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  return res;
231848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov}
232848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov
2337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyclass AtExitContext {
2347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany public:
2357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  AtExitContext()
2367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    : mtx_(MutexTypeAtExit, StatMtxAtExit)
2377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    , pos_() {
2387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
2397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  typedef void(*atexit_t)();
2417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
24231c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  int atexit(ThreadState *thr, uptr pc, bool is_on_exit,
24331c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov             atexit_t f, void *arg) {
2447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    Lock l(&mtx_);
2457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    if (pos_ == kMaxAtExit)
2467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      return 1;
2477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    Release(thr, pc, (uptr)this);
2487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    stack_[pos_] = f;
24931c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov    args_[pos_] = arg;
25031c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov    is_on_exits_[pos_] = is_on_exit;
2517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    pos_++;
2527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return 0;
2537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
2547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  void exit(ThreadState *thr, uptr pc) {
2567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    CHECK_EQ(thr->in_rtl, 0);
2577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    for (;;) {
2587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      atexit_t f = 0;
25931c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov      void *arg = 0;
26031c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov      bool is_on_exit = false;
2617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      {
2627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany        Lock l(&mtx_);
2637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany        if (pos_) {
2647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany          pos_--;
2657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany          f = stack_[pos_];
26631c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov          arg = args_[pos_];
26731c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov          is_on_exit = is_on_exits_[pos_];
2687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany          ScopedInRtl in_rtl;
2697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany          Acquire(thr, pc, (uptr)this);
2707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany        }
2717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      }
2727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      if (f == 0)
2737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany        break;
2747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      DPrintf("#%d: executing atexit func %p\n", thr->tid, f);
2757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      CHECK_EQ(thr->in_rtl, 0);
27631c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov      if (is_on_exit)
27731c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov        ((void(*)(int status, void *arg))f)(0, arg);
27831c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov      else
27931c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov        ((void(*)(void *arg, void *dso))f)(arg, 0);
2807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    }
2817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
2827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany private:
2847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  static const int kMaxAtExit = 128;
2857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Mutex mtx_;
2867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  atexit_t stack_[kMaxAtExit];
28731c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  void *args_[kMaxAtExit];
28831c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  bool is_on_exits_[kMaxAtExit];
2897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int pos_;
2907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany};
2917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic AtExitContext *atexit_ctx;
2937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void finalize(void *arg) {
2957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ThreadState * thr = cur_thread();
2967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  uptr pc = 0;
2977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  atexit_ctx->exit(thr, pc);
2987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int status = Finalize(cur_thread());
299b7b6b1cd9df0c954b1f890fcebf373db984923b3Dmitry Vyukov  if (status)
300b7b6b1cd9df0c954b1f890fcebf373db984923b3Dmitry Vyukov    _exit(status);
3017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3037ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, atexit, void (*f)()) {
30431c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  if (cur_thread()->in_symbolizer)
30531c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov    return 0;
3067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(atexit, f);
30731c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  return atexit_ctx->atexit(thr, pc, false, (void(*)())f, 0);
30831c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov}
30931c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov
31031c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry VyukovTSAN_INTERCEPTOR(int, on_exit, void(*f)(int, void*), void *arg) {
31131c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  if (cur_thread()->in_symbolizer)
31231c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov    return 0;
31331c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(on_exit, f, arg);
31431c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  return atexit_ctx->atexit(thr, pc, true, (void(*)())f, arg);
31531c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov}
31631c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov
31731c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry VyukovTSAN_INTERCEPTOR(int, __cxa_atexit, void (*f)(void *a), void *arg, void *dso) {
31831c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  if (cur_thread()->in_symbolizer)
31931c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov    return 0;
32031c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(__cxa_atexit, f, arg, dso);
32131c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  if (dso)
32231c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov    return REAL(__cxa_atexit)(f, arg, dso);
32331c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  return atexit_ctx->atexit(thr, pc, false, (void(*)())f, arg);
3247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
326f037f565b2e02878ceb6e7b49647e814e2990ef5Dmitry VyukovTSAN_INTERCEPTOR(void, longjmp, void *env, int val) {
327f037f565b2e02878ceb6e7b49647e814e2990ef5Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(longjmp, env, val);
328b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov  Printf("ThreadSanitizer: longjmp() is not supported\n");
329f037f565b2e02878ceb6e7b49647e814e2990ef5Dmitry Vyukov  Die();
330f037f565b2e02878ceb6e7b49647e814e2990ef5Dmitry Vyukov}
331f037f565b2e02878ceb6e7b49647e814e2990ef5Dmitry Vyukov
332f037f565b2e02878ceb6e7b49647e814e2990ef5Dmitry VyukovTSAN_INTERCEPTOR(void, siglongjmp, void *env, int val) {
333f037f565b2e02878ceb6e7b49647e814e2990ef5Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(siglongjmp, env, val);
334b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov  Printf("ThreadSanitizer: siglongjmp() is not supported\n");
335f037f565b2e02878ceb6e7b49647e814e2990ef5Dmitry Vyukov  Die();
336f037f565b2e02878ceb6e7b49647e814e2990ef5Dmitry Vyukov}
337f037f565b2e02878ceb6e7b49647e814e2990ef5Dmitry Vyukov
3387ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, malloc, uptr size) {
33931c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  if (cur_thread()->in_symbolizer)
34031c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov    return __libc_malloc(size);
34105906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov  void *p = 0;
34205906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov  {
34305906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov    SCOPED_INTERCEPTOR_RAW(malloc, size);
34405906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov    p = user_alloc(thr, pc, size);
34505906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov  }
34605906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov  invoke_malloc_hook(p, size);
34705906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov  return p;
3487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
35007ba8ef44deb54baa9307298fbffe25ddb30c362Dmitry VyukovTSAN_INTERCEPTOR(void*, __libc_memalign, uptr align, uptr sz) {
35107ba8ef44deb54baa9307298fbffe25ddb30c362Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(__libc_memalign, align, sz);
352543b94a5cd102c0795b44d78234d5458eed2c75eDmitry Vyukov  return user_alloc(thr, pc, sz, align);
35307ba8ef44deb54baa9307298fbffe25ddb30c362Dmitry Vyukov}
35407ba8ef44deb54baa9307298fbffe25ddb30c362Dmitry Vyukov
3557ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, calloc, uptr size, uptr n) {
35631c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  if (cur_thread()->in_symbolizer)
35731c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov    return __libc_calloc(size, n);
35865199f1b253c4bfb225805629217acb8f0b1e185Kostya Serebryany  if (__sanitizer::CallocShouldReturnNullDueToOverflow(size, n)) return 0;
35905906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov  void *p = 0;
36005906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov  {
36105906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov    SCOPED_INTERCEPTOR_RAW(calloc, size, n);
36205906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov    p = user_alloc(thr, pc, n * size);
3630ce948e0887e2c23c6510c32a639da9730bbce25Alexander Potapenko    if (p) internal_memset(p, 0, n * size);
36405906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov  }
36505906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov  invoke_malloc_hook(p, n * size);
3667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return p;
3677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3697ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, realloc, void *p, uptr size) {
37031c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  if (cur_thread()->in_symbolizer)
37131c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov    return __libc_realloc(p, size);
37205906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov  if (p)
37305906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov    invoke_free_hook(p);
37405906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov  {
37505906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov    SCOPED_INTERCEPTOR_RAW(realloc, p, size);
37605906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov    p = user_realloc(thr, pc, p, size);
37705906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov  }
37805906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov  invoke_malloc_hook(p, size);
37905906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov  return p;
3807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3827ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void, free, void *p) {
3837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (p == 0)
3847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
38531c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  if (cur_thread()->in_symbolizer)
38631c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov    return __libc_free(p);
38705906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov  invoke_free_hook(p);
3887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_INTERCEPTOR_RAW(free, p);
3897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  user_free(thr, pc, p);
3907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3927ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void, cfree, void *p) {
3937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (p == 0)
3947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
39531c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  if (cur_thread()->in_symbolizer)
39631c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov    return __libc_free(p);
39705906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov  invoke_free_hook(p);
3987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_INTERCEPTOR_RAW(cfree, p);
3997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  user_free(thr, pc, p);
4007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
4017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
4028a6b5e551ab8a331f7e7bc4bfcd74926fbffa3f6Alexey SamsonovTSAN_INTERCEPTOR(uptr, malloc_usable_size, void *p) {
4038a6b5e551ab8a331f7e7bc4bfcd74926fbffa3f6Alexey Samsonov  SCOPED_INTERCEPTOR_RAW(malloc_usable_size, p);
4048a6b5e551ab8a331f7e7bc4bfcd74926fbffa3f6Alexey Samsonov  return user_alloc_usable_size(thr, pc, p);
4058a6b5e551ab8a331f7e7bc4bfcd74926fbffa3f6Alexey Samsonov}
4068a6b5e551ab8a331f7e7bc4bfcd74926fbffa3f6Alexey Samsonov
4077eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov#define OPERATOR_NEW_BODY(mangled_name) \
40831c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  if (cur_thread()->in_symbolizer) \
40931c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov    return __libc_malloc(size); \
4107eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov  void *p = 0; \
4117eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov  {  \
4127eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov    SCOPED_INTERCEPTOR_RAW(mangled_name, size); \
4137eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov    p = user_alloc(thr, pc, size); \
4147eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov  }  \
4157eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov  invoke_malloc_hook(p, size);  \
4167eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov  return p;
4177eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov
4187eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonovvoid *operator new(__sanitizer::uptr size) {
4197eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov  OPERATOR_NEW_BODY(_Znwm);
4207eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov}
4217eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonovvoid *operator new[](__sanitizer::uptr size) {
4227eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov  OPERATOR_NEW_BODY(_Znam);
4237eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov}
4247eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonovvoid *operator new(__sanitizer::uptr size, std::nothrow_t const&) {
4257eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov  OPERATOR_NEW_BODY(_ZnwmRKSt9nothrow_t);
4267eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov}
4277eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonovvoid *operator new[](__sanitizer::uptr size, std::nothrow_t const&) {
4287eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov  OPERATOR_NEW_BODY(_ZnamRKSt9nothrow_t);
4297eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov}
4307eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov
4317eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov#define OPERATOR_DELETE_BODY(mangled_name) \
4327eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov  if (ptr == 0) return;  \
43331c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  if (cur_thread()->in_symbolizer) \
43431c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov    return __libc_free(ptr); \
4357eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov  invoke_free_hook(ptr);  \
4367eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov  SCOPED_INTERCEPTOR_RAW(mangled_name, ptr);  \
4377eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov  user_free(thr, pc, ptr);
4387eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov
4397eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonovvoid operator delete(void *ptr) {
4407eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov  OPERATOR_DELETE_BODY(_ZdlPv);
4417eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov}
4427eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonovvoid operator delete[](void *ptr) {
4437eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov  OPERATOR_DELETE_BODY(_ZdlPvRKSt9nothrow_t);
4447eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov}
4457eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonovvoid operator delete(void *ptr, std::nothrow_t const&) {
4467eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov  OPERATOR_DELETE_BODY(_ZdaPv);
4477eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov}
4487eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonovvoid operator delete[](void *ptr, std::nothrow_t const&) {
4497eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov  OPERATOR_DELETE_BODY(_ZdaPvRKSt9nothrow_t);
4507eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov}
4517eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov
452d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry VyukovTSAN_INTERCEPTOR(uptr, strlen, const char *s) {
4537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(strlen, s);
454d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov  uptr len = internal_strlen(s);
4557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)s, len + 1, false);
4567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return len;
4577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
4587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
459065c4ac846589d04436cb7f19f938ff42035313eDmitry VyukovTSAN_INTERCEPTOR(void*, memset, void *dst, int v, uptr size) {
460065c4ac846589d04436cb7f19f938ff42035313eDmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(memset, dst, v, size);
4617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)dst, size, true);
462065c4ac846589d04436cb7f19f938ff42035313eDmitry Vyukov  return internal_memset(dst, v, size);
4637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
4647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
465065c4ac846589d04436cb7f19f938ff42035313eDmitry VyukovTSAN_INTERCEPTOR(void*, memcpy, void *dst, const void *src, uptr size) {
466065c4ac846589d04436cb7f19f938ff42035313eDmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(memcpy, dst, src, size);
4677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)dst, size, true);
4687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)src, size, false);
469065c4ac846589d04436cb7f19f938ff42035313eDmitry Vyukov  return internal_memcpy(dst, src, size);
4707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
4717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
472065c4ac846589d04436cb7f19f938ff42035313eDmitry VyukovTSAN_INTERCEPTOR(int, memcmp, const void *s1, const void *s2, uptr n) {
473065c4ac846589d04436cb7f19f938ff42035313eDmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(memcmp, s1, s2, n);
474d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov  int res = 0;
475d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov  uptr len = 0;
476d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov  for (; len < n; len++) {
477d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov    if ((res = ((unsigned char*)s1)[len] - ((unsigned char*)s2)[len]))
478d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov      break;
479d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov  }
480d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov  MemoryAccessRange(thr, pc, (uptr)s1, len < n ? len + 1 : n, false);
481d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov  MemoryAccessRange(thr, pc, (uptr)s2, len < n ? len + 1 : n, false);
482d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov  return res;
483d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov}
484d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov
4857ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, strcmp, const char *s1, const char *s2) {
4867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(strcmp, s1, s2);
4877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  uptr len = 0;
4887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  for (; s1[len] && s2[len]; len++) {
4897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    if (s1[len] != s2[len])
4907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      break;
4917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
4927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)s1, len + 1, false);
4937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)s2, len + 1, false);
4947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return s1[len] - s2[len];
4957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
4967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
4977ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr n) {
4987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(strncmp, s1, s2, n);
4997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  uptr len = 0;
5007d38634b30beed9bed44dfa6cb8e977ec51d7c6cDmitry Vyukov  for (; len < n && s1[len] && s2[len]; len++) {
5017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    if (s1[len] != s2[len])
5027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      break;
5037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
5047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)s1, len < n ? len + 1 : n, false);
5057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)s2, len < n ? len + 1 : n, false);
5067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return len == n ? 0 : s1[len] - s2[len];
5077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5097ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, memchr, void *s, int c, uptr n) {
5107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(memchr, s, c, n);
5117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  void *res = REAL(memchr)(s, c, n);
5127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  uptr len = res ? (char*)res - (char*)s + 1 : n;
5137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)s, len, false);
5147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
5157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5177ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, memrchr, char *s, int c, uptr n) {
5187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(memrchr, s, c, n);
5197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)s, n, false);
5207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return REAL(memrchr)(s, c, n);
5217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5237ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, memmove, void *dst, void *src, uptr n) {
5247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(memmove, dst, src, n);
5257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)dst, n, true);
5267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)src, n, false);
5277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return REAL(memmove)(dst, src, n);
5287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
530d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry VyukovTSAN_INTERCEPTOR(char*, strchr, char *s, int c) {
5317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(strchr, s, c);
532d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov  char *res = REAL(strchr)(s, c);
533d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov  uptr len = res ? (char*)res - (char*)s + 1 : internal_strlen(s) + 1;
5347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)s, len, false);
5357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
5367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
538d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry VyukovTSAN_INTERCEPTOR(char*, strchrnul, char *s, int c) {
5397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(strchrnul, s, c);
540d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov  char *res = REAL(strchrnul)(s, c);
5417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  uptr len = (char*)res - (char*)s + 1;
5427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)s, len, false);
5437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
5447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
546d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry VyukovTSAN_INTERCEPTOR(char*, strrchr, char *s, int c) {
5477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(strrchr, s, c);
548d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov  MemoryAccessRange(thr, pc, (uptr)s, internal_strlen(s) + 1, false);
5497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return REAL(strrchr)(s, c);
5507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
552d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry VyukovTSAN_INTERCEPTOR(char*, strcpy, char *dst, const char *src) {  // NOLINT
5537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(strcpy, dst, src);  // NOLINT
554d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov  uptr srclen = internal_strlen(src);
5557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)dst, srclen + 1, true);
5567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)src, srclen + 1, false);
5577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return REAL(strcpy)(dst, src);  // NOLINT
5587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
560d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry VyukovTSAN_INTERCEPTOR(char*, strncpy, char *dst, char *src, uptr n) {
5617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(strncpy, dst, src, n);
562b93c3d5badc4066120edf3ed1c515cdd516a8776Kostya Serebryany  uptr srclen = internal_strnlen(src, n);
5637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)dst, n, true);
5647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)src, min(srclen + 1, n), false);
5657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return REAL(strncpy)(dst, src, n);
5667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5687ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(const char*, strstr, const char *s1, const char *s2) {
5697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(strstr, s1, s2);
5707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  const char *res = REAL(strstr)(s1, s2);
571d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov  uptr len1 = internal_strlen(s1);
572d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov  uptr len2 = internal_strlen(s2);
5737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)s1, len1 + 1, false);
5747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, (uptr)s2, len2 + 1, false);
5757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
5767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic bool fix_mmap_addr(void **addr, long_t sz, int flags) {
5797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (*addr) {
5807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    if (!IsAppMem((uptr)*addr) || !IsAppMem((uptr)*addr + sz - 1)) {
5817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      if (flags & MAP_FIXED) {
5827a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov        errno = EINVAL;
5837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany        return false;
5847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      } else {
5857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany        *addr = 0;
5867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      }
5877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    }
5887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
5897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return true;
5907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5927ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, mmap, void *addr, long_t sz, int prot,
5937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany                         int flags, int fd, unsigned off) {
5947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(mmap, addr, sz, prot, flags, fd, off);
5957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (!fix_mmap_addr(&addr, sz, flags))
5967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return MAP_FAILED;
5977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  void *res = REAL(mmap)(addr, sz, prot, flags, fd, off);
5987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res != MAP_FAILED) {
599c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov    if (fd > 0)
600c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov      FdAccess(thr, pc, fd);
60174172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    MemoryRangeImitateWrite(thr, pc, (uptr)res, sz);
6027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
6037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
6047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
6057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6067ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, mmap64, void *addr, long_t sz, int prot,
6077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany                           int flags, int fd, u64 off) {
6087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(mmap64, addr, sz, prot, flags, fd, off);
6097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (!fix_mmap_addr(&addr, sz, flags))
6107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return MAP_FAILED;
6117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  void *res = REAL(mmap64)(addr, sz, prot, flags, fd, off);
6127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res != MAP_FAILED) {
613c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov    if (fd > 0)
614c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov      FdAccess(thr, pc, fd);
61574172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    MemoryRangeImitateWrite(thr, pc, (uptr)res, sz);
6167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
6177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
6187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
6197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6207ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, munmap, void *addr, long_t sz) {
6217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(munmap, addr, sz);
6227ac33ac529ff93a57419f5ddf71b1fde68428577Dmitry Vyukov  DontNeedShadowFor((uptr)addr, sz);
6237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(munmap)(addr, sz);
6247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
6257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
6267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6277ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, memalign, uptr align, uptr sz) {
6287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(memalign, align, sz);
6292e87051d136db3150a3ca322d8862f92b0a684bbDmitry Vyukov  return user_alloc(thr, pc, sz, align);
6307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
6317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6327ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, valloc, uptr sz) {
6337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(valloc, sz);
634f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany  return user_alloc(thr, pc, sz, GetPageSizeCached());
6357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
6367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6377ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, pvalloc, uptr sz) {
6387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pvalloc, sz);
639f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany  sz = RoundUp(sz, GetPageSizeCached());
640f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany  return user_alloc(thr, pc, sz, GetPageSizeCached());
6417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
6427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6437ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, posix_memalign, void **memptr, uptr align, uptr sz) {
6447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(posix_memalign, memptr, align, sz);
6452e87051d136db3150a3ca322d8862f92b0a684bbDmitry Vyukov  *memptr = user_alloc(thr, pc, sz, align);
6467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return 0;
6477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
6487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// Used in thread-safe function static initialization.
6501ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukovextern "C" int INTERFACE_ATTRIBUTE __cxa_guard_acquire(atomic_uint32_t *g) {
6511ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov  SCOPED_INTERCEPTOR_RAW(__cxa_guard_acquire, g);
6521ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov  for (;;) {
6531ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov    u32 cmp = atomic_load(g, memory_order_acquire);
6541ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov    if (cmp == 0) {
6551ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov      if (atomic_compare_exchange_strong(g, &cmp, 1<<16, memory_order_relaxed))
6561ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov        return 1;
6571ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov    } else if (cmp == 1) {
6581ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov      Acquire(thr, pc, (uptr)g);
6591ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov      return 0;
6601ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov    } else {
6611ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov      internal_sched_yield();
6621ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov    }
6637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
6647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
6657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6661ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukovextern "C" void INTERFACE_ATTRIBUTE __cxa_guard_release(atomic_uint32_t *g) {
6671ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov  SCOPED_INTERCEPTOR_RAW(__cxa_guard_release, g);
6681ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov  Release(thr, pc, (uptr)g);
6691ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov  atomic_store(g, 1, memory_order_release);
6701ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov}
6711ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov
6721ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukovextern "C" void INTERFACE_ATTRIBUTE __cxa_guard_abort(atomic_uint32_t *g) {
6731ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov  SCOPED_INTERCEPTOR_RAW(__cxa_guard_abort, g);
6741ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov  atomic_store(g, 0, memory_order_relaxed);
6757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
6767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void thread_finalize(void *v) {
6787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  uptr iter = (uptr)v;
6797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (iter > 1) {
6807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    if (pthread_setspecific(g_thread_finalize_key, (void*)(iter - 1))) {
681b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov      Printf("ThreadSanitizer: failed to set thread key\n");
6827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      Die();
6837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    }
6847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
6857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
6867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  {
6877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    ScopedInRtl in_rtl;
688e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov    ThreadState *thr = cur_thread();
689e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov    ThreadFinish(thr);
6901fc03d50a87302689482efa24b045a393097b6c3Dmitry Vyukov    SignalContext *sctx = thr->signal_ctx;
6911fc03d50a87302689482efa24b045a393097b6c3Dmitry Vyukov    if (sctx) {
6921fc03d50a87302689482efa24b045a393097b6c3Dmitry Vyukov      thr->signal_ctx = 0;
693c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov      UnmapOrDie(sctx, sizeof(*sctx));
6941fc03d50a87302689482efa24b045a393097b6c3Dmitry Vyukov    }
6957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
6967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
6977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystruct ThreadParam {
7007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  void* (*callback)(void *arg);
7017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  void *param;
7027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  atomic_uintptr_t tid;
7037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany};
7047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
7057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void *__tsan_thread_start_func(void *arg) {
7067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ThreadParam *p = (ThreadParam*)arg;
7077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  void* (*callback)(void *arg) = p->callback;
7087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  void *param = p->param;
7097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int tid = 0;
7107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  {
7117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    ThreadState *thr = cur_thread();
7127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    ScopedInRtl in_rtl;
7137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    if (pthread_setspecific(g_thread_finalize_key, (void*)4)) {
714b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov      Printf("ThreadSanitizer: failed to set thread key\n");
7157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      Die();
7167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    }
7177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    while ((tid = atomic_load(&p->tid, memory_order_acquire)) == 0)
7187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      pthread_yield();
7197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    atomic_store(&p->tid, 0, memory_order_release);
7207dccf3f92a867f917ad19f9a6b37bcf93e64b35bDmitry Vyukov    ThreadStart(thr, tid, GetTid());
7217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    CHECK_EQ(thr->in_rtl, 1);
7227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
7237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  void *res = callback(param);
7247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // Prevent the callback from being tail called,
7257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // it mixes up stack traces.
7267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  volatile int foo = 42;
7277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  foo++;
7287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
7297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
7307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
7317ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_create,
7327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    void *th, void *attr, void *(*callback)(void*), void * param) {
7337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_create, th, attr, callback, param);
734f110e356170fbe990b99c0939d77eeaa89b25497Alexey Samsonov  __sanitizer_pthread_attr_t myattr;
7357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (attr == 0) {
7367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    pthread_attr_init(&myattr);
7377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    attr = &myattr;
7387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
7397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int detached = 0;
7407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  pthread_attr_getdetachstate(attr, &detached);
7417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  uptr stacksize = 0;
7427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  pthread_attr_getstacksize(attr, &stacksize);
7437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // We place the huge ThreadState object into TLS, account for that.
7447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  const uptr minstacksize = GetTlsSize() + 128*1024;
7457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (stacksize < minstacksize) {
746e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov    DPrintf("ThreadSanitizer: stacksize %zu->%zu\n", stacksize, minstacksize);
7477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    pthread_attr_setstacksize(attr, minstacksize);
7487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
7497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ThreadParam p;
7507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  p.callback = callback;
7517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  p.param = param;
7527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  atomic_store(&p.tid, 0, memory_order_relaxed);
7537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_create)(th, attr, __tsan_thread_start_func, &p);
7547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
75564310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    int tid = ThreadCreate(thr, pc, *(uptr*)th, detached);
7567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    CHECK_NE(tid, 0);
7577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    atomic_store(&p.tid, tid, memory_order_release);
7587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    while (atomic_load(&p.tid, memory_order_acquire) != 0)
7597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      pthread_yield();
7607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
7617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (attr == &myattr)
7627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    pthread_attr_destroy(&myattr);
7637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
7647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
7657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
7667ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_join, void *th, void **ret) {
7677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_join, th, ret);
7687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int tid = ThreadTid(thr, pc, (uptr)th);
769ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  int res = BLOCK_REAL(pthread_join)(th, ret);
7707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
77164310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    ThreadJoin(thr, pc, tid);
7727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
7737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
7747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
7757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
7767ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_detach, void *th) {
7777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_detach, th);
7787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int tid = ThreadTid(thr, pc, (uptr)th);
7797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_detach)(th);
7807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
78164310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    ThreadDetach(thr, pc, tid);
7827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
7837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
7847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
7857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
7867ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_mutex_init, void *m, void *a) {
7877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_mutex_init, m, a);
7887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_mutex_init)(m, a);
7897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
7907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    bool recursive = false;
7917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    if (a) {
7927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      int type = 0;
7937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      if (pthread_mutexattr_gettype(a, &type) == 0)
7947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany        recursive = (type == PTHREAD_MUTEX_RECURSIVE
7957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany            || type == PTHREAD_MUTEX_RECURSIVE_NP);
7967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    }
797c20e9ba760a93706c9160133cdcce62194f9694fDmitry Vyukov    MutexCreate(thr, pc, (uptr)m, false, recursive, false);
7987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
7997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
8007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
8017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
8027ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_mutex_destroy, void *m) {
8037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_mutex_destroy, m);
8047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_mutex_destroy)(m);
8057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0 || res == EBUSY) {
80664310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    MutexDestroy(thr, pc, (uptr)m);
8077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
8087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
8097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
8107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
8117ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_mutex_lock, void *m) {
8127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_mutex_lock, m);
8137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_mutex_lock)(m);
8147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
81564310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    MutexLock(thr, pc, (uptr)m);
8167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
8177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
8187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
8197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
8207ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_mutex_trylock, void *m) {
8217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_mutex_trylock, m);
8227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_mutex_trylock)(m);
8237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
82464310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    MutexLock(thr, pc, (uptr)m);
8257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
8267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
8277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
8287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
8297ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_mutex_timedlock, void *m, void *abstime) {
8307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_mutex_timedlock, m, abstime);
8317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_mutex_timedlock)(m, abstime);
8327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
83364310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    MutexLock(thr, pc, (uptr)m);
8347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
8357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
8367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
8377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
8387ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_mutex_unlock, void *m) {
8397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_mutex_unlock, m);
84064310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov  MutexUnlock(thr, pc, (uptr)m);
8417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_mutex_unlock)(m);
8427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
8437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
8447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
8457ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_spin_init, void *m, int pshared) {
8467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_spin_init, m, pshared);
8477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_spin_init)(m, pshared);
8487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
849c20e9ba760a93706c9160133cdcce62194f9694fDmitry Vyukov    MutexCreate(thr, pc, (uptr)m, false, false, false);
8507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
8517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
8527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
8537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
8547ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_spin_destroy, void *m) {
8557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_spin_destroy, m);
8567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_spin_destroy)(m);
8577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
85864310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    MutexDestroy(thr, pc, (uptr)m);
8597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
8607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
8617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
8627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
8637ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_spin_lock, void *m) {
8647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_spin_lock, m);
8657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_spin_lock)(m);
8667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
86764310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    MutexLock(thr, pc, (uptr)m);
8687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
8697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
8707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
8717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
8727ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_spin_trylock, void *m) {
8737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_spin_trylock, m);
8747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_spin_trylock)(m);
8757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
87664310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    MutexLock(thr, pc, (uptr)m);
8777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
8787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
8797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
8807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
8817ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_spin_unlock, void *m) {
8827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_spin_unlock, m);
88364310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov  MutexUnlock(thr, pc, (uptr)m);
8847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_spin_unlock)(m);
8857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
8867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
8877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
8887ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_rwlock_init, void *m, void *a) {
8897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_init, m, a);
8907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_rwlock_init)(m, a);
8917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
892c20e9ba760a93706c9160133cdcce62194f9694fDmitry Vyukov    MutexCreate(thr, pc, (uptr)m, true, false, false);
8937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
8947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
8957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
8967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
8977ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_rwlock_destroy, void *m) {
8987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_destroy, m);
8997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_rwlock_destroy)(m);
9007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
90164310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    MutexDestroy(thr, pc, (uptr)m);
9027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
9037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
9047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
9057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
9067ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_rwlock_rdlock, void *m) {
9077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_rdlock, m);
9087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_rwlock_rdlock)(m);
9097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
91064310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    MutexReadLock(thr, pc, (uptr)m);
9117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
9127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
9137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
9147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
9157ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_rwlock_tryrdlock, void *m) {
9167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_tryrdlock, m);
9177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_rwlock_tryrdlock)(m);
9187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
91964310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    MutexReadLock(thr, pc, (uptr)m);
9207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
9217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
9227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
9237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
9247ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_rwlock_timedrdlock, void *m, void *abstime) {
9257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_timedrdlock, m, abstime);
9267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_rwlock_timedrdlock)(m, abstime);
9277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
92864310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    MutexReadLock(thr, pc, (uptr)m);
9297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
9307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
9317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
9327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
9337ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_rwlock_wrlock, void *m) {
9347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_wrlock, m);
9357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_rwlock_wrlock)(m);
9367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
93764310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    MutexLock(thr, pc, (uptr)m);
9387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
9397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
9407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
9417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
9427ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_rwlock_trywrlock, void *m) {
9437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_trywrlock, m);
9447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_rwlock_trywrlock)(m);
9457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
94664310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    MutexLock(thr, pc, (uptr)m);
9477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
9487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
9497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
9507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
9517ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_rwlock_timedwrlock, void *m, void *abstime) {
9527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_timedwrlock, m, abstime);
9537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_rwlock_timedwrlock)(m, abstime);
9547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
95564310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    MutexLock(thr, pc, (uptr)m);
9567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
9577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
9587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
9597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
9607ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_rwlock_unlock, void *m) {
9617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_unlock, m);
96264310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov  MutexReadOrWriteUnlock(thr, pc, (uptr)m);
9637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_rwlock_unlock)(m);
9647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
9657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
9667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
967703e4e4a133aa6585361a2c6130cfc2874efff75Dmitry Vyukov// libpthread.so contains several versions of pthread_cond_init symbol.
968703e4e4a133aa6585361a2c6130cfc2874efff75Dmitry Vyukov// When we just dlsym() it, we get the wrong (old) version.
969c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov/*
9707ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_cond_init, void *c, void *a) {
9717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_cond_init, c, a);
9727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_cond_init)(c, a);
9737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
9747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
975c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov*/
9767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
9777ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_cond_destroy, void *c) {
9787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_cond_destroy, c);
9797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_cond_destroy)(c);
9807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
9817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
9827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
9837ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_cond_signal, void *c) {
9847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_cond_signal, c);
9857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_cond_signal)(c);
9867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
9877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
9887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
9897ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_cond_broadcast, void *c) {
9907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_cond_broadcast, c);
9917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_cond_broadcast)(c);
9927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
9937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
9947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
9957ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_cond_wait, void *c, void *m) {
9967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_cond_wait, c, m);
99764310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov  MutexUnlock(thr, pc, (uptr)m);
9987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_cond_wait)(c, m);
99964310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov  MutexLock(thr, pc, (uptr)m);
10007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
10017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
10027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
10037ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_cond_timedwait, void *c, void *m, void *abstime) {
10047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_cond_timedwait, c, m, abstime);
100564310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov  MutexUnlock(thr, pc, (uptr)m);
10067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_cond_timedwait)(c, m, abstime);
100764310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov  MutexLock(thr, pc, (uptr)m);
10087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
10097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
10107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
10117ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_barrier_init, void *b, void *a, unsigned count) {
10127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_barrier_init, b, a, count);
1013334553ec45d8982df45a6f5e656e068142ecde3fDmitry Vyukov  MemoryWrite(thr, pc, (uptr)b, kSizeLog1);
10147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_barrier_init)(b, a, count);
10157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
10167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
10177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
10187ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_barrier_destroy, void *b) {
10197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_barrier_destroy, b);
1020334553ec45d8982df45a6f5e656e068142ecde3fDmitry Vyukov  MemoryWrite(thr, pc, (uptr)b, kSizeLog1);
10217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_barrier_destroy)(b);
10227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
10237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
10247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
10257ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_barrier_wait, void *b) {
10267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_barrier_wait, b);
102764310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov  Release(thr, pc, (uptr)b);
1028334553ec45d8982df45a6f5e656e068142ecde3fDmitry Vyukov  MemoryRead(thr, pc, (uptr)b, kSizeLog1);
10297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pthread_barrier_wait)(b);
1030334553ec45d8982df45a6f5e656e068142ecde3fDmitry Vyukov  MemoryRead(thr, pc, (uptr)b, kSizeLog1);
10317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0 || res == PTHREAD_BARRIER_SERIAL_THREAD) {
103264310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    Acquire(thr, pc, (uptr)b);
10337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
10347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
10357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
10367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
10377ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) {
10387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pthread_once, o, f);
10397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (o == 0 || f == 0)
10407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return EINVAL;
10417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  atomic_uint32_t *a = static_cast<atomic_uint32_t*>(o);
10427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  u32 v = atomic_load(a, memory_order_acquire);
10437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (v == 0 && atomic_compare_exchange_strong(a, &v, 1,
10447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany                                               memory_order_relaxed)) {
10457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    const int old_in_rtl = thr->in_rtl;
10467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    thr->in_rtl = 0;
10477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    (*f)();
10487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    CHECK_EQ(thr->in_rtl, 0);
10497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    thr->in_rtl = old_in_rtl;
105064310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    Release(thr, pc, (uptr)o);
10517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    atomic_store(a, 2, memory_order_release);
10527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  } else {
10537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    while (v != 2) {
10547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      pthread_yield();
10557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      v = atomic_load(a, memory_order_acquire);
10567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    }
105764310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    Acquire(thr, pc, (uptr)o);
10587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
10597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return 0;
10607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
10617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
10627ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, sem_init, void *s, int pshared, unsigned value) {
10637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(sem_init, s, pshared, value);
10647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(sem_init)(s, pshared, value);
10657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
10667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
10677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
10687ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, sem_destroy, void *s) {
10697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(sem_destroy, s);
10707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(sem_destroy)(s);
10717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
10727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
10737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
10747ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, sem_wait, void *s) {
10757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(sem_wait, s);
1076ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  int res = BLOCK_REAL(sem_wait)(s);
10777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
107864310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    Acquire(thr, pc, (uptr)s);
10797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
10807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
10817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
10827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
10837ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, sem_trywait, void *s) {
10847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(sem_trywait, s);
1085ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  int res = BLOCK_REAL(sem_trywait)(s);
10867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
108764310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    Acquire(thr, pc, (uptr)s);
10887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
10897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
10907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
10917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
10927ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, sem_timedwait, void *s, void *abstime) {
10937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(sem_timedwait, s, abstime);
1094ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  int res = BLOCK_REAL(sem_timedwait)(s, abstime);
10957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
109664310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    Acquire(thr, pc, (uptr)s);
10977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
10987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
10997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
11007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
11017ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, sem_post, void *s) {
11027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(sem_post, s);
110364310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov  Release(thr, pc, (uptr)s);
11047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(sem_post)(s);
11057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
11067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
11077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
11087ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, sem_getvalue, void *s, int *sval) {
11097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(sem_getvalue, s, sval);
11107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(sem_getvalue)(s, sval);
11117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (res == 0) {
111264310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov    Acquire(thr, pc, (uptr)s);
11137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
11147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
11157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
11167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
111761ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, __xstat, int version, const char *path, void *buf) {
111861ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(__xstat, version, path, buf);
111961ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  return REAL(__xstat)(version, path, buf);
112061ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov}
112161ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov
112261ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, stat, const char *path, void *buf) {
112361ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(__xstat, 0, path, buf);
112461ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  return REAL(__xstat)(0, path, buf);
112561ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov}
112661ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov
112761ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, __xstat64, int version, const char *path, void *buf) {
112861ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(__xstat64, version, path, buf);
112961ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  return REAL(__xstat64)(version, path, buf);
113061ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov}
113161ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov
113261ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, stat64, const char *path, void *buf) {
113361ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(__xstat64, 0, path, buf);
113461ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  return REAL(__xstat64)(0, path, buf);
113561ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov}
113661ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov
113761ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, __lxstat, int version, const char *path, void *buf) {
113861ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(__lxstat, version, path, buf);
113961ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  return REAL(__lxstat)(version, path, buf);
114061ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov}
114161ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov
114261ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, lstat, const char *path, void *buf) {
114361ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(__lxstat, 0, path, buf);
114461ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  return REAL(__lxstat)(0, path, buf);
114561ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov}
114661ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov
114761ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, __lxstat64, int version, const char *path, void *buf) {
114861ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(__lxstat64, version, path, buf);
114961ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  return REAL(__lxstat64)(version, path, buf);
115061ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov}
115161ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov
115261ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, lstat64, const char *path, void *buf) {
115361ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(__lxstat64, 0, path, buf);
115461ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  return REAL(__lxstat64)(0, path, buf);
115561ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov}
115661ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov
115761ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, __fxstat, int version, int fd, void *buf) {
115861ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(__fxstat, version, fd, buf);
1159c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov  if (fd > 0)
1160c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov    FdAccess(thr, pc, fd);
116161ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  return REAL(__fxstat)(version, fd, buf);
116261ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov}
116361ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov
116461ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, fstat, int fd, void *buf) {
116561ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(__fxstat, 0, fd, buf);
1166c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov  if (fd > 0)
1167c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov    FdAccess(thr, pc, fd);
116861ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  return REAL(__fxstat)(0, fd, buf);
116961ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov}
117061ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov
117161ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, __fxstat64, int version, int fd, void *buf) {
117261ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(__fxstat64, version, fd, buf);
1173c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov  if (fd > 0)
1174c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov    FdAccess(thr, pc, fd);
117561ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  return REAL(__fxstat64)(version, fd, buf);
117661ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov}
117761ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov
117861ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, fstat64, int fd, void *buf) {
117961ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(__fxstat64, 0, fd, buf);
1180c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov  if (fd > 0)
1181c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov    FdAccess(thr, pc, fd);
118261ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  return REAL(__fxstat64)(0, fd, buf);
118361ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov}
118461ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov
1185ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry VyukovTSAN_INTERCEPTOR(int, open, const char *name, int flags, int mode) {
1186ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(open, name, flags, mode);
1187ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  int fd = REAL(open)(name, flags, mode);
1188ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  if (fd >= 0)
118968230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov    FdFileCreate(thr, pc, fd);
1190ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  return fd;
1191ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov}
1192ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov
1193c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry VyukovTSAN_INTERCEPTOR(int, open64, const char *name, int flags, int mode) {
1194c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(open64, name, flags, mode);
1195c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  int fd = REAL(open64)(name, flags, mode);
1196c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  if (fd >= 0)
1197c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov    FdFileCreate(thr, pc, fd);
1198c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  return fd;
1199c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov}
1200c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov
1201ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry VyukovTSAN_INTERCEPTOR(int, creat, const char *name, int mode) {
1202ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(creat, name, mode);
1203ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  int fd = REAL(creat)(name, mode);
1204ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  if (fd >= 0)
120568230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov    FdFileCreate(thr, pc, fd);
1206ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  return fd;
1207ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov}
1208ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov
1209c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry VyukovTSAN_INTERCEPTOR(int, creat64, const char *name, int mode) {
1210c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(creat64, name, mode);
1211c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  int fd = REAL(creat64)(name, mode);
1212c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  if (fd >= 0)
1213c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov    FdFileCreate(thr, pc, fd);
1214c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  return fd;
1215c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov}
1216c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov
1217ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry VyukovTSAN_INTERCEPTOR(int, dup, int oldfd) {
1218ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(dup, oldfd);
1219ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  int newfd = REAL(dup)(oldfd);
1220b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (oldfd >= 0 && newfd >= 0 && newfd != oldfd)
1221ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov    FdDup(thr, pc, oldfd, newfd);
1222ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  return newfd;
1223ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov}
1224ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov
1225ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry VyukovTSAN_INTERCEPTOR(int, dup2, int oldfd, int newfd) {
1226ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(dup2, oldfd, newfd);
1227ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  int newfd2 = REAL(dup2)(oldfd, newfd);
1228b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (oldfd >= 0 && newfd2 >= 0 && newfd2 != oldfd)
1229ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov    FdDup(thr, pc, oldfd, newfd2);
1230ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  return newfd2;
1231ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov}
1232ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov
1233ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry VyukovTSAN_INTERCEPTOR(int, dup3, int oldfd, int newfd, int flags) {
1234ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(dup3, oldfd, newfd, flags);
1235ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  int newfd2 = REAL(dup3)(oldfd, newfd, flags);
1236b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (oldfd >= 0 && newfd2 >= 0 && newfd2 != oldfd)
1237ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov    FdDup(thr, pc, oldfd, newfd2);
1238ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  return newfd2;
1239ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov}
1240ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov
124168230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry VyukovTSAN_INTERCEPTOR(int, eventfd, unsigned initval, int flags) {
124268230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(eventfd, initval, flags);
124368230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  int fd = REAL(eventfd)(initval, flags);
124468230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  if (fd >= 0)
124568230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov    FdEventCreate(thr, pc, fd);
124668230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  return fd;
124768230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov}
124868230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov
124945d4324bf5b0ec282f0a8f96312233e09a882502Dmitry VyukovTSAN_INTERCEPTOR(int, signalfd, int fd, void *mask, int flags) {
125045d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(signalfd, fd, mask, flags);
1251b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (fd >= 0)
1252b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov    FdClose(thr, pc, fd);
125345d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov  fd = REAL(signalfd)(fd, mask, flags);
125445d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov  if (fd >= 0)
125545d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov    FdSignalCreate(thr, pc, fd);
125645d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov  return fd;
125745d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov}
125845d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov
1259b75c67b495ca13801cc629b2c2c9dd0010e54739Dmitry VyukovTSAN_INTERCEPTOR(int, inotify_init, int fake) {
1260b75c67b495ca13801cc629b2c2c9dd0010e54739Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(inotify_init, fake);
1261b75c67b495ca13801cc629b2c2c9dd0010e54739Dmitry Vyukov  int fd = REAL(inotify_init)(fake);
126245d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov  if (fd >= 0)
126345d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov    FdInotifyCreate(thr, pc, fd);
126445d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov  return fd;
126545d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov}
126645d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov
126745d4324bf5b0ec282f0a8f96312233e09a882502Dmitry VyukovTSAN_INTERCEPTOR(int, inotify_init1, int flags) {
126845d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(inotify_init1, flags);
126945d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov  int fd = REAL(inotify_init1)(flags);
127045d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov  if (fd >= 0)
127145d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov    FdInotifyCreate(thr, pc, fd);
127245d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov  return fd;
127345d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov}
127445d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov
127568230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry VyukovTSAN_INTERCEPTOR(int, socket, int domain, int type, int protocol) {
127668230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(socket, domain, type, protocol);
127768230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  int fd = REAL(socket)(domain, type, protocol);
127868230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  if (fd >= 0)
127968230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov    FdSocketCreate(thr, pc, fd);
128068230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  return fd;
128168230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov}
128268230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov
1283983518e360a179d92bdbddebe05a87db3c6cc3c0Dmitry VyukovTSAN_INTERCEPTOR(int, socketpair, int domain, int type, int protocol, int *fd) {
1284983518e360a179d92bdbddebe05a87db3c6cc3c0Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(socketpair, domain, type, protocol, fd);
1285983518e360a179d92bdbddebe05a87db3c6cc3c0Dmitry Vyukov  int res = REAL(socketpair)(domain, type, protocol, fd);
1286983518e360a179d92bdbddebe05a87db3c6cc3c0Dmitry Vyukov  if (res == 0 && fd[0] >= 0 && fd[1] >= 0)
1287983518e360a179d92bdbddebe05a87db3c6cc3c0Dmitry Vyukov    FdPipeCreate(thr, pc, fd[0], fd[1]);
1288983518e360a179d92bdbddebe05a87db3c6cc3c0Dmitry Vyukov  return res;
1289983518e360a179d92bdbddebe05a87db3c6cc3c0Dmitry Vyukov}
1290983518e360a179d92bdbddebe05a87db3c6cc3c0Dmitry Vyukov
129168230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry VyukovTSAN_INTERCEPTOR(int, connect, int fd, void *addr, unsigned addrlen) {
129268230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(connect, fd, addr, addrlen);
1293ed513f69b8017a69214509105e7ec59fec77b468Dmitry Vyukov  FdSocketConnecting(thr, pc, fd);
129468230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  int res = REAL(connect)(fd, addr, addrlen);
1295b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (res == 0 && fd >= 0)
129668230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov    FdSocketConnect(thr, pc, fd);
129768230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  return res;
129868230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov}
129968230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov
130052c70e5818727521b89f7fc95a2a383df8985ca6Dmitry VyukovTSAN_INTERCEPTOR(int, bind, int fd, void *addr, unsigned addrlen) {
130152c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(bind, fd, addr, addrlen);
130252c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov  int res = REAL(bind)(fd, addr, addrlen);
130352c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov  if (fd > 0 && res == 0)
130452c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov    FdAccess(thr, pc, fd);
130552c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov  return res;
130652c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov}
130752c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov
130852c70e5818727521b89f7fc95a2a383df8985ca6Dmitry VyukovTSAN_INTERCEPTOR(int, listen, int fd, int backlog) {
130952c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(listen, fd, backlog);
131052c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov  int res = REAL(listen)(fd, backlog);
131152c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov  if (fd > 0 && res == 0)
131252c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov    FdAccess(thr, pc, fd);
131352c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov  return res;
131452c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov}
131552c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov
131668230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry VyukovTSAN_INTERCEPTOR(int, accept, int fd, void *addr, unsigned *addrlen) {
131768230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(accept, fd, addr, addrlen);
131868230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  int fd2 = REAL(accept)(fd, addr, addrlen);
1319b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (fd >= 0 && fd2 >= 0)
132068230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov    FdSocketAccept(thr, pc, fd, fd2);
132168230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  return fd2;
132268230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov}
132368230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov
132468230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry VyukovTSAN_INTERCEPTOR(int, accept4, int fd, void *addr, unsigned *addrlen, int f) {
132568230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(accept4, fd, addr, addrlen, f);
132668230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  int fd2 = REAL(accept4)(fd, addr, addrlen, f);
1327b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (fd >= 0 && fd2 >= 0)
132868230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov    FdSocketAccept(thr, pc, fd, fd2);
132968230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  return fd2;
133068230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov}
133168230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov
133268230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry VyukovTSAN_INTERCEPTOR(int, epoll_create, int size) {
133368230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(epoll_create, size);
133468230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  int fd = REAL(epoll_create)(size);
133568230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  if (fd >= 0)
133668230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov    FdPollCreate(thr, pc, fd);
133768230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  return fd;
133868230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov}
133968230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov
134068230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry VyukovTSAN_INTERCEPTOR(int, epoll_create1, int flags) {
134168230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(epoll_create1, flags);
134268230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  int fd = REAL(epoll_create1)(flags);
134368230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  if (fd >= 0)
134468230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov    FdPollCreate(thr, pc, fd);
134568230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  return fd;
134668230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov}
134768230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov
1348ddeb2c354235818494d86827e88a0c2fa44bebccDmitry VyukovTSAN_INTERCEPTOR(int, close, int fd) {
1349ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(close, fd);
1350c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  if (fd >= 0)
1351c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov    FdClose(thr, pc, fd);
1352ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov  return REAL(close)(fd);
1353ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov}
1354ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov
1355c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry VyukovTSAN_INTERCEPTOR(int, __close, int fd) {
1356c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(__close, fd);
1357c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  if (fd >= 0)
1358c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov    FdClose(thr, pc, fd);
1359c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  return REAL(__close)(fd);
1360c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov}
1361c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov
136203f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov// glibc guts
136303f224835f46801a0e22cc2951d21b67304e0457Dmitry VyukovTSAN_INTERCEPTOR(void, __res_iclose, void *state, bool free_addr) {
136403f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(__res_iclose, state, free_addr);
136503f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov  int fds[64];
136603f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov  int cnt = ExtractResolvFDs(state, fds, ARRAY_SIZE(fds));
136703f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov  for (int i = 0; i < cnt; i++) {
136803f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov    if (fds[i] > 0)
136903f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov      FdClose(thr, pc, fds[i]);
137003f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov  }
137103f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov  REAL(__res_iclose)(state, free_addr);
137203f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov}
137303f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov
137401e96987f557524a351b9f2229e7c920cdb96aadDmitry VyukovTSAN_INTERCEPTOR(int, pipe, int *pipefd) {
1375ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(pipe, pipefd);
1376ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov  int res = REAL(pipe)(pipefd);
1377b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (res == 0 && pipefd[0] >= 0 && pipefd[1] >= 0)
137868230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov    FdPipeCreate(thr, pc, pipefd[0], pipefd[1]);
137901e96987f557524a351b9f2229e7c920cdb96aadDmitry Vyukov  return res;
1380ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov}
1381ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov
138201e96987f557524a351b9f2229e7c920cdb96aadDmitry VyukovTSAN_INTERCEPTOR(int, pipe2, int *pipefd, int flags) {
1383ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(pipe2, pipefd, flags);
1384ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov  int res = REAL(pipe2)(pipefd, flags);
1385b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (res == 0 && pipefd[0] >= 0 && pipefd[1] >= 0)
138668230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov    FdPipeCreate(thr, pc, pipefd[0], pipefd[1]);
1387ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov  return res;
1388ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov}
1389ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov
13907ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(long_t, readv, int fd, void *vec, int cnt) {
13917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(readv, fd, vec, cnt);
13927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(readv)(fd, vec, cnt);
1393b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (res >= 0 && fd >= 0) {
13943f4e6d9b75fb3f7f2674a31008738cfda9cda9edDmitry Vyukov    FdAcquire(thr, pc, fd);
13957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
13967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
13977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
13987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
13997ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(long_t, preadv64, int fd, void *vec, int cnt, u64 off) {
14007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(preadv64, fd, vec, cnt, off);
14017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(preadv64)(fd, vec, cnt, off);
1402b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (res >= 0 && fd >= 0) {
14033f4e6d9b75fb3f7f2674a31008738cfda9cda9edDmitry Vyukov    FdAcquire(thr, pc, fd);
14047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
14057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
14067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
14077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
14087ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(long_t, writev, int fd, void *vec, int cnt) {
14097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(writev, fd, vec, cnt);
1410b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (fd >= 0)
1411b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov    FdRelease(thr, pc, fd);
14127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(writev)(fd, vec, cnt);
14137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
14147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
14157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
14167ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(long_t, pwritev64, int fd, void *vec, int cnt, u64 off) {
14177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(pwritev64, fd, vec, cnt, off);
1418b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (fd >= 0)
1419b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov    FdRelease(thr, pc, fd);
14207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(pwritev64)(fd, vec, cnt, off);
14217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
14227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
14237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
14247ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(long_t, send, int fd, void *buf, long_t len, int flags) {
14257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(send, fd, buf, len, flags);
1426b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (fd >= 0)
1427b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov    FdRelease(thr, pc, fd);
14287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(send)(fd, buf, len, flags);
14297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
14307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
14317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
14327ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(long_t, sendmsg, int fd, void *msg, int flags) {
14337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(sendmsg, fd, msg, flags);
1434b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (fd >= 0)
1435b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov    FdRelease(thr, pc, fd);
14367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(sendmsg)(fd, msg, flags);
14377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
14387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
14397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
14407ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(long_t, recv, int fd, void *buf, long_t len, int flags) {
14417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(recv, fd, buf, len, flags);
14427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(recv)(fd, buf, len, flags);
1443b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (res >= 0 && fd >= 0) {
14443f4e6d9b75fb3f7f2674a31008738cfda9cda9edDmitry Vyukov    FdAcquire(thr, pc, fd);
14457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
14467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
14477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
14487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
14497ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(long_t, recvmsg, int fd, void *msg, int flags) {
14507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(recvmsg, fd, msg, flags);
14517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(recvmsg)(fd, msg, flags);
1452b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (res >= 0 && fd >= 0) {
14533f4e6d9b75fb3f7f2674a31008738cfda9cda9edDmitry Vyukov    FdAcquire(thr, pc, fd);
14547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
14557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
14567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
14577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
14587ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, unlink, char *path) {
14597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(unlink, path);
1460c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  Release(thr, pc, File2addr(path));
14617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(unlink)(path);
14627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
14637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
14647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
14657ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, fopen, char *path, char *mode) {
14667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(fopen, path, mode);
14677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  void *res = REAL(fopen)(path, mode);
1468c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  Acquire(thr, pc, File2addr(path));
1469c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  if (res) {
1470f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov    int fd = fileno_unlocked(res);
1471c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov    if (fd >= 0)
1472c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov      FdFileCreate(thr, pc, fd);
1473c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  }
1474c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  return res;
1475c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov}
1476c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov
1477c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry VyukovTSAN_INTERCEPTOR(void*, freopen, char *path, char *mode, void *stream) {
1478c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(freopen, path, mode, stream);
1479c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  if (stream) {
1480f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov    int fd = fileno_unlocked(stream);
1481c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov    if (fd >= 0)
1482c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov      FdClose(thr, pc, fd);
1483c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  }
1484c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  void *res = REAL(freopen)(path, mode, stream);
1485c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  Acquire(thr, pc, File2addr(path));
1486c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  if (res) {
1487f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov    int fd = fileno_unlocked(res);
1488c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov    if (fd >= 0)
1489c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov      FdFileCreate(thr, pc, fd);
1490c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  }
1491c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  return res;
1492c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov}
1493c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov
1494c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry VyukovTSAN_INTERCEPTOR(int, fclose, void *stream) {
1495f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov  {
1496f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov    SCOPED_TSAN_INTERCEPTOR(fclose, stream);
1497f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov    if (stream) {
1498f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov      int fd = fileno_unlocked(stream);
1499f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov      if (fd >= 0)
1500f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov        FdClose(thr, pc, fd);
1501f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov    }
1502c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  }
1503f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov  return REAL(fclose)(stream);
15047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
15057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
15067ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(uptr, fread, void *ptr, uptr size, uptr nmemb, void *f) {
1507f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov  {
1508f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov    SCOPED_TSAN_INTERCEPTOR(fread, ptr, size, nmemb, f);
1509f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov    MemoryAccessRange(thr, pc, (uptr)ptr, size * nmemb, true);
1510f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov  }
15117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return REAL(fread)(ptr, size, nmemb, f);
15127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
15137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
15147ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(uptr, fwrite, const void *p, uptr size, uptr nmemb, void *f) {
1515f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov  {
1516f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov    SCOPED_TSAN_INTERCEPTOR(fwrite, p, size, nmemb, f);
1517f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov    MemoryAccessRange(thr, pc, (uptr)p, size * nmemb, false);
1518f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov  }
15197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return REAL(fwrite)(p, size, nmemb, f);
15207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
15217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
15227ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, puts, const char *s) {
15237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(puts, s);
1524d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov  MemoryAccessRange(thr, pc, (uptr)s, internal_strlen(s), false);
15257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return REAL(puts)(s);
15267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
15277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
15287ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, rmdir, char *path) {
15297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(rmdir, path);
1530c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  Release(thr, pc, Dir2addr(path));
15317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(rmdir)(path);
15327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
15337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
15347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
15357ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, opendir, char *path) {
15367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(opendir, path);
15377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  void *res = REAL(opendir)(path);
1538c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  if (res != 0)
1539c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov    Acquire(thr, pc, Dir2addr(path));
15407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
15417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
15427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
15437ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, epoll_ctl, int epfd, int op, int fd, void *ev) {
15447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(epoll_ctl, epfd, op, fd, ev);
1545b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (op == EPOLL_CTL_ADD && epfd >= 0) {
15463f4e6d9b75fb3f7f2674a31008738cfda9cda9edDmitry Vyukov    FdRelease(thr, pc, epfd);
15477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
15487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int res = REAL(epoll_ctl)(epfd, op, fd, ev);
1549f5d4273457ca3d26e6cf658b266cd61062a65101Dmitry Vyukov  if (fd >= 0)
1550f5d4273457ca3d26e6cf658b266cd61062a65101Dmitry Vyukov    FdAccess(thr, pc, fd);
15517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
15527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
15537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
15547ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, epoll_wait, int epfd, void *ev, int cnt, int timeout) {
15557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(epoll_wait, epfd, ev, cnt, timeout);
1556ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  int res = BLOCK_REAL(epoll_wait)(epfd, ev, cnt, timeout);
1557b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov  if (res > 0 && epfd >= 0) {
15583f4e6d9b75fb3f7f2674a31008738cfda9cda9edDmitry Vyukov    FdAcquire(thr, pc, epfd);
15597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
15607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
15617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
15627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1563ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry VyukovTSAN_INTERCEPTOR(int, poll, void *fds, long_t nfds, int timeout) {
1564ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(poll, fds, nfds, timeout);
1565ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  int res = BLOCK_REAL(poll)(fds, nfds, timeout);
1566ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  return res;
1567ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov}
1568ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov
1569d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukovstatic void ALWAYS_INLINE rtl_generic_sighandler(bool sigact, int sig,
1570d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov    my_siginfo_t *info, void *ctx) {
15717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ThreadState *thr = cur_thread();
1572e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  SignalContext *sctx = SigCtx(thr);
1573d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  // Don't mess with synchronous signals.
15741fc03d50a87302689482efa24b045a393097b6c3Dmitry Vyukov  if (sig == SIGSEGV || sig == SIGBUS || sig == SIGILL ||
15751fc03d50a87302689482efa24b045a393097b6c3Dmitry Vyukov      sig == SIGABRT || sig == SIGFPE || sig == SIGPIPE ||
1576ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov      // If we are sending signal to ourselves, we must process it now.
1577ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov      (sctx && sig == sctx->int_signal_send) ||
15780bf04eab1910cc8bf622c20ba08c339dc25e297eDmitry Vyukov      // If we are in blocking function, we can safely process it now
15790bf04eab1910cc8bf622c20ba08c339dc25e297eDmitry Vyukov      // (but check if we are in a recursive interceptor,
15800bf04eab1910cc8bf622c20ba08c339dc25e297eDmitry Vyukov      // i.e. pthread_join()->munmap()).
158180d46a2fbc0ae5086511a91119a6e28883b9f880Dmitry Vyukov      (sctx && sctx->in_blocking_func == 1 && thr->in_rtl == 1)) {
1582d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov    CHECK(thr->in_rtl == 0 || thr->in_rtl == 1);
1583d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov    int in_rtl = thr->in_rtl;
1584d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov    thr->in_rtl = 0;
1585d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov    CHECK_EQ(thr->in_signal_handler, false);
1586d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov    thr->in_signal_handler = true;
1587d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov    if (sigact)
1588d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov      sigactions[sig].sa_sigaction(sig, info, ctx);
1589d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov    else
1590d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov      sigactions[sig].sa_handler(sig);
1591d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov    CHECK_EQ(thr->in_signal_handler, true);
1592d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov    thr->in_signal_handler = false;
1593d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov    thr->in_rtl = in_rtl;
1594d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov    return;
1595d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  }
1596d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov
15971fc03d50a87302689482efa24b045a393097b6c3Dmitry Vyukov  if (sctx == 0)
15981fc03d50a87302689482efa24b045a393097b6c3Dmitry Vyukov    return;
1599e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  SignalDesc *signal = &sctx->pending_signals[sig];
16007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (signal->armed == false) {
16017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    signal->armed = true;
1602d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov    signal->sigaction = sigact;
1603d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov    if (info)
16046e4815579e5b48b48de092afcc3b092dfb97df5cDmitry Vyukov      internal_memcpy(&signal->siginfo, info, sizeof(*info));
1605a5562db12c5331433407ac21602086f34561c25cDmitry Vyukov    if (ctx)
16066e4815579e5b48b48de092afcc3b092dfb97df5cDmitry Vyukov      internal_memcpy(&signal->ctx, ctx, sizeof(signal->ctx));
1607e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov    sctx->pending_signal_count++;
16087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
16097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
16107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1611d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukovstatic void rtl_sighandler(int sig) {
1612d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  rtl_generic_sighandler(false, sig, 0, 0);
1613d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov}
1614d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov
16157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void rtl_sigaction(int sig, my_siginfo_t *info, void *ctx) {
1616d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  rtl_generic_sighandler(true, sig, info, ctx);
16177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
16187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
16197ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, sigaction, int sig, sigaction_t *act, sigaction_t *old) {
16207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SCOPED_TSAN_INTERCEPTOR(sigaction, sig, act, old);
1621d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  if (old)
16226e4815579e5b48b48de092afcc3b092dfb97df5cDmitry Vyukov    internal_memcpy(old, &sigactions[sig], sizeof(*old));
1623d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  if (act == 0)
1624d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov    return 0;
16256e4815579e5b48b48de092afcc3b092dfb97df5cDmitry Vyukov  internal_memcpy(&sigactions[sig], act, sizeof(*act));
16266e4815579e5b48b48de092afcc3b092dfb97df5cDmitry Vyukov  sigaction_t newact;
16276e4815579e5b48b48de092afcc3b092dfb97df5cDmitry Vyukov  internal_memcpy(&newact, act, sizeof(newact));
1628b4b9fa707324095e3590a57963fd754d7a4dd40eDmitry Vyukov  sigfillset(&newact.sa_mask);
1629d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  if (act->sa_handler != SIG_IGN && act->sa_handler != SIG_DFL) {
16307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    if (newact.sa_flags & SA_SIGINFO)
16317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      newact.sa_sigaction = rtl_sigaction;
16327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    else
16337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      newact.sa_handler = rtl_sighandler;
1634d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  }
1635d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  int res = REAL(sigaction)(sig, &newact, 0);
1636d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  return res;
1637d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov}
1638d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov
1639d91d06794506f10fb7599a2b835222fba29394e0Dmitry VyukovTSAN_INTERCEPTOR(sighandler_t, signal, int sig, sighandler_t h) {
16402135d8a7f4ba30fe35ed02d5e6ffd59a95b26219Alexey Samsonov  sigaction_t act;
1641d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  act.sa_handler = h;
164288207ab15125e2f1e9b3d541b735b2b8aba9b6d9Alexey Samsonov  REAL(memset)(&act.sa_mask, -1, sizeof(act.sa_mask));
1643d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  act.sa_flags = 0;
16442135d8a7f4ba30fe35ed02d5e6ffd59a95b26219Alexey Samsonov  sigaction_t old;
1645d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  int res = sigaction(sig, &act, &old);
1646d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  if (res)
1647d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov    return SIG_ERR;
1648d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  return old.sa_handler;
1649d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov}
1650d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov
1651d91d06794506f10fb7599a2b835222fba29394e0Dmitry VyukovTSAN_INTERCEPTOR(int, raise, int sig) {
1652d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(raise, sig);
1653e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  SignalContext *sctx = SigCtx(thr);
16541fc03d50a87302689482efa24b045a393097b6c3Dmitry Vyukov  CHECK_NE(sctx, 0);
1655e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  int prev = sctx->int_signal_send;
1656e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  sctx->int_signal_send = sig;
1657d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  int res = REAL(raise)(sig);
1658e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  CHECK_EQ(sctx->int_signal_send, sig);
1659e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  sctx->int_signal_send = prev;
1660d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  return res;
1661d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov}
1662d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov
1663d91d06794506f10fb7599a2b835222fba29394e0Dmitry VyukovTSAN_INTERCEPTOR(int, kill, int pid, int sig) {
1664d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(kill, pid, sig);
1665e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  SignalContext *sctx = SigCtx(thr);
16661fc03d50a87302689482efa24b045a393097b6c3Dmitry Vyukov  CHECK_NE(sctx, 0);
1667e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  int prev = sctx->int_signal_send;
1668d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  if (pid == GetPid()) {
1669e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov    sctx->int_signal_send = sig;
1670d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  }
1671d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  int res = REAL(kill)(pid, sig);
1672d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  if (pid == GetPid()) {
1673e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov    CHECK_EQ(sctx->int_signal_send, sig);
1674e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov    sctx->int_signal_send = prev;
1675d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  }
1676d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  return res;
1677d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov}
1678d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov
1679d91d06794506f10fb7599a2b835222fba29394e0Dmitry VyukovTSAN_INTERCEPTOR(int, pthread_kill, void *tid, int sig) {
1680d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(pthread_kill, tid, sig);
1681e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  SignalContext *sctx = SigCtx(thr);
16821fc03d50a87302689482efa24b045a393097b6c3Dmitry Vyukov  CHECK_NE(sctx, 0);
1683e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  int prev = sctx->int_signal_send;
1684d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  if (tid == pthread_self()) {
1685e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov    sctx->int_signal_send = sig;
1686d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  }
1687d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  int res = REAL(pthread_kill)(tid, sig);
1688d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  if (tid == pthread_self()) {
1689e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov    CHECK_EQ(sctx->int_signal_send, sig);
1690e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov    sctx->int_signal_send = prev;
16917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
16927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return res;
16937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
16947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1695ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry VyukovTSAN_INTERCEPTOR(int, gettimeofday, void *tv, void *tz) {
1696ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(gettimeofday, tv, tz);
1697ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  // It's intercepted merely to process pending signals.
1698ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  return REAL(gettimeofday)(tv, tz);
1699ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov}
1700ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov
170192733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov// Linux kernel has a bug that leads to kernel deadlock if a process
170292733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov// maps TBs of memory and then calls mlock().
170392733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukovstatic void MlockIsUnsupported() {
170492733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov  static atomic_uint8_t printed;
170592733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov  if (atomic_exchange(&printed, 1, memory_order_relaxed))
170692733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov    return;
170792733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov  Printf("INFO: ThreadSanitizer ignores mlock/mlockall/munlock/munlockall\n");
170892733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov}
170992733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov
171092733f94292cd36795238e1a6ed0a99a1dc0454dDmitry VyukovTSAN_INTERCEPTOR(int, mlock, const void *addr, uptr len) {
171192733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov  MlockIsUnsupported();
171292733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov  return 0;
171392733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov}
171492733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov
171592733f94292cd36795238e1a6ed0a99a1dc0454dDmitry VyukovTSAN_INTERCEPTOR(int, munlock, const void *addr, uptr len) {
171692733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov  MlockIsUnsupported();
171792733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov  return 0;
171892733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov}
171992733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov
172092733f94292cd36795238e1a6ed0a99a1dc0454dDmitry VyukovTSAN_INTERCEPTOR(int, mlockall, int flags) {
172192733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov  MlockIsUnsupported();
172292733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov  return 0;
172392733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov}
172492733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov
172592733f94292cd36795238e1a6ed0a99a1dc0454dDmitry VyukovTSAN_INTERCEPTOR(int, munlockall, void) {
172692733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov  MlockIsUnsupported();
172792733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov  return 0;
172892733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov}
172992733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov
1730b75c67b495ca13801cc629b2c2c9dd0010e54739Dmitry VyukovTSAN_INTERCEPTOR(int, fork, int fake) {
1731b75c67b495ca13801cc629b2c2c9dd0010e54739Dmitry Vyukov  SCOPED_TSAN_INTERCEPTOR(fork, fake);
17324554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov  // It's intercepted merely to process pending signals.
1733b75c67b495ca13801cc629b2c2c9dd0010e54739Dmitry Vyukov  int pid = REAL(fork)(fake);
17344554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov  if (pid == 0) {
17354554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov    // child
17364554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov    FdOnFork(thr, pc);
17374554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov  } else if (pid > 0) {
17384554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov    // parent
17394554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov  }
17404554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov  return pid;
17414554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov}
17424554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov
1743996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanovstruct TsanInterceptorContext {
1744996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  ThreadState *thr;
1745996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  const uptr caller_pc;
1746996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov  const uptr pc;
1747996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov};
1748996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov
1749996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
1750996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov    MemoryAccessRange(((TsanInterceptorContext*)ctx)->thr,  \
1751996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov                      ((TsanInterceptorContext*)ctx)->pc,   \
1752996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov                      (uptr)ptr, size, true)
1753996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size)       \
1754996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov    MemoryAccessRange(((TsanInterceptorContext*)ctx)->thr,  \
1755996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov                      ((TsanInterceptorContext*)ctx)->pc,   \
1756996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov                      (uptr)ptr, size, false)
1757996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
1758996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov    SCOPED_TSAN_INTERCEPTOR(func, __VA_ARGS__) \
1759996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov    TsanInterceptorContext _ctx = {thr, caller_pc, pc}; \
176082a9080eaff95d69b270cd863e9df63e3b4e59adEvgeniy Stepanov    ctx = (void*)&_ctx; \
176182a9080eaff95d69b270cd863e9df63e3b4e59adEvgeniy Stepanov    (void)ctx;
1762996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
1763996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov    FdAcquire(((TsanInterceptorContext*)ctx)->thr, pc, fd)
1764996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
1765996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov    FdRelease(((TsanInterceptorContext*)ctx)->thr, pc, fd)
1766996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \
1767996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov    ThreadSetName(((TsanInterceptorContext*)ctx)->thr, name)
17684f32c0beaa83ffbb84db23d2e6205bee57c39ce1Evgeniy Stepanov#include "sanitizer_common/sanitizer_common_interceptors.inc"
1769c8033193376c3326478a345c4ae6633d4d2862c6Kostya Serebryany
1770ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukovnamespace __tsan {
1771ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov
1772ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukovvoid ProcessPendingSignals(ThreadState *thr) {
17737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK_EQ(thr->in_rtl, 0);
1774e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  SignalContext *sctx = SigCtx(thr);
17751fc03d50a87302689482efa24b045a393097b6c3Dmitry Vyukov  if (sctx == 0 || sctx->pending_signal_count == 0 || thr->in_signal_handler)
17767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
1777158c6ac3bb46753db217f9c2c73485811a3a1890Dmitry Vyukov  Context *ctx = CTX();
17787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->in_signal_handler = true;
1779e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov  sctx->pending_signal_count = 0;
17807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // These are too big for stack.
17817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  static THREADLOCAL sigset_t emptyset, oldset;
17827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  sigfillset(&emptyset);
17837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  pthread_sigmask(SIG_SETMASK, &emptyset, &oldset);
17847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  for (int sig = 0; sig < kSigCount; sig++) {
1785e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov    SignalDesc *signal = &sctx->pending_signals[sig];
17867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    if (signal->armed) {
17877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      signal->armed = false;
1788d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov      if (sigactions[sig].sa_handler != SIG_DFL
1789d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov          && sigactions[sig].sa_handler != SIG_IGN) {
17907a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov        // Insure that the handler does not spoil errno.
17917a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov        const int saved_errno = errno;
17927a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov        errno = 0;
1793d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov        if (signal->sigaction)
1794a5562db12c5331433407ac21602086f34561c25cDmitry Vyukov          sigactions[sig].sa_sigaction(sig, &signal->siginfo, &signal->ctx);
1795d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov        else
1796d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov          sigactions[sig].sa_handler(sig);
17978a326776e41dc68c810ba3719a24328de517d8f9Dmitry Vyukov        if (flags()->report_bugs && errno != 0) {
17987a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov          ScopedInRtl in_rtl;
17994f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov          __tsan::StackTrace stack;
18007a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov          uptr pc = signal->sigaction ?
18017a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov              (uptr)sigactions[sig].sa_sigaction :
18027a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov              (uptr)sigactions[sig].sa_handler;
18037a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov          stack.Init(&pc, 1);
18042bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov          ThreadRegistryLock l(ctx->thread_registry);
18057a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov          ScopedReport rep(ReportTypeErrnoInSignal);
1806158c6ac3bb46753db217f9c2c73485811a3a1890Dmitry Vyukov          if (!IsFiredSuppression(ctx, rep, stack)) {
1807158c6ac3bb46753db217f9c2c73485811a3a1890Dmitry Vyukov            rep.AddStack(&stack);
1808158c6ac3bb46753db217f9c2c73485811a3a1890Dmitry Vyukov            OutputReport(ctx, rep, rep.GetReport()->stacks[0]);
1809158c6ac3bb46753db217f9c2c73485811a3a1890Dmitry Vyukov          }
18107a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov        }
18117a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov        errno = saved_errno;
1812d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov      }
18137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    }
18147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
18157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  pthread_sigmask(SIG_SETMASK, &oldset, 0);
18167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK_EQ(thr->in_signal_handler, true);
18177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->in_signal_handler = false;
18187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
18197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
182091ac008b435b879bb366bcf9516c53f2d07c30b1Dmitry Vyukovstatic void unreachable() {
182191ac008b435b879bb366bcf9516c53f2d07c30b1Dmitry Vyukov  Printf("FATAL: ThreadSanitizer: unreachable called\n");
182291ac008b435b879bb366bcf9516c53f2d07c30b1Dmitry Vyukov  Die();
182391ac008b435b879bb366bcf9516c53f2d07c30b1Dmitry Vyukov}
182491ac008b435b879bb366bcf9516c53f2d07c30b1Dmitry Vyukov
18257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid InitializeInterceptors() {
18267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK_GT(cur_thread()->in_rtl, 0);
18277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
18287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // We need to setup it early, because functions like dlsym() can call it.
1829065c4ac846589d04436cb7f19f938ff42035313eDmitry Vyukov  REAL(memset) = internal_memset;
1830065c4ac846589d04436cb7f19f938ff42035313eDmitry Vyukov  REAL(memcpy) = internal_memcpy;
1831065c4ac846589d04436cb7f19f938ff42035313eDmitry Vyukov  REAL(memcmp) = internal_memcmp;
18327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1833c8033193376c3326478a345c4ae6633d4d2862c6Kostya Serebryany  SANITIZER_COMMON_INTERCEPTORS_INIT;
1834c8033193376c3326478a345c4ae6633d4d2862c6Kostya Serebryany
1835f037f565b2e02878ceb6e7b49647e814e2990ef5Dmitry Vyukov  TSAN_INTERCEPT(longjmp);
1836f037f565b2e02878ceb6e7b49647e814e2990ef5Dmitry Vyukov  TSAN_INTERCEPT(siglongjmp);
1837f037f565b2e02878ceb6e7b49647e814e2990ef5Dmitry Vyukov
18387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(malloc);
183907ba8ef44deb54baa9307298fbffe25ddb30c362Dmitry Vyukov  TSAN_INTERCEPT(__libc_memalign);
18407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(calloc);
18417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(realloc);
18427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(free);
18437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(cfree);
18447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(mmap);
18457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(mmap64);
18467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(munmap);
18477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(memalign);
18487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(valloc);
18497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pvalloc);
18507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(posix_memalign);
18517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
18527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(strlen);
18537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(memset);
18547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(memcpy);
18557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(strcmp);
18567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(memchr);
18577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(memrchr);
18587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(memmove);
18597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(memcmp);
18607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(strchr);
18617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(strchrnul);
18627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(strrchr);
18637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(strncmp);
18647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(strcpy);  // NOLINT
18657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(strncpy);
18667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(strstr);
18677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
18687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_create);
18697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_join);
18707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_detach);
18717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
18727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_mutex_init);
18737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_mutex_destroy);
18747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_mutex_lock);
18757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_mutex_trylock);
18767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_mutex_timedlock);
18777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_mutex_unlock);
18787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
18797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_spin_init);
18807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_spin_destroy);
18817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_spin_lock);
18827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_spin_trylock);
18837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_spin_unlock);
18847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
18857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_rwlock_init);
18867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_rwlock_destroy);
18877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_rwlock_rdlock);
18887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_rwlock_tryrdlock);
18897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_rwlock_timedrdlock);
18907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_rwlock_wrlock);
18917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_rwlock_trywrlock);
18927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_rwlock_timedwrlock);
18937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_rwlock_unlock);
18947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1895c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  // TSAN_INTERCEPT(pthread_cond_init);
18967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_cond_destroy);
18977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_cond_signal);
18987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_cond_broadcast);
18997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_cond_wait);
19007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_cond_timedwait);
19017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
19027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_barrier_init);
19037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_barrier_destroy);
19047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_barrier_wait);
19057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
19067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pthread_once);
19077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
19087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(sem_init);
19097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(sem_destroy);
19107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(sem_wait);
19117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(sem_trywait);
19127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(sem_timedwait);
19137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(sem_post);
19147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(sem_getvalue);
19157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
191661ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  TSAN_INTERCEPT(stat);
191761ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  TSAN_INTERCEPT(__xstat);
191861ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  TSAN_INTERCEPT(stat64);
191961ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  TSAN_INTERCEPT(__xstat64);
192061ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  TSAN_INTERCEPT(lstat);
192161ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  TSAN_INTERCEPT(__lxstat);
192261ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  TSAN_INTERCEPT(lstat64);
192361ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  TSAN_INTERCEPT(__lxstat64);
192461ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  TSAN_INTERCEPT(fstat);
192561ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  TSAN_INTERCEPT(__fxstat);
192661ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  TSAN_INTERCEPT(fstat64);
192761ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov  TSAN_INTERCEPT(__fxstat64);
1928ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  TSAN_INTERCEPT(open);
1929c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  TSAN_INTERCEPT(open64);
1930ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  TSAN_INTERCEPT(creat);
1931c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  TSAN_INTERCEPT(creat64);
1932ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  TSAN_INTERCEPT(dup);
1933ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  TSAN_INTERCEPT(dup2);
1934ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov  TSAN_INTERCEPT(dup3);
193568230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  TSAN_INTERCEPT(eventfd);
193645d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov  TSAN_INTERCEPT(signalfd);
193745d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov  TSAN_INTERCEPT(inotify_init);
193845d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov  TSAN_INTERCEPT(inotify_init1);
193968230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  TSAN_INTERCEPT(socket);
1940983518e360a179d92bdbddebe05a87db3c6cc3c0Dmitry Vyukov  TSAN_INTERCEPT(socketpair);
194168230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  TSAN_INTERCEPT(connect);
194252c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov  TSAN_INTERCEPT(bind);
194352c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov  TSAN_INTERCEPT(listen);
194468230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  TSAN_INTERCEPT(accept);
194568230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  TSAN_INTERCEPT(accept4);
194668230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  TSAN_INTERCEPT(epoll_create);
194768230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  TSAN_INTERCEPT(epoll_create1);
1948ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov  TSAN_INTERCEPT(close);
194903f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov  TSAN_INTERCEPT(__close);
195003f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov  TSAN_INTERCEPT(__res_iclose);
1951ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov  TSAN_INTERCEPT(pipe);
1952ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov  TSAN_INTERCEPT(pipe2);
1953ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov
19547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(readv);
19557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(preadv64);
19567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(writev);
19577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(pwritev64);
19587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(send);
19597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(sendmsg);
19607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(recv);
19617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(recvmsg);
19627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
19637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(unlink);
19647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(fopen);
1965c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  TSAN_INTERCEPT(freopen);
1966c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov  TSAN_INTERCEPT(fclose);
19677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(fread);
19687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(fwrite);
19697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(puts);
19707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(rmdir);
19717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(opendir);
19727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
19737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(epoll_ctl);
19747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(epoll_wait);
1975ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov  TSAN_INTERCEPT(poll);
19767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
19777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TSAN_INTERCEPT(sigaction);
1978d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  TSAN_INTERCEPT(signal);
1979d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  TSAN_INTERCEPT(raise);
1980d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  TSAN_INTERCEPT(kill);
1981d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov  TSAN_INTERCEPT(pthread_kill);
1982848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  TSAN_INTERCEPT(sleep);
1983848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  TSAN_INTERCEPT(usleep);
1984848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  TSAN_INTERCEPT(nanosleep);
1985aad173b2f1dae9f88bbffd217ebd46ed1f020bcbDmitry Vyukov  TSAN_INTERCEPT(gettimeofday);
19867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
198792733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov  TSAN_INTERCEPT(mlock);
198892733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov  TSAN_INTERCEPT(munlock);
198992733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov  TSAN_INTERCEPT(mlockall);
199092733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov  TSAN_INTERCEPT(munlockall);
199192733f94292cd36795238e1a6ed0a99a1dc0454dDmitry Vyukov
19924554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov  TSAN_INTERCEPT(fork);
199331c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  TSAN_INTERCEPT(on_exit);
199431c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  TSAN_INTERCEPT(__cxa_atexit);
19954554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov
199691ac008b435b879bb366bcf9516c53f2d07c30b1Dmitry Vyukov  // Need to setup it, because interceptors check that the function is resolved.
199791ac008b435b879bb366bcf9516c53f2d07c30b1Dmitry Vyukov  // But atexit is emitted directly into the module, so can't be resolved.
199891ac008b435b879bb366bcf9516c53f2d07c30b1Dmitry Vyukov  REAL(atexit) = (int(*)(void(*)()))unreachable;
19997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  atexit_ctx = new(internal_alloc(MBlockAtExit, sizeof(AtExitContext)))
20007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      AtExitContext();
20017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
200231c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov  if (REAL(__cxa_atexit)(&finalize, 0, 0)) {
2003b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov    Printf("ThreadSanitizer: failed to setup atexit callback\n");
20047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    Die();
20057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
20067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
20077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) {
2008b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov    Printf("ThreadSanitizer: failed to create thread key\n");
20097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    Die();
20107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
20113f4e6d9b75fb3f7f2674a31008738cfda9cda9edDmitry Vyukov
20123f4e6d9b75fb3f7f2674a31008738cfda9cda9edDmitry Vyukov  FdInit();
20137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
20147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
201526127735454fddae3495794f38189d57dde6510fDmitry Vyukovvoid internal_start_thread(void(*func)(void *arg), void *arg) {
201626127735454fddae3495794f38189d57dde6510fDmitry Vyukov  void *th;
201726127735454fddae3495794f38189d57dde6510fDmitry Vyukov  REAL(pthread_create)(&th, 0, (void*(*)(void *arg))func, arg);
201826127735454fddae3495794f38189d57dde6510fDmitry Vyukov  REAL(pthread_detach)(th);
201926127735454fddae3495794f38189d57dde6510fDmitry Vyukov}
202026127735454fddae3495794f38189d57dde6510fDmitry Vyukov
20217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}  // namespace __tsan
2022