• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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