Rune - Implement hard-locking model feature
[rune.git] / libruntime / zalloc.c
1 /*
2  * ZALLOC.C     - Memory management functions
3  *
4  * (c)Copyright 1993-2014, Matthew Dillon, All Rights Reserved.  See the  
5  *    COPYRIGHT file at the base of the distribution.
6  */
7
8 #include "defs.h"
9 #include <signal.h>
10 #include <stddef.h>
11
12 /*NOT MPSAFE #define INTERNAL_SLABBER */
13
14 void
15 zinit(void)
16 {
17         slabinit();
18 }
19
20 void *
21 zalloc_norm(uintptr_t bytes)
22 {
23         void *ptr;
24
25 #ifdef INTERNAL_SLABBER
26         if (bytes == 0) {
27                 ptr = (void *)-1;
28         } else if (bytes < SLABALLOC_ZONE_LIMIT) {
29                 ptr = slab_alloc(bytes);
30                 bzero(ptr, bytes);
31         } else {
32                 ptr = runevalloc(bytes);
33                 /* already zerod */
34         }
35 #else
36         ptr = calloc(1, bytes);
37 #endif
38         return(ptr);
39 }
40
41 void *
42 znalloc_norm(uintptr_t bytes)
43 {
44         void *ptr;
45
46 #ifdef INTERNAL_SLABBER
47         if (bytes == 0) {
48                 ptr = (void *)-1;
49         } else if (bytes < SLABALLOC_ZONE_LIMIT) {
50                 ptr = slab_alloc(bytes);
51         } else {
52                 ptr = runevalloc(bytes);
53         }
54 #else
55         ptr = malloc(bytes);
56 #endif
57         return(ptr);
58 }
59
60 void *
61 zrealloc_norm(void *optr, uintptr_t obytes, uintptr_t nbytes)
62 {
63         void *nptr;
64
65 #ifdef INTERNAL_SLABBER
66         if (obytes == nbytes) {
67                 nptr = optr;
68         } else if (obytes == 0) {
69                 nptr = zalloc_norm(nbytes);
70 #ifdef HAVE_SLAB_REALLOC
71         } else if (obytes < SLABALLOC_ZONE_LIMIT &&
72                    nbytes < SLABALLOC_ZONE_LIMIT) {
73                 nptr = slab_realloc(optr, obytes, nbytes);
74                 if (nbytes > obytes)
75                         bzero((char *)nptr + obytes, nbytes - obytes);
76 #endif
77         } else {
78                 nptr = znalloc_norm(nbytes);
79                 if (nbytes > obytes) {
80                         bcopy(optr, nptr, obytes);
81                         bzero((char *)nptr + obytes, nbytes - obytes);
82                 } else {
83                         bcopy(optr, nptr, nbytes);
84                 }
85                 zfree_norm(optr, obytes);
86         }
87 #else
88         nptr = realloc(optr, nbytes);
89         if (obytes < nbytes)
90                 bzero((char *)nptr + obytes, nbytes - obytes);
91 #endif
92         return(nptr);
93 }
94
95 void
96 zfree_norm(void *ptr, uintptr_t bytes)
97 {
98 #ifdef INTERNAL_SLABBER
99         if (bytes == 0)
100                 ;
101         else if (bytes < SLABALLOC_ZONE_LIMIT)
102                 slab_free(ptr, bytes);
103         else
104                 runevfree(ptr, bytes);
105 #else
106         free(ptr);
107 #endif
108 }
109
110 void
111 zfree_wipe_norm(void *ptr, uintptr_t bytes)
112 {
113 #ifdef INTERNAL_SLABBER
114         if (bytes == 0) {
115                 ;
116         } else if (bytes < SLABALLOC_ZONE_LIMIT) {
117                 bzero(ptr, bytes);
118                 slab_free(ptr, bytes);
119         } else {
120                 runevfree(ptr, bytes);
121         }
122 #else
123         free(ptr);
124 #endif
125 }
126
127 /************************************************************************
128  *                          ZALLOC DEBUG SUPPORT                        *
129  ************************************************************************/
130
131 #ifdef ZALLOC_DEBUG
132
133 typedef struct ZRef {
134         struct ZRef     *zr_Next;
135         int             zr_Hv;
136         int             zr_Count;
137         const char      *zr_File;
138         int             zr_Line;
139         int             zr_Bytes;
140 } ZRef;
141
142 typedef struct ZallocDebug {
143         int             zd_Bytes;
144         int             zd_Magic;
145         ZRef            *zd_Ref;
146         int             zd_Guard;
147         char            zd_Data[4];
148 } ZallocDebug;
149
150 #define ZD_MAGIC       0xFA55FF11
151 #define ZD_MAGIC_FREE  0xF566AAFF
152 #define ZD_GUARD       0x51515151
153 #define ZD_GUARDCHAR   0x51
154
155 static int ZSig;
156
157 #define HSIZE   256
158 #define HMASK   (HSIZE - 1)
159
160 ZRef    *ZHash[HSIZE];
161
162 static
163 ZRef *
164 zref(const char *file, int line)
165 {
166         ZRef *zr;
167         ZRef **pzr;
168         int hv = 0x23FFBBCC + line;
169         int i;
170
171         for (i = 0; file[i]; ++i)
172                 hv = (hv << 5) ^ file[i] ^ (hv >> 23);
173         pzr = &ZHash[hv & HMASK];
174         while ((zr = *pzr) != NULL) {
175                 if (zr->zr_Hv == hv &&
176                         zr->zr_Line == line &&
177                         strcmp(zr->zr_File, file) == 0
178                 ) {
179                         return(zr);
180                 }
181                 pzr = &zr->zr_Next;
182         }
183         zr = zalloc_norm(sizeof(ZRef));
184         zr->zr_File = file;
185         zr->zr_Line = line;
186         zr->zr_Hv = hv;
187         zr->zr_Next = *pzr;
188         *pzr = zr;
189         return(zr);
190 }
191
192 static void
193 zalloc_dump(int sigNo)
194 {
195         int i;
196         char buf[256];
197
198         snprintf(buf, sizeof(buf), "ZALLOC DUMP\n");
199         write(2, buf, strlen(buf));
200
201         for (i = 0; i < HSIZE; ++i) {
202                 ZRef *zr;
203                 for (zr = ZHash[i]; zr; zr = zr->zr_Next) {
204                         snprintf(buf, sizeof(buf),
205                                  "%20s %-4d cnt=%-5d ttl=%-5d\n",
206                                  zr->zr_File,
207                                  zr->zr_Line,
208                                  zr->zr_Count,
209                                  zr->zr_Bytes
210                         );
211                         write(2, buf, strlen(buf));
212                 }
213         }
214 }
215
216 void *
217 zalloc_debug(uintptr_t bytes, const char *file, int line)
218 {
219         ZallocDebug *zd = zalloc_norm(sizeof(ZallocDebug) + bytes + 4);
220
221         if (ZSig == 0) {
222                 signal(SIGUSR2, zalloc_dump);
223                 ZSig = 1;
224         }
225
226         zd->zd_Bytes = bytes;
227         zd->zd_Magic = ZD_MAGIC;
228         zd->zd_Ref = zref(file, line);
229         ++zd->zd_Ref->zr_Count;
230         zd->zd_Ref->zr_Bytes += bytes;
231         zd->zd_Guard = ZD_GUARD;
232         zd->zd_Data[bytes] = ZD_GUARDCHAR;
233         return(zd->zd_Data);
234 }
235
236 void
237 zfree_debug(void *ptr, uintptr_t bytes, const char *file, int line)
238 {
239         ZallocDebug *zd = (void *)((char *)ptr -
240                                    offsetof(ZallocDebug, zd_Data[0]));
241         if (zd->zd_Magic != ZD_MAGIC) {
242                 if (zd->zd_Magic == ZD_MAGIC_FREE)
243                         dpanic("%s:%d, memory location already freed!",
244                                file, line);
245                 else
246                         dpanic("%s:%d, memory location is not valid!",
247                                file, line);
248         }
249         if (zd->zd_Guard != ZD_GUARD ||
250             zd->zd_Data[zd->zd_Bytes] != ZD_GUARDCHAR)
251                 dpanic("%s:%d, guard character overwritten!", file, line);
252         if (zd->zd_Bytes != bytes) {
253                 dpanic("%s:%d, byte count mismatch: %d/%d", file, line,
254                                 bytes, zd->zd_Bytes);
255         }
256         --zd->zd_Ref->zr_Count;
257         zd->zd_Ref->zr_Bytes -= zd->zd_Bytes;
258         if (zd->zd_Ref->zr_Count < 0 || zd->zd_Ref->zr_Bytes < 0)
259                 dpanic("%s:%d, reference structure not sane", file, line);
260         zd->zd_Magic = ZD_MAGIC_FREE;
261         zfree_norm(zd, sizeof(ZallocDebug) + zd->zd_Bytes + 4);
262 }
263
264 void *
265 zrealloc_debug(void *optr, uintptr_t obytes,
266                uintptr_t bytes, const char *file, int line)
267 {
268         void *ptr;
269
270         ptr = zalloc_debug(bytes, file, line);
271         if (obytes)
272                 bcopy(optr, ptr, (obytes > bytes) ? bytes : obytes);
273         if (optr)
274                 zfree_debug(optr, obytes, file, line);
275         return(ptr);
276 }
277
278 #endif