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