diff options
author | Jason Evans <jasone@canonware.com> | 2015-06-22 18:50:32 -0700 |
---|---|---|
committer | Jason Evans <jasone@canonware.com> | 2015-06-22 18:50:58 -0700 |
commit | 0a9f9a4d511e0c3343ff26e04d9592fefd96c2bc (patch) | |
tree | 39eb3985e55a9cbee05d9dc7f87c7cf4c6102b91 /src/arena.c | |
parent | dc0610a714c1ff207bf87ba907506ae0b111e092 (diff) | |
download | jemalloc-0a9f9a4d511e0c3343ff26e04d9592fefd96c2bc.tar.gz |
Convert arena_maybe_purge() recursion to iteration.
This resolves #235.
Diffstat (limited to 'src/arena.c')
-rw-r--r-- | src/arena.c | 34 |
1 files changed, 24 insertions, 10 deletions
diff --git a/src/arena.c b/src/arena.c index a3f36b3..fa37e30 100644 --- a/src/arena.c +++ b/src/arena.c @@ -1143,21 +1143,29 @@ arena_lg_dirty_mult_set(arena_t *arena, ssize_t lg_dirty_mult) void arena_maybe_purge(arena_t *arena) { - size_t threshold; /* Don't purge if the option is disabled. */ if (arena->lg_dirty_mult < 0) return; - threshold = (arena->nactive >> arena->lg_dirty_mult); - threshold = threshold < chunk_npages ? chunk_npages : threshold; + /* Don't recursively purge. */ + if (arena->purging) + return; /* - * Don't purge unless the number of purgeable pages exceeds the - * threshold. + * Iterate, since preventing recursive purging could otherwise leave too + * many dirty pages. */ - if (arena->ndirty <= threshold) - return; - - arena_purge(arena, false); + while (true) { + size_t threshold = (arena->nactive >> arena->lg_dirty_mult); + if (threshold < chunk_npages) + threshold = chunk_npages; + /* + * Don't purge unless the number of purgeable pages exceeds the + * threshold. + */ + if (arena->ndirty <= threshold) + return; + arena_purge(arena, false); + } } static size_t @@ -1411,6 +1419,8 @@ arena_purge(arena_t *arena, bool all) arena_runs_dirty_link_t purge_runs_sentinel; extent_node_t purge_chunks_sentinel; + arena->purging = true; + /* * Calls to arena_dirty_count() are disabled even for debug builds * because overhead grows nonlinearly as memory usage increases. @@ -1436,6 +1446,8 @@ arena_purge(arena_t *arena, bool all) assert(npurged == npurgeable); arena_unstash_purged(arena, &purge_runs_sentinel, &purge_chunks_sentinel); + + arena->purging = false; } void @@ -2053,7 +2065,8 @@ arena_malloc_large(arena_t *arena, size_t size, bool zero) * for 4 KiB pages and 64-byte cachelines. */ prng64(r, LG_PAGE - LG_CACHELINE, arena->offset_state, - UINT64_C(6364136223846793009), UINT64_C(1442695040888963409)); + UINT64_C(6364136223846793009), + UINT64_C(1442695040888963409)); random_offset = ((uintptr_t)r) << LG_CACHELINE; } else random_offset = 0; @@ -2873,6 +2886,7 @@ arena_new(unsigned ind) arena->spare = NULL; arena->lg_dirty_mult = arena_lg_dirty_mult_default_get(); + arena->purging = false; arena->nactive = 0; arena->ndirty = 0; |