1 /***** tl_spin: tl_mem.c *****/
2
3 /*
4 * This file is part of the public release of Spin. It is subject to the
5 * terms in the LICENSE file that is included in this source directory.
6 * Tool documentation is available at http://spinroot.com
7 *
8 * Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper,
9 * presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.
10 */
11
12 #include "tl.h"
13
14 #if 1
15 #define log(e, u, d) event[e][(int) u] += (long) d;
16 #else
17 #define log(e, u, d)
18 #endif
19
20 #define A_LARGE 80
21 #define A_USER 0x55000000
22 #define NOTOOBIG 32768
23
24 #define POOL 0
25 #define ALLOC 1
26 #define FREE 2
27 #define NREVENT 3
28
29 extern unsigned long All_Mem;
30 extern int tl_verbose;
31
32 union M {
33 long size;
34 union M *link;
35 };
36
37 static union M *freelist[A_LARGE];
38 static long req[A_LARGE];
39 static long event[NREVENT][A_LARGE];
40
41 void *
tl_emalloc(int U)42 tl_emalloc(int U)
43 { union M *m;
44 long r, u;
45 void *rp;
46
47 u = (long) ((U-1)/sizeof(union M) + 2);
48
49 if (u >= A_LARGE)
50 { log(ALLOC, 0, 1);
51 if (tl_verbose)
52 { printf("tl_spin: memalloc %ld bytes\n", u);
53 }
54 m = (union M *) emalloc((int) u*sizeof(union M));
55 All_Mem += (unsigned long) u*sizeof(union M);
56 } else
57 { if (!freelist[u])
58 { r = req[u] += req[u] ? req[u] : 1;
59 if (r >= NOTOOBIG)
60 { r = req[u] = NOTOOBIG;
61 }
62 log(POOL, u, r);
63 freelist[u] = (union M *)
64 emalloc((int) r*u*sizeof(union M));
65 All_Mem += (unsigned long) r*u*sizeof(union M);
66 m = freelist[u] + (r-2)*u;
67 for ( ; m >= freelist[u]; m -= u)
68 { m->link = m+u;
69 } }
70 log(ALLOC, u, 1);
71 m = freelist[u];
72 freelist[u] = m->link;
73 }
74 m->size = (u|A_USER);
75
76 for (r = 1; r < u; )
77 { (&m->size)[r++] = 0;
78 }
79
80 rp = (void *) (m+1);
81 memset(rp, 0, U);
82 return rp;
83 }
84
85 /* could be more efficient, but not a bottleneck */
86 void*
tl_erealloc(void * v,int U,int old_size)87 tl_erealloc(void *v, int U, int old_size)
88 { void* tmp = tl_emalloc(U);
89
90 if (v)
91 { strncpy(tmp, v, old_size);
92 tfree(v);
93 }
94
95 return tmp;
96 }
97
98 void
tfree(void * v)99 tfree(void *v)
100 { union M *m = (union M *) v;
101 long u;
102
103 --m;
104 if ((m->size&0xFF000000) != A_USER)
105 { Fatal("releasing a free block", (char *)0);
106 }
107
108 u = (m->size &= 0xFFFFFF);
109 if (u >= A_LARGE)
110 { log(FREE, 0, 1);
111 /* free(m); */
112 } else
113 { log(FREE, u, 1);
114 m->link = freelist[u];
115 freelist[u] = m;
116 }
117 }
118
119 void
a_stats(void)120 a_stats(void)
121 { long p, a, f;
122 int i;
123
124 printf(" size\t pool\tallocs\t frees\n");
125 for (i = 0; i < A_LARGE; i++)
126 { p = event[POOL][i];
127 a = event[ALLOC][i];
128 f = event[FREE][i];
129
130 if (p|a|f)
131 { printf("%5d\t%6ld\t%6ld\t%6ld\n",
132 i, p, a, f);
133 } }
134 }
135