1 /* 2 * Copyright (C) 2017 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 SRC_TRACING_CORE_SHARED_MEMORY_ARBITER_IMPL_H_ 18 #define SRC_TRACING_CORE_SHARED_MEMORY_ARBITER_IMPL_H_ 19 20 #include <stdint.h> 21 22 #include <functional> 23 #include <memory> 24 #include <mutex> 25 #include <vector> 26 27 #include "perfetto/base/weak_ptr.h" 28 #include "perfetto/tracing/core/basic_types.h" 29 #include "perfetto/tracing/core/shared_memory_abi.h" 30 #include "perfetto/tracing/core/shared_memory_arbiter.h" 31 #include "perfetto/tracing/core/startup_trace_writer_registry.h" 32 #include "src/tracing/core/id_allocator.h" 33 34 namespace perfetto { 35 36 class CommitDataRequest; 37 class PatchList; 38 class TraceWriter; 39 class TraceWriterImpl; 40 41 namespace base { 42 class TaskRunner; 43 } // namespace base 44 45 // This class handles the shared memory buffer on the producer side. It is used 46 // to obtain thread-local chunks and to partition pages from several threads. 47 // There is one arbiter instance per Producer. 48 // This class is thread-safe and uses locks to do so. Data sources are supposed 49 // to interact with this sporadically, only when they run out of space on their 50 // current thread-local chunk. 51 class SharedMemoryArbiterImpl : public SharedMemoryArbiter { 52 public: 53 // Args: 54 // |start|,|size|: boundaries of the shared memory buffer. 55 // |page_size|: a multiple of 4KB that defines the granularity of tracing 56 // pages. See tradeoff considerations in shared_memory_abi.h. 57 // |OnPagesCompleteCallback|: a callback that will be posted on the passed 58 // |TaskRunner| when one or more pages are complete (and hence the Producer 59 // should send a CommitData request to the Service). 60 // |TaskRunner|: Task runner for perfetto's main thread, which executes the 61 // OnPagesCompleteCallback and IPC calls to the |ProducerEndpoint|. 62 SharedMemoryArbiterImpl(void* start, 63 size_t size, 64 size_t page_size, 65 TracingService::ProducerEndpoint*, 66 base::TaskRunner*); 67 68 // Returns a new Chunk to write tracing data. The call always returns a valid 69 // Chunk. TODO(primiano): right now this blocks if there are no free chunks 70 // in the SMB. In the long term the caller should be allowed to pick a policy 71 // and handle the retry itself asynchronously. 72 SharedMemoryABI::Chunk GetNewChunk(const SharedMemoryABI::ChunkHeader&, 73 size_t size_hint = 0); 74 75 // Puts back a Chunk that has been completed and sends a request to the 76 // service to move it to the central tracing buffer. |target_buffer| is the 77 // absolute trace buffer ID where the service should move the chunk onto (the 78 // producer is just to copy back the same number received in the 79 // DataSourceConfig upon the StartDataSource() reques). 80 // PatchList is a pointer to the list of patches for previous chunks. The 81 // first patched entries will be removed from the patched list and sent over 82 // to the service in the same CommitData() IPC request. 83 void ReturnCompletedChunk(SharedMemoryABI::Chunk, 84 BufferID target_buffer, 85 PatchList*); 86 87 // Send a request to the service to apply completed patches from |patch_list|. 88 // |writer_id| is the ID of the TraceWriter that calls this method, 89 // |target_buffer| is the global trace buffer ID of its target buffer. 90 void SendPatches(WriterID writer_id, 91 BufferID target_buffer, 92 PatchList* patch_list); 93 94 // Forces a synchronous commit of the completed packets without waiting for 95 // the next task. 96 void FlushPendingCommitDataRequests(std::function<void()> callback = {}); 97 shmem_abi_for_testing()98 SharedMemoryABI* shmem_abi_for_testing() { return &shmem_abi_; } 99 set_default_layout_for_testing(SharedMemoryABI::PageLayout l)100 static void set_default_layout_for_testing(SharedMemoryABI::PageLayout l) { 101 default_page_layout = l; 102 } 103 104 // SharedMemoryArbiter implementation. 105 // See include/perfetto/tracing/core/shared_memory_arbiter.h for comments. 106 std::unique_ptr<TraceWriter> CreateTraceWriter( 107 BufferID target_buffer) override; 108 void BindStartupTraceWriterRegistry( 109 std::unique_ptr<StartupTraceWriterRegistry>, 110 BufferID target_buffer) override; 111 112 void NotifyFlushComplete(FlushRequestID) override; 113 114 private: 115 friend class TraceWriterImpl; 116 friend class StartupTraceWriterTest; 117 118 static SharedMemoryABI::PageLayout default_page_layout; 119 120 SharedMemoryArbiterImpl(const SharedMemoryArbiterImpl&) = delete; 121 SharedMemoryArbiterImpl& operator=(const SharedMemoryArbiterImpl&) = delete; 122 123 void UpdateCommitDataRequest(SharedMemoryABI::Chunk chunk, 124 WriterID writer_id, 125 BufferID target_buffer, 126 PatchList* patch_list); 127 128 // Called by the TraceWriter destructor. 129 void ReleaseWriterID(WriterID); 130 131 base::TaskRunner* const task_runner_; 132 TracingService::ProducerEndpoint* const producer_endpoint_; 133 134 // --- Begin lock-protected members --- 135 std::mutex lock_; 136 SharedMemoryABI shmem_abi_; 137 size_t page_idx_ = 0; 138 std::unique_ptr<CommitDataRequest> commit_data_req_; 139 size_t bytes_pending_commit_ = 0; // SUM(chunk.size() : commit_data_req_). 140 IdAllocator<WriterID> active_writer_ids_; 141 // Registries whose Bind() is in progress. We destroy each registry when their 142 // Bind() is complete or when the arbiter is destroyed itself. 143 std::vector<std::unique_ptr<StartupTraceWriterRegistry>> 144 startup_trace_writer_registries_; 145 // --- End lock-protected members --- 146 147 // Keep at the end. 148 base::WeakPtrFactory<SharedMemoryArbiterImpl> weak_ptr_factory_; 149 }; 150 151 } // namespace perfetto 152 153 #endif // SRC_TRACING_CORE_SHARED_MEMORY_ARBITER_IMPL_H_ 154