nmxp_memory.c 6.16 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
 *
10
 * $Id: nmxp_memory.c,v 1.11 2009-08-16 07:16:40 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 82 83 84 85 86 87 88
    int i;
    i=0;
    while(i < i_sfs) {
	nmxp_log(NMXP_LOG_NORM, NMXP_LOG_D_ANY, "%4d: %10ld \%sn",
		i+1, sfs[i].times, sfs[i].source_file_line
		);
	i++;
    }
}
Matteo Quintiliani's avatar
Matteo Quintiliani committed
89

90
inline int nmxp_mem_add_ptr(void *ptr, size_t size, char *source_file_line, struct timeval *tv) {
91 92
    int ret = -1;
    if(i_nms < MAX_MEM_STRUCTS) {
93
	nmxp_mem_add_sfs(source_file_line, 1);
94 95 96 97 98 99 100 101 102
	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
103
	ret = -1;
104 105 106 107 108
    }
    return ret;
}


109
inline int nmxp_mem_rem_ptr(void *ptr, struct timeval *tv, int *size) {
110 111 112 113 114 115 116 117 118 119 120 121 122
    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
123
	i = -1;
124
    } else {
125
	nmxp_mem_add_sfs(nms[i].source_file_line, -1);
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
	/* 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
144

145
inline int nmxp_mem_print_ptr(int print_items, int print_sfs, char *source_file, int line) {
Matteo Quintiliani's avatar
Matteo Quintiliani committed
146 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
    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;
    }

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

Matteo Quintiliani's avatar
Matteo Quintiliani committed
177 178 179 180 181 182
    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;
}


183
inline char *nmxp_mem_source_file_line(char *source_file, int line) {
184 185 186 187 188
    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
189

190
inline void *nmxp_mem_malloc(size_t size, char *source_file, int line) {
191 192 193 194 195 196 197 198 199
    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
200 201 202
    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);
    }
203 204 205
    return ret;
}

Matteo Quintiliani's avatar
Matteo Quintiliani committed
206

207
inline char *nmxp_mem_strdup(const char *str, char *source_file, int line) {
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
    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
223 224 225
    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);
    }
226 227 228 229
    return ret;
}


230
inline void nmxp_mem_free(void *ptr, char *source_file, int line) {
231 232 233 234 235 236 237 238
    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
239 240 241
	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);
	}
242 243 244 245
	free(ptr);
    }
}

246 247 248 249 250 251
#else

inline int nmxp_mem_null_function() {
    return -1;
}

252
#endif
253