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