summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lib/libc/stdlib/malloc.c743
1 files changed, 189 insertions, 554 deletions
diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c
index aedb4c8f0c..661265bb85 100644
--- a/src/lib/libc/stdlib/malloc.c
+++ b/src/lib/libc/stdlib/malloc.c
@@ -8,7 +8,7 @@
8 */ 8 */
9 9
10#if defined(LIBC_SCCS) && !defined(lint) 10#if defined(LIBC_SCCS) && !defined(lint)
11static char rcsid[] = "$OpenBSD: malloc.c,v 1.70 2004/08/05 21:55:21 tdeval Exp $"; 11static char rcsid[] = "$OpenBSD: malloc.c,v 1.71 2004/08/11 06:22:45 tdeval Exp $";
12#endif /* LIBC_SCCS and not lint */ 12#endif /* LIBC_SCCS and not lint */
13 13
14/* 14/*
@@ -38,8 +38,6 @@ static char rcsid[] = "$OpenBSD: malloc.c,v 1.70 2004/08/05 21:55:21 tdeval Exp
38#define SOME_JUNK 0xd0 /* as in "Duh" :-) */ 38#define SOME_JUNK 0xd0 /* as in "Duh" :-) */
39 39
40#include <sys/types.h> 40#include <sys/types.h>
41#include <sys/time.h>
42#include <sys/resource.h>
43#include <sys/param.h> 41#include <sys/param.h>
44#include <sys/mman.h> 42#include <sys/mman.h>
45#include <sys/uio.h> 43#include <sys/uio.h>
@@ -81,11 +79,11 @@ static char rcsid[] = "$OpenBSD: malloc.c,v 1.70 2004/08/05 21:55:21 tdeval Exp
81struct pginfo { 79struct pginfo {
82 struct pginfo *next; /* next on the free list */ 80 struct pginfo *next; /* next on the free list */
83 void *page; /* Pointer to the page */ 81 void *page; /* Pointer to the page */
84 u_short size; /* size of this page's chunks */ 82 u_short size; /* size of this page's chunks */
85 u_short shift; /* How far to shift for this size chunks */ 83 u_short shift; /* How far to shift for this size chunks */
86 u_short free; /* How many free chunks */ 84 u_short free; /* How many free chunks */
87 u_short total; /* How many chunk */ 85 u_short total; /* How many chunk */
88 u_long bits[1]; /* Which chunks are free */ 86 u_long bits[1]; /* Which chunks are free */
89}; 87};
90 88
91/* 89/*
@@ -96,8 +94,8 @@ struct pgfree {
96 struct pgfree *next; /* next run of free pages */ 94 struct pgfree *next; /* next run of free pages */
97 struct pgfree *prev; /* prev run of free pages */ 95 struct pgfree *prev; /* prev run of free pages */
98 void *page; /* pointer to free pages */ 96 void *page; /* pointer to free pages */
99 void *pdir; /* pointer to the base page's dir */ 97 void *end; /* pointer to end of free pages */
100 size_t size; /* number of bytes free */ 98 u_long size; /* number of bytes free */
101}; 99};
102 100
103/* 101/*
@@ -142,8 +140,8 @@ struct pgfree {
142/* A mask for the offset inside a page. */ 140/* A mask for the offset inside a page. */
143#define malloc_pagemask ((malloc_pagesize)-1) 141#define malloc_pagemask ((malloc_pagesize)-1)
144 142
145#define pageround(foo) (((foo) + (malloc_pagemask)) & ~malloc_pagemask) 143#define pageround(foo) (((foo) + (malloc_pagemask))&(~(malloc_pagemask)))
146#define ptr2index(foo) (((u_long)(foo) >> malloc_pageshift)+malloc_pageshift) 144#define ptr2index(foo) (((u_long)(foo) >> malloc_pageshift)-malloc_origo)
147 145
148/* fd of /dev/zero */ 146/* fd of /dev/zero */
149#ifdef USE_DEV_ZERO 147#ifdef USE_DEV_ZERO
@@ -163,22 +161,8 @@ static unsigned int malloc_started;
163/* Number of free pages we cache */ 161/* Number of free pages we cache */
164static unsigned int malloc_cache = 16; 162static unsigned int malloc_cache = 16;
165 163
166/* Structure used for linking discrete directory pages. */ 164/* The offset from pagenumber to index into the page directory */
167struct pdinfo { 165static u_long malloc_origo;
168 struct pginfo **base;
169 struct pdinfo *prev;
170 struct pdinfo *next;
171 u_long dirnum;
172};
173static struct pdinfo *last_dir; /* Caches to the last and previous */
174static struct pdinfo *prev_dir; /* referenced directory pages. */
175
176static size_t pdi_off;
177static u_long pdi_mod;
178#define PD_IDX(num) ((num) / (malloc_pagesize/sizeof(struct pginfo *)))
179#define PD_OFF(num) ((num) & ((malloc_pagesize/sizeof(struct pginfo *))-1))
180#define PI_IDX(index) ((index) / pdi_mod)
181#define PI_OFF(index) ((index) % pdi_mod)
182 166
183/* The last index in the page directory we care about */ 167/* The last index in the page directory we care about */
184static u_long last_index; 168static u_long last_index;
@@ -247,144 +231,72 @@ void utrace(struct ut *, int);
247/* Status of malloc. */ 231/* Status of malloc. */
248static int malloc_active; 232static int malloc_active;
249 233
250/* Allocated memory. */ 234/* my last break. */
251static size_t malloc_used;
252
253/* My last break. */
254static void *malloc_brk; 235static void *malloc_brk;
255 236
256/* One location cache for free-list holders. */ 237/* one location cache for free-list holders */
257static struct pgfree *px; 238static struct pgfree *px;
258 239
259/* Compile-time options. */ 240/* compile-time options */
260char *malloc_options; 241char *malloc_options;
261 242
262/* Name of the current public function. */ 243/* Name of the current public function */
263static char *malloc_func; 244static char *malloc_func;
264 245
265/* Macro for mmap. */ 246/* Macro for mmap */
266#define MMAP(size) \ 247#define MMAP(size) \
267 mmap((void *)0, (size), PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, \ 248 mmap((void *)0, (size), PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, \
268 MMAP_FD, (off_t)0) 249 MMAP_FD, (off_t)0)
269 250
270/* 251/*
271 * Necessary function declarations. 252 * Necessary function declarations
272 */ 253 */
254static int extend_pgdir(u_long index);
273static void *imalloc(size_t size); 255static void *imalloc(size_t size);
274static void ifree(void *ptr); 256static void ifree(void *ptr);
275static void *irealloc(void *ptr, size_t size); 257static void *irealloc(void *ptr, size_t size);
276static void *malloc_bytes(size_t size); 258static void *malloc_bytes(size_t size);
277 259
278
279/*
280 * Function for page directory lookup.
281 */
282static int
283pdir_lookup(u_long index, struct pdinfo **pdi)
284{
285 struct pdinfo *spi;
286 u_long pidx = PI_IDX(index);
287
288 if (last_dir != NULL && PD_IDX(last_dir->dirnum) == pidx)
289 *pdi = last_dir;
290 else if (prev_dir != NULL && PD_IDX(prev_dir->dirnum) == pidx)
291 *pdi = prev_dir;
292 else if (last_dir != NULL && prev_dir != NULL) {
293 if ((PD_IDX(last_dir->dirnum) > pidx) ?
294 (PD_IDX(last_dir->dirnum) - pidx):(pidx - PD_IDX(last_dir->dirnum))
295 < (PD_IDX(prev_dir->dirnum) > pidx) ?
296 (PD_IDX(prev_dir->dirnum) - pidx):(pidx - PD_IDX(prev_dir->dirnum)))
297 *pdi = last_dir;
298 else
299 *pdi = prev_dir;
300
301 if (PD_IDX((*pdi)->dirnum) > pidx) {
302 for (spi=(*pdi)->prev;spi!=NULL && PD_IDX(spi->dirnum)>pidx;
303 spi=spi->prev)
304 *pdi = spi;
305 if (spi != NULL)
306 *pdi = spi;
307 } else
308 for (spi=(*pdi)->next;spi!=NULL && PD_IDX(spi->dirnum)<=pidx;
309 spi=spi->next)
310 *pdi = spi;
311 } else {
312 *pdi = (struct pdinfo *)((caddr_t)page_dir + pdi_off);
313 for (spi=*pdi;spi!=NULL && PD_IDX(spi->dirnum)<=pidx;spi=spi->next)
314 *pdi = spi;
315 }
316
317 return ((PD_IDX((*pdi)->dirnum) == pidx)?0:(PD_IDX((*pdi)->dirnum) > pidx)?1:-1);
318}
319
320
321#ifdef MALLOC_STATS 260#ifdef MALLOC_STATS
322void 261void
323malloc_dump(FILE *fd) 262malloc_dump(FILE *fd)
324{ 263{
325 struct pginfo **pd; 264 struct pginfo **pd;
326 struct pgfree *pf; 265 struct pgfree *pf;
327 struct pdinfo *pi;
328 int j; 266 int j;
329 267
330 pd = page_dir; 268 pd = page_dir;
331 pi = (struct pdinfo *)((caddr_t)pd + pdi_off);
332 269
333 /* print out all the pages */ 270 /* print out all the pages */
334 for(j=0;j<=last_index;) { 271 for(j=0;j<=last_index;j++) {
335 fprintf(fd, "%08lx %5d ", j << malloc_pageshift, j); 272 fprintf(fd, "%08lx %5d ", (j+malloc_origo) << malloc_pageshift, j);
336 if (pd[PI_OFF(j)] == MALLOC_NOT_MINE) { 273 if (pd[j] == MALLOC_NOT_MINE) {
337 for(j++;j<=last_index && pd[PI_OFF(j)] == MALLOC_NOT_MINE;) { 274 for(j++;j<=last_index && pd[j] == MALLOC_NOT_MINE;j++)
338 if (!PI_OFF(++j)) { 275 ;
339 if ((pi = pi->next) == NULL ||
340 PD_IDX(pi->dirnum) != PI_IDX(j)) break;
341 pd = pi->base;
342 j += pdi_mod;
343 }
344 }
345 j--; 276 j--;
346 fprintf(fd, ".. %5d not mine\n", j); 277 fprintf(fd, ".. %5d not mine\n", j);
347 } else if (pd[PI_OFF(j)] == MALLOC_FREE) { 278 } else if (pd[j] == MALLOC_FREE) {
348 for(j++;j<=last_index && pd[PI_OFF(j)] == MALLOC_FREE;) { 279 for(j++;j<=last_index && pd[j] == MALLOC_FREE;j++)
349 if (!PI_OFF(++j)) { 280 ;
350 if ((pi = pi->next) == NULL ||
351 PD_IDX(pi->dirnum) != PI_IDX(j)) break;
352 pd = pi->base;
353 j += pdi_mod;
354 }
355 }
356 j--; 281 j--;
357 fprintf(fd, ".. %5d free\n", j); 282 fprintf(fd, ".. %5d free\n", j);
358 } else if (pd[PI_OFF(j)] == MALLOC_FIRST) { 283 } else if (pd[j] == MALLOC_FIRST) {
359 for(j++;j<=last_index && pd[PI_OFF(j)] == MALLOC_FOLLOW;) { 284 for(j++;j<=last_index && pd[j] == MALLOC_FOLLOW;j++)
360 if (!PI_OFF(++j)) { 285 ;
361 if ((pi = pi->next) == NULL ||
362 PD_IDX(pi->dirnum) != PI_IDX(j)) break;
363 pd = pi->base;
364 j += pdi_mod;
365 }
366 }
367 j--; 286 j--;
368 fprintf(fd, ".. %5d in use\n", j); 287 fprintf(fd, ".. %5d in use\n", j);
369 } else if (pd[PI_OFF(j)] < MALLOC_MAGIC) { 288 } else if (pd[j] < MALLOC_MAGIC) {
370 fprintf(fd, "(%p)\n", pd[PI_OFF(j)]); 289 fprintf(fd, "(%p)\n", pd[j]);
371 } else { 290 } else {
372 fprintf(fd, "%p %d (of %d) x %d @ %p --> %p\n", 291 fprintf(fd, "%p %d (of %d) x %d @ %p --> %p\n",
373 pd[PI_OFF(j)], pd[PI_OFF(j)]->free, pd[PI_OFF(j)]->total, 292 pd[j], pd[j]->free, pd[j]->total,
374 pd[PI_OFF(j)]->size, pd[PI_OFF(j)]->page, pd[PI_OFF(j)]->next); 293 pd[j]->size, pd[j]->page, pd[j]->next);
375 }
376 if (!PI_OFF(++j)) {
377 if ((pi = pi->next) == NULL)
378 break;
379 pd = pi->base;
380 j += (1 + PD_IDX(pi->dirnum) - PI_IDX(j)) * pdi_mod;
381 } 294 }
382 } 295 }
383 296
384 for(pf=free_list.next; pf; pf=pf->next) { 297 for(pf=free_list.next; pf; pf=pf->next) {
385 fprintf(fd, "Free: @%p [%p...%p[ %ld ->%p <-%p\n", 298 fprintf(fd, "Free: @%p [%p...%p[ %ld ->%p <-%p\n",
386 pf, pf->page, pf->page + pf->size, pf->size, 299 pf, pf->page, pf->end, pf->size, pf->prev, pf->next);
387 pf->prev, pf->next);
388 if (pf == pf->next) { 300 if (pf == pf->next) {
389 fprintf(fd, "Free_list loops\n"); 301 fprintf(fd, "Free_list loops\n");
390 break; 302 break;
@@ -396,7 +308,10 @@ malloc_dump(FILE *fd)
396 fprintf(fd, "Maxsize\t%d\n", malloc_maxsize); 308 fprintf(fd, "Maxsize\t%d\n", malloc_maxsize);
397 fprintf(fd, "Pagesize\t%lu\n", (u_long)malloc_pagesize); 309 fprintf(fd, "Pagesize\t%lu\n", (u_long)malloc_pagesize);
398 fprintf(fd, "Pageshift\t%d\n", malloc_pageshift); 310 fprintf(fd, "Pageshift\t%d\n", malloc_pageshift);
399 fprintf(fd, "In use\t%lu\n", (u_long)malloc_used); 311 fprintf(fd, "FirstPage\t%ld\n", malloc_origo);
312 fprintf(fd, "LastPage\t%ld %lx\n", last_index+malloc_pageshift,
313 (last_index + malloc_pageshift) << malloc_pageshift);
314 fprintf(fd, "Break\t%ld\n", (u_long)sbrk(0) >> malloc_pageshift);
400} 315}
401#endif /* MALLOC_STATS */ 316#endif /* MALLOC_STATS */
402 317
@@ -424,8 +339,7 @@ wrterror(char *p)
424 malloc_dump(stderr); 339 malloc_dump(stderr);
425#endif /* MALLOC_STATS */ 340#endif /* MALLOC_STATS */
426 malloc_active--; 341 malloc_active--;
427 if (malloc_abort) 342 abort();
428 abort();
429} 343}
430 344
431static void 345static void
@@ -471,86 +385,89 @@ malloc_exit(void)
471static void * 385static void *
472map_pages(size_t pages) 386map_pages(size_t pages)
473{ 387{
474 struct pdinfo *pi, *spi; 388 caddr_t result, tail;
475 struct pginfo **pd;
476 u_long pidx,lidx;
477 void *result, *tail;
478 u_long index;
479 389
390 result = (caddr_t)pageround((u_long)sbrk(0));
480 pages <<= malloc_pageshift; 391 pages <<= malloc_pageshift;
481 result = MMAP(pages + malloc_guard); 392 if (pages > SIZE_T_MAX - (size_t)result) {
482 if (result == MAP_FAILED) {
483 errno = ENOMEM;
484#ifdef MALLOC_EXTRA_SANITY 393#ifdef MALLOC_EXTRA_SANITY
485 wrtwarning("(ES): map_pages fails\n"); 394 wrtwarning("(ES): overflow in map_pages fails\n");
486#endif /* MALLOC_EXTRA_SANITY */ 395#endif /* MALLOC_EXTRA_SANITY */
396 errno = ENOMEM;
487 return (NULL); 397 return (NULL);
488 } 398 }
489 tail = result + pages + malloc_guard; 399 tail = result + pages + malloc_guard;
490 if (malloc_guard)
491 mprotect(result + pages, malloc_guard, PROT_NONE);
492
493 if (tail > malloc_brk)
494 malloc_brk = tail;
495 if ((index = ptr2index(tail) - 1) > last_index)
496 last_index = index;
497
498 /* Insert directory pages, if needed. */
499 pidx = PI_IDX(ptr2index(result));
500 lidx = PI_IDX(index);
501 400
502 pdir_lookup(ptr2index(result), &pi); 401 if (brk(tail) == (char *)-1) {
503
504 for (index=pidx,spi=pi;index<=lidx;index++) {
505 if (pi == NULL || PD_IDX(pi->dirnum) != index) {
506 if ((pd = MMAP(malloc_pagesize)) == MAP_FAILED) {
507 errno = ENOMEM;
508 munmap(result, tail - result);
509#ifdef MALLOC_EXTRA_SANITY 402#ifdef MALLOC_EXTRA_SANITY
510 wrtwarning("(ES): map_pages fails\n"); 403 wrtwarning("(ES): map_pages fails\n");
511#endif /* MALLOC_EXTRA_SANITY */
512 return (NULL);
513 }
514 memset(pd, 0, malloc_pagesize);
515 pi = (struct pdinfo *)((caddr_t)pd + pdi_off);
516 pi->base = pd;
517 pi->prev = spi;
518 pi->next = spi->next;
519 pi->dirnum = index * (malloc_pagesize/sizeof(struct pginfo *));
520
521 if (spi->next != NULL)
522 spi->next->prev = pi;
523 spi->next = pi;
524 }
525 if (index > pidx && index < lidx) {
526 pi->dirnum += pdi_mod;
527 } else if (index == pidx) {
528 if (pidx == lidx) {
529 pi->dirnum += (tail - result) >> malloc_pageshift;
530 } else {
531 pi->dirnum += pdi_mod - PI_OFF(ptr2index(result));
532 }
533 } else {
534 pi->dirnum += PI_OFF(ptr2index(tail - 1)) + 1;
535 }
536#ifdef MALLOC_EXTRA_SANITY
537 if (PD_OFF(pi->dirnum) > pdi_mod || PD_IDX(pi->dirnum) > index) {
538 wrterror("(ES): pages directory overflow\n");
539 errno = EFAULT;
540 return (NULL);
541 }
542#endif /* MALLOC_EXTRA_SANITY */ 404#endif /* MALLOC_EXTRA_SANITY */
543 if (index == pidx && pi != last_dir) { 405 return (NULL);
544 prev_dir = last_dir;
545 last_dir = pi;
546 }
547 spi = pi;
548 pi = spi->next;
549 } 406 }
407 if (malloc_guard)
408 mprotect(result + pages, malloc_pagesize, PROT_NONE);
409
410 last_index = ptr2index(tail) - 1;
411 malloc_brk = tail;
412
413 if ((last_index+1) >= malloc_ninfo && !extend_pgdir(last_index))
414 return (NULL);
550 415
551 return (result); 416 return (result);
552} 417}
553 418
419/*
420 * Extend page directory
421 */
422static int
423extend_pgdir(u_long index)
424{
425 struct pginfo **new, **old;
426 size_t i, oldlen;
427
428 /* Make it this many pages */
429 i = index * sizeof *page_dir;
430 i /= malloc_pagesize;
431 i += 2;
432
433 /* remember the old mapping size */
434 oldlen = malloc_ninfo * sizeof *page_dir;
435
436 /*
437 * NOTE: we allocate new pages and copy the directory rather than tempt
438 * fate by trying to "grow" the region.. There is nothing to prevent
439 * us from accidently re-mapping space that's been allocated by our caller
440 * via dlopen() or other mmap().
441 *
442 * The copy problem is not too bad, as there is 4K of page index per
443 * 4MB of malloc arena.
444 *
445 * We can totally avoid the copy if we open a file descriptor to associate
446 * the anon mappings with. Then, when we remap the pages at the new
447 * address, the old pages will be "magically" remapped.. But this means
448 * keeping open a "secret" file descriptor.....
449 */
450
451 /* Get new pages */
452 new = (struct pginfo**) MMAP(i * malloc_pagesize);
453 if (new == MAP_FAILED)
454 return (0);
455
456 /* Copy the old stuff */
457 memcpy(new, page_dir,
458 malloc_ninfo * sizeof *page_dir);
459
460 /* register the new size */
461 malloc_ninfo = i * malloc_pagesize / sizeof *page_dir;
462
463 /* swap the pointers */
464 old = page_dir;
465 page_dir = new;
466
467 /* Now free the old stuff */
468 munmap(old, oldlen);
469 return (1);
470}
554 471
555/* 472/*
556 * Initialize the world 473 * Initialize the world
@@ -603,12 +520,12 @@ malloc_init(void)
603 case 'h': malloc_hint = 0; break; 520 case 'h': malloc_hint = 0; break;
604 case 'H': malloc_hint = 1; break; 521 case 'H': malloc_hint = 1; break;
605#endif /* __FreeBSD__ */ 522#endif /* __FreeBSD__ */
523 case 'r': malloc_realloc = 0; break;
524 case 'R': malloc_realloc = 1; break;
606 case 'j': malloc_junk = 0; break; 525 case 'j': malloc_junk = 0; break;
607 case 'J': malloc_junk = 1; break; 526 case 'J': malloc_junk = 1; break;
608 case 'n': malloc_silent = 0; break; 527 case 'n': malloc_silent = 0; break;
609 case 'N': malloc_silent = 1; break; 528 case 'N': malloc_silent = 1; break;
610 case 'r': malloc_realloc = 0; break;
611 case 'R': malloc_realloc = 1; break;
612#ifdef __FreeBSD__ 529#ifdef __FreeBSD__
613 case 'u': malloc_utrace = 0; break; 530 case 'u': malloc_utrace = 0; break;
614 case 'U': malloc_utrace = 1; break; 531 case 'U': malloc_utrace = 1; break;
@@ -644,21 +561,17 @@ malloc_init(void)
644 /* Allocate one page for the page directory */ 561 /* Allocate one page for the page directory */
645 page_dir = (struct pginfo **) MMAP(malloc_pagesize); 562 page_dir = (struct pginfo **) MMAP(malloc_pagesize);
646 563
647 if (page_dir == MAP_FAILED) { 564 if (page_dir == MAP_FAILED)
648 wrterror("mmap(2) failed, check limits\n"); 565 wrterror("mmap(2) failed, check limits\n");
649 errno = ENOMEM;
650 return;
651 }
652 566
653 pdi_off = (malloc_pagesize - sizeof(struct pdinfo)) & ~(malloc_minsize - 1); 567 /*
654 pdi_mod = pdi_off / sizeof(struct pginfo *); 568 * We need a maximum of malloc_pageshift buckets, steal these from the
655 569 * front of the page_directory;
656 last_dir = (struct pdinfo *)((caddr_t)page_dir + pdi_off); 570 */
657 last_dir->base = page_dir; 571 malloc_origo = ((u_long)pageround((u_long)sbrk(0))) >> malloc_pageshift;
658 last_dir->prev = last_dir->next = NULL; 572 malloc_origo -= malloc_pageshift;
659 last_dir->dirnum = malloc_pageshift;
660 573
661 malloc_ninfo = pdi_mod; 574 malloc_ninfo = malloc_pagesize / sizeof *page_dir;
662 575
663 /* Been here, done that */ 576 /* Been here, done that */
664 malloc_started++; 577 malloc_started++;
@@ -670,6 +583,11 @@ malloc_init(void)
670 583
671 malloc_cache <<= malloc_pageshift; 584 malloc_cache <<= malloc_pageshift;
672 585
586 /*
587 * This is a nice hack from Kaleb Keithly (kaleb@x.org).
588 * We can sbrk(2) further back when we keep this on a low address.
589 */
590 px = (struct pgfree *) imalloc (sizeof *px);
673 errno = save_errno; 591 errno = save_errno;
674} 592}
675 593
@@ -681,66 +599,30 @@ malloc_pages(size_t size)
681{ 599{
682 void *p, *delay_free = NULL; 600 void *p, *delay_free = NULL;
683 int i; 601 int i;
684 struct rlimit rl;
685 struct pginfo **pd;
686 struct pdinfo *pi;
687 u_long pidx;
688 void *tp;
689 struct pgfree *pf; 602 struct pgfree *pf;
690 u_long index; 603 u_long index;
691 int m;
692 604
693 size = pageround(size) + malloc_guard; 605 size = pageround(size) + malloc_guard;
694 606
695 p = NULL; 607 p = NULL;
696 /* Look for free pages before asking for more */ 608 /* Look for free pages before asking for more */
697 for (pf = free_list.next; pf; pf = pf->next) { 609 for(pf = free_list.next; pf; pf = pf->next) {
698 610
699#ifdef MALLOC_EXTRA_SANITY 611#ifdef MALLOC_EXTRA_SANITY
700 if (pf->size & malloc_pagemask) { 612 if (pf->size & malloc_pagemask)
701 wrterror("(ES): junk length entry on free_list\n"); 613 wrterror("(ES): junk length entry on free_list\n");
702 errno = EFAULT; 614 if (!pf->size)
703 return (NULL);
704 }
705 if (!pf->size) {
706 wrterror("(ES): zero length entry on free_list\n"); 615 wrterror("(ES): zero length entry on free_list\n");
707 errno = EFAULT; 616 if (pf->page == pf->end)
708 return (NULL); 617 wrterror("(ES): zero entry on free_list\n");
709 } 618 if (pf->page > pf->end)
710 if (pf->page > (pf->page + pf->size)) {
711 wrterror("(ES): sick entry on free_list\n"); 619 wrterror("(ES): sick entry on free_list\n");
712 errno = EFAULT; 620 if ((void*)pf->page >= (void*)sbrk(0))
713 return (NULL); 621 wrterror("(ES): entry on free_list past brk\n");
714 } 622 if (page_dir[ptr2index(pf->page)] != MALLOC_FREE)
715 if ((pi = pf->pdir) == NULL) {
716 wrterror("(ES): invalid page directory on free-list\n");
717 errno = EFAULT;
718 return (NULL);
719 }
720 if ((pidx = PI_IDX(ptr2index(pf->page))) != PD_IDX(pi->dirnum)) {
721 wrterror("(ES): directory index mismatch on free-list\n");
722 errno = EFAULT;
723 return (NULL);
724 }
725 pd = pi->base;
726 if (pd[PI_OFF(ptr2index(pf->page))] != MALLOC_FREE) {
727 wrterror("(ES): non-free first page on free-list\n"); 623 wrterror("(ES): non-free first page on free-list\n");
728 errno = EFAULT; 624 if (page_dir[ptr2index(pf->end)-1] != MALLOC_FREE)
729 return (NULL);
730 }
731 pidx = PI_IDX(ptr2index((pf->page)+(pf->size))-1);
732 for (pi=pf->pdir; pi!=NULL && PD_IDX(pi->dirnum)<pidx; pi=pi->next);
733 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
734 wrterror("(ES): last page not referenced in page directory\n");
735 errno = EFAULT;
736 return (NULL);
737 }
738 pd = pi->base;
739 if (pd[PI_OFF(ptr2index((pf->page)+(pf->size))-1)] != MALLOC_FREE) {
740 wrterror("(ES): non-free last page on free-list\n"); 625 wrterror("(ES): non-free last page on free-list\n");
741 errno = EFAULT;
742 return (NULL);
743 }
744#endif /* MALLOC_EXTRA_SANITY */ 626#endif /* MALLOC_EXTRA_SANITY */
745 627
746 if (pf->size < size) 628 if (pf->size < size)
@@ -748,7 +630,6 @@ malloc_pages(size_t size)
748 630
749 if (pf->size == size) { 631 if (pf->size == size) {
750 p = pf->page; 632 p = pf->page;
751 pi = pf->pdir;
752 if (pf->next != NULL) 633 if (pf->next != NULL)
753 pf->next->prev = pf->prev; 634 pf->next->prev = pf->prev;
754 pf->prev->next = pf->next; 635 pf->prev->next = pf->next;
@@ -759,34 +640,17 @@ malloc_pages(size_t size)
759 p = pf->page; 640 p = pf->page;
760 pf->page = (char *)pf->page + size; 641 pf->page = (char *)pf->page + size;
761 pf->size -= size; 642 pf->size -= size;
762 pidx = PI_IDX(ptr2index(pf->page));
763 for (pi=pf->pdir; pi!=NULL && PD_IDX(pi->dirnum)<pidx; pi=pi->next);
764 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
765 wrterror("(ES): hole in directories\n");
766 errno = EFAULT;
767 return (NULL);
768 }
769 tp = pf->pdir;
770 pf->pdir = pi;
771 pi = tp;
772 break; 643 break;
773 } 644 }
774 645
775 size -= malloc_guard; 646 size -= malloc_guard;
776 647
777#ifdef MALLOC_EXTRA_SANITY 648#ifdef MALLOC_EXTRA_SANITY
778 if (p != NULL && pi != NULL) { 649 if (p != NULL && page_dir[ptr2index(p)] != MALLOC_FREE)
779 pidx = PD_IDX(pi->dirnum);
780 pd = pi->base;
781 }
782 if (p != NULL && pd[PI_OFF(ptr2index(p))] != MALLOC_FREE) {
783 wrterror("(ES): allocated non-free page on free-list\n"); 650 wrterror("(ES): allocated non-free page on free-list\n");
784 errno = EFAULT;
785 return (NULL);
786 }
787#endif /* MALLOC_EXTRA_SANITY */ 651#endif /* MALLOC_EXTRA_SANITY */
788 652
789 if (p != NULL && (malloc_guard || malloc_freeprot)) 653 if ((malloc_guard || malloc_freeprot) && p != NULL)
790 mprotect(p, size, PROT_READ|PROT_WRITE); 654 mprotect(p, size, PROT_READ|PROT_WRITE);
791 655
792 size >>= malloc_pageshift; 656 size >>= malloc_pageshift;
@@ -798,53 +662,9 @@ malloc_pages(size_t size)
798 if (p != NULL) { 662 if (p != NULL) {
799 663
800 index = ptr2index(p); 664 index = ptr2index(p);
801 pidx = PI_IDX(index); 665 page_dir[index] = MALLOC_FIRST;
802 pdir_lookup(index, &pi); 666 for (i=1;i<size;i++)
803#ifdef MALLOC_EXTRA_SANITY 667 page_dir[index+i] = MALLOC_FOLLOW;
804 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
805 wrterror("(ES): mapped pages not found in directory\n");
806 errno = EFAULT;
807 return (NULL);
808 }
809#endif /* MALLOC_EXTRA_SANITY */
810 if (pi != last_dir) {
811 prev_dir = last_dir;
812 last_dir = pi;
813 }
814 pd = pi->base;
815 pd[PI_OFF(index)] = MALLOC_FIRST;
816 for (i=1;i<size;i++) {
817 if (!PI_OFF(index+i)) {
818 pidx++;
819 pi = pi->next;
820#ifdef MALLOC_EXTRA_SANITY
821 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
822 wrterror("(ES): hole in mapped pages directory\n");
823 errno = EFAULT;
824 return (NULL);
825 }
826#endif /* MALLOC_EXTRA_SANITY */
827 pd = pi->base;
828 }
829 pd[PI_OFF(index+i)] = MALLOC_FOLLOW;
830 }
831 if (malloc_guard) {
832 if (!PI_OFF(index+i)) {
833 pidx++;
834 pi = pi->next;
835#ifdef MALLOC_EXTRA_SANITY
836 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
837 wrterror("(ES): hole in mapped pages directory\n");
838 errno = EFAULT;
839 return (NULL);
840 }
841#endif /* MALLOC_EXTRA_SANITY */
842 pd = pi->base;
843 }
844 pd[PI_OFF(index+i)] = MALLOC_FIRST;
845 }
846
847 malloc_used += size << malloc_pageshift;
848 668
849 if (malloc_junk) 669 if (malloc_junk)
850 memset(p, SOME_JUNK, size << malloc_pageshift); 670 memset(p, SOME_JUNK, size << malloc_pageshift);
@@ -867,10 +687,7 @@ malloc_pages(size_t size)
867static __inline__ int 687static __inline__ int
868malloc_make_chunks(int bits) 688malloc_make_chunks(int bits)
869{ 689{
870 struct pginfo *bp; 690 struct pginfo *bp;
871 struct pginfo **pd;
872 struct pdinfo *pi;
873 u_long pidx;
874 void *pp; 691 void *pp;
875 int i, k, l; 692 int i, k, l;
876 693
@@ -948,21 +765,7 @@ malloc_make_chunks(int bits)
948 765
949 /* MALLOC_LOCK */ 766 /* MALLOC_LOCK */
950 767
951 pidx = PI_IDX(ptr2index(pp)); 768 page_dir[ptr2index(pp)] = bp;
952 pdir_lookup(ptr2index(pp), &pi);
953#ifdef MALLOC_EXTRA_SANITY
954 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
955 wrterror("(ES): mapped pages not found in directory\n");
956 errno = EFAULT;
957 return (0);
958 }
959#endif /* MALLOC_EXTRA_SANITY */
960 if (pi != last_dir) {
961 prev_dir = last_dir;
962 last_dir = pi;
963 }
964 pd = pi->base;
965 pd[PI_OFF(ptr2index(pp))] = bp;
966 769
967 bp->next = page_dir[bits]; 770 bp->next = page_dir[bits];
968 page_dir[bits] = bp; 771 page_dir[bits] = bp;
@@ -1016,7 +819,7 @@ malloc_bytes(size_t size)
1016 u += u; 819 u += u;
1017 k++; 820 k++;
1018 } 821 }
1019 822
1020 if (malloc_guard) { 823 if (malloc_guard) {
1021 /* Walk to a random position. */ 824 /* Walk to a random position. */
1022 i = arc4random() % bp->free; 825 i = arc4random() % bp->free;
@@ -1029,14 +832,11 @@ malloc_bytes(size_t size)
1029 k = 0; 832 k = 0;
1030 } 833 }
1031#ifdef MALLOC_EXTRA_SANITY 834#ifdef MALLOC_EXTRA_SANITY
1032 if (lp - bp->bits > (bp->total - 1) / MALLOC_BITS) { 835 if (lp - bp->bits > (bp->total - 1) / MALLOC_BITS)
1033 wrterror("chunk overflow\n"); 836 wrterror("chunk overflow\n");
1034 errno = EFAULT;
1035 return (NULL);
1036 }
1037#endif /* MALLOC_EXTRA_SANITY */ 837#endif /* MALLOC_EXTRA_SANITY */
1038 if (*lp & u) 838 if (*lp & u)
1039 i--; 839 i--;
1040 } 840 }
1041 } 841 }
1042 *lp ^= u; 842 *lp ^= u;
@@ -1096,11 +896,9 @@ static void *
1096irealloc(void *ptr, size_t size) 896irealloc(void *ptr, size_t size)
1097{ 897{
1098 void *p; 898 void *p;
1099 u_long osize, index, i; 899 u_long osize, index;
1100 struct pginfo **mp; 900 struct pginfo **mp;
1101 struct pginfo **pd; 901 int i;
1102 struct pdinfo *pi;
1103 u_long pidx;
1104 902
1105 if (suicide) 903 if (suicide)
1106 abort(); 904 abort();
@@ -1122,22 +920,7 @@ irealloc(void *ptr, size_t size)
1122 return (NULL); 920 return (NULL);
1123 } 921 }
1124 922
1125 pidx = PI_IDX(index); 923 mp = &page_dir[index];
1126 pdir_lookup(index, &pi);
1127#ifdef MALLOC_EXTRA_SANITY
1128 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
1129 wrterror("(ES): mapped pages not found in directory\n");
1130 errno = EFAULT;
1131 return (NULL);
1132 }
1133#endif /* MALLOC_EXTRA_SANITY */
1134 if (pi != last_dir) {
1135 prev_dir = last_dir;
1136 last_dir = pi;
1137 }
1138
1139 pd = pi->base;
1140 mp = &pd[PI_OFF(index)];
1141 924
1142 if (*mp == MALLOC_FIRST) { /* Page allocation */ 925 if (*mp == MALLOC_FIRST) { /* Page allocation */
1143 926
@@ -1148,25 +931,8 @@ irealloc(void *ptr, size_t size)
1148 } 931 }
1149 932
1150 /* Find the size in bytes */ 933 /* Find the size in bytes */
1151 i = index; 934 for (osize = malloc_pagesize; *(++mp) == MALLOC_FOLLOW;)
1152 if (!PI_OFF(++i)) {
1153 pi = pi->next;
1154 if (pi != NULL && PD_IDX(pi->dirnum) != PI_IDX(i))
1155 pi = NULL;
1156 if (pi != NULL)
1157 pd = pi->base;
1158 }
1159 for (osize = malloc_pagesize;
1160 pi != NULL && pd[PI_OFF(i)] == MALLOC_FOLLOW;) {
1161 osize += malloc_pagesize; 935 osize += malloc_pagesize;
1162 if (!PI_OFF(++i)) {
1163 pi = pi->next;
1164 if (pi != NULL && PD_IDX(pi->dirnum) != PI_IDX(i))
1165 pi = NULL;
1166 if (pi != NULL)
1167 pd = pi->base;
1168 }
1169 }
1170 936
1171 if (!malloc_realloc && /* Unless we have to, */ 937 if (!malloc_realloc && /* Unless we have to, */
1172 size <= osize && /* .. or are too small, */ 938 size <= osize && /* .. or are too small, */
@@ -1222,7 +988,6 @@ irealloc(void *ptr, size_t size)
1222 } 988 }
1223 ifree(ptr); 989 ifree(ptr);
1224 } 990 }
1225
1226 return (p); 991 return (p);
1227} 992}
1228 993
@@ -1234,9 +999,6 @@ static __inline__ void
1234free_pages(void *ptr, u_long index, struct pginfo *info) 999free_pages(void *ptr, u_long index, struct pginfo *info)
1235{ 1000{
1236 u_long i, l; 1001 u_long i, l;
1237 struct pginfo **pd;
1238 struct pdinfo *pi, *spi;
1239 u_long pidx, lidx;
1240 struct pgfree *pf, *pt=NULL; 1002 struct pgfree *pf, *pt=NULL;
1241 void *tail; 1003 void *tail;
1242 1004
@@ -1256,77 +1018,40 @@ free_pages(void *ptr, u_long index, struct pginfo *info)
1256 } 1018 }
1257 1019
1258 /* Count how many pages and mark them free at the same time */ 1020 /* Count how many pages and mark them free at the same time */
1259 pidx = PI_IDX(index); 1021 page_dir[index] = MALLOC_FREE;
1260 pdir_lookup(index, &pi); 1022 for (i = 1; page_dir[index+i] == MALLOC_FOLLOW; i++)
1261#ifdef MALLOC_EXTRA_SANITY 1023 page_dir[index + i] = MALLOC_FREE;
1262 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
1263 wrterror("(ES): mapped pages not found in directory\n");
1264 errno = EFAULT;
1265 return;
1266 }
1267#endif /* MALLOC_EXTRA_SANITY */
1268
1269 spi = pi; /* Save page index for start of region. */
1270
1271 pd = pi->base;
1272 pd[PI_OFF(index)] = MALLOC_FREE;
1273 i = 1;
1274 if (!PI_OFF(index+i)) {
1275 pi = pi->next;
1276 if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(index+i))
1277 pi = NULL;
1278 else
1279 pd = pi->base;
1280 }
1281 while (pi != NULL && pd[PI_OFF(index+i)] == MALLOC_FOLLOW) {
1282 pd[PI_OFF(index+i)] = MALLOC_FREE;
1283 i++;
1284 if (!PI_OFF(index+i)) {
1285 if ((pi=pi->next) == NULL || PD_IDX(pi->dirnum) != PI_IDX(index+i))
1286 pi = NULL;
1287 else
1288 pd = pi->base;
1289 }
1290 }
1291 1024
1292 l = i << malloc_pageshift; 1025 l = i << malloc_pageshift;
1293 1026
1294 if (malloc_junk) 1027 if (malloc_junk)
1295 memset(ptr, SOME_JUNK, l); 1028 memset(ptr, SOME_JUNK, l);
1296 1029
1297 malloc_used -= l;
1298 if (malloc_guard) {
1299#ifdef MALLOC_EXTRA_SANITY
1300 if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(index+i)) {
1301 wrterror("(ES): hole in mapped pages directory\n");
1302 errno = EFAULT;
1303 return;
1304 }
1305#endif /* MALLOC_EXTRA_SANITY */
1306 pd[PI_OFF(index+i)] = MALLOC_FREE;
1307 l += malloc_guard;
1308 }
1309 tail = (char *)ptr + l;
1310
1311#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE)) 1030#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE))
1312 if (malloc_hint) 1031 if (malloc_hint)
1313 madvise(ptr, l, MADV_FREE); 1032 madvise(ptr, l, MADV_FREE);
1314#endif 1033#endif
1315 1034
1035 if (malloc_guard) {
1036 page_dir[index + i] = MALLOC_FREE;
1037 l += malloc_guard;
1038 }
1039 tail = (char *)ptr+l;
1040
1316 if (malloc_freeprot) 1041 if (malloc_freeprot)
1317 mprotect(ptr, l, PROT_NONE); 1042 mprotect(ptr, tail - ptr, PROT_NONE);
1318 1043
1319 /* Add to free-list. */ 1044 /* add to free-list */
1320 if (px == NULL) 1045 if (px == NULL)
1321 px = imalloc(sizeof *px); /* This cannot fail... */ 1046 px = imalloc(sizeof *px); /* This cannot fail... */
1322 px->page = ptr; 1047 px->page = ptr;
1323 px->pdir = spi; 1048 px->end = tail;
1324 px->size = l; 1049 px->size = l;
1325 1050
1326 if (free_list.next == NULL) { 1051 if (free_list.next == NULL) {
1327 1052
1328 /* Nothing on free list, put this at head. */ 1053 /* Nothing on free list, put this at head */
1329 px->next = NULL; 1054 px->next = free_list.next;
1330 px->prev = &free_list; 1055 px->prev = &free_list;
1331 free_list.next = px; 1056 free_list.next = px;
1332 pf = px; 1057 pf = px;
@@ -1336,9 +1061,9 @@ free_pages(void *ptr, u_long index, struct pginfo *info)
1336 1061
1337 /* Find the right spot, leave pf pointing to the modified entry. */ 1062 /* Find the right spot, leave pf pointing to the modified entry. */
1338 1063
1339 for(pf = free_list.next; (pf->page+pf->size) < ptr && pf->next != NULL; 1064 for(pf = free_list.next; pf->end < ptr && pf->next != NULL;
1340 pf = pf->next) 1065 pf = pf->next)
1341 ; /* Race ahead here. */ 1066 ; /* Race ahead here */
1342 1067
1343 if (pf->page > tail) { 1068 if (pf->page > tail) {
1344 /* Insert before entry */ 1069 /* Insert before entry */
@@ -1348,24 +1073,25 @@ free_pages(void *ptr, u_long index, struct pginfo *info)
1348 px->prev->next = px; 1073 px->prev->next = px;
1349 pf = px; 1074 pf = px;
1350 px = NULL; 1075 px = NULL;
1351 } else if ((pf->page + pf->size) == ptr ) { 1076 } else if (pf->end == ptr ) {
1352 /* Append to the previous entry. */ 1077 /* Append to the previous entry */
1078 pf->end = (char *)pf->end + l;
1353 pf->size += l; 1079 pf->size += l;
1354 if (pf->next != NULL && (pf->page + pf->size) == pf->next->page ) { 1080 if (pf->next != NULL && pf->end == pf->next->page ) {
1355 /* And collapse the next too. */ 1081 /* And collapse the next too. */
1356 pt = pf->next; 1082 pt = pf->next;
1083 pf->end = pt->end;
1357 pf->size += pt->size; 1084 pf->size += pt->size;
1358 pf->next = pt->next; 1085 pf->next = pt->next;
1359 if (pf->next != NULL) 1086 if (pf->next != NULL)
1360 pf->next->prev = pf; 1087 pf->next->prev = pf;
1361 } 1088 }
1362 } else if (pf->page == tail) { 1089 } else if (pf->page == tail) {
1363 /* Prepend to entry. */ 1090 /* Prepend to entry */
1364 pf->size += l; 1091 pf->size += l;
1365 pf->page = ptr; 1092 pf->page = ptr;
1366 pf->pdir = spi;
1367 } else if (pf->next == NULL) { 1093 } else if (pf->next == NULL) {
1368 /* Append at tail of chain. */ 1094 /* Append at tail of chain */
1369 px->next = NULL; 1095 px->next = NULL;
1370 px->prev = pf; 1096 px->prev = pf;
1371 pf->next = px; 1097 pf->next = px;
@@ -1373,80 +1099,34 @@ free_pages(void *ptr, u_long index, struct pginfo *info)
1373 px = NULL; 1099 px = NULL;
1374 } else { 1100 } else {
1375 wrterror("freelist is destroyed\n"); 1101 wrterror("freelist is destroyed\n");
1376 errno = EFAULT;
1377 return;
1378 } 1102 }
1379 } 1103 }
1380 1104
1381 if (pf->pdir != last_dir) {
1382 prev_dir = last_dir;
1383 last_dir = pf->pdir;
1384 }
1385
1386 /* Return something to OS ? */ 1105 /* Return something to OS ? */
1387 if (pf->next == NULL && /* If we're the last one, */ 1106 if (pf->next == NULL && /* If we're the last one, */
1388 pf->size > malloc_cache && /* ..and the cache is full, */ 1107 pf->size > malloc_cache && /* ..and the cache is full, */
1389 (pf->page + pf->size) == malloc_brk) { /* ..and none behind us, */ 1108 pf->end == malloc_brk && /* ..and none behind us, */
1109 malloc_brk == sbrk(0)) { /* ..and it's OK to do... */
1390 1110
1391 /* 1111 /*
1392 * Keep the cache intact. Notice that the '>' above guarantees that 1112 * Keep the cache intact. Notice that the '>' above guarantees that
1393 * the pf will always have at least one page afterwards. 1113 * the pf will always have at least one page afterwards.
1394 */ 1114 */
1395 if (munmap((char *)pf->page + malloc_cache, pf->size - malloc_cache)!=0) 1115 pf->end = (char *)pf->page + malloc_cache;
1396 goto not_return;
1397 tail = pf->page + pf->size;
1398 lidx = ptr2index(tail) - 1;
1399 pf->size = malloc_cache; 1116 pf->size = malloc_cache;
1400 1117
1401 malloc_brk = pf->page + malloc_cache; 1118 brk(pf->end);
1402 1119 malloc_brk = pf->end;
1403 index = ptr2index(malloc_brk);
1404
1405 pidx = PI_IDX(index);
1406 if (prev_dir != NULL && PD_IDX(prev_dir->dirnum) >= pidx)
1407 prev_dir = NULL; /* Will be wiped out below ! */
1408 1120
1409 for (pi=pf->pdir; pi!=NULL && PD_IDX(pi->dirnum)<pidx; pi=pi->next); 1121 index = ptr2index(pf->end);
1410 1122
1411 if (pi != NULL && PD_IDX(pi->dirnum) == pidx) { 1123 for(i=index;i <= last_index;)
1412 pd = pi->base; 1124 page_dir[i++] = MALLOC_NOT_MINE;
1413
1414 for(i=index;i <= last_index;) {
1415 if (pd[PI_OFF(i)] != MALLOC_NOT_MINE) {
1416 pd[PI_OFF(i)] = MALLOC_NOT_MINE;
1417#ifdef MALLOC_EXTRA_SANITY
1418 if (!PD_OFF(pi->dirnum)) {
1419 wrterror("(ES): pages directory underflow\n");
1420 errno = EFAULT;
1421 return;
1422 }
1423#endif /* MALLOC_EXTRA_SANITY */
1424 pi->dirnum--;
1425 }
1426 i++;
1427 if (!PI_OFF(i)) {
1428 /* If no page in that dir, free directory page. */
1429 if (!PD_OFF(pi->dirnum)) {
1430 /* Remove from list. */
1431 pi->prev->next = pi->next;
1432 if (pi->next != NULL)
1433 pi->next->prev = pi->prev;
1434 pi = pi->next;
1435 munmap(pd, malloc_pagesize);
1436 } else
1437 pi = pi->next;
1438 if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(i))
1439 break;
1440 pd = pi->base;
1441 }
1442 }
1443 }
1444 1125
1445 last_index = index - 1; 1126 last_index = index - 1;
1446 1127
1447 /* XXX: We could realloc/shrink the pagedir here I guess. */ 1128 /* XXX: We could realloc/shrink the pagedir here I guess. */
1448 } 1129 }
1449not_return:
1450 if (pt != NULL) 1130 if (pt != NULL)
1451 ifree(pt); 1131 ifree(pt);
1452} 1132}
@@ -1461,9 +1141,6 @@ free_bytes(void *ptr, int index, struct pginfo *info)
1461{ 1141{
1462 int i; 1142 int i;
1463 struct pginfo **mp; 1143 struct pginfo **mp;
1464 struct pginfo **pd;
1465 struct pdinfo *pi;
1466 u_long pidx;
1467 void *vp; 1144 void *vp;
1468 1145
1469 /* Find the chunk number on the page */ 1146 /* Find the chunk number on the page */
@@ -1495,8 +1172,7 @@ free_bytes(void *ptr, int index, struct pginfo *info)
1495 /* Page became non-full */ 1172 /* Page became non-full */
1496 1173
1497 /* Insert in address order */ 1174 /* Insert in address order */
1498 while (*mp != NULL && (*mp)->next != NULL && 1175 while (*mp && (*mp)->next && (*mp)->next->page < info->page)
1499 (*mp)->next->page < info->page)
1500 mp = &(*mp)->next; 1176 mp = &(*mp)->next;
1501 info->next = *mp; 1177 info->next = *mp;
1502 *mp = info; 1178 *mp = info;
@@ -1510,32 +1186,14 @@ free_bytes(void *ptr, int index, struct pginfo *info)
1510 while (*mp != info) { 1186 while (*mp != info) {
1511 mp = &((*mp)->next); 1187 mp = &((*mp)->next);
1512#ifdef MALLOC_EXTRA_SANITY 1188#ifdef MALLOC_EXTRA_SANITY
1513 if (!*mp) { 1189 if (!*mp)
1514 wrterror("(ES): Not on queue\n"); 1190 wrterror("(ES): Not on queue\n");
1515 errno = EFAULT;
1516 return;
1517 }
1518#endif /* MALLOC_EXTRA_SANITY */ 1191#endif /* MALLOC_EXTRA_SANITY */
1519 } 1192 }
1520 *mp = info->next; 1193 *mp = info->next;
1521 1194
1522 /* Free the page & the info structure if need be */ 1195 /* Free the page & the info structure if need be */
1523 pidx = PI_IDX(ptr2index(info->page)); 1196 page_dir[ptr2index(info->page)] = MALLOC_FIRST;
1524 pdir_lookup(ptr2index(info->page), &pi);
1525#ifdef MALLOC_EXTRA_SANITY
1526 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
1527 wrterror("(ES): mapped pages not found in directory\n");
1528 errno = EFAULT;
1529 return;
1530 }
1531#endif /* MALLOC_EXTRA_SANITY */
1532 if (pi != last_dir) {
1533 prev_dir = last_dir;
1534 last_dir = pi;
1535 }
1536
1537 pd = pi->base;
1538 pd[PI_OFF(ptr2index(info->page))] = MALLOC_FIRST;
1539 1197
1540 /* If the page was mprotected, unprotect it before releasing it */ 1198 /* If the page was mprotected, unprotect it before releasing it */
1541 if (info->size == 0) { 1199 if (info->size == 0) {
@@ -1553,9 +1211,6 @@ static void
1553ifree(void *ptr) 1211ifree(void *ptr)
1554{ 1212{
1555 struct pginfo *info; 1213 struct pginfo *info;
1556 struct pginfo **pd;
1557 struct pdinfo *pi;
1558 u_long pidx;
1559 u_long index; 1214 u_long index;
1560 1215
1561 /* This is legal */ 1216 /* This is legal */
@@ -1583,22 +1238,7 @@ ifree(void *ptr)
1583 return; 1238 return;
1584 } 1239 }
1585 1240
1586 pidx = PI_IDX(index); 1241 info = page_dir[index];
1587 pdir_lookup(index, &pi);
1588#ifdef MALLOC_EXTRA_SANITY
1589 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
1590 wrterror("(ES): mapped pages not found in directory\n");
1591 errno = EFAULT;
1592 return;
1593 }
1594#endif /* MALLOC_EXTRA_SANITY */
1595 if (pi != last_dir) {
1596 prev_dir = last_dir;
1597 last_dir = pi;
1598 }
1599
1600 pd = pi->base;
1601 info = pd[PI_OFF(index)];
1602 1242
1603 if (info < MALLOC_MAGIC) 1243 if (info < MALLOC_MAGIC)
1604 free_pages(ptr, index, info); 1244 free_pages(ptr, index, info);
@@ -1617,10 +1257,9 @@ malloc_recurse(void)
1617{ 1257{
1618 static int noprint; 1258 static int noprint;
1619 1259
1620 if (noprint == 0) { 1260 if (noprint == 0)
1621 noprint = 1;
1622 wrtwarning("recursive call\n"); 1261 wrtwarning("recursive call\n");
1623 } 1262 noprint = 1;
1624 malloc_active--; 1263 malloc_active--;
1625 _MALLOC_UNLOCK(); 1264 _MALLOC_UNLOCK();
1626 errno = EDEADLK; 1265 errno = EDEADLK;
@@ -1644,10 +1283,8 @@ malloc(size_t size)
1644 UTRACE(0, size, r); 1283 UTRACE(0, size, r);
1645 malloc_active--; 1284 malloc_active--;
1646 _MALLOC_UNLOCK(); 1285 _MALLOC_UNLOCK();
1647 if (malloc_xmalloc && r == NULL) { 1286 if (malloc_xmalloc && r == NULL)
1648 wrterror("out of memory\n"); 1287 wrterror("out of memory\n");
1649 errno = ENOMEM;
1650 }
1651 return (r); 1288 return (r);
1652} 1289}
1653 1290
@@ -1686,9 +1323,7 @@ realloc(void *ptr, size_t size)
1686 UTRACE(ptr, size, r); 1323 UTRACE(ptr, size, r);
1687 malloc_active--; 1324 malloc_active--;
1688 _MALLOC_UNLOCK(); 1325 _MALLOC_UNLOCK();
1689 if (malloc_xmalloc && r == NULL) { 1326 if (malloc_xmalloc && r == NULL)
1690 wrterror("out of memory\n"); 1327 wrterror("out of memory\n");
1691 errno = ENOMEM;
1692 }
1693 return (r); 1328 return (r);
1694} 1329}