summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/libc/stdlib/malloc.c656
1 files changed, 475 insertions, 181 deletions
diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c
index ffb74717e2..139c99aa6d 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.67 2004/04/12 09:25:11 tdeval Exp $"; 11static char rcsid[] = "$OpenBSD: malloc.c,v 1.68 2004/08/01 08:45:39 tdeval Exp $";
12#endif /* LIBC_SCCS and not lint */ 12#endif /* LIBC_SCCS and not lint */
13 13
14/* 14/*
@@ -38,6 +38,8 @@ static char rcsid[] = "$OpenBSD: malloc.c,v 1.67 2004/04/12 09:25:11 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>
41#include <sys/param.h> 43#include <sys/param.h>
42#include <sys/mman.h> 44#include <sys/mman.h>
43#include <sys/uio.h> 45#include <sys/uio.h>
@@ -79,11 +81,11 @@ static char rcsid[] = "$OpenBSD: malloc.c,v 1.67 2004/04/12 09:25:11 tdeval Exp
79struct pginfo { 81struct pginfo {
80 struct pginfo *next; /* next on the free list */ 82 struct pginfo *next; /* next on the free list */
81 void *page; /* Pointer to the page */ 83 void *page; /* Pointer to the page */
82 u_short size; /* size of this page's chunks */ 84 u_short size; /* size of this page's chunks */
83 u_short shift; /* How far to shift for this size chunks */ 85 u_short shift; /* How far to shift for this size chunks */
84 u_short free; /* How many free chunks */ 86 u_short free; /* How many free chunks */
85 u_short total; /* How many chunk */ 87 u_short total; /* How many chunk */
86 u_long bits[1]; /* Which chunks are free */ 88 u_long bits[1]; /* Which chunks are free */
87}; 89};
88 90
89/* 91/*
@@ -94,8 +96,8 @@ struct pgfree {
94 struct pgfree *next; /* next run of free pages */ 96 struct pgfree *next; /* next run of free pages */
95 struct pgfree *prev; /* prev run of free pages */ 97 struct pgfree *prev; /* prev run of free pages */
96 void *page; /* pointer to free pages */ 98 void *page; /* pointer to free pages */
97 void *end; /* pointer to end of free pages */ 99 void *pdir; /* pointer to the base page's dir */
98 u_long size; /* number of bytes free */ 100 size_t size; /* number of bytes free */
99}; 101};
100 102
101/* 103/*
@@ -140,8 +142,8 @@ struct pgfree {
140/* A mask for the offset inside a page. */ 142/* A mask for the offset inside a page. */
141#define malloc_pagemask ((malloc_pagesize)-1) 143#define malloc_pagemask ((malloc_pagesize)-1)
142 144
143#define pageround(foo) (((foo) + (malloc_pagemask))&(~(malloc_pagemask))) 145#define pageround(foo) (((foo) + (malloc_pagemask)) & ~malloc_pagemask)
144#define ptr2index(foo) (((u_long)(foo) >> malloc_pageshift)-malloc_origo) 146#define ptr2index(foo) (((u_long)(foo) >> malloc_pageshift)+malloc_pageshift)
145 147
146/* fd of /dev/zero */ 148/* fd of /dev/zero */
147#ifdef USE_DEV_ZERO 149#ifdef USE_DEV_ZERO
@@ -161,8 +163,22 @@ static unsigned int malloc_started;
161/* Number of free pages we cache */ 163/* Number of free pages we cache */
162static unsigned int malloc_cache = 16; 164static unsigned int malloc_cache = 16;
163 165
164/* The offset from pagenumber to index into the page directory */ 166/* Structure used for linking discrete directory pages. */
165static u_long malloc_origo; 167struct pdinfo {
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)
166 182
167/* The last index in the page directory we care about */ 183/* The last index in the page directory we care about */
168static u_long last_index; 184static u_long last_index;
@@ -231,72 +247,144 @@ void utrace(struct ut *, int);
231/* Status of malloc. */ 247/* Status of malloc. */
232static int malloc_active; 248static int malloc_active;
233 249
234/* my last break. */ 250/* Allocated memory. */
251static size_t malloc_used;
252
253/* My last break. */
235static void *malloc_brk; 254static void *malloc_brk;
236 255
237/* one location cache for free-list holders */ 256/* One location cache for free-list holders. */
238static struct pgfree *px; 257static struct pgfree *px;
239 258
240/* compile-time options */ 259/* Compile-time options. */
241char *malloc_options; 260char *malloc_options;
242 261
243/* Name of the current public function */ 262/* Name of the current public function. */
244static char *malloc_func; 263static char *malloc_func;
245 264
246/* Macro for mmap */ 265/* Macro for mmap. */
247#define MMAP(size) \ 266#define MMAP(size) \
248 mmap((void *)0, (size), PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, \ 267 mmap((void *)0, (size), PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, \
249 MMAP_FD, (off_t)0) 268 MMAP_FD, (off_t)0)
250 269
251/* 270/*
252 * Necessary function declarations 271 * Necessary function declarations.
253 */ 272 */
254static int extend_pgdir(u_long index);
255static void *imalloc(size_t size); 273static void *imalloc(size_t size);
256static void ifree(void *ptr); 274static void ifree(void *ptr);
257static void *irealloc(void *ptr, size_t size); 275static void *irealloc(void *ptr, size_t size);
258static void *malloc_bytes(size_t size); 276static void *malloc_bytes(size_t size);
259 277
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
260#ifdef MALLOC_STATS 321#ifdef MALLOC_STATS
261void 322void
262malloc_dump(FILE *fd) 323malloc_dump(FILE *fd)
263{ 324{
264 struct pginfo **pd; 325 struct pginfo **pd;
265 struct pgfree *pf; 326 struct pgfree *pf;
327 struct pdinfo *pi;
266 int j; 328 int j;
267 329
268 pd = page_dir; 330 pd = page_dir;
331 pi = (struct pdinfo *)((caddr_t)pd + pdi_off);
269 332
270 /* print out all the pages */ 333 /* print out all the pages */
271 for(j=0;j<=last_index;j++) { 334 for(j=0;j<=last_index;) {
272 fprintf(fd, "%08lx %5d ", (j+malloc_origo) << malloc_pageshift, j); 335 fprintf(fd, "%08lx %5d ", j << malloc_pageshift, j);
273 if (pd[j] == MALLOC_NOT_MINE) { 336 if (pd[PI_OFF(j)] == MALLOC_NOT_MINE) {
274 for(j++;j<=last_index && pd[j] == MALLOC_NOT_MINE;j++) 337 for(j++;j<=last_index && pd[PI_OFF(j)] == MALLOC_NOT_MINE;) {
275 ; 338 if (!PI_OFF(++j)) {
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 }
276 j--; 345 j--;
277 fprintf(fd, ".. %5d not mine\n", j); 346 fprintf(fd, ".. %5d not mine\n", j);
278 } else if (pd[j] == MALLOC_FREE) { 347 } else if (pd[PI_OFF(j)] == MALLOC_FREE) {
279 for(j++;j<=last_index && pd[j] == MALLOC_FREE;j++) 348 for(j++;j<=last_index && pd[PI_OFF(j)] == MALLOC_FREE;) {
280 ; 349 if (!PI_OFF(++j)) {
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 }
281 j--; 356 j--;
282 fprintf(fd, ".. %5d free\n", j); 357 fprintf(fd, ".. %5d free\n", j);
283 } else if (pd[j] == MALLOC_FIRST) { 358 } else if (pd[PI_OFF(j)] == MALLOC_FIRST) {
284 for(j++;j<=last_index && pd[j] == MALLOC_FOLLOW;j++) 359 for(j++;j<=last_index && pd[PI_OFF(j)] == MALLOC_FOLLOW;) {
285 ; 360 if (!PI_OFF(++j)) {
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 }
286 j--; 367 j--;
287 fprintf(fd, ".. %5d in use\n", j); 368 fprintf(fd, ".. %5d in use\n", j);
288 } else if (pd[j] < MALLOC_MAGIC) { 369 } else if (pd[PI_OFF(j)] < MALLOC_MAGIC) {
289 fprintf(fd, "(%p)\n", pd[j]); 370 fprintf(fd, "(%p)\n", pd[PI_OFF(j)]);
290 } else { 371 } else {
291 fprintf(fd, "%p %d (of %d) x %d @ %p --> %p\n", 372 fprintf(fd, "%p %d (of %d) x %d @ %p --> %p\n",
292 pd[j], pd[j]->free, pd[j]->total, 373 pd[PI_OFF(j)], pd[PI_OFF(j)]->free, pd[PI_OFF(j)]->total,
293 pd[j]->size, pd[j]->page, pd[j]->next); 374 pd[PI_OFF(j)]->size, pd[PI_OFF(j)]->page, pd[PI_OFF(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;
294 } 381 }
295 } 382 }
296 383
297 for(pf=free_list.next; pf; pf=pf->next) { 384 for(pf=free_list.next; pf; pf=pf->next) {
298 fprintf(fd, "Free: @%p [%p...%p[ %ld ->%p <-%p\n", 385 fprintf(fd, "Free: @%p [%p...%p[ %ld ->%p <-%p\n",
299 pf, pf->page, pf->end, pf->size, pf->prev, pf->next); 386 pf, pf->page, pf->page + pf->size, pf->size,
387 pf->prev, pf->next);
300 if (pf == pf->next) { 388 if (pf == pf->next) {
301 fprintf(fd, "Free_list loops\n"); 389 fprintf(fd, "Free_list loops\n");
302 break; 390 break;
@@ -308,10 +396,7 @@ malloc_dump(FILE *fd)
308 fprintf(fd, "Maxsize\t%d\n", malloc_maxsize); 396 fprintf(fd, "Maxsize\t%d\n", malloc_maxsize);
309 fprintf(fd, "Pagesize\t%lu\n", (u_long)malloc_pagesize); 397 fprintf(fd, "Pagesize\t%lu\n", (u_long)malloc_pagesize);
310 fprintf(fd, "Pageshift\t%d\n", malloc_pageshift); 398 fprintf(fd, "Pageshift\t%d\n", malloc_pageshift);
311 fprintf(fd, "FirstPage\t%ld\n", malloc_origo); 399 fprintf(fd, "In use\t%lu\n", (u_long)malloc_used);
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);
315} 400}
316#endif /* MALLOC_STATS */ 401#endif /* MALLOC_STATS */
317 402
@@ -385,90 +470,84 @@ malloc_exit(void)
385static void * 470static void *
386map_pages(size_t pages) 471map_pages(size_t pages)
387{ 472{
388 caddr_t result, tail; 473 struct pdinfo *pi, *spi;
474 struct pginfo **pd;
475 u_long pidx,lidx;
476 void *result, *tail;
477 u_long index;
389 478
390 result = (caddr_t)pageround((u_long)sbrk(0));
391 pages <<= malloc_pageshift; 479 pages <<= malloc_pageshift;
392 if (pages > SIZE_T_MAX - (size_t)result) { 480 result = MMAP(pages + malloc_guard);
393#ifdef MALLOC_EXTRA_SANITY 481 if (result == MAP_FAILED) {
394 wrtwarning("(ES): overflow in map_pages fails\n");
395#endif /* MALLOC_EXTRA_SANITY */
396 errno = ENOMEM; 482 errno = ENOMEM;
397 return (NULL);
398 }
399 tail = result + pages + malloc_guard;
400
401 if (brk(tail) == (char *)-1) {
402#ifdef MALLOC_EXTRA_SANITY 483#ifdef MALLOC_EXTRA_SANITY
403 wrtwarning("(ES): map_pages fails\n"); 484 wrtwarning("(ES): map_pages fails\n");
404#endif /* MALLOC_EXTRA_SANITY */ 485#endif /* MALLOC_EXTRA_SANITY */
405 return (NULL); 486 return (NULL);
406 } 487 }
488 tail = result + pages + malloc_guard;
407 if (malloc_guard) 489 if (malloc_guard)
408 mprotect(result + pages, malloc_pagesize, PROT_NONE); 490 mprotect(result + pages, malloc_guard, PROT_NONE);
409
410 last_index = ptr2index(tail) - 1;
411 malloc_brk = tail;
412 491
413 if ((last_index+1) >= malloc_ninfo && !extend_pgdir(last_index)) 492 if (tail > malloc_brk)
414 return (NULL); 493 malloc_brk = tail;
494 if ((index = ptr2index(tail) - 1) > last_index)
495 last_index = index;
415 496
416 return (result); 497 /* Insert directory pages, if needed. */
417} 498 pidx = PI_IDX(ptr2index(result));
499 lidx = PI_IDX(index);
418 500
419/* 501 pdir_lookup(ptr2index(result), &pi);
420 * Extend page directory
421 */
422static int
423extend_pgdir(u_long index)
424{
425 struct pginfo **new, **old;
426 size_t i, oldlen;
427 502
428 /* Make it this many pages */ 503 for (index=pidx,spi=pi;index<=lidx;index++) {
429 i = index * sizeof *page_dir; 504 if (pi == NULL || PD_IDX(pi->dirnum) != index) {
430 i /= malloc_pagesize; 505 if ((pd = MMAP(malloc_pagesize)) == MAP_FAILED) {
431 i += 2; 506 errno = ENOMEM;
432 507 munmap(result, tail - result);
433 /* remember the old mapping size */ 508#ifdef MALLOC_EXTRA_SANITY
434 oldlen = malloc_ninfo * sizeof *page_dir; 509 wrtwarning("(ES): map_pages fails\n");
435 510#endif /* MALLOC_EXTRA_SANITY */
436 /* 511 return (NULL);
437 * NOTE: we allocate new pages and copy the directory rather than tempt 512 }
438 * fate by trying to "grow" the region.. There is nothing to prevent 513 memset(pd, 0, malloc_pagesize);
439 * us from accidently re-mapping space that's been allocated by our caller 514 pi = (struct pdinfo *)((caddr_t)pd + pdi_off);
440 * via dlopen() or other mmap(). 515 pi->base = pd;
441 * 516 pi->prev = spi;
442 * The copy problem is not too bad, as there is 4K of page index per 517 pi->next = spi->next;
443 * 4MB of malloc arena. 518 pi->dirnum = index * (malloc_pagesize/sizeof(struct pginfo *));
444 * 519
445 * We can totally avoid the copy if we open a file descriptor to associate 520 if (spi->next != NULL)
446 * the anon mappings with. Then, when we remap the pages at the new 521 spi->next->prev = pi;
447 * address, the old pages will be "magically" remapped.. But this means 522 spi->next = pi;
448 * keeping open a "secret" file descriptor..... 523 }
449 */ 524 if (index > pidx && index < lidx) {
450 525 pi->dirnum += pdi_mod;
451 /* Get new pages */ 526 } else if (index == pidx) {
452 new = (struct pginfo**) MMAP(i * malloc_pagesize); 527 if (pidx == lidx) {
453 if (new == MAP_FAILED) 528 pi->dirnum += (tail - result) >> malloc_pageshift;
454 return (0); 529 } else {
455 530 pi->dirnum += pdi_mod - PI_OFF(ptr2index(result));
456 /* Copy the old stuff */ 531 }
457 memcpy(new, page_dir, 532 } else {
458 malloc_ninfo * sizeof *page_dir); 533 pi->dirnum += PI_OFF(ptr2index(tail - 1)) + 1;
459 534 }
460 /* register the new size */ 535#ifdef MALLOC_EXTRA_SANITY
461 malloc_ninfo = i * malloc_pagesize / sizeof *page_dir; 536 if (PD_OFF(pi->dirnum) > pdi_mod || PD_IDX(pi->dirnum) > index)
462 537 wrterror("(ES): pages directory overflow\n");
463 /* swap the pointers */ 538#endif /* MALLOC_EXTRA_SANITY */
464 old = page_dir; 539 if (index == pidx && pi != last_dir) {
465 page_dir = new; 540 prev_dir = last_dir;
541 last_dir = pi;
542 }
543 spi = pi;
544 pi = spi->next;
545 }
466 546
467 /* Now free the old stuff */ 547 return (result);
468 munmap(old, oldlen);
469 return (1);
470} 548}
471 549
550
472/* 551/*
473 * Initialize the world 552 * Initialize the world
474 */ 553 */
@@ -520,12 +599,12 @@ malloc_init(void)
520 case 'h': malloc_hint = 0; break; 599 case 'h': malloc_hint = 0; break;
521 case 'H': malloc_hint = 1; break; 600 case 'H': malloc_hint = 1; break;
522#endif /* __FreeBSD__ */ 601#endif /* __FreeBSD__ */
523 case 'r': malloc_realloc = 0; break;
524 case 'R': malloc_realloc = 1; break;
525 case 'j': malloc_junk = 0; break; 602 case 'j': malloc_junk = 0; break;
526 case 'J': malloc_junk = 1; break; 603 case 'J': malloc_junk = 1; break;
527 case 'n': malloc_silent = 0; break; 604 case 'n': malloc_silent = 0; break;
528 case 'N': malloc_silent = 1; break; 605 case 'N': malloc_silent = 1; break;
606 case 'r': malloc_realloc = 0; break;
607 case 'R': malloc_realloc = 1; break;
529#ifdef __FreeBSD__ 608#ifdef __FreeBSD__
530 case 'u': malloc_utrace = 0; break; 609 case 'u': malloc_utrace = 0; break;
531 case 'U': malloc_utrace = 1; break; 610 case 'U': malloc_utrace = 1; break;
@@ -564,14 +643,15 @@ malloc_init(void)
564 if (page_dir == MAP_FAILED) 643 if (page_dir == MAP_FAILED)
565 wrterror("mmap(2) failed, check limits\n"); 644 wrterror("mmap(2) failed, check limits\n");
566 645
567 /* 646 pdi_off = (malloc_pagesize - sizeof(struct pdinfo)) & ~(malloc_minsize - 1);
568 * We need a maximum of malloc_pageshift buckets, steal these from the 647 pdi_mod = pdi_off / sizeof(struct pginfo *);
569 * front of the page_directory; 648
570 */ 649 last_dir = (struct pdinfo *)((caddr_t)page_dir + pdi_off);
571 malloc_origo = ((u_long)pageround((u_long)sbrk(0))) >> malloc_pageshift; 650 last_dir->base = page_dir;
572 malloc_origo -= malloc_pageshift; 651 last_dir->prev = last_dir->next = NULL;
652 last_dir->dirnum = malloc_pageshift;
573 653
574 malloc_ninfo = malloc_pagesize / sizeof *page_dir; 654 malloc_ninfo = pdi_mod;
575 655
576 /* Been here, done that */ 656 /* Been here, done that */
577 malloc_started++; 657 malloc_started++;
@@ -583,11 +663,6 @@ malloc_init(void)
583 663
584 malloc_cache <<= malloc_pageshift; 664 malloc_cache <<= malloc_pageshift;
585 665
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);
591 errno = save_errno; 666 errno = save_errno;
592} 667}
593 668
@@ -599,29 +674,49 @@ malloc_pages(size_t size)
599{ 674{
600 void *p, *delay_free = NULL; 675 void *p, *delay_free = NULL;
601 int i; 676 int i;
677 struct rlimit rl;
678 struct pginfo **pd;
679 struct pdinfo *pi;
680 u_long pidx;
681 void *tp;
602 struct pgfree *pf; 682 struct pgfree *pf;
603 u_long index; 683 u_long index;
684 int m;
604 685
605 size = pageround(size) + malloc_guard; 686 size = pageround(size) + malloc_guard;
606 687
688 if (getrlimit(RLIMIT_DATA, &rl) == -1)
689 wrterror("process limits not available\n");
690 if (rl.rlim_cur != RLIM_INFINITY &&
691 size > ((size_t)rl.rlim_cur - malloc_used)) {
692 errno = ENOMEM;
693 return (NULL);
694 }
695
607 p = NULL; 696 p = NULL;
608 /* Look for free pages before asking for more */ 697 /* Look for free pages before asking for more */
609 for(pf = free_list.next; pf; pf = pf->next) { 698 for (pf = free_list.next; pf; pf = pf->next) {
610 699
611#ifdef MALLOC_EXTRA_SANITY 700#ifdef MALLOC_EXTRA_SANITY
612 if (pf->size & malloc_pagemask) 701 if (pf->size & malloc_pagemask)
613 wrterror("(ES): junk length entry on free_list\n"); 702 wrterror("(ES): junk length entry on free_list\n");
614 if (!pf->size) 703 if (!pf->size)
615 wrterror("(ES): zero length entry on free_list\n"); 704 wrterror("(ES): zero length entry on free_list\n");
616 if (pf->page == pf->end) 705 if (pf->page > (pf->page + pf->size))
617 wrterror("(ES): zero entry on free_list\n");
618 if (pf->page > pf->end)
619 wrterror("(ES): sick entry on free_list\n"); 706 wrterror("(ES): sick entry on free_list\n");
620 if ((void*)pf->page >= (void*)sbrk(0)) 707 if ((pi = pf->pdir) == NULL)
621 wrterror("(ES): entry on free_list past brk\n"); 708 wrterror("(ES): invalid page directory on free-list\n");
622 if (page_dir[ptr2index(pf->page)] != MALLOC_FREE) 709 if ((pidx = PI_IDX(ptr2index(pf->page))) != PD_IDX(pi->dirnum))
710 wrterror("(ES): directory index mismatch on free-list\n");
711 pd = pi->base;
712 if (pd[PI_OFF(ptr2index(pf->page))] != MALLOC_FREE)
623 wrterror("(ES): non-free first page on free-list\n"); 713 wrterror("(ES): non-free first page on free-list\n");
624 if (page_dir[ptr2index(pf->end)-1] != MALLOC_FREE) 714 pidx = PI_IDX(ptr2index((pf->page)+(pf->size))-1);
715 for (pi=pf->pdir; pi!=NULL && PD_IDX(pi->dirnum)<pidx; pi=pi->next);
716 if (pi == NULL || PD_IDX(pi->dirnum) != pidx)
717 wrterror("(ES): last page not referenced in page directory\n");
718 pd = pi->base;
719 if (pd[PI_OFF(ptr2index((pf->page)+(pf->size))-1)] != MALLOC_FREE)
625 wrterror("(ES): non-free last page on free-list\n"); 720 wrterror("(ES): non-free last page on free-list\n");
626#endif /* MALLOC_EXTRA_SANITY */ 721#endif /* MALLOC_EXTRA_SANITY */
627 722
@@ -630,6 +725,7 @@ malloc_pages(size_t size)
630 725
631 if (pf->size == size) { 726 if (pf->size == size) {
632 p = pf->page; 727 p = pf->page;
728 pi = pf->pdir;
633 if (pf->next != NULL) 729 if (pf->next != NULL)
634 pf->next->prev = pf->prev; 730 pf->next->prev = pf->prev;
635 pf->prev->next = pf->next; 731 pf->prev->next = pf->next;
@@ -640,17 +736,28 @@ malloc_pages(size_t size)
640 p = pf->page; 736 p = pf->page;
641 pf->page = (char *)pf->page + size; 737 pf->page = (char *)pf->page + size;
642 pf->size -= size; 738 pf->size -= size;
739 pidx = PI_IDX(ptr2index(pf->page));
740 for (pi=pf->pdir; pi!=NULL && PD_IDX(pi->dirnum)<pidx; pi=pi->next);
741 if (pi == NULL || PD_IDX(pi->dirnum) != pidx)
742 wrterror("(ES): hole in directories\n");
743 tp = pf->pdir;
744 pf->pdir = pi;
745 pi = tp;
643 break; 746 break;
644 } 747 }
645 748
646 size -= malloc_guard; 749 size -= malloc_guard;
647 750
648#ifdef MALLOC_EXTRA_SANITY 751#ifdef MALLOC_EXTRA_SANITY
649 if (p != NULL && page_dir[ptr2index(p)] != MALLOC_FREE) 752 if (p != NULL && pi != NULL) {
753 pidx = PD_IDX(pi->dirnum);
754 pd = pi->base;
755 }
756 if (p != NULL && pd[PI_OFF(ptr2index(p))] != MALLOC_FREE)
650 wrterror("(ES): allocated non-free page on free-list\n"); 757 wrterror("(ES): allocated non-free page on free-list\n");
651#endif /* MALLOC_EXTRA_SANITY */ 758#endif /* MALLOC_EXTRA_SANITY */
652 759
653 if ((malloc_guard || malloc_freeprot) && p != NULL) 760 if (p != NULL && (malloc_guard || malloc_freeprot))
654 mprotect(p, size, PROT_READ|PROT_WRITE); 761 mprotect(p, size, PROT_READ|PROT_WRITE);
655 762
656 size >>= malloc_pageshift; 763 size >>= malloc_pageshift;
@@ -662,9 +769,44 @@ malloc_pages(size_t size)
662 if (p != NULL) { 769 if (p != NULL) {
663 770
664 index = ptr2index(p); 771 index = ptr2index(p);
665 page_dir[index] = MALLOC_FIRST; 772 pidx = PI_IDX(index);
666 for (i=1;i<size;i++) 773 pdir_lookup(index, &pi);
667 page_dir[index+i] = MALLOC_FOLLOW; 774#ifdef MALLOC_EXTRA_SANITY
775 if (pi == NULL || PD_IDX(pi->dirnum) != pidx)
776 wrterror("(ES): mapped pages not found in directory\n");
777#endif /* MALLOC_EXTRA_SANITY */
778 if (pi != last_dir) {
779 prev_dir = last_dir;
780 last_dir = pi;
781 }
782 pd = pi->base;
783 pd[PI_OFF(index)] = MALLOC_FIRST;
784 for (i=1;i<size;i++) {
785 if (!PI_OFF(index+i)) {
786 pidx++;
787 pi = pi->next;
788#ifdef MALLOC_EXTRA_SANITY
789 if (pi == NULL || PD_IDX(pi->dirnum) != pidx)
790 wrterror("(ES): hole in mapped pages directory\n");
791#endif /* MALLOC_EXTRA_SANITY */
792 pd = pi->base;
793 }
794 pd[PI_OFF(index+i)] = MALLOC_FOLLOW;
795 }
796 if (malloc_guard) {
797 if (!PI_OFF(index+i)) {
798 pidx++;
799 pi = pi->next;
800#ifdef MALLOC_EXTRA_SANITY
801 if (pi == NULL || PD_IDX(pi->dirnum) != pidx)
802 wrterror("(ES): hole in mapped pages directory\n");
803#endif /* MALLOC_EXTRA_SANITY */
804 pd = pi->base;
805 }
806 pd[PI_OFF(index+i)] = MALLOC_FIRST;
807 }
808
809 malloc_used += size << malloc_pageshift;
668 810
669 if (malloc_junk) 811 if (malloc_junk)
670 memset(p, SOME_JUNK, size << malloc_pageshift); 812 memset(p, SOME_JUNK, size << malloc_pageshift);
@@ -687,7 +829,10 @@ malloc_pages(size_t size)
687static __inline__ int 829static __inline__ int
688malloc_make_chunks(int bits) 830malloc_make_chunks(int bits)
689{ 831{
690 struct pginfo *bp; 832 struct pginfo *bp;
833 struct pginfo **pd;
834 struct pdinfo *pi;
835 u_long pidx;
691 void *pp; 836 void *pp;
692 int i, k, l; 837 int i, k, l;
693 838
@@ -765,7 +910,18 @@ malloc_make_chunks(int bits)
765 910
766 /* MALLOC_LOCK */ 911 /* MALLOC_LOCK */
767 912
768 page_dir[ptr2index(pp)] = bp; 913 pidx = PI_IDX(ptr2index(pp));
914 pdir_lookup(ptr2index(pp), &pi);
915#ifdef MALLOC_EXTRA_SANITY
916 if (pi == NULL || PD_IDX(pi->dirnum) != pidx)
917 wrterror("(ES): mapped pages not found in directory\n");
918#endif /* MALLOC_EXTRA_SANITY */
919 if (pi != last_dir) {
920 prev_dir = last_dir;
921 last_dir = pi;
922 }
923 pd = pi->base;
924 pd[PI_OFF(ptr2index(pp))] = bp;
769 925
770 bp->next = page_dir[bits]; 926 bp->next = page_dir[bits];
771 page_dir[bits] = bp; 927 page_dir[bits] = bp;
@@ -819,7 +975,7 @@ malloc_bytes(size_t size)
819 u += u; 975 u += u;
820 k++; 976 k++;
821 } 977 }
822 978
823 if (malloc_guard) { 979 if (malloc_guard) {
824 /* Walk to a random position. */ 980 /* Walk to a random position. */
825 i = arc4random() % bp->free; 981 i = arc4random() % bp->free;
@@ -832,11 +988,11 @@ malloc_bytes(size_t size)
832 k = 0; 988 k = 0;
833 } 989 }
834#ifdef MALLOC_EXTRA_SANITY 990#ifdef MALLOC_EXTRA_SANITY
835 if (lp - bp->bits > (bp->total - 1) / MALLOC_BITS) 991 if (lp - bp->bits > (bp->total - 1) / MALLOC_BITS)
836 wrterror("chunk overflow\n"); 992 wrterror("chunk overflow\n");
837#endif /* MALLOC_EXTRA_SANITY */ 993#endif /* MALLOC_EXTRA_SANITY */
838 if (*lp & u) 994 if (*lp & u)
839 i--; 995 i--;
840 } 996 }
841 } 997 }
842 *lp ^= u; 998 *lp ^= u;
@@ -896,9 +1052,11 @@ static void *
896irealloc(void *ptr, size_t size) 1052irealloc(void *ptr, size_t size)
897{ 1053{
898 void *p; 1054 void *p;
899 u_long osize, index; 1055 u_long osize, index, i;
900 struct pginfo **mp; 1056 struct pginfo **mp;
901 int i; 1057 struct pginfo **pd;
1058 struct pdinfo *pi;
1059 u_long pidx;
902 1060
903 if (suicide) 1061 if (suicide)
904 abort(); 1062 abort();
@@ -920,7 +1078,19 @@ irealloc(void *ptr, size_t size)
920 return (NULL); 1078 return (NULL);
921 } 1079 }
922 1080
923 mp = &page_dir[index]; 1081 pidx = PI_IDX(index);
1082 pdir_lookup(index, &pi);
1083#ifdef MALLOC_EXTRA_SANITY
1084 if (pi == NULL || PD_IDX(pi->dirnum) != pidx)
1085 wrterror("(ES): mapped pages not found in directory\n");
1086#endif /* MALLOC_EXTRA_SANITY */
1087 if (pi != last_dir) {
1088 prev_dir = last_dir;
1089 last_dir = pi;
1090 }
1091
1092 pd = pi->base;
1093 mp = &pd[PI_OFF(index)];
924 1094
925 if (*mp == MALLOC_FIRST) { /* Page allocation */ 1095 if (*mp == MALLOC_FIRST) { /* Page allocation */
926 1096
@@ -931,8 +1101,25 @@ irealloc(void *ptr, size_t size)
931 } 1101 }
932 1102
933 /* Find the size in bytes */ 1103 /* Find the size in bytes */
934 for (osize = malloc_pagesize; *(++mp) == MALLOC_FOLLOW;) 1104 i = index;
1105 if (!PI_OFF(++i)) {
1106 pi = pi->next;
1107 if (pi != NULL && PD_IDX(pi->dirnum) != PI_IDX(i))
1108 pi = NULL;
1109 if (pi != NULL)
1110 pd = pi->base;
1111 }
1112 for (osize = malloc_pagesize;
1113 pi != NULL && pd[PI_OFF(i)] == MALLOC_FOLLOW;) {
935 osize += malloc_pagesize; 1114 osize += malloc_pagesize;
1115 if (!PI_OFF(++i)) {
1116 pi = pi->next;
1117 if (pi != NULL && PD_IDX(pi->dirnum) != PI_IDX(i))
1118 pi = NULL;
1119 if (pi != NULL)
1120 pd = pi->base;
1121 }
1122 }
936 1123
937 if (!malloc_realloc && /* Unless we have to, */ 1124 if (!malloc_realloc && /* Unless we have to, */
938 size <= osize && /* .. or are too small, */ 1125 size <= osize && /* .. or are too small, */
@@ -988,6 +1175,7 @@ irealloc(void *ptr, size_t size)
988 } 1175 }
989 ifree(ptr); 1176 ifree(ptr);
990 } 1177 }
1178
991 return (p); 1179 return (p);
992} 1180}
993 1181
@@ -999,6 +1187,9 @@ static __inline__ void
999free_pages(void *ptr, u_long index, struct pginfo *info) 1187free_pages(void *ptr, u_long index, struct pginfo *info)
1000{ 1188{
1001 u_long i, l; 1189 u_long i, l;
1190 struct pginfo **pd;
1191 struct pdinfo *pi, *spi;
1192 u_long pidx, lidx;
1002 struct pgfree *pf, *pt=NULL; 1193 struct pgfree *pf, *pt=NULL;
1003 void *tail; 1194 void *tail;
1004 1195
@@ -1018,40 +1209,71 @@ free_pages(void *ptr, u_long index, struct pginfo *info)
1018 } 1209 }
1019 1210
1020 /* Count how many pages and mark them free at the same time */ 1211 /* Count how many pages and mark them free at the same time */
1021 page_dir[index] = MALLOC_FREE; 1212 pidx = PI_IDX(index);
1022 for (i = 1; page_dir[index+i] == MALLOC_FOLLOW; i++) 1213 pdir_lookup(index, &pi);
1023 page_dir[index + i] = MALLOC_FREE; 1214#ifdef MALLOC_EXTRA_SANITY
1215 if (pi == NULL || PD_IDX(pi->dirnum) != pidx)
1216 wrterror("(ES): mapped pages not found in directory\n");
1217#endif /* MALLOC_EXTRA_SANITY */
1218
1219 spi = pi; /* Save page index for start of region. */
1220
1221 pd = pi->base;
1222 pd[PI_OFF(index)] = MALLOC_FREE;
1223 i = 1;
1224 if (!PI_OFF(index+i)) {
1225 pi = pi->next;
1226 if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(index+i))
1227 pi = NULL;
1228 else
1229 pd = pi->base;
1230 }
1231 while (pi != NULL && pd[PI_OFF(index+i)] == MALLOC_FOLLOW) {
1232 pd[PI_OFF(index+i)] = MALLOC_FREE;
1233 i++;
1234 if (!PI_OFF(index+i)) {
1235 if ((pi=pi->next) == NULL || PD_IDX(pi->dirnum) != PI_IDX(index+i))
1236 pi = NULL;
1237 else
1238 pd = pi->base;
1239 }
1240 }
1024 1241
1025 l = i << malloc_pageshift; 1242 l = i << malloc_pageshift;
1026 1243
1027 if (malloc_junk) 1244 if (malloc_junk)
1028 memset(ptr, SOME_JUNK, l); 1245 memset(ptr, SOME_JUNK, l);
1029 1246
1247 malloc_used -= l;
1248 if (malloc_guard) {
1249#ifdef MALLOC_EXTRA_SANITY
1250 if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(index+i))
1251 wrterror("(ES): hole in mapped pages directory\n");
1252#endif /* MALLOC_EXTRA_SANITY */
1253 pd[PI_OFF(index+i)] = MALLOC_FREE;
1254 l += malloc_guard;
1255 }
1256 tail = (char *)ptr + l;
1257
1030#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE)) 1258#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE))
1031 if (malloc_hint) 1259 if (malloc_hint)
1032 madvise(ptr, l, MADV_FREE); 1260 madvise(ptr, l, MADV_FREE);
1033#endif 1261#endif
1034 1262
1035 if (malloc_guard) {
1036 page_dir[index + i] = MALLOC_FREE;
1037 l += malloc_guard;
1038 }
1039 tail = (char *)ptr+l;
1040
1041 if (malloc_freeprot) 1263 if (malloc_freeprot)
1042 mprotect(ptr, tail - ptr, PROT_NONE); 1264 mprotect(ptr, l, PROT_NONE);
1043 1265
1044 /* add to free-list */ 1266 /* Add to free-list. */
1045 if (px == NULL) 1267 if (px == NULL)
1046 px = imalloc(sizeof *px); /* This cannot fail... */ 1268 px = imalloc(sizeof *px); /* This cannot fail... */
1047 px->page = ptr; 1269 px->page = ptr;
1048 px->end = tail; 1270 px->pdir = spi;
1049 px->size = l; 1271 px->size = l;
1050 1272
1051 if (free_list.next == NULL) { 1273 if (free_list.next == NULL) {
1052 1274
1053 /* Nothing on free list, put this at head */ 1275 /* Nothing on free list, put this at head. */
1054 px->next = free_list.next; 1276 px->next = NULL;
1055 px->prev = &free_list; 1277 px->prev = &free_list;
1056 free_list.next = px; 1278 free_list.next = px;
1057 pf = px; 1279 pf = px;
@@ -1061,9 +1283,9 @@ free_pages(void *ptr, u_long index, struct pginfo *info)
1061 1283
1062 /* Find the right spot, leave pf pointing to the modified entry. */ 1284 /* Find the right spot, leave pf pointing to the modified entry. */
1063 1285
1064 for(pf = free_list.next; pf->end < ptr && pf->next != NULL; 1286 for(pf = free_list.next; (pf->page+pf->size) < ptr && pf->next != NULL;
1065 pf = pf->next) 1287 pf = pf->next)
1066 ; /* Race ahead here */ 1288 ; /* Race ahead here. */
1067 1289
1068 if (pf->page > tail) { 1290 if (pf->page > tail) {
1069 /* Insert before entry */ 1291 /* Insert before entry */
@@ -1073,25 +1295,24 @@ free_pages(void *ptr, u_long index, struct pginfo *info)
1073 px->prev->next = px; 1295 px->prev->next = px;
1074 pf = px; 1296 pf = px;
1075 px = NULL; 1297 px = NULL;
1076 } else if (pf->end == ptr ) { 1298 } else if ((pf->page + pf->size) == ptr ) {
1077 /* Append to the previous entry */ 1299 /* Append to the previous entry. */
1078 pf->end = (char *)pf->end + l;
1079 pf->size += l; 1300 pf->size += l;
1080 if (pf->next != NULL && pf->end == pf->next->page ) { 1301 if (pf->next != NULL && (pf->page + pf->size) == pf->next->page ) {
1081 /* And collapse the next too. */ 1302 /* And collapse the next too. */
1082 pt = pf->next; 1303 pt = pf->next;
1083 pf->end = pt->end;
1084 pf->size += pt->size; 1304 pf->size += pt->size;
1085 pf->next = pt->next; 1305 pf->next = pt->next;
1086 if (pf->next != NULL) 1306 if (pf->next != NULL)
1087 pf->next->prev = pf; 1307 pf->next->prev = pf;
1088 } 1308 }
1089 } else if (pf->page == tail) { 1309 } else if (pf->page == tail) {
1090 /* Prepend to entry */ 1310 /* Prepend to entry. */
1091 pf->size += l; 1311 pf->size += l;
1092 pf->page = ptr; 1312 pf->page = ptr;
1313 pf->pdir = spi;
1093 } else if (pf->next == NULL) { 1314 } else if (pf->next == NULL) {
1094 /* Append at tail of chain */ 1315 /* Append at tail of chain. */
1095 px->next = NULL; 1316 px->next = NULL;
1096 px->prev = pf; 1317 px->prev = pf;
1097 pf->next = px; 1318 pf->next = px;
@@ -1102,31 +1323,72 @@ free_pages(void *ptr, u_long index, struct pginfo *info)
1102 } 1323 }
1103 } 1324 }
1104 1325
1326 if (pf->pdir != last_dir) {
1327 prev_dir = last_dir;
1328 last_dir = pf->pdir;
1329 }
1330
1105 /* Return something to OS ? */ 1331 /* Return something to OS ? */
1106 if (pf->next == NULL && /* If we're the last one, */ 1332 if (pf->next == NULL && /* If we're the last one, */
1107 pf->size > malloc_cache && /* ..and the cache is full, */ 1333 pf->size > malloc_cache && /* ..and the cache is full, */
1108 pf->end == malloc_brk && /* ..and none behind us, */ 1334 (pf->page + pf->size) == malloc_brk) { /* ..and none behind us, */
1109 malloc_brk == sbrk(0)) { /* ..and it's OK to do... */
1110 1335
1111 /* 1336 /*
1112 * Keep the cache intact. Notice that the '>' above guarantees that 1337 * Keep the cache intact. Notice that the '>' above guarantees that
1113 * the pf will always have at least one page afterwards. 1338 * the pf will always have at least one page afterwards.
1114 */ 1339 */
1115 pf->end = (char *)pf->page + malloc_cache; 1340 if (munmap((char *)pf->page + malloc_cache, pf->size - malloc_cache)!=0)
1341 goto not_return;
1342 tail = pf->page + pf->size;
1343 lidx = ptr2index(tail) - 1;
1116 pf->size = malloc_cache; 1344 pf->size = malloc_cache;
1117 1345
1118 brk(pf->end); 1346 malloc_brk = pf->page + malloc_cache;
1119 malloc_brk = pf->end;
1120 1347
1121 index = ptr2index(pf->end); 1348 index = ptr2index(malloc_brk);
1122 1349
1123 for(i=index;i <= last_index;) 1350 pidx = PI_IDX(index);
1124 page_dir[i++] = MALLOC_NOT_MINE; 1351 if (PD_IDX(prev_dir->dirnum) >= pidx)
1352 prev_dir = NULL; /* Will be wiped out below ! */
1353
1354 for (pi=pf->pdir; pi!=NULL && PD_IDX(pi->dirnum)<pidx; pi=pi->next);
1355
1356 if (pi != NULL && PD_IDX(pi->dirnum) == pidx) {
1357 pd = pi->base;
1358
1359 for(i=index;i <= last_index;) {
1360 if (pd[PI_OFF(i)] != MALLOC_NOT_MINE) {
1361 pd[PI_OFF(i)] = MALLOC_NOT_MINE;
1362#ifdef MALLOC_EXTRA_SANITY
1363 if (!PD_OFF(pi->dirnum))
1364 wrterror("(ES): pages directory underflow\n");
1365#endif /* MALLOC_EXTRA_SANITY */
1366 pi->dirnum--;
1367 }
1368 i++;
1369 if (!PI_OFF(i)) {
1370 /* If no page in that dir, free directory page. */
1371 if (!PD_OFF(pi->dirnum)) {
1372 /* Remove from list. */
1373 pi->prev->next = pi->next;
1374 if (pi->next != NULL)
1375 pi->next->prev = pi->prev;
1376 pi = pi->next;
1377 munmap(pd, malloc_pagesize);
1378 } else
1379 pi = pi->next;
1380 if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(i))
1381 break;
1382 pd = pi->base;
1383 }
1384 }
1385 }
1125 1386
1126 last_index = index - 1; 1387 last_index = index - 1;
1127 1388
1128 /* XXX: We could realloc/shrink the pagedir here I guess. */ 1389 /* XXX: We could realloc/shrink the pagedir here I guess. */
1129 } 1390 }
1391not_return:
1130 if (pt != NULL) 1392 if (pt != NULL)
1131 ifree(pt); 1393 ifree(pt);
1132} 1394}
@@ -1141,6 +1403,9 @@ free_bytes(void *ptr, int index, struct pginfo *info)
1141{ 1403{
1142 int i; 1404 int i;
1143 struct pginfo **mp; 1405 struct pginfo **mp;
1406 struct pginfo **pd;
1407 struct pdinfo *pi;
1408 u_long pidx;
1144 void *vp; 1409 void *vp;
1145 1410
1146 /* Find the chunk number on the page */ 1411 /* Find the chunk number on the page */
@@ -1172,7 +1437,8 @@ free_bytes(void *ptr, int index, struct pginfo *info)
1172 /* Page became non-full */ 1437 /* Page became non-full */
1173 1438
1174 /* Insert in address order */ 1439 /* Insert in address order */
1175 while (*mp && (*mp)->next && (*mp)->next->page < info->page) 1440 while (*mp != NULL && (*mp)->next != NULL &&
1441 (*mp)->next->page < info->page)
1176 mp = &(*mp)->next; 1442 mp = &(*mp)->next;
1177 info->next = *mp; 1443 info->next = *mp;
1178 *mp = info; 1444 *mp = info;
@@ -1193,7 +1459,19 @@ free_bytes(void *ptr, int index, struct pginfo *info)
1193 *mp = info->next; 1459 *mp = info->next;
1194 1460
1195 /* Free the page & the info structure if need be */ 1461 /* Free the page & the info structure if need be */
1196 page_dir[ptr2index(info->page)] = MALLOC_FIRST; 1462 pidx = PI_IDX(ptr2index(info->page));
1463 pdir_lookup(ptr2index(info->page), &pi);
1464#ifdef MALLOC_EXTRA_SANITY
1465 if (pi == NULL || PD_IDX(pi->dirnum) != pidx)
1466 wrterror("(ES): mapped pages not found in directory\n");
1467#endif /* MALLOC_EXTRA_SANITY */
1468 if (pi != last_dir) {
1469 prev_dir = last_dir;
1470 last_dir = pi;
1471 }
1472
1473 pd = pi->base;
1474 pd[PI_OFF(ptr2index(info->page))] = MALLOC_FIRST;
1197 1475
1198 /* If the page was mprotected, unprotect it before releasing it */ 1476 /* If the page was mprotected, unprotect it before releasing it */
1199 if (info->size == 0) { 1477 if (info->size == 0) {
@@ -1211,6 +1489,9 @@ static void
1211ifree(void *ptr) 1489ifree(void *ptr)
1212{ 1490{
1213 struct pginfo *info; 1491 struct pginfo *info;
1492 struct pginfo **pd;
1493 struct pdinfo *pi;
1494 u_long pidx;
1214 u_long index; 1495 u_long index;
1215 1496
1216 /* This is legal */ 1497 /* This is legal */
@@ -1238,7 +1519,19 @@ ifree(void *ptr)
1238 return; 1519 return;
1239 } 1520 }
1240 1521
1241 info = page_dir[index]; 1522 pidx = PI_IDX(index);
1523 pdir_lookup(index, &pi);
1524#ifdef MALLOC_EXTRA_SANITY
1525 if (pi == NULL || PD_IDX(pi->dirnum) != pidx)
1526 wrterror("(ES): mapped pages not found in directory\n");
1527#endif /* MALLOC_EXTRA_SANITY */
1528 if (pi != last_dir) {
1529 prev_dir = last_dir;
1530 last_dir = pi;
1531 }
1532
1533 pd = pi->base;
1534 info = pd[PI_OFF(index)];
1242 1535
1243 if (info < MALLOC_MAGIC) 1536 if (info < MALLOC_MAGIC)
1244 free_pages(ptr, index, info); 1537 free_pages(ptr, index, info);
@@ -1257,9 +1550,10 @@ malloc_recurse(void)
1257{ 1550{
1258 static int noprint; 1551 static int noprint;
1259 1552
1260 if (noprint == 0) 1553 if (noprint == 0) {
1554 noprint = 1;
1261 wrtwarning("recursive call\n"); 1555 wrtwarning("recursive call\n");
1262 noprint = 1; 1556 }
1263 malloc_active--; 1557 malloc_active--;
1264 _MALLOC_UNLOCK(); 1558 _MALLOC_UNLOCK();
1265 errno = EDEADLK; 1559 errno = EDEADLK;