xref: /freebsd/contrib/jemalloc/src/witness.c (revision c43cad87172039ccf38172129c79755ea79e6102)
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