Skip to content

Fixed Size Allocation

include/mem/fixed_size_alloc.h View source View on GitHub
struct fixed_size_node (1 field) source

The idea here:

memory is laid out as

[ data ] [ potential empty ] [ fixed_size_node ]

essentially, the objects have their own alignment, so each of these “full nodes” comes with the data first, then the empty zone. the fixed size node trails to link it all up

§ struct list_node list_node
struct fixed_size_page_hdr (4 fields) source
§ domain_id_t domain

DOMAIN_ID_NONE means it isn’t perdomain

§ size_t free_count
§ size_t total
§ struct list_node page_list
struct fixed_size_range_attributes (5 fields) source
§ size_t obj_size
§ size_t obj_align
§ void (*init_obj)(void *)
§ void (*deinit_obj)(void *)
§ bool bootstrap_mode : 1
struct fixed_size_range (8 fields) source
§ struct spinlock lock
§ struct list_head freelist

fixed_size_node list_node

§ struct list_head fl_pages

fixed_size_page_hdr page_list

§ size_t empty_pages
§ size_t full_node_size

node size + object size

§ struct fixed_size_range **perdomain_fsrs
§ domain_id_t domain
void * fixed_size_alloc(struct fixed_size_range *fsr)
source
void fixed_size_free(struct fixed_size_range *fsr, void *obj)
source
void fixed_size_reclaim_freelist_pages(struct fixed_size_range *fsr)
source
struct fixed_size_range * fixed_size_range_create(struct fixed_size_range_attributes *attrs)
source
void fixed_size_range_init(
    struct fixed_size_range *fsr,
    struct fixed_size_range_attributes *attrs
)
source
struct fixed_size_page_hdr * fixed_size_page_of(void *o)
source
#define FIXED_SIZE_KEEP_EMPTY_PAGES 1
source

Number of fully-empty freelist backing pages to keep cached per local tree before reclaiming on free

Provides hysteresis so a workload that oscillates across a page boundary does not pmm_alloc/pmm_free on every transition

#define FIXED_SIZE_RANGE_PERDOMAIN_DEFINE(name, ...)
source
Expansion
#define FIXED_SIZE_RANGE_PERDOMAIN_DEFINE(name, ...) \
    static cc_unused bool __fsr_##name##_enabled = false; \
    static void __##name##_fsr_init(struct fixed_size_range *fsr_, \
                                    size_t domain_) { \
        static struct fixed_size_range **__perdomain_fsrs_##name = NULL; \
        if (!__perdomain_fsrs_##name) \
            __perdomain_fsrs_##name = \
                nofail_vnews(__perdomain_fsrs_##name, global.domain_count); \
 \
        struct fixed_size_range_attributes __fsr_attrs = {__VA_ARGS__}; \
        fixed_size_range_init(fsr_, &__fsr_attrs); \
        __perdomain_fsrs_##name[domain_] = fsr_; \
        fsr_->perdomain_fsrs = __perdomain_fsrs_##name; \
        fsr_->domain = domain_; \
        if (domain_ == global.domain_count - 1) \
            __fsr_##name##_enabled = true; \
    } \
    PERDOMAIN_DEFINE(struct fixed_size_range, __##name##_fsr, \
                     __##name##_fsr_init)
#define FSR_PERDOMAIN_ENABLED(name)
source
Expansion
#define FSR_PERDOMAIN_ENABLED(name) __fsr_##name##_enabled
#define FSR_PERDOMAIN(name)
source
Expansion
#define FSR_PERDOMAIN(name) PERDOMAIN(__##name##_fsr)
#define FSR_PERDOMAIN_THIS(name)
source

_NONE here: domains are an optimization anyways

Expansion
#define FSR_PERDOMAIN_THIS(name) PERDOMAIN_PTR(TOPC_NONE, __##name##_fsr)
#define FSR_PERDOMAIN_ALLOC(name)
source
#define FSR_PERDOMAIN_FREE(name, obj)
source
Expansion
#define FSR_PERDOMAIN_FREE(name, obj) \
    fixed_size_free(FSR_PERDOMAIN_THIS(name), (obj))