Skip to content
This repository was archived by the owner on Dec 25, 2025. It is now read-only.

Commit 6813261

Browse files
committed
Reads from HeapMap are now lockless
1 parent a7f8680 commit 6813261

File tree

2 files changed

+41
-32
lines changed

2 files changed

+41
-32
lines changed

kernel/include/memory/heap.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,11 @@ class HeapMap {
5454

5555
struct Node {
5656
// Can be Node* (Levels 4-2)
57-
void* entries[MASK + 1];
57+
std::atomic<void*> entries[MASK + 1];
5858
};
5959

6060
private:
61-
static Node* root;
61+
static std::atomic<Node*> root;
6262
static SpinLock lock;
6363
};
6464

kernel/src/memory/heap.cpp

Lines changed: 39 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66
#include "memory/vmm.hpp"
77
#include "libs/math.hpp"
88
#include <string.h>
9+
#include <atomic>
910

1011
namespace kernel::memory {
11-
HeapMap::Node* HeapMap::root = nullptr;
12+
std::atomic<HeapMap::Node*> HeapMap::root = nullptr;
1213
SpinLock HeapMap::lock;
1314

1415
Slab* MetadataAllocator::alloc() {
@@ -56,69 +57,77 @@ void HeapMap::set(void* ptr, Slab* meta) {
5657
LockGuard guard(lock);
5758
uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);
5859

59-
if (!root) {
60-
root = reinterpret_cast<Node*>(VirtualManager::allocate(1));
61-
if (!root) {
62-
PANIC("Out of Memory!");
63-
}
64-
}
60+
Node* l4 = root.load(std::memory_order_relaxed);
6561

66-
Node* l4 = root;
62+
if (!l4) {
63+
l4 = reinterpret_cast<Node*>(VirtualManager::allocate(1));
64+
memset(l4, 0, PAGE_SIZE_4K);
65+
66+
root.store(l4, std::memory_order_release);
67+
}
6768

6869
// Level 4 -> Level 3
6970
uintptr_t i4 = (addr >> 39) & MASK;
70-
if (!l4->entries[i4]) {
71-
l4->entries[i4] = VirtualManager::allocate(1);
72-
}
71+
Node* l3 = static_cast<Node*>(l4->entries[i4].load(std::memory_order_relaxed));
72+
if (!l3) {
73+
l3 = reinterpret_cast<Node*>(VirtualManager::allocate(1));
74+
memset(l3, 0, PAGE_SIZE_4K);
7375

74-
Node* l3 = reinterpret_cast<Node*>(l4->entries[i4]);
76+
l4->entries[i4].store(l3, std::memory_order_release);
77+
}
7578

7679
// Level 3 -> Level 2
7780
uintptr_t i3 = (addr >> 30) & MASK;
78-
if (!l3->entries[i3]) {
79-
l3->entries[i3] = VirtualManager::allocate(1);
80-
}
81+
Node* l2 = static_cast<Node*>(l3->entries[i3].load(std::memory_order_relaxed));
82+
if (!l2) {
83+
l2 = reinterpret_cast<Node*>(VirtualManager::allocate(1));
84+
memset(l2, 0, PAGE_SIZE_4K);
8185

82-
Node* l2 = reinterpret_cast<Node*>(l3->entries[i3]);
86+
l3->entries[i3].store(l2, std::memory_order_release);
87+
}
8388

8489
// Level 2 -> Level 1
8590
uintptr_t i2 = (addr >> 21) & MASK;
86-
if (!l2->entries[i2]) {
87-
l2->entries[i2] = VirtualManager::allocate(1);
91+
Node* l1 = static_cast<Node*>(l2->entries[i2].load(std::memory_order_relaxed));
92+
if (!l1) {
93+
l1 = reinterpret_cast<Node*>(VirtualManager::allocate(1));
94+
memset(l1, 0, PAGE_SIZE_4K);
95+
96+
l2->entries[i2].store(l1, std::memory_order_release);
8897
}
8998

90-
Node* l1 = reinterpret_cast<Node*>(l2->entries[i2]);
91-
uintptr_t i1 = (addr >> 12) & MASK;
92-
l1->entries[i1] = reinterpret_cast<void*>(meta);
99+
uintptr_t i1 = (addr >> 12) & MASK;
100+
l1->entries[i1].store(meta, std::memory_order_release);
93101
}
94102

95103
Slab* HeapMap::get(void* ptr) {
96104
uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);
97105

98-
if (!root) {
106+
Node* l4 = root.load(std::memory_order_acquire);
107+
if (!l4) {
99108
return nullptr;
100109
}
101110

102-
Node* l4 = root;
103-
Node* l3 = reinterpret_cast<Node*>(l4->entries[(addr >> 39) & MASK]);
104-
111+
uintptr_t i4 = (addr >> 39) & MASK;
112+
Node* l3 = static_cast<Node*>(l4->entries[i4].load(std::memory_order_acquire));
105113
if (!l3) {
106114
return nullptr;
107115
}
108116

109-
Node* l2 = reinterpret_cast<Node*>(l3->entries[(addr >> 30) & MASK]);
110-
117+
uintptr_t i3 = (addr >> 30) & MASK;
118+
Node* l2 = static_cast<Node*>(l3->entries[i3].load(std::memory_order_acquire));
111119
if (!l2) {
112120
return nullptr;
113121
}
114122

115-
Node* l1 = reinterpret_cast<Node*>(l2->entries[(addr >> 21) & MASK]);
116-
123+
uintptr_t i2 = (addr >> 21) & MASK;
124+
Node* l1 = static_cast<Node*>(l2->entries[i2].load(std::memory_order_acquire));
117125
if (!l1) {
118126
return nullptr;
119127
}
120128

121-
return reinterpret_cast<Slab*>(l1->entries[(addr >> 12) & MASK]);
129+
uintptr_t i1 = (addr >> 12) & MASK;
130+
return static_cast<Slab*>(l1->entries[i1].load(std::memory_order_acquire));
122131
}
123132

124133
void HeapTLB::init() {

0 commit comments

Comments
 (0)