• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_TRACING_TLS_H_
18 #define INCLUDE_PERFETTO_TRACING_INTERNAL_TRACING_TLS_H_
19 
20 #include <array>
21 #include <memory>
22 
23 #include "perfetto/tracing/internal/basic_types.h"
24 #include "perfetto/tracing/internal/data_source_internal.h"
25 #include "perfetto/tracing/platform.h"
26 
27 namespace perfetto {
28 
29 class TraceWriterBase;
30 
31 namespace internal {
32 
33 // Organization of the thread-local storage
34 // ----------------------------------------
35 // First of all, remember the cardinality of the problem: at any point in time
36 // there are M data sources registered (i.e. number of subclasses of DataSource)
37 // and up to N concurrent instances for each data source, so up to M * N total
38 // data source instances around.
39 // Each data source instance can be accessed by T threads (no upper bound).
40 // We can safely put hard limits both to M and N (i.e. say that we support at
41 // most 32 data source types per process and up to 8 concurrent instances).
42 //
43 // We want to make it so from the Platform viewpoint, we use only one global
44 // TLS object, so T instances in total, one per thread, regardless of M and N.
45 // This allows to deal with at-thread-exit destruction only in one place, rather
46 // than N, M or M * N.
47 //
48 // Visually:
49 //                     [    Thread 1   ] [    Thread 2   ] [    Thread T   ]
50 //                     +---------------+ +---------------+ +---------------+
51 // Data source Foo     |               | |               | |               |
52 //  Instance 1         |     TLS       | |     TLS       | |     TLS       |
53 //  Instance 2         |    Object     | |    Object     | |    Object     |
54 //  Instance 3         |               | |               | |               |
55 //                     |               | |               | |               |
56 // Data source Bar     |               | |               | |               |
57 //  Instance 1         |               | |               | |               |
58 //  Instance 2         |               | |               | |               |
59 //                     +---------------+ +---------------+ +---------------+
60 //
61 // Each TLS Object is organized as an array of M DataSourceThreadLocalState.
62 // Each DSTLS itself is an array of up to N per-instance objects.
63 // The only per-instance object for now is the TraceWriter.
64 // So for each data source, for each instance, for each thread we keep one
65 // TraceWriter.
66 // The lookup is O(1): Given the TLS object, the TraceWriter is just tls[M][N].
67 class TracingTLS : public Platform::ThreadLocalObject {
68  public:
69   ~TracingTLS() override;
70 
71   // This is checked against TraceMuxerImpl's global generation counter to
72   // handle destruction of TraceWriter(s) that belong to data sources that
73   // have been stopped. When the two numbers diverge, a scan of all the
74   // thread-local TraceWriter(s) is issued.
75   uint32_t generation = 0;
76 
77   // This flag is true while this thread is inside a trace point for any data
78   // source or in other delicate parts of the tracing machinery during which we
79   // should not try to trace. Used to prevent unexpected re-entrancy.
80   bool is_in_trace_point = false;
81 
82   // By default all data source instances have independent thread-local state
83   // (see above).
84   std::array<DataSourceThreadLocalState, kMaxDataSources> data_sources_tls{};
85 
86   // Track event data sources, however, share the same thread-local state in
87   // order to be able to share trace writers and interning state across all
88   // track event categories.
89   DataSourceThreadLocalState track_event_tls{};
90 };
91 
92 struct ScopedReentrancyAnnotator {
ScopedReentrancyAnnotatorScopedReentrancyAnnotator93   ScopedReentrancyAnnotator(TracingTLS& root_tls) : root_tls_(root_tls) {
94     PERFETTO_DCHECK(!root_tls_.is_in_trace_point);
95     root_tls_.is_in_trace_point = true;
96   }
~ScopedReentrancyAnnotatorScopedReentrancyAnnotator97   ~ScopedReentrancyAnnotator() { root_tls_.is_in_trace_point = false; }
98 
99  private:
100   TracingTLS& root_tls_;
101 };
102 
103 }  // namespace internal
104 }  // namespace perfetto
105 
106 #endif  // INCLUDE_PERFETTO_TRACING_INTERNAL_TRACING_TLS_H_
107