sanitizer_thread_arg_retval.cpp 2.9 KB

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