diff --git a/Makefile.in b/Makefile.in index f60823f5..4b0e184f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -138,6 +138,7 @@ TESTS_UNIT := $(srcroot)test/unit/atomic.c \ $(srcroot)test/unit/bitmap.c \ $(srcroot)test/unit/ckh.c \ $(srcroot)test/unit/decay.c \ + $(srcroot)test/unit/fork.c \ $(srcroot)test/unit/hash.c \ $(srcroot)test/unit/junk.c \ $(srcroot)test/unit/junk_alloc.c \ diff --git a/include/jemalloc/internal/arena.h b/include/jemalloc/internal/arena.h index 3519873c..42a78960 100644 --- a/include/jemalloc/internal/arena.h +++ b/include/jemalloc/internal/arena.h @@ -584,7 +584,10 @@ void arena_nthreads_inc(arena_t *arena); void arena_nthreads_dec(arena_t *arena); arena_t *arena_new(unsigned ind); bool arena_boot(void); -void arena_prefork(arena_t *arena); +void arena_prefork0(arena_t *arena); +void arena_prefork1(arena_t *arena); +void arena_prefork2(arena_t *arena); +void arena_prefork3(arena_t *arena); void arena_postfork_parent(arena_t *arena); void arena_postfork_child(arena_t *arena); diff --git a/include/jemalloc/internal/private_symbols.txt b/include/jemalloc/internal/private_symbols.txt index 5fcc6692..fafee81f 100644 --- a/include/jemalloc/internal/private_symbols.txt +++ b/include/jemalloc/internal/private_symbols.txt @@ -81,7 +81,10 @@ arena_nthreads_inc arena_palloc arena_postfork_child arena_postfork_parent -arena_prefork +arena_prefork0 +arena_prefork1 +arena_prefork2 +arena_prefork3 arena_prof_accum arena_prof_accum_impl arena_prof_accum_locked @@ -408,7 +411,8 @@ prof_malloc_sample_object prof_mdump prof_postfork_child prof_postfork_parent -prof_prefork +prof_prefork0 +prof_prefork1 prof_realloc prof_reset prof_sample_accum_update diff --git a/include/jemalloc/internal/prof.h b/include/jemalloc/internal/prof.h index a25502a9..48dd6cc5 100644 --- a/include/jemalloc/internal/prof.h +++ b/include/jemalloc/internal/prof.h @@ -316,7 +316,8 @@ bool prof_gdump_set(bool active); void prof_boot0(void); void prof_boot1(void); bool prof_boot2(void); -void prof_prefork(void); +void prof_prefork0(void); +void prof_prefork1(void); void prof_postfork_parent(void); void prof_postfork_child(void); void prof_sample_threshold_update(prof_tdata_t *tdata); diff --git a/src/arena.c b/src/arena.c index b7645d8b..48e9b20b 100644 --- a/src/arena.c +++ b/src/arena.c @@ -3646,16 +3646,34 @@ arena_boot(void) } void -arena_prefork(arena_t *arena) +arena_prefork0(arena_t *arena) +{ + + malloc_mutex_prefork(&arena->lock); +} + +void +arena_prefork1(arena_t *arena) +{ + + malloc_mutex_prefork(&arena->chunks_mtx); +} + +void +arena_prefork2(arena_t *arena) +{ + + malloc_mutex_prefork(&arena->node_cache_mtx); +} + +void +arena_prefork3(arena_t *arena) { unsigned i; - malloc_mutex_prefork(&arena->lock); - malloc_mutex_prefork(&arena->huge_mtx); - malloc_mutex_prefork(&arena->chunks_mtx); - malloc_mutex_prefork(&arena->node_cache_mtx); for (i = 0; i < NBINS; i++) malloc_mutex_prefork(&arena->bins[i].lock); + malloc_mutex_prefork(&arena->huge_mtx); } void @@ -3663,11 +3681,11 @@ arena_postfork_parent(arena_t *arena) { unsigned i; + malloc_mutex_postfork_parent(&arena->huge_mtx); for (i = 0; i < NBINS; i++) malloc_mutex_postfork_parent(&arena->bins[i].lock); malloc_mutex_postfork_parent(&arena->node_cache_mtx); malloc_mutex_postfork_parent(&arena->chunks_mtx); - malloc_mutex_postfork_parent(&arena->huge_mtx); malloc_mutex_postfork_parent(&arena->lock); } @@ -3676,10 +3694,10 @@ arena_postfork_child(arena_t *arena) { unsigned i; + malloc_mutex_postfork_child(&arena->huge_mtx); for (i = 0; i < NBINS; i++) malloc_mutex_postfork_child(&arena->bins[i].lock); malloc_mutex_postfork_child(&arena->node_cache_mtx); malloc_mutex_postfork_child(&arena->chunks_mtx); - malloc_mutex_postfork_child(&arena->huge_mtx); malloc_mutex_postfork_child(&arena->lock); } diff --git a/src/jemalloc.c b/src/jemalloc.c index 0735376e..71207913 100644 --- a/src/jemalloc.c +++ b/src/jemalloc.c @@ -2644,7 +2644,8 @@ JEMALLOC_EXPORT void _malloc_prefork(void) #endif { - unsigned i, narenas; + unsigned i, j, narenas; + arena_t *arena; #ifdef JEMALLOC_MUTEX_INIT_CB if (!malloc_initialized()) @@ -2652,18 +2653,31 @@ _malloc_prefork(void) #endif assert(malloc_initialized()); + narenas = narenas_total_get(); + /* Acquire all mutexes in a safe order. */ ctl_prefork(); - prof_prefork(); malloc_mutex_prefork(&arenas_lock); - for (i = 0, narenas = narenas_total_get(); i < narenas; i++) { - arena_t *arena; - - if ((arena = arena_get(i, false)) != NULL) - arena_prefork(arena); + prof_prefork0(); + for (i = 0; i < 3; i++) { + for (j = 0; j < narenas; j++) { + if ((arena = arena_get(j, false)) != NULL) { + switch (i) { + case 0: arena_prefork0(arena); break; + case 1: arena_prefork1(arena); break; + case 2: arena_prefork2(arena); break; + default: not_reached(); + } + } + } } - chunk_prefork(); base_prefork(); + chunk_prefork(); + for (i = 0; i < narenas; i++) { + if ((arena = arena_get(i, false)) != NULL) + arena_prefork3(arena); + } + prof_prefork1(); } #ifndef JEMALLOC_MUTEX_INIT_CB @@ -2683,16 +2697,16 @@ _malloc_postfork(void) assert(malloc_initialized()); /* Release all mutexes, now that fork() has completed. */ - base_postfork_parent(); chunk_postfork_parent(); + base_postfork_parent(); for (i = 0, narenas = narenas_total_get(); i < narenas; i++) { arena_t *arena; if ((arena = arena_get(i, false)) != NULL) arena_postfork_parent(arena); } - malloc_mutex_postfork_parent(&arenas_lock); prof_postfork_parent(); + malloc_mutex_postfork_parent(&arenas_lock); ctl_postfork_parent(); } @@ -2704,16 +2718,16 @@ jemalloc_postfork_child(void) assert(malloc_initialized()); /* Release all mutexes, now that fork() has completed. */ - base_postfork_child(); chunk_postfork_child(); + base_postfork_child(); for (i = 0, narenas = narenas_total_get(); i < narenas; i++) { arena_t *arena; if ((arena = arena_get(i, false)) != NULL) arena_postfork_child(arena); } - malloc_mutex_postfork_child(&arenas_lock); prof_postfork_child(); + malloc_mutex_postfork_child(&arenas_lock); ctl_postfork_child(); } diff --git a/src/prof.c b/src/prof.c index b3872277..a92320d4 100644 --- a/src/prof.c +++ b/src/prof.c @@ -2198,20 +2198,32 @@ prof_boot2(void) } void -prof_prefork(void) +prof_prefork0(void) { if (opt_prof) { unsigned i; - malloc_mutex_prefork(&tdatas_mtx); + malloc_mutex_prefork(&prof_dump_mtx); malloc_mutex_prefork(&bt2gctx_mtx); - malloc_mutex_prefork(&next_thr_uid_mtx); - malloc_mutex_prefork(&prof_dump_seq_mtx); - for (i = 0; i < PROF_NCTX_LOCKS; i++) - malloc_mutex_prefork(&gctx_locks[i]); + malloc_mutex_prefork(&tdatas_mtx); for (i = 0; i < PROF_NTDATA_LOCKS; i++) malloc_mutex_prefork(&tdata_locks[i]); + for (i = 0; i < PROF_NCTX_LOCKS; i++) + malloc_mutex_prefork(&gctx_locks[i]); + } +} + +void +prof_prefork1(void) +{ + + if (opt_prof) { + malloc_mutex_prefork(&prof_active_mtx); + malloc_mutex_prefork(&prof_dump_seq_mtx); + malloc_mutex_prefork(&prof_gdump_mtx); + malloc_mutex_prefork(&next_thr_uid_mtx); + malloc_mutex_prefork(&prof_thread_active_init_mtx); } } @@ -2222,14 +2234,18 @@ prof_postfork_parent(void) if (opt_prof) { unsigned i; - for (i = 0; i < PROF_NTDATA_LOCKS; i++) - malloc_mutex_postfork_parent(&tdata_locks[i]); + malloc_mutex_postfork_parent(&prof_thread_active_init_mtx); + malloc_mutex_postfork_parent(&next_thr_uid_mtx); + malloc_mutex_postfork_parent(&prof_gdump_mtx); + malloc_mutex_postfork_parent(&prof_dump_seq_mtx); + malloc_mutex_postfork_parent(&prof_active_mtx); for (i = 0; i < PROF_NCTX_LOCKS; i++) malloc_mutex_postfork_parent(&gctx_locks[i]); - malloc_mutex_postfork_parent(&prof_dump_seq_mtx); - malloc_mutex_postfork_parent(&next_thr_uid_mtx); - malloc_mutex_postfork_parent(&bt2gctx_mtx); + for (i = 0; i < PROF_NTDATA_LOCKS; i++) + malloc_mutex_postfork_parent(&tdata_locks[i]); malloc_mutex_postfork_parent(&tdatas_mtx); + malloc_mutex_postfork_parent(&bt2gctx_mtx); + malloc_mutex_postfork_parent(&prof_dump_mtx); } } @@ -2240,14 +2256,18 @@ prof_postfork_child(void) if (opt_prof) { unsigned i; - for (i = 0; i < PROF_NTDATA_LOCKS; i++) - malloc_mutex_postfork_child(&tdata_locks[i]); + malloc_mutex_postfork_child(&prof_thread_active_init_mtx); + malloc_mutex_postfork_child(&next_thr_uid_mtx); + malloc_mutex_postfork_child(&prof_gdump_mtx); + malloc_mutex_postfork_child(&prof_dump_seq_mtx); + malloc_mutex_postfork_child(&prof_active_mtx); for (i = 0; i < PROF_NCTX_LOCKS; i++) malloc_mutex_postfork_child(&gctx_locks[i]); - malloc_mutex_postfork_child(&prof_dump_seq_mtx); - malloc_mutex_postfork_child(&next_thr_uid_mtx); - malloc_mutex_postfork_child(&bt2gctx_mtx); + for (i = 0; i < PROF_NTDATA_LOCKS; i++) + malloc_mutex_postfork_child(&tdata_locks[i]); malloc_mutex_postfork_child(&tdatas_mtx); + malloc_mutex_postfork_child(&bt2gctx_mtx); + malloc_mutex_postfork_child(&prof_dump_mtx); } } diff --git a/test/unit/fork.c b/test/unit/fork.c new file mode 100644 index 00000000..890bc869 --- /dev/null +++ b/test/unit/fork.c @@ -0,0 +1,39 @@ +#include "test/jemalloc_test.h" + +#include + +TEST_BEGIN(test_fork) +{ + void *p; + pid_t pid; + + p = malloc(1); + assert_ptr_not_null(p, "Unexpected malloc() failure"); + + pid = fork(); + if (pid == -1) { + /* Error. */ + test_fail("Unexpected fork() failure"); + } else if (pid == 0) { + /* Child. */ + exit(0); + } else { + int status; + + /* Parent. */ + free(p); + do { + if (waitpid(pid, &status, 0) == -1) + test_fail("Unexpected waitpid() failure"); + } while (!WIFEXITED(status) && !WIFSIGNALED(status)); + } +} +TEST_END + +int +main(void) +{ + + return (test( + test_fork)); +}