@@ -63,6 +63,45 @@ tsd_slow_update(tsd_t *tsd) {
6363 }
6464}
6565
66+ static bool
67+ tsd_data_init (tsd_t * tsd ) {
68+ /*
69+ * We initialize the rtree context first (before the tcache), since the
70+ * tcache initialization depends on it.
71+ */
72+ rtree_ctx_data_init (tsd_rtree_ctxp_get_unsafe (tsd ));
73+
74+ return tsd_tcache_enabled_data_init (tsd );
75+ }
76+
77+ static void
78+ assert_tsd_data_cleanup_done (tsd_t * tsd ) {
79+ assert (!tsd_nominal (tsd ));
80+ assert (* tsd_arenap_get_unsafe (tsd ) == NULL );
81+ assert (* tsd_iarenap_get_unsafe (tsd ) == NULL );
82+ assert (* tsd_arenas_tdata_bypassp_get_unsafe (tsd ) == true);
83+ assert (* tsd_arenas_tdatap_get_unsafe (tsd ) == NULL );
84+ assert (* tsd_tcache_enabledp_get_unsafe (tsd ) == false);
85+ assert (* tsd_prof_tdatap_get_unsafe (tsd ) == NULL );
86+ }
87+
88+ static bool
89+ tsd_data_init_nocleanup (tsd_t * tsd ) {
90+ assert (tsd -> state == tsd_state_reincarnated );
91+ /*
92+ * During reincarnation, there is no guarantee that the cleanup function
93+ * will be called (deallocation may happen after all tsd destructors).
94+ * We set up tsd in a way that no cleanup is needed.
95+ */
96+ rtree_ctx_data_init (tsd_rtree_ctxp_get_unsafe (tsd ));
97+ * tsd_arenas_tdata_bypassp_get (tsd ) = true;
98+ * tsd_tcache_enabledp_get_unsafe (tsd ) = false;
99+ * tsd_reentrancy_levelp_get (tsd ) = 1 ;
100+ assert_tsd_data_cleanup_done (tsd );
101+
102+ return false;
103+ }
104+
66105tsd_t *
67106tsd_fetch_slow (tsd_t * tsd ) {
68107 if (tsd -> state == tsd_state_nominal_slow ) {
@@ -79,7 +118,7 @@ tsd_fetch_slow(tsd_t *tsd) {
79118 } else if (tsd -> state == tsd_state_purgatory ) {
80119 tsd -> state = tsd_state_reincarnated ;
81120 tsd_set (tsd );
82- tsd_data_init (tsd );
121+ tsd_data_init_nocleanup (tsd );
83122 } else {
84123 assert (tsd -> state == tsd_state_reincarnated );
85124 }
@@ -131,21 +170,6 @@ malloc_tsd_cleanup_register(bool (*f)(void)) {
131170 ncleanups ++ ;
132171}
133172
134- bool
135- tsd_data_init (void * arg ) {
136- tsd_t * tsd = (tsd_t * )arg ;
137- /*
138- * We initialize the rtree context first (before the tcache), since the
139- * tcache initialization depends on it.
140- */
141- rtree_ctx_data_init (tsd_rtree_ctxp_get_unsafe (tsd ));
142-
143- if (tsd_tcache_enabled_data_init (tsd )) {
144- return true;
145- }
146- return false;
147- }
148-
149173static void
150174tsd_do_data_cleanup (tsd_t * tsd ) {
151175 prof_tdata_cleanup (tsd );
@@ -164,14 +188,16 @@ tsd_cleanup(void *arg) {
164188 case tsd_state_uninitialized :
165189 /* Do nothing. */
166190 break ;
167- case tsd_state_nominal :
168- case tsd_state_nominal_slow :
169191 case tsd_state_reincarnated :
170192 /*
171193 * Reincarnated means another destructor deallocated memory
172- * after this destructor was called. Reset state to
173- * tsd_state_purgatory and request another callback .
194+ * after the destructor was called. Cleanup isn't required but
195+ * is still called for testing and completeness .
174196 */
197+ assert_tsd_data_cleanup_done (tsd );
198+ /* Fall through. */
199+ case tsd_state_nominal :
200+ case tsd_state_nominal_slow :
175201 tsd_do_data_cleanup (tsd );
176202 tsd -> state = tsd_state_purgatory ;
177203 tsd_set (tsd );
0 commit comments