diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2004-06-14 15:07:37 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2004-06-14 15:07:37 +0000 |
commit | b37855660145f0a52aad66d5c65d938da2b6f322 (patch) | |
tree | a65423ea5968f87343bf0747712aabaf934f4913 /libexec | |
parent | c16191c9a13fe874af2df610136c41bb0d467edc (diff) |
Make _dl_malloc() deal with allocations > 4096 correctly. Also place
unused memory chunks on the free list when making a large allocation.
OK drahn@ deraadt@
Diffstat (limited to 'libexec')
-rw-r--r-- | libexec/ld.so/util.c | 34 |
1 files changed, 20 insertions, 14 deletions
diff --git a/libexec/ld.so/util.c b/libexec/ld.so/util.c index 4cbad23e467..0920dd3efc3 100644 --- a/libexec/ld.so/util.c +++ b/libexec/ld.so/util.c @@ -1,4 +1,4 @@ -/* $OpenBSD: util.c,v 1.17 2004/02/25 23:36:11 drahn Exp $ */ +/* $OpenBSD: util.c,v 1.18 2004/06/14 15:07:36 millert Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -51,7 +51,6 @@ __stack_smash_handler(char func[], int damaged) /* * Static vars usable after bootstrapping. */ -static void *_dl_malloc_base; static void *_dl_malloc_pool = 0; static long *_dl_malloc_free = 0; @@ -67,6 +66,8 @@ _dl_strdup(const char *orig) return (newstr); } +#define _dl_round_page(x) (((x) + (__LDPGSZ - 1)) & ~(__LDPGSZ - 1)) + /* * The following malloc/free code is a very simplified implementation * of a malloc function. However, we do not need to be very complex here @@ -76,15 +77,15 @@ _dl_strdup(const char *orig) * we can reuse that one to without a lot of complex colapsing code. */ void * -_dl_malloc(size_t size) +_dl_malloc(size_t need) { - long *p, *t, *n; + long *p, *t, *n, have; - size = (size + 8 + DL_MALLOC_ALIGN - 1) & ~(DL_MALLOC_ALIGN - 1); + need = (need + 8 + DL_MALLOC_ALIGN - 1) & ~(DL_MALLOC_ALIGN - 1); if ((t = _dl_malloc_free) != 0) { /* Try free list first */ n = (long *)&_dl_malloc_free; - while (t && t[-1] < size) { + while (t && t[-1] < need) { n = t; t = (long *)*t; } @@ -94,20 +95,25 @@ _dl_malloc(size_t size) return((void *)t); } } - if (_dl_malloc_pool == 0 || - _dl_malloc_pool + size > _dl_malloc_base + 4096) { - _dl_malloc_pool = (void *)_dl_mmap((void *)0, 4096, - PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0); + have = _dl_round_page((long)_dl_malloc_pool) - (long)_dl_malloc_pool; + if (need > have) { + if (have >= 8 + DL_MALLOC_ALIGN) { + p = _dl_malloc_pool; + *p = have; + _dl_free((void *)(p + 1)); /* move to freelist */ + } + _dl_malloc_pool = (void *)_dl_mmap((void *)0, + _dl_round_page(need), PROT_READ|PROT_WRITE, + MAP_ANON|MAP_PRIVATE, -1, 0); if (_dl_malloc_pool == 0 || _dl_malloc_pool == MAP_FAILED ) { _dl_printf("Dynamic loader failure: malloc.\n"); _dl_exit(7); } - _dl_malloc_base = _dl_malloc_pool; } p = _dl_malloc_pool; - _dl_malloc_pool += size; - _dl_memset(p, 0, size); - *p = size; + _dl_malloc_pool += need; + _dl_memset(p, 0, need); + *p = need; return((void *)(p + 1)); } |