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