nmxp_memory.c 6.21 KB
Newer Older
1 2 3 4 5 6 7 8 9
/*! \file
 *
 * \brief Memory management for Nanometrics Protocol Library
 *
 * Author:
 * 	Matteo Quintiliani
 * 	Istituto Nazionale di Geofisica e Vulcanologia - Italy
 *	quintiliani@ingv.it
 *
Matteo Quintiliani's avatar
Matteo Quintiliani committed
10
 * $Id: nmxp_memory.c,v 1.12 2009-08-16 07:31:18 mtheo Exp $
11 12 13
 *
 */

14 15
#ifdef NMXP_MEM_DEBUG

16 17 18 19 20 21 22 23 24 25
#include "nmxp_memory.h"
#include "nmxp_log.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>

#include "config.h"

Matteo Quintiliani's avatar
Matteo Quintiliani committed
26 27 28
/* Set debug_log_single to 1 for logging malloc(), strdup() and free() calls */
static int debug_log_single = 0;

29 30 31 32 33 34 35 36 37
#define MAX_LEN_SOURCE_FILE_LINE 100

typedef struct {
    void *p;
    int size;
    char source_file_line[MAX_LEN_SOURCE_FILE_LINE];
    struct timeval tv;
} NMXP_MEM_STRUCT;

38 39 40 41 42
typedef struct {
    char source_file_line[MAX_LEN_SOURCE_FILE_LINE];
    long int times;
} NMXP_MEM_SOURCE_FILE_LINE_STAT;

43
#define MAX_MEM_STRUCTS (4096 * 16)
44 45 46 47

static NMXP_MEM_STRUCT nms[MAX_MEM_STRUCTS];
static int i_nms = 0;

48 49 50 51 52
#define MAX_MEM_SFS (1024)
static NMXP_MEM_SOURCE_FILE_LINE_STAT sfs[MAX_MEM_SFS];
static int i_sfs = 0;


53 54
inline long int nmxp_mem_add_sfs(char *source_file_line, int t) {
    long int cur_times;
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
    int i;
    i=0;
    while(i < i_sfs
	    && i < MAX_MEM_SFS
	    &&  strcmp(sfs[i].source_file_line, source_file_line)!=0) {
	i++;
    }
    if(i >= i_sfs) {
	if(i_sfs < MAX_MEM_SFS) {
	    strncpy(sfs[i_sfs].source_file_line, source_file_line, MAX_LEN_SOURCE_FILE_LINE);
	    sfs[i_sfs].times=t;
	    i_sfs++;
	    cur_times = t;
	} else {
	    nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_ANY, "nmxp_mem_add_sfs i_sfs > MAX_MEM_SFS %d > %d\n", i_sfs, MAX_MEM_SFS);
	    cur_times = -1000000;
	}
    } else {
73 74
	sfs[i].times+=t;
	cur_times = sfs[i].times;
75 76 77 78
    }
    return cur_times;
}

79
inline void nmxp_mem_print_sfs() {
80 81
    int i;
    i=0;
Matteo Quintiliani's avatar
Matteo Quintiliani committed
82
    nmxp_log(NMXP_LOG_NORM, NMXP_LOG_D_ANY, "\n");
83
    while(i < i_sfs) {
Matteo Quintiliani's avatar
Matteo Quintiliani committed
84
	nmxp_log(NMXP_LOG_NORM, NMXP_LOG_D_ANY, "%4d: %10ld %s\n",
85 86 87 88 89
		i+1, sfs[i].times, sfs[i].source_file_line
		);
	i++;
    }
}
Matteo Quintiliani's avatar
Matteo Quintiliani committed
90

91
inline int nmxp_mem_add_ptr(void *ptr, size_t size, char *source_file_line, struct timeval *tv) {
92 93
    int ret = -1;
    if(i_nms < MAX_MEM_STRUCTS) {
94
	nmxp_mem_add_sfs(source_file_line, 1);
95 96 97 98 99 100 101 102 103
	nms[i_nms].p = ptr;
	nms[i_nms].size = size;
	strncpy(nms[i_nms].source_file_line, source_file_line, MAX_LEN_SOURCE_FILE_LINE);
	nms[i_nms].tv.tv_sec = tv->tv_sec;
	nms[i_nms].tv.tv_usec = tv->tv_usec;
	ret = i_nms;
	i_nms++;
    } else {
	nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_ANY, "nmxp_mem_add_ptr i_nms > MAX_MEM_STRUCTS %d > %d\n", i_nms, MAX_MEM_STRUCTS);
Matteo Quintiliani's avatar
Matteo Quintiliani committed
104
	ret = -1;
105 106 107 108 109
    }
    return ret;
}


110
inline int nmxp_mem_rem_ptr(void *ptr, struct timeval *tv, int *size) {
111 112 113 114 115 116 117 118 119 120 121 122 123
    int i, j;

    tv->tv_sec = 0;
    tv->tv_usec = 0;
    *size = 0;

    i = 0;
    while(i < i_nms && nms[i].p != ptr) {
	i++;
    }

    if(i >= i_nms  ||  i > MAX_MEM_STRUCTS) {
	nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_ANY, "nmxp_mem_rem_ptr %010p not found i=%d\n", ptr, i);
Matteo Quintiliani's avatar
Matteo Quintiliani committed
124
	i = -1;
125
    } else {
126
	nmxp_mem_add_sfs(nms[i].source_file_line, -1);
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
	/* shift */
	tv->tv_sec = nms[i].tv.tv_sec;
	tv->tv_usec = nms[i].tv.tv_usec;
	*size = nms[i].size;
	j = i;
	while(j < i_nms-1) {
	    nms[j].p = nms[j+1].p;
	    nms[j].size = nms[j+1].size;
	    strncpy(nms[j].source_file_line, nms[j+1].source_file_line, MAX_LEN_SOURCE_FILE_LINE);;
	    nms[j].tv.tv_sec = nms[j+1].tv.tv_sec;
	    nms[j].tv.tv_usec = nms[j+1].tv.tv_usec;
	    j++;
	}
	i_nms--;
    }
    return i;
}

Matteo Quintiliani's avatar
Matteo Quintiliani committed
145

146
inline int nmxp_mem_print_ptr(int print_items, int print_sfs, char *source_file, int line) {
Matteo Quintiliani's avatar
Matteo Quintiliani committed
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
    int i;
    static int old_tot_size = 0;
    int tot_size;

    tot_size = 0;
    for(i=0; i < i_nms  &&  i_nms < MAX_MEM_STRUCTS; i++) {
	tot_size += nms[i].size;
    }

    if(tot_size != old_tot_size) {
	if(print_items) {
	    i=0;
	    while(i<i_nms  && i_nms < MAX_MEM_STRUCTS) {
		nmxp_log(NMXP_LOG_NORM, NMXP_LOG_D_ANY, "%d %d.%d %010p %d %s\n",
			i,
			nms[i].tv.tv_sec,
			nms[i].tv.tv_usec,
			nms[i].p,
			nms[i].size,
			nms[i].source_file_line
			);
		i++;
	    }
	}
	old_tot_size = tot_size;
    }

174 175 176 177
    if(print_sfs) {
	nmxp_mem_print_sfs();
    }

Matteo Quintiliani's avatar
Matteo Quintiliani committed
178 179 180 181 182 183
    nmxp_log(NMXP_LOG_NORM, NMXP_LOG_D_ANY, "nmxp_mem_print_ptr() tot %d  %s:%d\n", tot_size, source_file, line);

    return tot_size;
}


184
inline char *nmxp_mem_source_file_line(char *source_file, int line) {
185 186 187 188 189
    static char source_file_line[MAX_LEN_SOURCE_FILE_LINE];
    snprintf(source_file_line, MAX_LEN_SOURCE_FILE_LINE, "%s:%d", source_file, line);
    return source_file_line;
}

Matteo Quintiliani's avatar
Matteo Quintiliani committed
190

191
inline void *nmxp_mem_malloc(size_t size, char *source_file, int line) {
192 193 194 195 196 197 198 199 200
    void *ret = NULL;
    struct timeval tv;
    int i;
    char source_file_line[MAX_LEN_SOURCE_FILE_LINE];
    
    gettimeofday(&tv, NULL);
    ret = malloc(size);
    strncpy(source_file_line, nmxp_mem_source_file_line(source_file, line), MAX_LEN_SOURCE_FILE_LINE);
    i = nmxp_mem_add_ptr(ret, size, source_file_line, &tv);
Matteo Quintiliani's avatar
Matteo Quintiliani committed
201 202 203
    if(debug_log_single  ||  i == -1) {
	nmxp_log(NMXP_LOG_NORM, NMXP_LOG_D_ANY, "nmxp_mem_malloc %d.%d %010p+%d %s_%d\n", tv.tv_sec, tv.tv_usec, ret, size, source_file_line, i);
    }
204 205 206
    return ret;
}

Matteo Quintiliani's avatar
Matteo Quintiliani committed
207

208
inline char *nmxp_mem_strdup(const char *str, char *source_file, int line) {
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
    char *ret = NULL;
    int size;
    struct timeval tv;
    int i;
    char source_file_line[MAX_LEN_SOURCE_FILE_LINE];

    gettimeofday(&tv, NULL);
    ret = strdup(str);
    if(str) {
	size = strlen(str);
    } else {
	size = 0;
    }
    strncpy(source_file_line, nmxp_mem_source_file_line(source_file, line), MAX_LEN_SOURCE_FILE_LINE);
    i = nmxp_mem_add_ptr(ret, size, source_file_line, &tv);
Matteo Quintiliani's avatar
Matteo Quintiliani committed
224 225 226
    if(debug_log_single  ||  i == -1) {
	nmxp_log(NMXP_LOG_NORM, NMXP_LOG_D_ANY, "nmxp_mem_strdup %d.%d %010p+%d %s_%d\n", tv.tv_sec, tv.tv_usec, ret, size, source_file_line, i);
    }
227 228 229 230
    return ret;
}


231
inline void nmxp_mem_free(void *ptr, char *source_file, int line) {
232 233 234 235 236 237 238 239
    int i;
    struct timeval tv;
    int size;
    char source_file_line[MAX_LEN_SOURCE_FILE_LINE];

    if(ptr) {
	i = nmxp_mem_rem_ptr(ptr, &tv, &size);
	strncpy(source_file_line, nmxp_mem_source_file_line(source_file, line), MAX_LEN_SOURCE_FILE_LINE);
Matteo Quintiliani's avatar
Matteo Quintiliani committed
240 241 242
	if(debug_log_single  ||  i == -1) {
	    nmxp_log(NMXP_LOG_NORM, NMXP_LOG_D_ANY, "nmxp_mem_free   %d.%d %010p+%d %s_%d\n", tv.tv_sec, tv.tv_usec, ptr, size, source_file_line, i);
	}
243 244 245 246
	free(ptr);
    }
}

247 248 249 250 251 252
#else

inline int nmxp_mem_null_function() {
    return -1;
}

253
#endif
254