]>
Commit | Line | Data |
---|---|---|
4e0938ef AJ |
1 | /* |
2 | * Copyright (C) 1996-2014 The Squid Software Foundation and contributors | |
3 | * | |
4 | * Squid software is distributed under GPLv2+ license and includes | |
5 | * contributions from numerous individuals and organizations. | |
6 | * Please see the COPYING and CONTRIBUTORS files for details. | |
7 | */ | |
8 | ||
f7f3304a | 9 | #include "squid.h" |
ef364f64 AJ |
10 | #include "hash.h" |
11 | ||
12 | #if HAVE_UNISTD_H | |
14c63c25 | 13 | #include <unistd.h> |
ef364f64 | 14 | #endif |
ef364f64 | 15 | #if HAVE_CTYPE_H |
14c63c25 | 16 | #include <ctype.h> |
ef364f64 AJ |
17 | #endif |
18 | #if HAVE_STRINGS_H | |
14c63c25 | 19 | #include <strings.h> |
ef364f64 | 20 | #endif |
14c63c25 | 21 | |
22 | static hash_table *mem_table = NULL; | |
23 | static hash_link *mem_entry; | |
24 | struct rusage myusage; | |
25 | ||
e7740002 | 26 | #ifdef WITH_LIB |
27 | #include "Mem.h" | |
28 | #include <assert.h> | |
29 | extern void sizeToPoolInit(); | |
30 | extern MemPool *sizeToPool(size_t size); | |
31 | #endif | |
32 | extern char *malloc_options; | |
33 | void my_free(char *, int, void *); | |
34 | ||
14c63c25 | 35 | FILE *fp; |
36 | char *fn; | |
37 | int initsiz; | |
38 | int maxsiz; | |
39 | int minchunk; | |
40 | HASHCMP ptrcmp; | |
41 | char mbuf[256]; | |
42 | char abuf[32]; | |
da537f52 | 43 | char *p; |
14c63c25 | 44 | |
45 | int size; | |
46 | void *addr; | |
47 | int amt; | |
48 | ||
49 | int i; | |
da537f52 | 50 | int a; |
468ae12b | 51 | int run_stats = 0; |
14c63c25 | 52 | void *my_xmalloc(size_t); |
53 | void *my_xcalloc(int, size_t); | |
54 | int my_xfree(void *); | |
55 | ||
56 | #define xmalloc my_xmalloc | |
57 | #define xcalloc my_xcalloc | |
58 | #define xfree my_xfree | |
da537f52 | 59 | |
14c63c25 | 60 | int *size2id_array[2]; |
468ae12b | 61 | int size2id_len = 0; |
62 | int size2id_alloc = 0; | |
14c63c25 | 63 | |
14c63c25 | 64 | typedef struct { |
468ae12b | 65 | char orig_ptr[32]; |
66 | void *my_ptr; | |
da537f52 | 67 | #ifdef WITH_LIB |
468ae12b | 68 | MemPool *pool; |
da537f52 | 69 | #endif |
468ae12b | 70 | int size; |
14c63c25 | 71 | } memitem; |
72 | ||
73 | struct { | |
468ae12b | 74 | int mallocs, frees, callocs, reallocs; |
14c63c25 | 75 | } mstat; |
76 | ||
77 | memitem *mi; | |
da537f52 | 78 | void size2id(size_t, memitem *); |
79 | void badformat(); | |
80 | void init_stats(), print_stats(); | |
468ae12b | 81 | void my_hash_insert(hash_table * h, const char *k, memitem * item); |
82 | static void *xmemAlloc(memitem * item); | |
83 | static void xmemFree(memitem * item); | |
14c63c25 | 84 | |
468ae12b | 85 | int |
86 | ptrcmp(const void *a, const void *b) | |
14c63c25 | 87 | { |
468ae12b | 88 | return (strcmp(a, b)); |
14c63c25 | 89 | } |
90 | ||
468ae12b | 91 | main(int argc, char **argv) |
14c63c25 | 92 | { |
93 | char c; | |
468ae12b | 94 | extern char *optarg; |
e7740002 | 95 | malloc_options = "A"; |
468ae12b | 96 | a = 0; |
e7740002 | 97 | while ((c = getopt(argc, argv, "f:i:M:l:m:r:N")) != -1) { |
26ac0430 AJ |
98 | switch (c) { |
99 | case 'N': | |
100 | mem_pools_on = 0; | |
101 | break; | |
102 | case 'r': | |
103 | run_stats = atoi(optarg); | |
104 | break; | |
105 | case 'f': | |
86c63190 | 106 | fn = xstrdup(optarg); |
26ac0430 AJ |
107 | fp = fopen(fn, "r"); |
108 | break; | |
109 | case 'i': | |
110 | initsiz = atoi(optarg); | |
111 | break; | |
112 | case 'l': | |
113 | mem_max_size = atoi(optarg) * 1024 * 1024; | |
114 | break; | |
115 | case 'M': | |
116 | maxsiz = atoi(optarg); | |
117 | break; | |
118 | case 'm': | |
119 | minchunk = atoi(optarg); | |
120 | break; | |
121 | default: | |
122 | fprintf(stderr, | |
123 | "Usage: %s -f file -M maxsiz -i initsiz -m minchunk", argv[0]); | |
124 | exit(1); | |
125 | } | |
468ae12b | 126 | |
14c63c25 | 127 | } |
128 | if (!fp) { | |
26ac0430 AJ |
129 | fprintf(stderr, |
130 | "%s pummels %s\n%s . o O ( You't supply a valid tracefile.)\n", | |
131 | argv[0], getenv("USER"), argv[0]); | |
132 | exit(1); | |
14c63c25 | 133 | } |
e7740002 | 134 | #ifdef WITH_LIB |
135 | sizeToPoolInit(); | |
136 | #endif | |
f53969cc | 137 | mem_table = hash_create(ptrcmp, 229, hash4); /* small hash table */ |
14c63c25 | 138 | init_stats(); |
468ae12b | 139 | while (fgets(mbuf, 256, fp) != NULL) { |
26ac0430 AJ |
140 | if (run_stats > 0 && (++a) % run_stats == 0) |
141 | print_stats(); | |
142 | p = NULL; | |
143 | switch (mbuf[0]) { | |
f53969cc | 144 | case 'm': /* malloc */ |
26ac0430 AJ |
145 | p = strtok(&mbuf[2], ":"); |
146 | if (!p) | |
147 | badformat(); | |
148 | size = atoi(p); | |
149 | p = strtok(NULL, "\n"); | |
150 | if (!p) | |
151 | badformat(); | |
152 | mi = malloc(sizeof(memitem)); | |
153 | strcpy(mi->orig_ptr, p); | |
154 | mi->size = size; | |
155 | size2id(size, mi); | |
f53969cc | 156 | mi->my_ptr = xmemAlloc(mi); /* (void *)xmalloc(size); */ |
26ac0430 AJ |
157 | assert(mi->my_ptr); |
158 | my_hash_insert(mem_table, mi->orig_ptr, mi); | |
159 | mstat.mallocs++; | |
160 | break; | |
f53969cc | 161 | case 'c': /* calloc */ |
26ac0430 AJ |
162 | p = strtok(&mbuf[2], ":"); |
163 | if (!p) | |
164 | badformat(); | |
165 | amt = atoi(p); | |
166 | p = strtok(NULL, ":"); | |
167 | if (!p) | |
168 | badformat(); | |
169 | size = atoi(p); | |
170 | p = strtok(NULL, "\n"); | |
171 | if (!p) | |
172 | badformat(); | |
173 | mi = malloc(sizeof(memitem)); | |
174 | strcpy(mi->orig_ptr, p); | |
175 | size2id(size, mi); | |
176 | mi->size = amt * size; | |
f53969cc | 177 | mi->my_ptr = xmemAlloc(mi); /*(void *)xmalloc(amt*size); */ |
26ac0430 AJ |
178 | assert(mi->my_ptr); |
179 | my_hash_insert(mem_table, mi->orig_ptr, mi); | |
180 | mstat.callocs++; | |
181 | break; | |
182 | case 'r': | |
183 | p = strtok(&mbuf[2], ":"); | |
184 | if (!p) | |
185 | badformat(); | |
186 | strcpy(abuf, p); | |
187 | p = strtok(NULL, ":"); | |
188 | if (!p) | |
189 | badformat(); | |
190 | mem_entry = hash_lookup(mem_table, p); | |
191 | if (mem_entry == NULL) { | |
192 | fprintf(stderr, "invalid realloc (%s)!\n", p); | |
193 | break; | |
194 | } | |
195 | mi = (memitem *) (mem_entry->item); | |
196 | assert(mi->pool); | |
197 | assert(mi->my_ptr); | |
f53969cc SM |
198 | xmemFree(mi); /* xfree(mi->my_ptr); */ |
199 | size2id(atoi(p), mi); /* we don't need it here I guess? */ | |
26ac0430 AJ |
200 | strcpy(mi->orig_ptr, abuf); |
201 | p = strtok(NULL, "\n"); | |
202 | if (!p) | |
203 | badformat(); | |
f53969cc | 204 | mi->my_ptr = xmemAlloc(mi); /* (char *)xmalloc(atoi(p)); */ |
26ac0430 AJ |
205 | assert(mi->my_ptr); |
206 | mstat.reallocs++; | |
207 | break; | |
208 | case 'f': | |
209 | p = strtok(&mbuf[2], "\n"); | |
210 | mem_entry = hash_lookup(mem_table, p); | |
211 | if (mem_entry == NULL) { | |
212 | if (p[0] != '0') | |
213 | fprintf(stderr, "invalid free (%s) at line %d!\n", p, a); | |
214 | break; | |
215 | } | |
216 | mi = (memitem *) (mem_entry->item); | |
217 | assert(mi->pool); | |
218 | assert(mi->my_ptr); | |
f53969cc | 219 | xmemFree(mi); /* xfree(mi->my_ptr); */ |
26ac0430 AJ |
220 | hash_unlink(mem_table, mem_entry, 1); |
221 | free(mi); | |
222 | mstat.frees++; | |
223 | break; | |
224 | default: | |
225 | fprintf(stderr, "%s pummels %s.bad.format\n", argv[0], fn); | |
226 | exit(1); | |
227 | } | |
14c63c25 | 228 | |
229 | } | |
230 | fclose(fp); | |
231 | print_stats(); | |
232 | } | |
233 | ||
234 | void * | |
235 | my_xmalloc(size_t a) | |
236 | { | |
468ae12b | 237 | return NULL; |
14c63c25 | 238 | } |
239 | ||
240 | void * | |
241 | my_xcalloc(int a, size_t b) | |
242 | { | |
468ae12b | 243 | return NULL; |
14c63c25 | 244 | } |
245 | ||
246 | int | |
247 | my_xfree(void *p) | |
248 | { | |
468ae12b | 249 | return 0; |
14c63c25 | 250 | } |
251 | void | |
252 | init_stats() | |
253 | { | |
254 | ||
255 | } | |
256 | ||
257 | void | |
258 | print_stats() | |
259 | { | |
e7740002 | 260 | #ifdef WITH_LIB |
468ae12b | 261 | memReport(stdout); |
e7740002 | 262 | #endif |
468ae12b | 263 | getrusage(RUSAGE_SELF, &myusage); |
264 | printf("m/c/f/r=%d/%d/%d/%d\n", mstat.mallocs, mstat.callocs, | |
26ac0430 | 265 | mstat.frees, mstat.reallocs); |
e7740002 | 266 | #if 0 |
468ae12b | 267 | printf("types : %d\n", size2id_len); |
e7740002 | 268 | #endif |
468ae12b | 269 | printf("user time used : %d.%d\n", (int) myusage.ru_utime.tv_sec, |
26ac0430 | 270 | (int) myusage.ru_utime.tv_usec); |
468ae12b | 271 | printf("system time used : %d.%d\n", (int) myusage.ru_stime.tv_sec, |
26ac0430 | 272 | (int) myusage.ru_stime.tv_usec); |
468ae12b | 273 | printf("max resident set size : %d\n", (int) myusage.ru_maxrss); |
274 | printf("page faults : %d\n", (int) myusage.ru_majflt); | |
14c63c25 | 275 | } |
276 | ||
da537f52 | 277 | void |
468ae12b | 278 | size2id(size_t sz, memitem * mi) |
14c63c25 | 279 | { |
da537f52 | 280 | #ifdef WITH_LIB |
468ae12b | 281 | mi->pool = sizeToPool(sz); |
282 | assert(mi->pool); | |
da537f52 | 283 | #endif |
468ae12b | 284 | return; |
da537f52 | 285 | } |
286 | ||
287 | void | |
288 | badformat() | |
289 | { | |
468ae12b | 290 | fprintf(stderr, "pummel.bad.format\n"); |
da537f52 | 291 | exit(1); |
14c63c25 | 292 | } |
293 | ||
da537f52 | 294 | /* unused code, saved for parts */ |
295 | const char * | |
296 | make_nam(int id, int size) | |
297 | { | |
f53969cc | 298 | const char *buf = malloc(30); /* argh */ |
86c63190 | 299 | snprintf((char *)buf, sizeof(buf)-1, "pl:%d/%d", id, size); |
da537f52 | 300 | return buf; |
301 | } | |
e7740002 | 302 | |
303 | void | |
468ae12b | 304 | my_hash_insert(hash_table * h, const char *k, memitem * item) |
305 | { | |
306 | memitem *l; | |
307 | assert(item->pool); | |
308 | assert(item->my_ptr); | |
309 | hash_insert(h, k, item); | |
e7740002 | 310 | } |
311 | ||
312 | static void * | |
468ae12b | 313 | xmemAlloc(memitem * item) |
e7740002 | 314 | { |
315 | extern MemPool *StringPool; | |
316 | assert(item && item->pool); | |
317 | if (StringPool == item->pool) | |
26ac0430 | 318 | return memStringAlloc(item->pool, item->size); |
e7740002 | 319 | else |
26ac0430 | 320 | return memAlloc(item->pool); |
e7740002 | 321 | } |
322 | ||
323 | static void | |
468ae12b | 324 | xmemFree(memitem * item) |
e7740002 | 325 | { |
326 | extern MemPool *StringPool; | |
327 | assert(item && item->pool); | |
328 | if (StringPool == item->pool) | |
26ac0430 | 329 | return memStringFree(item->pool, item->my_ptr, item->size); |
e7740002 | 330 | else |
26ac0430 | 331 | return memFree(item->pool, item->my_ptr); |
e7740002 | 332 | } |
333 | ||
26ac0430 | 334 | void |
468ae12b | 335 | my_free(char *file, int line, void *ptr) |
e7740002 | 336 | { |
337 | #if 0 | |
468ae12b | 338 | fprintf(stderr, "{%s:%d:%p", file, line, ptr); |
e7740002 | 339 | #endif |
468ae12b | 340 | free(ptr); |
341 | #if 0 | |
342 | fprintf(stderr, "}\n"); | |
e7740002 | 343 | #endif |
344 | } | |
f53969cc | 345 |