| 1093 | } |
| 1094 | |
| 1095 | void |
| 1096 | arena_reset(tsd_t *tsd, arena_t *arena) { |
| 1097 | /* |
| 1098 | * Locking in this function is unintuitive. The caller guarantees that |
| 1099 | * no concurrent operations are happening in this arena, but there are |
| 1100 | * still reasons that some locking is necessary: |
| 1101 | * |
| 1102 | * - Some of the functions in the transitive closure of calls assume |
| 1103 | * appropriate locks are held, and in some cases these locks are |
| 1104 | * temporarily dropped to avoid lock order reversal or deadlock due to |
| 1105 | * reentry. |
| 1106 | * - mallctl("epoch", ...) may concurrently refresh stats. While |
| 1107 | * strictly speaking this is a "concurrent operation", disallowing |
| 1108 | * stats refreshes would impose an inconvenient burden. |
| 1109 | */ |
| 1110 | |
| 1111 | /* Large allocations. */ |
| 1112 | malloc_mutex_lock(tsd_tsdn(tsd), &arena->large_mtx); |
| 1113 | |
| 1114 | for (extent_t *extent = extent_list_first(&arena->large); extent != |
| 1115 | NULL; extent = extent_list_first(&arena->large)) { |
| 1116 | void *ptr = extent_base_get(extent); |
| 1117 | size_t usize; |
| 1118 | |
| 1119 | malloc_mutex_unlock(tsd_tsdn(tsd), &arena->large_mtx); |
| 1120 | alloc_ctx_t alloc_ctx; |
| 1121 | rtree_ctx_t *rtree_ctx = tsd_rtree_ctx(tsd); |
| 1122 | rtree_szind_slab_read(tsd_tsdn(tsd), &extents_rtree, rtree_ctx, |
| 1123 | (uintptr_t)ptr, true, &alloc_ctx.szind, &alloc_ctx.slab); |
| 1124 | assert(alloc_ctx.szind != SC_NSIZES); |
| 1125 | |
| 1126 | if (config_stats || (config_prof && opt_prof)) { |
| 1127 | usize = sz_index2size(alloc_ctx.szind); |
| 1128 | assert(usize == isalloc(tsd_tsdn(tsd), ptr)); |
| 1129 | } |
| 1130 | /* Remove large allocation from prof sample set. */ |
| 1131 | if (config_prof && opt_prof) { |
| 1132 | prof_free(tsd, ptr, usize, &alloc_ctx); |
| 1133 | } |
| 1134 | large_dalloc(tsd_tsdn(tsd), extent); |
| 1135 | malloc_mutex_lock(tsd_tsdn(tsd), &arena->large_mtx); |
| 1136 | } |
| 1137 | malloc_mutex_unlock(tsd_tsdn(tsd), &arena->large_mtx); |
| 1138 | |
| 1139 | /* Bins. */ |
| 1140 | for (unsigned i = 0; i < SC_NBINS; i++) { |
| 1141 | for (unsigned j = 0; j < bin_infos[i].n_shards; j++) { |
| 1142 | arena_bin_reset(tsd, arena, |
| 1143 | &arena->bins[i].bin_shards[j]); |
| 1144 | } |
| 1145 | } |
| 1146 | |
| 1147 | atomic_store_zu(&arena->nactive, 0, ATOMIC_RELAXED); |
| 1148 | } |
| 1149 | |
| 1150 | static void |
| 1151 | arena_destroy_retained(tsdn_t *tsdn, arena_t *arena) { |
no test coverage detected