llvm-project
109 строк · 2.9 Кб
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
18namespace __sanitizer {19
20void ThreadArgRetval::CreateLocked(uptr thread, bool detached,21const Args& args) {22CheckLocked();23Data& t = data_[thread];24t = {};25t.gen = gen_++;26static_assert(sizeof(gen_) == sizeof(u32) && kInvalidGen == UINT32_MAX);27if (gen_ == kInvalidGen)28gen_ = 0;29t.detached = detached;30t.args = args;31}
32
33ThreadArgRetval::Args ThreadArgRetval::GetArgs(uptr thread) const {34__sanitizer::Lock lock(&mtx_);35auto t = data_.find(thread);36CHECK(t);37if (t->second.done)38return {};39return t->second.args;40}
41
42void ThreadArgRetval::Finish(uptr thread, void* retval) {43__sanitizer::Lock lock(&mtx_);44auto t = data_.find(thread);45if (!t)46return;47if (t->second.detached) {48// Retval of detached thread connot be retrieved.49data_.erase(t);50return;51}52t->second.done = true;53t->second.args.arg_retval = retval;54}
55
56u32 ThreadArgRetval::BeforeJoin(uptr thread) const {57__sanitizer::Lock lock(&mtx_);58auto t = data_.find(thread);59if (t && !t->second.detached) {60return t->second.gen;61}62if (!common_flags()->detect_invalid_join)63return kInvalidGen;64const char* reason = "unknown";65if (!t) {66reason = "already joined";67} else if (t->second.detached) {68reason = "detached";69}70Report("ERROR: %s: Joining %s thread, aborting.\n", SanitizerToolName,71reason);72Die();73}
74
75void ThreadArgRetval::AfterJoin(uptr thread, u32 gen) {76__sanitizer::Lock lock(&mtx_);77auto t = data_.find(thread);78if (!t || gen != t->second.gen) {79// Thread was reused and erased by any other event, or we had an invalid80// join.81return;82}83CHECK(!t->second.detached);84data_.erase(t);85}
86
87void ThreadArgRetval::DetachLocked(uptr thread) {88CheckLocked();89auto t = data_.find(thread);90CHECK(t);91CHECK(!t->second.detached);92if (t->second.done) {93// We can't retrive retval after detached thread finished.94data_.erase(t);95return;96}97t->second.detached = true;98}
99
100void ThreadArgRetval::GetAllPtrsLocked(InternalMmapVector<uptr>* ptrs) {101CheckLocked();102CHECK(ptrs);103data_.forEach([&](DenseMap<uptr, Data>::value_type& kv) -> bool {104ptrs->push_back((uptr)kv.second.args.arg_retval);105return true;106});107}
108
109} // namespace __sanitizer110