Skip to content

Commit 4e0e41e

Browse files
committed
重写 buddy 分配器与内存统计机制, 增加页引用计数机制.
1 parent 5c66b7d commit 4e0e41e

File tree

10 files changed

+974
-905
lines changed

10 files changed

+974
-905
lines changed

src/arch/x86_64/task/sched_x64.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,19 +70,22 @@ void calibrate_tsc_with_hpet() {
7070
uint64_t ns_end = nano_time();
7171
uint64_t delta_tsc = tsc_end - tsc_start;
7272
uint64_t delta_ns = ns_end - ns_start;
73-
if (delta_tsc == 0 || delta_ns == 0)
73+
if (delta_tsc == 0 || delta_ns == 0) {
7474
return;
75+
}
7576
arch_current_cpu()->arch_data.tsc_conv_shift = 22;
7677
arch_current_cpu()->arch_data.tsc_conv_mul =
7778
(uint32_t)((delta_ns << arch_current_cpu()->arch_data.tsc_conv_shift) / delta_tsc);
7879
arch_current_cpu()->arch_data.tsc_base_tsc = read_tsc();
7980
arch_current_cpu()->arch_data.tsc_base_ns = nano_time();
8081
uint64_t freq_hz = (delta_tsc * 1000000000ull) / delta_ns;
81-
if (is_bsp)
82+
if (is_bsp) {
8283
kinfo("Estimated TSC frequency: %llu MHz", freq_hz / 1000 / 1000);
84+
}
8385
end:
84-
if (is_bsp)
86+
if (is_bsp) {
8587
kinfo("%s clock time %llu", cpu_has_rdtsc() ? "TSC" : "HPET", sched_clock());
88+
}
8689
spin_unlock(tsc_lock);
8790
}
8891

src/include/mem/bitmap.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,5 @@ void bitmap_set_range(Bitmap *bitmap, size_t start, size_t end, bool value);
2020
size_t bitmap_find_range(Bitmap *bitmap, size_t length, bool value);
2121

2222
size_t bitmap_find_range_from(Bitmap *bitmap, size_t length, bool value, size_t start_from);
23+
24+
Bitmap *get_usable_regions();

src/include/mem/buddy.h

Lines changed: 34 additions & 241 deletions
Original file line numberDiff line numberDiff line change
@@ -1,274 +1,67 @@
11
#pragma once
22

3-
#define MAX_ORDER 20
3+
#define MAX_ORDER 31
4+
#define MIN_ORDER 12 // 4KB = 2^12
5+
#define ORDER_COUNT (MAX_ORDER - MIN_ORDER)
46

5-
// Zone 边界(物理地址)
6-
#define ZONE_DMA_END (16UL << 20) // 16MB
7-
#define ZONE_DMA32_END (4UL << 30) // 4GB
7+
// Zone 边界
8+
#define ZONE_DMA_END (16UL << 20) // 16MB
9+
#define ZONE_DMA32_END (4UL << 30) // 4GB
810

9-
#define GFP_DMA (1 << 0) // 必须从 ZONE_DMA 分配
10-
#define GFP_DMA32 (1 << 1) // 可以从 ZONE_DMA32 分配
11-
#define GFP_KERNEL (1 << 2) // 内核普通分配
12-
#define GFP_ATOMIC (1 << 3) // 原子分配,不能睡眠
13-
#define GFP_NOWAIT (1 << 4) // 不等待,快速失败
11+
// GFP 标志
12+
#define GFP_DMA (1 << 0)
13+
#define GFP_DMA32 (1 << 1)
14+
#define GFP_KERNEL (1 << 2)
15+
#define GFP_ATOMIC (1 << 3)
16+
#define GFP_NOWAIT (1 << 4)
1417

15-
// 常用组合
1618
#define GFP_KERNEL_NORMAL (GFP_KERNEL)
17-
#define GFP_KERNEL_DMA (GFP_KERNEL | GFP_DMA)
18-
#define GFP_KERNEL_DMA32 (GFP_KERNEL | GFP_DMA32)
19-
20-
#define PG_reserved 0
21-
#define PG_slab 1
22-
#define PG_buddy 2
23-
#define PG_compound 3
24-
#define PG_head 4
25-
#define PG_dirty 5
26-
#define PG_lru 6
27-
28-
#define PCPU_CACHE_LOW 4
29-
#define PCPU_CACHE_HIGH 32
30-
#define PCPU_BATCH 8
31-
32-
// 页面标志操作
33-
#define PageBuddy(page) test_bit(PG_buddy, &(page)->flags)
34-
#define SetPageBuddy(page) set_bit(PG_buddy, &(page)->flags)
35-
#define ClearPageBuddy(page) clear_bit(PG_buddy, &(page)->flags)
36-
37-
#define PageCompound(page) test_bit(PG_compound, &(page)->flags)
38-
#define SetPageCompound(page) set_bit(PG_compound, &(page)->flags)
39-
#define ClearPageCompound(page) clear_bit(PG_compound, &(page)->flags)
40-
41-
#define PageHead(page) test_bit(PG_head, &(page)->flags)
42-
#define SetPageHead(page) set_bit(PG_head, &(page)->flags)
43-
#define ClearPageHead(page) clear_bit(PG_head, &(page)->flags)
44-
45-
#define PageReserved(page) test_bit(PG_reserved, &(page)->flags)
46-
#define SetPageReserved(page) set_bit(PG_reserved, &(page)->flags)
47-
#define ClearPageReserved(page) clear_bit(PG_reserved, &(page)->flags)
48-
49-
#define pfn_to_page(pfn) (&mem_map[(pfn) - min_pfn])
50-
#define page_to_pfn(page) ((uint64_t)((page) - mem_map) + min_pfn)
51-
#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
52-
#define phys_to_page(phys) pfn_to_page((phys) >> PAGE_SHIFT)
53-
#define virt_to_page(virt) phys_to_page(virt_to_phys(virt))
54-
#define page_to_virt(page) phys_to_virt(page_to_phys(page))
19+
#define GFP_KERNEL_DMA (GFP_KERNEL | GFP_DMA)
20+
#define GFP_KERNEL_DMA32 (GFP_KERNEL | GFP_DMA32)
5521

5622
#include "lock.h"
5723
#include "types.h"
5824

25+
typedef struct buddy_allocator {
26+
uintptr_t free_area[ORDER_COUNT];
27+
spin_t lock;
28+
} buddy_allocator_t;
29+
5930
enum zone_type {
6031
#if defined(__x86_64__)
61-
ZONE_DMA, // 0-16MB,用于传统 ISA DMA
32+
ZONE_DMA, // 0-16MB
6233
#endif
63-
ZONE_DMA32, // 0-4GB,用于 32 位 DMA
64-
ZONE_NORMAL, // 正常内存
34+
ZONE_DMA32, // 0-4GB
35+
ZONE_NORMAL, // 4GB+
6536
__MAX_NR_ZONES
6637
};
6738

68-
extern const char *zone_names[__MAX_NR_ZONES];
69-
70-
enum zone_type pfn_to_zone_type(uint64_t pfn);
71-
72-
typedef struct {
73-
volatile int counter;
74-
} atomic_t;
75-
76-
static inline void atomic_set(atomic_t *v, int i) {
77-
v->counter = i;
78-
}
79-
80-
static inline int atomic_read(atomic_t *v) {
81-
return v->counter;
82-
}
83-
84-
static inline void atomic_inc(atomic_t *v) {
85-
__sync_add_and_fetch(&v->counter, 1);
86-
}
87-
88-
static inline int atomic_dec_and_test(atomic_t *v) {
89-
return __sync_sub_and_fetch(&v->counter, 1) == 0;
90-
}
91-
92-
static inline void atomic_add(int i, atomic_t *v) {
93-
__sync_add_and_fetch(&v->counter, i);
94-
}
95-
96-
static inline void atomic_sub(int i, atomic_t *v) {
97-
__sync_sub_and_fetch(&v->counter, i);
98-
}
99-
100-
typedef struct page {
101-
atomic_t _refcount;
102-
uint64_t flags;
103-
104-
union {
105-
struct {
106-
struct page *next;
107-
struct page *prev;
108-
} lru;
109-
struct {
110-
void *private;
111-
};
112-
};
113-
114-
unsigned char order;
115-
uint32_t compound_nr;
116-
117-
// 新增:所属的 zone
118-
unsigned char zone_id;
119-
120-
uint32_t magic;
121-
} page_t;
122-
123-
#define PAGE_MAGIC 0xDEADBEEF
124-
125-
enum zone_stat_item {
126-
NR_FREE_PAGES, // 空闲页数
127-
NR_ALLOC_PAGES, // 已分配页数
128-
NR_ACTIVE, // 活跃页数
129-
NR_INACTIVE, // 非活跃页数
130-
NR_ZONE_STATS
131-
};
132-
133-
typedef struct zone_stats {
134-
atomic_t count[NR_ZONE_STATS];
135-
} zone_stats_t;
136-
137-
typedef struct free_area {
138-
struct page *free_list;
139-
uint64_t nr_free;
140-
} free_area_t;
141-
142-
typedef struct per_cpu_pages {
143-
struct page *pages[PCPU_CACHE_HIGH];
144-
int count;
145-
int low; // 低水位
146-
int high; // 高水位
147-
int batch; // 批量操作数量
148-
149-
uint64_t alloc_hits;
150-
uint64_t alloc_misses;
151-
uint64_t free_hits;
152-
uint64_t free_misses;
153-
} per_cpu_pages_t;
154-
39+
// Zone 结构
15540
typedef struct zone {
156-
// Buddy 分配器
157-
free_area_t free_area[MAX_ORDER];
158-
159-
// Zone 范围
41+
buddy_allocator_t allocator;
16042
uint64_t zone_start_pfn;
16143
uint64_t zone_end_pfn;
162-
uint64_t spanned_pages; // 跨越的页数(包括空洞)
163-
uint64_t present_pages; // 物理存在的页数
164-
uint64_t managed_pages; // 可管理的页数
165-
166-
// Zone 类型
44+
uint64_t managed_pages;
45+
uint64_t free_pages;
16746
enum zone_type type;
16847
const char *name;
169-
170-
// 统计信息
171-
zone_stats_t vm_stat;
172-
173-
// Per-CPU 页面缓存(每个CPU一个)
174-
per_cpu_pages_t *per_cpu_pageset;
175-
176-
// 锁
177-
spin_t lock;
178-
179-
// 链表节点(用于遍历所有zone)
180-
struct zone *next;
18148
} zone_t;
18249

183-
typedef struct zonelist {
184-
zone_t *zones[__MAX_NR_ZONES]; // 按优先级排序的 zone 列表
185-
int nr_zones; // zone 数量
186-
} zonelist_t;
187-
188-
extern page_t *mem_map;
189-
extern uint64_t max_pfn;
190-
extern uint64_t min_pfn;
19150
extern zone_t *zones[__MAX_NR_ZONES];
19251
extern int nr_zones;
193-
194-
// 获取页面所属的 zone
195-
#define page_zone(page) (zones[(page)->zone_id])
196-
197-
static inline void set_bit(int nr, volatile uint64_t *addr) {
198-
*addr |= (1UL << nr);
199-
}
200-
201-
static inline void clear_bit(int nr, volatile uint64_t *addr) {
202-
*addr &= ~(1UL << nr);
203-
}
204-
205-
static inline int test_bit(int nr, const volatile uint64_t *addr) {
206-
return (*addr >> nr) & 1;
207-
}
208-
209-
// 引用计数操作
210-
static inline int page_ref_count(page_t *page) {
211-
return atomic_read(&page->_refcount);
212-
}
213-
214-
static inline void set_page_refcounted(page_t *page) {
215-
atomic_set(&page->_refcount, 1);
216-
}
217-
218-
static inline void get_page(page_t *page) {
219-
atomic_inc(&page->_refcount);
220-
}
221-
222-
static inline bool put_page_testzero(page_t *page) {
223-
return atomic_dec_and_test(&page->_refcount);
224-
}
225-
226-
// 复合页操作
227-
static inline void set_compound_order(page_t *page, uint32_t order) {
228-
page->order = order;
229-
page->compound_nr = 1U << order;
230-
}
231-
232-
static inline uint32_t compound_order(page_t *page) {
233-
if (!PageHead(page))
234-
return 0;
235-
return page->order;
236-
}
237-
238-
// Zone 统计操作
239-
static inline void zone_page_state_add(long delta, zone_t *zone, enum zone_stat_item item) {
240-
atomic_add(delta, &zone->vm_stat.count[item]);
241-
}
242-
243-
static inline uint64_t zone_page_state(zone_t *zone, enum zone_stat_item item) {
244-
return atomic_read(&zone->vm_stat.count[item]);
245-
}
52+
extern const char *zone_names[__MAX_NR_ZONES];
24653

24754
// 初始化
248-
void zones_init(uint64_t memory_size);
55+
void buddy_init(void);
24956
void add_memory_region(uintptr_t start, uintptr_t end, enum zone_type type);
250-
void percpu_pagecache_init();
251-
252-
// 分配(多 zone 版本)
253-
page_t *alloc_pages(uint32_t gfp_flags, uint32_t order);
254-
#define alloc_page(gfp) alloc_pages(gfp, 0)
25557

256-
// 兼容接口(默认从 NORMAL zone
257-
#define __alloc_pages(order) alloc_pages(GFP_KERNEL, order)
258-
#define __alloc_page() alloc_pages(GFP_KERNEL, 0)
58+
// 分配/释放(底层接口
59+
uintptr_t buddy_alloc_zone(zone_t *zone, size_t count);
60+
void buddy_free_zone(zone_t *zone, uintptr_t addr, size_t order);
25961

260-
// 释放
261-
void __free_pages(page_t *page, uint32_t order);
262-
#define free_page(page) __free_pages(page, 0)
263-
264-
// Zone 查询
62+
// 辅助函数
26563
zone_t *get_zone(enum zone_type type);
26664
bool zone_has_memory(zone_t *zone);
65+
enum zone_type phys_to_zone_type(uintptr_t phys);
26766

268-
// Zonelist 构建
269-
void build_zonelist(zonelist_t *zl, uint32_t gfp_flags);
270-
271-
void init_frame_buddy(uint64_t memory_size);
272-
273-
uintptr_t buddy_alloc_frames(size_t count);
274-
void buddy_free_frames(uintptr_t addr, size_t count);
67+
void free_frames_released(uintptr_t addr, size_t count);

src/include/mem/frame.h

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,12 @@
1111
#include "metadata.h"
1212
#include "types.h"
1313

14-
typedef struct {
15-
void *allocator;
16-
size_t total_frames;
17-
size_t origin_frames;
18-
size_t usable_frames;
19-
} FrameAllocator;
20-
21-
extern FrameAllocator frame_allocator;
22-
2314
uint64_t get_memory_size();
2415

2516
void init_frame();
2617
uint64_t alloc_frames(size_t count);
27-
uint64_t alloc_frames_2M(size_t count);
28-
uint64_t alloc_frames_1G(size_t count);
2918
void free_frames(uint64_t addr, size_t count);
3019
void free_frame(uint64_t addr);
31-
void free_frames_2M(uint64_t addr);
32-
void free_frames_1G(uint64_t addr);
3320

3421
uint64_t get_physical_memory_offset();
3522
void *phys_to_virt(uint64_t phys_addr);

src/include/mem/page_ref.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#pragma once
2+
3+
#include "types.h"
4+
5+
typedef struct page {
6+
int refcount;
7+
// TODO
8+
} page_t;
9+
10+
extern page_t *page_maps;
11+
12+
void page_ref_init();
13+
14+
page_t *get_page_ref(uint64_t addr);
15+
16+
int page_refcount_read(page_t *page);
17+
void page_ref(page_t *page);
18+
bool page_try_ref(page_t *page);
19+
int page_unref(page_t *page);
20+
bool page_try_release_last(page_t *page);
21+
bool page_can_free(page_t *page);
22+
23+
bool address_ref(uint64_t addr);
24+
void address_unref(uint64_t addr);
25+
bool address_can_free(uint64_t addr);
26+
bool address_is_managed(uint64_t addr);
27+
void address_release(uint64_t addr);

0 commit comments

Comments
 (0)