summaryrefslogtreecommitdiff
path: root/src/lib/libc/stdlib/malloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libc/stdlib/malloc.c')
-rw-r--r--src/lib/libc/stdlib/malloc.c84
1 files changed, 72 insertions, 12 deletions
diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c
index f2b8b1549b..07c73ca774 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.219 2017/04/06 08:39:47 otto Exp $ */ 1/* $OpenBSD: malloc.c,v 1.220 2017/04/10 05:45:02 otto Exp $ */
2/* 2/*
3 * Copyright (c) 2008, 2010, 2011, 2016 Otto Moerbeek <otto@drijf.net> 3 * Copyright (c) 2008, 2010, 2011, 2016 Otto Moerbeek <otto@drijf.net>
4 * Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org> 4 * Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org>
@@ -185,7 +185,7 @@ struct malloc_readonly {
185 int malloc_realloc; /* always realloc? */ 185 int malloc_realloc; /* always realloc? */
186 int malloc_xmalloc; /* xmalloc behaviour? */ 186 int malloc_xmalloc; /* xmalloc behaviour? */
187 int chunk_canaries; /* use canaries after chunks? */ 187 int chunk_canaries; /* use canaries after chunks? */
188 int internal_recallocarray; /* use better recallocarray? */ 188 int internal_funcs; /* use better recallocarray/freezero? */
189 u_int malloc_cache; /* free pages we cache */ 189 u_int malloc_cache; /* free pages we cache */
190 size_t malloc_guard; /* use guard pages after allocations? */ 190 size_t malloc_guard; /* use guard pages after allocations? */
191#ifdef MALLOC_STATS 191#ifdef MALLOC_STATS
@@ -343,7 +343,14 @@ unmap(struct dir_info *d, void *p, size_t sz, int clear)
343 if (sz != PAGEROUND(sz)) 343 if (sz != PAGEROUND(sz))
344 wrterror(d, "munmap round"); 344 wrterror(d, "munmap round");
345 345
346 if (psz > mopts.malloc_cache) { 346 rsz = mopts.malloc_cache - d->free_regions_size;
347
348 /*
349 * normally the cache holds recently freed regions, but if the region
350 * to unmap is larger than the cache size or we're clearing and the
351 * cache is full, just munmap
352 */
353 if (psz > mopts.malloc_cache || (clear && rsz == 0)) {
347 i = munmap(p, sz); 354 i = munmap(p, sz);
348 if (i) 355 if (i)
349 wrterror(d, "munmap %p", p); 356 wrterror(d, "munmap %p", p);
@@ -351,7 +358,6 @@ unmap(struct dir_info *d, void *p, size_t sz, int clear)
351 return; 358 return;
352 } 359 }
353 tounmap = 0; 360 tounmap = 0;
354 rsz = mopts.malloc_cache - d->free_regions_size;
355 if (psz > rsz) 361 if (psz > rsz)
356 tounmap = psz - rsz; 362 tounmap = psz - rsz;
357 offset = getrbyte(d); 363 offset = getrbyte(d);
@@ -1234,7 +1240,7 @@ _malloc_init(int from_rthreads)
1234 if (from_rthreads) 1240 if (from_rthreads)
1235 mopts.malloc_mt = 1; 1241 mopts.malloc_mt = 1;
1236 else 1242 else
1237 mopts.internal_recallocarray = 1; 1243 mopts.internal_funcs = 1;
1238 1244
1239 /* 1245 /*
1240 * Options have been set and will never be reset. 1246 * Options have been set and will never be reset.
@@ -1297,7 +1303,7 @@ validate_junk(struct dir_info *pool, void *p)
1297} 1303}
1298 1304
1299static void 1305static void
1300ofree(struct dir_info *argpool, void *p, int clear) 1306ofree(struct dir_info *argpool, void *p, int clear, int check, size_t argsz)
1301{ 1307{
1302 struct dir_info *pool; 1308 struct dir_info *pool;
1303 struct region_info *r; 1309 struct region_info *r;
@@ -1326,6 +1332,25 @@ ofree(struct dir_info *argpool, void *p, int clear)
1326 } 1332 }
1327 1333
1328 REALSIZE(sz, r); 1334 REALSIZE(sz, r);
1335 if (check) {
1336 if (sz <= MALLOC_MAXCHUNK) {
1337 if (mopts.chunk_canaries) {
1338 struct chunk_info *info =
1339 (struct chunk_info *)r->size;
1340 uint32_t chunknum =
1341 find_chunknum(pool, r, p, 0);
1342
1343 if (info->bits[info->offset + chunknum] !=
1344 argsz)
1345 wrterror(pool, "recorded old size %hu"
1346 " != %zu",
1347 info->bits[info->offset + chunknum],
1348 argsz);
1349 }
1350 } else if (argsz != sz - mopts.malloc_guard)
1351 wrterror(pool, "recorded old size %zu != %zu",
1352 sz - mopts.malloc_guard, argsz);
1353 }
1329 if (sz > MALLOC_MAXCHUNK) { 1354 if (sz > MALLOC_MAXCHUNK) {
1330 if (!MALLOC_MOVE_COND(sz)) { 1355 if (!MALLOC_MOVE_COND(sz)) {
1331 if (r->p != p) 1356 if (r->p != p)
@@ -1411,13 +1436,48 @@ free(void *ptr)
1411 malloc_recurse(d); 1436 malloc_recurse(d);
1412 return; 1437 return;
1413 } 1438 }
1414 ofree(d, ptr, 0); 1439 ofree(d, ptr, 0, 0, 0);
1415 d->active--; 1440 d->active--;
1416 _MALLOC_UNLOCK(d->mutex); 1441 _MALLOC_UNLOCK(d->mutex);
1417 errno = saved_errno; 1442 errno = saved_errno;
1418} 1443}
1419/*DEF_STRONG(free);*/ 1444/*DEF_STRONG(free);*/
1420 1445
1446static void
1447freezero_p(void *ptr, size_t sz)
1448{
1449 explicit_bzero(ptr, sz);
1450 free(ptr);
1451}
1452
1453void
1454freezero(void *ptr, size_t sz)
1455{
1456 struct dir_info *d;
1457 int saved_errno = errno;
1458
1459 /* This is legal. */
1460 if (ptr == NULL)
1461 return;
1462
1463 if (!mopts.internal_funcs)
1464 return freezero_p(ptr, sz);
1465
1466 d = getpool();
1467 if (d == NULL)
1468 wrterror(d, "freezero() called before allocation");
1469 _MALLOC_LOCK(d->mutex);
1470 d->func = "freezero";
1471 if (d->active++) {
1472 malloc_recurse(d);
1473 return;
1474 }
1475 ofree(d, ptr, 1, 1, sz);
1476 d->active--;
1477 _MALLOC_UNLOCK(d->mutex);
1478 errno = saved_errno;
1479}
1480DEF_WEAK(freezero);
1421 1481
1422static void * 1482static void *
1423orealloc(struct dir_info *argpool, void *p, size_t newsz, void *f) 1483orealloc(struct dir_info *argpool, void *p, size_t newsz, void *f)
@@ -1591,7 +1651,7 @@ gotit:
1591 } 1651 }
1592 if (newsz != 0 && oldsz != 0) 1652 if (newsz != 0 && oldsz != 0)
1593 memcpy(q, p, oldsz < newsz ? oldsz : newsz); 1653 memcpy(q, p, oldsz < newsz ? oldsz : newsz);
1594 ofree(pool, p, 0); 1654 ofree(pool, p, 0, 0, 0);
1595 ret = q; 1655 ret = q;
1596 } else { 1656 } else {
1597 /* oldsz == newsz */ 1657 /* oldsz == newsz */
@@ -1751,7 +1811,7 @@ orecallocarray(struct dir_info *argpool, void *p, size_t oldsize,
1751 } else 1811 } else
1752 memcpy(newptr, p, newsize); 1812 memcpy(newptr, p, newsize);
1753 1813
1754 ofree(pool, p, 1); 1814 ofree(pool, p, 1, 0, 0);
1755 1815
1756done: 1816done:
1757 if (argpool != pool) { 1817 if (argpool != pool) {
@@ -1824,7 +1884,7 @@ recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size)
1824 void *r; 1884 void *r;
1825 int saved_errno = errno; 1885 int saved_errno = errno;
1826 1886
1827 if (!mopts.internal_recallocarray) 1887 if (!mopts.internal_funcs)
1828 return recallocarray_p(ptr, oldnmemb, newnmemb, size); 1888 return recallocarray_p(ptr, oldnmemb, newnmemb, size);
1829 1889
1830 d = getpool(); 1890 d = getpool();
@@ -2275,8 +2335,8 @@ malloc_exit(void)
2275 __progname); 2335 __progname);
2276 write(fd, buf, strlen(buf)); 2336 write(fd, buf, strlen(buf));
2277 snprintf(buf, sizeof(buf), 2337 snprintf(buf, sizeof(buf),
2278 "MT=%d IRC=%d F=%d U=%d J=%d R=%d X=%d C=%d cache=%u G=%zu\n", 2338 "MT=%d I=%d F=%d U=%d J=%d R=%d X=%d C=%d cache=%u G=%zu\n",
2279 mopts.malloc_mt, mopts.internal_recallocarray, 2339 mopts.malloc_mt, mopts.internal_funcs,
2280 mopts.malloc_freenow, 2340 mopts.malloc_freenow,
2281 mopts.malloc_freeunmap, mopts.malloc_junk, 2341 mopts.malloc_freeunmap, mopts.malloc_junk,
2282 mopts.malloc_realloc, mopts.malloc_xmalloc, 2342 mopts.malloc_realloc, mopts.malloc_xmalloc,