• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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_EXT_TRACING_CORE_SHARED_MEMORY_ARBITER_H_
18 #define INCLUDE_PERFETTO_EXT_TRACING_CORE_SHARED_MEMORY_ARBITER_H_
19 
20 #include <stddef.h>
21 
22 #include <functional>
23 #include <memory>
24 #include <vector>
25 
26 #include "perfetto/base/export.h"
27 #include "perfetto/ext/tracing/core/basic_types.h"
28 #include "perfetto/ext/tracing/core/tracing_service.h"
29 #include "perfetto/tracing/buffer_exhausted_policy.h"
30 
31 namespace perfetto {
32 
33 namespace base {
34 class TaskRunner;
35 }
36 
37 class SharedMemory;
38 class TraceWriter;
39 
40 // Used by the Producer-side of the transport layer to vend TraceWriters
41 // from the SharedMemory it receives from the Service-side.
42 class PERFETTO_EXPORT SharedMemoryArbiter {
43  public:
44   virtual ~SharedMemoryArbiter();
45 
46   // Creates a new TraceWriter and assigns it a new WriterID. The WriterID is
47   // written in each chunk header owned by a given TraceWriter and is used by
48   // the Service to reconstruct TracePackets written by the same TraceWriter.
49   // Returns null impl of TraceWriter if all WriterID slots are exhausted. The
50   // writer will commit to the provided |target_buffer|. If the arbiter was
51   // created via CreateUnbound(), only BufferExhaustedPolicy::kDrop is
52   // supported.
53   virtual std::unique_ptr<TraceWriter> CreateTraceWriter(
54       BufferID target_buffer,
55       BufferExhaustedPolicy buffer_exhausted_policy =
56           BufferExhaustedPolicy::kDefault) = 0;
57 
58   // Creates a TraceWriter that will commit to the target buffer with the given
59   // reservation ID (creating a new reservation for this ID if none exists yet).
60   // The buffer reservation should be bound to an actual BufferID via
61   // BindStartupTargetBuffer() once the actual BufferID is known. Only supported
62   // if the arbiter was created using CreateUnbound(), and may be called while
63   // the arbiter is unbound.
64   //
65   // While any unbound buffer reservation exists, all commits will be buffered
66   // until all reservations were bound. Thus, until all reservations are bound,
67   // the data written to the SMB will not be consumed by the service - the SMB
68   // size should be chosen with this in mind. Startup writers always use
69   // BufferExhaustedPolicy::kDrop, as we cannot feasibly stall while not
70   // flushing to the service.
71   //
72   // The |target_buffer_reservation_id| should be greater than 0 but can
73   // otherwise be freely chosen by the producer and is only used to translate
74   // packets into the actual buffer id once
75   // BindStartupTargetBuffer(reservation_id) is called. For example, Chrome uses
76   // startup tracing not only for the first, but also subsequent tracing
77   // sessions (to enable tracing in the browser process before it instructs the
78   // tracing service to start tracing asynchronously, minimizing trace data loss
79   // in the meantime), and increments the reservation ID between sessions.
80   // Similarly, if more than a single target buffer per session is required
81   // (e.g. for two different data sources), different reservation IDs should be
82   // chosen for different targets buffers.
83   virtual std::unique_ptr<TraceWriter> CreateStartupTraceWriter(
84       uint16_t target_buffer_reservation_id) = 0;
85 
86   // Should only be called on unbound SharedMemoryArbiters. Binds the arbiter to
87   // the provided ProducerEndpoint and TaskRunner. Should be called only once
88   // and on the provided |TaskRunner|. Usually called by the producer (i.e., no
89   // specific data source) once it connects to the service. Both the endpoint
90   // and task runner should remain valid for the remainder of the arbiter's
91   // lifetime.
92   virtual void BindToProducerEndpoint(TracingService::ProducerEndpoint*,
93                                       base::TaskRunner*) = 0;
94 
95   // Binds commits from TraceWriters created via CreateStartupTraceWriter() with
96   // the given |target_buffer_reservation_id| to |target_buffer_id|. May only be
97   // called once per |target_buffer_reservation_id|. Should be called on the
98   // arbiter's TaskRunner, and after BindToProducerEndpoint() was called.
99   // Usually, it is called by a specific data source, after it received its
100   // configuration (including the target buffer ID) from the service.
101   virtual void BindStartupTargetBuffer(uint16_t target_buffer_reservation_id,
102                                        BufferID target_buffer_id) = 0;
103 
104   // Treat the reservation as resolved to an invalid buffer. Commits for this
105   // reservation will be flushed to the service ASAP. The service will free
106   // committed chunks but otherwise ignore them. The producer can call this
107   // method, for example, if connection to the tracing service failed or the
108   // session was stopped concurrently before the connection was established.
109   virtual void AbortStartupTracingForReservation(
110       uint16_t target_buffer_reservation_id) = 0;
111 
112   // Notifies the service that all data for the given FlushRequestID has been
113   // committed in the shared memory buffer. Should only be called while bound.
114   virtual void NotifyFlushComplete(FlushRequestID) = 0;
115 
116   // Create a bound arbiter instance. Args:
117   // |SharedMemory|: the shared memory buffer to use.
118   // |page_size|: a multiple of 4KB that defines the granularity of tracing
119   // pages. See tradeoff considerations in shared_memory_abi.h.
120   // |ProducerEndpoint|: The service's producer endpoint used e.g. to commit
121   // chunks and register trace writers.
122   // |TaskRunner|: Task runner for perfetto's main thread, which executes the
123   // OnPagesCompleteCallback and IPC calls to the |ProducerEndpoint|.
124   //
125   // Implemented in src/core/shared_memory_arbiter_impl.cc.
126   static std::unique_ptr<SharedMemoryArbiter> CreateInstance(
127       SharedMemory*,
128       size_t page_size,
129       TracingService::ProducerEndpoint*,
130       base::TaskRunner*);
131 
132   // Create an unbound arbiter instance, which should later be bound to a
133   // ProducerEndpoint and TaskRunner by calling BindToProducerEndpoint(). The
134   // returned arbiter will ONLY support trace writers with
135   // BufferExhaustedPolicy::kDrop.
136   //
137   // An unbound SharedMemoryArbiter can be used to write to a producer-created
138   // SharedMemory buffer before the producer connects to the tracing service.
139   // The producer can then pass this SMB to the service when it connects (see
140   // TracingService::ConnectProducer).
141   //
142   // To trace into the SMB before the service starts the tracing session, trace
143   // writers can be obtained via CreateStartupTraceWriter() and later associated
144   // with a target buffer via BindStartupTargetBuffer(), once the target buffer
145   // is known.
146   //
147   // Implemented in src/core/shared_memory_arbiter_impl.cc. See CreateInstance()
148   // for comments about the arguments.
149   static std::unique_ptr<SharedMemoryArbiter> CreateUnboundInstance(
150       SharedMemory*,
151       size_t page_size);
152 };
153 
154 }  // namespace perfetto
155 
156 #endif  // INCLUDE_PERFETTO_EXT_TRACING_CORE_SHARED_MEMORY_ARBITER_H_
157