kmp_wrapper_malloc.h 7.2 KB

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