Skip to content

Commit 02f91ad

Browse files
committedMay 11, 2024··
pmm: Implemented nb_alloc() for NBBS.
Signed-off-by: TunaCici <36923239+TunaCici@users.noreply.github.com>
1 parent c800d22 commit 02f91ad

File tree

3 files changed

+98
-15
lines changed

3 files changed

+98
-15
lines changed
 

‎Kernel/Include/Memory/NBBS.h

+27-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
#define BUSY (OCC | OCC_LEFT | OCC_RIGHT)
3232

3333
#define EXP2(n) (0x1 << (n))
34-
#define LOG2(n) (64 - __builtin_clzll(n)) // 64 bit
34+
#define LOG2_LOWER(n) (64 - __builtin_clzll(n) - 1) // 64 bit
3535
#define CAS(addr, cmp, val) __atomic_compare_exchange (addr, cmp, val, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
3636

3737
/*
@@ -44,6 +44,14 @@ int nb_init(uint64_t base_addr, uint64_t size);
4444
void* nb_alloc(uint64_t size);
4545
void* nb_free(void *addr);
4646

47+
/*
48+
* Private APIs
49+
*
50+
* TODO: Explain.
51+
*/
52+
53+
uint32_t try_alloc(uint32_t node);
54+
4755
/*
4856
* Helpers
4957
*
@@ -84,3 +92,21 @@ static inline uint8_t is_free(uint8_t val)
8492
{
8593
return !(val & BUSY);
8694
}
95+
96+
/* TODO: Ugly code; refactor */
97+
static inline uint32_t leftmost(uint32_t node, uint32_t depth)
98+
{
99+
/* Index to level */
100+
uint32_t level = LOG2_LOWER(node);
101+
102+
/* Size (in terms of leaf size) */
103+
uint64_t block_size = EXP2(depth - level);
104+
105+
/* Offset within level */
106+
uint64_t offset = node % EXP2(level);
107+
108+
/* Leftmost leaf */
109+
uint32_t leftmost_leaf = EXP2(depth) + offset * block_size;
110+
111+
return leftmost_leaf;
112+
}

‎Kernel/Main.c

+12-2
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,20 @@ void kmain(boot_sysinfo* boot_params)
8181
/* 2. Init NBBS */
8282
klog("[kmain] Initializing NBBS...\n");
8383

84-
if (nb_init(mem_start, mem_end - mem_start)) {
84+
if (nb_init(mem_start, 32 * 1024)) {
8585
klog("[kmain] Failed to initialize NBBS ;(\n");
8686
} else {
87-
klog("[kmain] Initialized NBBS!\n");
87+
klog("[kmain] Initialized NBBS (%u KiB)!\n", 64u);
88+
}
89+
90+
klog("[kmain] nb_alloc\n");
91+
92+
uint64_t *bruh = nb_alloc(4096);
93+
94+
if (bruh) {
95+
klog("[kmain] nb_alloc ok\n");
96+
} else {
97+
klog("[kmain] nb_alloc fail\n");
8898
}
8999

90100
/* 2. Init PMM */

‎Kernel/Memory/NBBS.c

+59-12
Original file line numberDiff line numberDiff line change
@@ -15,44 +15,46 @@
1515

1616
static volatile uint8_t *tree = 0;
1717
static volatile uint32_t *index = 0;
18+
static volatile uint64_t base_address = 0;
1819

1920
static volatile uint32_t depth = 0;
2021
static volatile uint64_t tree_size = 0; /* bytes */
2122
static volatile uint64_t index_size = 0; /* bytes */
2223

2324
static volatile uint64_t total_memory = 0;
24-
static volatile uint64_t max_level = 0; /* [0, depth] */
25+
static volatile uint64_t max_level = 0;
2526
static volatile uint64_t min_size = 0;
2627
static volatile uint64_t max_size = 0;
2728

28-
int nb_init(uint64_t base_addr, uint64_t size)
29+
int nb_init(uint64_t base, uint64_t size)
2930
{
30-
if (size < min_size) {
31+
if (base == 0 | size == 0) {
3132
return 1;
3233
}
3334

34-
if (base_addr == 0 | size == 0) {
35+
if (size < min_size) {
3536
return 1;
3637
}
3738

3839
/* Setup */
40+
base_address = base;
3941
total_memory = size;
4042
min_size = PAGE_SIZE;
41-
depth = LOG2(total_memory / min_size) - 1;
43+
depth = LOG2_LOWER(total_memory / min_size);
4244
max_level = 0;
43-
max_size = (EXP2(depth - max_level) * min_size);
45+
max_size = EXP2(depth - max_level) * min_size;
4446

4547
/* Calculate required tree size */
46-
uint32_t total_nodes = 1; // we start at idx 1
47-
for (uint32_t i = 0; i < depth; i++) {
48-
total_nodes += (size / (EXP2(i) * min_size));
48+
uint32_t total_nodes = 1; // we have garbage node at idx 0
49+
for (uint32_t i = 0; i <= depth; i++) {
50+
total_nodes += (total_memory / (EXP2(i) * min_size));
4951
}
5052

5153
/* Calculate required index size */
52-
uint32_t total_elems = (size / min_size);
54+
uint32_t total_pages = (total_memory / min_size);
5355

54-
tree_size = total_nodes * 1; // each node is 1 byte
55-
index_size = total_elems * 4; // each elem is 4 byte
56+
tree_size = total_nodes * 1; // each node is 1 byte
57+
index_size = total_pages * 4; // each page id is 4 byte
5658

5759
/* Allocate */
5860
uint32_t req_pages = (tree_size + PAGE_SIZE - 1) / PAGE_SIZE;
@@ -76,9 +78,54 @@ int nb_init(uint64_t base_addr, uint64_t size)
7678
return 0;
7779
}
7880

81+
uint32_t try_alloc(uint32_t node)
82+
{
83+
return 1;
84+
}
85+
7986
void* nb_alloc(uint64_t size)
8087
{
88+
if (max_size < size) {
89+
return 0;
90+
}
8191

92+
if (size < min_size) {
93+
size = min_size;
94+
}
95+
96+
uint32_t level = LOG2_LOWER(total_memory / size);
97+
98+
if (depth < level) {
99+
level = depth;
100+
}
101+
102+
/* Range of nodes at target level */
103+
uint32_t start_node = EXP2(level);
104+
uint32_t end_node = EXP2(level + 1);
105+
106+
for (uint32_t i = start_node; i < end_node; i++) {
107+
if (is_free(tree[i])) {
108+
uint32_t failed_at = try_alloc(i);
109+
110+
if (!failed_at) {
111+
/* TODO: Explain what's going on here */
112+
uint32_t leaf = leftmost(i, depth) - EXP2(depth);
113+
index[leaf] = i;
114+
115+
return (void*) (base_address + leaf * min_size);
116+
} else {
117+
/* Skip the entire subtree [of failed] */
118+
uint32_t curr_level = LOG2_LOWER(i);
119+
uint32_t fail_level = LOG2_LOWER(failed_at);
120+
121+
uint32_t d = EXP2(curr_level - fail_level);
122+
i = (failed_at + 1) * d;
123+
}
124+
}
125+
}
126+
127+
return (void*) 0;
128+
82129
}
83130

84131
void* nb_free(void *addr)

0 commit comments

Comments
 (0)
Please sign in to comment.