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