| 543 | } |
| 544 | |
| 545 | static void |
| 546 | tcache_destroy(tsd_t *tsd, tcache_t *tcache, bool tsd_tcache) { |
| 547 | tcache_flush_cache(tsd, tcache); |
| 548 | arena_t *arena = tcache->arena; |
| 549 | tcache_arena_dissociate(tsd_tsdn(tsd), tcache); |
| 550 | |
| 551 | if (tsd_tcache) { |
| 552 | /* Release the avail array for the TSD embedded auto tcache. */ |
| 553 | void *avail_array = |
| 554 | (void *)((uintptr_t)tcache_small_bin_get(tcache, 0)->avail - |
| 555 | (uintptr_t)tcache_bin_info[0].ncached_max * sizeof(void *)); |
| 556 | idalloctm(tsd_tsdn(tsd), avail_array, NULL, NULL, true, true); |
| 557 | } else { |
| 558 | /* Release both the tcache struct and avail array. */ |
| 559 | idalloctm(tsd_tsdn(tsd), tcache, NULL, NULL, true, true); |
| 560 | } |
| 561 | |
| 562 | /* |
| 563 | * The deallocation and tcache flush above may not trigger decay since |
| 564 | * we are on the tcache shutdown path (potentially with non-nominal |
| 565 | * tsd). Manually trigger decay to avoid pathological cases. Also |
| 566 | * include arena 0 because the tcache array is allocated from it. |
| 567 | */ |
| 568 | arena_decay(tsd_tsdn(tsd), arena_get(tsd_tsdn(tsd), 0, false), |
| 569 | false, false); |
| 570 | |
| 571 | if (arena_nthreads_get(arena, false) == 0 && |
| 572 | !background_thread_enabled()) { |
| 573 | /* Force purging when no threads assigned to the arena anymore. */ |
| 574 | arena_decay(tsd_tsdn(tsd), arena, false, true); |
| 575 | } else { |
| 576 | arena_decay(tsd_tsdn(tsd), arena, false, false); |
| 577 | } |
| 578 | } |
| 579 | |
| 580 | /* For auto tcache (embedded in TSD) only. */ |
| 581 | void |
no test coverage detected