-/* $OpenBSD: malloc.c,v 1.162 2014/05/10 18:14:55 otto Exp $ */
+/* $OpenBSD: malloc.c,v 1.163 2014/05/12 19:02:20 tedu Exp $ */
/*
* Copyright (c) 2008, 2010, 2011 Otto Moerbeek <otto@drijf.net>
* Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org>
#define MALLOC_DELAYED_CHUNK_MASK 15
#define MALLOC_INITIAL_REGIONS 512
#define MALLOC_DEFAULT_CACHE 64
+#define MALLOC_CHUNK_LISTS 4
/*
* When the P option is active, we move allocations between half a page
/* 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];
+ struct chunk_head chunk_dir[MALLOC_MAXSHIFT + 1][MALLOC_CHUNK_LISTS];
size_t free_regions_size; /* free pages cached */
/* free pages cache */
struct region_info free_regions[MALLOC_MAXCACHE];
}
for (i = 0; i <= MALLOC_MAXSHIFT; i++) {
LIST_INIT(&d->chunk_info_list[i]);
- LIST_INIT(&d->chunk_dir[i]);
+ for (j = 0; j < MALLOC_CHUNK_LISTS; j++)
+ LIST_INIT(&d->chunk_dir[i][j]);
}
malloc_used += regioninfo_size;
d->canary1 = mopts.malloc_canary ^ (u_int32_t)(uintptr_t)d;
* Allocate a page of chunks
*/
static struct chunk_info *
-omalloc_make_chunks(struct dir_info *d, int bits)
+omalloc_make_chunks(struct dir_info *d, int bits, int listnum)
{
struct chunk_info *bp;
void *pp;
for (; i < k; i++)
bp->bits[i / MALLOC_BITS] |= (u_short)1U << (i % MALLOC_BITS);
- LIST_INSERT_HEAD(&d->chunk_dir[bits], bp, entries);
+ LIST_INSERT_HEAD(&d->chunk_dir[bits][listnum], bp, entries);
bits++;
if ((uintptr_t)pp & bits)
static void *
malloc_bytes(struct dir_info *d, size_t size, void *f)
{
- int i, j;
+ int i, j, listnum;
size_t k;
u_short u, *lp;
struct chunk_info *bp;
j++;
}
+ listnum = getrbyte() % MALLOC_CHUNK_LISTS;
/* If it's empty, make a page more of that size chunks */
- if (LIST_EMPTY(&d->chunk_dir[j])) {
- bp = omalloc_make_chunks(d, j);
+ if ((bp = LIST_FIRST(&d->chunk_dir[j][listnum])) == NULL) {
+ bp = omalloc_make_chunks(d, j, listnum);
if (bp == NULL)
return NULL;
- } else
- bp = LIST_FIRST(&d->chunk_dir[j]);
+ }
if (bp->canary != d->canary1)
wrterror("chunk info corrupted", NULL);
{
struct chunk_head *mp;
struct chunk_info *info;
- int i;
+ int i, listnum;
info = (struct chunk_info *)r->size;
if (info->canary != d->canary1)
info->bits[i / MALLOC_BITS] |= 1U << (i % MALLOC_BITS);
info->free++;
- if (info->size != 0)
- mp = d->chunk_dir + info->shift;
- else
- mp = d->chunk_dir;
-
if (info->free == 1) {
/* Page became non-full */
+ listnum = getrbyte() % MALLOC_CHUNK_LISTS;
+ if (info->size != 0)
+ mp = &d->chunk_dir[info->shift][listnum];
+ else
+ mp = &d->chunk_dir[0][listnum];
+
LIST_INSERT_HEAD(mp, info, entries);
return;
}
+
if (info->free != info->total)
return;