fix: bugs

This commit is contained in:
Faynot
2026-07-06 00:25:49 +03:00
parent 1b38c7f445
commit c092a81331
23 changed files with 2502 additions and 123 deletions

105
kernel/docs/allocator.md Normal file
View File

@@ -0,0 +1,105 @@
# Аллокатор кучи
**Файл**: `src/mem/allocator.rs`
Slab-аллокатор со spinlock-синхронизацией и fallback bump-аллокацией для больших блоков.
---
## Примитив синхронизации: `Locked<A>`
Самодельный spinlock (альтернатива `spin::Mutex`).
```rust
pub struct Locked<A> {
inner: UnsafeCell<A>,
lock: AtomicBool,
}
```
- `new(inner)` — создаёт с unlocked состоянием
- `lock() -> LockedGuard<'_, A>` — CAS-цикл на `AtomicBool` (спин-ожидание)
### LockedGuard
- `Deref`/`DerefMut` — доступ к внутренним данным
- `Drop``store(false, Release)` — освобождение блокировки
`unsafe impl<A> Sync for Locked<A>` — разработчик гарантирует корректность.
---
## SlabAllocator
```rust
pub struct SlabAllocator {
list_heads: [Option<&'static mut ListNode>; 9], // slab free list
large_block_free: Option<&'static mut LargeBlockNode>, // free list для >2048
heap_start: usize,
heap_end: usize,
next_bump: usize,
}
```
### Slab классы
```rust
const BLOCK_SIZES: &[usize] = &[8, 16, 32, 64, 128, 256, 512, 1024, 2048];
```
9 классов — степени двойки от 8 до 2048.
### ListNode / LargeBlockNode
```rust
struct ListNode {
next: Option<&'static mut ListNode>,
}
struct LargeBlockNode {
size: usize,
next: Option<&'static mut LargeBlockNode>,
}
```
Односвязные списки свободных блоков.
### `init(&mut self, start, size)`
Устанавливает границы кучи: `heap_start = start`, `heap_end = start + size`, `next_bump = start`.
### `list_index(layout) -> Option<usize>`
Находит индекс наименьшего slab-класса, покрывающего `max(size, align)`.
Пример: layout size=20, align=8 → блок 20 > 16, следующий 32 → index 3 (32 байта).
### `fallback_alloc(&mut self, layout) -> *mut u8`
1. Проверяет `large_block_free` — если есть подходящий блок, отдаёт его
2. Иначе bump-аллокация: выравнивание, проверка `next_bump + size <= heap_end`, возврат `next_bump`
3. При OOM возвращает null
---
## Глобальный аллокатор
```rust
#[global_allocator]
pub static ALLOCATOR: Locked<SlabAllocator>;
```
### `GlobalAlloc::alloc(&self, layout) -> *mut u8`
1. Lock allocator
2. Если `layout.size()` влезает в slab класс:
- Находит `list_index`
- Если free list не пуст: pop голову, вернуть указатель
- Если пуст: `fallback_alloc(layout)` но с размером slab-блока (не `layout.size()`)
3. Для блоков > 2048: сразу `fallback_alloc(layout)`
### `GlobalAlloc::dealloc(&self, ptr, layout)`
1. Lock allocator
2. Для slab-sized: push обратно в slab free list как ListNode
3. Для больших: push в large_block_free как LargeBlockNode