Home | History | Annotate | Download | only in core
      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 
     98   SharedMemoryABI* shmem_abi_for_testing() { return &shmem_abi_; }
     99 
    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