| 844 | } |
| 845 | |
| 846 | static void |
| 847 | prof_gctx_try_destroy(tsd_t *tsd, prof_tdata_t *tdata_self, prof_gctx_t *gctx, |
| 848 | prof_tdata_t *tdata) { |
| 849 | cassert(config_prof); |
| 850 | |
| 851 | /* |
| 852 | * Check that gctx is still unused by any thread cache before destroying |
| 853 | * it. prof_lookup() increments gctx->nlimbo in order to avoid a race |
| 854 | * condition with this function, as does prof_tctx_destroy() in order to |
| 855 | * avoid a race between the main body of prof_tctx_destroy() and entry |
| 856 | * into this function. |
| 857 | */ |
| 858 | prof_enter(tsd, tdata_self); |
| 859 | malloc_mutex_lock(tsd_tsdn(tsd), gctx->lock); |
| 860 | assert(gctx->nlimbo != 0); |
| 861 | if (tctx_tree_empty(&gctx->tctxs) && gctx->nlimbo == 1) { |
| 862 | /* Remove gctx from bt2gctx. */ |
| 863 | if (ckh_remove(tsd, &bt2gctx, &gctx->bt, NULL, NULL)) { |
| 864 | not_reached(); |
| 865 | } |
| 866 | prof_leave(tsd, tdata_self); |
| 867 | /* Destroy gctx. */ |
| 868 | malloc_mutex_unlock(tsd_tsdn(tsd), gctx->lock); |
| 869 | idalloctm(tsd_tsdn(tsd), gctx, NULL, NULL, true, true); |
| 870 | } else { |
| 871 | /* |
| 872 | * Compensate for increment in prof_tctx_destroy() or |
| 873 | * prof_lookup(). |
| 874 | */ |
| 875 | gctx->nlimbo--; |
| 876 | malloc_mutex_unlock(tsd_tsdn(tsd), gctx->lock); |
| 877 | prof_leave(tsd, tdata_self); |
| 878 | } |
| 879 | } |
| 880 | |
| 881 | static bool |
| 882 | prof_tctx_should_destroy(tsdn_t *tsdn, prof_tctx_t *tctx) { |
no test coverage detected