reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
  192
  193
  194
  195
  196
/*
 * kmp_wrapper_malloc.h -- Wrappers for memory allocation routines
 *                         (malloc(), free(), and others).
 */

//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef KMP_WRAPPER_MALLOC_H
#define KMP_WRAPPER_MALLOC_H

/* This header serves for 3 purposes:
   1. Declaring standard memory allocation rourines in OS-independent way.
   2. Passing source location info through memory allocation wrappers.
   3. Enabling native memory debugging capabilities.

   1. Declaring standard memory allocation rourines in OS-independent way.
   -----------------------------------------------------------------------
   On Linux* OS, alloca() function is declared in <alloca.h> header, while on
   Windows* OS there is no <alloca.h> header, function _alloca() (note
   underscore!) is declared in <malloc.h>. This header eliminates these
   differences, so client code incluiding "kmp_wrapper_malloc.h" can rely on
   following routines:

        malloc
        calloc
        realloc
        free
        alloca

   in OS-independent way. It also enables memory tracking capabilities in debug
   build. (Currently it is available only on Windows* OS.)

   2. Passing source location info through memory allocation wrappers.
   -------------------------------------------------------------------
   Some tools may help debugging memory errors, for example, report memory
   leaks. However, memory allocation wrappers may hinder source location.
   For example:

   void * aligned_malloc( int size ) {
     void * ptr = malloc( size ); // All the memory leaks will be reported at
                                  // this line.
     // some adjustments...
     return ptr;
   };

   ptr = aligned_malloc( size ); // Memory leak will *not* be detected here. :-(

   To overcome the problem, information about original source location should
   be passed through all the memory allocation wrappers, for example:

   void * aligned_malloc( int size, char const * file, int line ) {
     void * ptr = _malloc_dbg( size, file, line );
     // some adjustments...
     return ptr;
   };
   void * ptr = aligned_malloc( size, __FILE__, __LINE__ );

   This is a good idea for debug, but passing additional arguments impacts
   performance. Disabling extra arguments in release version of the software
   introduces too many conditional compilation, which makes code unreadable.
   This header defines few macros and functions facilitating it:

   void * _aligned_malloc( int size KMP_SRC_LOC_DECL ) {
     void * ptr = malloc_src_loc( size KMP_SRC_LOC_PARM );
     // some adjustments...
     return ptr;
   };
   #define aligned_malloc( size ) _aligned_malloc( (size) KMP_SRC_LOC_CURR )
   // Use macro instead of direct call to function.

   void * ptr = aligned_malloc( size );  // Bingo! Memory leak will be
                                         // reported at this line.

   3. Enabling native memory debugging capabilities.
   -------------------------------------------------
   Some platforms may offer memory debugging capabilities. For example, debug
   version of Microsoft RTL tracks all memory allocations and can report memory
   leaks. This header enables this, and makes report more useful (see "Passing
   source location info through memory allocation wrappers").
*/

#include <stdlib.h>

#include "kmp_os.h"

// Include alloca() declaration.
#if KMP_OS_WINDOWS
#include <malloc.h> // Windows* OS: _alloca() declared in "malloc.h".
#if KMP_MSVC_COMPAT
#define alloca _alloca // Allow to use alloca() with no underscore.
#endif
#elif KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_OPENBSD
// Declared in "stdlib.h".
#elif KMP_OS_UNIX
#include <alloca.h> // Linux* OS and OS X*: alloc() declared in "alloca".
#else
#error Unknown or unsupported OS.
#endif

/* KMP_SRC_LOC_DECL -- Declaring source location paramemters, to be used in
   function declaration.
   KMP_SRC_LOC_PARM -- Source location paramemters, to be used to pass
   parameters to underlying levels.
   KMP_SRC_LOC_CURR -- Source location arguments describing current location,
   to be used at top-level.

   Typical usage:
   void * _aligned_malloc( int size KMP_SRC_LOC_DECL ) {
     // Note: Comma is missed before KMP_SRC_LOC_DECL.
     KE_TRACE( 25, ( "called from %s:%d\n", KMP_SRC_LOC_PARM ) );
     ...
   }
   #define aligned_malloc( size ) _aligned_malloc( (size) KMP_SRC_LOC_CURR )
   // Use macro instead of direct call to function -- macro passes info
   // about current source location to the func.
*/
#if KMP_DEBUG
#define KMP_SRC_LOC_DECL , char const *_file_, int _line_
#define KMP_SRC_LOC_PARM , _file_, _line_
#define KMP_SRC_LOC_CURR , __FILE__, __LINE__
#else
#define KMP_SRC_LOC_DECL
#define KMP_SRC_LOC_PARM
#define KMP_SRC_LOC_CURR
#endif // KMP_DEBUG

/* malloc_src_loc() and free_src_loc() are pseudo-functions (really macros)
   with accepts extra arguments (source location info) in debug mode. They
   should be used in place of malloc() and free(), this allows enabling native
   memory debugging capabilities (if any).

   Typical usage:
   ptr = malloc_src_loc( size KMP_SRC_LOC_PARM );
   // Inside memory allocation wrapper, or
   ptr = malloc_src_loc( size KMP_SRC_LOC_CURR );
   // Outside of memory allocation wrapper.
*/
#define malloc_src_loc(args) _malloc_src_loc(args)
#define free_src_loc(args) _free_src_loc(args)
/* Depending on build mode (debug or release), malloc_src_loc is declared with
   1 or 3 parameters, but calls to malloc_src_loc() are always the same:

   ... malloc_src_loc( size KMP_SRC_LOC_PARM ); // or KMP_SRC_LOC_CURR

   Compiler issues warning/error "too few arguments in macro invocation".
   Declaring two macros, malloc_src_loc() and _malloc_src_loc(), overcomes the
   problem. */

#if KMP_DEBUG

#if KMP_OS_WINDOWS && _DEBUG
// KMP_DEBUG != _DEBUG. MS debug RTL is available only if _DEBUG is defined.

// Windows* OS has native memory debugging capabilities. Enable them.

#include <crtdbg.h>

#define KMP_MEM_BLOCK _CLIENT_BLOCK
#define malloc(size) _malloc_dbg((size), KMP_MEM_BLOCK, __FILE__, __LINE__)
#define calloc(num, size)                                                      \
  _calloc_dbg((num), (size), KMP_MEM_BLOCK, __FILE__, __LINE__)
#define realloc(ptr, size)                                                     \
  _realloc_dbg((ptr), (size), KMP_MEM_BLOCK, __FILE__, __LINE__)
#define free(ptr) _free_dbg((ptr), KMP_MEM_BLOCK)

#define _malloc_src_loc(size, file, line)                                      \
  _malloc_dbg((size), KMP_MEM_BLOCK, (file), (line))
#define _free_src_loc(ptr, file, line) _free_dbg((ptr), KMP_MEM_BLOCK)

#else

// Linux* OS, OS X*, or non-debug Windows* OS.

#define _malloc_src_loc(size, file, line) malloc((size))
#define _free_src_loc(ptr, file, line) free((ptr))

#endif

#else

// In release build malloc_src_loc() and free_src_loc() do not have extra
// parameters.
#define _malloc_src_loc(size) malloc((size))
#define _free_src_loc(ptr) free((ptr))

#endif // KMP_DEBUG

#endif // KMP_WRAPPER_MALLOC_H

// end of file //