1fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov//===-- tsan_fd.cc --------------------------------------------------------===//
2fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov//
3fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov//                     The LLVM Compiler Infrastructure
4fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov//
5fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov// This file is distributed under the University of Illinois Open Source
6fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov// License. See LICENSE.TXT for details.
7fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov//
8fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov//===----------------------------------------------------------------------===//
9fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov//
10fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov// This file is a part of ThreadSanitizer (TSan), a race detector.
11fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov//
12fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov//===----------------------------------------------------------------------===//
13fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov
14fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov#include "tsan_fd.h"
15fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov#include "tsan_rtl.h"
16fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov#include <sanitizer_common/sanitizer_atomic.h>
17fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov
18fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukovnamespace __tsan {
19fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov
20fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukovconst int kTableSizeL1 = 1024;
21fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukovconst int kTableSizeL2 = 1024;
22fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukovconst int kTableSize = kTableSizeL1 * kTableSizeL2;
23fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov
24c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukovstruct FdSync {
25fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov  atomic_uint64_t rc;
26fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov};
27fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov
28c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukovstruct FdDesc {
29c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  FdSync *sync;
30c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  int creation_tid;
31c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  u32 creation_stack;
32c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov};
33c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov
34fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukovstruct FdContext {
35fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov  atomic_uintptr_t tab[kTableSizeL1];
36fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov  // Addresses used for synchronization.
37c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  FdSync globsync;
38c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  FdSync filesync;
39c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  FdSync socksync;
40ed513f69b8017a69214509105e7ec59fec77b468Dmitry Vyukov  u64 connectsync;
41fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov};
42fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov
43fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukovstatic FdContext fdctx;
44fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov
45175599be65a5c08551bbe0359a7ca1aadb23ec8bDmitry Vyukovstatic bool bogusfd(int fd) {
46175599be65a5c08551bbe0359a7ca1aadb23ec8bDmitry Vyukov  // Apparently a bogus fd value.
472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return fd < 0 || fd >= kTableSize;
48175599be65a5c08551bbe0359a7ca1aadb23ec8bDmitry Vyukov}
49175599be65a5c08551bbe0359a7ca1aadb23ec8bDmitry Vyukov
505d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hinesstatic FdSync *allocsync(ThreadState *thr, uptr pc) {
515d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  FdSync *s = (FdSync*)user_alloc(thr, pc, sizeof(FdSync));
52c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  atomic_store(&s->rc, 1, memory_order_relaxed);
53c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  return s;
54fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov}
55fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov
56c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukovstatic FdSync *ref(FdSync *s) {
57c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  if (s && atomic_load(&s->rc, memory_order_relaxed) != (u64)-1)
58c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov    atomic_fetch_add(&s->rc, 1, memory_order_relaxed);
59c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  return s;
60fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov}
61fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov
62c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukovstatic void unref(ThreadState *thr, uptr pc, FdSync *s) {
63c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  if (s && atomic_load(&s->rc, memory_order_relaxed) != (u64)-1) {
64c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov    if (atomic_fetch_sub(&s->rc, 1, memory_order_acq_rel) == 1) {
65c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov      CHECK_NE(s, &fdctx.globsync);
66c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov      CHECK_NE(s, &fdctx.filesync);
67c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov      CHECK_NE(s, &fdctx.socksync);
685d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines      user_free(thr, pc, s);
69fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov    }
70fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov  }
71fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov}
72fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov
73c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukovstatic FdDesc *fddesc(ThreadState *thr, uptr pc, int fd) {
74175599be65a5c08551bbe0359a7ca1aadb23ec8bDmitry Vyukov  CHECK_GE(fd, 0);
75fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov  CHECK_LT(fd, kTableSize);
76fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov  atomic_uintptr_t *pl1 = &fdctx.tab[fd / kTableSizeL2];
77fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov  uptr l1 = atomic_load(pl1, memory_order_consume);
78fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov  if (l1 == 0) {
79c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov    uptr size = kTableSizeL2 * sizeof(FdDesc);
8077330179d0c0fe876f3b89fca9a23c4504b1e692Alexey Samsonov    // We need this to reside in user memory to properly catch races on it.
8177330179d0c0fe876f3b89fca9a23c4504b1e692Alexey Samsonov    void *p = user_alloc(thr, pc, size);
82fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov    internal_memset(p, 0, size);
83c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov    MemoryResetRange(thr, (uptr)&fddesc, (uptr)p, size);
84fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov    if (atomic_compare_exchange_strong(pl1, &l1, (uptr)p, memory_order_acq_rel))
85fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov      l1 = (uptr)p;
86fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov    else
8777330179d0c0fe876f3b89fca9a23c4504b1e692Alexey Samsonov      user_free(thr, pc, p);
88fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov  }
89c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  return &((FdDesc*)l1)[fd % kTableSizeL2];  // NOLINT
90fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov}
91fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov
92fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov// pd must be already ref'ed.
93c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukovstatic void init(ThreadState *thr, uptr pc, int fd, FdSync *s) {
94c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  FdDesc *d = fddesc(thr, pc, fd);
95fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov  // As a matter of fact, we don't intercept all close calls.
96fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov  // See e.g. libc __res_iclose().
9745d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov  if (d->sync) {
98c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov    unref(thr, pc, d->sync);
9945d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov    d->sync = 0;
10045d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov  }
101e3178e8fab67e77165978006928228f9be2ce30dDmitry Vyukov  if (flags()->io_sync == 0) {
102e3178e8fab67e77165978006928228f9be2ce30dDmitry Vyukov    unref(thr, pc, s);
103e3178e8fab67e77165978006928228f9be2ce30dDmitry Vyukov  } else if (flags()->io_sync == 1) {
104e3178e8fab67e77165978006928228f9be2ce30dDmitry Vyukov    d->sync = s;
105e3178e8fab67e77165978006928228f9be2ce30dDmitry Vyukov  } else if (flags()->io_sync == 2) {
106e3178e8fab67e77165978006928228f9be2ce30dDmitry Vyukov    unref(thr, pc, s);
107e3178e8fab67e77165978006928228f9be2ce30dDmitry Vyukov    d->sync = &fdctx.globsync;
108e3178e8fab67e77165978006928228f9be2ce30dDmitry Vyukov  }
109c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  d->creation_tid = thr->tid;
110c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  d->creation_stack = CurrentStackId(thr, pc);
111fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov  // To catch races between fd usage and open.
112c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  MemoryRangeImitateWrite(thr, pc, (uptr)d, 8);
113fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov}
114fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov
115fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukovvoid FdInit() {
116c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  atomic_store(&fdctx.globsync.rc, (u64)-1, memory_order_relaxed);
117c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  atomic_store(&fdctx.filesync.rc, (u64)-1, memory_order_relaxed);
118c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  atomic_store(&fdctx.socksync.rc, (u64)-1, memory_order_relaxed);
119c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov}
120c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov
1214554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukovvoid FdOnFork(ThreadState *thr, uptr pc) {
1224554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov  // On fork() we need to reset all fd's, because the child is going
1234554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov  // close all them, and that will cause races between previous read/write
1244554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov  // and the close.
1254554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov  for (int l1 = 0; l1 < kTableSizeL1; l1++) {
1264554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov    FdDesc *tab = (FdDesc*)atomic_load(&fdctx.tab[l1], memory_order_relaxed);
1274554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov    if (tab == 0)
1284554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov      break;
1294554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov    for (int l2 = 0; l2 < kTableSizeL2; l2++) {
1304554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov      FdDesc *d = &tab[l2];
1314554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov      MemoryResetRange(thr, pc, (uptr)d, 8);
1324554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov    }
1334554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov  }
1344554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov}
1354554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov
136c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukovbool FdLocation(uptr addr, int *fd, int *tid, u32 *stack) {
137c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  for (int l1 = 0; l1 < kTableSizeL1; l1++) {
138c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov    FdDesc *tab = (FdDesc*)atomic_load(&fdctx.tab[l1], memory_order_relaxed);
139c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov    if (tab == 0)
140c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov      break;
141c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov    if (addr >= (uptr)tab && addr < (uptr)(tab + kTableSizeL2)) {
142c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov      int l2 = (addr - (uptr)tab) / sizeof(FdDesc);
143c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov      FdDesc *d = &tab[l2];
144c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov      *fd = l1 * kTableSizeL1 + l2;
145c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov      *tid = d->creation_tid;
146c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov      *stack = d->creation_stack;
147c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov      return true;
148c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov    }
149c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  }
150c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  return false;
151fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov}
152fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov
153fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukovvoid FdAcquire(ThreadState *thr, uptr pc, int fd) {
154175599be65a5c08551bbe0359a7ca1aadb23ec8bDmitry Vyukov  if (bogusfd(fd))
155175599be65a5c08551bbe0359a7ca1aadb23ec8bDmitry Vyukov    return;
156c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  FdDesc *d = fddesc(thr, pc, fd);
157c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  FdSync *s = d->sync;
158c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  DPrintf("#%d: FdAcquire(%d) -> %p\n", thr->tid, fd, s);
159334553ec45d8982df45a6f5e656e068142ecde3fDmitry Vyukov  MemoryRead(thr, pc, (uptr)d, kSizeLog8);
160c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  if (s)
161c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov    Acquire(thr, pc, (uptr)s);
162fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov}
163fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov
164fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukovvoid FdRelease(ThreadState *thr, uptr pc, int fd) {
165175599be65a5c08551bbe0359a7ca1aadb23ec8bDmitry Vyukov  if (bogusfd(fd))
166175599be65a5c08551bbe0359a7ca1aadb23ec8bDmitry Vyukov    return;
167c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  FdDesc *d = fddesc(thr, pc, fd);
168c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  FdSync *s = d->sync;
169c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  DPrintf("#%d: FdRelease(%d) -> %p\n", thr->tid, fd, s);
17048e54204b82ba982ed7992847413dd0043fdc700Dmitry Vyukov  MemoryRead(thr, pc, (uptr)d, kSizeLog8);
171c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  if (s)
172c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov    Release(thr, pc, (uptr)s);
173fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov}
174fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov
175a597258803f870d859e2e8b18bbb4fabf4d5a3f8Dmitry Vyukovvoid FdAccess(ThreadState *thr, uptr pc, int fd) {
176a597258803f870d859e2e8b18bbb4fabf4d5a3f8Dmitry Vyukov  DPrintf("#%d: FdAccess(%d)\n", thr->tid, fd);
177175599be65a5c08551bbe0359a7ca1aadb23ec8bDmitry Vyukov  if (bogusfd(fd))
178175599be65a5c08551bbe0359a7ca1aadb23ec8bDmitry Vyukov    return;
179a597258803f870d859e2e8b18bbb4fabf4d5a3f8Dmitry Vyukov  FdDesc *d = fddesc(thr, pc, fd);
180334553ec45d8982df45a6f5e656e068142ecde3fDmitry Vyukov  MemoryRead(thr, pc, (uptr)d, kSizeLog8);
181a597258803f870d859e2e8b18bbb4fabf4d5a3f8Dmitry Vyukov}
182a597258803f870d859e2e8b18bbb4fabf4d5a3f8Dmitry Vyukov
183fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukovvoid FdClose(ThreadState *thr, uptr pc, int fd) {
184fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov  DPrintf("#%d: FdClose(%d)\n", thr->tid, fd);
185175599be65a5c08551bbe0359a7ca1aadb23ec8bDmitry Vyukov  if (bogusfd(fd))
186175599be65a5c08551bbe0359a7ca1aadb23ec8bDmitry Vyukov    return;
187c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  FdDesc *d = fddesc(thr, pc, fd);
188fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov  // To catch races between fd usage and close.
189334553ec45d8982df45a6f5e656e068142ecde3fDmitry Vyukov  MemoryWrite(thr, pc, (uptr)d, kSizeLog8);
190fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov  // We need to clear it, because if we do not intercept any call out there
191fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov  // that creates fd, we will hit false postives.
192c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  MemoryResetRange(thr, pc, (uptr)d, 8);
193c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  unref(thr, pc, d->sync);
194c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  d->sync = 0;
195c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  d->creation_tid = 0;
196c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  d->creation_stack = 0;
197fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov}
198fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov
199fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukovvoid FdFileCreate(ThreadState *thr, uptr pc, int fd) {
200fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov  DPrintf("#%d: FdFileCreate(%d)\n", thr->tid, fd);
201175599be65a5c08551bbe0359a7ca1aadb23ec8bDmitry Vyukov  if (bogusfd(fd))
202175599be65a5c08551bbe0359a7ca1aadb23ec8bDmitry Vyukov    return;
203c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  init(thr, pc, fd, &fdctx.filesync);
204fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov}
205fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov
206fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukovvoid FdDup(ThreadState *thr, uptr pc, int oldfd, int newfd) {
207fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov  DPrintf("#%d: FdDup(%d, %d)\n", thr->tid, oldfd, newfd);
208175599be65a5c08551bbe0359a7ca1aadb23ec8bDmitry Vyukov  if (bogusfd(oldfd) || bogusfd(newfd))
209175599be65a5c08551bbe0359a7ca1aadb23ec8bDmitry Vyukov    return;
210fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov  // Ignore the case when user dups not yet connected socket.
211c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  FdDesc *od = fddesc(thr, pc, oldfd);
212334553ec45d8982df45a6f5e656e068142ecde3fDmitry Vyukov  MemoryRead(thr, pc, (uptr)od, kSizeLog8);
213fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov  FdClose(thr, pc, newfd);
214c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  init(thr, pc, newfd, ref(od->sync));
215fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov}
216fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov
217fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukovvoid FdPipeCreate(ThreadState *thr, uptr pc, int rfd, int wfd) {
218fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov  DPrintf("#%d: FdCreatePipe(%d, %d)\n", thr->tid, rfd, wfd);
2195d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  FdSync *s = allocsync(thr, pc);
220e3178e8fab67e77165978006928228f9be2ce30dDmitry Vyukov  init(thr, pc, rfd, ref(s));
221c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  init(thr, pc, wfd, ref(s));
222e3178e8fab67e77165978006928228f9be2ce30dDmitry Vyukov  unref(thr, pc, s);
223fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov}
224fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov
225fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukovvoid FdEventCreate(ThreadState *thr, uptr pc, int fd) {
226fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov  DPrintf("#%d: FdEventCreate(%d)\n", thr->tid, fd);
227175599be65a5c08551bbe0359a7ca1aadb23ec8bDmitry Vyukov  if (bogusfd(fd))
228175599be65a5c08551bbe0359a7ca1aadb23ec8bDmitry Vyukov    return;
2295d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  init(thr, pc, fd, allocsync(thr, pc));
230fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov}
231fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov
23245d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukovvoid FdSignalCreate(ThreadState *thr, uptr pc, int fd) {
23345d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov  DPrintf("#%d: FdSignalCreate(%d)\n", thr->tid, fd);
234175599be65a5c08551bbe0359a7ca1aadb23ec8bDmitry Vyukov  if (bogusfd(fd))
235175599be65a5c08551bbe0359a7ca1aadb23ec8bDmitry Vyukov    return;
23645d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov  init(thr, pc, fd, 0);
23745d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov}
23845d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov
23945d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukovvoid FdInotifyCreate(ThreadState *thr, uptr pc, int fd) {
24045d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov  DPrintf("#%d: FdInotifyCreate(%d)\n", thr->tid, fd);
241175599be65a5c08551bbe0359a7ca1aadb23ec8bDmitry Vyukov  if (bogusfd(fd))
242175599be65a5c08551bbe0359a7ca1aadb23ec8bDmitry Vyukov    return;
24345d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov  init(thr, pc, fd, 0);
24445d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov}
24545d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov
246fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukovvoid FdPollCreate(ThreadState *thr, uptr pc, int fd) {
247fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov  DPrintf("#%d: FdPollCreate(%d)\n", thr->tid, fd);
248175599be65a5c08551bbe0359a7ca1aadb23ec8bDmitry Vyukov  if (bogusfd(fd))
249175599be65a5c08551bbe0359a7ca1aadb23ec8bDmitry Vyukov    return;
2505d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  init(thr, pc, fd, allocsync(thr, pc));
251fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov}
252fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov
253fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukovvoid FdSocketCreate(ThreadState *thr, uptr pc, int fd) {
254fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov  DPrintf("#%d: FdSocketCreate(%d)\n", thr->tid, fd);
255175599be65a5c08551bbe0359a7ca1aadb23ec8bDmitry Vyukov  if (bogusfd(fd))
256175599be65a5c08551bbe0359a7ca1aadb23ec8bDmitry Vyukov    return;
257fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov  // It can be a UDP socket.
258c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  init(thr, pc, fd, &fdctx.socksync);
259fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov}
260fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov
261fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukovvoid FdSocketAccept(ThreadState *thr, uptr pc, int fd, int newfd) {
262fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov  DPrintf("#%d: FdSocketAccept(%d, %d)\n", thr->tid, fd, newfd);
263175599be65a5c08551bbe0359a7ca1aadb23ec8bDmitry Vyukov  if (bogusfd(fd))
264175599be65a5c08551bbe0359a7ca1aadb23ec8bDmitry Vyukov    return;
265ed513f69b8017a69214509105e7ec59fec77b468Dmitry Vyukov  // Synchronize connect->accept.
266ed513f69b8017a69214509105e7ec59fec77b468Dmitry Vyukov  Acquire(thr, pc, (uptr)&fdctx.connectsync);
267c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  init(thr, pc, newfd, &fdctx.socksync);
268fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov}
269fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov
270ed513f69b8017a69214509105e7ec59fec77b468Dmitry Vyukovvoid FdSocketConnecting(ThreadState *thr, uptr pc, int fd) {
271ed513f69b8017a69214509105e7ec59fec77b468Dmitry Vyukov  DPrintf("#%d: FdSocketConnecting(%d)\n", thr->tid, fd);
272175599be65a5c08551bbe0359a7ca1aadb23ec8bDmitry Vyukov  if (bogusfd(fd))
273175599be65a5c08551bbe0359a7ca1aadb23ec8bDmitry Vyukov    return;
274ed513f69b8017a69214509105e7ec59fec77b468Dmitry Vyukov  // Synchronize connect->accept.
275ed513f69b8017a69214509105e7ec59fec77b468Dmitry Vyukov  Release(thr, pc, (uptr)&fdctx.connectsync);
276ed513f69b8017a69214509105e7ec59fec77b468Dmitry Vyukov}
277ed513f69b8017a69214509105e7ec59fec77b468Dmitry Vyukov
278fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukovvoid FdSocketConnect(ThreadState *thr, uptr pc, int fd) {
279fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov  DPrintf("#%d: FdSocketConnect(%d)\n", thr->tid, fd);
280175599be65a5c08551bbe0359a7ca1aadb23ec8bDmitry Vyukov  if (bogusfd(fd))
281175599be65a5c08551bbe0359a7ca1aadb23ec8bDmitry Vyukov    return;
282c2234cd922bbd94e276e0bebb08004d63cbc5cf2Dmitry Vyukov  init(thr, pc, fd, &fdctx.socksync);
283fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov}
284fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov
2852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesuptr File2addr(const char *path) {
286fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov  (void)path;
287fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov  static u64 addr;
288fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov  return (uptr)&addr;
289fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov}
290fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov
2912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesuptr Dir2addr(const char *path) {
292fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov  (void)path;
293fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov  static u64 addr;
294fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov  return (uptr)&addr;
295fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov}
296fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov
297fb8ca8143896ef012d9e2bcb20ff3e4cfed93092Dmitry Vyukov}  //  namespace __tsan
298