summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lib/libc/stdlib/malloc.c55
1 files changed, 32 insertions, 23 deletions
diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c
index b9f692ebb7..97092a2e0d 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.188 2016/04/12 18:14:02 otto Exp $ */ 1/* $OpenBSD: malloc.c,v 1.189 2016/06/27 15:33:40 tedu Exp $ */
2/* 2/*
3 * Copyright (c) 2008, 2010, 2011 Otto Moerbeek <otto@drijf.net> 3 * Copyright (c) 2008, 2010, 2011 Otto Moerbeek <otto@drijf.net>
4 * Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org> 4 * Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org>
@@ -122,6 +122,8 @@ struct dir_info {
122 char *func; /* current function */ 122 char *func; /* current function */
123 u_char rbytes[32]; /* random bytes */ 123 u_char rbytes[32]; /* random bytes */
124 u_short chunk_start; 124 u_short chunk_start;
125 void *unmap_me;
126 size_t unmap_me_sz;
125#ifdef MALLOC_STATS 127#ifdef MALLOC_STATS
126 size_t inserts; 128 size_t inserts;
127 size_t insert_collisions; 129 size_t insert_collisions;
@@ -218,10 +220,16 @@ static void malloc_exit(void);
218static inline void 220static inline void
219_MALLOC_LEAVE(struct dir_info *d) 221_MALLOC_LEAVE(struct dir_info *d)
220{ 222{
223 void *unmap_me = d->unmap_me;
224 size_t unmap_me_sz = d->unmap_me_sz;
225
221 if (__isthreaded) { 226 if (__isthreaded) {
222 d->active--; 227 d->active--;
223 _MALLOC_UNLOCK(); 228 _MALLOC_UNLOCK();
224 } 229 }
230
231 if (unmap_me != NULL)
232 munmap(unmap_me, unmap_me_sz);
225} 233}
226 234
227static inline void 235static inline void
@@ -231,6 +239,8 @@ _MALLOC_ENTER(struct dir_info *d)
231 _MALLOC_LOCK(); 239 _MALLOC_LOCK();
232 d->active++; 240 d->active++;
233 } 241 }
242 d->unmap_me = NULL;
243 d->unmap_me_sz = 0;
234} 244}
235 245
236static inline size_t 246static inline size_t
@@ -295,6 +305,16 @@ wrterror(struct dir_info *d, char *msg, void *p)
295 abort(); 305 abort();
296} 306}
297 307
308static inline void
309_MUNMAP(struct dir_info *d, void *p, size_t sz)
310{
311 if (d->unmap_me == NULL) {
312 d->unmap_me = p;
313 d->unmap_me_sz = sz;
314 } else if (munmap(p, sz) == -1)
315 wrterror(d, "munmap", p);
316}
317
298static void 318static void
299rbytes_init(struct dir_info *d) 319rbytes_init(struct dir_info *d)
300{ 320{
@@ -335,9 +355,7 @@ unmap(struct dir_info *d, void *p, size_t sz)
335 } 355 }
336 356
337 if (psz > mopts.malloc_cache) { 357 if (psz > mopts.malloc_cache) {
338 i = munmap(p, sz); 358 _MUNMAP(d, p, sz);
339 if (i)
340 wrterror(d, "munmap", p);
341 STATS_SUB(d->malloc_used, sz); 359 STATS_SUB(d->malloc_used, sz);
342 return; 360 return;
343 } 361 }
@@ -350,8 +368,7 @@ unmap(struct dir_info *d, void *p, size_t sz)
350 r = &d->free_regions[(i + offset) & (mopts.malloc_cache - 1)]; 368 r = &d->free_regions[(i + offset) & (mopts.malloc_cache - 1)];
351 if (r->p != NULL) { 369 if (r->p != NULL) {
352 rsz = r->size << MALLOC_PAGESHIFT; 370 rsz = r->size << MALLOC_PAGESHIFT;
353 if (munmap(r->p, rsz)) 371 _MUNMAP(d, r->p, rsz);
354 wrterror(d, "munmap", r->p);
355 r->p = NULL; 372 r->p = NULL;
356 if (tounmap > r->size) 373 if (tounmap > r->size)
357 tounmap -= r->size; 374 tounmap -= r->size;
@@ -394,8 +411,7 @@ zapcacheregion(struct dir_info *d, void *p, size_t len)
394 r = &d->free_regions[i]; 411 r = &d->free_regions[i];
395 if (r->p >= p && r->p <= (void *)((char *)p + len)) { 412 if (r->p >= p && r->p <= (void *)((char *)p + len)) {
396 rsz = r->size << MALLOC_PAGESHIFT; 413 rsz = r->size << MALLOC_PAGESHIFT;
397 if (munmap(r->p, rsz)) 414 _MUNMAP(d, r->p, rsz);
398 wrterror(d, "munmap", r->p);
399 r->p = NULL; 415 r->p = NULL;
400 d->free_regions_size -= r->size; 416 d->free_regions_size -= r->size;
401 r->size = 0; 417 r->size = 0;
@@ -727,11 +743,9 @@ omalloc_grow(struct dir_info *d)
727 } 743 }
728 } 744 }
729 /* avoid pages containing meta info to end up in cache */ 745 /* avoid pages containing meta info to end up in cache */
730 if (munmap(d->r, d->regions_total * sizeof(struct region_info))) 746 _MUNMAP(d, d->r, d->regions_total * sizeof(struct region_info));
731 wrterror(d, "munmap", d->r); 747 STATS_SUB(d->malloc_used,
732 else 748 d->regions_total * sizeof(struct region_info));
733 STATS_SUB(d->malloc_used,
734 d->regions_total * sizeof(struct region_info));
735 d->regions_free = d->regions_free + d->regions_total; 749 d->regions_free = d->regions_free + d->regions_total;
736 d->regions_total = newtotal; 750 d->regions_total = newtotal;
737 d->r = p; 751 d->r = p;
@@ -1428,10 +1442,8 @@ gotit:
1428 STATS_SETF(r, f); 1442 STATS_SETF(r, f);
1429 STATS_INC(pool->cheap_reallocs); 1443 STATS_INC(pool->cheap_reallocs);
1430 return p; 1444 return p;
1431 } else if (q != MAP_FAILED) { 1445 } else if (q != MAP_FAILED)
1432 if (munmap(q, needed)) 1446 _MUNMAP(pool, q, needed);
1433 wrterror(pool, "munmap", q);
1434 }
1435 } 1447 }
1436 } else if (rnewsz < roldsz) { 1448 } else if (rnewsz < roldsz) {
1437 if (mopts.malloc_guard) { 1449 if (mopts.malloc_guard) {
@@ -1600,12 +1612,9 @@ mapalign(struct dir_info *d, size_t alignment, size_t sz, int zero_fill)
1600 if (p == MAP_FAILED) 1612 if (p == MAP_FAILED)
1601 return MAP_FAILED; 1613 return MAP_FAILED;
1602 q = (char *)(((uintptr_t)p + alignment - 1) & ~(alignment - 1)); 1614 q = (char *)(((uintptr_t)p + alignment - 1) & ~(alignment - 1));
1603 if (q != p) { 1615 if (q != p)
1604 if (munmap(p, q - p)) 1616 _MUNMAP(d, p, q - p);
1605 wrterror(d, "munmap", p); 1617 _MUNMAP(d, q + sz, alignment - (q - p));
1606 }
1607 if (munmap(q + sz, alignment - (q - p)))
1608 wrterror(d, "munmap", q + sz);
1609 STATS_SUB(d->malloc_used, alignment); 1618 STATS_SUB(d->malloc_used, alignment);
1610 1619
1611 return q; 1620 return q;