Tested on i386. No breakage, and no issues so far.

On Wed, Sep 7, 2011 at 10:53 AM, Otto Moerbeek <o...@drijf.net> wrote:
> Hi,
>
> This makes struct chunk_info a variable sized struct, wasting less
> space for meta data, by only allocating space actually needed for the
> bitmap (modulo alignment requirements).
>
> I have been runing this on amd64 and loongson for a while.
>
> Please review this and test on as many platforms as you can find.
>
>        -Otto
>
> Index: malloc.c
> ===================================================================
> RCS file: /cvs/src/lib/libc/stdlib/malloc.c,v
> retrieving revision 1.139
> diff -u -p -r1.139 malloc.c
> --- malloc.c    12 Jul 2011 14:43:42 -0000      1.139
> +++ malloc.c    7 Sep 2011 06:49:36 -0000
> @@ -109,8 +109,8 @@ struct dir_info {
>        struct region_info *r;          /* region slots */
>        size_t regions_total;           /* number of region slots */
>        size_t regions_free;            /* number of free slots */
> -                                       /* list of free chunk info structs
*/
> -       struct chunk_head chunk_info_list;
> +                                       /* lists of free chunk info structs
*/
> +       struct chunk_head chunk_info_list[MALLOC_MAXSHIFT + 1];
>                                        /* lists of chunks with free slots
*/
>        struct chunk_head chunk_dir[MALLOC_MAXSHIFT + 1];
>        size_t free_regions_size;       /* free pages cached */
> @@ -156,7 +156,7 @@ struct chunk_info {
>        u_short free;                   /* how many free chunks */
>        u_short total;                  /* how many chunk */
>                                        /* which chunks are free */
> -       u_short bits[(MALLOC_PAGESIZE / MALLOC_MINSIZE) / MALLOC_BITS];
> +       u_short bits[1];
>  };
>
>  struct malloc_readonly {
> @@ -622,9 +622,10 @@ omalloc_init(struct dir_info **dp)
>                d->regions_total = 0;
>                return 1;
>        }
> -       LIST_INIT(&d->chunk_info_list);
> -       for (i = 0; i <= MALLOC_MAXSHIFT; i++)
> +       for (i = 0; i <= MALLOC_MAXSHIFT; i++) {
> +               LIST_INIT(&d->chunk_info_list[i]);
>                LIST_INIT(&d->chunk_dir[i]);
> +       }
>        malloc_used += regioninfo_size;
>        d->canary1 = mopts.malloc_canary ^ (u_int32_t)(uintptr_t)d;
>        d->canary2 = ~d->canary1;
> @@ -689,22 +690,36 @@ omalloc_grow(struct dir_info *d)
>  }
>
>  static struct chunk_info *
> -alloc_chunk_info(struct dir_info *d)
> +alloc_chunk_info(struct dir_info *d, int bits)
>  {
>        struct chunk_info *p;
> -       int i;
> -
> -       if (LIST_EMPTY(&d->chunk_info_list)) {
> -               p = MMAP(MALLOC_PAGESIZE);
> -               if (p == MAP_FAILED)
> +       size_t size, count;
> +
> +       if (bits == 0)
> +               count = MALLOC_PAGESIZE / MALLOC_MINSIZE;
> +       else
> +               count = MALLOC_PAGESIZE >> bits;
> +
> +       size = howmany(count, MALLOC_BITS);
> +       size = sizeof(struct chunk_info) + (size - 1) * sizeof(u_short);
> +       size = ALIGN(size);
> +
> +       if (LIST_EMPTY(&d->chunk_info_list[bits])) {
> +               void *q;
> +               int i;
> +
> +               q = MMAP(MALLOC_PAGESIZE);
> +               if (q == MAP_FAILED)
>                        return NULL;
>                malloc_used += MALLOC_PAGESIZE;
> -               for (i = 0; i < MALLOC_PAGESIZE / sizeof(*p); i++)
> -                       LIST_INSERT_HEAD(&d->chunk_info_list, &p[i],
entries);
> +               count = MALLOC_PAGESIZE / size;
> +               for (i = 0; i < count; i++, q += size)
> +                       LIST_INSERT_HEAD(&d->chunk_info_list[bits],
> +                           (struct chunk_info *)q, entries);
>        }
> -       p = LIST_FIRST(&d->chunk_info_list);
> +       p = LIST_FIRST(&d->chunk_info_list[bits]);
>        LIST_REMOVE(p, entries);
> -       memset(p, 0, sizeof *p);
> +       memset(p, 0, size);
>        p->canary = d->canary1;
>        return p;
>  }
> @@ -803,14 +818,14 @@ omalloc_make_chunks(struct dir_info *d,
>  {
>        struct chunk_info *bp;
>        void            *pp;
> -       long            i, k;
> +       int             i, k;
>
>        /* Allocate a new bucket */
>        pp = map(d, MALLOC_PAGESIZE, 0);
>        if (pp == MAP_FAILED)
>                return NULL;
>
> -       bp = alloc_chunk_info(d);
> +       bp = alloc_chunk_info(d, bits);
>        if (bp == NULL) {
>                unmap(d, pp, MALLOC_PAGESIZE);
>                return NULL;
> @@ -829,7 +844,7 @@ omalloc_make_chunks(struct dir_info *d,
>                k = mprotect(pp, MALLOC_PAGESIZE, PROT_NONE);
>                if (k < 0) {
>                        unmap(d, pp, MALLOC_PAGESIZE);
> -                       LIST_INSERT_HEAD(&d->chunk_info_list, bp, entries);
> +                       LIST_INSERT_HEAD(&d->chunk_info_list[0], bp,
entries);
>                        return NULL;
>                }
>        } else {
> @@ -956,7 +971,7 @@ free_bytes(struct dir_info *d, struct re
>  {
>        struct chunk_head *mp;
>        struct chunk_info *info;
> -       long i;
> +       int i;
>
>        info = (struct chunk_info *)r->size;
>        if (info->canary != d->canary1)
> @@ -997,7 +1012,11 @@ free_bytes(struct dir_info *d, struct re
>        unmap(d, info->page, MALLOC_PAGESIZE);
>
>        delete(d, r);
> -       LIST_INSERT_HEAD(&d->chunk_info_list, info, entries);
> +       if (info->size != 0)
> +               mp = &d->chunk_info_list[info->shift];
> +       else
> +               mp = &d->chunk_info_list[0];
> +       LIST_INSERT_HEAD(mp, info, entries);
>  }
>
>
> @@ -1521,7 +1540,7 @@ dump_chunk(int fd, struct chunk_info *p,
>                }
>                p = LIST_NEXT(p, entries);
>                if (p != NULL) {
> -                       snprintf(buf, sizeof(buf), "    ");
> +                       snprintf(buf, sizeof(buf), "        ");
>                        write(fd, buf, strlen(buf));
>                }
>        }
> @@ -1531,17 +1550,25 @@ static void
>  dump_free_chunk_info(int fd, struct dir_info *d)
>  {
>        char buf[64];
> -       int i;
> +       int i, count;
>
>        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));
> +               struct chunk_info *p;
> +
> +               count = 0;
> +               LIST_FOREACH(p, &d->chunk_info_list[i], entries)
> +                       count++;
> +               p = LIST_FIRST(&d->chunk_dir[i]);
> +               if (p == NULL && count == 0)
> +                       continue;
> +               snprintf(buf, sizeof(buf), "%2d) %3d ", i, count);
> +               write(fd, buf, strlen(buf));
> +               if (p != NULL)
>                        dump_chunk(fd, p, NULL, 1);
> -               }
> +               else
> +                       write(fd, "\n", 1);
>        }
>
>  }
>
>



--
`` Real men run current !''

Reply via email to