| 370 | } |
| 371 | |
| 372 | void |
| 373 | tsd_cleanup(void *arg) { |
| 374 | tsd_t *tsd = (tsd_t *)arg; |
| 375 | |
| 376 | switch (tsd_state_get(tsd)) { |
| 377 | case tsd_state_uninitialized: |
| 378 | /* Do nothing. */ |
| 379 | break; |
| 380 | case tsd_state_minimal_initialized: |
| 381 | /* This implies the thread only did free() in its life time. */ |
| 382 | /* Fall through. */ |
| 383 | case tsd_state_reincarnated: |
| 384 | /* |
| 385 | * Reincarnated means another destructor deallocated memory |
| 386 | * after the destructor was called. Cleanup isn't required but |
| 387 | * is still called for testing and completeness. |
| 388 | */ |
| 389 | assert_tsd_data_cleanup_done(tsd); |
| 390 | /* Fall through. */ |
| 391 | case tsd_state_nominal: |
| 392 | case tsd_state_nominal_slow: |
| 393 | tsd_do_data_cleanup(tsd); |
| 394 | tsd_state_set(tsd, tsd_state_purgatory); |
| 395 | tsd_set(tsd); |
| 396 | break; |
| 397 | case tsd_state_purgatory: |
| 398 | /* |
| 399 | * The previous time this destructor was called, we set the |
| 400 | * state to tsd_state_purgatory so that other destructors |
| 401 | * wouldn't cause re-creation of the tsd. This time, do |
| 402 | * nothing, and do not request another callback. |
| 403 | */ |
| 404 | break; |
| 405 | default: |
| 406 | not_reached(); |
| 407 | } |
| 408 | #ifdef JEMALLOC_JET |
| 409 | test_callback_t test_callback = *tsd_test_callbackp_get_unsafe(tsd); |
| 410 | int *data = tsd_test_datap_get_unsafe(tsd); |
| 411 | if (test_callback != NULL) { |
| 412 | test_callback(data); |
| 413 | } |
| 414 | #endif |
| 415 | } |
| 416 | |
| 417 | tsd_t * |
| 418 | malloc_tsd_boot0(void) { |