stdio: puts() and vprintf()
[neatlibc.git] / memtst.c
blob908b51d854546e0549efd1230473da16fda59f1f
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
5 #define MTHASH(v) ((((long) v) >> 8) & 0xffff)
6 #define MEMTSTSZ (1 << 18)
7 #define MTHASHSZ (1 << 16)
8 #define MTBTLEN 5
10 struct memtst {
11 long *mem;
12 long n;
13 long bt[MTBTLEN];
14 int freed;
17 static struct memtst *memtst; /* memtst records */
18 static int memtst_n; /* number of items in memtst[] */
19 static int memtst_sz = MEMTSTSZ;
20 static int *memtst_tail; /* hash table list tails */
21 static int *memtst_prev; /* hash table list previous items */
22 static int memtst_mcnt, memtst_fcnt; /* malloc() and free() count */
23 static long memtst_mmax; /* maximum memory used */
24 static long memtst_mcur; /* allocated memory */
25 static long memtst_mtot; /* total memory allocated */
27 static int memtst_full(void)
29 return memtst_n == memtst_sz;
32 static char *memtst_show(long *bt)
34 static char s[100];
35 snprintf(s, sizeof(s), "%8p %8p %8p %8p %8p",
36 bt[0], bt[1], bt[2], bt[3], bt[4]);
37 return s;
40 static void memtst_summary(void)
42 int i;
43 fprintf(stderr, "memtst %d %d %ld", memtst_mcnt, memtst_fcnt, memtst_mtot);
44 if (memtst_full()) {
45 fprintf(stderr, "\nmemtst: increase MEMTSTSZ\n");
46 return;
48 fprintf(stderr, " %ld\n", memtst_mmax);
49 for (i = 0; i < memtst_n; i++) {
50 struct memtst *mt = &memtst[i];
51 if (!mt->freed)
52 fprintf(stderr, "memtstleak %8p %8ld %s\n",
53 mt->mem, mt->n, memtst_show(mt->bt));
57 static void memtst_init(void)
59 memtst = malloc(memtst_sz * sizeof(memtst[0]));
60 memtst_prev = malloc(memtst_sz * sizeof(memtst_prev[0]));
61 memtst_tail = malloc(MTHASHSZ * sizeof(memtst_tail[0]));
62 memset(memtst_tail, 0xff, MTHASHSZ * sizeof(memtst_tail[0]));
63 atexit(memtst_summary);
66 static void memtst_put(void *mem, int n, long *bt)
68 struct memtst *mt;
69 if (!memtst)
70 memtst_init();
71 if (memtst_full())
72 return;
73 mt = &memtst[memtst_n];
74 mt->mem = mem;
75 mt->n = n;
76 memcpy(mt->bt, bt, sizeof(mt->bt));
77 memtst_prev[memtst_n] = memtst_tail[MTHASH(mem)];
78 memtst_tail[MTHASH(mem)] = memtst_n;
79 memtst_n++;
82 static struct memtst *memtst_get(void *mem)
84 int idx;
85 if (!memtst)
86 return NULL;
87 idx = memtst_tail[MTHASH(mem)];
88 while (idx >= 0) {
89 struct memtst *mt = &memtst[idx];
90 if (!mt->freed && mt->mem == mem)
91 return mt;
92 idx = memtst_prev[idx];
94 return NULL;
97 long memtst_back(int n);
99 static void memtst_bt(long *bt)
101 bt[0] = memtst_back(1);
102 bt[1] = memtst_back(2);
103 bt[2] = memtst_back(3);
104 bt[3] = memtst_back(4);
105 bt[4] = memtst_back(5);
108 void *memtst_malloc(long n)
110 void *v = malloc(n);
111 long bt[MTBTLEN];
112 memtst_bt(bt);
113 if (!v)
114 fprintf(stderr, "memtstfail %8ld %s\n", n, memtst_show(bt));
115 else
116 memtst_put(v, n, bt);
117 if (v) {
118 memtst_mcnt++;
119 memtst_mcur += n;
120 memtst_mtot += n;
122 if (memtst_mcur > memtst_mmax)
123 memtst_mmax = memtst_mcur;
124 return v;
127 void memtst_free(void *v)
129 struct memtst *mt;
130 if (!v)
131 return;
132 memtst_fcnt++;
133 mt = memtst_get(v);
134 if (!mt && !memtst_full()) {
135 long bt[MTBTLEN];
136 memtst_bt(bt);
137 fprintf(stderr, "memtstfree %8p %s\n", v, memtst_show(bt));
138 return;
140 if (mt)
141 memtst_mcur -= mt->n;
142 if (mt)
143 mt->freed = 1;
144 free(v);
147 void *memtst_calloc(long n, long sz)
149 void *r = memtst_malloc(n * sz);
150 if (r)
151 memset(r, 0, n * sz);
152 return r;