2020-07-11 08:40:13 +08:00
|
|
|
#ifndef JEMALLOC_INTERNAL_PSSET_H
|
|
|
|
#define JEMALLOC_INTERNAL_PSSET_H
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* It has the same synchronization guarantees as the eset; stats queries don't
|
|
|
|
* need any external synchronization, everything else does.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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? */
|
|
|
|
size_t npageslabs;
|
|
|
|
/* Of them, how many pages are active? */
|
|
|
|
size_t nactive;
|
|
|
|
/* How many are inactive? */
|
|
|
|
size_t ninactive;
|
|
|
|
};
|
|
|
|
|
2020-09-05 03:01:52 +08:00
|
|
|
static inline void
|
|
|
|
psset_bin_stats_accum(psset_bin_stats_t *dst, psset_bin_stats_t *src) {
|
|
|
|
dst->npageslabs += src->npageslabs;
|
|
|
|
dst->nactive += src->nactive;
|
|
|
|
dst->ninactive += src->ninactive;
|
|
|
|
}
|
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
edata_heap_t pageslabs[PSSET_NPSIZES];
|
|
|
|
bitmap_t bitmap[BITMAP_GROUPS(PSSET_NPSIZES)];
|
2020-09-03 03:59:10 +08:00
|
|
|
/*
|
|
|
|
* Full slabs don't live in any edata heap. But we still track their
|
|
|
|
* stats.
|
|
|
|
*/
|
|
|
|
psset_bin_stats_t full_slab_stats;
|
|
|
|
psset_bin_stats_t slab_stats[PSSET_NPSIZES];
|
2020-07-11 08:40:13 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
void psset_init(psset_t *psset);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Tries to obtain a chunk from an existing pageslab already in the set.
|
|
|
|
* Returns true on failure.
|
|
|
|
*/
|
|
|
|
bool psset_alloc_reuse(psset_t *psset, edata_t *r_edata, size_t size);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Given a newly created pageslab ps (not currently in the set), pass ownership
|
|
|
|
* to the psset and allocate an extent from within it. The passed-in pageslab
|
|
|
|
* must be at least as big as size.
|
|
|
|
*/
|
|
|
|
void psset_alloc_new(psset_t *psset, edata_t *ps,
|
|
|
|
edata_t *r_edata, size_t size);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Given an extent that comes from a pageslab in this pageslab set, returns it
|
|
|
|
* to its slab. Does not take ownership of the underlying edata_t.
|
|
|
|
*
|
|
|
|
* If some slab becomes empty as a result of the dalloc, it is retuend -- the
|
|
|
|
* result must be checked and deallocated to the central HPA. Otherwise returns
|
|
|
|
* NULL.
|
|
|
|
*/
|
|
|
|
edata_t *psset_dalloc(psset_t *psset, edata_t *edata);
|
|
|
|
|
|
|
|
#endif /* JEMALLOC_INTERNAL_PSSET_H */
|