// Copyright 2016 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifdef UNSAFE_BUFFERS_BUILD // TODO(crbug.com/40284755): Remove this and spanify to fix the errors. #pragma allow_unsafe_buffers #endif #ifndef BASE_TRACE_EVENT_CATEGORY_REGISTRY_H_ #define BASE_TRACE_EVENT_CATEGORY_REGISTRY_H_ #include #include #include #include "base/base_export.h" #include "base/check_op.h" #include "base/containers/span.h" #include "base/memory/raw_ptr.h" #include "base/trace_event/builtin_categories.h" #include "base/trace_event/common/trace_event_common.h" #include "base/trace_event/trace_category.h" #include "build/build_config.h" namespace base { namespace trace_event { class TraceCategoryTest; class TraceLog; // Allows fast and thread-safe acces to the state of all tracing categories. // All the methods in this class can be concurrently called on multiple threads, // unless otherwise noted (e.g., GetOrCreateCategoryLocked). // The reason why this is a fully static class with global state is to allow to // statically define known categories as global linker-initialized structs, // without requiring static initializers. class BASE_EXPORT CategoryRegistry { public: // Known categories. static TraceCategory* const kCategoryMetadata; static TraceCategory* const kCategoryAlreadyShutdown; // Returns a category entry from the Category.state_ptr() pointer. // TODO(primiano): trace macros should just keep a pointer to the entire // TraceCategory, not just the enabled state pointer. That would remove the // need for this function and make everything cleaner at no extra cost (as // long as the |state_| is the first field of the struct, which can be // guaranteed via static_assert, see TraceCategory ctor). static const TraceCategory* GetCategoryByStatePtr( const uint8_t* category_state); // Returns a category from its name or nullptr if not found. // The output |category| argument is an undefinitely lived pointer to the // TraceCategory owned by the registry. TRACE_EVENTx macros will cache this // pointer and use it for checks in their fast-paths. static TraceCategory* GetCategoryByName(const char* category_name); // Returns a built-in category from its name or nullptr if not found at // compile-time. The return value is an undefinitely lived pointer to the // TraceCategory owned by the registry. static constexpr TraceCategory* GetBuiltinCategoryByName( const char* category_group) { #if BUILDFLAG(IS_WIN) && defined(COMPONENT_BUILD) // The address cannot be evaluated at compile-time in Windows component // builds. return nullptr; #else for (size_t i = 0; i < BuiltinCategories::Size(); ++i) { if (StrEqConstexpr(category_group, BuiltinCategories::At(i))) return &categories_[i]; } return nullptr; #endif } // Returns whether |category| points at one of the meta categories that // shouldn't be displayed in the tracing UI. static bool IsMetaCategory(const TraceCategory* category); private: friend class TraceCategoryTest; friend class TraceLog; using CategoryInitializerFn = void (*)(TraceCategory*); // The max number of trace categories that can be recorded. static constexpr size_t kMaxCategories = 350; // Checks that there is enough space for all builtin categories. static_assert(BuiltinCategories::Size() <= kMaxCategories, "kMaxCategories must be greater than kNumBuiltinCategories"); // Only for debugging/testing purposes, is a no-op on release builds. static void Initialize(); // Resets the state of all categories, to clear up the state between tests. static void ResetForTesting(); // Used to get/create a category in the slow-path. If the category exists // already, this has the same effect of GetCategoryByName and returns false. // If not, a new category is created and the CategoryInitializerFn is invoked // before retuning true. The caller must guarantee serialization: either call // this method from a single thread or hold a lock when calling this. static bool GetOrCreateCategoryLocked(const char* category_name, CategoryInitializerFn, TraceCategory**); // Allows to iterate over the valid categories in a for-each loop. // This includes builtin categories such as __metadata. static base::span GetAllCategories(); // Returns whether |category| correctly points at |categories_| array entry. static bool IsValidCategoryPtr(const TraceCategory* category); // The static array of trace categories. static TraceCategory categories_[kMaxCategories]; // Contains the number of created categories. static std::atomic category_index_; }; } // namespace trace_event } // namespace base #endif // BASE_TRACE_EVENT_CATEGORY_REGISTRY_H_