// Copyright 2022 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef BASE_ALLOCATOR_DISPATCHER_TLS_H_ #define BASE_ALLOCATOR_DISPATCHER_TLS_H_ #include <string_view> #include "build/build_config.h" #if BUILDFLAG(IS_POSIX) // the current allocation mechanism (mmap) and TLS // support (pthread) are both defined by POSIX #define USE_LOCAL_TLS_EMULATION() … #else #define USE_LOCAL_TLS_EMULATION … #endif #if USE_LOCAL_TLS_EMULATION() #include <algorithm> #include <atomic> #include <memory> #include <mutex> #include "base/base_export.h" #include "base/check.h" #include "base/compiler_specific.h" #include "partition_alloc/partition_alloc_constants.h" #include <pthread.h> #if HAS_FEATURE(thread_sanitizer) #define DISABLE_TSAN_INSTRUMENTATION … #else #define DISABLE_TSAN_INSTRUMENTATION #endif #define STR_HELPER … #define STR … // Verify that a condition holds and cancel the process in case it doesn't. The // functionality is similar to RAW_CHECK but includes more information in the // logged messages. It is non allocating to prevent recursions. #define TLS_RAW_CHECK … #define TLS_RAW_CHECK_IMPL … namespace base::debug { struct CrashKeyString; } namespace base::allocator::dispatcher { namespace internal { // Allocate memory using POSIX' mmap and unmap functionality. The allocator // implements the allocator interface required by ThreadLocalStorage. struct BASE_EXPORT MMapAllocator { … }; // The allocator used by default for the thread local storage. DefaultAllocator; OnThreadTerminationFunction; // The TLS system used by default for the thread local storage. It stores and // retrieves thread specific data pointers. class BASE_EXPORT PThreadTLSSystem { … }; DefaultTLSSystem; // In some scenarios, most notably when testing, the allocator and TLS system // passed to |ThreadLocalStorage| are not copyable and have to be wrapped, i.e. // using std::reference_wrapper. |dereference| is a small helper to retrieve the // underlying value. template <typename T> T& dereference(T& ref) { … } template <typename T> T& dereference(std::reference_wrapper<T>& ref) { … } // Store thread local data. The data is organized in chunks, where each chunk // holds |ItemsPerChunk|. Each item may be free or used. // // When a thread requests data, the chunks are searched for a free data item, // which is registered for this thread and marked as |used|. Further requests by // this thread will then always return the same item. When a thread terminates, // the item will be reset and return to the pool of free items. // // Upon construction, the first chunk is created. If a thread requests data and // there is no free item available, another chunk is created. Upon destruction, // all memory is freed. Pointers to data items become invalid! // // Constructor and destructor are not thread safe. // // @tparam PayloadType The item type to be stored. // @tparam AllocatorType The allocator being used. An allocator must provide // the following interface: // void* AllocateMemory(size_t size_in_bytes); // Allocate size_in_bytes bytes // of raw memory. // void FreeMemory(void* pointer_to_allocated, size_t size_in_bytes); // Free // the raw memory pointed to by pointer_to_allocated. // Any failure in allocation or free must terminate the process. // @tparam TLSSystemType The TLS system being used. A TLS system must provide // the following interface: // bool Setup(OnThreadTerminationFunction thread_termination_function); // bool Destroy(); // void* GetThreadSpecificData(); // bool SetThreadSpecificData(void* data); // @tparam AllocationChunkSize The minimum size of a memory chunk that the // allocator can handle. We try to size the chunks so that each chunk uses this // size to the maximum. // @tparam IsDestructibleForTesting For testing purposes we allow the destructor // to perform clean up upon destruction. Otherwise, using the destructor will // result in a compilation failure. template <typename PayloadType, typename AllocatorType, typename TLSSystemType, size_t AllocationChunkSize, bool IsDestructibleForTesting> struct ThreadLocalStorage { … }; } // namespace internal // The ThreadLocalStorage visible to the user. This uses the internal default // allocator and TLS system. ThreadLocalStorage; } // namespace base::allocator::dispatcher #undef TLS_RAW_CHECK_IMPL #undef TLS_RAW_CHECK #undef STR #undef STR_HELPER #endif // USE_LOCAL_TLS_EMULATION() #endif // BASE_ALLOCATOR_DISPATCHER_TLS_H_