summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/libc/stdlib/malloc.c746
1 files changed, 364 insertions, 382 deletions
diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c
index 1697a6e65e..cb2ba737ae 100644
--- a/src/lib/libc/stdlib/malloc.c
+++ b/src/lib/libc/stdlib/malloc.c
@@ -1,4 +1,5 @@
1/* $OpenBSD: malloc.c,v 1.77 2005/10/05 02:18:29 deraadt Exp $ */ 1/* $OpenBSD: malloc.c,v 1.78 2005/10/05 18:38:10 deraadt Exp $ */
2
2/* 3/*
3 * ---------------------------------------------------------------------------- 4 * ----------------------------------------------------------------------------
4 * "THE BEER-WARE LICENSE" (Revision 42): 5 * "THE BEER-WARE LICENSE" (Revision 42):
@@ -65,45 +66,44 @@
65 * 66 *
66 */ 67 */
67 68
68#if defined(__OpenBSD__) && defined(__sparc__) 69#if defined(__sparc__)
69#define malloc_pageshift 13U 70#define malloc_pageshift 13U
70#endif /* __OpenBSD__ */ 71#endif /* __sparc__ */
72
73#ifndef malloc_pageshift
74#define malloc_pageshift (PGSHIFT)
75#endif
71 76
72/* 77/*
73 * No user serviceable parts behind this point. 78 * No user serviceable parts behind this point.
74 * 79 *
75 * This structure describes a page worth of chunks. 80 * This structure describes a page worth of chunks.
76 */ 81 */
77
78struct pginfo { 82struct pginfo {
79 struct pginfo *next; /* next on the free list */ 83 struct pginfo *next; /* next on the free list */
80 void *page; /* Pointer to the page */ 84 void *page; /* Pointer to the page */
81 u_short size; /* size of this page's chunks */ 85 u_short size; /* size of this page's chunks */
82 u_short shift; /* How far to shift for this size chunks */ 86 u_short shift; /* How far to shift for this size chunks */
83 u_short free; /* How many free chunks */ 87 u_short free; /* How many free chunks */
84 u_short total; /* How many chunk */ 88 u_short total; /* How many chunk */
85 u_long bits[1];/* Which chunks are free */ 89 u_long bits[1];/* Which chunks are free */
86}; 90};
87 91
92/* How many bits per u_long in the bitmap */
93#define MALLOC_BITS (NBBY * sizeof(u_long))
94
88/* 95/*
89 * This structure describes a number of free pages. 96 * This structure describes a number of free pages.
90 */ 97 */
91
92struct pgfree { 98struct pgfree {
93 struct pgfree *next; /* next run of free pages */ 99 struct pgfree *next; /* next run of free pages */
94 struct pgfree *prev; /* prev run of free pages */ 100 struct pgfree *prev; /* prev run of free pages */
95 void *page; /* pointer to free pages */ 101 void *page; /* pointer to free pages */
96 void *pdir; /* pointer to the base page's dir */ 102 void *pdir; /* pointer to the base page's dir */
97 size_t size; /* number of bytes free */ 103 size_t size; /* number of bytes free */
98}; 104};
99 105
100/* 106/*
101 * How many bits per u_long in the bitmap.
102 * Change only if not 8 bits/byte
103 */
104#define MALLOC_BITS (8*sizeof(u_long))
105
106/*
107 * Magic values to put in the page_directory 107 * Magic values to put in the page_directory
108 */ 108 */
109#define MALLOC_NOT_MINE ((struct pginfo*) 0) 109#define MALLOC_NOT_MINE ((struct pginfo*) 0)
@@ -112,18 +112,10 @@ struct pgfree {
112#define MALLOC_FOLLOW ((struct pginfo*) 3) 112#define MALLOC_FOLLOW ((struct pginfo*) 3)
113#define MALLOC_MAGIC ((struct pginfo*) 4) 113#define MALLOC_MAGIC ((struct pginfo*) 4)
114 114
115#ifndef malloc_pageshift
116#define malloc_pageshift (PGSHIFT)
117#endif
118
119#ifndef malloc_minsize 115#ifndef malloc_minsize
120#define malloc_minsize 16U 116#define malloc_minsize 16U
121#endif 117#endif
122 118
123#ifndef malloc_pageshift
124#error "malloc_pageshift undefined"
125#endif
126
127#if !defined(malloc_pagesize) 119#if !defined(malloc_pagesize)
128#define malloc_pagesize (1UL<<malloc_pageshift) 120#define malloc_pagesize (1UL<<malloc_pageshift)
129#endif 121#endif
@@ -136,50 +128,38 @@ struct pgfree {
136#define malloc_maxsize ((malloc_pagesize)>>1) 128#define malloc_maxsize ((malloc_pagesize)>>1)
137#endif 129#endif
138 130
139/* A mask for the offset inside a page. */ 131/* A mask for the offset inside a page. */
140#define malloc_pagemask ((malloc_pagesize)-1) 132#define malloc_pagemask ((malloc_pagesize)-1)
141 133
142#define pageround(foo) (((foo) + (malloc_pagemask)) & ~malloc_pagemask) 134#define pageround(foo) (((foo) + (malloc_pagemask)) & ~malloc_pagemask)
143#define ptr2index(foo) (((u_long)(foo) >> malloc_pageshift)+malloc_pageshift) 135#define ptr2index(foo) (((u_long)(foo) >> malloc_pageshift)+malloc_pageshift)
144#define index2ptr(idx) ((void*)(((idx)-malloc_pageshift)<<malloc_pageshift)) 136#define index2ptr(idx) ((void*)(((idx)-malloc_pageshift)<<malloc_pageshift))
145 137
146/* fd of /dev/zero */
147#ifdef USE_DEV_ZERO
148static int fdzero;
149#define MMAP_FD fdzero
150#define INIT_MMAP() \
151 { if ((fdzero=open("/dev/zero", O_RDWR, 0000)) == -1) \
152 wrterror("open of /dev/zero\n"); }
153#else
154#define MMAP_FD (-1)
155#define INIT_MMAP()
156#endif
157
158/* Set when initialization has been done */ 138/* Set when initialization has been done */
159static unsigned int malloc_started; 139static unsigned int malloc_started;
160 140
161/* Number of free pages we cache */ 141/* Number of free pages we cache */
162static unsigned int malloc_cache = 16; 142static unsigned int malloc_cache = 16;
163 143
164/* Structure used for linking discrete directory pages. */ 144/* Structure used for linking discrete directory pages. */
165struct pdinfo { 145struct pdinfo {
166 struct pginfo **base; 146 struct pginfo **base;
167 struct pdinfo *prev; 147 struct pdinfo *prev;
168 struct pdinfo *next; 148 struct pdinfo *next;
169 u_long dirnum; 149 u_long dirnum;
170}; 150};
171static struct pdinfo *last_dir; /* Caches to the last and previous */ 151static struct pdinfo *last_dir; /* Caches to the last and previous */
172static struct pdinfo *prev_dir; /* referenced directory pages. */ 152static struct pdinfo *prev_dir; /* referenced directory pages. */
173 153
174static size_t pdi_off; 154static size_t pdi_off;
175static u_long pdi_mod; 155static u_long pdi_mod;
176#define PD_IDX(num) ((num) / (malloc_pagesize/sizeof(struct pginfo *))) 156#define PD_IDX(num) ((num) / (malloc_pagesize/sizeof(struct pginfo *)))
177#define PD_OFF(num) ((num) & ((malloc_pagesize/sizeof(struct pginfo *))-1)) 157#define PD_OFF(num) ((num) & ((malloc_pagesize/sizeof(struct pginfo *))-1))
178#define PI_IDX(index) ((index) / pdi_mod) 158#define PI_IDX(index) ((index) / pdi_mod)
179#define PI_OFF(index) ((index) % pdi_mod) 159#define PI_OFF(index) ((index) % pdi_mod)
180 160
181/* The last index in the page directory we care about */ 161/* The last index in the page directory we care about */
182static u_long last_index; 162static u_long last_index;
183 163
184/* Pointer to page directory. Allocated "as if with" malloc */ 164/* Pointer to page directory. Allocated "as if with" malloc */
185static struct pginfo **page_dir; 165static struct pginfo **page_dir;
@@ -187,57 +167,54 @@ static struct pginfo **page_dir;
187/* Free pages line up here */ 167/* Free pages line up here */
188static struct pgfree free_list; 168static struct pgfree free_list;
189 169
190/* Abort(), user doesn't handle problems. */ 170/* Abort(), user doesn't handle problems. */
191static int malloc_abort = 2; 171static int malloc_abort = 2;
192 172
193/* Are we trying to die ? */ 173/* Are we trying to die ? */
194static int suicide; 174static int suicide;
195 175
196#ifdef MALLOC_STATS 176#ifdef MALLOC_STATS
197/* dump statistics */ 177/* dump statistics */
198static int malloc_stats; 178static int malloc_stats;
199#endif 179#endif
200 180
201/* avoid outputting warnings? */ 181/* avoid outputting warnings? */
202static int malloc_silent; 182static int malloc_silent;
203 183
204/* always realloc ? */ 184/* always realloc ? */
205static int malloc_realloc; 185static int malloc_realloc;
206 186
207/* mprotect free pages PROT_NONE? */ 187/* mprotect free pages PROT_NONE? */
208static int malloc_freeprot; 188static int malloc_freeprot;
209 189
210/* use guard pages after allocations? */ 190/* use guard pages after allocations? */
211static int malloc_guard = 0; 191static int malloc_guard = 0;
212static int malloc_guarded; 192static int malloc_guarded;
213/* align pointers to end of page? */ 193/* align pointers to end of page? */
214static int malloc_ptrguard; 194static int malloc_ptrguard;
215 195
216#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE)) 196static int malloc_hint;
217/* pass the kernel a hint on free pages ? */
218static int malloc_hint;
219#endif
220 197
221/* xmalloc behaviour ? */ 198/* xmalloc behaviour ? */
222static int malloc_xmalloc; 199static int malloc_xmalloc;
223 200
224/* zero fill ? */ 201/* zero fill ? */
225static int malloc_zero; 202static int malloc_zero;
226 203
227/* junk fill ? */ 204/* junk fill ? */
228static int malloc_junk; 205static int malloc_junk;
229 206
230#ifdef __FreeBSD__ 207#ifdef __FreeBSD__
231/* utrace ? */ 208/* utrace ? */
232static int malloc_utrace; 209static int malloc_utrace;
233 210
234struct ut { 211struct ut {
235 void *p; 212 void *p;
236 size_t s; 213 size_t s;
237 void *r; 214 void *r;
238}; 215};
239 216
240void utrace(struct ut *, int); 217void utrace(struct ut *, int);
241 218
242#define UTRACE(a, b, c) \ 219#define UTRACE(a, b, c) \
243 if (malloc_utrace) \ 220 if (malloc_utrace) \
@@ -247,36 +224,34 @@ void utrace(struct ut *, int);
247#endif 224#endif
248 225
249/* Status of malloc. */ 226/* Status of malloc. */
250static int malloc_active; 227static int malloc_active;
251 228
252/* Allocated memory. */ 229/* Allocated memory. */
253static size_t malloc_used; 230static size_t malloc_used;
254 231
255/* My last break. */ 232/* My last break. */
256static void *malloc_brk; 233static void *malloc_brk;
257 234
258/* One location cache for free-list holders. */ 235/* One location cache for free-list holders. */
259static struct pgfree *px; 236static struct pgfree *px;
260 237
261/* Compile-time options. */ 238/* Compile-time options. */
262char *malloc_options; 239char *malloc_options;
263 240
264/* Name of the current public function. */ 241/* Name of the current public function. */
265static char *malloc_func; 242static char *malloc_func;
266 243
267/* Macro for mmap. */
268#define MMAP(size) \ 244#define MMAP(size) \
269 mmap((void *)0, (size), PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, \ 245 mmap((void *)0, (size), PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, \
270 MMAP_FD, (off_t)0) 246 -1, (off_t)0)
271 247
272/* 248/*
273 * Necessary function declarations. 249 * Necessary function declarations.
274 */ 250 */
275static void *imalloc(size_t size); 251static void *imalloc(size_t size);
276static void ifree(void *ptr); 252static void ifree(void *ptr);
277static void *irealloc(void *ptr, size_t size); 253static void *irealloc(void *ptr, size_t size);
278static void *malloc_bytes(size_t size); 254static void *malloc_bytes(size_t size);
279
280 255
281/* 256/*
282 * Function for page directory lookup. 257 * Function for page directory lookup.
@@ -284,8 +259,8 @@ static void *malloc_bytes(size_t size);
284static int 259static int
285pdir_lookup(u_long index, struct pdinfo ** pdi) 260pdir_lookup(u_long index, struct pdinfo ** pdi)
286{ 261{
287 struct pdinfo *spi; 262 struct pdinfo *spi;
288 u_long pidx = PI_IDX(index); 263 u_long pidx = PI_IDX(index);
289 264
290 if (last_dir != NULL && PD_IDX(last_dir->dirnum) == pidx) 265 if (last_dir != NULL && PD_IDX(last_dir->dirnum) == pidx)
291 *pdi = last_dir; 266 *pdi = last_dir;
@@ -293,48 +268,56 @@ pdir_lookup(u_long index, struct pdinfo ** pdi)
293 *pdi = prev_dir; 268 *pdi = prev_dir;
294 else if (last_dir != NULL && prev_dir != NULL) { 269 else if (last_dir != NULL && prev_dir != NULL) {
295 if ((PD_IDX(last_dir->dirnum) > pidx) ? 270 if ((PD_IDX(last_dir->dirnum) > pidx) ?
296 (PD_IDX(last_dir->dirnum) - pidx) : (pidx - PD_IDX(last_dir->dirnum)) 271 (PD_IDX(last_dir->dirnum) - pidx) :
272 (pidx - PD_IDX(last_dir->dirnum))
297 < (PD_IDX(prev_dir->dirnum) > pidx) ? 273 < (PD_IDX(prev_dir->dirnum) > pidx) ?
298 (PD_IDX(prev_dir->dirnum) - pidx) : (pidx - PD_IDX(prev_dir->dirnum))) 274 (PD_IDX(prev_dir->dirnum) - pidx) :
275 (pidx - PD_IDX(prev_dir->dirnum)))
299 *pdi = last_dir; 276 *pdi = last_dir;
300 else 277 else
301 *pdi = prev_dir; 278 *pdi = prev_dir;
302 279
303 if (PD_IDX((*pdi)->dirnum) > pidx) { 280 if (PD_IDX((*pdi)->dirnum) > pidx) {
304 for (spi = (*pdi)->prev; spi != NULL && PD_IDX(spi->dirnum) > pidx; 281 for (spi = (*pdi)->prev;
305 spi = spi->prev) 282 spi != NULL && PD_IDX(spi->dirnum) > pidx;
283 spi = spi->prev)
306 *pdi = spi; 284 *pdi = spi;
307 if (spi != NULL) 285 if (spi != NULL)
308 *pdi = spi; 286 *pdi = spi;
309 } else 287 } else
310 for (spi = (*pdi)->next; spi != NULL && PD_IDX(spi->dirnum) <= pidx; 288 for (spi = (*pdi)->next;
311 spi = spi->next) 289 spi != NULL && PD_IDX(spi->dirnum) <= pidx;
290 spi = spi->next)
312 *pdi = spi; 291 *pdi = spi;
313 } else { 292 } else {
314 *pdi = (struct pdinfo *) ((caddr_t) page_dir + pdi_off); 293 *pdi = (struct pdinfo *) ((caddr_t) page_dir + pdi_off);
315 for (spi = *pdi; spi != NULL && PD_IDX(spi->dirnum) <= pidx; spi = spi->next) 294 for (spi = *pdi;
295 spi != NULL && PD_IDX(spi->dirnum) <= pidx;
296 spi = spi->next)
316 *pdi = spi; 297 *pdi = spi;
317 } 298 }
318 299
319 return ((PD_IDX((*pdi)->dirnum) == pidx) ? 0 : (PD_IDX((*pdi)->dirnum) > pidx) ? 1 : -1); 300 return ((PD_IDX((*pdi)->dirnum) == pidx) ? 0 :
301 (PD_IDX((*pdi)->dirnum) > pidx) ? 1 : -1);
320} 302}
321 303
322 304#ifdef MALLOC_STATS
323#ifdef MALLOC_STATS
324void 305void
325malloc_dump(FILE * fd) 306malloc_dump(int fd)
326{ 307{
327 struct pginfo **pd; 308 char buf[1024];
328 struct pgfree *pf; 309 struct pginfo **pd;
329 struct pdinfo *pi; 310 struct pgfree *pf;
330 int j; 311 struct pdinfo *pi;
312 int j;
331 313
332 pd = page_dir; 314 pd = page_dir;
333 pi = (struct pdinfo *) ((caddr_t) pd + pdi_off); 315 pi = (struct pdinfo *) ((caddr_t) pd + pdi_off);
334 316
335 /* print out all the pages */ 317 /* print out all the pages */
336 for (j = 0; j <= last_index;) { 318 for (j = 0; j <= last_index;) {
337 fprintf(fd, "%08lx %5d ", j << malloc_pageshift, j); 319 snprintf(buf, sizeof buf, "%08lx %5d ", j << malloc_pageshift, j);
320 write(fd, buf, strlen(buf));
338 if (pd[PI_OFF(j)] == MALLOC_NOT_MINE) { 321 if (pd[PI_OFF(j)] == MALLOC_NOT_MINE) {
339 for (j++; j <= last_index && pd[PI_OFF(j)] == MALLOC_NOT_MINE;) { 322 for (j++; j <= last_index && pd[PI_OFF(j)] == MALLOC_NOT_MINE;) {
340 if (!PI_OFF(++j)) { 323 if (!PI_OFF(++j)) {
@@ -346,7 +329,8 @@ malloc_dump(FILE * fd)
346 } 329 }
347 } 330 }
348 j--; 331 j--;
349 fprintf(fd, ".. %5d not mine\n", j); 332 snprintf(buf, sizeof buf, ".. %5d not mine\n", j);
333 write(fd, buf, strlen(buf));
350 } else if (pd[PI_OFF(j)] == MALLOC_FREE) { 334 } else if (pd[PI_OFF(j)] == MALLOC_FREE) {
351 for (j++; j <= last_index && pd[PI_OFF(j)] == MALLOC_FREE;) { 335 for (j++; j <= last_index && pd[PI_OFF(j)] == MALLOC_FREE;) {
352 if (!PI_OFF(++j)) { 336 if (!PI_OFF(++j)) {
@@ -358,7 +342,8 @@ malloc_dump(FILE * fd)
358 } 342 }
359 } 343 }
360 j--; 344 j--;
361 fprintf(fd, ".. %5d free\n", j); 345 snprintf(buf, sizeof buf, ".. %5d free\n", j);
346 write(fd, buf, strlen(buf));
362 } else if (pd[PI_OFF(j)] == MALLOC_FIRST) { 347 } else if (pd[PI_OFF(j)] == MALLOC_FIRST) {
363 for (j++; j <= last_index && pd[PI_OFF(j)] == MALLOC_FOLLOW;) { 348 for (j++; j <= last_index && pd[PI_OFF(j)] == MALLOC_FOLLOW;) {
364 if (!PI_OFF(++j)) { 349 if (!PI_OFF(++j)) {
@@ -370,13 +355,17 @@ malloc_dump(FILE * fd)
370 } 355 }
371 } 356 }
372 j--; 357 j--;
373 fprintf(fd, ".. %5d in use\n", j); 358 snprintf(buf, sizeof buf, ".. %5d in use\n", j);
359 write(fd, buf, strlen(buf));
374 } else if (pd[PI_OFF(j)] < MALLOC_MAGIC) { 360 } else if (pd[PI_OFF(j)] < MALLOC_MAGIC) {
375 fprintf(fd, "(%p)\n", pd[PI_OFF(j)]); 361 snprintf(buf, sizeof buf, "(%p)\n", pd[PI_OFF(j)]);
362 write(fd, buf, strlen(buf));
376 } else { 363 } else {
377 fprintf(fd, "%p %d (of %d) x %d @ %p --> %p\n", 364 snprintf(buf, sizeof buf, "%p %d (of %d) x %d @ %p --> %p\n",
378 pd[PI_OFF(j)], pd[PI_OFF(j)]->free, pd[PI_OFF(j)]->total, 365 pd[PI_OFF(j)], pd[PI_OFF(j)]->free,
379 pd[PI_OFF(j)]->size, pd[PI_OFF(j)]->page, pd[PI_OFF(j)]->next); 366 pd[PI_OFF(j)]->total, pd[PI_OFF(j)]->size,
367 pd[PI_OFF(j)]->page, pd[PI_OFF(j)]->next);
368 write(fd, buf, strlen(buf));
380 } 369 }
381 if (!PI_OFF(++j)) { 370 if (!PI_OFF(++j)) {
382 if ((pi = pi->next) == NULL) 371 if ((pi = pi->next) == NULL)
@@ -387,32 +376,40 @@ malloc_dump(FILE * fd)
387 } 376 }
388 377
389 for (pf = free_list.next; pf; pf = pf->next) { 378 for (pf = free_list.next; pf; pf = pf->next) {
390 fprintf(fd, "Free: @%p [%p...%p[ %ld ->%p <-%p\n", 379 snprintf(buf, sizeof buf, "Free: @%p [%p...%p[ %ld ->%p <-%p\n",
391 pf, pf->page, pf->page + pf->size, pf->size, 380 pf, pf->page, pf->page + pf->size,
392 pf->prev, pf->next); 381 pf->size, pf->prev, pf->next);
382 write(fd, buf, strlen(buf));
393 if (pf == pf->next) { 383 if (pf == pf->next) {
394 fprintf(fd, "Free_list loops\n"); 384 snprintf(buf, sizeof buf, "Free_list loops\n");
385 write(fd, buf, strlen(buf));
395 break; 386 break;
396 } 387 }
397 } 388 }
398 389
399 /* print out various info */ 390 /* print out various info */
400 fprintf(fd, "Minsize\t%d\n", malloc_minsize); 391 snprintf(buf, sizeof buf, "Minsize\t%d\n", malloc_minsize);
401 fprintf(fd, "Maxsize\t%d\n", malloc_maxsize); 392 write(fd, buf, strlen(buf));
402 fprintf(fd, "Pagesize\t%lu\n", (u_long) malloc_pagesize); 393 snprintf(buf, sizeof buf, "Maxsize\t%d\n", malloc_maxsize);
403 fprintf(fd, "Pageshift\t%d\n", malloc_pageshift); 394 write(fd, buf, strlen(buf));
404 fprintf(fd, "In use\t%lu\n", (u_long) malloc_used); 395 snprintf(buf, sizeof buf, "Pagesize\t%lu\n", (u_long) malloc_pagesize);
405 fprintf(fd, "Guarded\t%lu\n", (u_long) malloc_guarded); 396 write(fd, buf, strlen(buf));
397 snprintf(buf, sizeof buf, "Pageshift\t%d\n", malloc_pageshift);
398 write(fd, buf, strlen(buf));
399 snprintf(buf, sizeof buf, "In use\t%lu\n", (u_long) malloc_used);
400 write(fd, buf, strlen(buf));
401 snprintf(buf, sizeof buf, "Guarded\t%lu\n", (u_long) malloc_guarded);
402 write(fd, buf, strlen(buf));
406} 403}
407#endif /* MALLOC_STATS */ 404#endif /* MALLOC_STATS */
408 405
409extern char *__progname; 406extern char *__progname;
410 407
411static void 408static void
412wrterror(char *p) 409wrterror(char *p)
413{ 410{
414 char *q = " error: "; 411 char *q = " error: ";
415 struct iovec iov[4]; 412 struct iovec iov[5];
416 413
417 iov[0].iov_base = __progname; 414 iov[0].iov_base = __progname;
418 iov[0].iov_len = strlen(__progname); 415 iov[0].iov_len = strlen(__progname);
@@ -422,13 +419,15 @@ wrterror(char *p)
422 iov[2].iov_len = strlen(q); 419 iov[2].iov_len = strlen(q);
423 iov[3].iov_base = p; 420 iov[3].iov_base = p;
424 iov[3].iov_len = strlen(p); 421 iov[3].iov_len = strlen(p);
425 writev(STDERR_FILENO, iov, 4); 422 iov[4].iov_base = "\n";
423 iov[4].iov_len = 1;
424 writev(STDERR_FILENO, iov, 5);
426 425
427 suicide = 1; 426 suicide = 1;
428#ifdef MALLOC_STATS 427#ifdef MALLOC_STATS
429 if (malloc_stats) 428 if (malloc_stats)
430 malloc_dump(stderr); 429 malloc_dump(STDERR_FILENO);
431#endif /* MALLOC_STATS */ 430#endif /* MALLOC_STATS */
432 malloc_active--; 431 malloc_active--;
433 if (malloc_abort) 432 if (malloc_abort)
434 abort(); 433 abort();
@@ -437,8 +436,8 @@ wrterror(char *p)
437static void 436static void
438wrtwarning(char *p) 437wrtwarning(char *p)
439{ 438{
440 char *q = " warning: "; 439 char *q = " warning: ";
441 struct iovec iov[4]; 440 struct iovec iov[5];
442 441
443 if (malloc_abort) 442 if (malloc_abort)
444 wrterror(p); 443 wrterror(p);
@@ -453,43 +452,48 @@ wrtwarning(char *p)
453 iov[2].iov_len = strlen(q); 452 iov[2].iov_len = strlen(q);
454 iov[3].iov_base = p; 453 iov[3].iov_base = p;
455 iov[3].iov_len = strlen(p); 454 iov[3].iov_len = strlen(p);
456 writev(STDERR_FILENO, iov, 4); 455 iov[4].iov_base = "\n";
456 iov[4].iov_len = 1;
457
458 writev(STDERR_FILENO, iov, 5);
457} 459}
458 460
459#ifdef MALLOC_STATS 461#ifdef MALLOC_STATS
460static void 462static void
461malloc_exit(void) 463malloc_exit(void)
462{ 464{
463 FILE *fd = fopen("malloc.out", "a"); 465 char *q = "malloc() warning: Couldn't dump stats\n";
464 char *q = "malloc() warning: Couldn't dump stats\n"; 466 int save_errno = errno, fd;
465 if (fd != NULL) { 467
468 fd = open("malloc.out", O_RDWR|O_APPEND);
469 if (fd != -1) {
466 malloc_dump(fd); 470 malloc_dump(fd);
467 fclose(fd); 471 close(fd);
468 } else 472 } else
469 write(STDERR_FILENO, q, strlen(q)); 473 write(STDERR_FILENO, q, strlen(q));
474 errno = save_errno;
470} 475}
471#endif /* MALLOC_STATS */ 476#endif /* MALLOC_STATS */
472
473 477
474/* 478/*
475 * Allocate a number of pages from the OS 479 * Allocate a number of pages from the OS
476 */ 480 */
477static void * 481static void *
478map_pages(size_t pages) 482map_pages(size_t pages)
479{ 483{
480 struct pdinfo *pi, *spi; 484 struct pdinfo *pi, *spi;
481 struct pginfo **pd; 485 struct pginfo **pd;
482 u_long idx, pidx, lidx; 486 u_long idx, pidx, lidx;
483 void *result, *tail; 487 void *result, *tail;
484 u_long index, lindex; 488 u_long index, lindex;
485 489
486 pages <<= malloc_pageshift; 490 pages <<= malloc_pageshift;
487 result = MMAP(pages + malloc_guard); 491 result = MMAP(pages + malloc_guard);
488 if (result == MAP_FAILED) { 492 if (result == MAP_FAILED) {
489 errno = ENOMEM; 493 errno = ENOMEM;
490#ifdef MALLOC_EXTRA_SANITY 494#ifdef MALLOC_EXTRA_SANITY
491 wrtwarning("(ES): map_pages fails\n"); 495 wrtwarning("(ES): map_pages fails");
492#endif /* MALLOC_EXTRA_SANITY */ 496#endif /* MALLOC_EXTRA_SANITY */
493 return (NULL); 497 return (NULL);
494 } 498 }
495 index = ptr2index(result); 499 index = ptr2index(result);
@@ -511,11 +515,11 @@ map_pages(size_t pages)
511 for (idx = pidx, spi = pi; idx <= lidx; idx++) { 515 for (idx = pidx, spi = pi; idx <= lidx; idx++) {
512 if (pi == NULL || PD_IDX(pi->dirnum) != idx) { 516 if (pi == NULL || PD_IDX(pi->dirnum) != idx) {
513 if ((pd = MMAP(malloc_pagesize)) == MAP_FAILED) { 517 if ((pd = MMAP(malloc_pagesize)) == MAP_FAILED) {
514 errno = ENOMEM; 518 errno = ENOMEM; /* XXX */
515 munmap(result, tail - result); 519 munmap(result, tail - result);
516#ifdef MALLOC_EXTRA_SANITY 520#ifdef MALLOC_EXTRA_SANITY
517 wrtwarning("(ES): map_pages fails\n"); 521 wrtwarning("(ES): map_pages fails");
518#endif /* MALLOC_EXTRA_SANITY */ 522#endif /* MALLOC_EXTRA_SANITY */
519 return (NULL); 523 return (NULL);
520 } 524 }
521 memset(pd, 0, malloc_pagesize); 525 memset(pd, 0, malloc_pagesize);
@@ -540,13 +544,13 @@ map_pages(size_t pages)
540 } else { 544 } else {
541 pi->dirnum += PI_OFF(ptr2index(tail - 1)) + 1; 545 pi->dirnum += PI_OFF(ptr2index(tail - 1)) + 1;
542 } 546 }
543#ifdef MALLOC_EXTRA_SANITY 547#ifdef MALLOC_EXTRA_SANITY
544 if (PD_OFF(pi->dirnum) > pdi_mod || PD_IDX(pi->dirnum) > idx) { 548 if (PD_OFF(pi->dirnum) > pdi_mod || PD_IDX(pi->dirnum) > idx) {
545 wrterror("(ES): pages directory overflow\n"); 549 wrterror("(ES): pages directory overflow");
546 errno = EFAULT; 550 errno = EFAULT;
547 return (NULL); 551 return (NULL);
548 } 552 }
549#endif /* MALLOC_EXTRA_SANITY */ 553#endif /* MALLOC_EXTRA_SANITY */
550 if (idx == pidx && pi != last_dir) { 554 if (idx == pidx && pi != last_dir) {
551 prev_dir = last_dir; 555 prev_dir = last_dir;
552 last_dir = pi; 556 last_dir = pi;
@@ -558,24 +562,20 @@ map_pages(size_t pages)
558 return (result); 562 return (result);
559} 563}
560 564
561
562/* 565/*
563 * Initialize the world 566 * Initialize the world
564 */ 567 */
565static void 568static void
566malloc_init(void) 569malloc_init(void)
567{ 570{
568 char *p, b[64]; 571 char *p, b[64];
569 int i, j; 572 int i, j, save_errno = errno;
570 int save_errno = errno;
571 573
572 _MALLOC_LOCK_INIT(); 574 _MALLOC_LOCK_INIT();
573 575
574 INIT_MMAP(); 576#ifdef MALLOC_EXTRA_SANITY
575
576#ifdef MALLOC_EXTRA_SANITY
577 malloc_junk = 1; 577 malloc_junk = 1;
578#endif /* MALLOC_EXTRA_SANITY */ 578#endif /* MALLOC_EXTRA_SANITY */
579 579
580 for (i = 0; i < 3; i++) { 580 for (i = 0; i < 3; i++) {
581 switch (i) { 581 switch (i) {
@@ -586,21 +586,19 @@ malloc_init(void)
586 b[j] = '\0'; 586 b[j] = '\0';
587 p = b; 587 p = b;
588 break; 588 break;
589
590 case 1: 589 case 1:
591 if (issetugid() == 0) 590 if (issetugid() == 0)
592 p = getenv("MALLOC_OPTIONS"); 591 p = getenv("MALLOC_OPTIONS");
593 else 592 else
594 continue; 593 continue;
595 break; 594 break;
596
597 case 2: 595 case 2:
598 p = malloc_options; 596 p = malloc_options;
599 break; 597 break;
600
601 default: 598 default:
602 p = NULL; 599 p = NULL;
603 } 600 }
601
604 for (; p != NULL && *p != '\0'; p++) { 602 for (; p != NULL && *p != '\0'; p++) {
605 switch (*p) { 603 switch (*p) {
606 case '>': 604 case '>':
@@ -615,14 +613,14 @@ malloc_init(void)
615 case 'A': 613 case 'A':
616 malloc_abort = 1; 614 malloc_abort = 1;
617 break; 615 break;
618#ifdef MALLOC_STATS 616#ifdef MALLOC_STATS
619 case 'd': 617 case 'd':
620 malloc_stats = 0; 618 malloc_stats = 0;
621 break; 619 break;
622 case 'D': 620 case 'D':
623 malloc_stats = 1; 621 malloc_stats = 1;
624 break; 622 break;
625#endif /* MALLOC_STATS */ 623#endif /* MALLOC_STATS */
626 case 'f': 624 case 'f':
627 malloc_freeprot = 0; 625 malloc_freeprot = 0;
628 break; 626 break;
@@ -635,14 +633,12 @@ malloc_init(void)
635 case 'G': 633 case 'G':
636 malloc_guard = malloc_pagesize; 634 malloc_guard = malloc_pagesize;
637 break; 635 break;
638#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE))
639 case 'h': 636 case 'h':
640 malloc_hint = 0; 637 malloc_hint = 0;
641 break; 638 break;
642 case 'H': 639 case 'H':
643 malloc_hint = 1; 640 malloc_hint = 1;
644 break; 641 break;
645#endif /* __FreeBSD__ */
646 case 'j': 642 case 'j':
647 malloc_junk = 0; 643 malloc_junk = 0;
648 break; 644 break;
@@ -674,7 +670,7 @@ malloc_init(void)
674 case 'U': 670 case 'U':
675 malloc_utrace = 1; 671 malloc_utrace = 1;
676 break; 672 break;
677#endif /* __FreeBSD__ */ 673#endif /* __FreeBSD__ */
678 case 'x': 674 case 'x':
679 malloc_xmalloc = 0; 675 malloc_xmalloc = 0;
680 break; 676 break;
@@ -690,7 +686,7 @@ malloc_init(void)
690 default: 686 default:
691 j = malloc_abort; 687 j = malloc_abort;
692 malloc_abort = 0; 688 malloc_abort = 0;
693 wrtwarning("unknown char in MALLOC_OPTIONS\n"); 689 wrtwarning("unknown char in MALLOC_OPTIONS");
694 malloc_abort = j; 690 malloc_abort = j;
695 break; 691 break;
696 } 692 }
@@ -700,22 +696,23 @@ malloc_init(void)
700 UTRACE(0, 0, 0); 696 UTRACE(0, 0, 0);
701 697
702 /* 698 /*
703 * We want junk in the entire allocation, and zero only in the part 699 * We want junk in the entire allocation, and zero only in the part
704 * the user asked for. 700 * the user asked for.
705 */ 701 */
706 if (malloc_zero) 702 if (malloc_zero)
707 malloc_junk = 1; 703 malloc_junk = 1;
708 704
709#ifdef MALLOC_STATS 705#ifdef MALLOC_STATS
710 if (malloc_stats && (atexit(malloc_exit) == -1)) 706 if (malloc_stats && (atexit(malloc_exit) == -1))
711 wrtwarning("atexit(2) failed. Will not be able to dump malloc stats on exit\n"); 707 wrtwarning("atexit(2) failed."
712#endif /* MALLOC_STATS */ 708 " Will not be able to dump malloc stats on exit");
709#endif /* MALLOC_STATS */
713 710
714 /* Allocate one page for the page directory. */ 711 /* Allocate one page for the page directory. */
715 page_dir = (struct pginfo **) MMAP(malloc_pagesize); 712 page_dir = (struct pginfo **)MMAP(malloc_pagesize);
716 713
717 if (page_dir == MAP_FAILED) { 714 if (page_dir == MAP_FAILED) {
718 wrterror("mmap(2) failed, check limits\n"); 715 wrterror("mmap(2) failed, check limits");
719 errno = ENOMEM; 716 errno = ENOMEM;
720 return; 717 return;
721 } 718 }
@@ -731,31 +728,25 @@ malloc_init(void)
731 malloc_started++; 728 malloc_started++;
732 729
733 /* Recalculate the cache size in bytes, and make sure it's nonzero. */ 730 /* Recalculate the cache size in bytes, and make sure it's nonzero. */
734
735 if (!malloc_cache) 731 if (!malloc_cache)
736 malloc_cache++; 732 malloc_cache++;
737
738 malloc_cache <<= malloc_pageshift; 733 malloc_cache <<= malloc_pageshift;
739
740 errno = save_errno; 734 errno = save_errno;
741} 735}
742 736
743/* 737/*
744 * Allocate a number of complete pages 738 * Allocate a number of complete pages
745 */ 739 */
746static void * 740static void *
747malloc_pages(size_t size) 741malloc_pages(size_t size)
748{ 742{
749 void *p, *delay_free = NULL; 743 void *p, *delay_free = NULL, *tp;
750 int i; 744 int i, m;
751 struct rlimit rl; 745 struct rlimit rl;
752 struct pginfo **pd; 746 struct pginfo **pd;
753 struct pdinfo *pi; 747 struct pdinfo *pi;
754 u_long pidx; 748 u_long pidx, index;
755 void *tp; 749 struct pgfree *pf;
756 struct pgfree *pf;
757 u_long index;
758 int m;
759 750
760 size = pageround(size) + malloc_guard; 751 size = pageround(size) + malloc_guard;
761 752
@@ -763,52 +754,54 @@ malloc_pages(size_t size)
763 /* Look for free pages before asking for more */ 754 /* Look for free pages before asking for more */
764 for (pf = free_list.next; pf; pf = pf->next) { 755 for (pf = free_list.next; pf; pf = pf->next) {
765 756
766#ifdef MALLOC_EXTRA_SANITY 757#ifdef MALLOC_EXTRA_SANITY
767 if (pf->size & malloc_pagemask) { 758 if (pf->size & malloc_pagemask) {
768 wrterror("(ES): junk length entry on free_list\n"); 759 wrterror("(ES): junk length entry on free_list");
769 errno = EFAULT; 760 errno = EFAULT;
770 return (NULL); 761 return (NULL);
771 } 762 }
772 if (!pf->size) { 763 if (!pf->size) {
773 wrterror("(ES): zero length entry on free_list\n"); 764 wrterror("(ES): zero length entry on free_list");
774 errno = EFAULT; 765 errno = EFAULT;
775 return (NULL); 766 return (NULL);
776 } 767 }
777 if (pf->page > (pf->page + pf->size)) { 768 if (pf->page > (pf->page + pf->size)) {
778 wrterror("(ES): sick entry on free_list\n"); 769 wrterror("(ES): sick entry on free_list");
779 errno = EFAULT; 770 errno = EFAULT;
780 return (NULL); 771 return (NULL);
781 } 772 }
782 if ((pi = pf->pdir) == NULL) { 773 if ((pi = pf->pdir) == NULL) {
783 wrterror("(ES): invalid page directory on free-list\n"); 774 wrterror("(ES): invalid page directory on free-list");
784 errno = EFAULT; 775 errno = EFAULT;
785 return (NULL); 776 return (NULL);
786 } 777 }
787 if ((pidx = PI_IDX(ptr2index(pf->page))) != PD_IDX(pi->dirnum)) { 778 if ((pidx = PI_IDX(ptr2index(pf->page))) != PD_IDX(pi->dirnum)) {
788 wrterror("(ES): directory index mismatch on free-list\n"); 779 wrterror("(ES): directory index mismatch on free-list");
789 errno = EFAULT; 780 errno = EFAULT;
790 return (NULL); 781 return (NULL);
791 } 782 }
792 pd = pi->base; 783 pd = pi->base;
793 if (pd[PI_OFF(ptr2index(pf->page))] != MALLOC_FREE) { 784 if (pd[PI_OFF(ptr2index(pf->page))] != MALLOC_FREE) {
794 wrterror("(ES): non-free first page on free-list\n"); 785 wrterror("(ES): non-free first page on free-list");
795 errno = EFAULT; 786 errno = EFAULT;
796 return (NULL); 787 return (NULL);
797 } 788 }
798 pidx = PI_IDX(ptr2index((pf->page) + (pf->size)) - 1); 789 pidx = PI_IDX(ptr2index((pf->page) + (pf->size)) - 1);
799 for (pi = pf->pdir; pi != NULL && PD_IDX(pi->dirnum) < pidx; pi = pi->next); 790 for (pi = pf->pdir; pi != NULL && PD_IDX(pi->dirnum) < pidx;
791 pi = pi->next)
792 ;
800 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { 793 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
801 wrterror("(ES): last page not referenced in page directory\n"); 794 wrterror("(ES): last page not referenced in page directory");
802 errno = EFAULT; 795 errno = EFAULT;
803 return (NULL); 796 return (NULL);
804 } 797 }
805 pd = pi->base; 798 pd = pi->base;
806 if (pd[PI_OFF(ptr2index((pf->page) + (pf->size)) - 1)] != MALLOC_FREE) { 799 if (pd[PI_OFF(ptr2index((pf->page) + (pf->size)) - 1)] != MALLOC_FREE) {
807 wrterror("(ES): non-free last page on free-list\n"); 800 wrterror("(ES): non-free last page on free-list");
808 errno = EFAULT; 801 errno = EFAULT;
809 return (NULL); 802 return (NULL);
810 } 803 }
811#endif /* MALLOC_EXTRA_SANITY */ 804#endif /* MALLOC_EXTRA_SANITY */
812 805
813 if (pf->size < size) 806 if (pf->size < size)
814 continue; 807 continue;
@@ -826,9 +819,11 @@ malloc_pages(size_t size)
826 pf->page = (char *) pf->page + size; 819 pf->page = (char *) pf->page + size;
827 pf->size -= size; 820 pf->size -= size;
828 pidx = PI_IDX(ptr2index(pf->page)); 821 pidx = PI_IDX(ptr2index(pf->page));
829 for (pi = pf->pdir; pi != NULL && PD_IDX(pi->dirnum) < pidx; pi = pi->next); 822 for (pi = pf->pdir; pi != NULL && PD_IDX(pi->dirnum) < pidx;
823 pi = pi->next)
824 ;
830 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { 825 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
831 wrterror("(ES): hole in directories\n"); 826 wrterror("(ES): hole in directories");
832 errno = EFAULT; 827 errno = EFAULT;
833 return (NULL); 828 return (NULL);
834 } 829 }
@@ -840,17 +835,17 @@ malloc_pages(size_t size)
840 835
841 size -= malloc_guard; 836 size -= malloc_guard;
842 837
843#ifdef MALLOC_EXTRA_SANITY 838#ifdef MALLOC_EXTRA_SANITY
844 if (p != NULL && pi != NULL) { 839 if (p != NULL && pi != NULL) {
845 pidx = PD_IDX(pi->dirnum); 840 pidx = PD_IDX(pi->dirnum);
846 pd = pi->base; 841 pd = pi->base;
847 } 842 }
848 if (p != NULL && pd[PI_OFF(ptr2index(p))] != MALLOC_FREE) { 843 if (p != NULL && pd[PI_OFF(ptr2index(p))] != MALLOC_FREE) {
849 wrterror("(ES): allocated non-free page on free-list\n"); 844 wrterror("(ES): allocated non-free page on free-list");
850 errno = EFAULT; 845 errno = EFAULT;
851 return (NULL); 846 return (NULL);
852 } 847 }
853#endif /* MALLOC_EXTRA_SANITY */ 848#endif /* MALLOC_EXTRA_SANITY */
854 849
855 if (p != NULL && (malloc_guard || malloc_freeprot)) 850 if (p != NULL && (malloc_guard || malloc_freeprot))
856 mprotect(p, size, PROT_READ | PROT_WRITE); 851 mprotect(p, size, PROT_READ | PROT_WRITE);
@@ -862,17 +857,16 @@ malloc_pages(size_t size)
862 p = map_pages(size); 857 p = map_pages(size);
863 858
864 if (p != NULL) { 859 if (p != NULL) {
865
866 index = ptr2index(p); 860 index = ptr2index(p);
867 pidx = PI_IDX(index); 861 pidx = PI_IDX(index);
868 pdir_lookup(index, &pi); 862 pdir_lookup(index, &pi);
869#ifdef MALLOC_EXTRA_SANITY 863#ifdef MALLOC_EXTRA_SANITY
870 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { 864 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
871 wrterror("(ES): mapped pages not found in directory\n"); 865 wrterror("(ES): mapped pages not found in directory");
872 errno = EFAULT; 866 errno = EFAULT;
873 return (NULL); 867 return (NULL);
874 } 868 }
875#endif /* MALLOC_EXTRA_SANITY */ 869#endif /* MALLOC_EXTRA_SANITY */
876 if (pi != last_dir) { 870 if (pi != last_dir) {
877 prev_dir = last_dir; 871 prev_dir = last_dir;
878 last_dir = pi; 872 last_dir = pi;
@@ -883,13 +877,13 @@ malloc_pages(size_t size)
883 if (!PI_OFF(index + i)) { 877 if (!PI_OFF(index + i)) {
884 pidx++; 878 pidx++;
885 pi = pi->next; 879 pi = pi->next;
886#ifdef MALLOC_EXTRA_SANITY 880#ifdef MALLOC_EXTRA_SANITY
887 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { 881 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
888 wrterror("(ES): hole in mapped pages directory\n"); 882 wrterror("(ES): hole in mapped pages directory");
889 errno = EFAULT; 883 errno = EFAULT;
890 return (NULL); 884 return (NULL);
891 } 885 }
892#endif /* MALLOC_EXTRA_SANITY */ 886#endif /* MALLOC_EXTRA_SANITY */
893 pd = pi->base; 887 pd = pi->base;
894 } 888 }
895 pd[PI_OFF(index + i)] = MALLOC_FOLLOW; 889 pd[PI_OFF(index + i)] = MALLOC_FOLLOW;
@@ -898,13 +892,13 @@ malloc_pages(size_t size)
898 if (!PI_OFF(index + i)) { 892 if (!PI_OFF(index + i)) {
899 pidx++; 893 pidx++;
900 pi = pi->next; 894 pi = pi->next;
901#ifdef MALLOC_EXTRA_SANITY 895#ifdef MALLOC_EXTRA_SANITY
902 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { 896 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
903 wrterror("(ES): hole in mapped pages directory\n"); 897 wrterror("(ES): hole in mapped pages directory");
904 errno = EFAULT; 898 errno = EFAULT;
905 return (NULL); 899 return (NULL);
906 } 900 }
907#endif /* MALLOC_EXTRA_SANITY */ 901#endif /* MALLOC_EXTRA_SANITY */
908 pd = pi->base; 902 pd = pi->base;
909 } 903 }
910 pd[PI_OFF(index + i)] = MALLOC_FIRST; 904 pd[PI_OFF(index + i)] = MALLOC_FIRST;
@@ -931,12 +925,11 @@ malloc_pages(size_t size)
931static __inline__ int 925static __inline__ int
932malloc_make_chunks(int bits) 926malloc_make_chunks(int bits)
933{ 927{
934 struct pginfo *bp; 928 struct pginfo *bp, **pd;
935 struct pginfo **pd; 929 struct pdinfo *pi;
936 struct pdinfo *pi; 930 u_long pidx;
937 u_long pidx; 931 void *pp;
938 void *pp; 932 int i, k, l;
939 int i, k, l;
940 933
941 /* Allocate a new bucket */ 934 /* Allocate a new bucket */
942 pp = malloc_pages((size_t) malloc_pagesize); 935 pp = malloc_pages((size_t) malloc_pagesize);
@@ -946,15 +939,16 @@ malloc_make_chunks(int bits)
946 /* Find length of admin structure */ 939 /* Find length of admin structure */
947 l = sizeof *bp - sizeof(u_long); 940 l = sizeof *bp - sizeof(u_long);
948 l += sizeof(u_long) * 941 l += sizeof(u_long) *
949 (((malloc_pagesize >> bits) + MALLOC_BITS - 1) / MALLOC_BITS); 942 (((malloc_pagesize >> bits) + MALLOC_BITS - 1) / MALLOC_BITS);
950 943
951 /* Don't waste more than two chunks on this */ 944 /* Don't waste more than two chunks on this */
945
952 /* 946 /*
953 * If we are to allocate a memory protected page for the malloc(0) 947 * If we are to allocate a memory protected page for the malloc(0)
954 * case (when bits=0), it must be from a different page than the 948 * case (when bits=0), it must be from a different page than the
955 * pginfo page. 949 * pginfo page.
956 * --> Treat it like the big chunk alloc, get a second data page. 950 * --> Treat it like the big chunk alloc, get a second data page.
957 */ 951 */
958 if (bits != 0 && (1UL << (bits)) <= l + l) { 952 if (bits != 0 && (1UL << (bits)) <= l + l) {
959 bp = (struct pginfo *) pp; 953 bp = (struct pginfo *) pp;
960 } else { 954 } else {
@@ -967,7 +961,6 @@ malloc_make_chunks(int bits)
967 961
968 /* memory protect the page allocated in the malloc(0) case */ 962 /* memory protect the page allocated in the malloc(0) case */
969 if (bits == 0) { 963 if (bits == 0) {
970
971 bp->size = 0; 964 bp->size = 0;
972 bp->shift = 1; 965 bp->shift = 1;
973 i = malloc_minsize - 1; 966 i = malloc_minsize - 1;
@@ -1013,13 +1006,13 @@ malloc_make_chunks(int bits)
1013 1006
1014 pidx = PI_IDX(ptr2index(pp)); 1007 pidx = PI_IDX(ptr2index(pp));
1015 pdir_lookup(ptr2index(pp), &pi); 1008 pdir_lookup(ptr2index(pp), &pi);
1016#ifdef MALLOC_EXTRA_SANITY 1009#ifdef MALLOC_EXTRA_SANITY
1017 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { 1010 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
1018 wrterror("(ES): mapped pages not found in directory\n"); 1011 wrterror("(ES): mapped pages not found in directory");
1019 errno = EFAULT; 1012 errno = EFAULT;
1020 return (0); 1013 return (0);
1021 } 1014 }
1022#endif /* MALLOC_EXTRA_SANITY */ 1015#endif /* MALLOC_EXTRA_SANITY */
1023 if (pi != last_dir) { 1016 if (pi != last_dir) {
1024 prev_dir = last_dir; 1017 prev_dir = last_dir;
1025 last_dir = pi; 1018 last_dir = pi;
@@ -1031,21 +1024,18 @@ malloc_make_chunks(int bits)
1031 page_dir[bits] = bp; 1024 page_dir[bits] = bp;
1032 1025
1033 /* MALLOC_UNLOCK */ 1026 /* MALLOC_UNLOCK */
1034
1035 return (1); 1027 return (1);
1036} 1028}
1037 1029
1038/* 1030/*
1039 * Allocate a fragment 1031 * Allocate a fragment
1040 */ 1032 */
1041static void * 1033static void *
1042malloc_bytes(size_t size) 1034malloc_bytes(size_t size)
1043{ 1035{
1044 int i, j; 1036 int i, j, k;
1045 u_long u; 1037 u_long u, *lp;
1046 struct pginfo *bp; 1038 struct pginfo *bp;
1047 int k;
1048 u_long *lp;
1049 1039
1050 /* Don't bother with anything less than this */ 1040 /* Don't bother with anything less than this */
1051 /* unless we have a malloc(0) requests */ 1041 /* unless we have a malloc(0) requests */
@@ -1090,13 +1080,13 @@ malloc_bytes(size_t size)
1090 u = 1; 1080 u = 1;
1091 k = 0; 1081 k = 0;
1092 } 1082 }
1093#ifdef MALLOC_EXTRA_SANITY 1083#ifdef MALLOC_EXTRA_SANITY
1094 if (lp - bp->bits > (bp->total - 1) / MALLOC_BITS) { 1084 if (lp - bp->bits > (bp->total - 1) / MALLOC_BITS) {
1095 wrterror("chunk overflow\n"); 1085 wrterror("chunk overflow");
1096 errno = EFAULT; 1086 errno = EFAULT;
1097 return (NULL); 1087 return (NULL);
1098 } 1088 }
1099#endif /* MALLOC_EXTRA_SANITY */ 1089#endif /* MALLOC_EXTRA_SANITY */
1100 if (*lp & u) 1090 if (*lp & u)
1101 i--; 1091 i--;
1102 } 1092 }
@@ -1128,11 +1118,11 @@ malloc_bytes(size_t size)
1128/* 1118/*
1129 * Allocate a piece of memory 1119 * Allocate a piece of memory
1130 */ 1120 */
1131static void * 1121static void *
1132imalloc(size_t size) 1122imalloc(size_t size)
1133{ 1123{
1134 void *result; 1124 void *result;
1135 int ptralloc = 0; 1125 int ptralloc = 0;
1136 1126
1137 if (!malloc_started) 1127 if (!malloc_started)
1138 malloc_init(); 1128 malloc_init();
@@ -1153,7 +1143,7 @@ imalloc(size_t size)
1153 result = malloc_pages(size); 1143 result = malloc_pages(size);
1154 1144
1155 if (malloc_abort == 1 && result == NULL) 1145 if (malloc_abort == 1 && result == NULL)
1156 wrterror("allocation failed\n"); 1146 wrterror("allocation failed");
1157 1147
1158 if (malloc_zero && result != NULL) 1148 if (malloc_zero && result != NULL)
1159 memset(result, 0, size); 1149 memset(result, 0, size);
@@ -1166,53 +1156,52 @@ imalloc(size_t size)
1166/* 1156/*
1167 * Change the size of an allocation. 1157 * Change the size of an allocation.
1168 */ 1158 */
1169static void * 1159static void *
1170irealloc(void *ptr, size_t size) 1160irealloc(void *ptr, size_t size)
1171{ 1161{
1172 void *p; 1162 void *p;
1173 u_long osize, index, i; 1163 u_long osize, index, i;
1174 struct pginfo **mp; 1164 struct pginfo **mp;
1175 struct pginfo **pd; 1165 struct pginfo **pd;
1176 struct pdinfo *pi; 1166 struct pdinfo *pi;
1177 u_long pidx; 1167 u_long pidx;
1178 1168
1179 if (suicide) 1169 if (suicide)
1180 abort(); 1170 abort();
1181 1171
1182 if (!malloc_started) { 1172 if (!malloc_started) {
1183 wrtwarning("malloc() has never been called\n"); 1173 wrtwarning("malloc() has never been called");
1184 return (NULL); 1174 return (NULL);
1185 } 1175 }
1186 if (malloc_ptrguard && PTR_ALIGNED(ptr)) { 1176 if (malloc_ptrguard && PTR_ALIGNED(ptr)) {
1187 if (size <= PTR_SIZE) { 1177 if (size <= PTR_SIZE)
1188 return (ptr); 1178 return (ptr);
1189 } else { 1179
1190 p = imalloc(size); 1180 p = imalloc(size);
1191 if (p) 1181 if (p)
1192 memcpy(p, ptr, PTR_SIZE); 1182 memcpy(p, ptr, PTR_SIZE);
1193 ifree(ptr); 1183 ifree(ptr);
1194 return (p); 1184 return (p);
1195 }
1196 } 1185 }
1197 index = ptr2index(ptr); 1186 index = ptr2index(ptr);
1198 1187
1199 if (index < malloc_pageshift) { 1188 if (index < malloc_pageshift) {
1200 wrtwarning("junk pointer, too low to make sense\n"); 1189 wrtwarning("junk pointer, too low to make sense");
1201 return (NULL); 1190 return (NULL);
1202 } 1191 }
1203 if (index > last_index) { 1192 if (index > last_index) {
1204 wrtwarning("junk pointer, too high to make sense\n"); 1193 wrtwarning("junk pointer, too high to make sense");
1205 return (NULL); 1194 return (NULL);
1206 } 1195 }
1207 pidx = PI_IDX(index); 1196 pidx = PI_IDX(index);
1208 pdir_lookup(index, &pi); 1197 pdir_lookup(index, &pi);
1209#ifdef MALLOC_EXTRA_SANITY 1198#ifdef MALLOC_EXTRA_SANITY
1210 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { 1199 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
1211 wrterror("(ES): mapped pages not found in directory\n"); 1200 wrterror("(ES): mapped pages not found in directory");
1212 errno = EFAULT; 1201 errno = EFAULT;
1213 return (NULL); 1202 return (NULL);
1214 } 1203 }
1215#endif /* MALLOC_EXTRA_SANITY */ 1204#endif /* MALLOC_EXTRA_SANITY */
1216 if (pi != last_dir) { 1205 if (pi != last_dir) {
1217 prev_dir = last_dir; 1206 prev_dir = last_dir;
1218 last_dir = pi; 1207 last_dir = pi;
@@ -1224,7 +1213,7 @@ irealloc(void *ptr, size_t size)
1224 1213
1225 /* Check the pointer */ 1214 /* Check the pointer */
1226 if ((u_long) ptr & malloc_pagemask) { 1215 if ((u_long) ptr & malloc_pagemask) {
1227 wrtwarning("modified (page-) pointer\n"); 1216 wrtwarning("modified (page-) pointer");
1228 return (NULL); 1217 return (NULL);
1229 } 1218 }
1230 /* Find the size in bytes */ 1219 /* Find the size in bytes */
@@ -1237,7 +1226,7 @@ irealloc(void *ptr, size_t size)
1237 pd = pi->base; 1226 pd = pi->base;
1238 } 1227 }
1239 for (osize = malloc_pagesize; 1228 for (osize = malloc_pagesize;
1240 pi != NULL && pd[PI_OFF(i)] == MALLOC_FOLLOW;) { 1229 pi != NULL && pd[PI_OFF(i)] == MALLOC_FOLLOW;) {
1241 osize += malloc_pagesize; 1230 osize += malloc_pagesize;
1242 if (!PI_OFF(++i)) { 1231 if (!PI_OFF(++i)) {
1243 pi = pi->next; 1232 pi = pi->next;
@@ -1248,19 +1237,17 @@ irealloc(void *ptr, size_t size)
1248 } 1237 }
1249 } 1238 }
1250 1239
1251 if (!malloc_realloc && /* Unless we have to, */ 1240 if (!malloc_realloc && size <= osize &&
1252 size <= osize && /* .. or are too small, */ 1241 size > osize - malloc_pagesize) {
1253 size > (osize - malloc_pagesize)) { /* .. or can free a
1254 * page, */
1255 if (malloc_junk) 1242 if (malloc_junk)
1256 memset((char *) ptr + size, SOME_JUNK, osize - size); 1243 memset((char *)ptr + size, SOME_JUNK, osize - size);
1257 return (ptr); /* ..don't do anything else. */ 1244 return (ptr); /* ..don't do anything else. */
1258 } 1245 }
1259 } else if (*mp >= MALLOC_MAGIC) { /* Chunk allocation */ 1246 } else if (*mp >= MALLOC_MAGIC) { /* Chunk allocation */
1260 1247
1261 /* Check the pointer for sane values */ 1248 /* Check the pointer for sane values */
1262 if ((u_long) ptr & ((1UL << ((*mp)->shift)) - 1)) { 1249 if ((u_long) ptr & ((1UL << ((*mp)->shift)) - 1)) {
1263 wrtwarning("modified (chunk-) pointer\n"); 1250 wrtwarning("modified (chunk-) pointer");
1264 return (NULL); 1251 return (NULL);
1265 } 1252 }
1266 /* Find the chunk index in the page */ 1253 /* Find the chunk index in the page */
@@ -1268,22 +1255,19 @@ irealloc(void *ptr, size_t size)
1268 1255
1269 /* Verify that it isn't a free chunk already */ 1256 /* Verify that it isn't a free chunk already */
1270 if ((*mp)->bits[i / MALLOC_BITS] & (1UL << (i % MALLOC_BITS))) { 1257 if ((*mp)->bits[i / MALLOC_BITS] & (1UL << (i % MALLOC_BITS))) {
1271 wrtwarning("chunk is already free\n"); 1258 wrtwarning("chunk is already free");
1272 return (NULL); 1259 return (NULL);
1273 } 1260 }
1274 osize = (*mp)->size; 1261 osize = (*mp)->size;
1275 1262
1276 if (!malloc_realloc && /* Unless we have to, */ 1263 if (!malloc_realloc && size <= osize &&
1277 size <= osize && /* ..or are too small, */ 1264 (size > osize / 2 || osize == malloc_minsize)) {
1278 (size > osize / 2 || /* ..or could use a smaller
1279 * size, */
1280 osize == malloc_minsize)) { /* ..(if there is one) */
1281 if (malloc_junk) 1265 if (malloc_junk)
1282 memset((char *) ptr + size, SOME_JUNK, osize - size); 1266 memset((char *) ptr + size, SOME_JUNK, osize - size);
1283 return (ptr); /* ..don't do anything else. */ 1267 return (ptr); /* ..don't do anything else. */
1284 } 1268 }
1285 } else { 1269 } else {
1286 wrtwarning("irealloc: pointer to wrong page\n"); 1270 wrtwarning("irealloc: pointer to wrong page");
1287 return (NULL); 1271 return (NULL);
1288 } 1272 }
1289 1273
@@ -1306,39 +1290,37 @@ irealloc(void *ptr, size_t size)
1306/* 1290/*
1307 * Free a sequence of pages 1291 * Free a sequence of pages
1308 */ 1292 */
1309
1310static __inline__ void 1293static __inline__ void
1311free_pages(void *ptr, u_long index, struct pginfo * info) 1294free_pages(void *ptr, u_long index, struct pginfo * info)
1312{ 1295{
1313 u_long i, l, cachesize = 0; 1296 u_long i, l, cachesize = 0, pidx, lidx;
1314 struct pginfo **pd; 1297 struct pginfo **pd;
1315 struct pdinfo *pi, *spi; 1298 struct pdinfo *pi, *spi;
1316 u_long pidx, lidx; 1299 struct pgfree *pf, *pt = NULL;
1317 struct pgfree *pf, *pt = NULL; 1300 void *tail;
1318 void *tail;
1319 1301
1320 if (info == MALLOC_FREE) { 1302 if (info == MALLOC_FREE) {
1321 wrtwarning("page is already free\n"); 1303 wrtwarning("page is already free");
1322 return; 1304 return;
1323 } 1305 }
1324 if (info != MALLOC_FIRST) { 1306 if (info != MALLOC_FIRST) {
1325 wrtwarning("free_pages: pointer to wrong page\n"); 1307 wrtwarning("free_pages: pointer to wrong page");
1326 return; 1308 return;
1327 } 1309 }
1328 if ((u_long) ptr & malloc_pagemask) { 1310 if ((u_long) ptr & malloc_pagemask) {
1329 wrtwarning("modified (page-) pointer\n"); 1311 wrtwarning("modified (page-) pointer");
1330 return; 1312 return;
1331 } 1313 }
1332 /* Count how many pages and mark them free at the same time */ 1314 /* Count how many pages and mark them free at the same time */
1333 pidx = PI_IDX(index); 1315 pidx = PI_IDX(index);
1334 pdir_lookup(index, &pi); 1316 pdir_lookup(index, &pi);
1335#ifdef MALLOC_EXTRA_SANITY 1317#ifdef MALLOC_EXTRA_SANITY
1336 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { 1318 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
1337 wrterror("(ES): mapped pages not found in directory\n"); 1319 wrterror("(ES): mapped pages not found in directory");
1338 errno = EFAULT; 1320 errno = EFAULT;
1339 return; 1321 return;
1340 } 1322 }
1341#endif /* MALLOC_EXTRA_SANITY */ 1323#endif /* MALLOC_EXTRA_SANITY */
1342 1324
1343 spi = pi; /* Save page index for start of region. */ 1325 spi = pi; /* Save page index for start of region. */
1344 1326
@@ -1356,7 +1338,8 @@ free_pages(void *ptr, u_long index, struct pginfo * info)
1356 pd[PI_OFF(index + i)] = MALLOC_FREE; 1338 pd[PI_OFF(index + i)] = MALLOC_FREE;
1357 i++; 1339 i++;
1358 if (!PI_OFF(index + i)) { 1340 if (!PI_OFF(index + i)) {
1359 if ((pi = pi->next) == NULL || PD_IDX(pi->dirnum) != PI_IDX(index + i)) 1341 if ((pi = pi->next) == NULL ||
1342 PD_IDX(pi->dirnum) != PI_IDX(index + i))
1360 pi = NULL; 1343 pi = NULL;
1361 else 1344 else
1362 pd = pi->base; 1345 pd = pi->base;
@@ -1371,22 +1354,20 @@ free_pages(void *ptr, u_long index, struct pginfo * info)
1371 malloc_used -= l; 1354 malloc_used -= l;
1372 malloc_guarded -= malloc_guard; 1355 malloc_guarded -= malloc_guard;
1373 if (malloc_guard) { 1356 if (malloc_guard) {
1374#ifdef MALLOC_EXTRA_SANITY 1357#ifdef MALLOC_EXTRA_SANITY
1375 if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(index + i)) { 1358 if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(index + i)) {
1376 wrterror("(ES): hole in mapped pages directory\n"); 1359 wrterror("(ES): hole in mapped pages directory");
1377 errno = EFAULT; 1360 errno = EFAULT;
1378 return; 1361 return;
1379 } 1362 }
1380#endif /* MALLOC_EXTRA_SANITY */ 1363#endif /* MALLOC_EXTRA_SANITY */
1381 pd[PI_OFF(index + i)] = MALLOC_FREE; 1364 pd[PI_OFF(index + i)] = MALLOC_FREE;
1382 l += malloc_guard; 1365 l += malloc_guard;
1383 } 1366 }
1384 tail = (char *) ptr + l; 1367 tail = (char *) ptr + l;
1385 1368
1386#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE))
1387 if (malloc_hint) 1369 if (malloc_hint)
1388 madvise(ptr, l, MADV_FREE); 1370 madvise(ptr, l, MADV_FREE);
1389#endif
1390 1371
1391 if (malloc_freeprot) 1372 if (malloc_freeprot)
1392 mprotect(ptr, l, PROT_NONE); 1373 mprotect(ptr, l, PROT_NONE);
@@ -1399,16 +1380,13 @@ free_pages(void *ptr, u_long index, struct pginfo * info)
1399 px->size = l; 1380 px->size = l;
1400 1381
1401 if (free_list.next == NULL) { 1382 if (free_list.next == NULL) {
1402
1403 /* Nothing on free list, put this at head. */ 1383 /* Nothing on free list, put this at head. */
1404 px->next = NULL; 1384 px->next = NULL;
1405 px->prev = &free_list; 1385 px->prev = &free_list;
1406 free_list.next = px; 1386 free_list.next = px;
1407 pf = px; 1387 pf = px;
1408 px = NULL; 1388 px = NULL;
1409
1410 } else { 1389 } else {
1411
1412 /* 1390 /*
1413 * Find the right spot, leave pf pointing to the modified 1391 * Find the right spot, leave pf pointing to the modified
1414 * entry. 1392 * entry.
@@ -1416,8 +1394,8 @@ free_pages(void *ptr, u_long index, struct pginfo * info)
1416 1394
1417 /* Race ahead here, while calculating cache size. */ 1395 /* Race ahead here, while calculating cache size. */
1418 for (pf = free_list.next; 1396 for (pf = free_list.next;
1419 (pf->page + pf->size) < ptr && pf->next != NULL; 1397 pf->page + pf->size < ptr && pf->next != NULL;
1420 pf = pf->next) 1398 pf = pf->next)
1421 cachesize += pf->size; 1399 cachesize += pf->size;
1422 1400
1423 /* Finish cache size calculation. */ 1401 /* Finish cache size calculation. */
@@ -1439,7 +1417,8 @@ free_pages(void *ptr, u_long index, struct pginfo * info)
1439 /* Append to the previous entry. */ 1417 /* Append to the previous entry. */
1440 cachesize -= pf->size; 1418 cachesize -= pf->size;
1441 pf->size += l; 1419 pf->size += l;
1442 if (pf->next != NULL && (pf->page + pf->size) == pf->next->page) { 1420 if (pf->next != NULL &&
1421 pf->page + pf->size == pf->next->page) {
1443 /* And collapse the next too. */ 1422 /* And collapse the next too. */
1444 pt = pf->next; 1423 pt = pf->next;
1445 pf->size += pt->size; 1424 pf->size += pt->size;
@@ -1461,7 +1440,7 @@ free_pages(void *ptr, u_long index, struct pginfo * info)
1461 pf = px; 1440 pf = px;
1462 px = NULL; 1441 px = NULL;
1463 } else { 1442 } else {
1464 wrterror("freelist is destroyed\n"); 1443 wrterror("freelist is destroyed");
1465 errno = EFAULT; 1444 errno = EFAULT;
1466 return; 1445 return;
1467 } 1446 }
@@ -1471,6 +1450,7 @@ free_pages(void *ptr, u_long index, struct pginfo * info)
1471 prev_dir = last_dir; 1450 prev_dir = last_dir;
1472 last_dir = pf->pdir; 1451 last_dir = pf->pdir;
1473 } 1452 }
1453
1474 /* Return something to OS ? */ 1454 /* Return something to OS ? */
1475 if (pf->size > (malloc_cache - cachesize)) { 1455 if (pf->size > (malloc_cache - cachesize)) {
1476 1456
@@ -1479,7 +1459,7 @@ free_pages(void *ptr, u_long index, struct pginfo * info)
1479 * the pf will always have at least one page afterwards. 1459 * the pf will always have at least one page afterwards.
1480 */ 1460 */
1481 if (munmap((char *) pf->page + (malloc_cache - cachesize), 1461 if (munmap((char *) pf->page + (malloc_cache - cachesize),
1482 pf->size - (malloc_cache - cachesize)) != 0) 1462 pf->size - (malloc_cache - cachesize)) != 0)
1483 goto not_return; 1463 goto not_return;
1484 tail = pf->page + pf->size; 1464 tail = pf->page + pf->size;
1485 lidx = ptr2index(tail) - 1; 1465 lidx = ptr2index(tail) - 1;
@@ -1491,7 +1471,9 @@ free_pages(void *ptr, u_long index, struct pginfo * info)
1491 if (prev_dir != NULL && PD_IDX(prev_dir->dirnum) >= pidx) 1471 if (prev_dir != NULL && PD_IDX(prev_dir->dirnum) >= pidx)
1492 prev_dir = NULL; /* Will be wiped out below ! */ 1472 prev_dir = NULL; /* Will be wiped out below ! */
1493 1473
1494 for (pi = pf->pdir; pi != NULL && PD_IDX(pi->dirnum) < pidx; pi = pi->next); 1474 for (pi = pf->pdir; pi != NULL && PD_IDX(pi->dirnum) < pidx;
1475 pi = pi->next)
1476 ;
1495 1477
1496 spi = pi; 1478 spi = pi;
1497 if (pi != NULL && PD_IDX(pi->dirnum) == pidx) { 1479 if (pi != NULL && PD_IDX(pi->dirnum) == pidx) {
@@ -1500,19 +1482,19 @@ free_pages(void *ptr, u_long index, struct pginfo * info)
1500 for (i = index; i <= lidx;) { 1482 for (i = index; i <= lidx;) {
1501 if (pd[PI_OFF(i)] != MALLOC_NOT_MINE) { 1483 if (pd[PI_OFF(i)] != MALLOC_NOT_MINE) {
1502 pd[PI_OFF(i)] = MALLOC_NOT_MINE; 1484 pd[PI_OFF(i)] = MALLOC_NOT_MINE;
1503#ifdef MALLOC_EXTRA_SANITY 1485#ifdef MALLOC_EXTRA_SANITY
1504 if (!PD_OFF(pi->dirnum)) { 1486 if (!PD_OFF(pi->dirnum)) {
1505 wrterror("(ES): pages directory underflow\n"); 1487 wrterror("(ES): pages directory underflow");
1506 errno = EFAULT; 1488 errno = EFAULT;
1507 return; 1489 return;
1508 } 1490 }
1509#endif /* MALLOC_EXTRA_SANITY */ 1491#endif /* MALLOC_EXTRA_SANITY */
1510 pi->dirnum--; 1492 pi->dirnum--;
1511 } 1493 }
1512#ifdef MALLOC_EXTRA_SANITY 1494#ifdef MALLOC_EXTRA_SANITY
1513 else 1495 else
1514 wrtwarning("(ES): page already unmapped\n"); 1496 wrtwarning("(ES): page already unmapped");
1515#endif /* MALLOC_EXTRA_SANITY */ 1497#endif /* MALLOC_EXTRA_SANITY */
1516 i++; 1498 i++;
1517 if (!PI_OFF(i)) { 1499 if (!PI_OFF(i)) {
1518 /* 1500 /*
@@ -1521,8 +1503,7 @@ free_pages(void *ptr, u_long index, struct pginfo * info)
1521 */ 1503 */
1522 if (!PD_OFF(pi->dirnum)) { 1504 if (!PD_OFF(pi->dirnum)) {
1523 /* Remove from list. */ 1505 /* Remove from list. */
1524 if (spi == pi) /* Update spi only if 1506 if (spi == pi)
1525 * first. */
1526 spi = pi->prev; 1507 spi = pi->prev;
1527 if (pi->prev != NULL) 1508 if (pi->prev != NULL)
1528 pi->prev->next = pi->next; 1509 pi->prev->next = pi->next;
@@ -1532,7 +1513,8 @@ free_pages(void *ptr, u_long index, struct pginfo * info)
1532 munmap(pd, malloc_pagesize); 1513 munmap(pd, malloc_pagesize);
1533 } else 1514 } else
1534 pi = pi->next; 1515 pi = pi->next;
1535 if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(i)) 1516 if (pi == NULL ||
1517 PD_IDX(pi->dirnum) != PI_IDX(i))
1536 break; 1518 break;
1537 pd = pi->base; 1519 pd = pi->base;
1538 } 1520 }
@@ -1555,6 +1537,7 @@ free_pages(void *ptr, u_long index, struct pginfo * info)
1555 last_index = index - 1; 1537 last_index = index - 1;
1556 malloc_brk = index2ptr(index); 1538 malloc_brk = index2ptr(index);
1557 } 1539 }
1540
1558 /* XXX: We could realloc/shrink the pagedir here I guess. */ 1541 /* XXX: We could realloc/shrink the pagedir here I guess. */
1559 if (pf->size == 0) { /* Remove from free-list as well. */ 1542 if (pf->size == 0) { /* Remove from free-list as well. */
1560 if (px) 1543 if (px)
@@ -1567,21 +1550,24 @@ free_pages(void *ptr, u_long index, struct pginfo * info)
1567 } else { 1550 } else {
1568 pd = spi->base; 1551 pd = spi->base;
1569 if (PD_IDX(spi->dirnum) < pidx) 1552 if (PD_IDX(spi->dirnum) < pidx)
1570 index = ((PD_IDX(spi->dirnum) + 1) * pdi_mod) - 1; 1553 index =
1571 for (pi = spi, i = index; pd[PI_OFF(i)] == MALLOC_NOT_MINE; i--) 1554 ((PD_IDX(spi->dirnum) + 1) *
1572#ifdef MALLOC_EXTRA_SANITY 1555 pdi_mod) - 1;
1573 if (!PI_OFF(i)) { /* Should never enter 1556 for (pi = spi, i = index;
1574 * here. */ 1557 pd[PI_OFF(i)] == MALLOC_NOT_MINE;
1558 i--)
1559#ifdef MALLOC_EXTRA_SANITY
1560 if (!PI_OFF(i)) {
1575 pi = pi->prev; 1561 pi = pi->prev;
1576 if (pi == NULL || i == 0) 1562 if (pi == NULL || i == 0)
1577 break; 1563 break;
1578 pd = pi->base; 1564 pd = pi->base;
1579 i = (PD_IDX(pi->dirnum) + 1) * pdi_mod; 1565 i = (PD_IDX(pi->dirnum) + 1) * pdi_mod;
1580 } 1566 }
1581#else /* !MALLOC_EXTRA_SANITY */ 1567#else /* !MALLOC_EXTRA_SANITY */
1582 { 1568 {
1583 } 1569 }
1584#endif /* MALLOC_EXTRA_SANITY */ 1570#endif /* MALLOC_EXTRA_SANITY */
1585 malloc_brk = index2ptr(i + 1); 1571 malloc_brk = index2ptr(i + 1);
1586 } 1572 }
1587 last_index = i; 1573 last_index = i;
@@ -1610,22 +1596,21 @@ not_return:
1610static __inline__ void 1596static __inline__ void
1611free_bytes(void *ptr, int index, struct pginfo * info) 1597free_bytes(void *ptr, int index, struct pginfo * info)
1612{ 1598{
1613 int i; 1599 struct pginfo **mp, **pd;
1614 struct pginfo **mp; 1600 struct pdinfo *pi;
1615 struct pginfo **pd; 1601 u_long pidx;
1616 struct pdinfo *pi; 1602 void *vp;
1617 u_long pidx; 1603 int i;
1618 void *vp;
1619 1604
1620 /* Find the chunk number on the page */ 1605 /* Find the chunk number on the page */
1621 i = ((u_long) ptr & malloc_pagemask) >> info->shift; 1606 i = ((u_long) ptr & malloc_pagemask) >> info->shift;
1622 1607
1623 if ((u_long) ptr & ((1UL << (info->shift)) - 1)) { 1608 if ((u_long) ptr & ((1UL << (info->shift)) - 1)) {
1624 wrtwarning("modified (chunk-) pointer\n"); 1609 wrtwarning("modified (chunk-) pointer");
1625 return; 1610 return;
1626 } 1611 }
1627 if (info->bits[i / MALLOC_BITS] & (1UL << (i % MALLOC_BITS))) { 1612 if (info->bits[i / MALLOC_BITS] & (1UL << (i % MALLOC_BITS))) {
1628 wrtwarning("chunk is already free\n"); 1613 wrtwarning("chunk is already free");
1629 return; 1614 return;
1630 } 1615 }
1631 if (malloc_junk && info->size != 0) 1616 if (malloc_junk && info->size != 0)
@@ -1640,12 +1625,11 @@ free_bytes(void *ptr, int index, struct pginfo * info)
1640 mp = page_dir; 1625 mp = page_dir;
1641 1626
1642 if (info->free == 1) { 1627 if (info->free == 1) {
1643
1644 /* Page became non-full */ 1628 /* Page became non-full */
1645 1629
1646 /* Insert in address order */ 1630 /* Insert in address order */
1647 while (*mp != NULL && (*mp)->next != NULL && 1631 while (*mp != NULL && (*mp)->next != NULL &&
1648 (*mp)->next->page < info->page) 1632 (*mp)->next->page < info->page)
1649 mp = &(*mp)->next; 1633 mp = &(*mp)->next;
1650 info->next = *mp; 1634 info->next = *mp;
1651 *mp = info; 1635 *mp = info;
@@ -1657,26 +1641,26 @@ free_bytes(void *ptr, int index, struct pginfo * info)
1657 /* Find & remove this page in the queue */ 1641 /* Find & remove this page in the queue */
1658 while (*mp != info) { 1642 while (*mp != info) {
1659 mp = &((*mp)->next); 1643 mp = &((*mp)->next);
1660#ifdef MALLOC_EXTRA_SANITY 1644#ifdef MALLOC_EXTRA_SANITY
1661 if (!*mp) { 1645 if (!*mp) {
1662 wrterror("(ES): Not on queue\n"); 1646 wrterror("(ES): Not on queue");
1663 errno = EFAULT; 1647 errno = EFAULT;
1664 return; 1648 return;
1665 } 1649 }
1666#endif /* MALLOC_EXTRA_SANITY */ 1650#endif /* MALLOC_EXTRA_SANITY */
1667 } 1651 }
1668 *mp = info->next; 1652 *mp = info->next;
1669 1653
1670 /* Free the page & the info structure if need be */ 1654 /* Free the page & the info structure if need be */
1671 pidx = PI_IDX(ptr2index(info->page)); 1655 pidx = PI_IDX(ptr2index(info->page));
1672 pdir_lookup(ptr2index(info->page), &pi); 1656 pdir_lookup(ptr2index(info->page), &pi);
1673#ifdef MALLOC_EXTRA_SANITY 1657#ifdef MALLOC_EXTRA_SANITY
1674 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { 1658 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
1675 wrterror("(ES): mapped pages not found in directory\n"); 1659 wrterror("(ES): mapped pages not found in directory");
1676 errno = EFAULT; 1660 errno = EFAULT;
1677 return; 1661 return;
1678 } 1662 }
1679#endif /* MALLOC_EXTRA_SANITY */ 1663#endif /* MALLOC_EXTRA_SANITY */
1680 if (pi != last_dir) { 1664 if (pi != last_dir) {
1681 prev_dir = last_dir; 1665 prev_dir = last_dir;
1682 last_dir = pi; 1666 last_dir = pi;
@@ -1685,10 +1669,9 @@ free_bytes(void *ptr, int index, struct pginfo * info)
1685 pd[PI_OFF(ptr2index(info->page))] = MALLOC_FIRST; 1669 pd[PI_OFF(ptr2index(info->page))] = MALLOC_FIRST;
1686 1670
1687 /* If the page was mprotected, unprotect it before releasing it */ 1671 /* If the page was mprotected, unprotect it before releasing it */
1688 if (info->size == 0) { 1672 if (info->size == 0)
1689 mprotect(info->page, malloc_pagesize, PROT_READ | PROT_WRITE); 1673 mprotect(info->page, malloc_pagesize, PROT_READ | PROT_WRITE);
1690 /* Do we have to care if mprotect succeeds here ? */ 1674
1691 }
1692 vp = info->page; /* Order is important ! */ 1675 vp = info->page; /* Order is important ! */
1693 if (vp != (void *) info) 1676 if (vp != (void *) info)
1694 ifree(info); 1677 ifree(info);
@@ -1698,18 +1681,16 @@ free_bytes(void *ptr, int index, struct pginfo * info)
1698static void 1681static void
1699ifree(void *ptr) 1682ifree(void *ptr)
1700{ 1683{
1701 struct pginfo *info; 1684 struct pginfo *info, **pd;
1702 struct pginfo **pd; 1685 u_long pidx, index;
1703 struct pdinfo *pi; 1686 struct pdinfo *pi;
1704 u_long pidx;
1705 u_long index;
1706 1687
1707 /* This is legal */ 1688 /* This is legal */
1708 if (ptr == NULL) 1689 if (ptr == NULL)
1709 return; 1690 return;
1710 1691
1711 if (!malloc_started) { 1692 if (!malloc_started) {
1712 wrtwarning("malloc() has never been called\n"); 1693 wrtwarning("malloc() has never been called");
1713 return; 1694 return;
1714 } 1695 }
1715 /* If we're already sinking, don't make matters any worse. */ 1696 /* If we're already sinking, don't make matters any worse. */
@@ -1723,23 +1704,23 @@ ifree(void *ptr)
1723 1704
1724 if (index < malloc_pageshift) { 1705 if (index < malloc_pageshift) {
1725 warnx("(%p)", ptr); 1706 warnx("(%p)", ptr);
1726 wrtwarning("ifree: junk pointer, too low to make sense\n"); 1707 wrtwarning("ifree: junk pointer, too low to make sense");
1727 return; 1708 return;
1728 } 1709 }
1729 if (index > last_index) { 1710 if (index > last_index) {
1730 warnx("(%p)", ptr); 1711 warnx("(%p)", ptr);
1731 wrtwarning("ifree: junk pointer, too high to make sense\n"); 1712 wrtwarning("ifree: junk pointer, too high to make sense");
1732 return; 1713 return;
1733 } 1714 }
1734 pidx = PI_IDX(index); 1715 pidx = PI_IDX(index);
1735 pdir_lookup(index, &pi); 1716 pdir_lookup(index, &pi);
1736#ifdef MALLOC_EXTRA_SANITY 1717#ifdef MALLOC_EXTRA_SANITY
1737 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { 1718 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
1738 wrterror("(ES): mapped pages not found in directory\n"); 1719 wrterror("(ES): mapped pages not found in directory");
1739 errno = EFAULT; 1720 errno = EFAULT;
1740 return; 1721 return;
1741 } 1722 }
1742#endif /* MALLOC_EXTRA_SANITY */ 1723#endif /* MALLOC_EXTRA_SANITY */
1743 if (pi != last_dir) { 1724 if (pi != last_dir) {
1744 prev_dir = last_dir; 1725 prev_dir = last_dir;
1745 last_dir = pi; 1726 last_dir = pi;
@@ -1762,11 +1743,11 @@ ifree(void *ptr)
1762static void 1743static void
1763malloc_recurse(void) 1744malloc_recurse(void)
1764{ 1745{
1765 static int noprint; 1746 static int noprint;
1766 1747
1767 if (noprint == 0) { 1748 if (noprint == 0) {
1768 noprint = 1; 1749 noprint = 1;
1769 wrtwarning("recursive call\n"); 1750 wrtwarning("recursive call");
1770 } 1751 }
1771 malloc_active--; 1752 malloc_active--;
1772 _MALLOC_UNLOCK(); 1753 _MALLOC_UNLOCK();
@@ -1776,10 +1757,10 @@ malloc_recurse(void)
1776/* 1757/*
1777 * These are the public exported interface routines. 1758 * These are the public exported interface routines.
1778 */ 1759 */
1779void * 1760void *
1780malloc(size_t size) 1761malloc(size_t size)
1781{ 1762{
1782 void *r; 1763 void *r;
1783 1764
1784 _MALLOC_LOCK(); 1765 _MALLOC_LOCK();
1785 malloc_func = " in malloc():"; 1766 malloc_func = " in malloc():";
@@ -1792,7 +1773,7 @@ malloc(size_t size)
1792 malloc_active--; 1773 malloc_active--;
1793 _MALLOC_UNLOCK(); 1774 _MALLOC_UNLOCK();
1794 if (malloc_xmalloc && r == NULL) { 1775 if (malloc_xmalloc && r == NULL) {
1795 wrterror("out of memory\n"); 1776 wrterror("out of memory");
1796 errno = ENOMEM; 1777 errno = ENOMEM;
1797 } 1778 }
1798 return (r); 1779 return (r);
@@ -1814,10 +1795,10 @@ free(void *ptr)
1814 return; 1795 return;
1815} 1796}
1816 1797
1817void * 1798void *
1818realloc(void *ptr, size_t size) 1799realloc(void *ptr, size_t size)
1819{ 1800{
1820 void *r; 1801 void *r;
1821 1802
1822 _MALLOC_LOCK(); 1803 _MALLOC_LOCK();
1823 malloc_func = " in realloc():"; 1804 malloc_func = " in realloc():";
@@ -1825,16 +1806,17 @@ realloc(void *ptr, size_t size)
1825 malloc_recurse(); 1806 malloc_recurse();
1826 return (NULL); 1807 return (NULL);
1827 } 1808 }
1828 if (ptr == NULL) { 1809
1810 if (ptr == NULL)
1829 r = imalloc(size); 1811 r = imalloc(size);
1830 } else { 1812 else
1831 r = irealloc(ptr, size); 1813 r = irealloc(ptr, size);
1832 } 1814
1833 UTRACE(ptr, size, r); 1815 UTRACE(ptr, size, r);
1834 malloc_active--; 1816 malloc_active--;
1835 _MALLOC_UNLOCK(); 1817 _MALLOC_UNLOCK();
1836 if (malloc_xmalloc && r == NULL) { 1818 if (malloc_xmalloc && r == NULL) {
1837 wrterror("out of memory\n"); 1819 wrterror("out of memory");
1838 errno = ENOMEM; 1820 errno = ENOMEM;
1839 } 1821 }
1840 return (r); 1822 return (r);