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 <stdlib.h> 63 64 #include <cinttypes> 65 66 #pragma GCC diagnostic push 67 68 #if defined(__clang__) 69 #pragma GCC diagnostic ignored "-Wnullability-extension" 70 #else 71 #define _Nullable 72 #define _Nonnull 73 #endif 74 75 // Maximum size of heap name, including NUL-byte. 76 #define HEAPPROFD_HEAP_NAME_SZ 64 77 78 #ifdef __cplusplus 79 extern "C" { 80 #endif 81 82 typedef struct AHeapInfo AHeapInfo; 83 typedef struct AHeapProfileEnableCallbackInfo AHeapProfileEnableCallbackInfo; 84 typedef struct AHeapProfileDisableCallbackInfo AHeapProfileDisableCallbackInfo; 85 86 typedef void (*_Nonnull AHeapInfo_EnableCallback)( 87 void* _Nullable data, 88 const AHeapProfileEnableCallbackInfo* _Nonnull session_info); 89 90 typedef void (*_Nonnull AHeapInfo_DisableCallback)( 91 void* _Nullable data, 92 const AHeapProfileDisableCallbackInfo* _Nonnull session_info); 93 94 // Get sampling interval (in bytes) of the profiling session that was started. 95 uint64_t AHeapProfileEnableCallbackInfo_getSamplingInterval( 96 const AHeapProfileEnableCallbackInfo* _Nonnull session_info); 97 98 // Create new AHeapInfo, a struct describing a heap. 99 // 100 // Takes name of the heap, up to 64 bytes including null terminator. To 101 // guarantee uniqueness, this should include the caller's domain name, 102 // e.g. "dev.perfetto.largeobjects". 103 // 104 // On error, returns NULL. 105 // Errors are: 106 // * Empty or too long (larger than 64 bytes including null terminator) 107 // heap_name. 108 // * Too many heaps have been registered in this process already. 109 // 110 // Must eventually be passed to AHeapProfile_registerHeap. 111 AHeapInfo* _Nullable AHeapInfo_create(const char* _Nonnull heap_name); 112 113 // Set enabled callback in AHeapInfo. 114 // 115 // If info is NULL, do nothing. 116 // 117 // After this AHeapInfo is registered via AHeapProfile_registerHeap, 118 // this callback is called when profiling of the heap is requested. 119 AHeapInfo* _Nullable AHeapInfo_setEnabledCallback( 120 AHeapInfo* _Nullable info, 121 AHeapInfo_EnableCallback callback, 122 void* _Nullable data); 123 124 // Set disabled callback in AHeapInfo. 125 // 126 // If info is NULL, do nothing. 127 // 128 // After this AHeapInfo is registered via AHeapProfile_registerHeap, 129 // this callback is called when profiling of the heap ends. 130 AHeapInfo* _Nullable AHeapInfo_setDisabledCallback( 131 AHeapInfo* _Nullable info, 132 AHeapInfo_DisableCallback callback, 133 void* _Nullable data); 134 135 // Register heap described in AHeapInfo. 136 // 137 // If info is NULL, return a no-op heap_id. 138 // 139 // The returned heap_id can be used in AHeapProfile_reportAllocation and 140 // AHeapProfile_reportFree. 141 // 142 // Takes ownership of |info|. 143 uint32_t AHeapProfile_registerHeap(AHeapInfo* _Nullable info); 144 145 // Reports an allocation of |size| on the given |heap_id|. 146 // 147 // The |alloc_id| needs to be a unique identifier for the allocation, and can 148 // can be used in AHeapProfile_reportFree to report the allocation has been 149 // freed. 150 // 151 // If a profiling session is active, this function decides whether the reported 152 // allocation should be sampled. If the allocation is sampled, it will be 153 // associated to the current callstack in the profile. 154 // 155 // Returns whether the allocation was sampled. 156 bool AHeapProfile_reportAllocation(uint32_t heap_id, 157 uint64_t alloc_id, 158 uint64_t size); 159 160 // Reports a sample of |size| on the given |heap_id|. 161 // 162 // If a profiling session is active, this function associates the sample with 163 // the current callstack in the profile. 164 // 165 // Returns whether the profiling session was active. 166 // 167 // THIS IS GENERALLY NOT WHAT YOU WANT. THIS IS ONLY NEEDED IF YOU NEED TO 168 // DO THE SAMPLING YOURSELF FOR PERFORMANCE REASONS. 169 // USE AHeapProfile_reportAllocation TO REPORT AN ALLOCATION AND LET 170 // HEAPPROFD DO THE SAMPLING. 171 // 172 // TODO(fmayer): Make this unavailable to non-Mainline. 173 bool AHeapProfile_reportSample(uint32_t heap_id, 174 uint64_t alloc_id, 175 uint64_t size); 176 177 // Report allocation was freed on the given heap. 178 // 179 // If |alloc_id| was sampled in a previous call to 180 // AHeapProfile_reportAllocation, this allocation is marked as freed in the 181 // profile. 182 // 183 // It is allowed to call with an |alloc_id| that was either not sampled or never 184 // passed to AHeapProfile_reportAllocation, in which case the call will not 185 // change the output. 186 void AHeapProfile_reportFree(uint32_t heap_id, uint64_t alloc_id); 187 188 #ifdef __cplusplus 189 } 190 #endif 191 192 #pragma GCC diagnostic pop 193 194 #endif // SRC_PROFILING_MEMORY_INCLUDE_PERFETTO_HEAP_PROFILE_H_ 195