Rizin
unix-like reverse engineering framework and cli tools
witness.h
Go to the documentation of this file.
1 /******************************************************************************/
2 #ifdef JEMALLOC_H_TYPES
3 
4 typedef struct witness_s witness_t;
5 typedef unsigned witness_rank_t;
6 typedef ql_head(witness_t) witness_list_t;
7 typedef int witness_comp_t (const witness_t *, const witness_t *);
8 
9 /*
10  * Lock ranks. Witnesses with rank WITNESS_RANK_OMIT are completely ignored by
11  * the witness machinery.
12  */
13 #define WITNESS_RANK_OMIT 0U
14 
15 #define WITNESS_RANK_MIN 1U
16 
17 #define WITNESS_RANK_INIT 1U
18 #define WITNESS_RANK_CTL 1U
19 #define WITNESS_RANK_TCACHES 2U
20 #define WITNESS_RANK_ARENAS 3U
21 
22 #define WITNESS_RANK_PROF_DUMP 4U
23 #define WITNESS_RANK_PROF_BT2GCTX 5U
24 #define WITNESS_RANK_PROF_TDATAS 6U
25 #define WITNESS_RANK_PROF_TDATA 7U
26 #define WITNESS_RANK_PROF_GCTX 8U
27 
28 /*
29  * Used as an argument to witness_assert_depth_to_rank() in order to validate
30  * depth excluding non-core locks with lower ranks. Since the rank argument to
31  * witness_assert_depth_to_rank() is inclusive rather than exclusive, this
32  * definition can have the same value as the minimally ranked core lock.
33  */
34 #define WITNESS_RANK_CORE 9U
35 
36 #define WITNESS_RANK_ARENA 9U
37 #define WITNESS_RANK_ARENA_CHUNKS 10U
38 #define WITNESS_RANK_ARENA_NODE_CACHE 11U
39 
40 #define WITNESS_RANK_BASE 12U
41 
42 #define WITNESS_RANK_LEAF 0xffffffffU
43 #define WITNESS_RANK_ARENA_BIN WITNESS_RANK_LEAF
44 #define WITNESS_RANK_ARENA_HUGE WITNESS_RANK_LEAF
45 #define WITNESS_RANK_DSS WITNESS_RANK_LEAF
46 #define WITNESS_RANK_PROF_ACTIVE WITNESS_RANK_LEAF
47 #define WITNESS_RANK_PROF_DUMP_SEQ WITNESS_RANK_LEAF
48 #define WITNESS_RANK_PROF_GDUMP WITNESS_RANK_LEAF
49 #define WITNESS_RANK_PROF_NEXT_THR_UID WITNESS_RANK_LEAF
50 #define WITNESS_RANK_PROF_THREAD_ACTIVE_INIT WITNESS_RANK_LEAF
51 
52 #define WITNESS_INITIALIZER(rank) {"initializer", rank, NULL, {NULL, NULL}}
53 
54 #endif /* JEMALLOC_H_TYPES */
55 /******************************************************************************/
56 #ifdef JEMALLOC_H_STRUCTS
57 
58 struct witness_s {
59  /* Name, used for printing lock order reversal messages. */
60  const char *name;
61 
62  /*
63  * Witness rank, where 0 is lowest and UINT_MAX is highest. Witnesses
64  * must be acquired in order of increasing rank.
65  */
66  witness_rank_t rank;
67 
68  /*
69  * If two witnesses are of equal rank and they have the samp comp
70  * function pointer, it is called as a last attempt to differentiate
71  * between witnesses of equal rank.
72  */
73  witness_comp_t *comp;
74 
75  /* Linkage for thread's currently owned locks. */
76  ql_elm(witness_t) link;
77 };
78 
79 #endif /* JEMALLOC_H_STRUCTS */
80 /******************************************************************************/
81 #ifdef JEMALLOC_H_EXTERNS
82 
83 void witness_init(witness_t *witness, const char *name, witness_rank_t rank,
84  witness_comp_t *comp);
85 #ifdef JEMALLOC_JET
86 typedef void (witness_lock_error_t)(const witness_list_t *, const witness_t *);
87 extern witness_lock_error_t *witness_lock_error;
88 #else
89 void witness_lock_error(const witness_list_t *witnesses,
90  const witness_t *witness);
91 #endif
92 #ifdef JEMALLOC_JET
93 typedef void (witness_owner_error_t)(const witness_t *);
94 extern witness_owner_error_t *witness_owner_error;
95 #else
96 void witness_owner_error(const witness_t *witness);
97 #endif
98 #ifdef JEMALLOC_JET
99 typedef void (witness_not_owner_error_t)(const witness_t *);
100 extern witness_not_owner_error_t *witness_not_owner_error;
101 #else
102 void witness_not_owner_error(const witness_t *witness);
103 #endif
104 #ifdef JEMALLOC_JET
105 typedef void (witness_depth_error_t)(const witness_list_t *,
106  witness_rank_t rank_inclusive, unsigned depth);
107 extern witness_depth_error_t *witness_depth_error;
108 #else
109 void witness_depth_error(const witness_list_t *witnesses,
110  witness_rank_t rank_inclusive, unsigned depth);
111 #endif
112 
113 void witnesses_cleanup(tsd_t *tsd);
114 void witness_fork_cleanup(tsd_t *tsd);
115 void witness_prefork(tsd_t *tsd);
116 void witness_postfork_parent(tsd_t *tsd);
117 void witness_postfork_child(tsd_t *tsd);
118 
119 #endif /* JEMALLOC_H_EXTERNS */
120 /******************************************************************************/
121 #ifdef JEMALLOC_H_INLINES
122 
123 #ifndef JEMALLOC_ENABLE_INLINE
124 bool witness_owner(tsd_t *tsd, const witness_t *witness);
125 void witness_assert_owner(tsdn_t *tsdn, const witness_t *witness);
126 void witness_assert_not_owner(tsdn_t *tsdn, const witness_t *witness);
127 void witness_assert_depth_to_rank(tsdn_t *tsdn, witness_rank_t rank_inclusive,
128  unsigned depth);
129 void witness_assert_depth(tsdn_t *tsdn, unsigned depth);
130 void witness_assert_lockless(tsdn_t *tsdn);
131 void witness_lock(tsdn_t *tsdn, witness_t *witness);
132 void witness_unlock(tsdn_t *tsdn, witness_t *witness);
133 #endif
134 
135 #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_MUTEX_C_))
136 JEMALLOC_INLINE bool
137 witness_owner(tsd_t *tsd, const witness_t *witness)
138 {
139  witness_list_t *witnesses;
140  witness_t *w;
141 
142  cassert(config_debug);
143 
144  witnesses = tsd_witnessesp_get(tsd);
145  ql_foreach(w, witnesses, link) {
146  if (w == witness)
147  return (true);
148  }
149 
150  return (false);
151 }
152 
153 JEMALLOC_INLINE void
154 witness_assert_owner(tsdn_t *tsdn, const witness_t *witness)
155 {
156  tsd_t *tsd;
157 
158  if (!config_debug)
159  return;
160 
161  if (tsdn_null(tsdn))
162  return;
163  tsd = tsdn_tsd(tsdn);
164  if (witness->rank == WITNESS_RANK_OMIT)
165  return;
166 
167  if (witness_owner(tsd, witness))
168  return;
169  witness_owner_error(witness);
170 }
171 
172 JEMALLOC_INLINE void
173 witness_assert_not_owner(tsdn_t *tsdn, const witness_t *witness)
174 {
175  tsd_t *tsd;
176  witness_list_t *witnesses;
177  witness_t *w;
178 
179  if (!config_debug)
180  return;
181 
182  if (tsdn_null(tsdn))
183  return;
184  tsd = tsdn_tsd(tsdn);
185  if (witness->rank == WITNESS_RANK_OMIT)
186  return;
187 
188  witnesses = tsd_witnessesp_get(tsd);
189  ql_foreach(w, witnesses, link) {
190  if (w == witness)
191  witness_not_owner_error(witness);
192  }
193 }
194 
195 JEMALLOC_INLINE void
196 witness_assert_depth_to_rank(tsdn_t *tsdn, witness_rank_t rank_inclusive,
197  unsigned depth) {
198  tsd_t *tsd;
199  unsigned d;
200  witness_list_t *witnesses;
201  witness_t *w;
202 
203  if (!config_debug)
204  return;
205 
206  if (tsdn_null(tsdn))
207  return;
208  tsd = tsdn_tsd(tsdn);
209 
210  d = 0;
211  witnesses = tsd_witnessesp_get(tsd);
212  w = ql_last(witnesses, link);
213  if (w != NULL) {
214  ql_reverse_foreach(w, witnesses, link) {
215  if (w->rank < rank_inclusive) {
216  break;
217  }
218  d++;
219  }
220  }
221  if (d != depth)
222  witness_depth_error(witnesses, rank_inclusive, depth);
223 }
224 
225 JEMALLOC_INLINE void
226 witness_assert_depth(tsdn_t *tsdn, unsigned depth) {
227  witness_assert_depth_to_rank(tsdn, WITNESS_RANK_MIN, depth);
228 }
229 
230 JEMALLOC_INLINE void
231 witness_assert_lockless(tsdn_t *tsdn) {
232  witness_assert_depth(tsdn, 0);
233 }
234 
235 JEMALLOC_INLINE void
236 witness_lock(tsdn_t *tsdn, witness_t *witness)
237 {
238  tsd_t *tsd;
239  witness_list_t *witnesses;
240  witness_t *w;
241 
242  if (!config_debug)
243  return;
244 
245  if (tsdn_null(tsdn))
246  return;
247  tsd = tsdn_tsd(tsdn);
248  if (witness->rank == WITNESS_RANK_OMIT)
249  return;
250 
251  witness_assert_not_owner(tsdn, witness);
252 
253  witnesses = tsd_witnessesp_get(tsd);
254  w = ql_last(witnesses, link);
255  if (w == NULL) {
256  /* No other locks; do nothing. */
257  } else if (tsd_witness_fork_get(tsd) && w->rank <= witness->rank) {
258  /* Forking, and relaxed ranking satisfied. */
259  } else if (w->rank > witness->rank) {
260  /* Not forking, rank order reversal. */
261  witness_lock_error(witnesses, witness);
262  } else if (w->rank == witness->rank && (w->comp == NULL || w->comp !=
263  witness->comp || w->comp(w, witness) > 0)) {
264  /*
265  * Missing/incompatible comparison function, or comparison
266  * function indicates rank order reversal.
267  */
268  witness_lock_error(witnesses, witness);
269  }
270 
271  ql_elm_new(witness, link);
272  ql_tail_insert(witnesses, witness, link);
273 }
274 
275 JEMALLOC_INLINE void
276 witness_unlock(tsdn_t *tsdn, witness_t *witness)
277 {
278  tsd_t *tsd;
279  witness_list_t *witnesses;
280 
281  if (!config_debug)
282  return;
283 
284  if (tsdn_null(tsdn))
285  return;
286  tsd = tsdn_tsd(tsdn);
287  if (witness->rank == WITNESS_RANK_OMIT)
288  return;
289 
290  /*
291  * Check whether owner before removal, rather than relying on
292  * witness_assert_owner() to abort, so that unit tests can test this
293  * function's failure mode without causing undefined behavior.
294  */
295  if (witness_owner(tsd, witness)) {
296  witnesses = tsd_witnessesp_get(tsd);
297  ql_remove(witnesses, witness, link);
298  } else
299  witness_assert_owner(tsdn, witness);
300 }
301 #endif
302 
303 #endif /* JEMALLOC_H_INLINES */
304 /******************************************************************************/
#define NULL
Definition: cris-opc.c:27
#define w
Definition: crypto_rc6.c:13
static static fork const void static count static fd link
Definition: sflib.h:33
static const bool config_debug
#define JEMALLOC_INLINE
const char * name
Definition: op.c:541
#define witness_assert_not_owner
#define witness_assert_depth
#define witness_not_owner_error
#define witness_prefork
#define witness_lock
#define witness_fork_cleanup
#define tsdn_null
#define witness_assert_lockless
#define witness_assert_depth_to_rank
#define witness_unlock
#define witness_postfork_parent
#define witness_owner_error
#define witness_lock_error
#define tsd_witnessesp_get
#define tsd_witness_fork_get
#define witness_owner
#define witness_init
#define witness_assert_owner
#define tsdn_tsd
#define witnesses_cleanup
#define witness_depth_error
#define witness_postfork_child
#define ql_elm(a_type)
Definition: ql.h:9
#define ql_remove(a_head, a_elm, a_field)
Definition: ql.h:56
#define ql_reverse_foreach(a_var, a_head, a_field)
Definition: ql.h:80
#define ql_elm_new(a_elm, a_field)
Definition: ql.h:16
#define ql_tail_insert(a_head, a_elm, a_field)
Definition: ql.h:49
#define ql_last(a_head, a_field)
Definition: ql.h:20
#define ql_foreach(a_var, a_head, a_field)
Definition: ql.h:77
#define ql_head(a_type)
Definition: ql.h:2
#define d(i)
Definition: sha256.c:44
Definition: z80asm.h:102