1345153Sdim/* 2345153Sdim * kmp_wrapper_malloc.h -- Wrappers for memory allocation routines 3345153Sdim * (malloc(), free(), and others). 4345153Sdim */ 5345153Sdim 6345153Sdim//===----------------------------------------------------------------------===// 7345153Sdim// 8353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 9353358Sdim// See https://llvm.org/LICENSE.txt for license information. 10353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 11345153Sdim// 12345153Sdim//===----------------------------------------------------------------------===// 13345153Sdim 14345153Sdim#ifndef KMP_WRAPPER_MALLOC_H 15345153Sdim#define KMP_WRAPPER_MALLOC_H 16345153Sdim 17345153Sdim/* This header serves for 3 purposes: 18345153Sdim 1. Declaring standard memory allocation rourines in OS-independent way. 19345153Sdim 2. Passing source location info through memory allocation wrappers. 20345153Sdim 3. Enabling native memory debugging capabilities. 21345153Sdim 22345153Sdim 1. Declaring standard memory allocation rourines in OS-independent way. 23345153Sdim ----------------------------------------------------------------------- 24345153Sdim On Linux* OS, alloca() function is declared in <alloca.h> header, while on 25345153Sdim Windows* OS there is no <alloca.h> header, function _alloca() (note 26345153Sdim underscore!) is declared in <malloc.h>. This header eliminates these 27360784Sdim differences, so client code including "kmp_wrapper_malloc.h" can rely on 28345153Sdim following routines: 29345153Sdim 30345153Sdim malloc 31345153Sdim calloc 32345153Sdim realloc 33345153Sdim free 34345153Sdim alloca 35345153Sdim 36345153Sdim in OS-independent way. It also enables memory tracking capabilities in debug 37345153Sdim build. (Currently it is available only on Windows* OS.) 38345153Sdim 39345153Sdim 2. Passing source location info through memory allocation wrappers. 40345153Sdim ------------------------------------------------------------------- 41345153Sdim Some tools may help debugging memory errors, for example, report memory 42345153Sdim leaks. However, memory allocation wrappers may hinder source location. 43345153Sdim For example: 44345153Sdim 45345153Sdim void * aligned_malloc( int size ) { 46345153Sdim void * ptr = malloc( size ); // All the memory leaks will be reported at 47345153Sdim // this line. 48345153Sdim // some adjustments... 49345153Sdim return ptr; 50345153Sdim }; 51345153Sdim 52345153Sdim ptr = aligned_malloc( size ); // Memory leak will *not* be detected here. :-( 53345153Sdim 54345153Sdim To overcome the problem, information about original source location should 55345153Sdim be passed through all the memory allocation wrappers, for example: 56345153Sdim 57345153Sdim void * aligned_malloc( int size, char const * file, int line ) { 58345153Sdim void * ptr = _malloc_dbg( size, file, line ); 59345153Sdim // some adjustments... 60345153Sdim return ptr; 61345153Sdim }; 62345153Sdim void * ptr = aligned_malloc( size, __FILE__, __LINE__ ); 63345153Sdim 64345153Sdim This is a good idea for debug, but passing additional arguments impacts 65345153Sdim performance. Disabling extra arguments in release version of the software 66345153Sdim introduces too many conditional compilation, which makes code unreadable. 67345153Sdim This header defines few macros and functions facilitating it: 68345153Sdim 69345153Sdim void * _aligned_malloc( int size KMP_SRC_LOC_DECL ) { 70345153Sdim void * ptr = malloc_src_loc( size KMP_SRC_LOC_PARM ); 71345153Sdim // some adjustments... 72345153Sdim return ptr; 73345153Sdim }; 74345153Sdim #define aligned_malloc( size ) _aligned_malloc( (size) KMP_SRC_LOC_CURR ) 75345153Sdim // Use macro instead of direct call to function. 76345153Sdim 77345153Sdim void * ptr = aligned_malloc( size ); // Bingo! Memory leak will be 78345153Sdim // reported at this line. 79345153Sdim 80345153Sdim 3. Enabling native memory debugging capabilities. 81345153Sdim ------------------------------------------------- 82345153Sdim Some platforms may offer memory debugging capabilities. For example, debug 83345153Sdim version of Microsoft RTL tracks all memory allocations and can report memory 84345153Sdim leaks. This header enables this, and makes report more useful (see "Passing 85345153Sdim source location info through memory allocation wrappers"). 86345153Sdim*/ 87345153Sdim 88345153Sdim#include <stdlib.h> 89345153Sdim 90345153Sdim#include "kmp_os.h" 91345153Sdim 92345153Sdim// Include alloca() declaration. 93345153Sdim#if KMP_OS_WINDOWS 94345153Sdim#include <malloc.h> // Windows* OS: _alloca() declared in "malloc.h". 95345153Sdim#if KMP_MSVC_COMPAT 96345153Sdim#define alloca _alloca // Allow to use alloca() with no underscore. 97345153Sdim#endif 98345153Sdim#elif KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_OPENBSD 99345153Sdim// Declared in "stdlib.h". 100345153Sdim#elif KMP_OS_UNIX 101345153Sdim#include <alloca.h> // Linux* OS and OS X*: alloc() declared in "alloca". 102345153Sdim#else 103345153Sdim#error Unknown or unsupported OS. 104345153Sdim#endif 105345153Sdim 106345153Sdim/* KMP_SRC_LOC_DECL -- Declaring source location paramemters, to be used in 107345153Sdim function declaration. 108345153Sdim KMP_SRC_LOC_PARM -- Source location paramemters, to be used to pass 109345153Sdim parameters to underlying levels. 110345153Sdim KMP_SRC_LOC_CURR -- Source location arguments describing current location, 111345153Sdim to be used at top-level. 112345153Sdim 113345153Sdim Typical usage: 114345153Sdim void * _aligned_malloc( int size KMP_SRC_LOC_DECL ) { 115345153Sdim // Note: Comma is missed before KMP_SRC_LOC_DECL. 116345153Sdim KE_TRACE( 25, ( "called from %s:%d\n", KMP_SRC_LOC_PARM ) ); 117345153Sdim ... 118345153Sdim } 119345153Sdim #define aligned_malloc( size ) _aligned_malloc( (size) KMP_SRC_LOC_CURR ) 120345153Sdim // Use macro instead of direct call to function -- macro passes info 121345153Sdim // about current source location to the func. 122345153Sdim*/ 123345153Sdim#if KMP_DEBUG 124345153Sdim#define KMP_SRC_LOC_DECL , char const *_file_, int _line_ 125345153Sdim#define KMP_SRC_LOC_PARM , _file_, _line_ 126345153Sdim#define KMP_SRC_LOC_CURR , __FILE__, __LINE__ 127345153Sdim#else 128345153Sdim#define KMP_SRC_LOC_DECL 129345153Sdim#define KMP_SRC_LOC_PARM 130345153Sdim#define KMP_SRC_LOC_CURR 131345153Sdim#endif // KMP_DEBUG 132345153Sdim 133345153Sdim/* malloc_src_loc() and free_src_loc() are pseudo-functions (really macros) 134345153Sdim with accepts extra arguments (source location info) in debug mode. They 135345153Sdim should be used in place of malloc() and free(), this allows enabling native 136345153Sdim memory debugging capabilities (if any). 137345153Sdim 138345153Sdim Typical usage: 139345153Sdim ptr = malloc_src_loc( size KMP_SRC_LOC_PARM ); 140345153Sdim // Inside memory allocation wrapper, or 141345153Sdim ptr = malloc_src_loc( size KMP_SRC_LOC_CURR ); 142345153Sdim // Outside of memory allocation wrapper. 143345153Sdim*/ 144345153Sdim#define malloc_src_loc(args) _malloc_src_loc(args) 145345153Sdim#define free_src_loc(args) _free_src_loc(args) 146345153Sdim/* Depending on build mode (debug or release), malloc_src_loc is declared with 147345153Sdim 1 or 3 parameters, but calls to malloc_src_loc() are always the same: 148345153Sdim 149345153Sdim ... malloc_src_loc( size KMP_SRC_LOC_PARM ); // or KMP_SRC_LOC_CURR 150345153Sdim 151345153Sdim Compiler issues warning/error "too few arguments in macro invocation". 152345153Sdim Declaring two macros, malloc_src_loc() and _malloc_src_loc(), overcomes the 153345153Sdim problem. */ 154345153Sdim 155345153Sdim#if KMP_DEBUG 156345153Sdim 157345153Sdim#if KMP_OS_WINDOWS && _DEBUG 158345153Sdim// KMP_DEBUG != _DEBUG. MS debug RTL is available only if _DEBUG is defined. 159345153Sdim 160345153Sdim// Windows* OS has native memory debugging capabilities. Enable them. 161345153Sdim 162345153Sdim#include <crtdbg.h> 163345153Sdim 164345153Sdim#define KMP_MEM_BLOCK _CLIENT_BLOCK 165345153Sdim#define malloc(size) _malloc_dbg((size), KMP_MEM_BLOCK, __FILE__, __LINE__) 166345153Sdim#define calloc(num, size) \ 167345153Sdim _calloc_dbg((num), (size), KMP_MEM_BLOCK, __FILE__, __LINE__) 168345153Sdim#define realloc(ptr, size) \ 169345153Sdim _realloc_dbg((ptr), (size), KMP_MEM_BLOCK, __FILE__, __LINE__) 170345153Sdim#define free(ptr) _free_dbg((ptr), KMP_MEM_BLOCK) 171345153Sdim 172345153Sdim#define _malloc_src_loc(size, file, line) \ 173345153Sdim _malloc_dbg((size), KMP_MEM_BLOCK, (file), (line)) 174345153Sdim#define _free_src_loc(ptr, file, line) _free_dbg((ptr), KMP_MEM_BLOCK) 175345153Sdim 176345153Sdim#else 177345153Sdim 178345153Sdim// Linux* OS, OS X*, or non-debug Windows* OS. 179345153Sdim 180345153Sdim#define _malloc_src_loc(size, file, line) malloc((size)) 181345153Sdim#define _free_src_loc(ptr, file, line) free((ptr)) 182345153Sdim 183345153Sdim#endif 184345153Sdim 185345153Sdim#else 186345153Sdim 187345153Sdim// In release build malloc_src_loc() and free_src_loc() do not have extra 188345153Sdim// parameters. 189345153Sdim#define _malloc_src_loc(size) malloc((size)) 190345153Sdim#define _free_src_loc(ptr) free((ptr)) 191345153Sdim 192345153Sdim#endif // KMP_DEBUG 193345153Sdim 194345153Sdim#endif // KMP_WRAPPER_MALLOC_H 195345153Sdim 196345153Sdim// end of file // 197