1 //===-- sanitizer_thread_arg_retval.cpp -------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file is shared between sanitizer tools. 10 // 11 // Tracks thread arguments and return value for leak checking. 12 //===----------------------------------------------------------------------===// 13 14 #include "sanitizer_thread_arg_retval.h" 15 16 #include "sanitizer_placement_new.h" 17 18 namespace __sanitizer { 19 20 void ThreadArgRetval::CreateLocked(uptr thread, bool detached, 21 const Args& args) { 22 CheckLocked(); 23 Data& t = data_[thread]; 24 t = {}; 25 t.gen = gen_++; 26 t.detached = detached; 27 t.args = args; 28 } 29 30 ThreadArgRetval::Args ThreadArgRetval::GetArgs(uptr thread) const { 31 __sanitizer::Lock lock(&mtx_); 32 auto t = data_.find(thread); 33 CHECK(t); 34 if (t->second.done) 35 return {}; 36 return t->second.args; 37 } 38 39 void ThreadArgRetval::Finish(uptr thread, void* retval) { 40 __sanitizer::Lock lock(&mtx_); 41 auto t = data_.find(thread); 42 if (!t) 43 return; 44 if (t->second.detached) { 45 // Retval of detached thread connot be retrieved. 46 data_.erase(t); 47 return; 48 } 49 t->second.done = true; 50 t->second.args.arg_retval = retval; 51 } 52 53 u32 ThreadArgRetval::BeforeJoin(uptr thread) const { 54 __sanitizer::Lock lock(&mtx_); 55 auto t = data_.find(thread); 56 CHECK(t); 57 CHECK(!t->second.detached); 58 return t->second.gen; 59 } 60 61 void ThreadArgRetval::AfterJoin(uptr thread, u32 gen) { 62 __sanitizer::Lock lock(&mtx_); 63 auto t = data_.find(thread); 64 if (!t || gen != t->second.gen) { 65 // Thread was reused and erased by any other event. 66 return; 67 } 68 CHECK(!t->second.detached); 69 data_.erase(t); 70 } 71 72 void ThreadArgRetval::DetachLocked(uptr thread) { 73 CheckLocked(); 74 auto t = data_.find(thread); 75 CHECK(t); 76 CHECK(!t->second.detached); 77 if (t->second.done) { 78 // We can't retrive retval after detached thread finished. 79 data_.erase(t); 80 return; 81 } 82 t->second.detached = true; 83 } 84 85 void ThreadArgRetval::GetAllPtrsLocked(InternalMmapVector<uptr>* ptrs) { 86 CheckLocked(); 87 CHECK(ptrs); 88 data_.forEach([&](DenseMap<uptr, Data>::value_type& kv) -> bool { 89 ptrs->push_back((uptr)kv.second.args.arg_retval); 90 return true; 91 }); 92 } 93 94 } // namespace __sanitizer 95