tsan_mman.cc revision 1acfa02e08e6d3316c80f52255cbb7d9e3164128
1603c4be006d8c53905d736bf1f19a49f5ce98276Alexey Samsonov//===-- tsan_mman.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//===----------------------------------------------------------------------===//
13f7667cc84cdd8923c0b6c7cfc92b7bd5692ce18cAlexey Samsonov#include "sanitizer_common/sanitizer_common.h"
142e87051d136db3150a3ca322d8862f92b0a684bbDmitry Vyukov#include "sanitizer_common/sanitizer_placement_new.h"
157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_mman.h"
167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_rtl.h"
177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_report.h"
187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_flags.h"
197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
204f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov// May be overriden by front-end.
214f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonovextern "C" void WEAK __tsan_malloc_hook(void *ptr, uptr size) {
224f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov  (void)ptr;
234f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov  (void)size;
244f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov}
254f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov
264f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonovextern "C" void WEAK __tsan_free_hook(void *ptr) {
274f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov  (void)ptr;
284f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov}
294f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov
307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanynamespace __tsan {
317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
32ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukovstatic char allocator_placeholder[sizeof(Allocator)] ALIGNED(64);
33ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry VyukovAllocator *allocator() {
342e87051d136db3150a3ca322d8862f92b0a684bbDmitry Vyukov  return reinterpret_cast<Allocator*>(&allocator_placeholder);
352e87051d136db3150a3ca322d8862f92b0a684bbDmitry Vyukov}
362e87051d136db3150a3ca322d8862f92b0a684bbDmitry Vyukov
372e87051d136db3150a3ca322d8862f92b0a684bbDmitry Vyukovvoid InitializeAllocator() {
382e87051d136db3150a3ca322d8862f92b0a684bbDmitry Vyukov  allocator()->Init();
392e87051d136db3150a3ca322d8862f92b0a684bbDmitry Vyukov}
402e87051d136db3150a3ca322d8862f92b0a684bbDmitry Vyukov
41bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukovvoid AllocatorThreadStart(ThreadState *thr) {
42bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  allocator()->InitCache(&thr->alloc_cache);
43bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov}
44bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov
45bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukovvoid AllocatorThreadFinish(ThreadState *thr) {
46bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  allocator()->DestroyCache(&thr->alloc_cache);
47bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov}
48bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov
49bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukovvoid AllocatorPrintStats() {
50bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  allocator()->PrintStats();
512e87051d136db3150a3ca322d8862f92b0a684bbDmitry Vyukov}
522e87051d136db3150a3ca322d8862f92b0a684bbDmitry Vyukov
537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void SignalUnsafeCall(ThreadState *thr, uptr pc) {
547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (!thr->in_signal_handler || !flags()->report_signal_unsafe)
557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
56158c6ac3bb46753db217f9c2c73485811a3a1890Dmitry Vyukov  Context *ctx = CTX();
577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StackTrace stack;
587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  stack.ObtainCurrent(thr, pc);
59fb917e9069ea44f7103f50c658be84a8f66de56cDmitry Vyukov  Lock l(&ctx->thread_mtx);
607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ScopedReport rep(ReportTypeSignalUnsafe);
61158c6ac3bb46753db217f9c2c73485811a3a1890Dmitry Vyukov  if (!IsFiredSuppression(ctx, rep, stack)) {
62158c6ac3bb46753db217f9c2c73485811a3a1890Dmitry Vyukov    rep.AddStack(&stack);
63158c6ac3bb46753db217f9c2c73485811a3a1890Dmitry Vyukov    OutputReport(ctx, rep, rep.GetReport()->stacks[0]);
64158c6ac3bb46753db217f9c2c73485811a3a1890Dmitry Vyukov  }
657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
672e87051d136db3150a3ca322d8862f92b0a684bbDmitry Vyukovvoid *user_alloc(ThreadState *thr, uptr pc, uptr sz, uptr align) {
687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK_GT(thr->in_rtl, 0);
692e87051d136db3150a3ca322d8862f92b0a684bbDmitry Vyukov  void *p = allocator()->Allocate(&thr->alloc_cache, sz, align);
702e87051d136db3150a3ca322d8862f92b0a684bbDmitry Vyukov  if (p == 0)
71efd958213d70188ae6f79afd79fe2c84956d24ffDmitry Vyukov    return 0;
72ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov  MBlock *b = new(allocator()->GetMetaData(p)) MBlock;
737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  b->size = sz;
74ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov  b->head = 0;
75ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov  b->alloc_tid = thr->unique_id;
76848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  b->alloc_stack_id = CurrentStackId(thr, pc);
777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (CTX() && CTX()->initialized) {
789bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov    MemoryRangeImitateWrite(thr, pc, (uptr)p, sz);
797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
80e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov  DPrintf("#%d: alloc(%zu) = %p\n", thr->tid, sz, p);
817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SignalUnsafeCall(thr, pc);
827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return p;
837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid user_free(ThreadState *thr, uptr pc, void *p) {
867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK_GT(thr->in_rtl, 0);
877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK_NE(p, (void*)0);
887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  DPrintf("#%d: free(%p)\n", thr->tid, p);
892e87051d136db3150a3ca322d8862f92b0a684bbDmitry Vyukov  MBlock *b = (MBlock*)allocator()->GetMetaData(p);
909bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov  if (b->head)   {
919bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov    Lock l(&b->mtx);
929bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov    for (SyncVar *s = b->head; s;) {
939bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov      SyncVar *res = s;
949bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov      s = s->next;
959bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov      StatInc(thr, StatSyncDestroyed);
969bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov      res->mtx.Lock();
979bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov      res->mtx.Unlock();
989bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov      DestroyAndFree(res);
999bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov    }
1009bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov    b->head = 0;
1019bbc579e11900741551b81b5e91d22ca47d70b26Dmitry Vyukov  }
1027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (CTX() && CTX()->initialized && thr->in_rtl == 1) {
1037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    MemoryRangeFreed(thr, pc, (uptr)p, b->size);
1047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
105ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov  b->~MBlock();
1062e87051d136db3150a3ca322d8862f92b0a684bbDmitry Vyukov  allocator()->Deallocate(&thr->alloc_cache, p);
1077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SignalUnsafeCall(thr, pc);
1087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
1097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid *user_realloc(ThreadState *thr, uptr pc, void *p, uptr sz) {
1117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK_GT(thr->in_rtl, 0);
1127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  void *p2 = 0;
1137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // FIXME: Handle "shrinking" more efficiently,
1147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // it seems that some software actually does this.
1157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (sz) {
1167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    p2 = user_alloc(thr, pc, sz);
117efd958213d70188ae6f79afd79fe2c84956d24ffDmitry Vyukov    if (p2 == 0)
118efd958213d70188ae6f79afd79fe2c84956d24ffDmitry Vyukov      return 0;
1197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    if (p) {
1207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      MBlock *b = user_mblock(thr, p);
1217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      internal_memcpy(p2, p, min(b->size, sz));
1227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    }
1237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
1247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (p) {
1257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    user_free(thr, pc, p);
1267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
1277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return p2;
1287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
1297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1307ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyMBlock *user_mblock(ThreadState *thr, void *p) {
1317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK_NE(p, (void*)0);
132491d34b7b75c42ac746ce90cda5a124bda038383Dmitry Vyukov  Allocator *a = allocator();
133f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov  void *b = a->GetBlockBegin(p);
134f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov  CHECK_NE(b, 0);
135f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov  return (MBlock*)a->GetMetaData(b);
1367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
1377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1384f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonovvoid invoke_malloc_hook(void *ptr, uptr size) {
1394f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov  Context *ctx = CTX();
1404f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov  ThreadState *thr = cur_thread();
1414f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov  if (ctx == 0 || !ctx->initialized || thr->in_rtl)
1424f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov    return;
1434f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov  __tsan_malloc_hook(ptr, size);
1444f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov}
1454f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov
1464f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonovvoid invoke_free_hook(void *ptr) {
1474f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov  Context *ctx = CTX();
1484f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov  ThreadState *thr = cur_thread();
1494f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov  if (ctx == 0 || !ctx->initialized || thr->in_rtl)
1504f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov    return;
1514f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov  __tsan_free_hook(ptr);
1524f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov}
1534f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov
1547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid *internal_alloc(MBlockType typ, uptr sz) {
1557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ThreadState *thr = cur_thread();
1567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK_GT(thr->in_rtl, 0);
1579ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov  if (thr->nomalloc) {
1589ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov    thr->nomalloc = 0;  // CHECK calls internal_malloc().
1599ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov    CHECK(0);
1609ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov  }
161f7667cc84cdd8923c0b6c7cfc92b7bd5692ce18cAlexey Samsonov  return InternalAlloc(sz);
1627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
1637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid internal_free(void *p) {
1657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ThreadState *thr = cur_thread();
1667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK_GT(thr->in_rtl, 0);
1679ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov  if (thr->nomalloc) {
1689ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov    thr->nomalloc = 0;  // CHECK calls internal_malloc().
1699ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov    CHECK(0);
1709ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov  }
171f7667cc84cdd8923c0b6c7cfc92b7bd5692ce18cAlexey Samsonov  InternalFree(p);
1727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
1737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}  // namespace __tsan
17512530820a4d45e799cdbb83e7b3b1e8ef111650cDmitry Vyukov
17612530820a4d45e799cdbb83e7b3b1e8ef111650cDmitry Vyukovusing namespace __tsan;
17712530820a4d45e799cdbb83e7b3b1e8ef111650cDmitry Vyukov
17812530820a4d45e799cdbb83e7b3b1e8ef111650cDmitry Vyukovextern "C" {
17912530820a4d45e799cdbb83e7b3b1e8ef111650cDmitry Vyukovuptr __tsan_get_current_allocated_bytes() {
180bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  u64 stats[AllocatorStatCount];
181bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  allocator()->GetStats(stats);
182bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  u64 m = stats[AllocatorStatMalloced];
183bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  u64 f = stats[AllocatorStatFreed];
184bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  return m >= f ? m - f : 1;
18512530820a4d45e799cdbb83e7b3b1e8ef111650cDmitry Vyukov}
18612530820a4d45e799cdbb83e7b3b1e8ef111650cDmitry Vyukov
18712530820a4d45e799cdbb83e7b3b1e8ef111650cDmitry Vyukovuptr __tsan_get_heap_size() {
188bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  u64 stats[AllocatorStatCount];
189bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  allocator()->GetStats(stats);
190bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  u64 m = stats[AllocatorStatMmapped];
191bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  u64 f = stats[AllocatorStatUnmapped];
192bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  return m >= f ? m - f : 1;
19312530820a4d45e799cdbb83e7b3b1e8ef111650cDmitry Vyukov}
19412530820a4d45e799cdbb83e7b3b1e8ef111650cDmitry Vyukov
19512530820a4d45e799cdbb83e7b3b1e8ef111650cDmitry Vyukovuptr __tsan_get_free_bytes() {
1961acfa02e08e6d3316c80f52255cbb7d9e3164128Dmitry Vyukov  return 1;
19712530820a4d45e799cdbb83e7b3b1e8ef111650cDmitry Vyukov}
19812530820a4d45e799cdbb83e7b3b1e8ef111650cDmitry Vyukov
19912530820a4d45e799cdbb83e7b3b1e8ef111650cDmitry Vyukovuptr __tsan_get_unmapped_bytes() {
2001acfa02e08e6d3316c80f52255cbb7d9e3164128Dmitry Vyukov  return 1;
20112530820a4d45e799cdbb83e7b3b1e8ef111650cDmitry Vyukov}
20212530820a4d45e799cdbb83e7b3b1e8ef111650cDmitry Vyukov
20312530820a4d45e799cdbb83e7b3b1e8ef111650cDmitry Vyukovuptr __tsan_get_estimated_allocated_size(uptr size) {
20412530820a4d45e799cdbb83e7b3b1e8ef111650cDmitry Vyukov  return size;
20512530820a4d45e799cdbb83e7b3b1e8ef111650cDmitry Vyukov}
20612530820a4d45e799cdbb83e7b3b1e8ef111650cDmitry Vyukov
207bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukovbool __tsan_get_ownership(void *p) {
208bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  return allocator()->GetBlockBegin(p) != 0;
20912530820a4d45e799cdbb83e7b3b1e8ef111650cDmitry Vyukov}
21012530820a4d45e799cdbb83e7b3b1e8ef111650cDmitry Vyukov
211bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukovuptr __tsan_get_allocated_size(void *p) {
212bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  if (p == 0)
213bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov    return 0;
214bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  p = allocator()->GetBlockBegin(p);
215bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  if (p == 0)
216bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov    return 0;
217bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  MBlock *b = (MBlock*)allocator()->GetMetaData(p);
218bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  return b->size;
21912530820a4d45e799cdbb83e7b3b1e8ef111650cDmitry Vyukov}
22012530820a4d45e799cdbb83e7b3b1e8ef111650cDmitry Vyukov}  // extern "C"
221