1 | #include "jemalloc/internal/jemalloc_preamble.h" |
2 | #include "jemalloc/internal/jemalloc_internal_includes.h" |
3 | |
4 | #include "jemalloc/internal/assert.h" |
5 | #include "jemalloc/internal/malloc_io.h" |
6 | |
7 | void |
8 | witness_init(witness_t *witness, const char *name, witness_rank_t rank, |
9 | witness_comp_t *comp, void *opaque) { |
10 | witness->name = name; |
11 | witness->rank = rank; |
12 | witness->comp = comp; |
13 | witness->opaque = opaque; |
14 | } |
15 | |
16 | static void |
17 | witness_print_witness(witness_t *w, unsigned n) { |
18 | assert(n > 0); |
19 | if (n == 1) { |
20 | malloc_printf(" %s(%u)" , w->name, w->rank); |
21 | } else { |
22 | malloc_printf(" %s(%u)X%u" , w->name, w->rank, n); |
23 | } |
24 | } |
25 | |
26 | static void |
27 | witness_print_witnesses(const witness_list_t *witnesses) { |
28 | witness_t *w, *last = NULL; |
29 | unsigned n = 0; |
30 | ql_foreach(w, witnesses, link) { |
31 | if (last != NULL && w->rank > last->rank) { |
32 | assert(w->name != last->name); |
33 | witness_print_witness(last, n); |
34 | n = 0; |
35 | } else if (last != NULL) { |
36 | assert(w->rank == last->rank); |
37 | assert(w->name == last->name); |
38 | } |
39 | last = w; |
40 | ++n; |
41 | } |
42 | if (last != NULL) { |
43 | witness_print_witness(last, n); |
44 | } |
45 | } |
46 | |
47 | static void |
48 | witness_lock_error_impl(const witness_list_t *witnesses, |
49 | const witness_t *witness) { |
50 | malloc_printf("<jemalloc>: Lock rank order reversal:" ); |
51 | witness_print_witnesses(witnesses); |
52 | malloc_printf(" %s(%u)\n" , witness->name, witness->rank); |
53 | abort(); |
54 | } |
55 | witness_lock_error_t *JET_MUTABLE witness_lock_error = witness_lock_error_impl; |
56 | |
57 | static void |
58 | witness_owner_error_impl(const witness_t *witness) { |
59 | malloc_printf("<jemalloc>: Should own %s(%u)\n" , witness->name, |
60 | witness->rank); |
61 | abort(); |
62 | } |
63 | witness_owner_error_t *JET_MUTABLE witness_owner_error = |
64 | witness_owner_error_impl; |
65 | |
66 | static void |
67 | witness_not_owner_error_impl(const witness_t *witness) { |
68 | malloc_printf("<jemalloc>: Should not own %s(%u)\n" , witness->name, |
69 | witness->rank); |
70 | abort(); |
71 | } |
72 | witness_not_owner_error_t *JET_MUTABLE witness_not_owner_error = |
73 | witness_not_owner_error_impl; |
74 | |
75 | static void |
76 | witness_depth_error_impl(const witness_list_t *witnesses, |
77 | witness_rank_t rank_inclusive, unsigned depth) { |
78 | malloc_printf("<jemalloc>: Should own %u lock%s of rank >= %u:" , depth, |
79 | (depth != 1) ? "s" : "" , rank_inclusive); |
80 | witness_print_witnesses(witnesses); |
81 | malloc_printf("\n" ); |
82 | abort(); |
83 | } |
84 | witness_depth_error_t *JET_MUTABLE witness_depth_error = |
85 | witness_depth_error_impl; |
86 | |
87 | void |
88 | witnesses_cleanup(witness_tsd_t *witness_tsd) { |
89 | witness_assert_lockless(witness_tsd_tsdn(witness_tsd)); |
90 | |
91 | /* Do nothing. */ |
92 | } |
93 | |
94 | void |
95 | witness_prefork(witness_tsd_t *witness_tsd) { |
96 | if (!config_debug) { |
97 | return; |
98 | } |
99 | witness_tsd->forking = true; |
100 | } |
101 | |
102 | void |
103 | witness_postfork_parent(witness_tsd_t *witness_tsd) { |
104 | if (!config_debug) { |
105 | return; |
106 | } |
107 | witness_tsd->forking = false; |
108 | } |
109 | |
110 | void |
111 | witness_postfork_child(witness_tsd_t *witness_tsd) { |
112 | if (!config_debug) { |
113 | return; |
114 | } |
115 | #ifndef JEMALLOC_MUTEX_INIT_CB |
116 | witness_list_t *witnesses; |
117 | |
118 | witnesses = &witness_tsd->witnesses; |
119 | ql_new(witnesses); |
120 | #endif |
121 | witness_tsd->forking = false; |
122 | } |
123 | |