blob: baef4ca66edcf1c463f4d0ac951269439f891281 [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 Mayerb85a9382018-09-27 13:59:01 +010035const char* GetThreadStackBase();
36
Florian Mayerdac31272019-02-26 12:07:02 +000037constexpr uint32_t kClientSockTimeoutMs = 1000;
Ryan Savitski14c12d62019-01-08 22:38:53 +000038
Ryan Savitskia502bde2019-02-26 21:34:03 +000039// Profiling client, used to sample and record the malloc/free family of calls,
40// and communicate the necessary state to a separate profiling daemon process.
41//
42// Created and owned by the malloc hooks.
43//
44// Methods of this class are thread-safe unless otherwise stated, in which case
45// the caller needs to synchronize calls behind a mutex or similar.
Florian Mayerb85a9382018-09-27 13:59:01 +010046class Client {
47 public:
Florian Mayer51950592019-03-06 20:05:15 +000048 Client(base::Optional<base::UnixSocketRaw> sock);
49 Client(const std::string& sock_name);
Florian Mayer20c4b3c2019-01-24 18:25:35 +000050 bool RecordMalloc(uint64_t alloc_size,
Florian Mayer9a7fb2b2018-10-17 18:17:40 +010051 uint64_t total_size,
52 uint64_t alloc_address);
Florian Mayer20c4b3c2019-01-24 18:25:35 +000053 bool RecordFree(uint64_t alloc_address);
Florian Mayer2da28412018-10-30 17:33:10 +000054 void Shutdown();
Florian Mayerb85a9382018-09-27 13:59:01 +010055
Ryan Savitskia502bde2019-02-26 21:34:03 +000056 // Returns the number of bytes to assign to an allocation with the given
57 // |alloc_size|, based on the current sampling rate. A return value of zero
58 // means that the allocation should not be recorded. Not idempotent, each
59 // invocation mutates the sampler state.
60 //
61 // Not thread-safe.
62 size_t GetSampleSizeLocked(size_t alloc_size) {
63 if (!inited_.load(std::memory_order_acquire))
64 return 0;
65 return sampler_.SampleSize(alloc_size);
66 }
67
Florian Mayer1fe77732018-10-02 17:25:53 +010068 ClientConfiguration client_config_for_testing() { return client_config_; }
Florian Mayerb12c4f22018-11-14 16:13:02 +000069 bool inited() { return inited_; }
Florian Mayer1fe77732018-10-02 17:25:53 +010070
Florian Mayerb85a9382018-09-27 13:59:01 +010071 private:
72 const char* GetStackBase();
73
Ryan Savitski549753e2019-03-15 15:52:37 +000074 // Add address to buffer of deallocations. Flush if necessary.
75 // Can be called from any thread. Must not hold free_batch_lock_.
76 bool AddFreeToBatch(uint64_t addr, uint64_t sequence_number);
77 // Flush the contents of free_batch_. Must hold free_batch_lock_.
78 bool FlushFreesLocked();
79
Ryan Savitskia502bde2019-02-26 21:34:03 +000080 // TODO(rsavitski): used to check if the client is completely initialized
81 // after construction. The reads in RecordFree & GetSampleSizeLocked are no
82 // longer necessary (was an optimization to not do redundant work after
83 // shutdown). Turn into a normal bool, or indicate construction failures
84 // differently.
Florian Mayerf0867992018-11-16 10:12:18 +000085 std::atomic<bool> inited_{false};
Florian Mayer1fe77732018-10-02 17:25:53 +010086 ClientConfiguration client_config_;
Ryan Savitskia502bde2019-02-26 21:34:03 +000087 // sampler_ operations are not thread-safe.
88 Sampler sampler_;
Florian Mayer51950592019-03-06 20:05:15 +000089 base::UnixSocketRaw sock_;
Ryan Savitski549753e2019-03-15 15:52:37 +000090
91 // Protected by free_batch_lock_.
92 FreeBatch free_batch_;
93 std::timed_mutex free_batch_lock_;
94
Florian Mayerb85a9382018-09-27 13:59:01 +010095 const char* main_thread_stack_base_ = nullptr;
96 std::atomic<uint64_t> sequence_number_{0};
Florian Mayer51950592019-03-06 20:05:15 +000097 SharedRingBuffer shmem_;
Florian Mayerb85a9382018-09-27 13:59:01 +010098};
99
Florian Mayer8c0d0482018-10-22 14:23:40 +0100100} // namespace profiling
Florian Mayer824274d2018-09-17 11:33:45 +0100101} // namespace perfetto
102
103#endif // SRC_PROFILING_MEMORY_CLIENT_H_