17ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//===-- tsan_sync.h ---------------------------------------------*- C++ -*-===// 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// 127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//===----------------------------------------------------------------------===// 137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#ifndef TSAN_SYNC_H 147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#define TSAN_SYNC_H 157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 16fce5bd4cc29fddb5e8f0cb9c12df7c10187a991dDmitry Vyukov#include "sanitizer_common/sanitizer_atomic.h" 17fce5bd4cc29fddb5e8f0cb9c12df7c10187a991dDmitry Vyukov#include "sanitizer_common/sanitizer_common.h" 187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_clock.h" 197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_defs.h" 207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_mutex.h" 217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanynamespace __tsan { 237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyclass SlabCache; 257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyclass StackTrace { 277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany public: 287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StackTrace(); 299ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov // Initialized the object in "static mode", 309ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov // in this mode it never calls malloc/free but uses the provided buffer. 319ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov StackTrace(uptr *buf, uptr cnt); 327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ~StackTrace(); 337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany void Reset(); 347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany void Init(const uptr *pcs, uptr cnt); 367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany void ObtainCurrent(ThreadState *thr, uptr toppc); 377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany bool IsEmpty() const; 387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr Size() const; 397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr Get(uptr i) const; 407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany const uptr *Begin() const; 417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany void CopyFrom(const StackTrace& other); 427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany private: 447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr n_; 457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr *s_; 469ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov const uptr c_; 477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StackTrace(const StackTrace&); 497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany void operator = (const StackTrace&); 507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}; 517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystruct SyncVar { 537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany explicit SyncVar(uptr addr); 547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany static const int kInvalidTid = -1; 567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Mutex mtx; 587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany const uptr addr; 597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SyncClock clock; 607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SyncClock read_clock; // Used for rw mutexes only. 6126127735454fddae3495794f38189d57dde6510fDmitry Vyukov StackTrace creation_stack; 627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int owner_tid; // Set only by exclusive owners. 63332c62b52b3603be872b28bd3ea5e739aa28cd05Dmitry Vyukov u64 last_lock; 647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int recursion; 657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany bool is_rw; 667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany bool is_recursive; 677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany bool is_broken; 682e933fc077595b18de37d2ed44e8f14c6053a432Dmitry Vyukov bool is_linker_init; 697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SyncVar *next; // In SyncTab hashtable. 7026127735454fddae3495794f38189d57dde6510fDmitry Vyukov 7126127735454fddae3495794f38189d57dde6510fDmitry Vyukov uptr GetMemoryConsumption(); 727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}; 737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyclass SyncTab { 757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany public: 767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SyncTab(); 777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ~SyncTab(); 787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // If the SyncVar does not exist yet, it is created. 807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SyncVar* GetAndLock(ThreadState *thr, uptr pc, 817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr addr, bool write_lock); 827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // If the SyncVar does not exist, returns 0. 847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SyncVar* GetAndRemove(ThreadState *thr, uptr pc, uptr addr); 857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 8626127735454fddae3495794f38189d57dde6510fDmitry Vyukov uptr GetMemoryConsumption(uptr *nsync); 8726127735454fddae3495794f38189d57dde6510fDmitry Vyukov 887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany private: 897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany struct Part { 907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Mutex mtx; 917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SyncVar *val; 927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany char pad[kCacheLineSize - sizeof(Mutex) - sizeof(SyncVar*)]; // NOLINT 937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Part(); 947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany }; 957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // FIXME: Implement something more sane. 977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany static const int kPartCount = 1009; 987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Part tab_[kPartCount]; 997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int PartIdx(uptr addr); 1017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SyncTab(const SyncTab&); // Not implemented. 1037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany void operator = (const SyncTab&); // Not implemented. 1047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}; 1057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} // namespace __tsan 1077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif // TSAN_SYNC_H 109