aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/android_je_mallinfo.c100
-rw-r--r--src/arena.c10
-rw-r--r--src/jemalloc.c16
-rw-r--r--src/pages.c18
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);