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