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