blob: adf9e5493593d146d610bd165cf4d136cc997bba [file] [log] [blame]
Florian Mayer824274d2018-09-17 11:33:45 +01001/*
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 SRC_PROFILING_MEMORY_CLIENT_H_
18#define SRC_PROFILING_MEMORY_CLIENT_H_
19
20#include <stddef.h>
Florian Mayeraf266022018-09-17 15:18:15 +010021
Ryan Savitskia502bde2019-02-26 21:34:03 +000022#include <atomic>
Florian Mayereff98042018-12-10 17:44:44 +000023#include <condition_variable>
Florian Mayer824274d2018-09-17 11:33:45 +010024#include <mutex>
25#include <vector>
26
Primiano Tucci43ebf4d2019-01-02 20:04:34 +010027#include "perfetto/base/unix_socket.h"
Ryan Savitskia502bde2019-02-26 21:34:03 +000028#include "src/profiling/memory/sampler.h"
Florian Mayer51950592019-03-06 20:05:15 +000029#include "src/profiling/memory/shared_ring_buffer.h"
Florian Mayerb85a9382018-09-27 13:59:01 +010030#include "src/profiling/memory/wire_protocol.h"
Florian Mayer824274d2018-09-17 11:33:45 +010031
32namespace perfetto {
Florian Mayer8c0d0482018-10-22 14:23:40 +010033namespace profiling {
Florian Mayer824274d2018-09-17 11:33:45 +010034
Florian Mayer51950592019-03-06 20:05:15 +000035class Client;
Florian Mayerb85a9382018-09-27 13:59:01 +010036
37// Cache for frees that have been observed. It is infeasible to send every
38// free separately, so we batch and send the whole buffer once it is full.
39class FreePage {
40 public:
Florian Mayer51950592019-03-06 20:05:15 +000041 FreePage() { free_page_.num_entries = 0; }
Florian Mayer192136e2019-01-30 18:04:34 +000042
Florian Mayer51950592019-03-06 20:05:15 +000043 // Add address to buffer. Flush if necessary.
Ryan Savitskia502bde2019-02-26 21:34:03 +000044 // Can be called from any thread. Must not hold mutex_.
Florian Mayer51950592019-03-06 20:05:15 +000045 bool Add(const uint64_t addr, uint64_t sequence_number, Client* client);
Florian Mayerb85a9382018-09-27 13:59:01 +010046
47 private:
Florian Mayer51950592019-03-06 20:05:15 +000048 // TODO(fmayer): Sort out naming. It's confusing data FreePage has a member
49 // called free_page_ that is of type FreeMetadata.
Florian Mayerb85a9382018-09-27 13:59:01 +010050 FreeMetadata free_page_;
Florian Mayer65081572018-12-18 13:41:08 +000051 std::timed_mutex mutex_;
Florian Mayerb85a9382018-09-27 13:59:01 +010052};
53
54const char* GetThreadStackBase();
55
Florian Mayerdac31272019-02-26 12:07:02 +000056constexpr uint32_t kClientSockTimeoutMs = 1000;
Ryan Savitski14c12d62019-01-08 22:38:53 +000057
Ryan Savitskia502bde2019-02-26 21:34:03 +000058// Profiling client, used to sample and record the malloc/free family of calls,
59// and communicate the necessary state to a separate profiling daemon process.
60//
61// Created and owned by the malloc hooks.
62//
63// Methods of this class are thread-safe unless otherwise stated, in which case
64// the caller needs to synchronize calls behind a mutex or similar.
Florian Mayerb85a9382018-09-27 13:59:01 +010065class Client {
66 public:
Florian Mayer51950592019-03-06 20:05:15 +000067 Client(base::Optional<base::UnixSocketRaw> sock);
68 Client(const std::string& sock_name);
Florian Mayer20c4b3c2019-01-24 18:25:35 +000069 bool RecordMalloc(uint64_t alloc_size,
Florian Mayer9a7fb2b2018-10-17 18:17:40 +010070 uint64_t total_size,
71 uint64_t alloc_address);
Florian Mayer20c4b3c2019-01-24 18:25:35 +000072 bool RecordFree(uint64_t alloc_address);
Florian Mayer2da28412018-10-30 17:33:10 +000073 void Shutdown();
Florian Mayer51950592019-03-06 20:05:15 +000074 bool FlushFrees(FreeMetadata* free_metadata);
Florian Mayerb85a9382018-09-27 13:59:01 +010075
Ryan Savitskia502bde2019-02-26 21:34:03 +000076 // Returns the number of bytes to assign to an allocation with the given
77 // |alloc_size|, based on the current sampling rate. A return value of zero
78 // means that the allocation should not be recorded. Not idempotent, each
79 // invocation mutates the sampler state.
80 //
81 // Not thread-safe.
82 size_t GetSampleSizeLocked(size_t alloc_size) {
83 if (!inited_.load(std::memory_order_acquire))
84 return 0;
85 return sampler_.SampleSize(alloc_size);
86 }
87
Florian Mayer1fe77732018-10-02 17:25:53 +010088 ClientConfiguration client_config_for_testing() { return client_config_; }
Florian Mayerb12c4f22018-11-14 16:13:02 +000089 bool inited() { return inited_; }
Florian Mayer1fe77732018-10-02 17:25:53 +010090
Florian Mayerb85a9382018-09-27 13:59:01 +010091 private:
92 const char* GetStackBase();
93
Ryan Savitskia502bde2019-02-26 21:34:03 +000094 // TODO(rsavitski): used to check if the client is completely initialized
95 // after construction. The reads in RecordFree & GetSampleSizeLocked are no
96 // longer necessary (was an optimization to not do redundant work after
97 // shutdown). Turn into a normal bool, or indicate construction failures
98 // differently.
Florian Mayerf0867992018-11-16 10:12:18 +000099 std::atomic<bool> inited_{false};
Florian Mayer1fe77732018-10-02 17:25:53 +0100100 ClientConfiguration client_config_;
Ryan Savitskia502bde2019-02-26 21:34:03 +0000101 // sampler_ operations are not thread-safe.
102 Sampler sampler_;
Florian Mayer51950592019-03-06 20:05:15 +0000103 base::UnixSocketRaw sock_;
Florian Mayerb85a9382018-09-27 13:59:01 +0100104 FreePage free_page_;
105 const char* main_thread_stack_base_ = nullptr;
106 std::atomic<uint64_t> sequence_number_{0};
Florian Mayer51950592019-03-06 20:05:15 +0000107 SharedRingBuffer shmem_;
Florian Mayerb85a9382018-09-27 13:59:01 +0100108};
109
Florian Mayer8c0d0482018-10-22 14:23:40 +0100110} // namespace profiling
Florian Mayer824274d2018-09-17 11:33:45 +0100111} // namespace perfetto
112
113#endif // SRC_PROFILING_MEMORY_CLIENT_H_