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