| 1597 | } |
| 1598 | |
| 1599 | static extent_t * |
| 1600 | extent_try_coalesce_impl(tsdn_t *tsdn, arena_t *arena, |
| 1601 | extent_hooks_t **r_extent_hooks, rtree_ctx_t *rtree_ctx, extents_t *extents, |
| 1602 | extent_t *extent, bool *coalesced, bool growing_retained, |
| 1603 | bool inactive_only) { |
| 1604 | /* |
| 1605 | * We avoid checking / locking inactive neighbors for large size |
| 1606 | * classes, since they are eagerly coalesced on deallocation which can |
| 1607 | * cause lock contention. |
| 1608 | */ |
| 1609 | /* |
| 1610 | * Continue attempting to coalesce until failure, to protect against |
| 1611 | * races with other threads that are thwarted by this one. |
| 1612 | */ |
| 1613 | bool again; |
| 1614 | do { |
| 1615 | again = false; |
| 1616 | |
| 1617 | /* Try to coalesce forward. */ |
| 1618 | extent_t *next = extent_lock_from_addr(tsdn, rtree_ctx, |
| 1619 | extent_past_get(extent), inactive_only); |
| 1620 | if (next != NULL) { |
| 1621 | /* |
| 1622 | * extents->mtx only protects against races for |
| 1623 | * like-state extents, so call extent_can_coalesce() |
| 1624 | * before releasing next's pool lock. |
| 1625 | */ |
| 1626 | bool can_coalesce = extent_can_coalesce(arena, extents, |
| 1627 | extent, next); |
| 1628 | |
| 1629 | extent_unlock(tsdn, next); |
| 1630 | |
| 1631 | if (can_coalesce && !extent_coalesce(tsdn, arena, |
| 1632 | r_extent_hooks, extents, extent, next, true, |
| 1633 | growing_retained)) { |
| 1634 | if (extents->delay_coalesce) { |
| 1635 | /* Do minimal coalescing. */ |
| 1636 | *coalesced = true; |
| 1637 | return extent; |
| 1638 | } |
| 1639 | again = true; |
| 1640 | } |
| 1641 | } |
| 1642 | |
| 1643 | /* Try to coalesce backward. */ |
| 1644 | extent_t *prev = extent_lock_from_addr(tsdn, rtree_ctx, |
| 1645 | extent_before_get(extent), inactive_only); |
| 1646 | if (prev != NULL) { |
| 1647 | bool can_coalesce = extent_can_coalesce(arena, extents, |
| 1648 | extent, prev); |
| 1649 | extent_unlock(tsdn, prev); |
| 1650 | |
| 1651 | if (can_coalesce && !extent_coalesce(tsdn, arena, |
| 1652 | r_extent_hooks, extents, extent, prev, false, |
| 1653 | growing_retained)) { |
| 1654 | extent = prev; |
| 1655 | if (extents->delay_coalesce) { |
| 1656 | /* Do minimal coalescing. */ |
no test coverage detected