Skip to content

Commit 2687a72

Browse files
committed
Fix fork()-related lock rank ordering reversals.
1 parent de35328 commit 2687a72

File tree

8 files changed

+137
-37
lines changed

8 files changed

+137
-37
lines changed

Makefile.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ TESTS_UNIT := $(srcroot)test/unit/atomic.c \
138138
$(srcroot)test/unit/bitmap.c \
139139
$(srcroot)test/unit/ckh.c \
140140
$(srcroot)test/unit/decay.c \
141+
$(srcroot)test/unit/fork.c \
141142
$(srcroot)test/unit/hash.c \
142143
$(srcroot)test/unit/junk.c \
143144
$(srcroot)test/unit/junk_alloc.c \

include/jemalloc/internal/arena.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,10 @@ void arena_nthreads_inc(arena_t *arena);
584584
void arena_nthreads_dec(arena_t *arena);
585585
arena_t *arena_new(unsigned ind);
586586
bool arena_boot(void);
587-
void arena_prefork(arena_t *arena);
587+
void arena_prefork0(arena_t *arena);
588+
void arena_prefork1(arena_t *arena);
589+
void arena_prefork2(arena_t *arena);
590+
void arena_prefork3(arena_t *arena);
588591
void arena_postfork_parent(arena_t *arena);
589592
void arena_postfork_child(arena_t *arena);
590593

include/jemalloc/internal/private_symbols.txt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,10 @@ arena_nthreads_inc
8181
arena_palloc
8282
arena_postfork_child
8383
arena_postfork_parent
84-
arena_prefork
84+
arena_prefork0
85+
arena_prefork1
86+
arena_prefork2
87+
arena_prefork3
8588
arena_prof_accum
8689
arena_prof_accum_impl
8790
arena_prof_accum_locked
@@ -408,7 +411,8 @@ prof_malloc_sample_object
408411
prof_mdump
409412
prof_postfork_child
410413
prof_postfork_parent
411-
prof_prefork
414+
prof_prefork0
415+
prof_prefork1
412416
prof_realloc
413417
prof_reset
414418
prof_sample_accum_update

include/jemalloc/internal/prof.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,8 @@ bool prof_gdump_set(bool active);
316316
void prof_boot0(void);
317317
void prof_boot1(void);
318318
bool prof_boot2(void);
319-
void prof_prefork(void);
319+
void prof_prefork0(void);
320+
void prof_prefork1(void);
320321
void prof_postfork_parent(void);
321322
void prof_postfork_child(void);
322323
void prof_sample_threshold_update(prof_tdata_t *tdata);

src/arena.c

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3646,28 +3646,46 @@ arena_boot(void)
36463646
}
36473647

36483648
void
3649-
arena_prefork(arena_t *arena)
3649+
arena_prefork0(arena_t *arena)
36503650
{
3651-
unsigned i;
36523651

36533652
malloc_mutex_prefork(&arena->lock);
3654-
malloc_mutex_prefork(&arena->huge_mtx);
3653+
}
3654+
3655+
void
3656+
arena_prefork1(arena_t *arena)
3657+
{
3658+
36553659
malloc_mutex_prefork(&arena->chunks_mtx);
3660+
}
3661+
3662+
void
3663+
arena_prefork2(arena_t *arena)
3664+
{
3665+
36563666
malloc_mutex_prefork(&arena->node_cache_mtx);
3667+
}
3668+
3669+
void
3670+
arena_prefork3(arena_t *arena)
3671+
{
3672+
unsigned i;
3673+
36573674
for (i = 0; i < NBINS; i++)
36583675
malloc_mutex_prefork(&arena->bins[i].lock);
3676+
malloc_mutex_prefork(&arena->huge_mtx);
36593677
}
36603678

36613679
void
36623680
arena_postfork_parent(arena_t *arena)
36633681
{
36643682
unsigned i;
36653683

3684+
malloc_mutex_postfork_parent(&arena->huge_mtx);
36663685
for (i = 0; i < NBINS; i++)
36673686
malloc_mutex_postfork_parent(&arena->bins[i].lock);
36683687
malloc_mutex_postfork_parent(&arena->node_cache_mtx);
36693688
malloc_mutex_postfork_parent(&arena->chunks_mtx);
3670-
malloc_mutex_postfork_parent(&arena->huge_mtx);
36713689
malloc_mutex_postfork_parent(&arena->lock);
36723690
}
36733691

@@ -3676,10 +3694,10 @@ arena_postfork_child(arena_t *arena)
36763694
{
36773695
unsigned i;
36783696

3697+
malloc_mutex_postfork_child(&arena->huge_mtx);
36793698
for (i = 0; i < NBINS; i++)
36803699
malloc_mutex_postfork_child(&arena->bins[i].lock);
36813700
malloc_mutex_postfork_child(&arena->node_cache_mtx);
36823701
malloc_mutex_postfork_child(&arena->chunks_mtx);
3683-
malloc_mutex_postfork_child(&arena->huge_mtx);
36843702
malloc_mutex_postfork_child(&arena->lock);
36853703
}

src/jemalloc.c

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2644,26 +2644,40 @@ JEMALLOC_EXPORT void
26442644
_malloc_prefork(void)
26452645
#endif
26462646
{
2647-
unsigned i, narenas;
2647+
unsigned i, j, narenas;
2648+
arena_t *arena;
26482649

26492650
#ifdef JEMALLOC_MUTEX_INIT_CB
26502651
if (!malloc_initialized())
26512652
return;
26522653
#endif
26532654
assert(malloc_initialized());
26542655

2656+
narenas = narenas_total_get();
2657+
26552658
/* Acquire all mutexes in a safe order. */
26562659
ctl_prefork();
2657-
prof_prefork();
26582660
malloc_mutex_prefork(&arenas_lock);
2659-
for (i = 0, narenas = narenas_total_get(); i < narenas; i++) {
2660-
arena_t *arena;
2661-
2662-
if ((arena = arena_get(i, false)) != NULL)
2663-
arena_prefork(arena);
2661+
prof_prefork0();
2662+
for (i = 0; i < 3; i++) {
2663+
for (j = 0; j < narenas; j++) {
2664+
if ((arena = arena_get(j, false)) != NULL) {
2665+
switch (i) {
2666+
case 0: arena_prefork0(arena); break;
2667+
case 1: arena_prefork1(arena); break;
2668+
case 2: arena_prefork2(arena); break;
2669+
default: not_reached();
2670+
}
2671+
}
2672+
}
26642673
}
2665-
chunk_prefork();
26662674
base_prefork();
2675+
chunk_prefork();
2676+
for (i = 0; i < narenas; i++) {
2677+
if ((arena = arena_get(i, false)) != NULL)
2678+
arena_prefork3(arena);
2679+
}
2680+
prof_prefork1();
26672681
}
26682682

26692683
#ifndef JEMALLOC_MUTEX_INIT_CB
@@ -2683,16 +2697,16 @@ _malloc_postfork(void)
26832697
assert(malloc_initialized());
26842698

26852699
/* Release all mutexes, now that fork() has completed. */
2686-
base_postfork_parent();
26872700
chunk_postfork_parent();
2701+
base_postfork_parent();
26882702
for (i = 0, narenas = narenas_total_get(); i < narenas; i++) {
26892703
arena_t *arena;
26902704

26912705
if ((arena = arena_get(i, false)) != NULL)
26922706
arena_postfork_parent(arena);
26932707
}
2694-
malloc_mutex_postfork_parent(&arenas_lock);
26952708
prof_postfork_parent();
2709+
malloc_mutex_postfork_parent(&arenas_lock);
26962710
ctl_postfork_parent();
26972711
}
26982712

@@ -2704,16 +2718,16 @@ jemalloc_postfork_child(void)
27042718
assert(malloc_initialized());
27052719

27062720
/* Release all mutexes, now that fork() has completed. */
2707-
base_postfork_child();
27082721
chunk_postfork_child();
2722+
base_postfork_child();
27092723
for (i = 0, narenas = narenas_total_get(); i < narenas; i++) {
27102724
arena_t *arena;
27112725

27122726
if ((arena = arena_get(i, false)) != NULL)
27132727
arena_postfork_child(arena);
27142728
}
2715-
malloc_mutex_postfork_child(&arenas_lock);
27162729
prof_postfork_child();
2730+
malloc_mutex_postfork_child(&arenas_lock);
27172731
ctl_postfork_child();
27182732
}
27192733

src/prof.c

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2198,20 +2198,32 @@ prof_boot2(void)
21982198
}
21992199

22002200
void
2201-
prof_prefork(void)
2201+
prof_prefork0(void)
22022202
{
22032203

22042204
if (opt_prof) {
22052205
unsigned i;
22062206

2207-
malloc_mutex_prefork(&tdatas_mtx);
2207+
malloc_mutex_prefork(&prof_dump_mtx);
22082208
malloc_mutex_prefork(&bt2gctx_mtx);
2209-
malloc_mutex_prefork(&next_thr_uid_mtx);
2210-
malloc_mutex_prefork(&prof_dump_seq_mtx);
2211-
for (i = 0; i < PROF_NCTX_LOCKS; i++)
2212-
malloc_mutex_prefork(&gctx_locks[i]);
2209+
malloc_mutex_prefork(&tdatas_mtx);
22132210
for (i = 0; i < PROF_NTDATA_LOCKS; i++)
22142211
malloc_mutex_prefork(&tdata_locks[i]);
2212+
for (i = 0; i < PROF_NCTX_LOCKS; i++)
2213+
malloc_mutex_prefork(&gctx_locks[i]);
2214+
}
2215+
}
2216+
2217+
void
2218+
prof_prefork1(void)
2219+
{
2220+
2221+
if (opt_prof) {
2222+
malloc_mutex_prefork(&prof_active_mtx);
2223+
malloc_mutex_prefork(&prof_dump_seq_mtx);
2224+
malloc_mutex_prefork(&prof_gdump_mtx);
2225+
malloc_mutex_prefork(&next_thr_uid_mtx);
2226+
malloc_mutex_prefork(&prof_thread_active_init_mtx);
22152227
}
22162228
}
22172229

@@ -2222,14 +2234,18 @@ prof_postfork_parent(void)
22222234
if (opt_prof) {
22232235
unsigned i;
22242236

2225-
for (i = 0; i < PROF_NTDATA_LOCKS; i++)
2226-
malloc_mutex_postfork_parent(&tdata_locks[i]);
2237+
malloc_mutex_postfork_parent(&prof_thread_active_init_mtx);
2238+
malloc_mutex_postfork_parent(&next_thr_uid_mtx);
2239+
malloc_mutex_postfork_parent(&prof_gdump_mtx);
2240+
malloc_mutex_postfork_parent(&prof_dump_seq_mtx);
2241+
malloc_mutex_postfork_parent(&prof_active_mtx);
22272242
for (i = 0; i < PROF_NCTX_LOCKS; i++)
22282243
malloc_mutex_postfork_parent(&gctx_locks[i]);
2229-
malloc_mutex_postfork_parent(&prof_dump_seq_mtx);
2230-
malloc_mutex_postfork_parent(&next_thr_uid_mtx);
2231-
malloc_mutex_postfork_parent(&bt2gctx_mtx);
2244+
for (i = 0; i < PROF_NTDATA_LOCKS; i++)
2245+
malloc_mutex_postfork_parent(&tdata_locks[i]);
22322246
malloc_mutex_postfork_parent(&tdatas_mtx);
2247+
malloc_mutex_postfork_parent(&bt2gctx_mtx);
2248+
malloc_mutex_postfork_parent(&prof_dump_mtx);
22332249
}
22342250
}
22352251

@@ -2240,14 +2256,18 @@ prof_postfork_child(void)
22402256
if (opt_prof) {
22412257
unsigned i;
22422258

2243-
for (i = 0; i < PROF_NTDATA_LOCKS; i++)
2244-
malloc_mutex_postfork_child(&tdata_locks[i]);
2259+
malloc_mutex_postfork_child(&prof_thread_active_init_mtx);
2260+
malloc_mutex_postfork_child(&next_thr_uid_mtx);
2261+
malloc_mutex_postfork_child(&prof_gdump_mtx);
2262+
malloc_mutex_postfork_child(&prof_dump_seq_mtx);
2263+
malloc_mutex_postfork_child(&prof_active_mtx);
22452264
for (i = 0; i < PROF_NCTX_LOCKS; i++)
22462265
malloc_mutex_postfork_child(&gctx_locks[i]);
2247-
malloc_mutex_postfork_child(&prof_dump_seq_mtx);
2248-
malloc_mutex_postfork_child(&next_thr_uid_mtx);
2249-
malloc_mutex_postfork_child(&bt2gctx_mtx);
2266+
for (i = 0; i < PROF_NTDATA_LOCKS; i++)
2267+
malloc_mutex_postfork_child(&tdata_locks[i]);
22502268
malloc_mutex_postfork_child(&tdatas_mtx);
2269+
malloc_mutex_postfork_child(&bt2gctx_mtx);
2270+
malloc_mutex_postfork_child(&prof_dump_mtx);
22512271
}
22522272
}
22532273

test/unit/fork.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#include "test/jemalloc_test.h"
2+
3+
#include <sys/wait.h>
4+
5+
TEST_BEGIN(test_fork)
6+
{
7+
void *p;
8+
pid_t pid;
9+
10+
p = malloc(1);
11+
assert_ptr_not_null(p, "Unexpected malloc() failure");
12+
13+
pid = fork();
14+
if (pid == -1) {
15+
/* Error. */
16+
test_fail("Unexpected fork() failure");
17+
} else if (pid == 0) {
18+
/* Child. */
19+
exit(0);
20+
} else {
21+
int status;
22+
23+
/* Parent. */
24+
free(p);
25+
do {
26+
if (waitpid(pid, &status, 0) == -1)
27+
test_fail("Unexpected waitpid() failure");
28+
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
29+
}
30+
}
31+
TEST_END
32+
33+
int
34+
main(void)
35+
{
36+
37+
return (test(
38+
test_fork));
39+
}

0 commit comments

Comments
 (0)