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