| 576 | } |
| 577 | |
| 578 | static void |
| 579 | prof_gctx_try_destroy(tsd_t *tsd, prof_tdata_t *tdata_self, prof_gctx_t *gctx, |
| 580 | prof_tdata_t *tdata) { |
| 581 | cassert(config_prof); |
| 582 | |
| 583 | /* |
| 584 | * Check that gctx is still unused by any thread cache before destroying |
| 585 | * it. prof_lookup() increments gctx->nlimbo in order to avoid a race |
| 586 | * condition with this function, as does prof_tctx_destroy() in order to |
| 587 | * avoid a race between the main body of prof_tctx_destroy() and entry |
| 588 | * into this function. |
| 589 | */ |
| 590 | prof_enter(tsd, tdata_self); |
| 591 | malloc_mutex_lock(tsd_tsdn(tsd), gctx->lock); |
| 592 | assert(gctx->nlimbo != 0); |
| 593 | if (tctx_tree_empty(&gctx->tctxs) && gctx->nlimbo == 1) { |
| 594 | /* Remove gctx from bt2gctx. */ |
| 595 | if (ckh_remove(tsd, &bt2gctx, &gctx->bt, NULL, NULL)) { |
| 596 | not_reached(); |
| 597 | } |
| 598 | prof_leave(tsd, tdata_self); |
| 599 | /* Destroy gctx. */ |
| 600 | malloc_mutex_unlock(tsd_tsdn(tsd), gctx->lock); |
| 601 | idalloctm(tsd_tsdn(tsd), gctx, NULL, NULL, true, true); |
| 602 | } else { |
| 603 | /* |
| 604 | * Compensate for increment in prof_tctx_destroy() or |
| 605 | * prof_lookup(). |
| 606 | */ |
| 607 | gctx->nlimbo--; |
| 608 | malloc_mutex_unlock(tsd_tsdn(tsd), gctx->lock); |
| 609 | prof_leave(tsd, tdata_self); |
| 610 | } |
| 611 | } |
| 612 | |
| 613 | static bool |
| 614 | prof_tctx_should_destroy(tsdn_t *tsdn, prof_tctx_t *tctx) { |
no test coverage detected