summaryrefslogtreecommitdiff
path: root/lib/libc
diff options
context:
space:
mode:
authorOtto Moerbeek <otto@cvs.openbsd.org>2008-08-22 17:14:58 +0000
committerOtto Moerbeek <otto@cvs.openbsd.org>2008-08-22 17:14:58 +0000
commit382374da4558eceeadbb678b08cfdd1029c58b0f (patch)
tree95ea1df4c604892c3635a994179cbf242a753c74 /lib/libc
parent18b5442f524b67a486479dd751e16d3a7d6ea1e0 (diff)
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@
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/stdlib/Makefile.inc4
-rw-r--r--lib/libc/stdlib/malloc.c61
2 files changed, 57 insertions, 8 deletions
diff --git a/lib/libc/stdlib/Makefile.inc b/lib/libc/stdlib/Makefile.inc
index f1708a1111d..09db4ce7935 100644
--- a/lib/libc/stdlib/Makefile.inc
+++ b/lib/libc/stdlib/Makefile.inc
@@ -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 \
diff --git a/lib/libc/stdlib/malloc.c b/lib/libc/stdlib/malloc.c
index 645dc5afc92..d03b8315146 100644
--- a/lib/libc/stdlib/malloc.c
+++ b/lib/libc/stdlib/malloc.c
@@ -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;
+}