diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/android_je_mallinfo.c | 100 | ||||
-rw-r--r-- | src/arena.c | 10 | ||||
-rw-r--r-- | src/jemalloc.c | 16 | ||||
-rw-r--r-- | src/pages.c | 18 |
4 files changed, 143 insertions, 1 deletions
diff --git a/src/android_je_mallinfo.c b/src/android_je_mallinfo.c new file mode 100644 index 0000000..1637edd --- /dev/null +++ b/src/android_je_mallinfo.c @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This is an implementation that uses the same arena access pattern found + * in the arena_stats_merge function from src/arena.c. + */ +struct mallinfo je_mallinfo() { + struct mallinfo mi; + memset(&mi, 0, sizeof(mi)); + + malloc_mutex_lock(&arenas_lock); + for (unsigned i = 0; i < narenas_auto; i++) { + if (arenas[i] != NULL) { + malloc_mutex_lock(&arenas[i]->lock); + mi.hblkhd += arenas[i]->stats.mapped; + mi.uordblks += arenas[i]->stats.allocated_large; + mi.uordblks += arenas[i]->stats.allocated_huge; + malloc_mutex_unlock(&arenas[i]->lock); + + for (unsigned j = 0; j < NBINS; j++) { + arena_bin_t* bin = &arenas[i]->bins[j]; + + malloc_mutex_lock(&bin->lock); + mi.uordblks += arena_bin_info[j].reg_size * bin->stats.curregs; + malloc_mutex_unlock(&bin->lock); + } + } + } + malloc_mutex_unlock(&arenas_lock); + mi.fordblks = mi.hblkhd - mi.uordblks; + mi.usmblks = mi.hblkhd; + return mi; +} + +size_t __mallinfo_narenas() { + return narenas_auto; +} + +size_t __mallinfo_nbins() { + return NBINS; +} + +struct mallinfo __mallinfo_arena_info(size_t aidx) { + struct mallinfo mi; + memset(&mi, 0, sizeof(mi)); + + malloc_mutex_lock(&arenas_lock); + if (aidx < narenas_auto) { + if (arenas[aidx] != NULL) { + malloc_mutex_lock(&arenas[aidx]->lock); + mi.hblkhd = arenas[aidx]->stats.mapped; + mi.ordblks = arenas[aidx]->stats.allocated_large; + mi.uordblks = arenas[aidx]->stats.allocated_huge; + malloc_mutex_unlock(&arenas[aidx]->lock); + + for (unsigned j = 0; j < NBINS; j++) { + arena_bin_t* bin = &arenas[aidx]->bins[j]; + + malloc_mutex_lock(&bin->lock); + mi.fsmblks += arena_bin_info[j].reg_size * bin->stats.curregs; + malloc_mutex_unlock(&bin->lock); + } + } + } + malloc_mutex_unlock(&arenas_lock); + return mi; +} + +struct mallinfo __mallinfo_bin_info(size_t aidx, size_t bidx) { + struct mallinfo mi; + memset(&mi, 0, sizeof(mi)); + + malloc_mutex_lock(&arenas_lock); + if (aidx < narenas_auto && bidx < NBINS) { + if (arenas[aidx] != NULL) { + arena_bin_t* bin = &arenas[aidx]->bins[bidx]; + + malloc_mutex_lock(&bin->lock); + mi.ordblks = arena_bin_info[bidx].reg_size * bin->stats.curregs; + mi.uordblks = bin->stats.nmalloc; + mi.fordblks = bin->stats.ndalloc; + malloc_mutex_unlock(&bin->lock); + } + } + malloc_mutex_unlock(&arenas_lock); + return mi; +} diff --git a/src/arena.c b/src/arena.c index 949fc5b..07d83ef 100644 --- a/src/arena.c +++ b/src/arena.c @@ -1207,10 +1207,13 @@ arena_lg_dirty_mult_set(arena_t *arena, ssize_t lg_dirty_mult) void arena_maybe_purge(arena_t *arena) { - +#if defined(ANDROID_ALWAYS_PURGE) + size_t num_tries = 0; +#else /* Don't purge if the option is disabled. */ if (arena->lg_dirty_mult < 0) return; +#endif /* Don't recursively purge. */ if (arena->purging) return; @@ -1219,6 +1222,10 @@ arena_maybe_purge(arena_t *arena) * many dirty pages. */ while (true) { +#if defined(ANDROID_ALWAYS_PURGE) + if (arena->ndirty == 0 || ++num_tries == 3) + return; +#else size_t threshold = (arena->nactive >> arena->lg_dirty_mult); if (threshold < chunk_npages) threshold = chunk_npages; @@ -1228,6 +1235,7 @@ arena_maybe_purge(arena_t *arena) */ if (arena->ndirty <= threshold) return; +#endif arena_purge(arena, false); } } diff --git a/src/jemalloc.c b/src/jemalloc.c index 7cf1487..8e56bb0 100644 --- a/src/jemalloc.c +++ b/src/jemalloc.c @@ -864,7 +864,11 @@ malloc_conf_init(void) opt_tcache = false; } +#if defined(__ANDROID__) + for (i = 0; i < 1; i++) { +#else for (i = 0; i < 3; i++) { +#endif /* Get runtime configuration. */ switch (i) { case 0: @@ -1278,6 +1282,14 @@ malloc_init_hard_finish(void) else opt_narenas = 1; } +#if defined(ANDROID_MAX_ARENAS) + /* Never create more than MAX_ARENAS arenas regardless of num_cpus. + * Extra arenas use more PSS and are not very useful unless + * lots of threads are allocing/freeing at the same time. + */ + if (opt_narenas > ANDROID_MAX_ARENAS) + opt_narenas = ANDROID_MAX_ARENAS; +#endif narenas_auto = opt_narenas; /* * Make sure that the arenas array can be allocated. In practice, this @@ -2593,3 +2605,7 @@ jemalloc_postfork_child(void) } /******************************************************************************/ + +/* ANDROID extension */ +#include "android_je_mallinfo.c" +/* End ANDROID extension */ diff --git a/src/pages.c b/src/pages.c index 83a167f..993c0a6 100644 --- a/src/pages.c +++ b/src/pages.c @@ -2,6 +2,17 @@ #include "jemalloc/internal/jemalloc_internal.h" /******************************************************************************/ +/* Defines/includes needed for special android code. */ + +#if defined(__ANDROID__) +#include <sys/prctl.h> + +/* Definitions of prctl arguments to set a vma name in Android kernels. */ +#define ANDROID_PR_SET_VMA 0x53564d41 +#define ANDROID_PR_SET_VMA_ANON_NAME 0 +#endif + +/******************************************************************************/ void * pages_map(void *addr, size_t size) @@ -36,6 +47,13 @@ pages_map(void *addr, size_t size) ret = NULL; } #endif +#if defined(__ANDROID__) + if (ret != NULL) { + /* Name this memory as being used by libc */ + prctl(ANDROID_PR_SET_VMA, ANDROID_PR_SET_VMA_ANON_NAME, ret, + size, "libc_malloc"); + } +#endif assert(ret == NULL || (addr == NULL && ret != addr) || (addr != NULL && ret == addr)); return (ret); |