xref: /wlan-dirver/qca-wifi-host-cmn/qdf/inc/qdf_talloc.h (revision 1397a33f48ea6455be40871470b286e535820eb8)
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