1 /*-------------------------------------------------------------------- 2 * 3 * Copyright (c) 1991-2021 by the GMT Team (https://www.generic-mapping-tools.org/team.html) 4 * See LICENSE.TXT file for copying and redistribution conditions. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU Lesser General Public License as published by 8 * the Free Software Foundation; version 3 or any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Lesser General Public License for more details. 14 * 15 * Contact info: www.generic-mapping-tools.org 16 *--------------------------------------------------------------------*/ 17 18 /*! 19 * \file gmt_M_memory.h 20 * \brief 21 */ 22 23 #ifndef GMT_MEMORY_H 24 #define GMT_MEMORY_H 25 26 enum GMT_enum_mem_alloc { /* Initial memory for 2 double columns is 32 Mb */ 27 GMT_INITIAL_MEM_COL_ALLOC = 2U, 28 GMT_INITIAL_MEM_ROW_ALLOC = 2097152U /* 2^21 */ 29 }; 30 31 /*! Macros to reallocate memory for groups of 2, 3 or 4 arrays at a time of the same size/type */ 32 #if defined (DEBUG) || defined (MEMDEBUG) 33 #define gmt_M_malloc(C,a,n,n_alloc,type) gmt_malloc_func(C,a,n,n_alloc,sizeof(type),__SOURCE_LINE_FUNC) 34 #else 35 #define gmt_M_malloc(C,a,n,n_alloc,type) gmt_malloc_func(C,a,n,n_alloc,sizeof(type),__func__) 36 #endif 37 /* The __kp = n_alloc below is needed since NULL may be passed. __k is used to ensure only the final gmt_M_malloc call changes n_alloc (unless it is NULL) */ 38 #define gmt_M_malloc2(C,a,b,n,n_alloc,type) { size_t __k, *__kp = n_alloc; __k = (__kp) ? *__kp : 0U; a = gmt_M_malloc(C,a,n,&__k,type); b = gmt_M_malloc(C,b,n,n_alloc,type); } 39 #define gmt_M_malloc3(C,a,b,c,n,n_alloc,type) { size_t __k, *__kp = n_alloc; __k = (__kp) ? *__kp : 0U; a = gmt_M_malloc(C,a,n,&__k,type); __k = (__kp) ? *__kp : 0U; b = gmt_M_malloc(C,b,n,&__k,type); c = gmt_M_malloc(C,c,n,n_alloc,type); } 40 #define gmt_M_malloc4(C,a,b,c,d,n,n_alloc,type) { size_t __k, *__kp = n_alloc; __k = (__kp) ? *__kp : 0U; a = gmt_M_malloc(C,a,n,&__k,type); __k = (__kp) ? *__kp : 0U; b = gmt_M_malloc(C,b,n,&__k,type); __k = (__kp) ? *__kp : 0U; c = gmt_M_malloc(C,c,n,&__k,type); d = gmt_M_malloc(C,d,n,n_alloc,type); } 41 42 /*! Convenience macro for gmt_memory_func */ 43 #if defined (DEBUG) || defined (MEMDEBUG) 44 #define gmt_M_memory(C,ptr,n,type) gmt_memory_func(C,ptr,n,sizeof(type),false,__SOURCE_LINE_FUNC) 45 #define gmt_M_memory_aligned(C,ptr,n,type) gmt_memory_func(C,ptr,n,sizeof(type),true,__SOURCE_LINE_FUNC) 46 #else 47 #define gmt_M_memory(C,ptr,n,type) gmt_memory_func(C,ptr,n,sizeof(type),false,__func__) 48 #define gmt_M_memory_aligned(C,ptr,n,type) gmt_memory_func(C,ptr,n,sizeof(type),true,__func__) 49 #endif 50 51 /*! Convenience macro for gmt_free_func */ 52 #if defined (DEBUG) || defined (MEMDEBUG) 53 #define gmt_M_free(C,ptr) (gmt_free_func(C,ptr,false,__SOURCE_LINE_FUNC),(ptr)=NULL) 54 #define gmt_M_free_aligned(C,ptr) (gmt_free_func(C,ptr,true,__SOURCE_LINE_FUNC),(ptr)=NULL) 55 #else 56 #define gmt_M_free(C,ptr) (gmt_free_func(C,ptr,false,__func__),(ptr)=NULL) 57 #define gmt_M_free_aligned(C,ptr) (gmt_free_func(C,ptr,true,__func__),(ptr)=NULL) 58 #endif 59 60 /*! Convenience macro for free that explicitly sets freed pointer to NULL */ 61 #define gmt_M_str_free(ptr) (free((void *)(ptr)),(ptr)=NULL) 62 63 #ifdef MEMDEBUG 64 65 struct MEMORY_ITEM { 66 size_t size; /* Size of memory allocated */ 67 void *ptr; /* Memory pointer */ 68 char *name; /* Source filename and line or function name */ 69 size_t ID; /* Unique ID for this allocation */ 70 struct MEMORY_ITEM *l, *r; 71 }; 72 73 struct MEMORY_TRACKER { 74 #ifdef MEMDEBUG 75 bool active; /* Normally true but can be changed to focus on just some allocations */ 76 bool search; /* Normally true but can be changed to skip searching when we know we add a new item */ 77 bool do_log; /* true if we wish to write detailed alloc/free log */ 78 uint64_t n_ptr; /* Number of unique pointers to allocated memory */ 79 uint64_t n_allocated; /* Number of items allocated by gmt_M_memory */ 80 uint64_t n_reallocated; /* Number of items reallocated by gmt_M_memory */ 81 uint64_t n_freed; /* Number of items freed by gmt_M_free */ 82 uint64_t n_ID; /* Running number assigned to new allocations */ 83 uint64_t find; /* If > 0 then we look for this ID to be allocated */ 84 size_t current; /* Memory allocated at current time */ 85 size_t maximum; /* Highest memory count during execution */ 86 size_t largest; /* Highest memory allocation to a single variable */ 87 size_t n_alloc; /* Allocated size of memory pointer array */ 88 struct MEMORY_ITEM *root; /* Pointer to splay tree */ 89 FILE *fp; /* For logging if GMT_TRACK_MEMORY is 2 */ 90 #endif 91 }; 92 93 /* Items needed if -DMEMDEBUG is in effect */ 94 EXTERN_MSC int gmt_memtrack_init (struct GMT_CTRL *GMT); 95 EXTERN_MSC void gmt_memtrack_report (struct GMT_CTRL *GMT); 96 97 #endif 98 99 #endif /* GMT_MEMORY_H */ 100