2020-07-11 08:40:13 +08:00
|
|
|
#ifndef JEMALLOC_INTERNAL_PSSET_H
|
|
|
|
#define JEMALLOC_INTERNAL_PSSET_H
|
|
|
|
|
2020-11-18 08:32:45 +08:00
|
|
|
#include "jemalloc/internal/hpdata.h"
|
|
|
|
|
2020-07-11 08:40:13 +08:00
|
|
|
/*
|
|
|
|
* A page-slab set. What the eset is to PAC, the psset is to HPA. It maintains
|
|
|
|
* a collection of page-slabs (the intent being that they are backed by
|
|
|
|
* hugepages, or at least could be), and handles allocation and deallocation
|
|
|
|
* requests.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* One more than the maximum pszind_t we will serve out of the HPA.
|
|
|
|
* Practically, we expect only the first few to be actually used. This
|
|
|
|
* corresponds to a maximum size of of 512MB on systems with 4k pages and
|
|
|
|
* SC_NGROUP == 4, which is already an unreasonably large maximum. Morally, you
|
|
|
|
* can think of this as being SC_NPSIZES, but there's no sense in wasting that
|
|
|
|
* much space in the arena, making bitmaps that much larger, etc.
|
|
|
|
*/
|
|
|
|
#define PSSET_NPSIZES 64
|
|
|
|
|
2020-09-03 03:59:10 +08:00
|
|
|
typedef struct psset_bin_stats_s psset_bin_stats_t;
|
|
|
|
struct psset_bin_stats_s {
|
|
|
|
/* How many pageslabs are in this bin? */
|
2020-12-04 10:32:42 +08:00
|
|
|
size_t npageslabs;
|
2020-09-03 03:59:10 +08:00
|
|
|
/* Of them, how many pages are active? */
|
2020-12-04 10:32:42 +08:00
|
|
|
size_t nactive;
|
2020-12-04 11:15:54 +08:00
|
|
|
/* And how many are dirty? */
|
|
|
|
size_t ndirty;
|
2020-09-03 03:59:10 +08:00
|
|
|
};
|
|
|
|
|
2020-11-11 08:23:03 +08:00
|
|
|
typedef struct psset_stats_s psset_stats_t;
|
|
|
|
struct psset_stats_s {
|
2020-12-04 10:32:42 +08:00
|
|
|
/*
|
|
|
|
* The second index is huge stats; nonfull_slabs[pszind][0] contains
|
|
|
|
* stats for the non-huge slabs in bucket pszind, while
|
|
|
|
* nonfull_slabs[pszind][1] contains stats for the huge slabs.
|
|
|
|
*/
|
|
|
|
psset_bin_stats_t nonfull_slabs[PSSET_NPSIZES][2];
|
|
|
|
|
2020-11-11 08:23:03 +08:00
|
|
|
/*
|
2020-12-06 09:42:04 +08:00
|
|
|
* Full slabs don't live in any edata heap, but we still track their
|
2020-11-11 08:23:03 +08:00
|
|
|
* stats.
|
|
|
|
*/
|
2020-12-04 10:32:42 +08:00
|
|
|
psset_bin_stats_t full_slabs[2];
|
2020-12-06 09:42:04 +08:00
|
|
|
|
|
|
|
/* Empty slabs are similar. */
|
|
|
|
psset_bin_stats_t empty_slabs[2];
|
2020-11-11 08:23:03 +08:00
|
|
|
};
|
2020-09-05 03:01:52 +08:00
|
|
|
|
2020-07-11 08:40:13 +08:00
|
|
|
typedef struct psset_s psset_t;
|
|
|
|
struct psset_s {
|
|
|
|
/*
|
|
|
|
* The pageslabs, quantized by the size class of the largest contiguous
|
|
|
|
* free run of pages in a pageslab.
|
|
|
|
*/
|
2020-11-18 08:32:45 +08:00
|
|
|
hpdata_age_heap_t pageslabs[PSSET_NPSIZES];
|
2021-02-09 03:04:46 +08:00
|
|
|
/* Bitmap for which set bits correspond to non-empty heaps. */
|
|
|
|
fb_group_t bitmap[FB_NGROUPS(PSSET_NPSIZES)];
|
2020-12-07 04:49:03 +08:00
|
|
|
/*
|
|
|
|
* The sum of all bin stats in stats. This lets us quickly answer
|
|
|
|
* queries for the number of dirty, active, and retained pages in the
|
|
|
|
* entire set.
|
|
|
|
*/
|
|
|
|
psset_bin_stats_t merged_stats;
|
2020-11-11 08:23:03 +08:00
|
|
|
psset_stats_t stats;
|
2020-12-07 01:49:26 +08:00
|
|
|
/*
|
|
|
|
* Slabs with no active allocations, but which are allowed to serve new
|
|
|
|
* allocations.
|
|
|
|
*/
|
|
|
|
hpdata_empty_list_t empty;
|
|
|
|
/* Slabs which are available to be purged. */
|
|
|
|
hpdata_purge_list_t to_purge;
|
|
|
|
/* Slabs which are available to be hugified. */
|
|
|
|
hpdata_hugify_list_t to_hugify;
|
2020-07-11 08:40:13 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
void psset_init(psset_t *psset);
|
2020-11-11 08:23:03 +08:00
|
|
|
void psset_stats_accum(psset_stats_t *dst, psset_stats_t *src);
|
2020-07-11 08:40:13 +08:00
|
|
|
|
2020-12-06 07:58:31 +08:00
|
|
|
/*
|
|
|
|
* Begin or end updating the given pageslab's metadata. While the pageslab is
|
|
|
|
* being updated, it won't be returned from psset_fit calls.
|
|
|
|
*/
|
|
|
|
void psset_update_begin(psset_t *psset, hpdata_t *ps);
|
|
|
|
void psset_update_end(psset_t *psset, hpdata_t *ps);
|
2020-11-10 09:24:31 +08:00
|
|
|
|
2020-12-01 05:28:54 +08:00
|
|
|
/* Analogous to the eset_fit; pick a hpdata to serve the request. */
|
2020-12-06 07:58:31 +08:00
|
|
|
hpdata_t *psset_pick_alloc(psset_t *psset, size_t size);
|
2020-12-07 01:49:26 +08:00
|
|
|
/* Pick one to purge. */
|
|
|
|
hpdata_t *psset_pick_purge(psset_t *psset);
|
|
|
|
/* Pick one to hugify. */
|
|
|
|
hpdata_t *psset_pick_hugify(psset_t *psset);
|
2020-07-11 08:40:13 +08:00
|
|
|
|
2020-12-06 09:42:04 +08:00
|
|
|
void psset_insert(psset_t *psset, hpdata_t *ps);
|
|
|
|
void psset_remove(psset_t *psset, hpdata_t *ps);
|
|
|
|
|
2020-12-07 04:49:03 +08:00
|
|
|
static inline size_t
|
|
|
|
psset_npageslabs(psset_t *psset) {
|
|
|
|
return psset->merged_stats.npageslabs;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline size_t
|
|
|
|
psset_nactive(psset_t *psset) {
|
|
|
|
return psset->merged_stats.nactive;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline size_t
|
|
|
|
psset_ndirty(psset_t *psset) {
|
|
|
|
return psset->merged_stats.ndirty;
|
|
|
|
}
|
|
|
|
|
2020-07-11 08:40:13 +08:00
|
|
|
#endif /* JEMALLOC_INTERNAL_PSSET_H */
|