1 /* 2 * kmp_wrapper_malloc.h -- Wrappers for memory allocation routines 3 * (malloc(), free(), and others). 4 */ 5 6 7 //===----------------------------------------------------------------------===// 8 // 9 // The LLVM Compiler Infrastructure 10 // 11 // This file is dual licensed under the MIT and the University of Illinois Open 12 // Source Licenses. See LICENSE.txt for details. 13 // 14 //===----------------------------------------------------------------------===// 15 16 17 #ifndef KMP_WRAPPER_MALLOC_H 18 #define KMP_WRAPPER_MALLOC_H 19 20 /* 21 This header serves for 3 purposes: 22 23 1. Declaring standard memory allocation rourines in OS-independent way. 24 2. Passing source location info through memory allocation wrappers. 25 3. Enabling native memory debugging capabilities. 26 27 28 1. Declaring standard memory allocation rourines in OS-independent way. 29 ----------------------------------------------------------------------- 30 31 On Linux* OS, alloca() function is declared in <alloca.h> header, while on Windows* OS there is no 32 <alloca.h> header, function _alloca() (note underscore!) is declared in <malloc.h>. This header 33 eliminates these differences, so client code incluiding "kmp_wrapper_malloc.h" can rely on 34 following routines: 35 36 malloc 37 calloc 38 realloc 39 free 40 alloca 41 42 in OS-independent way. It also enables memory tracking capabilities in debug build. (Currently 43 it is available only on Windows* OS.) 44 45 46 2. Passing source location info through memory allocation wrappers. 47 ------------------------------------------------------------------- 48 49 Some tools may help debugging memory errors, for example, report memory leaks. However, memory 50 allocation wrappers may hinder source location. 51 52 For example: 53 54 void * aligned_malloc( int size ) { 55 void * ptr = malloc( size ); // All the memory leaks will be reported at this line. 56 // some adjustments... 57 return ptr; 58 }; 59 60 ptr = aligned_malloc( size ); // Memory leak will *not* be detected here. :-( 61 62 To overcome the problem, information about original source location should be passed through all 63 the memory allocation wrappers, for example: 64 65 void * aligned_malloc( int size, char const * file, int line ) { 66 void * ptr = _malloc_dbg( size, file, line ); 67 // some adjustments... 68 return ptr; 69 }; 70 71 void * ptr = aligned_malloc( size, __FILE__, __LINE__ ); 72 73 This is a good idea for debug, but passing additional arguments impacts performance. Disabling 74 extra arguments in release version of the software introduces too many conditional compilation, 75 which makes code unreadable. This header defines few macros and functions facilitating it: 76 77 void * _aligned_malloc( int size KMP_SRC_LOC_DECL ) { 78 void * ptr = malloc_src_loc( size KMP_SRC_LOC_PARM ); 79 // some adjustments... 80 return ptr; 81 }; 82 #define aligned_malloc( size ) _aligned_malloc( (size) KMP_SRC_LOC_CURR ) 83 // Use macro instead of direct call to function. 84 85 void * ptr = aligned_malloc( size ); // Bingo! Memory leak will be reported at this line. 86 87 88 3. Enabling native memory debugging capabilities. 89 ------------------------------------------------- 90 91 Some platforms may offer memory debugging capabilities. For example, debug version of Microsoft 92 RTL tracks all memory allocations and can report memory leaks. This header enables this, and 93 makes report more useful (see "Passing source location info through memory allocation 94 wrappers"). 95 96 */ 97 98 #include <stdlib.h> 99 100 #include "kmp_os.h" 101 102 // Include alloca() declaration. 103 #if KMP_OS_WINDOWS 104 #include <malloc.h> // Windows* OS: _alloca() declared in "malloc.h". 105 #define alloca _alloca // Allow to use alloca() with no underscore. 106 #elif KMP_OS_FREEBSD || KMP_OS_NETBSD 107 // Declared in "stdlib.h". 108 #elif KMP_OS_UNIX 109 #include <alloca.h> // Linux* OS and OS X*: alloc() declared in "alloca". 110 #else 111 #error Unknown or unsupported OS. 112 #endif 113 114 /* 115 KMP_SRC_LOC_DECL -- Declaring source location paramemters, to be used in function declaration. 116 KMP_SRC_LOC_PARM -- Source location paramemters, to be used to pass parameters to underlying 117 levels. 118 KMP_SRC_LOC_CURR -- Source location arguments describing current location, to be used at 119 top-level. 120 121 Typical usage: 122 123 void * _aligned_malloc( int size KMP_SRC_LOC_DECL ) { 124 // Note: Comma is missed before KMP_SRC_LOC_DECL. 125 KE_TRACE( 25, ( "called from %s:%d\n", KMP_SRC_LOC_PARM ) ); 126 ... 127 } 128 #define aligned_malloc( size ) _aligned_malloc( (size) KMP_SRC_LOC_CURR ) 129 // Use macro instead of direct call to function -- macro passes info about current 130 // source location to the func. 131 */ 132 #if KMP_DEBUG 133 #define KMP_SRC_LOC_DECL , char const * _file_, int _line_ 134 #define KMP_SRC_LOC_PARM , _file_, _line_ 135 #define KMP_SRC_LOC_CURR , __FILE__, __LINE__ 136 #else 137 #define KMP_SRC_LOC_DECL 138 #define KMP_SRC_LOC_PARM 139 #define KMP_SRC_LOC_CURR 140 #endif // KMP_DEBUG 141 142 /* 143 malloc_src_loc() and free_src_loc() are pseudo-functions (really macros) with accepts extra 144 arguments (source location info) in debug mode. They should be used in place of malloc() and 145 free(), this allows enabling native memory debugging capabilities (if any). 146 147 Typical usage: 148 149 ptr = malloc_src_loc( size KMP_SRC_LOC_PARM ); 150 // Inside memory allocation wrapper, or 151 ptr = malloc_src_loc( size KMP_SRC_LOC_CURR ); 152 // Outside of memory allocation wrapper. 153 154 155 */ 156 #define malloc_src_loc( args ) _malloc_src_loc( args ) 157 #define free_src_loc( args ) _free_src_loc( args ) 158 /* 159 Depending on build mode (debug or release), malloc_src_loc is declared with 1 or 3 160 parameters, but calls to malloc_src_loc() are always the same: 161 162 ... malloc_src_loc( size KMP_SRC_LOC_PARM ); // or KMP_SRC_LOC_CURR 163 164 Compiler issues warning/error "too few arguments in macro invocation". Declaring two 165 macroses, malloc_src_loc() and _malloc_src_loc() overcomes the problem. 166 */ 167 168 #if KMP_DEBUG 169 170 #if KMP_OS_WINDOWS && _DEBUG 171 // KMP_DEBUG != _DEBUG. MS debug RTL is available only if _DEBUG is defined. 172 173 // Windows* OS has native memory debugging capabilities. Enable them. 174 175 #include <crtdbg.h> 176 177 #define KMP_MEM_BLOCK _CLIENT_BLOCK 178 #define malloc( size ) _malloc_dbg( (size), KMP_MEM_BLOCK, __FILE__, __LINE__ ) 179 #define calloc( num, size ) _calloc_dbg( (num), (size), KMP_MEM_BLOCK, __FILE__, __LINE__ ) 180 #define realloc( ptr, size ) _realloc_dbg( (ptr), (size), KMP_MEM_BLOCK, __FILE__, __LINE__ ) 181 #define free( ptr ) _free_dbg( (ptr), KMP_MEM_BLOCK ) 182 183 #define _malloc_src_loc( size, file, line ) _malloc_dbg( (size), KMP_MEM_BLOCK, (file), (line) ) 184 #define _free_src_loc( ptr, file, line ) _free_dbg( (ptr), KMP_MEM_BLOCK ) 185 186 #else 187 188 // Linux* OS, OS X*, or non-debug Windows* OS. 189 190 #define _malloc_src_loc( size, file, line ) malloc( (size) ) 191 #define _free_src_loc( ptr, file, line ) free( (ptr) ) 192 193 #endif 194 195 #else 196 197 // In release build malloc_src_loc() and free_src_loc() do not have extra parameters. 198 #define _malloc_src_loc( size ) malloc( (size) ) 199 #define _free_src_loc( ptr ) free( (ptr) ) 200 201 #endif // KMP_DEBUG 202 203 #endif // KMP_WRAPPER_MALLOC_H 204 205 // end of file // 206