• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifdef UNSAFE_BUFFERS_BUILD
6 // TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
7 #pragma allow_unsafe_buffers
8 #endif
9 
10 #ifndef BASE_TRACE_EVENT_CATEGORY_REGISTRY_H_
11 #define BASE_TRACE_EVENT_CATEGORY_REGISTRY_H_
12 
13 #include <stddef.h>
14 #include <stdint.h>
15 
16 #include <atomic>
17 
18 #include "base/base_export.h"
19 #include "base/check_op.h"
20 #include "base/containers/span.h"
21 #include "base/memory/raw_ptr.h"
22 #include "base/trace_event/builtin_categories.h"
23 #include "base/trace_event/common/trace_event_common.h"
24 #include "base/trace_event/trace_category.h"
25 #include "build/build_config.h"
26 
27 namespace base {
28 namespace trace_event {
29 
30 class TraceCategoryTest;
31 class TraceLog;
32 
33 // Allows fast and thread-safe acces to the state of all tracing categories.
34 // All the methods in this class can be concurrently called on multiple threads,
35 // unless otherwise noted (e.g., GetOrCreateCategoryLocked).
36 // The reason why this is a fully static class with global state is to allow to
37 // statically define known categories as global linker-initialized structs,
38 // without requiring static initializers.
39 class BASE_EXPORT CategoryRegistry {
40  public:
41   // Known categories.
42   static TraceCategory* const kCategoryMetadata;
43   static TraceCategory* const kCategoryAlreadyShutdown;
44 
45   // Returns a category entry from the Category.state_ptr() pointer.
46   // TODO(primiano): trace macros should just keep a pointer to the entire
47   // TraceCategory, not just the enabled state pointer. That would remove the
48   // need for this function and make everything cleaner at no extra cost (as
49   // long as the |state_| is the first field of the struct, which can be
50   // guaranteed via static_assert, see TraceCategory ctor).
51   static const TraceCategory* GetCategoryByStatePtr(
52       const uint8_t* category_state);
53 
54   // Returns a category from its name or nullptr if not found.
55   // The output |category| argument is an undefinitely lived pointer to the
56   // TraceCategory owned by the registry. TRACE_EVENTx macros will cache this
57   // pointer and use it for checks in their fast-paths.
58   static TraceCategory* GetCategoryByName(const char* category_name);
59 
60   // Returns a built-in category from its name or nullptr if not found at
61   // compile-time. The return value is an undefinitely lived pointer to the
62   // TraceCategory owned by the registry.
GetBuiltinCategoryByName(const char * category_group)63   static constexpr TraceCategory* GetBuiltinCategoryByName(
64       const char* category_group) {
65 #if BUILDFLAG(IS_WIN) && defined(COMPONENT_BUILD)
66     // The address cannot be evaluated at compile-time in Windows component
67     // builds.
68     return nullptr;
69 #else
70     for (size_t i = 0; i < BuiltinCategories::Size(); ++i) {
71       if (StrEqConstexpr(category_group, BuiltinCategories::At(i)))
72         return &categories_[i];
73     }
74     return nullptr;
75 #endif
76   }
77 
78   // Returns whether |category| points at one of the meta categories that
79   // shouldn't be displayed in the tracing UI.
80   static bool IsMetaCategory(const TraceCategory* category);
81 
82  private:
83   friend class TraceCategoryTest;
84   friend class TraceLog;
85   using CategoryInitializerFn = void (*)(TraceCategory*);
86 
87   // The max number of trace categories that can be recorded.
88   static constexpr size_t kMaxCategories = 350;
89 
90   // Checks that there is enough space for all builtin categories.
91   static_assert(BuiltinCategories::Size() <= kMaxCategories,
92                 "kMaxCategories must be greater than kNumBuiltinCategories");
93 
94   // Only for debugging/testing purposes, is a no-op on release builds.
95   static void Initialize();
96 
97   // Resets the state of all categories, to clear up the state between tests.
98   static void ResetForTesting();
99 
100   // Used to get/create a category in the slow-path. If the category exists
101   // already, this has the same effect of GetCategoryByName and returns false.
102   // If not, a new category is created and the CategoryInitializerFn is invoked
103   // before retuning true. The caller must guarantee serialization: either call
104   // this method from a single thread or hold a lock when calling this.
105   static bool GetOrCreateCategoryLocked(const char* category_name,
106                                         CategoryInitializerFn,
107                                         TraceCategory**);
108 
109   // Allows to iterate over the valid categories in a for-each loop.
110   // This includes builtin categories such as __metadata.
111   static base::span<TraceCategory> GetAllCategories();
112 
113   // Returns whether |category| correctly points at |categories_| array entry.
114   static bool IsValidCategoryPtr(const TraceCategory* category);
115 
116   // The static array of trace categories.
117   static TraceCategory categories_[kMaxCategories];
118 
119   // Contains the number of created categories.
120   static std::atomic<size_t> category_index_;
121 };
122 
123 }  // namespace trace_event
124 }  // namespace base
125 
126 #endif  // BASE_TRACE_EVENT_CATEGORY_REGISTRY_H_
127