1 #include <lunaix/mm/page.h>
2 #include <lunaix/mm/pmm.h>
3 #include <lunaix/status.h>
5 // This is a very large array...
6 static struct pp_struct pm_table[PM_BMP_MAX_SIZE];
11 pmm_mark_page_free(ptr_t ppn)
13 pm_table[ppn].ref_counts = 0;
17 pmm_mark_page_occupied(pid_t owner, ptr_t ppn, pp_attr_t attr)
20 (struct pp_struct){ .owner = owner, .ref_counts = 1, .attr = attr };
24 pmm_mark_chunk_free(ptr_t start_ppn, size_t page_count)
26 for (size_t i = start_ppn; i < start_ppn + page_count && i < max_pg; i++) {
27 pm_table[i].ref_counts = 0;
32 pmm_mark_chunk_occupied(pid_t owner,
37 for (size_t i = start_ppn; i < start_ppn + page_count && i < max_pg; i++) {
39 (struct pp_struct){ .owner = owner, .ref_counts = 1, .attr = attr };
43 // 我们跳过位于0x0的页。我们不希望空指针是指向一个有效的内存空间。
44 #define LOOKUP_START 1
46 volatile size_t pg_lookup_ptr;
49 pmm_init(ptr_t mem_upper_lim)
51 max_pg = (PG_ALIGN(mem_upper_lim) >> 12);
53 pg_lookup_ptr = LOOKUP_START;
55 // mark all as occupied
56 for (size_t i = 0; i < PM_BMP_MAX_SIZE; i++) {
58 (struct pp_struct){ .owner = 0, .attr = 0, .ref_counts = 1 };
63 pmm_alloc_cpage(pid_t owner, size_t num_pages, pp_attr_t attr)
68 while (p2 < max_pg && p2 - p1 < num_pages) {
69 (!(&pm_table[p2])->ref_counts) ? (p2++) : (p1 = ++p2);
72 if (p2 == max_pg && p2 - p1 < num_pages) {
76 pmm_mark_chunk_occupied(owner, p1, num_pages, attr);
82 pmm_alloc_page(pid_t owner, pp_attr_t attr)
84 // Next fit approach. Maximize the throughput!
85 ptr_t good_page_found = (ptr_t)NULL;
86 size_t old_pg_ptr = pg_lookup_ptr;
87 size_t upper_lim = max_pg;
89 while (!good_page_found && pg_lookup_ptr < upper_lim) {
90 pm = &pm_table[pg_lookup_ptr];
92 if (!pm->ref_counts) {
93 *pm = (struct pp_struct){ .attr = attr,
96 good_page_found = pg_lookup_ptr << 12;
101 // We've searched the interval [old_pg_ptr, max_pg) but failed
102 // may be chances in [1, old_pg_ptr) ?
104 if (pg_lookup_ptr >= upper_lim && old_pg_ptr != LOOKUP_START) {
105 upper_lim = old_pg_ptr;
106 pg_lookup_ptr = LOOKUP_START;
107 old_pg_ptr = LOOKUP_START;
111 if (!good_page_found) {
112 __current->k_status = LXOUTOFMEM;
114 return good_page_found;
118 pmm_free_page(pid_t owner, ptr_t page)
120 struct pp_struct* pm = &pm_table[page >> 12];
122 // Is this a MMIO mapping or double free?
123 if ((page >> 12) >= max_pg || !(pm->ref_counts)) {
128 if ((pm->attr & PP_FGLOCKED)) {
132 // TODO: 检查权限,保证:1) 只有正在使用该页(包括被分享者)的进程可以释放;
139 pmm_ref_page(pid_t owner, ptr_t page)
141 (void)owner; // TODO: do smth with owner
143 u32_t ppn = page >> 12;
145 if (ppn >= PM_BMP_MAX_SIZE) {
149 struct pp_struct* pm = &pm_table[ppn];
150 if (ppn >= max_pg || !pm->ref_counts) {
161 u32_t ppn = pa >> 12;
163 if (ppn >= PM_BMP_MAX_SIZE) {
167 return &pm_table[ppn];