10b57cec5SDimitry Andric /* 20b57cec5SDimitry Andric * kmp_wrapper_malloc.h -- Wrappers for memory allocation routines 30b57cec5SDimitry Andric * (malloc(), free(), and others). 40b57cec5SDimitry Andric */ 50b57cec5SDimitry Andric 60b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 70b57cec5SDimitry Andric // 80b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 90b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 100b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #ifndef KMP_WRAPPER_MALLOC_H 150b57cec5SDimitry Andric #define KMP_WRAPPER_MALLOC_H 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric /* This header serves for 3 purposes: 185ffd83dbSDimitry Andric 1. Declaring standard memory allocation routines in OS-independent way. 190b57cec5SDimitry Andric 2. Passing source location info through memory allocation wrappers. 200b57cec5SDimitry Andric 3. Enabling native memory debugging capabilities. 210b57cec5SDimitry Andric 225ffd83dbSDimitry Andric 1. Declaring standard memory allocation routines in OS-independent way. 230b57cec5SDimitry Andric ----------------------------------------------------------------------- 240b57cec5SDimitry Andric On Linux* OS, alloca() function is declared in <alloca.h> header, while on 250b57cec5SDimitry Andric Windows* OS there is no <alloca.h> header, function _alloca() (note 260b57cec5SDimitry Andric underscore!) is declared in <malloc.h>. This header eliminates these 27480093f4SDimitry Andric differences, so client code including "kmp_wrapper_malloc.h" can rely on 280b57cec5SDimitry Andric following routines: 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric malloc 310b57cec5SDimitry Andric calloc 320b57cec5SDimitry Andric realloc 330b57cec5SDimitry Andric free 340b57cec5SDimitry Andric alloca 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric in OS-independent way. It also enables memory tracking capabilities in debug 370b57cec5SDimitry Andric build. (Currently it is available only on Windows* OS.) 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric 2. Passing source location info through memory allocation wrappers. 400b57cec5SDimitry Andric ------------------------------------------------------------------- 410b57cec5SDimitry Andric Some tools may help debugging memory errors, for example, report memory 420b57cec5SDimitry Andric leaks. However, memory allocation wrappers may hinder source location. 430b57cec5SDimitry Andric For example: 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric void * aligned_malloc( int size ) { 460b57cec5SDimitry Andric void * ptr = malloc( size ); // All the memory leaks will be reported at 470b57cec5SDimitry Andric // this line. 480b57cec5SDimitry Andric // some adjustments... 490b57cec5SDimitry Andric return ptr; 500b57cec5SDimitry Andric }; 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric ptr = aligned_malloc( size ); // Memory leak will *not* be detected here. :-( 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric To overcome the problem, information about original source location should 550b57cec5SDimitry Andric be passed through all the memory allocation wrappers, for example: 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric void * aligned_malloc( int size, char const * file, int line ) { 580b57cec5SDimitry Andric void * ptr = _malloc_dbg( size, file, line ); 590b57cec5SDimitry Andric // some adjustments... 600b57cec5SDimitry Andric return ptr; 610b57cec5SDimitry Andric }; 620b57cec5SDimitry Andric void * ptr = aligned_malloc( size, __FILE__, __LINE__ ); 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric This is a good idea for debug, but passing additional arguments impacts 650b57cec5SDimitry Andric performance. Disabling extra arguments in release version of the software 660b57cec5SDimitry Andric introduces too many conditional compilation, which makes code unreadable. 670b57cec5SDimitry Andric This header defines few macros and functions facilitating it: 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric void * _aligned_malloc( int size KMP_SRC_LOC_DECL ) { 700b57cec5SDimitry Andric void * ptr = malloc_src_loc( size KMP_SRC_LOC_PARM ); 710b57cec5SDimitry Andric // some adjustments... 720b57cec5SDimitry Andric return ptr; 730b57cec5SDimitry Andric }; 740b57cec5SDimitry Andric #define aligned_malloc( size ) _aligned_malloc( (size) KMP_SRC_LOC_CURR ) 750b57cec5SDimitry Andric // Use macro instead of direct call to function. 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric void * ptr = aligned_malloc( size ); // Bingo! Memory leak will be 780b57cec5SDimitry Andric // reported at this line. 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric 3. Enabling native memory debugging capabilities. 810b57cec5SDimitry Andric ------------------------------------------------- 820b57cec5SDimitry Andric Some platforms may offer memory debugging capabilities. For example, debug 830b57cec5SDimitry Andric version of Microsoft RTL tracks all memory allocations and can report memory 840b57cec5SDimitry Andric leaks. This header enables this, and makes report more useful (see "Passing 850b57cec5SDimitry Andric source location info through memory allocation wrappers"). 860b57cec5SDimitry Andric */ 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric #include <stdlib.h> 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric #include "kmp_os.h" 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric // Include alloca() declaration. 930b57cec5SDimitry Andric #if KMP_OS_WINDOWS 940b57cec5SDimitry Andric #include <malloc.h> // Windows* OS: _alloca() declared in "malloc.h". 950b57cec5SDimitry Andric #if KMP_MSVC_COMPAT 960b57cec5SDimitry Andric #define alloca _alloca // Allow to use alloca() with no underscore. 970b57cec5SDimitry Andric #endif 980b57cec5SDimitry Andric #elif KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_OPENBSD 990b57cec5SDimitry Andric // Declared in "stdlib.h". 1000b57cec5SDimitry Andric #elif KMP_OS_UNIX 1010b57cec5SDimitry Andric #include <alloca.h> // Linux* OS and OS X*: alloc() declared in "alloca". 1020b57cec5SDimitry Andric #else 1030b57cec5SDimitry Andric #error Unknown or unsupported OS. 1040b57cec5SDimitry Andric #endif 1050b57cec5SDimitry Andric 1065ffd83dbSDimitry Andric /* KMP_SRC_LOC_DECL -- Declaring source location parameters, to be used in 1070b57cec5SDimitry Andric function declaration. 1085ffd83dbSDimitry Andric KMP_SRC_LOC_PARM -- Source location parameters, to be used to pass 1090b57cec5SDimitry Andric parameters to underlying levels. 1100b57cec5SDimitry Andric KMP_SRC_LOC_CURR -- Source location arguments describing current location, 1110b57cec5SDimitry Andric to be used at top-level. 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric Typical usage: 1140b57cec5SDimitry Andric void * _aligned_malloc( int size KMP_SRC_LOC_DECL ) { 1150b57cec5SDimitry Andric // Note: Comma is missed before KMP_SRC_LOC_DECL. 1160b57cec5SDimitry Andric KE_TRACE( 25, ( "called from %s:%d\n", KMP_SRC_LOC_PARM ) ); 1170b57cec5SDimitry Andric ... 1180b57cec5SDimitry Andric } 1190b57cec5SDimitry Andric #define aligned_malloc( size ) _aligned_malloc( (size) KMP_SRC_LOC_CURR ) 1200b57cec5SDimitry Andric // Use macro instead of direct call to function -- macro passes info 1210b57cec5SDimitry Andric // about current source location to the func. 1220b57cec5SDimitry Andric */ 1230b57cec5SDimitry Andric #if KMP_DEBUG 1240b57cec5SDimitry Andric #define KMP_SRC_LOC_DECL , char const *_file_, int _line_ 1250b57cec5SDimitry Andric #define KMP_SRC_LOC_PARM , _file_, _line_ 1260b57cec5SDimitry Andric #define KMP_SRC_LOC_CURR , __FILE__, __LINE__ 1270b57cec5SDimitry Andric #else 1280b57cec5SDimitry Andric #define KMP_SRC_LOC_DECL 1290b57cec5SDimitry Andric #define KMP_SRC_LOC_PARM 1300b57cec5SDimitry Andric #define KMP_SRC_LOC_CURR 1310b57cec5SDimitry Andric #endif // KMP_DEBUG 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andric /* malloc_src_loc() and free_src_loc() are pseudo-functions (really macros) 1340b57cec5SDimitry Andric with accepts extra arguments (source location info) in debug mode. They 1350b57cec5SDimitry Andric should be used in place of malloc() and free(), this allows enabling native 1360b57cec5SDimitry Andric memory debugging capabilities (if any). 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric Typical usage: 1390b57cec5SDimitry Andric ptr = malloc_src_loc( size KMP_SRC_LOC_PARM ); 1400b57cec5SDimitry Andric // Inside memory allocation wrapper, or 1410b57cec5SDimitry Andric ptr = malloc_src_loc( size KMP_SRC_LOC_CURR ); 1420b57cec5SDimitry Andric // Outside of memory allocation wrapper. 1430b57cec5SDimitry Andric */ 1440b57cec5SDimitry Andric #define malloc_src_loc(args) _malloc_src_loc(args) 1450b57cec5SDimitry Andric #define free_src_loc(args) _free_src_loc(args) 1460b57cec5SDimitry Andric /* Depending on build mode (debug or release), malloc_src_loc is declared with 1470b57cec5SDimitry Andric 1 or 3 parameters, but calls to malloc_src_loc() are always the same: 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric ... malloc_src_loc( size KMP_SRC_LOC_PARM ); // or KMP_SRC_LOC_CURR 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric Compiler issues warning/error "too few arguments in macro invocation". 1520b57cec5SDimitry Andric Declaring two macros, malloc_src_loc() and _malloc_src_loc(), overcomes the 1530b57cec5SDimitry Andric problem. */ 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric #if KMP_DEBUG 1560b57cec5SDimitry Andric 157bdd1243dSDimitry Andric #if KMP_OS_WINDOWS && _DEBUG && !defined(__MINGW32__) 1580b57cec5SDimitry Andric // KMP_DEBUG != _DEBUG. MS debug RTL is available only if _DEBUG is defined. 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric // Windows* OS has native memory debugging capabilities. Enable them. 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric #include <crtdbg.h> 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric #define KMP_MEM_BLOCK _CLIENT_BLOCK 1650b57cec5SDimitry Andric #define malloc(size) _malloc_dbg((size), KMP_MEM_BLOCK, __FILE__, __LINE__) 1660b57cec5SDimitry Andric #define calloc(num, size) \ 1670b57cec5SDimitry Andric _calloc_dbg((num), (size), KMP_MEM_BLOCK, __FILE__, __LINE__) 1680b57cec5SDimitry Andric #define realloc(ptr, size) \ 1690b57cec5SDimitry Andric _realloc_dbg((ptr), (size), KMP_MEM_BLOCK, __FILE__, __LINE__) 1700b57cec5SDimitry Andric #define free(ptr) _free_dbg((ptr), KMP_MEM_BLOCK) 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric #define _malloc_src_loc(size, file, line) \ 1730b57cec5SDimitry Andric _malloc_dbg((size), KMP_MEM_BLOCK, (file), (line)) 1740b57cec5SDimitry Andric #define _free_src_loc(ptr, file, line) _free_dbg((ptr), KMP_MEM_BLOCK) 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric #else 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric // Linux* OS, OS X*, or non-debug Windows* OS. 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric #define _malloc_src_loc(size, file, line) malloc((size)) 1810b57cec5SDimitry Andric #define _free_src_loc(ptr, file, line) free((ptr)) 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric #endif 1840b57cec5SDimitry Andric 1850b57cec5SDimitry Andric #else 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric // In release build malloc_src_loc() and free_src_loc() do not have extra 1880b57cec5SDimitry Andric // parameters. 1890b57cec5SDimitry Andric #define _malloc_src_loc(size) malloc((size)) 1900b57cec5SDimitry Andric #define _free_src_loc(ptr) free((ptr)) 1910b57cec5SDimitry Andric 1920b57cec5SDimitry Andric #endif // KMP_DEBUG 1930b57cec5SDimitry Andric 1940b57cec5SDimitry Andric #endif // KMP_WRAPPER_MALLOC_H 1950b57cec5SDimitry Andric 1960b57cec5SDimitry Andric // end of file // 197