tsan_sync.cc revision 9ad7c32720dfa1287f8cfd481e5d583435178cae
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//===----------------------------------------------------------------------===// 1347b1634df012507799eb39aa17d4022d748ba67bAlexey Samsonov#include "sanitizer_common/sanitizer_placement_new.h" 147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_sync.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_() 1369ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov , s_() 1379ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov , c_() { 1389ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov} 1399ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov 1409ad7c32720dfa1287f8cfd481e5d583435178caeDmitry VyukovStackTrace::StackTrace(uptr *buf, uptr cnt) 1419ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov : n_() 1429ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov , s_(buf) 1439ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov , c_(cnt) { 1449ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov CHECK_NE(buf, 0); 1459ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov CHECK_NE(cnt, 0); 1467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1487ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyStackTrace::~StackTrace() { 1497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Reset(); 1507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid StackTrace::Reset() { 1539ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov if (s_ && !c_) { 1547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK_NE(n_, 0); 1557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany internal_free(s_); 1567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany s_ = 0; 1577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 1589ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov n_ = 0; 1597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid StackTrace::Init(const uptr *pcs, uptr cnt) { 1627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Reset(); 1637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (cnt == 0) 1647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 1659ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov if (c_) { 1669ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov CHECK_NE(s_, 0); 1679ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov CHECK_LE(cnt, c_); 1689ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov } else { 1699ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov s_ = (uptr*)internal_alloc(MBlockStackTrace, cnt * sizeof(s_[0])); 1709ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov } 1717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany n_ = cnt; 1729ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov internal_memcpy(s_, pcs, cnt * sizeof(s_[0])); 1737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid StackTrace::ObtainCurrent(ThreadState *thr, uptr toppc) { 1767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Reset(); 1777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany n_ = thr->shadow_stack_pos - &thr->shadow_stack[0]; 1787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (n_ + !!toppc == 0) 1797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 1809ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov if (c_) { 1819ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov CHECK_NE(s_, 0); 1829ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov CHECK_LE(n_ + !!toppc, c_); 1839ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov } else { 1849ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov s_ = (uptr*)internal_alloc(MBlockStackTrace, 1859ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov (n_ + !!toppc) * sizeof(s_[0])); 1869ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov } 1877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (uptr i = 0; i < n_; i++) 1887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany s_[i] = thr->shadow_stack[i]; 1897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (toppc) { 1907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany s_[n_] = toppc; 1917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany n_++; 1927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 1937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid StackTrace::CopyFrom(const StackTrace& other) { 1967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Reset(); 1977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Init(other.Begin(), other.Size()); 1987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanybool StackTrace::IsEmpty() const { 2017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return n_ == 0; 2027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyuptr StackTrace::Size() const { 2057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return n_; 2067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyuptr StackTrace::Get(uptr i) const { 2097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK_LT(i, n_); 2107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return s_[i]; 2117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst uptr *StackTrace::Begin() const { 2147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return s_; 2157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} // namespace __tsan 218