1 /* 2 * Copyright (c) 2018 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /** 21 * DOC: qdf_talloc.h - Public APIs for t(ree) alloc(ate) memory management 22 * 23 * These APIs allocate memory like malloc, but track those allocations via a 24 * parent-child relationship, or tree. If the parent is freed while it still has 25 * children, a panic will be triggered. This effectively gives you the ability 26 * to limit the lifetime of an allocation by ensuring the child allocation 27 * lifetime will be strictly less than the parent allocation lifetime. 28 */ 29 30 #ifndef __QDF_TALLOC_H 31 #define __QDF_TALLOC_H 32 33 #include "i_qdf_talloc.h" 34 #include "qdf_status.h" 35 36 /** 37 * qdf_talloc() - t(ree) alloc(ate) memory 38 * @parent: the parent memory of the new allocation 39 * @size: requested size of the newly allocated memory 40 * 41 * Return: pointer to the newly allocated memory 42 */ 43 #define qdf_talloc(parent, size) \ 44 qdf_talloc_fl(parent, size, __func__, __LINE__) 45 46 /** 47 * qdf_talloc_type() - t(ree) alloc(ate) memory for a type 48 * @parent: the parent memory of the new allocation 49 * @cursor: pointer to the type of memory to allocate 50 * 51 * This API automatically determines the correct size needed or an allocation 52 * based on the type of @cursor. If you need to allocate an arbitrary number 53 * of bytes, use qdf_talloc() instead. 54 * 55 * Return: pointer to the newly allocated memory 56 */ 57 #define qdf_talloc_type(parent, cursor) \ 58 qdf_talloc(parent, sizeof(*(cursor))) 59 60 /** 61 * qdf_talloc_fl() - t(ree) alloc(ate) memory with function and line info 62 * @parent: the parent memory of the new allocation 63 * @size: requested size of the newly allocated memory 64 * @func: name of the function requesting the allocation 65 * @line: line number of the call site in @func 66 * 67 * Return: pointer to the newly allocated memory 68 */ 69 #define qdf_talloc_fl(parent, size, func, line) \ 70 __qdf_talloc_fl(parent, size, func, line) 71 72 /** 73 * qdf_tfree() - free memory allocated using the *_talloc() function family 74 * @ptr: double point to memory to free, set to NULL 75 * 76 * Return: None 77 */ 78 #define qdf_tfree(ptr) \ 79 qdf_tfree_fl(ptr, __func__, __LINE__) 80 81 /** 82 * qdf_tfree_fl() - free memory allocated using the *_talloc() function family 83 * with function and line info 84 * @ptr: pointer to memory to free 85 * @func: name of the function requesting the free 86 * @line: line number of the call site in @func 87 * 88 * Return: None 89 */ 90 #define qdf_tfree_fl(ptr, func, line) \ 91 do { \ 92 __qdf_tfree_fl(ptr, func, line); \ 93 ptr = (void *)1; \ 94 } while (false) 95 96 /** 97 * qdf_talloc_assert_no_children() - assert @parent has not child allocations 98 * @parent: the parent memory pointer to check 99 * 100 * Return: None 101 */ 102 #define qdf_talloc_assert_no_children(parent) \ 103 qdf_talloc_assert_no_children_fl(parent, __func__, __LINE__) 104 105 #ifdef WLAN_TALLOC_DEBUG 106 107 /** 108 * qdf_talloc_feature_init() - initialize the QDF talloc feature 109 * 110 * Must be called before allocating memory via a qdf_talloc API. 111 * 112 * Return: None 113 */ 114 QDF_STATUS qdf_talloc_feature_init(void); 115 116 /** 117 * qdf_talloc_feature_deinit() - deinitialize the QDF talloc feature 118 * 119 * Memory must not be allocated via a qdf_talloc API after this is called. This 120 * API asserts that the parent/child relationship table is empty in order to 121 * catch memory leaks. 122 * 123 * Return: None 124 */ 125 void qdf_talloc_feature_deinit(void); 126 127 void *__qdf_talloc_fl(const void *parent, const size_t size, 128 const char *func, const uint16_t line); 129 130 void __qdf_tfree_fl(void *ptr, const char *func, const uint16_t line); 131 132 /** 133 * qdf_talloc_assert_no_children_fl() - assert @parent has not child allocations 134 * @parent: the parent memory pointer to check 135 * @func: name of the function requesting the assert 136 * @line: line number of the call site in @func 137 * 138 * Return: None 139 */ 140 void qdf_talloc_assert_no_children_fl(const void *parent, 141 const char *func, const uint16_t line); 142 143 #else /* WLAN_TALLOC_DEBUG */ 144 qdf_talloc_feature_init(void)145 static inline QDF_STATUS qdf_talloc_feature_init(void) 146 { 147 return QDF_STATUS_SUCCESS; 148 } 149 qdf_talloc_feature_deinit(void)150 static inline void qdf_talloc_feature_deinit(void) { } 151 __qdf_talloc_fl(const void * parent,const size_t size,const char * func,const uint16_t line)152 static inline void *__qdf_talloc_fl(const void *parent, const size_t size, 153 const char *func, const uint16_t line) 154 { 155 return __zalloc_auto(size); 156 } 157 158 static inline void __qdf_tfree_fl(void * ptr,const char * func,const uint16_t line)159 __qdf_tfree_fl(void *ptr, const char *func, const uint16_t line) 160 { 161 __k_free(ptr); 162 } 163 164 static inline void qdf_talloc_assert_no_children_fl(const void * parent,const char * func,const uint16_t line)165 qdf_talloc_assert_no_children_fl(const void *parent, 166 const char *func, const uint16_t line) { } 167 168 #endif /* WLAN_TALLOC_DEBUG */ 169 170 #endif /* __QDF_TALLOC_H */ 171