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 #if defined(__tile__)
51 /* Need to define __mm_ function alternatives, since these are SSE only.
52  */
53 #include <malloc.h>
54 #define _mm_malloc(a,b) memalign((b),(a))
55 #define _mm_free(a) free((a))
56 #endif /* defined(__tile__) */
57 
58 SC_ATOMIC_EXTERN(unsigned int, engine_stage);
59 
60 /* Use this only if you want to debug memory allocation and free()
61  * It will log a lot of lines more, so think that is a performance killer */
62 
63 /* Uncomment this if you want to print memory allocations and free's() */
64 //#define DBG_MEM_ALLOC
65 
66 #ifdef DBG_MEM_ALLOC
67 
68 /* Uncomment this if you want to print mallocs at the startup (recommended) */
69 #define DBG_MEM_ALLOC_SKIP_STARTUP
70 
71 #define SCMalloc(a) ({ \
72  void *ptrmem = NULL; \
73  extern size_t global_mem; \
74  extern uint8_t print_mem_flag; \
75  \
76  ptrmem = malloc((a)); \
77  if (ptrmem == NULL && (a) > 0) { \
78  SCLogError(SC_ERR_MEM_ALLOC, "SCMalloc failed: %s, while trying " \
79  "to allocate %"PRIuMAX" bytes", strerror(errno), (uintmax_t)(a)); \
80  if (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT) {\
81  SCLogError(SC_ERR_FATAL, "Out of memory. The engine cannot be initialized. Exiting..."); \
82  exit(EXIT_FAILURE); \
83  } \
84  } \
85  \
86  global_mem += (a); \
87  if (print_mem_flag == 1) { \
88  SCLogInfo("SCMalloc return at %p of size %"PRIuMAX, \
89  ptrmem, (uintmax_t)(a)); \
90  } \
91  (void*)ptrmem; \
92 })
93 
94 #define SCRealloc(x, a) ({ \
95  void *ptrmem = NULL; \
96  extern size_t global_mem; \
97  extern uint8_t print_mem_flag; \
98  \
99  ptrmem = realloc((x), (a)); \
100  if (ptrmem == NULL && (a) > 0) { \
101  SCLogError(SC_ERR_MEM_ALLOC, "SCRealloc failed: %s, while trying " \
102  "to allocate %"PRIuMAX" bytes", strerror(errno), (uintmax_t)(a)); \
103  if (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT) {\
104  SCLogError(SC_ERR_FATAL, "Out of memory. The engine cannot be initialized. Exiting..."); \
105  exit(EXIT_FAILURE); \
106  } \
107  } \
108  \
109  global_mem += (a); \
110  if (print_mem_flag == 1) { \
111  SCLogInfo("SCRealloc return at %p (old:%p) of size %"PRIuMAX, \
112  ptrmem, (x), (uintmax_t)(a)); \
113  } \
114  (void*)ptrmem; \
115 })
116 
117 #define SCCalloc(nm, a) ({ \
118  void *ptrmem = NULL; \
119  extern size_t global_mem; \
120  extern uint8_t print_mem_flag; \
121  \
122  ptrmem = calloc((nm), (a)); \
123  if (ptrmem == NULL && (a) > 0) { \
124  SCLogError(SC_ERR_MEM_ALLOC, "SCCalloc failed: %s, while trying " \
125  "to allocate %"PRIuMAX" bytes", strerror(errno), (uintmax_t)a); \
126  if (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT) {\
127  SCLogError(SC_ERR_FATAL, "Out of memory. The engine cannot be initialized. Exiting..."); \
128  exit(EXIT_FAILURE); \
129  } \
130  } \
131  \
132  global_mem += (a)*(nm); \
133  if (print_mem_flag == 1) { \
134  SCLogInfo("SCCalloc return at %p of size %"PRIuMAX" (nm) %"PRIuMAX, \
135  ptrmem, (uintmax_t)(a), (uintmax_t)(nm)); \
136  } \
137  (void*)ptrmem; \
138 })
139 
140 #define SCStrdup(a) ({ \
141  char *ptrmem = NULL; \
142  extern size_t global_mem; \
143  extern uint8_t print_mem_flag; \
144  size_t len = strlen((a)); \
145  \
146  ptrmem = strdup((a)); \
147  if (ptrmem == NULL) { \
148  SCLogError(SC_ERR_MEM_ALLOC, "SCStrdup failed: %s, while trying " \
149  "to allocate %"PRIuMAX" bytes", strerror(errno), (uintmax_t)len); \
150  if (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT) {\
151  SCLogError(SC_ERR_FATAL, "Out of memory. The engine cannot be initialized. Exiting..."); \
152  exit(EXIT_FAILURE); \
153  } \
154  } \
155  \
156  global_mem += len; \
157  if (print_mem_flag == 1) { \
158  SCLogInfo("SCStrdup return at %p of size %"PRIuMAX, \
159  ptrmem, (uintmax_t)len); \
160  } \
161  (void*)ptrmem; \
162 })
163 
164 #define SCFree(a) ({ \
165  extern uint8_t print_mem_flag; \
166  if (print_mem_flag == 1) { \
167  SCLogInfo("SCFree at %p", (a)); \
168  } \
169  free((a)); \
170 })
171 
172 #else /* !DBG_MEM_ALLOC */
173 
174 #define SCMalloc(a) ({ \
175  void *ptrmem = NULL; \
176  \
177  ptrmem = malloc((a)); \
178  if (ptrmem == NULL) { \
179  if (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT) {\
180  uintmax_t scmalloc_size_ = (uintmax_t)(a); \
181  SCLogError(SC_ERR_MEM_ALLOC, "SCMalloc failed: %s, while trying " \
182  "to allocate %"PRIuMAX" bytes", strerror(errno), scmalloc_size_); \
183  SCLogError(SC_ERR_FATAL, "Out of memory. The engine cannot be initialized. Exiting..."); \
184  exit(EXIT_FAILURE); \
185  } \
186  } \
187  (void*)ptrmem; \
188 })
189 
190 #define SCRealloc(x, a) ({ \
191  void *ptrmem = NULL; \
192  \
193  ptrmem = realloc((x), (a)); \
194  if (ptrmem == NULL) { \
195  if (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT) {\
196  SCLogError(SC_ERR_MEM_ALLOC, "SCRealloc failed: %s, while trying " \
197  "to allocate %"PRIuMAX" bytes", strerror(errno), (uintmax_t)(a)); \
198  SCLogError(SC_ERR_FATAL, "Out of memory. The engine cannot be initialized. Exiting..."); \
199  exit(EXIT_FAILURE); \
200  } \
201  } \
202  (void*)ptrmem; \
203 })
204 
205 #define SCCalloc(nm, a) ({ \
206  void *ptrmem = NULL; \
207  \
208  ptrmem = calloc((nm), (a)); \
209  if (ptrmem == NULL) { \
210  if (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT) {\
211  SCLogError(SC_ERR_MEM_ALLOC, "SCCalloc failed: %s, while trying " \
212  "to allocate %"PRIuMAX" bytes", strerror(errno), (uintmax_t)(a)); \
213  SCLogError(SC_ERR_FATAL, "Out of memory. The engine cannot be initialized. Exiting..."); \
214  exit(EXIT_FAILURE); \
215  } \
216  } \
217  (void*)ptrmem; \
218 })
219 
220 #define SCStrdup(a) ({ \
221  char *ptrmem = NULL; \
222  \
223  ptrmem = strdup((a)); \
224  if (ptrmem == NULL) { \
225  if (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT) {\
226  size_t _scstrdup_len = strlen((a)); \
227  SCLogError(SC_ERR_MEM_ALLOC, "SCStrdup failed: %s, while trying " \
228  "to allocate %"PRIuMAX" bytes", strerror(errno), (uintmax_t)_scstrdup_len); \
229  SCLogError(SC_ERR_FATAL, "Out of memory. The engine cannot be initialized. Exiting..."); \
230  exit(EXIT_FAILURE); \
231  } \
232  } \
233  (void*)ptrmem; \
234 })
235 
236 #define SCFree(a) ({ \
237  free(a); \
238 })
239 
240 #if defined(__WIN32) || defined(_WIN32)
241 
242 /** \brief wrapper for allocing aligned mem
243  * \param a size
244  * \param b alignement
245  */
246 #define SCMallocAligned(a, b) ({ \
247  void *ptrmem = NULL; \
248  \
249  ptrmem = _mm_malloc((a), (b)); \
250  if (ptrmem == NULL) { \
251  if (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT) {\
252  SCLogError(SC_ERR_MEM_ALLOC, "SCMallocAligned(posix_memalign) failed: %s, while trying " \
253  "to allocate %"PRIuMAX" bytes, alignment %"PRIuMAX, strerror(errno), (uintmax_t)(a), (uintmax_t)(b)); \
254  SCLogError(SC_ERR_FATAL, "Out of memory. The engine cannot be initialized. Exiting..."); \
255  exit(EXIT_FAILURE); \
256  } \
257  } \
258  (void*)ptrmem; \
259 })
260 
261 /** \brief Free aligned memory
262  *
263  * Not needed for mem alloc'd by posix_memalign,
264  * but for possible future use of _mm_malloc needing
265  * _mm_free.
266  */
267 #define SCFreeAligned(a) ({ \
268  _mm_free(a); \
269 })
270 
271 #else /* !win */
272 
273 /** \brief wrapper for allocing aligned mem
274  * \param a size
275  * \param b alignement
276  */
277 #define SCMallocAligned(a, b) ({ \
278  void *ptrmem = NULL; \
279  \
280  int r = posix_memalign(&ptrmem, (b), (a)); \
281  if (r != 0 || ptrmem == NULL) { \
282  if (ptrmem != NULL) { \
283  free(ptrmem); \
284  ptrmem = NULL; \
285  } \
286  if (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT) {\
287  SCLogError(SC_ERR_MEM_ALLOC, "SCMallocAligned(posix_memalign) failed: %s, while trying " \
288  "to allocate %"PRIuMAX" bytes, alignment %"PRIuMAX, strerror(errno), (uintmax_t)a, (uintmax_t)b); \
289  SCLogError(SC_ERR_FATAL, "Out of memory. The engine cannot be initialized. Exiting..."); \
290  exit(EXIT_FAILURE); \
291  } \
292  } \
293  (void*)ptrmem; \
294 })
295 
296 /** \brief Free aligned memory
297  *
298  * Not needed for mem alloc'd by posix_memalign,
299  * but for possible future use of _mm_malloc needing
300  * _mm_free.
301  */
302 #define SCFreeAligned(a) ({ \
303  free(a); \
304 })
305 
306 #endif /* __WIN32 */
307 
308 #endif /* DBG_MEM_ALLOC */
309 
310 #endif /* CPPCHECK */
311 
312 #endif /* __UTIL_MEM_H__ */
313 
SC_ATOMIC_EXTERN(unsigned int, engine_stage)