blob: 31c36a2430e48da674b6ad09ce97e768ea601dcd [file] [log] [blame]
Jason Evansb2c0d632016-04-13 23:36:15 -07001#define JEMALLOC_WITNESS_C_
2#include "jemalloc/internal/jemalloc_internal.h"
3
4void
5witness_init(witness_t *witness, const char *name, witness_rank_t rank,
6 witness_comp_t *comp)
7{
8
9 witness->name = name;
10 witness->rank = rank;
11 witness->comp = comp;
12}
13
14#ifdef JEMALLOC_JET
15#undef witness_lock_error
16#define witness_lock_error JEMALLOC_N(witness_lock_error_impl)
17#endif
18static void
19witness_lock_error(const witness_list_t *witnesses, const witness_t *witness)
20{
21 witness_t *w;
22
23 malloc_printf("<jemalloc>: Lock rank order reversal:");
24 ql_foreach(w, witnesses, link) {
25 malloc_printf(" %s(%u)", w->name, w->rank);
26 }
27 malloc_printf(" %s(%u)\n", witness->name, witness->rank);
28 abort();
29}
30#ifdef JEMALLOC_JET
31#undef witness_lock_error
32#define witness_lock_error JEMALLOC_N(witness_lock_error)
33witness_lock_error_t *witness_lock_error = JEMALLOC_N(witness_lock_error_impl);
34#endif
35
36void
37witness_lock(tsd_t *tsd, witness_t *witness)
38{
39 witness_list_t *witnesses;
40 witness_t *w;
41
Jason Evansb2c0d632016-04-13 23:36:15 -070042 if (tsd == NULL)
43 return;
44 if (witness->rank == WITNESS_RANK_OMIT)
45 return;
46
47 witness_assert_not_owner(tsd, witness);
48
49 witnesses = tsd_witnessesp_get(tsd);
50 w = ql_last(witnesses, link);
Jason Evans174c0c32016-04-25 23:14:40 -070051 if (w == NULL) {
52 /* No other locks; do nothing. */
53 } else if (tsd_witness_fork_get(tsd) && w->rank <= witness->rank) {
54 /* Forking, and relaxed ranking satisfied. */
55 } else if (w->rank > witness->rank) {
56 /* Not forking, rank order reversal. */
Jason Evansb2c0d632016-04-13 23:36:15 -070057 witness_lock_error(witnesses, witness);
Jason Evans174c0c32016-04-25 23:14:40 -070058 } else if (w->rank == witness->rank && (w->comp == NULL || w->comp !=
59 witness->comp || w->comp(w, witness) > 0)) {
60 /*
61 * Missing/incompatible comparison function, or comparison
62 * function indicates rank order reversal.
63 */
64 witness_lock_error(witnesses, witness);
65 }
Jason Evansb2c0d632016-04-13 23:36:15 -070066
67 ql_elm_new(witness, link);
68 ql_tail_insert(witnesses, witness, link);
69}
70
71void
72witness_unlock(tsd_t *tsd, witness_t *witness)
73{
74 witness_list_t *witnesses;
75
Jason Evansb2c0d632016-04-13 23:36:15 -070076 if (tsd == NULL)
77 return;
78 if (witness->rank == WITNESS_RANK_OMIT)
79 return;
80
81 witness_assert_owner(tsd, witness);
82
83 witnesses = tsd_witnessesp_get(tsd);
84 ql_remove(witnesses, witness, link);
85}
86
87#ifdef JEMALLOC_JET
88#undef witness_owner_error
89#define witness_owner_error JEMALLOC_N(witness_owner_error_impl)
90#endif
91static void
92witness_owner_error(const witness_t *witness)
93{
94
95 malloc_printf("<jemalloc>: Should own %s(%u)\n", witness->name,
96 witness->rank);
97 abort();
98}
99#ifdef JEMALLOC_JET
100#undef witness_owner_error
101#define witness_owner_error JEMALLOC_N(witness_owner_error)
102witness_owner_error_t *witness_owner_error =
103 JEMALLOC_N(witness_owner_error_impl);
104#endif
105
106void
107witness_assert_owner(tsd_t *tsd, const witness_t *witness)
108{
109 witness_list_t *witnesses;
110 witness_t *w;
111
Jason Evansb2c0d632016-04-13 23:36:15 -0700112 if (tsd == NULL)
113 return;
114 if (witness->rank == WITNESS_RANK_OMIT)
115 return;
116
117 witnesses = tsd_witnessesp_get(tsd);
118 ql_foreach(w, witnesses, link) {
119 if (w == witness)
120 return;
121 }
122 witness_owner_error(witness);
123}
124
125#ifdef JEMALLOC_JET
126#undef witness_not_owner_error
127#define witness_not_owner_error JEMALLOC_N(witness_not_owner_error_impl)
128#endif
129static void
130witness_not_owner_error(const witness_t *witness)
131{
132
133 malloc_printf("<jemalloc>: Should not own %s(%u)\n", witness->name,
134 witness->rank);
135 abort();
136}
137#ifdef JEMALLOC_JET
138#undef witness_not_owner_error
139#define witness_not_owner_error JEMALLOC_N(witness_not_owner_error)
140witness_not_owner_error_t *witness_not_owner_error =
141 JEMALLOC_N(witness_not_owner_error_impl);
142#endif
143
144void
145witness_assert_not_owner(tsd_t *tsd, const witness_t *witness)
146{
147 witness_list_t *witnesses;
148 witness_t *w;
149
Jason Evansb2c0d632016-04-13 23:36:15 -0700150 if (tsd == NULL)
151 return;
152 if (witness->rank == WITNESS_RANK_OMIT)
153 return;
154
155 witnesses = tsd_witnessesp_get(tsd);
156 ql_foreach(w, witnesses, link) {
157 if (w == witness)
158 witness_not_owner_error(witness);
159 }
160}
161
162#ifdef JEMALLOC_JET
163#undef witness_lockless_error
164#define witness_lockless_error JEMALLOC_N(witness_lockless_error_impl)
165#endif
166static void
167witness_lockless_error(const witness_list_t *witnesses)
168{
169 witness_t *w;
170
171 malloc_printf("<jemalloc>: Should not own any locks:");
172 ql_foreach(w, witnesses, link) {
173 malloc_printf(" %s(%u)", w->name, w->rank);
174 }
175 malloc_printf("\n");
176 abort();
177}
178#ifdef JEMALLOC_JET
179#undef witness_lockless_error
180#define witness_lockless_error JEMALLOC_N(witness_lockless_error)
181witness_lockless_error_t *witness_lockless_error =
182 JEMALLOC_N(witness_lockless_error_impl);
183#endif
184
185void
186witness_assert_lockless(tsd_t *tsd)
187{
188 witness_list_t *witnesses;
189 witness_t *w;
190
Jason Evansb2c0d632016-04-13 23:36:15 -0700191 if (tsd == NULL)
192 return;
193
194 witnesses = tsd_witnessesp_get(tsd);
195 w = ql_last(witnesses, link);
196 if (w != NULL) {
197 witness_lockless_error(witnesses);
198 }
199}
200
201void
202witnesses_cleanup(tsd_t *tsd)
203{
204
205 witness_assert_lockless(tsd);
206
207 /* Do nothing. */
208}
Jason Evans174c0c32016-04-25 23:14:40 -0700209
210void
211witness_fork_cleanup(tsd_t *tsd)
212{
213
214 /* Do nothing. */
215}
216
217void
218witness_prefork(tsd_t *tsd)
219{
220
221 tsd_witness_fork_set(tsd, true);
222}
223
224void
Jason Evans108c4a12016-04-26 10:47:22 -0700225witness_postfork_parent(tsd_t *tsd)
Jason Evans174c0c32016-04-25 23:14:40 -0700226{
227
228 tsd_witness_fork_set(tsd, false);
229}
Jason Evans108c4a12016-04-26 10:47:22 -0700230
231void
232witness_postfork_child(tsd_t *tsd)
233{
234#ifndef JEMALLOC_MUTEX_INIT_CB
235 witness_list_t *witnesses;
236
237 witnesses = tsd_witnessesp_get(tsd);
238 ql_new(witnesses);
239#endif
240 tsd_witness_fork_set(tsd, false);
241}