/*******************************************************************************
* This file is part of SWIFT.
* Copyright (c) 2018 Peter W. Draper (p.w.draper@durham.ac.uk)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*
******************************************************************************/
#ifndef SWIFT_MEMUSE_H
#define SWIFT_MEMUSE_H
/* Config parameters. */
#include
/* Includes. */
#include
/* API. */
void memuse_use(long *size, long *resident, long *shared, long *text,
long *data, long *library, long *dirty);
const char *memuse_process(int inmb);
#ifdef SWIFT_MEMUSE_REPORTS
void memuse_log_dump(const char *filename);
void memuse_log_dump_error(int rank);
void memuse_log_allocation(const char *label, void *ptr, int allocated,
size_t size);
#else
/* No-op when not reporting. */
#define memuse_log_allocation(label, ptr, allocated, size)
#endif
#ifdef HAVE_LSAN_IGNORE_OBJECT
#include
/**
* @brief if allocated memory is intended to leak, mark it to be
* ignored in any leak reports.
* Currently only works for the GCC/clang address sanitizer.
*
* @param memptr pointer to the memory that will leak.
*/
__attribute__((always_inline)) inline void swift_ignore_leak(
const void *memptr) {
__lsan_ignore_object(memptr);
}
#else
/* No-op when not checking for leaks. */
#define swift_ignore_leak(memptr)
#endif
/**
* @brief allocate aligned memory. The use and results are the same as the
* posix_memalign function. This function should be used for any
* significant allocations and consistently labelled.
*
* @param label a symbolic label for the memory, i.e. "parts".
* @param memptr pointer to the allocated memory.
* @param alignment alignment boundary.
* @param size the quantity of bytes to allocate.
* @result zero on success, otherwise an error code.
*/
__attribute__((always_inline)) inline int swift_memalign(const char *label,
void **memptr,
size_t alignment,
size_t size) {
int result = posix_memalign(memptr, alignment, size);
#ifdef SWIFT_MEMUSE_REPORTS
if (result == 0) {
memuse_log_allocation(label, *memptr, 1, size);
} else {
/* Failed allocations are interesting as well. */
memuse_log_allocation(label, NULL, -1, size);
}
#endif
return result;
}
/**
* @brief allocate memory. The use and results are the same as the
* malloc function. This function should be used for any
* _significant_ allocations and consistently labelled.
* Do not use this function for small or high frequency
* allocations in production code.
*
* @param label a symbolic label for the memory, i.e. "parts".
* @param size the quantity of bytes to allocate.
* @result pointer to the allocated memory or NULL on failure.
*/
__attribute__((always_inline)) inline void *swift_malloc(const char *label,
size_t size) {
void *memptr = malloc(size);
#ifdef SWIFT_MEMUSE_REPORTS
if (memptr != NULL) {
memuse_log_allocation(label, memptr, 1, size);
} else {
/* Failed allocations are interesting as well. */
memuse_log_allocation(label, NULL, -1, size);
}
#endif
return memptr;
}
/**
* @brief allocate zeroed memory. The use and results are the same as the
* calloc function. This function should be used for any
* _significant_ allocations and consistently labelled.
* Do not use this function for small or high frequency
* allocations in production code.
*
* @param label a symbolic label for the memory, i.e. "parts".
* @param nmemb number of element to allocate.
* @param size the size of each element in bytes.
* @result pointer to the allocated memory or NULL on failure.
*/
__attribute__((always_inline)) inline void *swift_calloc(const char *label,
size_t nmemb,
size_t size) {
void *memptr = calloc(nmemb, size);
#ifdef SWIFT_MEMUSE_REPORTS
if (memptr != NULL) {
memuse_log_allocation(label, memptr, 1, size * nmemb);
} else {
/* Failed allocations are interesting as well. */
memuse_log_allocation(label, NULL, -1, size * nmemb);
}
#endif
return memptr;
}
/**
* @brief reallocate memory. The use and results are the same as the
* realloc function. This function should be used for any
* _significant_ allocations and consistently labelled.
* Do not use this function for small or high frequency
* allocations in production code.
*
* @param label a symbolic label for the memory, i.e. "parts".
* @param ptr pointer to memory that may need reallocating or allocating.
* @param size the quantity of bytes that should be available.
* @result pointer to the allocated memory or NULL on failure.
*/
__attribute__((always_inline)) inline void *swift_realloc(const char *label,
void *ptr,
size_t size) {
void *memptr = realloc(ptr, size);
#ifdef SWIFT_MEMUSE_REPORTS
if (memptr != NULL) {
/* On reallocation we free the previous memory. */
if (ptr != NULL && ptr != memptr) memuse_log_allocation(label, ptr, 0, 0);
memuse_log_allocation(label, memptr, 1, size);
} else {
/* Can be NULL if size is zero, we have just freed the memory. */
if (size == 0) {
memuse_log_allocation(label, ptr, 0, 0);
} else {
/* Failed allocations are interesting as well. */
memuse_log_allocation(label, NULL, -1, size);
}
}
#endif
return memptr;
}
/**
* @brief free aligned memory. The use and results are the same as the
* free function. The label should match a prior call to swift_memalign
* or swift_malloc.
*
* @param label a symbolic label for the memory, i.e. "parts".
* @param ptr pointer to the allocated memory.
*/
__attribute__((always_inline)) inline void swift_free(const char *label,
void *ptr) {
#ifdef SWIFT_MEMUSE_REPORTS
memuse_log_allocation(label, ptr, 0, 0);
#endif
free(ptr);
return;
}
#endif /* SWIFT_MEMUSE_H */