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 # stdlib sources
.PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/stdlib ${LIBCSRCDIR}/stdlib .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 \ 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 \ 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 \ 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 \ 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> * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
* *
@ -443,7 +443,7 @@ unmap(struct dir_info *d, void *p, size_t sz)
} }
static void * 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; size_t psz = PAGEROUND(sz) >> MALLOC_PAGESHIFT;
struct region_info *r, *big = NULL; struct region_info *r, *big = NULL;
@ -454,6 +454,7 @@ map(struct dir_info *d, size_t sz)
p = MMAP(sz); p = MMAP(sz);
if (p != MAP_FAILED) if (p != MAP_FAILED)
malloc_used += sz; malloc_used += sz;
/* zero fill not needed */
return p; return p;
} }
offset = getrbyte(); offset = getrbyte();
@ -469,6 +470,8 @@ map(struct dir_info *d, size_t sz)
r->p = NULL; r->p = NULL;
r->size = 0; r->size = 0;
d->free_regions_size -= psz; d->free_regions_size -= psz;
if (zero_fill)
memset(p, 0, sz);
return p; return p;
} else if (r->size > psz) } else if (r->size > psz)
big = r; big = r;
@ -483,6 +486,8 @@ map(struct dir_info *d, size_t sz)
madvise(p, sz, MADV_NORMAL); madvise(p, sz, MADV_NORMAL);
r->size -= psz; r->size -= psz;
d->free_regions_size -= psz; d->free_regions_size -= psz;
if (zero_fill)
memset(p, 0, sz);
return p; return p;
} }
p = MMAP(sz); p = MMAP(sz);
@ -490,6 +495,7 @@ map(struct dir_info *d, size_t sz)
malloc_used += sz; malloc_used += sz;
if (d->free_regions_size > malloc_cache) if (d->free_regions_size > malloc_cache)
wrtwarning("malloc cache"); wrtwarning("malloc cache");
/* zero fill not needed */
return p; return p;
} }
@ -835,7 +841,7 @@ omalloc_make_chunks(struct dir_info *d, int bits)
long i, k; long i, k;
/* Allocate a new bucket */ /* Allocate a new bucket */
pp = map(d, MALLOC_PAGESIZE);
pp = map(d, MALLOC_PAGESIZE, 0);
if (pp == MAP_FAILED) if (pp == MAP_FAILED)
return NULL; return NULL;
@ -1053,7 +1059,7 @@ omalloc(size_t sz, int zero_fill)
} }
sz += malloc_guard; sz += malloc_guard;
psz = PAGEROUND(sz); psz = PAGEROUND(sz);
p = map(&g_pool, psz);
p = map(&g_pool, psz, zero_fill);
if (p == MAP_FAILED) { if (p == MAP_FAILED) {
errno = ENOMEM; errno = ENOMEM;
return NULL; return NULL;
@ -1077,8 +1083,6 @@ omalloc(size_t sz, int zero_fill)
sz - malloc_guard < MALLOC_PAGESIZE - MALLOC_MINSIZE) sz - malloc_guard < MALLOC_PAGESIZE - MALLOC_MINSIZE)
p = ((char *)p) + ((MALLOC_PAGESIZE - MALLOC_MINSIZE - p = ((char *)p) + ((MALLOC_PAGESIZE - MALLOC_MINSIZE -
(sz - malloc_guard)) & ~(MALLOC_MINSIZE-1)); (sz - malloc_guard)) & ~(MALLOC_MINSIZE-1));
if (zero_fill)
memset(p, 0, sz - malloc_guard);
} else { } else {
/* takes care of SOME_JUNK */ /* takes care of SOME_JUNK */
p = malloc_bytes(&g_pool, sz); p = malloc_bytes(&g_pool, sz);
@ -1323,3 +1327,48 @@ realloc(void *ptr, size_t size)
} }
return r; 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