tsan_sync.cc revision 2d1fdb26e458c4ddc04155c1d421bced3ba90cd0
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 202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid DDMutexInit(ThreadState *thr, uptr pc, SyncVar *s); 212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 22ad9da372f962495b3487685232d09390be841b1cDmitry VyukovSyncVar::SyncVar(uptr addr, u64 uid) 237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany : mtx(MutexTypeSyncVar, StatMtxSyncVar) 247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , addr(addr) 25ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov , uid(uid) 262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines , creation_stack_id() 277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , owner_tid(kInvalidTid) 28332c62b52b3603be872b28bd3ea5e739aa28cd05Dmitry Vyukov , last_lock() 297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , recursion() 307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , is_rw() 317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , is_recursive() 322e933fc077595b18de37d2ed44e8f14c6053a432Dmitry Vyukov , is_broken() 332e933fc077595b18de37d2ed44e8f14c6053a432Dmitry Vyukov , is_linker_init() { 347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 367ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanySyncTab::Part::Part() 377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany : mtx(MutexTypeSyncTab, StatMtxSyncTab) 387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , val() { 397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 417ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanySyncTab::SyncTab() { 427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 447ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanySyncTab::~SyncTab() { 457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (int i = 0; i < kPartCount; i++) { 467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany while (tab_[i].val) { 477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SyncVar *tmp = tab_[i].val; 487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany tab_[i].val = tmp->next; 497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany DestroyAndFree(tmp); 507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 54ad9da372f962495b3487685232d09390be841b1cDmitry VyukovSyncVar* SyncTab::GetOrCreateAndLock(ThreadState *thr, uptr pc, 55ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov uptr addr, bool write_lock) { 56ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov return GetAndLock(thr, pc, addr, write_lock, true); 57ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov} 58ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov 59ad9da372f962495b3487685232d09390be841b1cDmitry VyukovSyncVar* SyncTab::GetIfExistsAndLock(uptr addr, bool write_lock) { 60ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov return GetAndLock(0, 0, addr, write_lock, false); 61ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov} 62ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov 6321cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry VyukovSyncVar* SyncTab::Create(ThreadState *thr, uptr pc, uptr addr) { 6421cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov StatInc(thr, StatSyncCreated); 6521cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov void *mem = internal_alloc(MBlockSync, sizeof(SyncVar)); 6621cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov const u64 uid = atomic_fetch_add(&uid_gen_, 1, memory_order_relaxed); 6721cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov SyncVar *res = new(mem) SyncVar(addr, uid); 682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines res->creation_stack_id = 0; 692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (!kGoMode) // Go does not use them 702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines res->creation_stack_id = CurrentStackId(thr, pc); 712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (flags()->detect_deadlocks) 722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines DDMutexInit(thr, pc, res); 7321cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov return res; 7421cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov} 7521cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov 767ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanySyncVar* SyncTab::GetAndLock(ThreadState *thr, uptr pc, 77ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov uptr addr, bool write_lock, bool create) { 789bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov#ifndef TSAN_GO 7921cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov { // NOLINT 8021cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov SyncVar *res = GetJavaSync(thr, pc, addr, write_lock, create); 8121cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov if (res) 8221cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov return res; 8321cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov } 8421cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov 854554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov // Here we ask only PrimaryAllocator, because 864554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov // SecondaryAllocator::PointerIsMine() is slow and we have fallback on 874554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov // the hashmap anyway. 889bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov if (PrimaryAllocator::PointerIsMine((void*)addr)) { 899bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov MBlock *b = user_mblock(thr, (void*)addr); 9003049413f8978c202a254eb0acfa2f10b9bbe34aDmitry Vyukov CHECK_NE(b, 0); 91f51c3860ce0a1ae81d0dc9da27db0693718db18eDmitry Vyukov MBlock::ScopedLock l(b); 929bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov SyncVar *res = 0; 93f51c3860ce0a1ae81d0dc9da27db0693718db18eDmitry Vyukov for (res = b->ListHead(); res; res = res->next) { 949bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov if (res->addr == addr) 959bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov break; 969bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov } 979bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov if (res == 0) { 98ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov if (!create) 99ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov return 0; 10021cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov res = Create(thr, pc, addr); 101f51c3860ce0a1ae81d0dc9da27db0693718db18eDmitry Vyukov b->ListPush(res); 1029bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov } 1039bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov if (write_lock) 1049bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov res->mtx.Lock(); 1059bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov else 1069bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov res->mtx.ReadLock(); 1079bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov return res; 1089bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov } 1099bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov#endif 1109bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov 1117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Part *p = &tab_[PartIdx(addr)]; 1127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany { 1137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ReadLock l(&p->mtx); 1147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (SyncVar *res = p->val; res; res = res->next) { 1157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res->addr == addr) { 1167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (write_lock) 1177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany res->mtx.Lock(); 1187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany else 1197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany res->mtx.ReadLock(); 1207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 1217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 1227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 1237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 124ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov if (!create) 125ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov return 0; 1267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany { 1277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Lock l(&p->mtx); 1287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SyncVar *res = p->val; 1297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (; res; res = res->next) { 1307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res->addr == addr) 1317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany break; 1327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 1337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res == 0) { 13421cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov res = Create(thr, pc, addr); 1357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany res->next = p->val; 1367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany p->val = res; 1377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 1387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (write_lock) 1397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany res->mtx.Lock(); 1407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany else 1417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany res->mtx.ReadLock(); 1427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 1437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 1447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1467ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanySyncVar* SyncTab::GetAndRemove(ThreadState *thr, uptr pc, uptr addr) { 1479bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov#ifndef TSAN_GO 14821cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov { // NOLINT 14921cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov SyncVar *res = GetAndRemoveJavaSync(thr, pc, addr); 15021cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov if (res) 15121cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov return res; 15221cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov } 1539bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov if (PrimaryAllocator::PointerIsMine((void*)addr)) { 1549bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov MBlock *b = user_mblock(thr, (void*)addr); 15503049413f8978c202a254eb0acfa2f10b9bbe34aDmitry Vyukov CHECK_NE(b, 0); 1569bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov SyncVar *res = 0; 1579bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov { 158f51c3860ce0a1ae81d0dc9da27db0693718db18eDmitry Vyukov MBlock::ScopedLock l(b); 159f51c3860ce0a1ae81d0dc9da27db0693718db18eDmitry Vyukov res = b->ListHead(); 160f51c3860ce0a1ae81d0dc9da27db0693718db18eDmitry Vyukov if (res) { 1619bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov if (res->addr == addr) { 16255e711ed818d7553d62eba4b3a2fad3e2723f697Dmitry Vyukov if (res->is_linker_init) 16355e711ed818d7553d62eba4b3a2fad3e2723f697Dmitry Vyukov return 0; 164f51c3860ce0a1ae81d0dc9da27db0693718db18eDmitry Vyukov b->ListPop(); 165f51c3860ce0a1ae81d0dc9da27db0693718db18eDmitry Vyukov } else { 166f51c3860ce0a1ae81d0dc9da27db0693718db18eDmitry Vyukov SyncVar **prev = &res->next; 167f51c3860ce0a1ae81d0dc9da27db0693718db18eDmitry Vyukov res = *prev; 168f51c3860ce0a1ae81d0dc9da27db0693718db18eDmitry Vyukov while (res) { 169f51c3860ce0a1ae81d0dc9da27db0693718db18eDmitry Vyukov if (res->addr == addr) { 170f51c3860ce0a1ae81d0dc9da27db0693718db18eDmitry Vyukov if (res->is_linker_init) 171f51c3860ce0a1ae81d0dc9da27db0693718db18eDmitry Vyukov return 0; 172f51c3860ce0a1ae81d0dc9da27db0693718db18eDmitry Vyukov *prev = res->next; 173f51c3860ce0a1ae81d0dc9da27db0693718db18eDmitry Vyukov break; 174f51c3860ce0a1ae81d0dc9da27db0693718db18eDmitry Vyukov } 175f51c3860ce0a1ae81d0dc9da27db0693718db18eDmitry Vyukov prev = &res->next; 176f51c3860ce0a1ae81d0dc9da27db0693718db18eDmitry Vyukov res = *prev; 177f51c3860ce0a1ae81d0dc9da27db0693718db18eDmitry Vyukov } 178f51c3860ce0a1ae81d0dc9da27db0693718db18eDmitry Vyukov } 179f51c3860ce0a1ae81d0dc9da27db0693718db18eDmitry Vyukov if (res) { 180f51c3860ce0a1ae81d0dc9da27db0693718db18eDmitry Vyukov StatInc(thr, StatSyncDestroyed); 181f51c3860ce0a1ae81d0dc9da27db0693718db18eDmitry Vyukov res->mtx.Lock(); 182f51c3860ce0a1ae81d0dc9da27db0693718db18eDmitry Vyukov res->mtx.Unlock(); 1839bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov } 1849bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov } 1859bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov } 1869bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov return res; 1879bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov } 1889bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov#endif 1899bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov 1907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Part *p = &tab_[PartIdx(addr)]; 1917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SyncVar *res = 0; 1927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany { 1937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Lock l(&p->mtx); 1947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SyncVar **prev = &p->val; 1957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany res = *prev; 1967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany while (res) { 1977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res->addr == addr) { 19855e711ed818d7553d62eba4b3a2fad3e2723f697Dmitry Vyukov if (res->is_linker_init) 19955e711ed818d7553d62eba4b3a2fad3e2723f697Dmitry Vyukov return 0; 2007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany *prev = res->next; 2017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany break; 2027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 2037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany prev = &res->next; 2047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany res = *prev; 2057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 2067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 2077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res) { 2087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StatInc(thr, StatSyncDestroyed); 2097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany res->mtx.Lock(); 2107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany res->mtx.Unlock(); 2117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 2127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 2137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyint SyncTab::PartIdx(uptr addr) { 2167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return (addr >> 3) % kPartCount; 2177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2197ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyStackTrace::StackTrace() 2207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany : n_() 2219ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov , s_() 2229ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov , c_() { 2239ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov} 2249ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov 2259ad7c32720dfa1287f8cfd481e5d583435178caeDmitry VyukovStackTrace::StackTrace(uptr *buf, uptr cnt) 2269ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov : n_() 2279ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov , s_(buf) 2289ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov , c_(cnt) { 2299ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov CHECK_NE(buf, 0); 2309ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov CHECK_NE(cnt, 0); 2317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2337ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyStackTrace::~StackTrace() { 2347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Reset(); 2357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid StackTrace::Reset() { 2389ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov if (s_ && !c_) { 2397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK_NE(n_, 0); 2407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany internal_free(s_); 2417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany s_ = 0; 2427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 2439ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov n_ = 0; 2447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid StackTrace::Init(const uptr *pcs, uptr cnt) { 2477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Reset(); 2487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (cnt == 0) 2497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 2509ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov if (c_) { 2519ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov CHECK_NE(s_, 0); 2529ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov CHECK_LE(cnt, c_); 2539ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov } else { 2549ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov s_ = (uptr*)internal_alloc(MBlockStackTrace, cnt * sizeof(s_[0])); 2559ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov } 2567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany n_ = cnt; 2579ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov internal_memcpy(s_, pcs, cnt * sizeof(s_[0])); 2587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid StackTrace::ObtainCurrent(ThreadState *thr, uptr toppc) { 2617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Reset(); 26225d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov n_ = thr->shadow_stack_pos - thr->shadow_stack; 2637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (n_ + !!toppc == 0) 2647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 2650ab628c61594eb80612e5389d9c33da0e0d70c66Dmitry Vyukov uptr start = 0; 2669ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov if (c_) { 2679ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov CHECK_NE(s_, 0); 2680ab628c61594eb80612e5389d9c33da0e0d70c66Dmitry Vyukov if (n_ + !!toppc > c_) { 2690ab628c61594eb80612e5389d9c33da0e0d70c66Dmitry Vyukov start = n_ - c_ + !!toppc; 2700ab628c61594eb80612e5389d9c33da0e0d70c66Dmitry Vyukov n_ = c_ - !!toppc; 2710ab628c61594eb80612e5389d9c33da0e0d70c66Dmitry Vyukov } 2729ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov } else { 27301a7ce809bf7cc627d73c045c70bcca9891f632cDmitry Vyukov // Cap potentially huge stacks. 27401a7ce809bf7cc627d73c045c70bcca9891f632cDmitry Vyukov if (n_ + !!toppc > kTraceStackSize) { 27501a7ce809bf7cc627d73c045c70bcca9891f632cDmitry Vyukov start = n_ - kTraceStackSize + !!toppc; 27601a7ce809bf7cc627d73c045c70bcca9891f632cDmitry Vyukov n_ = kTraceStackSize - !!toppc; 27701a7ce809bf7cc627d73c045c70bcca9891f632cDmitry Vyukov } 2789ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov s_ = (uptr*)internal_alloc(MBlockStackTrace, 2799ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov (n_ + !!toppc) * sizeof(s_[0])); 2809ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov } 2817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (uptr i = 0; i < n_; i++) 2820ab628c61594eb80612e5389d9c33da0e0d70c66Dmitry Vyukov s_[i] = thr->shadow_stack[start + i]; 2837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (toppc) { 2847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany s_[n_] = toppc; 2857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany n_++; 2867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 2877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid StackTrace::CopyFrom(const StackTrace& other) { 2907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Reset(); 2917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Init(other.Begin(), other.Size()); 2927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanybool StackTrace::IsEmpty() const { 2957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return n_ == 0; 2967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyuptr StackTrace::Size() const { 2997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return n_; 3007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyuptr StackTrace::Get(uptr i) const { 3037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK_LT(i, n_); 3047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return s_[i]; 3057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst uptr *StackTrace::Begin() const { 3087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return s_; 3097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} // namespace __tsan 312