mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
196 lines
7.2 KiB
C
196 lines
7.2 KiB
C
/*
|
|
* 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 routines in OS-independent way.
|
|
2. Passing source location info through memory allocation wrappers.
|
|
3. Enabling native memory debugging capabilities.
|
|
|
|
1. Declaring standard memory allocation routines 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 including "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 parameters, to be used in
|
|
function declaration.
|
|
KMP_SRC_LOC_PARM -- Source location parameters, 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 && !defined(__MINGW32__)
|
|
// 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 //
|