1 //===-- sanitizer_thread_arg_retval.cpp -------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file is shared between sanitizer tools.
11 // Tracks thread arguments and return value for leak checking.
12 //===----------------------------------------------------------------------===//
14 #include "sanitizer_thread_arg_retval.h"
16 #include "sanitizer_placement_new.h"
18 namespace __sanitizer
{
20 void ThreadArgRetval::CreateLocked(uptr thread
, bool detached
,
23 Data
& t
= data_
[thread
];
26 static_assert(sizeof(gen_
) == sizeof(u32
) && kInvalidGen
== UINT32_MAX
);
27 if (gen_
== kInvalidGen
)
29 t
.detached
= detached
;
33 ThreadArgRetval::Args
ThreadArgRetval::GetArgs(uptr thread
) const {
34 __sanitizer::Lock
lock(&mtx_
);
35 auto t
= data_
.find(thread
);
39 return t
->second
.args
;
42 void ThreadArgRetval::Finish(uptr thread
, void* retval
) {
43 __sanitizer::Lock
lock(&mtx_
);
44 auto t
= data_
.find(thread
);
47 if (t
->second
.detached
) {
48 // Retval of detached thread connot be retrieved.
52 t
->second
.done
= true;
53 t
->second
.args
.arg_retval
= retval
;
56 u32
ThreadArgRetval::BeforeJoin(uptr thread
) const {
57 __sanitizer::Lock
lock(&mtx_
);
58 auto t
= data_
.find(thread
);
59 if (t
&& !t
->second
.detached
) {
62 if (!common_flags()->detect_invalid_join
)
64 const char* reason
= "unknown";
66 reason
= "already joined";
67 } else if (t
->second
.detached
) {
70 Report("ERROR: %s: Joining %s thread, aborting.\n", SanitizerToolName
,
75 void ThreadArgRetval::AfterJoin(uptr thread
, u32 gen
) {
76 __sanitizer::Lock
lock(&mtx_
);
77 auto t
= data_
.find(thread
);
78 if (!t
|| gen
!= t
->second
.gen
) {
79 // Thread was reused and erased by any other event, or we had an invalid
83 CHECK(!t
->second
.detached
);
87 void ThreadArgRetval::DetachLocked(uptr thread
) {
89 auto t
= data_
.find(thread
);
91 CHECK(!t
->second
.detached
);
93 // We can't retrive retval after detached thread finished.
97 t
->second
.detached
= true;
100 void ThreadArgRetval::GetAllPtrsLocked(InternalMmapVector
<uptr
>* ptrs
) {
103 data_
.forEach([&](DenseMap
<uptr
, Data
>::value_type
& kv
) -> bool {
104 ptrs
->push_back((uptr
)kv
.second
.args
.arg_retval
);
109 } // namespace __sanitizer