tsan_sync.cc revision 603c4be006d8c53905d736bf1f19a49f5ce98276
1603c4be006d8c53905d736bf1f19a49f5ce98276Alexey Samsonov//===-- tsan_sync.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// 127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//===----------------------------------------------------------------------===// 137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_sync.h" 147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_placement_new.h" 157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_rtl.h" 167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_mman.h" 177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanynamespace __tsan { 197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 207ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanySyncVar::SyncVar(uptr addr) 217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany : mtx(MutexTypeSyncVar, StatMtxSyncVar) 227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , addr(addr) 237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , owner_tid(kInvalidTid) 247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , recursion() 257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , is_rw() 267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , is_recursive() 277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , is_broken() { 287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 307ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanySyncTab::Part::Part() 317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany : mtx(MutexTypeSyncTab, StatMtxSyncTab) 327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , val() { 337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 357ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanySyncTab::SyncTab() { 367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 387ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanySyncTab::~SyncTab() { 397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (int i = 0; i < kPartCount; i++) { 407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany while (tab_[i].val) { 417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SyncVar *tmp = tab_[i].val; 427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany tab_[i].val = tmp->next; 437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany DestroyAndFree(tmp); 447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 487ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanySyncVar* SyncTab::GetAndLock(ThreadState *thr, uptr pc, 497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr addr, bool write_lock) { 507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Part *p = &tab_[PartIdx(addr)]; 517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany { 527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ReadLock l(&p->mtx); 537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (SyncVar *res = p->val; res; res = res->next) { 547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res->addr == addr) { 557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (write_lock) 567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany res->mtx.Lock(); 577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany else 587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany res->mtx.ReadLock(); 597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany { 647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Lock l(&p->mtx); 657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SyncVar *res = p->val; 667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (; res; res = res->next) { 677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res->addr == addr) 687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany break; 697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res == 0) { 717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StatInc(thr, StatSyncCreated); 727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany void *mem = internal_alloc(MBlockSync, sizeof(SyncVar)); 737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany res = new(mem) SyncVar(addr); 747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany res->creation_stack.ObtainCurrent(thr, pc); 757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany res->next = p->val; 767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany p->val = res; 777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (write_lock) 797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany res->mtx.Lock(); 807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany else 817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany res->mtx.ReadLock(); 827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 867ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanySyncVar* SyncTab::GetAndRemove(ThreadState *thr, uptr pc, uptr addr) { 877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Part *p = &tab_[PartIdx(addr)]; 887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SyncVar *res = 0; 897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany { 907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Lock l(&p->mtx); 917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SyncVar **prev = &p->val; 927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany res = *prev; 937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany while (res) { 947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res->addr == addr) { 957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany *prev = res->next; 967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany break; 977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany prev = &res->next; 997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany res = *prev; 1007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 1017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 1027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res) { 1037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StatInc(thr, StatSyncDestroyed); 1047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany res->mtx.Lock(); 1057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany res->mtx.Unlock(); 1067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 1077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 1087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 11026127735454fddae3495794f38189d57dde6510fDmitry Vyukovuptr SyncVar::GetMemoryConsumption() { 11126127735454fddae3495794f38189d57dde6510fDmitry Vyukov return sizeof(*this) 11226127735454fddae3495794f38189d57dde6510fDmitry Vyukov + clock.size() * sizeof(u64) 11326127735454fddae3495794f38189d57dde6510fDmitry Vyukov + read_clock.size() * sizeof(u64) 11426127735454fddae3495794f38189d57dde6510fDmitry Vyukov + creation_stack.Size() * sizeof(uptr); 11526127735454fddae3495794f38189d57dde6510fDmitry Vyukov} 11626127735454fddae3495794f38189d57dde6510fDmitry Vyukov 11726127735454fddae3495794f38189d57dde6510fDmitry Vyukovuptr SyncTab::GetMemoryConsumption(uptr *nsync) { 11826127735454fddae3495794f38189d57dde6510fDmitry Vyukov uptr mem = 0; 11926127735454fddae3495794f38189d57dde6510fDmitry Vyukov for (int i = 0; i < kPartCount; i++) { 12026127735454fddae3495794f38189d57dde6510fDmitry Vyukov Part *p = &tab_[i]; 12126127735454fddae3495794f38189d57dde6510fDmitry Vyukov Lock l(&p->mtx); 12226127735454fddae3495794f38189d57dde6510fDmitry Vyukov for (SyncVar *s = p->val; s; s = s->next) { 12326127735454fddae3495794f38189d57dde6510fDmitry Vyukov *nsync += 1; 12426127735454fddae3495794f38189d57dde6510fDmitry Vyukov mem += s->GetMemoryConsumption(); 12526127735454fddae3495794f38189d57dde6510fDmitry Vyukov } 12626127735454fddae3495794f38189d57dde6510fDmitry Vyukov } 12726127735454fddae3495794f38189d57dde6510fDmitry Vyukov return mem; 12826127735454fddae3495794f38189d57dde6510fDmitry Vyukov} 12926127735454fddae3495794f38189d57dde6510fDmitry Vyukov 1307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyint SyncTab::PartIdx(uptr addr) { 1317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return (addr >> 3) % kPartCount; 1327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1347ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyStackTrace::StackTrace() 1357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany : n_() 1367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , s_() { 1377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1397ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyStackTrace::~StackTrace() { 1407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Reset(); 1417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid StackTrace::Reset() { 1447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (s_) { 1457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK_NE(n_, 0); 1467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany internal_free(s_); 1477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany s_ = 0; 1487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany n_ = 0; 1497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 1507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid StackTrace::Init(const uptr *pcs, uptr cnt) { 1537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Reset(); 1547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (cnt == 0) 1557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 1567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany n_ = cnt; 1577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany s_ = (uptr*)internal_alloc(MBlockStackTrace, cnt * sizeof(s_[0])); 1587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany internal_memcpy(s_, pcs, cnt * sizeof(s_[0])); 1597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid StackTrace::ObtainCurrent(ThreadState *thr, uptr toppc) { 1627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Reset(); 1637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany n_ = thr->shadow_stack_pos - &thr->shadow_stack[0]; 1647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (n_ + !!toppc == 0) 1657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 1667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany s_ = (uptr*)internal_alloc(MBlockStackTrace, (n_ + !!toppc) * sizeof(s_[0])); 1677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (uptr i = 0; i < n_; i++) 1687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany s_[i] = thr->shadow_stack[i]; 1697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (toppc) { 1707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany s_[n_] = toppc; 1717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany n_++; 1727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 1737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid StackTrace::CopyFrom(const StackTrace& other) { 1767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Reset(); 1777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Init(other.Begin(), other.Size()); 1787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanybool StackTrace::IsEmpty() const { 1817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return n_ == 0; 1827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyuptr StackTrace::Size() const { 1857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return n_; 1867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyuptr StackTrace::Get(uptr i) const { 1897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK_LT(i, n_); 1907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return s_[i]; 1917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst uptr *StackTrace::Begin() const { 1947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return s_; 1957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} // namespace __tsan 198