suricata
util-mem.h
Go to the documentation of this file.
1 /* Copyright (C) 2007-2014 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Pablo Rincon Crespo <pablo.rincon.crespo@gmail.com>
22  *
23  * Utility Macros for memory management
24  *
25  * \todo Add wrappers for functions that allocate/free memory here.
26  * Currently we have malloc, calloc, realloc, strdup and free,
27  * but there are more.
28  */
29 
30 #ifndef __UTIL_MEM_H__
31 #define __UTIL_MEM_H__
32 
33 #include "util-atomic.h"
34 
35 #if CPPCHECK==1 || defined(__clang_analyzer__)
36 #define SCMalloc malloc
37 #define SCCalloc calloc
38 #define SCRealloc realloc
39 #define SCFree free
40 #define SCStrdup strdup
41 #define SCMallocAligned _mm_malloc
42 #define SCFreeAligned _mm_free
43 #else /* CPPCHECK */
44 
45 
46 #if defined(_WIN32) || defined(__WIN32)
47 #include "mm_malloc.h"
48 #endif
49 
50 SC_ATOMIC_EXTERN(unsigned int, engine_stage);
51 
52 /* Use this only if you want to debug memory allocation and free()
53  * It will log a lot of lines more, so think that is a performance killer */
54 
55 /* Uncomment this if you want to print memory allocations and free's() */
56 //#define DBG_MEM_ALLOC
57 
58 #ifdef DBG_MEM_ALLOC
59 
60 /* Uncomment this if you want to print mallocs at the startup (recommended) */
61 #define DBG_MEM_ALLOC_SKIP_STARTUP
62 
63 #define SCMalloc(a) ({ \
64  void *ptrmem = NULL; \
65  extern size_t global_mem; \
66  extern uint8_t print_mem_flag; \
67  \
68  ptrmem = malloc((a)); \
69  if (ptrmem == NULL && (a) > 0) { \
70  SCLogError(SC_ERR_MEM_ALLOC, "SCMalloc failed: %s, while trying " \
71  "to allocate %"PRIuMAX" bytes", strerror(errno), (uintmax_t)(a)); \
72  if (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT) {\
73  SCLogError(SC_ERR_FATAL, "Out of memory. The engine cannot be initialized. Exiting..."); \
74  exit(EXIT_FAILURE); \
75  } \
76  } \
77  \
78  global_mem += (a); \
79  if (print_mem_flag == 1) { \
80  SCLogInfo("SCMalloc return at %p of size %"PRIuMAX, \
81  ptrmem, (uintmax_t)(a)); \
82  } \
83  (void*)ptrmem; \
84 })
85 
86 #define SCRealloc(x, a) ({ \
87  void *ptrmem = NULL; \
88  extern size_t global_mem; \
89  extern uint8_t print_mem_flag; \
90  \
91  ptrmem = realloc((x), (a)); \
92  if (ptrmem == NULL && (a) > 0) { \
93  SCLogError(SC_ERR_MEM_ALLOC, "SCRealloc failed: %s, while trying " \
94  "to allocate %"PRIuMAX" bytes", strerror(errno), (uintmax_t)(a)); \
95  if (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT) {\
96  SCLogError(SC_ERR_FATAL, "Out of memory. The engine cannot be initialized. Exiting..."); \
97  exit(EXIT_FAILURE); \
98  } \
99  } \
100  \
101  global_mem += (a); \
102  if (print_mem_flag == 1) { \
103  SCLogInfo("SCRealloc return at %p (old:%p) of size %"PRIuMAX, \
104  ptrmem, (x), (uintmax_t)(a)); \
105  } \
106  (void*)ptrmem; \
107 })
108 
109 #define SCCalloc(nm, a) ({ \
110  void *ptrmem = NULL; \
111  extern size_t global_mem; \
112  extern uint8_t print_mem_flag; \
113  \
114  ptrmem = calloc((nm), (a)); \
115  if (ptrmem == NULL && (a) > 0) { \
116  SCLogError(SC_ERR_MEM_ALLOC, "SCCalloc failed: %s, while trying " \
117  "to allocate %"PRIuMAX" bytes", strerror(errno), (uintmax_t)a); \
118  if (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT) {\
119  SCLogError(SC_ERR_FATAL, "Out of memory. The engine cannot be initialized. Exiting..."); \
120  exit(EXIT_FAILURE); \
121  } \
122  } \
123  \
124  global_mem += (a)*(nm); \
125  if (print_mem_flag == 1) { \
126  SCLogInfo("SCCalloc return at %p of size %"PRIuMAX" (nm) %"PRIuMAX, \
127  ptrmem, (uintmax_t)(a), (uintmax_t)(nm)); \
128  } \
129  (void*)ptrmem; \
130 })
131 
132 #define SCStrdup(a) ({ \
133  char *ptrmem = NULL; \
134  extern size_t global_mem; \
135  extern uint8_t print_mem_flag; \
136  size_t len = strlen((a)); \
137  \
138  ptrmem = strdup((a)); \
139  if (ptrmem == NULL) { \
140  SCLogError(SC_ERR_MEM_ALLOC, "SCStrdup failed: %s, while trying " \
141  "to allocate %"PRIuMAX" bytes", strerror(errno), (uintmax_t)len); \
142  if (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT) {\
143  SCLogError(SC_ERR_FATAL, "Out of memory. The engine cannot be initialized. Exiting..."); \
144  exit(EXIT_FAILURE); \
145  } \
146  } \
147  \
148  global_mem += len; \
149  if (print_mem_flag == 1) { \
150  SCLogInfo("SCStrdup return at %p of size %"PRIuMAX, \
151  ptrmem, (uintmax_t)len); \
152  } \
153  (void*)ptrmem; \
154 })
155 
156 #define SCFree(a) ({ \
157  extern uint8_t print_mem_flag; \
158  if (print_mem_flag == 1) { \
159  SCLogInfo("SCFree at %p", (a)); \
160  } \
161  free((a)); \
162 })
163 
164 #else /* !DBG_MEM_ALLOC */
165 
166 #define SCMalloc(a) ({ \
167  void *ptrmem = NULL; \
168  \
169  ptrmem = malloc((a)); \
170  if (ptrmem == NULL) { \
171  if (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT) {\
172  uintmax_t scmalloc_size_ = (uintmax_t)(a); \
173  SCLogError(SC_ERR_MEM_ALLOC, "SCMalloc failed: %s, while trying " \
174  "to allocate %"PRIuMAX" bytes", strerror(errno), scmalloc_size_); \
175  SCLogError(SC_ERR_FATAL, "Out of memory. The engine cannot be initialized. Exiting..."); \
176  exit(EXIT_FAILURE); \
177  } \
178  } \
179  (void*)ptrmem; \
180 })
181 
182 #define SCRealloc(x, a) ({ \
183  void *ptrmem = NULL; \
184  \
185  ptrmem = realloc((x), (a)); \
186  if (ptrmem == NULL) { \
187  if (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT) {\
188  SCLogError(SC_ERR_MEM_ALLOC, "SCRealloc failed: %s, while trying " \
189  "to allocate %"PRIuMAX" bytes", strerror(errno), (uintmax_t)(a)); \
190  SCLogError(SC_ERR_FATAL, "Out of memory. The engine cannot be initialized. Exiting..."); \
191  exit(EXIT_FAILURE); \
192  } \
193  } \
194  (void*)ptrmem; \
195 })
196 
197 #define SCCalloc(nm, a) ({ \
198  void *ptrmem = NULL; \
199  \
200  ptrmem = calloc((nm), (a)); \
201  if (ptrmem == NULL) { \
202  if (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT) {\
203  SCLogError(SC_ERR_MEM_ALLOC, "SCCalloc failed: %s, while trying " \
204  "to allocate %"PRIuMAX" bytes", strerror(errno), (uintmax_t)(a)); \
205  SCLogError(SC_ERR_FATAL, "Out of memory. The engine cannot be initialized. Exiting..."); \
206  exit(EXIT_FAILURE); \
207  } \
208  } \
209  (void*)ptrmem; \
210 })
211 
212 #define SCStrdup(a) ({ \
213  char *ptrmem = NULL; \
214  \
215  ptrmem = strdup((a)); \
216  if (ptrmem == NULL) { \
217  if (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT) {\
218  size_t _scstrdup_len = strlen((a)); \
219  SCLogError(SC_ERR_MEM_ALLOC, "SCStrdup failed: %s, while trying " \
220  "to allocate %"PRIuMAX" bytes", strerror(errno), (uintmax_t)_scstrdup_len); \
221  SCLogError(SC_ERR_FATAL, "Out of memory. The engine cannot be initialized. Exiting..."); \
222  exit(EXIT_FAILURE); \
223  } \
224  } \
225  (void*)ptrmem; \
226 })
227 
228 #define SCFree(a) ({ \
229  free(a); \
230 })
231 
232 #if defined(__WIN32) || defined(_WIN32)
233 
234 /** \brief wrapper for allocing aligned mem
235  * \param a size
236  * \param b alignement
237  */
238 #define SCMallocAligned(a, b) ({ \
239  void *ptrmem = NULL; \
240  \
241  ptrmem = _mm_malloc((a), (b)); \
242  if (ptrmem == NULL) { \
243  if (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT) {\
244  SCLogError(SC_ERR_MEM_ALLOC, "SCMallocAligned(posix_memalign) failed: %s, while trying " \
245  "to allocate %"PRIuMAX" bytes, alignment %"PRIuMAX, strerror(errno), (uintmax_t)(a), (uintmax_t)(b)); \
246  SCLogError(SC_ERR_FATAL, "Out of memory. The engine cannot be initialized. Exiting..."); \
247  exit(EXIT_FAILURE); \
248  } \
249  } \
250  (void*)ptrmem; \
251 })
252 
253 /** \brief Free aligned memory
254  *
255  * Not needed for mem alloc'd by posix_memalign,
256  * but for possible future use of _mm_malloc needing
257  * _mm_free.
258  */
259 #define SCFreeAligned(a) ({ \
260  _mm_free(a); \
261 })
262 
263 #else /* !win */
264 
265 /** \brief wrapper for allocing aligned mem
266  * \param a size
267  * \param b alignement
268  */
269 #define SCMallocAligned(a, b) ({ \
270  void *ptrmem = NULL; \
271  \
272  int r = posix_memalign(&ptrmem, (b), (a)); \
273  if (r != 0 || ptrmem == NULL) { \
274  if (ptrmem != NULL) { \
275  free(ptrmem); \
276  ptrmem = NULL; \
277  } \
278  if (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT) {\
279  SCLogError(SC_ERR_MEM_ALLOC, "SCMallocAligned(posix_memalign) failed: %s, while trying " \
280  "to allocate %"PRIuMAX" bytes, alignment %"PRIuMAX, strerror(errno), (uintmax_t)a, (uintmax_t)b); \
281  SCLogError(SC_ERR_FATAL, "Out of memory. The engine cannot be initialized. Exiting..."); \
282  exit(EXIT_FAILURE); \
283  } \
284  } \
285  (void*)ptrmem; \
286 })
287 
288 /** \brief Free aligned memory
289  *
290  * Not needed for mem alloc'd by posix_memalign,
291  * but for possible future use of _mm_malloc needing
292  * _mm_free.
293  */
294 #define SCFreeAligned(a) ({ \
295  free(a); \
296 })
297 
298 #endif /* __WIN32 */
299 
300 #endif /* DBG_MEM_ALLOC */
301 
302 #endif /* CPPCHECK */
303 
304 #endif /* __UTIL_MEM_H__ */
305 
SC_ATOMIC_EXTERN(unsigned int, engine_stage)