• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 // API to report allocations to heapprofd. This allows users to see the
18 // callstacks causing these allocations in heap profiles.
19 //
20 // In the context of this API, a "heap" is memory associated with an allocator.
21 // An example of an allocator is the malloc-family of libc functions (malloc /
22 // calloc / posix_memalign).
23 //
24 // A very simple custom allocator would look like this:
25 //
26 // void* my_malloc(size_t size) {
27 //   void* ptr = [code to somehow allocate get size bytes];
28 //   return ptr;
29 // }
30 //
31 // void my_free(void* ptr) {
32 //   [code to somehow free ptr]
33 // }
34 //
35 // To find out where in a program these two functions get called, we instrument
36 // the allocator using this API:
37 //
38 // static uint32_t g_heap_id =
39 //   AHeapProfile_registerHeap(AHeapInfo_create("invalid.example"));
40 //
41 // void* my_malloc(size_t size) {
42 //   void* ptr = [code to somehow allocate get size bytes];
43 //   AHeapProfile_reportAllocation(g_heap_id, static_cast<uintptr_t>(ptr),
44 //                                 size);
45 //   return ptr;
46 // }
47 //
48 // void my_free(void* ptr) {
49 //   AHeapProfile_reportFree(g_heap_id, static_cast<uintptr_t>(ptr));
50 //   [code to somehow free ptr]
51 // }
52 //
53 // This will allow users to get a flamegraph of the callstacks calling into
54 // these functions.
55 //
56 // See https://perfetto.dev/docs/data-sources/native-heap-profiler for more
57 // information on heapprofd in general.
58 
59 #ifndef SRC_PROFILING_MEMORY_INCLUDE_PERFETTO_HEAP_PROFILE_H_
60 #define SRC_PROFILING_MEMORY_INCLUDE_PERFETTO_HEAP_PROFILE_H_
61 
62 #include <inttypes.h>
63 #include <stdlib.h>
64 
65 #pragma GCC diagnostic push
66 
67 #if defined(__clang__)
68 #pragma GCC diagnostic ignored "-Wnullability-extension"
69 #else
70 #define _Nullable
71 #define _Nonnull
72 #endif
73 
74 // Maximum size of heap name, including NUL-byte.
75 #define HEAPPROFD_HEAP_NAME_SZ 64
76 
77 #ifdef __cplusplus
78 extern "C" {
79 #endif
80 
81 typedef struct AHeapInfo AHeapInfo;
82 typedef struct AHeapProfileEnableCallbackInfo AHeapProfileEnableCallbackInfo;
83 typedef struct AHeapProfileDisableCallbackInfo AHeapProfileDisableCallbackInfo;
84 
85 // Get sampling interval (in bytes) of the profiling session that was started.
86 uint64_t AHeapProfileEnableCallbackInfo_getSamplingInterval(
87     const AHeapProfileEnableCallbackInfo* _Nonnull session_info);
88 
89 // Create new AHeapInfo, a struct describing a heap.
90 //
91 // Takes name of the heap, up to 64 bytes including null terminator. To
92 // guarantee uniqueness, this should include the caller's domain name,
93 // e.g. "dev.perfetto.largeobjects".
94 //
95 // On error, returns NULL.
96 // Errors are:
97 //  * Empty or too long (larger than 64 bytes including null terminator)
98 //    heap_name.
99 //  * Too many heaps have been registered in this process already.
100 //
101 // Must eventually be passed to AHeapProfile_registerHeap.
102 AHeapInfo* _Nullable AHeapInfo_create(const char* _Nonnull heap_name);
103 
104 // Set enabled callback in AHeapInfo.
105 //
106 // If info is NULL, do nothing.
107 //
108 // After this AHeapInfo is registered via AHeapProfile_registerHeap,
109 // this callback is called when profiling of the heap is requested.
110 AHeapInfo* _Nullable AHeapInfo_setEnabledCallback(
111     AHeapInfo* _Nullable info,
112     void (*_Nonnull callback)(
113         void* _Nullable,
114         const AHeapProfileEnableCallbackInfo* _Nonnull session_info),
115     void* _Nullable data);
116 
117 // Set disabled callback in AHeapInfo.
118 //
119 // If info is NULL, do nothing.
120 //
121 // After this AHeapInfo is registered via AHeapProfile_registerHeap,
122 // this callback is called when profiling of the heap ends.
123 AHeapInfo* _Nullable AHeapInfo_setDisabledCallback(
124     AHeapInfo* _Nullable info,
125     void (*_Nonnull callback)(
126         void* _Nullable,
127         const AHeapProfileDisableCallbackInfo* _Nonnull session_info),
128     void* _Nullable data);
129 
130 // Register heap described in AHeapInfo.
131 //
132 // If info is NULL, return a no-op heap_id.
133 //
134 // The returned heap_id can be used in AHeapProfile_reportAllocation and
135 // AHeapProfile_reportFree.
136 //
137 // Takes ownership of |info|.
138 uint32_t AHeapProfile_registerHeap(AHeapInfo* _Nullable info);
139 
140 // Reports an allocation of |size| on the given |heap_id|.
141 //
142 // The |alloc_id| needs to be a unique identifier for the allocation, and can
143 // can be used in AHeapProfile_reportFree to report the allocation has been
144 // freed.
145 //
146 // If a profiling session is active, this function decides whether the reported
147 // allocation should be sampled. If the allocation is sampled, it will be
148 // associated to the current callstack in the profile.
149 //
150 // Returns whether the allocation was sampled.
151 bool AHeapProfile_reportAllocation(uint32_t heap_id,
152                                    uint64_t alloc_id,
153                                    uint64_t size);
154 
155 // Reports a sample of |size| on the given |heap_id|.
156 //
157 // If a profiling session is active, this function associates the sample with
158 // the current callstack in the profile.
159 //
160 // Returns whether the profiling session was active.
161 //
162 // THIS IS GENERALLY NOT WHAT YOU WANT. THIS IS ONLY NEEDED IF YOU NEED TO
163 // DO THE SAMPLING YOURSELF FOR PERFORMANCE REASONS.
164 // USE AHeapProfile_reportAllocation TO REPORT AN ALLOCATION AND LET
165 // HEAPPROFD DO THE SAMPLING.
166 //
167 // TODO(fmayer): Make this unavailable to non-Mainline.
168 bool AHeapProfile_reportSample(uint32_t heap_id,
169                                uint64_t alloc_id,
170                                uint64_t size);
171 
172 // Report allocation was freed on the given heap.
173 //
174 // If |alloc_id| was sampled in a previous call to
175 // AHeapProfile_reportAllocation, this allocation is marked as freed in the
176 // profile.
177 //
178 // It is allowed to call with an |alloc_id| that was either not sampled or never
179 // passed to AHeapProfile_reportAllocation, in which case the call will not
180 // change the output.
181 void AHeapProfile_reportFree(uint32_t heap_id, uint64_t alloc_id);
182 
183 #ifdef __cplusplus
184 }
185 #endif
186 
187 #pragma GCC diagnostic pop
188 
189 #endif  // SRC_PROFILING_MEMORY_INCLUDE_PERFETTO_HEAP_PROFILE_H_
190