1 // Copyright 2017 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 //
6 // The API for initializing the trace provider for a process.
7 //
8 
9 #pragma once
10 
11 #include <zircon/compiler.h>
12 #include <zircon/types.h>
13 
14 #include <lib/async/dispatcher.h>
15 
16 __BEGIN_CDECLS
17 
18 // The format of fifo packets for messages passed between the trace manager
19 // and trace providers.
20 typedef struct trace_provider_packet {
21     // One of TRACE_PROVIDER_*.
22     uint16_t request;
23 
24     // For alignment and future concerns, must be zero.
25     uint16_t reserved;
26 
27     // Optional data for the request.
28     // The contents depend on the request.
29     // If unused they must be passed as zero.
30     uint32_t data32;
31     uint64_t data64;
32 } trace_provider_packet_t;
33 
34 // The protocol version we are using.
35 // This is non-zero to catch initialization bugs.
36 #define TRACE_PROVIDER_FIFO_PROTOCOL_VERSION 1
37 
38 // Provider->Manager
39 // Zero is reserved to catch initialization bugs.
40 
41 // Indicate the provider successfully started.
42 // |data32| is TRACE_PROVIDER_FIFO_PROTOCOL_VERSION
43 // |data64| is unused (must be zero).
44 #define TRACE_PROVIDER_STARTED (0x1)
45 
46 // Provider->Manager
47 // A buffer is full and needs to be saved (streaming mode only).
48 // |data32| is the "wrapped count", which is a count of the number of times
49 // a buffer has filled.
50 // |data64| is current offset in the durable buffer
51 #define TRACE_PROVIDER_SAVE_BUFFER (0x2)
52 
53 // Temporary to ease soft-roll into garnet.
54 // Can be removed when garnet side lands.
55 #define TRACE_PROVIDER_BUFFER_OVERFLOW (0x2)
56 
57 // Next Provider->Manager packet = 0x3
58 
59 // Manager->Provider
60 // A buffer has been saved (streaminng mode only).
61 // |data32| is the "wrapped count", which is a count of the number of times
62 // a buffer has filled.
63 // |data64| is unused (must be zero).
64 #define TRACE_PROVIDER_BUFFER_SAVED (0x100)
65 
66 // Next Manager->Provider packet = 0x101
67 
68 // End fifo packet descriptions.
69 
70 // Represents a trace provider.
71 typedef struct trace_provider trace_provider_t;
72 
73 // Creates a trace provider associated with the specified async dispatcher
74 // and registers it with the tracing system.
75 //
76 // The trace provider will start and stop the trace engine in response to requests
77 // from the tracing system.
78 //
79 // |to_service| is the channel to use to connect to the trace manager.
80 // It is consumed regardless of success/failure.
81 //
82 // |dispatcher| is the asynchronous dispatcher which the trace provider and trace
83 // engine will use for dispatch.  This must outlive the trace provider instance.
84 //
85 // |name| is the name of the trace provider and is used for diagnostic
86 // purposes. The maximum supported length is 100 characters.
87 //
88 // Returns the trace provider, or null if creation failed.
89 //
90 // TODO(ZX-1036): Currently this connects to the trace manager service.
91 // Switch to passively exporting the trace provider via the "hub" through
92 // the process's exported directory once that stuff is implemented.  We'll
93 // probably need to pass some extra parameters to the trace provider then.
94 trace_provider_t* trace_provider_create_with_name_etc(
95     zx_handle_t to_service, async_dispatcher_t* dispatcher, const char* name);
96 
97 // Wrapper around trace_provider_create_with_name for backward compatibility.
98 // TODO(DX-422): Update all providers to use create_with_name, then change this
99 // to also take a name, then update all providers to call this one, and then
100 // delete trace_provider_create_with_name.
101 trace_provider_t* trace_provider_create_etc(
102     zx_handle_t to_service, async_dispatcher_t* dispatcher);
103 
104 // Same as trace_provider_create_with_name except does not return until the
105 // provider is registered with the trace manager.
106 // On return, if !NULL, |*out_already_started| is true if the trace manager has
107 // already started tracing, which is a hint to the provider to wait for the
108 // Start() message before continuing if it wishes to not drop trace records
109 // before Start() is received.
110 trace_provider_t* trace_provider_create_synchronously_etc(
111     zx_handle_t to_service, async_dispatcher_t* dispatcher, const char* name,
112     bool* out_already_started);
113 
114 // Wrappers on the above functions that use fdio.
115 trace_provider_t* trace_provider_create_with_name_fdio(
116     async_dispatcher_t* dispatcher, const char* name);
117 trace_provider_t* trace_provider_create_with_fdio(
118     async_dispatcher_t* dispatcher);
119 trace_provider_t* trace_provider_create_synchronously_with_fdio(
120     async_dispatcher_t* dispatcher, const char* name,
121     bool* out_already_started);
122 
123 // Compatibility wrappers.
124 // TODO(PT-63): Remove these (and the _etc suffixes on the above routines)
125 // when all clients are updated.
126 trace_provider_t* trace_provider_create_with_name(
127     async_dispatcher_t* dispatcher, const char* name);
128 trace_provider_t* trace_provider_create(async_dispatcher_t* dispatcher);
129 trace_provider_t* trace_provider_create_synchronously(
130     async_dispatcher_t* dispatcher, const char* name,
131     bool* out_already_started);
132 
133 // Destroys the trace provider.
134 void trace_provider_destroy(trace_provider_t* provider);
135 
136 __END_CDECLS
137 
138 #ifdef __cplusplus
139 
140 #include <fbl/unique_ptr.h>
141 #include <lib/zx/channel.h>
142 
143 namespace trace {
144 
145 // Convenience RAII wrapper for creating and destroying a trace provider.
146 // TODO(PT-63): Remove Etc suffix when all clients are updated.
147 class TraceProviderEtc {
148 public:
149     // Create a trace provider synchronously, and return an indicator of
150     // whether tracing has started already in |*out_already_started|.
151     // Returns a boolean indicating success.
152     // This is done with a factory function because it's more complex than
153     // the basic constructor.
CreateSynchronously(zx::channel to_service,async_dispatcher_t * dispatcher,const char * name,fbl::unique_ptr<TraceProviderEtc> * out_provider,bool * out_already_started)154     static bool CreateSynchronously(
155             zx::channel to_service,
156             async_dispatcher_t* dispatcher,
157             const char* name,
158             fbl::unique_ptr<TraceProviderEtc>* out_provider,
159             bool* out_already_started) {
160         auto provider = trace_provider_create_synchronously_etc(
161             to_service.release(), dispatcher, name, out_already_started);
162         if (!provider)
163             return false;
164         *out_provider = fbl::unique_ptr<TraceProviderEtc>(
165             new TraceProviderEtc(provider));
166         return true;
167     }
168 
169     // Creates a trace provider.
TraceProviderEtc(zx::channel to_service,async_dispatcher_t * dispatcher)170     TraceProviderEtc(zx::channel to_service, async_dispatcher_t* dispatcher)
171         : provider_(trace_provider_create_etc(to_service.release(),
172                                               dispatcher)) {}
173 
174     // Creates a trace provider.
TraceProviderEtc(zx::channel to_service,async_dispatcher_t * dispatcher,const char * name)175     TraceProviderEtc(zx::channel to_service, async_dispatcher_t* dispatcher,
176                      const char* name)
177         : provider_(trace_provider_create_with_name_etc(to_service.release(),
178                                                         dispatcher, name)) {}
179 
180     // Destroys a trace provider.
~TraceProviderEtc()181     ~TraceProviderEtc() {
182         if (provider_)
183             trace_provider_destroy(provider_);
184     }
185 
186     // Returns true if the trace provider was created successfully.
is_valid()187     bool is_valid() const {
188         return provider_ != nullptr;
189     }
190 
191 protected:
TraceProviderEtc(trace_provider_t * provider)192     explicit TraceProviderEtc(trace_provider_t* provider)
193         : provider_(provider) {}
194 
195 private:
196     trace_provider_t* const provider_;
197 };
198 
199 class TraceProviderWithFdio : public TraceProviderEtc {
200 public:
CreateSynchronously(async_dispatcher_t * dispatcher,const char * name,fbl::unique_ptr<TraceProviderWithFdio> * out_provider,bool * out_already_started)201     static bool CreateSynchronously(
202             async_dispatcher_t* dispatcher,
203             const char* name,
204             fbl::unique_ptr<TraceProviderWithFdio>* out_provider,
205             bool* out_already_started) {
206         auto provider = trace_provider_create_synchronously_with_fdio(
207             dispatcher, name, out_already_started);
208         if (!provider)
209             return false;
210         *out_provider = fbl::unique_ptr<TraceProviderWithFdio>(
211             new TraceProviderWithFdio(provider));
212         return true;
213     }
214 
215     // Creates a trace provider.
TraceProviderWithFdio(async_dispatcher_t * dispatcher)216     explicit TraceProviderWithFdio(async_dispatcher_t* dispatcher)
217         : TraceProviderWithFdio(
218             trace_provider_create_with_fdio(dispatcher)) {}
219 
220     // Creates a trace provider.
TraceProviderWithFdio(async_dispatcher_t * dispatcher,const char * name)221     explicit TraceProviderWithFdio(async_dispatcher_t* dispatcher,
222                                    const char* name)
223         : TraceProviderWithFdio(
224             trace_provider_create_with_name_fdio(dispatcher, name)) {}
225 
226 private:
TraceProviderWithFdio(trace_provider_t * provider)227     explicit TraceProviderWithFdio(trace_provider_t* provider)
228         : TraceProviderEtc(provider) {}
229 };
230 
231 // Compatibility wrapper.
232 // TODO(PT-63): Delete (and remove _etc from above version) when all clients
233 // are updated.
234 using TraceProvider = TraceProviderWithFdio;
235 
236 } // namespace trace
237 
238 #endif // __cplusplus
239