1*c43cad87SWarner Losh #include "jemalloc/internal/jemalloc_preamble.h" 2*c43cad87SWarner Losh #include "jemalloc/internal/jemalloc_internal_includes.h" 3*c43cad87SWarner Losh 4*c43cad87SWarner Losh #include "jemalloc/internal/psset.h" 5*c43cad87SWarner Losh 6*c43cad87SWarner Losh #include "jemalloc/internal/fb.h" 7*c43cad87SWarner Losh 8*c43cad87SWarner Losh void 9*c43cad87SWarner Losh psset_init(psset_t *psset) { 10*c43cad87SWarner Losh for (unsigned i = 0; i < PSSET_NPSIZES; i++) { 11*c43cad87SWarner Losh hpdata_age_heap_new(&psset->pageslabs[i]); 12*c43cad87SWarner Losh } 13*c43cad87SWarner Losh fb_init(psset->pageslab_bitmap, PSSET_NPSIZES); 14*c43cad87SWarner Losh memset(&psset->merged_stats, 0, sizeof(psset->merged_stats)); 15*c43cad87SWarner Losh memset(&psset->stats, 0, sizeof(psset->stats)); 16*c43cad87SWarner Losh hpdata_empty_list_init(&psset->empty); 17*c43cad87SWarner Losh for (int i = 0; i < PSSET_NPURGE_LISTS; i++) { 18*c43cad87SWarner Losh hpdata_purge_list_init(&psset->to_purge[i]); 19*c43cad87SWarner Losh } 20*c43cad87SWarner Losh fb_init(psset->purge_bitmap, PSSET_NPURGE_LISTS); 21*c43cad87SWarner Losh hpdata_hugify_list_init(&psset->to_hugify); 22*c43cad87SWarner Losh } 23*c43cad87SWarner Losh 24*c43cad87SWarner Losh static void 25*c43cad87SWarner Losh psset_bin_stats_accum(psset_bin_stats_t *dst, psset_bin_stats_t *src) { 26*c43cad87SWarner Losh dst->npageslabs += src->npageslabs; 27*c43cad87SWarner Losh dst->nactive += src->nactive; 28*c43cad87SWarner Losh dst->ndirty += src->ndirty; 29*c43cad87SWarner Losh } 30*c43cad87SWarner Losh 31*c43cad87SWarner Losh void 32*c43cad87SWarner Losh psset_stats_accum(psset_stats_t *dst, psset_stats_t *src) { 33*c43cad87SWarner Losh psset_bin_stats_accum(&dst->full_slabs[0], &src->full_slabs[0]); 34*c43cad87SWarner Losh psset_bin_stats_accum(&dst->full_slabs[1], &src->full_slabs[1]); 35*c43cad87SWarner Losh psset_bin_stats_accum(&dst->empty_slabs[0], &src->empty_slabs[0]); 36*c43cad87SWarner Losh psset_bin_stats_accum(&dst->empty_slabs[1], &src->empty_slabs[1]); 37*c43cad87SWarner Losh for (pszind_t i = 0; i < PSSET_NPSIZES; i++) { 38*c43cad87SWarner Losh psset_bin_stats_accum(&dst->nonfull_slabs[i][0], 39*c43cad87SWarner Losh &src->nonfull_slabs[i][0]); 40*c43cad87SWarner Losh psset_bin_stats_accum(&dst->nonfull_slabs[i][1], 41*c43cad87SWarner Losh &src->nonfull_slabs[i][1]); 42*c43cad87SWarner Losh } 43*c43cad87SWarner Losh } 44*c43cad87SWarner Losh 45*c43cad87SWarner Losh /* 46*c43cad87SWarner Losh * The stats maintenance strategy is to remove a pageslab's contribution to the 47*c43cad87SWarner Losh * stats when we call psset_update_begin, and re-add it (to a potentially new 48*c43cad87SWarner Losh * bin) when we call psset_update_end. 49*c43cad87SWarner Losh */ 50*c43cad87SWarner Losh JEMALLOC_ALWAYS_INLINE void 51*c43cad87SWarner Losh psset_bin_stats_insert_remove(psset_t *psset, psset_bin_stats_t *binstats, 52*c43cad87SWarner Losh hpdata_t *ps, bool insert) { 53*c43cad87SWarner Losh size_t mul = insert ? (size_t)1 : (size_t)-1; 54*c43cad87SWarner Losh size_t huge_idx = (size_t)hpdata_huge_get(ps); 55*c43cad87SWarner Losh 56*c43cad87SWarner Losh binstats[huge_idx].npageslabs += mul * 1; 57*c43cad87SWarner Losh binstats[huge_idx].nactive += mul * hpdata_nactive_get(ps); 58*c43cad87SWarner Losh binstats[huge_idx].ndirty += mul * hpdata_ndirty_get(ps); 59*c43cad87SWarner Losh 60*c43cad87SWarner Losh psset->merged_stats.npageslabs += mul * 1; 61*c43cad87SWarner Losh psset->merged_stats.nactive += mul * hpdata_nactive_get(ps); 62*c43cad87SWarner Losh psset->merged_stats.ndirty += mul * hpdata_ndirty_get(ps); 63*c43cad87SWarner Losh 64*c43cad87SWarner Losh if (config_debug) { 65*c43cad87SWarner Losh psset_bin_stats_t check_stats = {0}; 66*c43cad87SWarner Losh for (size_t huge = 0; huge <= 1; huge++) { 67*c43cad87SWarner Losh psset_bin_stats_accum(&check_stats, 68*c43cad87SWarner Losh &psset->stats.full_slabs[huge]); 69*c43cad87SWarner Losh psset_bin_stats_accum(&check_stats, 70*c43cad87SWarner Losh &psset->stats.empty_slabs[huge]); 71*c43cad87SWarner Losh for (pszind_t pind = 0; pind < PSSET_NPSIZES; pind++) { 72*c43cad87SWarner Losh psset_bin_stats_accum(&check_stats, 73*c43cad87SWarner Losh &psset->stats.nonfull_slabs[pind][huge]); 74*c43cad87SWarner Losh } 75*c43cad87SWarner Losh } 76*c43cad87SWarner Losh assert(psset->merged_stats.npageslabs 77*c43cad87SWarner Losh == check_stats.npageslabs); 78*c43cad87SWarner Losh assert(psset->merged_stats.nactive == check_stats.nactive); 79*c43cad87SWarner Losh assert(psset->merged_stats.ndirty == check_stats.ndirty); 80*c43cad87SWarner Losh } 81*c43cad87SWarner Losh } 82*c43cad87SWarner Losh 83*c43cad87SWarner Losh static void 84*c43cad87SWarner Losh psset_bin_stats_insert(psset_t *psset, psset_bin_stats_t *binstats, 85*c43cad87SWarner Losh hpdata_t *ps) { 86*c43cad87SWarner Losh psset_bin_stats_insert_remove(psset, binstats, ps, true); 87*c43cad87SWarner Losh } 88*c43cad87SWarner Losh 89*c43cad87SWarner Losh static void 90*c43cad87SWarner Losh psset_bin_stats_remove(psset_t *psset, psset_bin_stats_t *binstats, 91*c43cad87SWarner Losh hpdata_t *ps) { 92*c43cad87SWarner Losh psset_bin_stats_insert_remove(psset, binstats, ps, false); 93*c43cad87SWarner Losh } 94*c43cad87SWarner Losh 95*c43cad87SWarner Losh static void 96*c43cad87SWarner Losh psset_hpdata_heap_remove(psset_t *psset, pszind_t pind, hpdata_t *ps) { 97*c43cad87SWarner Losh hpdata_age_heap_remove(&psset->pageslabs[pind], ps); 98*c43cad87SWarner Losh if (hpdata_age_heap_empty(&psset->pageslabs[pind])) { 99*c43cad87SWarner Losh fb_unset(psset->pageslab_bitmap, PSSET_NPSIZES, (size_t)pind); 100*c43cad87SWarner Losh } 101*c43cad87SWarner Losh } 102*c43cad87SWarner Losh 103*c43cad87SWarner Losh static void 104*c43cad87SWarner Losh psset_hpdata_heap_insert(psset_t *psset, pszind_t pind, hpdata_t *ps) { 105*c43cad87SWarner Losh if (hpdata_age_heap_empty(&psset->pageslabs[pind])) { 106*c43cad87SWarner Losh fb_set(psset->pageslab_bitmap, PSSET_NPSIZES, (size_t)pind); 107*c43cad87SWarner Losh } 108*c43cad87SWarner Losh hpdata_age_heap_insert(&psset->pageslabs[pind], ps); 109*c43cad87SWarner Losh } 110*c43cad87SWarner Losh 111*c43cad87SWarner Losh static void 112*c43cad87SWarner Losh psset_stats_insert(psset_t* psset, hpdata_t *ps) { 113*c43cad87SWarner Losh if (hpdata_empty(ps)) { 114*c43cad87SWarner Losh psset_bin_stats_insert(psset, psset->stats.empty_slabs, ps); 115*c43cad87SWarner Losh } else if (hpdata_full(ps)) { 116*c43cad87SWarner Losh psset_bin_stats_insert(psset, psset->stats.full_slabs, ps); 117*c43cad87SWarner Losh } else { 118*c43cad87SWarner Losh size_t longest_free_range = hpdata_longest_free_range_get(ps); 119*c43cad87SWarner Losh 120*c43cad87SWarner Losh pszind_t pind = sz_psz2ind(sz_psz_quantize_floor( 121*c43cad87SWarner Losh longest_free_range << LG_PAGE)); 122*c43cad87SWarner Losh assert(pind < PSSET_NPSIZES); 123*c43cad87SWarner Losh 124*c43cad87SWarner Losh psset_bin_stats_insert(psset, psset->stats.nonfull_slabs[pind], 125*c43cad87SWarner Losh ps); 126*c43cad87SWarner Losh } 127*c43cad87SWarner Losh } 128*c43cad87SWarner Losh 129*c43cad87SWarner Losh static void 130*c43cad87SWarner Losh psset_stats_remove(psset_t *psset, hpdata_t *ps) { 131*c43cad87SWarner Losh if (hpdata_empty(ps)) { 132*c43cad87SWarner Losh psset_bin_stats_remove(psset, psset->stats.empty_slabs, ps); 133*c43cad87SWarner Losh } else if (hpdata_full(ps)) { 134*c43cad87SWarner Losh psset_bin_stats_remove(psset, psset->stats.full_slabs, ps); 135*c43cad87SWarner Losh } else { 136*c43cad87SWarner Losh size_t longest_free_range = hpdata_longest_free_range_get(ps); 137*c43cad87SWarner Losh 138*c43cad87SWarner Losh pszind_t pind = sz_psz2ind(sz_psz_quantize_floor( 139*c43cad87SWarner Losh longest_free_range << LG_PAGE)); 140*c43cad87SWarner Losh assert(pind < PSSET_NPSIZES); 141*c43cad87SWarner Losh 142*c43cad87SWarner Losh psset_bin_stats_remove(psset, psset->stats.nonfull_slabs[pind], 143*c43cad87SWarner Losh ps); 144*c43cad87SWarner Losh } 145*c43cad87SWarner Losh } 146*c43cad87SWarner Losh 147*c43cad87SWarner Losh /* 148*c43cad87SWarner Losh * Put ps into some container so that it can be found during future allocation 149*c43cad87SWarner Losh * requests. 150*c43cad87SWarner Losh */ 151*c43cad87SWarner Losh static void 152*c43cad87SWarner Losh psset_alloc_container_insert(psset_t *psset, hpdata_t *ps) { 153*c43cad87SWarner Losh assert(!hpdata_in_psset_alloc_container_get(ps)); 154*c43cad87SWarner Losh hpdata_in_psset_alloc_container_set(ps, true); 155*c43cad87SWarner Losh if (hpdata_empty(ps)) { 156*c43cad87SWarner Losh /* 157*c43cad87SWarner Losh * This prepend, paired with popping the head in psset_fit, 158*c43cad87SWarner Losh * means we implement LIFO ordering for the empty slabs set, 159*c43cad87SWarner Losh * which seems reasonable. 160*c43cad87SWarner Losh */ 161*c43cad87SWarner Losh hpdata_empty_list_prepend(&psset->empty, ps); 162*c43cad87SWarner Losh } else if (hpdata_full(ps)) { 163*c43cad87SWarner Losh /* 164*c43cad87SWarner Losh * We don't need to keep track of the full slabs; we're never 165*c43cad87SWarner Losh * going to return them from a psset_pick_alloc call. 166*c43cad87SWarner Losh */ 167*c43cad87SWarner Losh } else { 168*c43cad87SWarner Losh size_t longest_free_range = hpdata_longest_free_range_get(ps); 169*c43cad87SWarner Losh 170*c43cad87SWarner Losh pszind_t pind = sz_psz2ind(sz_psz_quantize_floor( 171*c43cad87SWarner Losh longest_free_range << LG_PAGE)); 172*c43cad87SWarner Losh assert(pind < PSSET_NPSIZES); 173*c43cad87SWarner Losh 174*c43cad87SWarner Losh psset_hpdata_heap_insert(psset, pind, ps); 175*c43cad87SWarner Losh } 176*c43cad87SWarner Losh } 177*c43cad87SWarner Losh 178*c43cad87SWarner Losh /* Remove ps from those collections. */ 179*c43cad87SWarner Losh static void 180*c43cad87SWarner Losh psset_alloc_container_remove(psset_t *psset, hpdata_t *ps) { 181*c43cad87SWarner Losh assert(hpdata_in_psset_alloc_container_get(ps)); 182*c43cad87SWarner Losh hpdata_in_psset_alloc_container_set(ps, false); 183*c43cad87SWarner Losh 184*c43cad87SWarner Losh if (hpdata_empty(ps)) { 185*c43cad87SWarner Losh hpdata_empty_list_remove(&psset->empty, ps); 186*c43cad87SWarner Losh } else if (hpdata_full(ps)) { 187*c43cad87SWarner Losh /* Same as above -- do nothing in this case. */ 188*c43cad87SWarner Losh } else { 189*c43cad87SWarner Losh size_t longest_free_range = hpdata_longest_free_range_get(ps); 190*c43cad87SWarner Losh 191*c43cad87SWarner Losh pszind_t pind = sz_psz2ind(sz_psz_quantize_floor( 192*c43cad87SWarner Losh longest_free_range << LG_PAGE)); 193*c43cad87SWarner Losh assert(pind < PSSET_NPSIZES); 194*c43cad87SWarner Losh 195*c43cad87SWarner Losh psset_hpdata_heap_remove(psset, pind, ps); 196*c43cad87SWarner Losh } 197*c43cad87SWarner Losh } 198*c43cad87SWarner Losh 199*c43cad87SWarner Losh static size_t 200*c43cad87SWarner Losh psset_purge_list_ind(hpdata_t *ps) { 201*c43cad87SWarner Losh size_t ndirty = hpdata_ndirty_get(ps); 202*c43cad87SWarner Losh /* Shouldn't have something with no dirty pages purgeable. */ 203*c43cad87SWarner Losh assert(ndirty > 0); 204*c43cad87SWarner Losh /* 205*c43cad87SWarner Losh * Higher indices correspond to lists we'd like to purge earlier; make 206*c43cad87SWarner Losh * the two highest indices correspond to empty lists, which we attempt 207*c43cad87SWarner Losh * to purge before purging any non-empty list. This has two advantages: 208*c43cad87SWarner Losh * - Empty page slabs are the least likely to get reused (we'll only 209*c43cad87SWarner Losh * pick them for an allocation if we have no other choice). 210*c43cad87SWarner Losh * - Empty page slabs can purge every dirty page they contain in a 211*c43cad87SWarner Losh * single call, which is not usually the case. 212*c43cad87SWarner Losh * 213*c43cad87SWarner Losh * We purge hugeified empty slabs before nonhugeified ones, on the basis 214*c43cad87SWarner Losh * that they are fully dirty, while nonhugified slabs might not be, so 215*c43cad87SWarner Losh * we free up more pages more easily. 216*c43cad87SWarner Losh */ 217*c43cad87SWarner Losh if (hpdata_nactive_get(ps) == 0) { 218*c43cad87SWarner Losh if (hpdata_huge_get(ps)) { 219*c43cad87SWarner Losh return PSSET_NPURGE_LISTS - 1; 220*c43cad87SWarner Losh } else { 221*c43cad87SWarner Losh return PSSET_NPURGE_LISTS - 2; 222*c43cad87SWarner Losh } 223*c43cad87SWarner Losh } 224*c43cad87SWarner Losh 225*c43cad87SWarner Losh pszind_t pind = sz_psz2ind(sz_psz_quantize_floor(ndirty << LG_PAGE)); 226*c43cad87SWarner Losh /* 227*c43cad87SWarner Losh * For non-empty slabs, we may reuse them again. Prefer purging 228*c43cad87SWarner Losh * non-hugeified slabs before hugeified ones then, among pages of 229*c43cad87SWarner Losh * similar dirtiness. We still get some benefit from the hugification. 230*c43cad87SWarner Losh */ 231*c43cad87SWarner Losh return (size_t)pind * 2 + (hpdata_huge_get(ps) ? 0 : 1); 232*c43cad87SWarner Losh } 233*c43cad87SWarner Losh 234*c43cad87SWarner Losh static void 235*c43cad87SWarner Losh psset_maybe_remove_purge_list(psset_t *psset, hpdata_t *ps) { 236*c43cad87SWarner Losh /* 237*c43cad87SWarner Losh * Remove the hpdata from its purge list (if it's in one). Even if it's 238*c43cad87SWarner Losh * going to stay in the same one, by appending it during 239*c43cad87SWarner Losh * psset_update_end, we move it to the end of its queue, so that we 240*c43cad87SWarner Losh * purge LRU within a given dirtiness bucket. 241*c43cad87SWarner Losh */ 242*c43cad87SWarner Losh if (hpdata_purge_allowed_get(ps)) { 243*c43cad87SWarner Losh size_t ind = psset_purge_list_ind(ps); 244*c43cad87SWarner Losh hpdata_purge_list_t *purge_list = &psset->to_purge[ind]; 245*c43cad87SWarner Losh hpdata_purge_list_remove(purge_list, ps); 246*c43cad87SWarner Losh if (hpdata_purge_list_empty(purge_list)) { 247*c43cad87SWarner Losh fb_unset(psset->purge_bitmap, PSSET_NPURGE_LISTS, ind); 248*c43cad87SWarner Losh } 249*c43cad87SWarner Losh } 250*c43cad87SWarner Losh } 251*c43cad87SWarner Losh 252*c43cad87SWarner Losh static void 253*c43cad87SWarner Losh psset_maybe_insert_purge_list(psset_t *psset, hpdata_t *ps) { 254*c43cad87SWarner Losh if (hpdata_purge_allowed_get(ps)) { 255*c43cad87SWarner Losh size_t ind = psset_purge_list_ind(ps); 256*c43cad87SWarner Losh hpdata_purge_list_t *purge_list = &psset->to_purge[ind]; 257*c43cad87SWarner Losh if (hpdata_purge_list_empty(purge_list)) { 258*c43cad87SWarner Losh fb_set(psset->purge_bitmap, PSSET_NPURGE_LISTS, ind); 259*c43cad87SWarner Losh } 260*c43cad87SWarner Losh hpdata_purge_list_append(purge_list, ps); 261*c43cad87SWarner Losh } 262*c43cad87SWarner Losh 263*c43cad87SWarner Losh } 264*c43cad87SWarner Losh 265*c43cad87SWarner Losh void 266*c43cad87SWarner Losh psset_update_begin(psset_t *psset, hpdata_t *ps) { 267*c43cad87SWarner Losh hpdata_assert_consistent(ps); 268*c43cad87SWarner Losh assert(hpdata_in_psset_get(ps)); 269*c43cad87SWarner Losh hpdata_updating_set(ps, true); 270*c43cad87SWarner Losh psset_stats_remove(psset, ps); 271*c43cad87SWarner Losh if (hpdata_in_psset_alloc_container_get(ps)) { 272*c43cad87SWarner Losh /* 273*c43cad87SWarner Losh * Some metadata updates can break alloc container invariants 274*c43cad87SWarner Losh * (e.g. the longest free range determines the hpdata_heap_t the 275*c43cad87SWarner Losh * pageslab lives in). 276*c43cad87SWarner Losh */ 277*c43cad87SWarner Losh assert(hpdata_alloc_allowed_get(ps)); 278*c43cad87SWarner Losh psset_alloc_container_remove(psset, ps); 279*c43cad87SWarner Losh } 280*c43cad87SWarner Losh psset_maybe_remove_purge_list(psset, ps); 281*c43cad87SWarner Losh /* 282*c43cad87SWarner Losh * We don't update presence in the hugify list; we try to keep it FIFO, 283*c43cad87SWarner Losh * even in the presence of other metadata updates. We'll update 284*c43cad87SWarner Losh * presence at the end of the metadata update if necessary. 285*c43cad87SWarner Losh */ 286*c43cad87SWarner Losh } 287*c43cad87SWarner Losh 288*c43cad87SWarner Losh void 289*c43cad87SWarner Losh psset_update_end(psset_t *psset, hpdata_t *ps) { 290*c43cad87SWarner Losh assert(hpdata_in_psset_get(ps)); 291*c43cad87SWarner Losh hpdata_updating_set(ps, false); 292*c43cad87SWarner Losh psset_stats_insert(psset, ps); 293*c43cad87SWarner Losh 294*c43cad87SWarner Losh /* 295*c43cad87SWarner Losh * The update begin should have removed ps from whatever alloc container 296*c43cad87SWarner Losh * it was in. 297*c43cad87SWarner Losh */ 298*c43cad87SWarner Losh assert(!hpdata_in_psset_alloc_container_get(ps)); 299*c43cad87SWarner Losh if (hpdata_alloc_allowed_get(ps)) { 300*c43cad87SWarner Losh psset_alloc_container_insert(psset, ps); 301*c43cad87SWarner Losh } 302*c43cad87SWarner Losh psset_maybe_insert_purge_list(psset, ps); 303*c43cad87SWarner Losh 304*c43cad87SWarner Losh if (hpdata_hugify_allowed_get(ps) 305*c43cad87SWarner Losh && !hpdata_in_psset_hugify_container_get(ps)) { 306*c43cad87SWarner Losh hpdata_in_psset_hugify_container_set(ps, true); 307*c43cad87SWarner Losh hpdata_hugify_list_append(&psset->to_hugify, ps); 308*c43cad87SWarner Losh } else if (!hpdata_hugify_allowed_get(ps) 309*c43cad87SWarner Losh && hpdata_in_psset_hugify_container_get(ps)) { 310*c43cad87SWarner Losh hpdata_in_psset_hugify_container_set(ps, false); 311*c43cad87SWarner Losh hpdata_hugify_list_remove(&psset->to_hugify, ps); 312*c43cad87SWarner Losh } 313*c43cad87SWarner Losh hpdata_assert_consistent(ps); 314*c43cad87SWarner Losh } 315*c43cad87SWarner Losh 316*c43cad87SWarner Losh hpdata_t * 317*c43cad87SWarner Losh psset_pick_alloc(psset_t *psset, size_t size) { 318*c43cad87SWarner Losh assert((size & PAGE_MASK) == 0); 319*c43cad87SWarner Losh assert(size <= HUGEPAGE); 320*c43cad87SWarner Losh 321*c43cad87SWarner Losh pszind_t min_pind = sz_psz2ind(sz_psz_quantize_ceil(size)); 322*c43cad87SWarner Losh pszind_t pind = (pszind_t)fb_ffs(psset->pageslab_bitmap, PSSET_NPSIZES, 323*c43cad87SWarner Losh (size_t)min_pind); 324*c43cad87SWarner Losh if (pind == PSSET_NPSIZES) { 325*c43cad87SWarner Losh return hpdata_empty_list_first(&psset->empty); 326*c43cad87SWarner Losh } 327*c43cad87SWarner Losh hpdata_t *ps = hpdata_age_heap_first(&psset->pageslabs[pind]); 328*c43cad87SWarner Losh if (ps == NULL) { 329*c43cad87SWarner Losh return NULL; 330*c43cad87SWarner Losh } 331*c43cad87SWarner Losh 332*c43cad87SWarner Losh hpdata_assert_consistent(ps); 333*c43cad87SWarner Losh 334*c43cad87SWarner Losh return ps; 335*c43cad87SWarner Losh } 336*c43cad87SWarner Losh 337*c43cad87SWarner Losh hpdata_t * 338*c43cad87SWarner Losh psset_pick_purge(psset_t *psset) { 339*c43cad87SWarner Losh ssize_t ind_ssz = fb_fls(psset->purge_bitmap, PSSET_NPURGE_LISTS, 340*c43cad87SWarner Losh PSSET_NPURGE_LISTS - 1); 341*c43cad87SWarner Losh if (ind_ssz < 0) { 342*c43cad87SWarner Losh return NULL; 343*c43cad87SWarner Losh } 344*c43cad87SWarner Losh pszind_t ind = (pszind_t)ind_ssz; 345*c43cad87SWarner Losh assert(ind < PSSET_NPURGE_LISTS); 346*c43cad87SWarner Losh hpdata_t *ps = hpdata_purge_list_first(&psset->to_purge[ind]); 347*c43cad87SWarner Losh assert(ps != NULL); 348*c43cad87SWarner Losh return ps; 349*c43cad87SWarner Losh } 350*c43cad87SWarner Losh 351*c43cad87SWarner Losh hpdata_t * 352*c43cad87SWarner Losh psset_pick_hugify(psset_t *psset) { 353*c43cad87SWarner Losh return hpdata_hugify_list_first(&psset->to_hugify); 354*c43cad87SWarner Losh } 355*c43cad87SWarner Losh 356*c43cad87SWarner Losh void 357*c43cad87SWarner Losh psset_insert(psset_t *psset, hpdata_t *ps) { 358*c43cad87SWarner Losh hpdata_in_psset_set(ps, true); 359*c43cad87SWarner Losh 360*c43cad87SWarner Losh psset_stats_insert(psset, ps); 361*c43cad87SWarner Losh if (hpdata_alloc_allowed_get(ps)) { 362*c43cad87SWarner Losh psset_alloc_container_insert(psset, ps); 363*c43cad87SWarner Losh } 364*c43cad87SWarner Losh psset_maybe_insert_purge_list(psset, ps); 365*c43cad87SWarner Losh 366*c43cad87SWarner Losh if (hpdata_hugify_allowed_get(ps)) { 367*c43cad87SWarner Losh hpdata_in_psset_hugify_container_set(ps, true); 368*c43cad87SWarner Losh hpdata_hugify_list_append(&psset->to_hugify, ps); 369*c43cad87SWarner Losh } 370*c43cad87SWarner Losh } 371*c43cad87SWarner Losh 372*c43cad87SWarner Losh void 373*c43cad87SWarner Losh psset_remove(psset_t *psset, hpdata_t *ps) { 374*c43cad87SWarner Losh hpdata_in_psset_set(ps, false); 375*c43cad87SWarner Losh 376*c43cad87SWarner Losh psset_stats_remove(psset, ps); 377*c43cad87SWarner Losh if (hpdata_in_psset_alloc_container_get(ps)) { 378*c43cad87SWarner Losh psset_alloc_container_remove(psset, ps); 379*c43cad87SWarner Losh } 380*c43cad87SWarner Losh psset_maybe_remove_purge_list(psset, ps); 381*c43cad87SWarner Losh if (hpdata_in_psset_hugify_container_get(ps)) { 382*c43cad87SWarner Losh hpdata_in_psset_hugify_container_set(ps, false); 383*c43cad87SWarner Losh hpdata_hugify_list_remove(&psset->to_hugify, ps); 384*c43cad87SWarner Losh } 385*c43cad87SWarner Losh } 386