diff options
| author | Alex Rønne Petersen <alex@alexrp.com> | 2025-04-12 18:14:17 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-04-12 18:14:17 +0200 |
| commit | 9352f379e8a08bcc5a3bfc851bfb6c6a662000af (patch) | |
| tree | 9fee8a3b98ab806c02aab3a6e9646ccea08f40f1 /lib/libtsan/sanitizer_common/sanitizer_thread_arg_retval.cpp | |
| parent | 4e700fdf8ed01e7fc856e631ceffd6006e6f48df (diff) | |
| parent | 1f896c1bf89aa0e3d2a0dce1f4cf6ba6ce5ae9ed (diff) | |
| download | zig-9352f379e8a08bcc5a3bfc851bfb6c6a662000af.tar.gz zig-9352f379e8a08bcc5a3bfc851bfb6c6a662000af.zip | |
Merge pull request #23529 from alexrp/2879-groundwork
Introduce libzigc for libc function implementations in Zig
Diffstat (limited to 'lib/libtsan/sanitizer_common/sanitizer_thread_arg_retval.cpp')
| -rw-r--r-- | lib/libtsan/sanitizer_common/sanitizer_thread_arg_retval.cpp | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/lib/libtsan/sanitizer_common/sanitizer_thread_arg_retval.cpp b/lib/libtsan/sanitizer_common/sanitizer_thread_arg_retval.cpp new file mode 100644 index 0000000000..754fd7b65a --- /dev/null +++ b/lib/libtsan/sanitizer_common/sanitizer_thread_arg_retval.cpp @@ -0,0 +1,109 @@ +//===-- sanitizer_thread_arg_retval.cpp -------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file is shared between sanitizer tools. +// +// Tracks thread arguments and return value for leak checking. +//===----------------------------------------------------------------------===// + +#include "sanitizer_thread_arg_retval.h" + +#include "sanitizer_placement_new.h" + +namespace __sanitizer { + +void ThreadArgRetval::CreateLocked(uptr thread, bool detached, + const Args& args) { + CheckLocked(); + Data& t = data_[thread]; + t = {}; + t.gen = gen_++; + static_assert(sizeof(gen_) == sizeof(u32) && kInvalidGen == UINT32_MAX); + if (gen_ == kInvalidGen) + gen_ = 0; + t.detached = detached; + t.args = args; +} + +ThreadArgRetval::Args ThreadArgRetval::GetArgs(uptr thread) const { + __sanitizer::Lock lock(&mtx_); + auto t = data_.find(thread); + CHECK(t); + if (t->second.done) + return {}; + return t->second.args; +} + +void ThreadArgRetval::Finish(uptr thread, void* retval) { + __sanitizer::Lock lock(&mtx_); + auto t = data_.find(thread); + if (!t) + return; + if (t->second.detached) { + // Retval of detached thread connot be retrieved. + data_.erase(t); + return; + } + t->second.done = true; + t->second.args.arg_retval = retval; +} + +u32 ThreadArgRetval::BeforeJoin(uptr thread) const { + __sanitizer::Lock lock(&mtx_); + auto t = data_.find(thread); + if (t && !t->second.detached) { + return t->second.gen; + } + if (!common_flags()->detect_invalid_join) + return kInvalidGen; + const char* reason = "unknown"; + if (!t) { + reason = "already joined"; + } else if (t->second.detached) { + reason = "detached"; + } + Report("ERROR: %s: Joining %s thread, aborting.\n", SanitizerToolName, + reason); + Die(); +} + +void ThreadArgRetval::AfterJoin(uptr thread, u32 gen) { + __sanitizer::Lock lock(&mtx_); + auto t = data_.find(thread); + if (!t || gen != t->second.gen) { + // Thread was reused and erased by any other event, or we had an invalid + // join. + return; + } + CHECK(!t->second.detached); + data_.erase(t); +} + +void ThreadArgRetval::DetachLocked(uptr thread) { + CheckLocked(); + auto t = data_.find(thread); + CHECK(t); + CHECK(!t->second.detached); + if (t->second.done) { + // We can't retrive retval after detached thread finished. + data_.erase(t); + return; + } + t->second.detached = true; +} + +void ThreadArgRetval::GetAllPtrsLocked(InternalMmapVector<uptr>* ptrs) { + CheckLocked(); + CHECK(ptrs); + data_.forEach([&](DenseMap<uptr, Data>::value_type& kv) -> bool { + ptrs->push_back((uptr)kv.second.args.arg_retval); + return true; + }); +} + +} // namespace __sanitizer |
