diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /security/sandbox/chromium/base/threading/thread_local_internal.h | |
parent | Initial commit. (diff) | |
download | thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'security/sandbox/chromium/base/threading/thread_local_internal.h')
-rw-r--r-- | security/sandbox/chromium/base/threading/thread_local_internal.h | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/security/sandbox/chromium/base/threading/thread_local_internal.h b/security/sandbox/chromium/base/threading/thread_local_internal.h new file mode 100644 index 0000000000..6f7fdc9768 --- /dev/null +++ b/security/sandbox/chromium/base/threading/thread_local_internal.h @@ -0,0 +1,80 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_THREADING_THREAD_LOCAL_INTERNAL_H_ +#define BASE_THREADING_THREAD_LOCAL_INTERNAL_H_ + +#if DCHECK_IS_ON() + +#include <atomic> +#include <memory> + +#include "base/macros.h" +#include "base/threading/thread_local_storage.h" + +namespace base { +namespace internal { + +// A version of ThreadLocalOwnedPointer which verifies that it's only destroyed +// when no threads, other than the one it is destroyed on, have remaining state +// set in it. A ThreadLocalOwnedPointer instance being destroyed too early would +// result in leaks per unregistering the TLS slot (and thus the DeleteTlsPtr +// hook). +template <typename T> +class CheckedThreadLocalOwnedPointer { + public: + CheckedThreadLocalOwnedPointer() = default; + + ~CheckedThreadLocalOwnedPointer() { + Set(nullptr); + + DCHECK_EQ(num_assigned_threads_.load(std::memory_order_relaxed), 0) + << "Memory leak: Must join all threads or release all associated " + "thread-local slots before ~ThreadLocalOwnedPointer"; + } + + T* Get() const { + PtrTracker* const ptr_tracker = static_cast<PtrTracker*>(slot_.Get()); + return ptr_tracker ? ptr_tracker->ptr_.get() : nullptr; + } + + void Set(std::unique_ptr<T> ptr) { + delete static_cast<PtrTracker*>(slot_.Get()); + if (ptr) + slot_.Set(new PtrTracker(this, std::move(ptr))); + else + slot_.Set(nullptr); + } + + private: + struct PtrTracker { + public: + PtrTracker(CheckedThreadLocalOwnedPointer<T>* outer, std::unique_ptr<T> ptr) + : outer_(outer), ptr_(std::move(ptr)) { + outer_->num_assigned_threads_.fetch_add(1, std::memory_order_relaxed); + } + + ~PtrTracker() { + outer_->num_assigned_threads_.fetch_sub(1, std::memory_order_relaxed); + } + + CheckedThreadLocalOwnedPointer<T>* const outer_; + const std::unique_ptr<T> ptr_; + }; + + static void DeleteTlsPtr(void* ptr) { delete static_cast<PtrTracker*>(ptr); } + + ThreadLocalStorage::Slot slot_{&DeleteTlsPtr}; + + std::atomic_int num_assigned_threads_{0}; + + DISALLOW_COPY_AND_ASSIGN(CheckedThreadLocalOwnedPointer<T>); +}; + +} // namespace internal +} // namespace base + +#endif // DCHECK_IS_ON() + +#endif // BASE_THREADING_THREAD_LOCAL_INTERNAL_H_ |