diff options
author | otto <> | 2008-08-22 17:14:57 +0000 |
---|---|---|
committer | otto <> | 2008-08-22 17:14:57 +0000 |
commit | e6c446cc76e761b92735aca89f612db2ed9a52d2 (patch) | |
tree | f6236b9a87997344d17ae9b8295480c318e6ddca /src | |
parent | e72de9455c1c4ac62f67569f4309a7875d9ca4fa (diff) | |
download | openbsd-e6c446cc76e761b92735aca89f612db2ed9a52d2.tar.gz openbsd-e6c446cc76e761b92735aca89f612db2ed9a52d2.tar.bz2 openbsd-e6c446cc76e761b92735aca89f612db2ed9a52d2.zip |
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 'src')
-rw-r--r-- | src/lib/libc/stdlib/Makefile.inc | 4 | ||||
-rw-r--r-- | src/lib/libc/stdlib/malloc.c | 61 |
2 files changed, 57 insertions, 8 deletions
diff --git a/src/lib/libc/stdlib/Makefile.inc b/src/lib/libc/stdlib/Makefile.inc index f1708a1111..09db4ce793 100644 --- a/src/lib/libc/stdlib/Makefile.inc +++ b/src/lib/libc/stdlib/Makefile.inc | |||
@@ -1,10 +1,10 @@ | |||
1 | # $OpenBSD: Makefile.inc,v 1.38 2008/06/13 21:04:24 landry Exp $ | 1 | # $OpenBSD: Makefile.inc,v 1.39 2008/08/22 17:14:56 otto Exp $ |
2 | 2 | ||
3 | # stdlib sources | 3 | # stdlib sources |
4 | .PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/stdlib ${LIBCSRCDIR}/stdlib | 4 | .PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/stdlib ${LIBCSRCDIR}/stdlib |
5 | 5 | ||
6 | SRCS+= a64l.c abort.c atexit.c atoi.c atof.c atol.c atoll.c bsearch.c \ | 6 | SRCS+= a64l.c abort.c atexit.c atoi.c atof.c atol.c atoll.c bsearch.c \ |
7 | calloc.c cfree.c exit.c ecvt.c gcvt.c getenv.c getopt_long.c \ | 7 | cfree.c exit.c ecvt.c gcvt.c getenv.c getopt_long.c \ |
8 | getsubopt.c hcreate.c heapsort.c imaxabs.c imaxdiv.c l64a.c llabs.c \ | 8 | getsubopt.c hcreate.c heapsort.c imaxabs.c imaxdiv.c l64a.c llabs.c \ |
9 | lldiv.c lsearch.c malloc.c merge.c putenv.c qsort.c radixsort.c rand.c \ | 9 | lldiv.c lsearch.c malloc.c merge.c putenv.c qsort.c radixsort.c rand.c \ |
10 | random.c realpath.c setenv.c strtoimax.c strtod.c strtof.c strtol.c \ | 10 | random.c realpath.c setenv.c strtoimax.c strtod.c strtof.c strtol.c \ |
diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c index 645dc5afc9..d03b831514 100644 --- a/src/lib/libc/stdlib/malloc.c +++ b/src/lib/libc/stdlib/malloc.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: malloc.c,v 1.93 2008/08/07 18:41:47 otto Exp $ */ | 1 | /* $OpenBSD: malloc.c,v 1.94 2008/08/22 17:14:57 otto Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net> | 3 | * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net> |
4 | * | 4 | * |
@@ -443,7 +443,7 @@ unmap(struct dir_info *d, void *p, size_t sz) | |||
443 | } | 443 | } |
444 | 444 | ||
445 | static void * | 445 | static void * |
446 | map(struct dir_info *d, size_t sz) | 446 | map(struct dir_info *d, size_t sz, int zero_fill) |
447 | { | 447 | { |
448 | size_t psz = PAGEROUND(sz) >> MALLOC_PAGESHIFT; | 448 | size_t psz = PAGEROUND(sz) >> MALLOC_PAGESHIFT; |
449 | struct region_info *r, *big = NULL; | 449 | struct region_info *r, *big = NULL; |
@@ -454,6 +454,7 @@ map(struct dir_info *d, size_t sz) | |||
454 | p = MMAP(sz); | 454 | p = MMAP(sz); |
455 | if (p != MAP_FAILED) | 455 | if (p != MAP_FAILED) |
456 | malloc_used += sz; | 456 | malloc_used += sz; |
457 | /* zero fill not needed */ | ||
457 | return p; | 458 | return p; |
458 | } | 459 | } |
459 | offset = getrbyte(); | 460 | offset = getrbyte(); |
@@ -469,6 +470,8 @@ map(struct dir_info *d, size_t sz) | |||
469 | r->p = NULL; | 470 | r->p = NULL; |
470 | r->size = 0; | 471 | r->size = 0; |
471 | d->free_regions_size -= psz; | 472 | d->free_regions_size -= psz; |
473 | if (zero_fill) | ||
474 | memset(p, 0, sz); | ||
472 | return p; | 475 | return p; |
473 | } else if (r->size > psz) | 476 | } else if (r->size > psz) |
474 | big = r; | 477 | big = r; |
@@ -483,6 +486,8 @@ map(struct dir_info *d, size_t sz) | |||
483 | madvise(p, sz, MADV_NORMAL); | 486 | madvise(p, sz, MADV_NORMAL); |
484 | r->size -= psz; | 487 | r->size -= psz; |
485 | d->free_regions_size -= psz; | 488 | d->free_regions_size -= psz; |
489 | if (zero_fill) | ||
490 | memset(p, 0, sz); | ||
486 | return p; | 491 | return p; |
487 | } | 492 | } |
488 | p = MMAP(sz); | 493 | p = MMAP(sz); |
@@ -490,6 +495,7 @@ map(struct dir_info *d, size_t sz) | |||
490 | malloc_used += sz; | 495 | malloc_used += sz; |
491 | if (d->free_regions_size > malloc_cache) | 496 | if (d->free_regions_size > malloc_cache) |
492 | wrtwarning("malloc cache"); | 497 | wrtwarning("malloc cache"); |
498 | /* zero fill not needed */ | ||
493 | return p; | 499 | return p; |
494 | } | 500 | } |
495 | 501 | ||
@@ -835,7 +841,7 @@ omalloc_make_chunks(struct dir_info *d, int bits) | |||
835 | long i, k; | 841 | long i, k; |
836 | 842 | ||
837 | /* Allocate a new bucket */ | 843 | /* Allocate a new bucket */ |
838 | pp = map(d, MALLOC_PAGESIZE); | 844 | pp = map(d, MALLOC_PAGESIZE, 0); |
839 | if (pp == MAP_FAILED) | 845 | if (pp == MAP_FAILED) |
840 | return NULL; | 846 | return NULL; |
841 | 847 | ||
@@ -1053,7 +1059,7 @@ omalloc(size_t sz, int zero_fill) | |||
1053 | } | 1059 | } |
1054 | sz += malloc_guard; | 1060 | sz += malloc_guard; |
1055 | psz = PAGEROUND(sz); | 1061 | psz = PAGEROUND(sz); |
1056 | p = map(&g_pool, psz); | 1062 | p = map(&g_pool, psz, zero_fill); |
1057 | if (p == MAP_FAILED) { | 1063 | if (p == MAP_FAILED) { |
1058 | errno = ENOMEM; | 1064 | errno = ENOMEM; |
1059 | return NULL; | 1065 | return NULL; |
@@ -1077,8 +1083,6 @@ omalloc(size_t sz, int zero_fill) | |||
1077 | sz - malloc_guard < MALLOC_PAGESIZE - MALLOC_MINSIZE) | 1083 | sz - malloc_guard < MALLOC_PAGESIZE - MALLOC_MINSIZE) |
1078 | p = ((char *)p) + ((MALLOC_PAGESIZE - MALLOC_MINSIZE - | 1084 | p = ((char *)p) + ((MALLOC_PAGESIZE - MALLOC_MINSIZE - |
1079 | (sz - malloc_guard)) & ~(MALLOC_MINSIZE-1)); | 1085 | (sz - malloc_guard)) & ~(MALLOC_MINSIZE-1)); |
1080 | if (zero_fill) | ||
1081 | memset(p, 0, sz - malloc_guard); | ||
1082 | } else { | 1086 | } else { |
1083 | /* takes care of SOME_JUNK */ | 1087 | /* takes care of SOME_JUNK */ |
1084 | p = malloc_bytes(&g_pool, sz); | 1088 | p = malloc_bytes(&g_pool, sz); |
@@ -1323,3 +1327,48 @@ realloc(void *ptr, size_t size) | |||
1323 | } | 1327 | } |
1324 | return r; | 1328 | return r; |
1325 | } | 1329 | } |
1330 | |||
1331 | |||
1332 | #define MUL_NO_OVERFLOW (1UL << (sizeof(size_t) * 4)) | ||
1333 | |||
1334 | void * | ||
1335 | calloc(size_t nmemb, size_t size) | ||
1336 | { | ||
1337 | void *r; | ||
1338 | |||
1339 | _MALLOC_LOCK(); | ||
1340 | malloc_func = " in calloc():"; | ||
1341 | if (!g_pool.regions_total) { | ||
1342 | if (omalloc_init(&g_pool)) { | ||
1343 | _MALLOC_UNLOCK(); | ||
1344 | if (malloc_xmalloc) | ||
1345 | wrterror("out of memory"); | ||
1346 | errno = ENOMEM; | ||
1347 | return NULL; | ||
1348 | } | ||
1349 | } | ||
1350 | if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && | ||
1351 | nmemb > 0 && SIZE_MAX / nmemb < size) { | ||
1352 | _MALLOC_UNLOCK(); | ||
1353 | if (malloc_xmalloc) | ||
1354 | wrterror("out of memory"); | ||
1355 | errno = ENOMEM; | ||
1356 | return NULL; | ||
1357 | } | ||
1358 | |||
1359 | if (malloc_active++) { | ||
1360 | malloc_recurse(); | ||
1361 | return NULL; | ||
1362 | } | ||
1363 | |||
1364 | size *= nmemb; | ||
1365 | r = omalloc(size, 1); | ||
1366 | |||
1367 | malloc_active--; | ||
1368 | _MALLOC_UNLOCK(); | ||
1369 | if (r == NULL && malloc_xmalloc) { | ||
1370 | wrterror("out of memory"); | ||
1371 | errno = ENOMEM; | ||
1372 | } | ||
1373 | return r; | ||
1374 | } | ||