Browse Source

Smarter implementation of calloc(3), which uses the fact that mmap(2)

returns zero filled pages; remember to replace this function as well if you
provide your own malloc implementation; ok djm@ deraadt@
OPENBSD_4_5
otto 16 years ago
parent
commit
74022f5554
2 changed files with 57 additions and 8 deletions
  1. +2
    -2
      src/lib/libc/stdlib/Makefile.inc
  2. +55
    -6
      src/lib/libc/stdlib/malloc.c

+ 2
- 2
src/lib/libc/stdlib/Makefile.inc View File

@ -1,10 +1,10 @@
# $OpenBSD: Makefile.inc,v 1.38 2008/06/13 21:04:24 landry Exp $
# $OpenBSD: Makefile.inc,v 1.39 2008/08/22 17:14:56 otto Exp $
# stdlib sources
.PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/stdlib ${LIBCSRCDIR}/stdlib
SRCS+= a64l.c abort.c atexit.c atoi.c atof.c atol.c atoll.c bsearch.c \
calloc.c cfree.c exit.c ecvt.c gcvt.c getenv.c getopt_long.c \
cfree.c exit.c ecvt.c gcvt.c getenv.c getopt_long.c \
getsubopt.c hcreate.c heapsort.c imaxabs.c imaxdiv.c l64a.c llabs.c \
lldiv.c lsearch.c malloc.c merge.c putenv.c qsort.c radixsort.c rand.c \
random.c realpath.c setenv.c strtoimax.c strtod.c strtof.c strtol.c \


+ 55
- 6
src/lib/libc/stdlib/malloc.c View File

@ -1,4 +1,4 @@
/* $OpenBSD: malloc.c,v 1.93 2008/08/07 18:41:47 otto Exp $ */
/* $OpenBSD: malloc.c,v 1.94 2008/08/22 17:14:57 otto Exp $ */
/*
* Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
*
@ -443,7 +443,7 @@ unmap(struct dir_info *d, void *p, size_t sz)
}
static void *
map(struct dir_info *d, size_t sz)
map(struct dir_info *d, size_t sz, int zero_fill)
{
size_t psz = PAGEROUND(sz) >> MALLOC_PAGESHIFT;
struct region_info *r, *big = NULL;
@ -454,6 +454,7 @@ map(struct dir_info *d, size_t sz)
p = MMAP(sz);
if (p != MAP_FAILED)
malloc_used += sz;
/* zero fill not needed */
return p;
}
offset = getrbyte();
@ -469,6 +470,8 @@ map(struct dir_info *d, size_t sz)
r->p = NULL;
r->size = 0;
d->free_regions_size -= psz;
if (zero_fill)
memset(p, 0, sz);
return p;
} else if (r->size > psz)
big = r;
@ -483,6 +486,8 @@ map(struct dir_info *d, size_t sz)
madvise(p, sz, MADV_NORMAL);
r->size -= psz;
d->free_regions_size -= psz;
if (zero_fill)
memset(p, 0, sz);
return p;
}
p = MMAP(sz);
@ -490,6 +495,7 @@ map(struct dir_info *d, size_t sz)
malloc_used += sz;
if (d->free_regions_size > malloc_cache)
wrtwarning("malloc cache");
/* zero fill not needed */
return p;
}
@ -835,7 +841,7 @@ omalloc_make_chunks(struct dir_info *d, int bits)
long i, k;
/* Allocate a new bucket */
pp = map(d, MALLOC_PAGESIZE);
pp = map(d, MALLOC_PAGESIZE, 0);
if (pp == MAP_FAILED)
return NULL;
@ -1053,7 +1059,7 @@ omalloc(size_t sz, int zero_fill)
}
sz += malloc_guard;
psz = PAGEROUND(sz);
p = map(&g_pool, psz);
p = map(&g_pool, psz, zero_fill);
if (p == MAP_FAILED) {
errno = ENOMEM;
return NULL;
@ -1077,8 +1083,6 @@ omalloc(size_t sz, int zero_fill)
sz - malloc_guard < MALLOC_PAGESIZE - MALLOC_MINSIZE)
p = ((char *)p) + ((MALLOC_PAGESIZE - MALLOC_MINSIZE -
(sz - malloc_guard)) & ~(MALLOC_MINSIZE-1));
if (zero_fill)
memset(p, 0, sz - malloc_guard);
} else {
/* takes care of SOME_JUNK */
p = malloc_bytes(&g_pool, sz);
@ -1323,3 +1327,48 @@ realloc(void *ptr, size_t size)
}
return r;
}
#define MUL_NO_OVERFLOW (1UL << (sizeof(size_t) * 4))
void *
calloc(size_t nmemb, size_t size)
{
void *r;
_MALLOC_LOCK();
malloc_func = " in calloc():";
if (!g_pool.regions_total) {
if (omalloc_init(&g_pool)) {
_MALLOC_UNLOCK();
if (malloc_xmalloc)
wrterror("out of memory");
errno = ENOMEM;
return NULL;
}
}
if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
nmemb > 0 && SIZE_MAX / nmemb < size) {
_MALLOC_UNLOCK();
if (malloc_xmalloc)
wrterror("out of memory");
errno = ENOMEM;
return NULL;
}
if (malloc_active++) {
malloc_recurse();
return NULL;
}
size *= nmemb;
r = omalloc(size, 1);
malloc_active--;
_MALLOC_UNLOCK();
if (r == NULL && malloc_xmalloc) {
wrterror("out of memory");
errno = ENOMEM;
}
return r;
}

Loading…
Cancel
Save