blob: 67982ce9bc9be5bb457f71265c63742a4b358636 [file] [log] [blame] [edit]
/*
* SPDX-License-Identifier: GPL-2.0
* Copyright (c) 2025 Meta Platforms, Inc. and affiliates.
* Copyright (c) 2025 Tejun Heo <tj@kernel.org>
* Copyright (c) 2025 Emil Tsalapatis <etsal@meta.com>
*/
#pragma once
#ifndef __BPF__
#define __arena
#endif /* __BPF__ */
struct scx_alloc_stats {
__u64 chunk_allocs;
__u64 data_allocs;
__u64 alloc_ops;
__u64 free_ops;
__u64 active_allocs;
__u64 arena_pages_used;
};
struct sdt_pool {
void __arena *slab;
__u64 elem_size;
__u64 max_elems;
__u64 idx;
};
#ifndef div_round_up
#define div_round_up(a, b) (((a) + (b) - 1) / (b))
#endif
#ifndef round_up
#define round_up(a, b) (div_round_up((a), (b)) * (b))
#endif
typedef struct sdt_desc __arena sdt_desc_t;
enum sdt_consts {
SDT_TASK_ENTS_PER_PAGE_SHIFT = 9,
SDT_TASK_LEVELS = 3,
SDT_TASK_ENTS_PER_CHUNK = 1 << SDT_TASK_ENTS_PER_PAGE_SHIFT,
SDT_TASK_CHUNK_BITMAP_U64S = div_round_up(SDT_TASK_ENTS_PER_CHUNK, 64),
SDT_TASK_MIN_ELEM_PER_ALLOC = 8,
};
union sdt_id {
__s64 val;
struct {
__s32 idx; /* index in the radix tree */
__s32 genn; /* ++'d on recycle so that it forms unique'ish 64bit ID */
};
};
struct sdt_chunk;
/*
* Each index page is described by the following descriptor which carries the
* bitmap. This way the actual index can host power-of-two numbers of entries
* which makes indexing cheaper.
*/
struct sdt_desc {
__u64 allocated[SDT_TASK_CHUNK_BITMAP_U64S];
__u64 nr_free;
struct sdt_chunk __arena *chunk;
};
/*
* Leaf node containing per-task data.
*/
struct sdt_data {
union sdt_id tid;
__u64 payload[];
};
/*
* Intermediate node pointing to another intermediate node or leaf node.
*/
struct sdt_chunk {
union {
sdt_desc_t * descs[SDT_TASK_ENTS_PER_CHUNK];
struct sdt_data __arena *data[SDT_TASK_ENTS_PER_CHUNK];
};
};
struct scx_allocator {
struct sdt_pool pool;
sdt_desc_t *root;
};
struct scx_stats {
int seq;
pid_t pid;
__u64 enqueue;
__u64 exit;
__u64 init;
__u64 select_busy_cpu;
__u64 select_idle_cpu;
};
#ifdef __BPF__
void __arena *scx_task_data(struct task_struct *p);
int scx_task_init(__u64 data_size);
void __arena *scx_task_alloc(struct task_struct *p);
void scx_task_free(struct task_struct *p);
void scx_arena_subprog_init(void);
int scx_alloc_init(struct scx_allocator *alloc, __u64 data_size);
u64 scx_alloc_internal(struct scx_allocator *alloc);
int scx_alloc_free_idx(struct scx_allocator *alloc, __u64 idx);
#endif /* __BPF__ */