diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c index 0d1b2290..025508a3 100644 --- a/src/lib/libc/stdlib/malloc.c +++ b/src/lib/libc/stdlib/malloc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: malloc.c,v 1.130 2011/05/05 12:11:20 otto Exp $ */ +/* $OpenBSD: malloc.c,v 1.131 2011/05/08 07:08:13 otto Exp $ */ /* * Copyright (c) 2008 Otto Moerbeek * @@ -192,6 +192,11 @@ static u_char getrnibble(void); extern char *__progname; +#ifdef MALLOC_STATS +void malloc_dump(int); +static void malloc_exit(void); +#endif + /* low bits of r->p determine size: 0 means >= page size and p->size holding * real size, otherwise r->size is a shift count, or 1 for malloc(0) */ @@ -217,142 +222,6 @@ hash(void *p) return sum; } -#ifdef MALLOC_STATS -static void -dump_chunk(int fd, struct chunk_info *p, int fromfreelist) -{ - char buf[64]; - - while (p != NULL) { - snprintf(buf, sizeof(buf), "chunk %d %d/%d %p\n", p->size, - p->free, p->total, p->page); - write(fd, buf, strlen(buf)); - if (!fromfreelist) - break; - p = LIST_NEXT(p, entries); - if (p != NULL) { - snprintf(buf, sizeof(buf), " "); - write(fd, buf, strlen(buf)); - } - } -} - -static void -dump_free_chunk_info(int fd, struct dir_info *d) -{ - char buf[64]; - int i; - - snprintf(buf, sizeof(buf), "Free chunk structs:\n"); - write(fd, buf, strlen(buf)); - for (i = 0; i < MALLOC_MAXSHIFT; i++) { - struct chunk_info *p = LIST_FIRST(&d->chunk_dir[i]); - if (p != NULL) { - snprintf(buf, sizeof(buf), "%2d) ", i); - write(fd, buf, strlen(buf)); - dump_chunk(fd, p, 1); - } - } - -} - -static void -dump_free_page_info(int fd, struct dir_info *d) -{ - char buf[64]; - int i; - - snprintf(buf, sizeof(buf), "Free pages cached: %zu\n", - d->free_regions_size); - write(fd, buf, strlen(buf)); - for (i = 0; i < mopts.malloc_cache; i++) { - if (d->free_regions[i].p != NULL) { - snprintf(buf, sizeof(buf), "%2d) ", i); - write(fd, buf, strlen(buf)); - snprintf(buf, sizeof(buf), "free at %p: %zu\n", - d->free_regions[i].p, d->free_regions[i].size); - write(fd, buf, strlen(buf)); - } - } -} - -static void -malloc_dump1(int fd, struct dir_info *d) -{ - char buf[64]; - size_t i, realsize; - - snprintf(buf, sizeof(buf), "Malloc dir of %s at %p\n", __progname, d); - write(fd, buf, strlen(buf)); - if (d == NULL) - return; - snprintf(buf, sizeof(buf), "Regions slots %zu\n", d->regions_total); - write(fd, buf, strlen(buf)); - snprintf(buf, sizeof(buf), "Finds %zu/%zu %f\n", d->finds, - d->find_collisions, - 1.0 + (double)d->find_collisions / d->finds); - write(fd, buf, strlen(buf)); - snprintf(buf, sizeof(buf), "Inserts %zu/%zu %f\n", d->inserts, - d->insert_collisions, - 1.0 + (double)d->insert_collisions / d->inserts); - write(fd, buf, strlen(buf)); - snprintf(buf, sizeof(buf), "Deletes %zu/%zu\n", d->deletes, - d->delete_moves); - write(fd, buf, strlen(buf)); - snprintf(buf, sizeof(buf), "Cheap reallocs %zu/%zu\n", - d->cheap_reallocs, d->cheap_realloc_tries); - write(fd, buf, strlen(buf)); - snprintf(buf, sizeof(buf), "Regions slots free %zu\n", d->regions_free); - write(fd, buf, strlen(buf)); - for (i = 0; i < d->regions_total; i++) { - if (d->r[i].p != NULL) { - size_t h = hash(d->r[i].p) & - (d->regions_total - 1); - snprintf(buf, sizeof(buf), "%4zx) #%zx %zd ", - i, h, h - i); - write(fd, buf, strlen(buf)); - REALSIZE(realsize, &d->r[i]); - if (realsize > MALLOC_MAXCHUNK) { - snprintf(buf, sizeof(buf), - "%p: %zu\n", d->r[i].p, realsize); - write(fd, buf, strlen(buf)); - } else - dump_chunk(fd, - (struct chunk_info *)d->r[i].size, 0); - } - } - dump_free_chunk_info(fd, d); - dump_free_page_info(fd, d); - snprintf(buf, sizeof(buf), "In use %zu\n", malloc_used); - write(fd, buf, strlen(buf)); - snprintf(buf, sizeof(buf), "Guarded %zu\n", malloc_guarded); - write(fd, buf, strlen(buf)); -} - - -void -malloc_dump(int fd) -{ - malloc_dump1(fd, g_pool); -} - -static void -malloc_exit(void) -{ - static const char q[] = "malloc() warning: Couldn't dump stats\n"; - int save_errno = errno, fd; - - fd = open("malloc.out", O_RDWR|O_APPEND); - if (fd != -1) { - malloc_dump(fd); - close(fd); - } else - write(STDERR_FILENO, q, sizeof(q) - 1); - errno = save_errno; -} -#endif /* MALLOC_STATS */ - - static void wrterror(char *msg, void *p) { @@ -1516,3 +1385,138 @@ posix_memalign(void **memptr, size_t alignment, size_t size) return 0; } +#ifdef MALLOC_STATS +static void +dump_chunk(int fd, struct chunk_info *p, int fromfreelist) +{ + char buf[64]; + + while (p != NULL) { + snprintf(buf, sizeof(buf), "chunk %d %d/%d %p\n", p->size, + p->free, p->total, p->page); + write(fd, buf, strlen(buf)); + if (!fromfreelist) + break; + p = LIST_NEXT(p, entries); + if (p != NULL) { + snprintf(buf, sizeof(buf), " "); + write(fd, buf, strlen(buf)); + } + } +} + +static void +dump_free_chunk_info(int fd, struct dir_info *d) +{ + char buf[64]; + int i; + + snprintf(buf, sizeof(buf), "Free chunk structs:\n"); + write(fd, buf, strlen(buf)); + for (i = 0; i < MALLOC_MAXSHIFT; i++) { + struct chunk_info *p = LIST_FIRST(&d->chunk_dir[i]); + if (p != NULL) { + snprintf(buf, sizeof(buf), "%2d) ", i); + write(fd, buf, strlen(buf)); + dump_chunk(fd, p, 1); + } + } + +} + +static void +dump_free_page_info(int fd, struct dir_info *d) +{ + char buf[64]; + int i; + + snprintf(buf, sizeof(buf), "Free pages cached: %zu\n", + d->free_regions_size); + write(fd, buf, strlen(buf)); + for (i = 0; i < mopts.malloc_cache; i++) { + if (d->free_regions[i].p != NULL) { + snprintf(buf, sizeof(buf), "%2d) ", i); + write(fd, buf, strlen(buf)); + snprintf(buf, sizeof(buf), "free at %p: %zu\n", + d->free_regions[i].p, d->free_regions[i].size); + write(fd, buf, strlen(buf)); + } + } +} + +static void +malloc_dump1(int fd, struct dir_info *d) +{ + char buf[64]; + size_t i, realsize; + + snprintf(buf, sizeof(buf), "Malloc dir of %s at %p\n", __progname, d); + write(fd, buf, strlen(buf)); + if (d == NULL) + return; + snprintf(buf, sizeof(buf), "Regions slots %zu\n", d->regions_total); + write(fd, buf, strlen(buf)); + snprintf(buf, sizeof(buf), "Finds %zu/%zu %f\n", d->finds, + d->find_collisions, + 1.0 + (double)d->find_collisions / d->finds); + write(fd, buf, strlen(buf)); + snprintf(buf, sizeof(buf), "Inserts %zu/%zu %f\n", d->inserts, + d->insert_collisions, + 1.0 + (double)d->insert_collisions / d->inserts); + write(fd, buf, strlen(buf)); + snprintf(buf, sizeof(buf), "Deletes %zu/%zu\n", d->deletes, + d->delete_moves); + write(fd, buf, strlen(buf)); + snprintf(buf, sizeof(buf), "Cheap reallocs %zu/%zu\n", + d->cheap_reallocs, d->cheap_realloc_tries); + write(fd, buf, strlen(buf)); + snprintf(buf, sizeof(buf), "Regions slots free %zu\n", d->regions_free); + write(fd, buf, strlen(buf)); + for (i = 0; i < d->regions_total; i++) { + if (d->r[i].p != NULL) { + size_t h = hash(d->r[i].p) & + (d->regions_total - 1); + snprintf(buf, sizeof(buf), "%4zx) #%zx %zd ", + i, h, h - i); + write(fd, buf, strlen(buf)); + REALSIZE(realsize, &d->r[i]); + if (realsize > MALLOC_MAXCHUNK) { + snprintf(buf, sizeof(buf), + "%p: %zu\n", d->r[i].p, realsize); + write(fd, buf, strlen(buf)); + } else + dump_chunk(fd, + (struct chunk_info *)d->r[i].size, 0); + } + } + dump_free_chunk_info(fd, d); + dump_free_page_info(fd, d); + snprintf(buf, sizeof(buf), "In use %zu\n", malloc_used); + write(fd, buf, strlen(buf)); + snprintf(buf, sizeof(buf), "Guarded %zu\n", malloc_guarded); + write(fd, buf, strlen(buf)); +} + + +void +malloc_dump(int fd) +{ + malloc_dump1(fd, g_pool); +} + +static void +malloc_exit(void) +{ + static const char q[] = "malloc() warning: Couldn't dump stats\n"; + int save_errno = errno, fd; + + fd = open("malloc.out", O_RDWR|O_APPEND); + if (fd != -1) { + malloc_dump(fd); + close(fd); + } else + write(STDERR_FILENO, q, sizeof(q) - 1); + errno = save_errno; +} + +#endif /* MALLOC_STATS */