From dd5886e642fdf976c3e0b82ef1f82b3e04e12b7c Mon Sep 17 00:00:00 2001 From: zhangzheng <1358745329@qq.com> Date: Sat, 6 Apr 2024 16:08:27 +0000 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=86=85=E5=AD=98=E7=AE=A1?= =?UTF-8?q?=E7=90=86=EF=BC=8C=E4=BD=86=E6=98=AF=E8=BF=98=E5=AD=98=E5=9C=A8?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 25 +- mkrtos_bootstrap/bsp/AARCH64_QEMU/link.lds | 2 +- mkrtos_bootstrap/bsp/AARCH64_QEMU/link.lds.S | 2 +- mkrtos_configs/aarch64_qemu_defconfig | 5 +- mkrtos_knl/CMakeLists.txt | 4 + mkrtos_knl/Kconfig | 3 + mkrtos_knl/arch/aarch64/aarch64_qemu/arch.c | 7 +- mkrtos_knl/arch/aarch64/aarch64_qemu/arch.h | 1 + mkrtos_knl/arch/aarch64/aarch64_qemu/vector.S | 7 +- mkrtos_knl/arch/aarch64/early_boot.c | 82 +- mkrtos_knl/arch/aarch64/early_boot.h | 9 +- mkrtos_knl/arch/aarch64/link.lds | 8 +- mkrtos_knl/arch/aarch64/link.lds.S | 8 +- mkrtos_knl/arch/aarch64/mm_space.c | 9 +- mkrtos_knl/arch/aarch64/sche_arch.c | 2 +- mkrtos_knl/arch/aarch64/thread_aarch64.c | 4 +- mkrtos_knl/arch/aarch64/thread_armv8.c | 25 +- mkrtos_knl/inc/knl/kobject.h | 1 + mkrtos_knl/inc/knl/mm_space.h | 17 +- mkrtos_knl/inc/knl/mm_wrap.h | 1 + mkrtos_knl/inc/knl/prot.h | 1 + mkrtos_knl/inc/knl/thread.h | 21 +- mkrtos_knl/inc/knl/util.h | 2 +- mkrtos_knl/inc/knl/vma.h | 141 ++++ mkrtos_knl/inc/lib/types.h | 2 + mkrtos_knl/knl/CMakeLists.txt | 10 +- mkrtos_knl/knl/buddy.c | 36 +- mkrtos_knl/knl/elf64.c | 13 +- mkrtos_knl/knl/factory.c | 2 +- mkrtos_knl/knl/globals.c | 7 +- mkrtos_knl/knl/ipc.c | 2 +- mkrtos_knl/knl/mm/mln_func.h | 180 +++++ mkrtos_knl/knl/mm/mln_rbtree.c | 372 +++++++++ mkrtos_knl/knl/mm/mln_rbtree.h | 308 ++++++++ mkrtos_knl/knl/mm/mln_types.h | 69 ++ mkrtos_knl/knl/mm/mln_utils.h | 166 ++++ mkrtos_knl/knl/mm/rbtree_mm.c | 64 ++ mkrtos_knl/knl/mm/rbtree_mm.h | 5 + mkrtos_knl/knl/mm/vma.c | 723 ++++++++++++++++++ mkrtos_knl/knl/mm/vma_obj.c | 107 +++ mkrtos_knl/knl/mm/vma_obj.h | 2 + mkrtos_knl/knl/mm_wrap.c | 4 + mkrtos_knl/knl/slab.c | 5 + mkrtos_knl/knl/task.c | 4 + mkrtos_knl/knl/thread.c | 6 +- mkrtos_knl/knl/thread_knl.c | 12 +- mkrtos_knl/test/kthread_test.c | 2 + .../lib/libc_backend/inc/syscall_backend.h | 4 +- .../lib/libc_backend/src/aarch64/mm_backend.c | 79 ++ .../src/aarch64/syscall_backend.c | 16 +- mkrtos_user/lib/libc_backend/src/fd_map.c | 3 - mkrtos_user/lib/libc_backend/src/fs_backend.c | 1 + mkrtos_user/lib/sys/inc/u_arch.h | 2 + mkrtos_user/lib/sys/inc/u_prot.h | 3 +- mkrtos_user/lib/sys/inc/u_vmam.h | 32 + mkrtos_user/lib/sys/src/u_thread.c | 4 + mkrtos_user/lib/sys/src/u_vmam.c | 52 ++ mkrtos_user/server/init/src/cons.c | 6 +- mkrtos_user/server/init/src/main.c | 7 +- .../server/init/src/test/malloc_test.c | 13 + mkrtos_user/server/init/src/test/mm_test.c | 2 - mkrtos_user/server/init/src/test/test.h | 1 + 62 files changed, 2597 insertions(+), 116 deletions(-) create mode 100644 mkrtos_knl/inc/knl/vma.h create mode 100644 mkrtos_knl/knl/mm/mln_func.h create mode 100644 mkrtos_knl/knl/mm/mln_rbtree.c create mode 100644 mkrtos_knl/knl/mm/mln_rbtree.h create mode 100644 mkrtos_knl/knl/mm/mln_types.h create mode 100644 mkrtos_knl/knl/mm/mln_utils.h create mode 100644 mkrtos_knl/knl/mm/rbtree_mm.c create mode 100644 mkrtos_knl/knl/mm/rbtree_mm.h create mode 100644 mkrtos_knl/knl/mm/vma.c create mode 100644 mkrtos_knl/knl/mm/vma_obj.c create mode 100644 mkrtos_knl/knl/mm/vma_obj.h create mode 100644 mkrtos_user/lib/libc_backend/src/aarch64/mm_backend.c create mode 100644 mkrtos_user/lib/sys/inc/u_vmam.h create mode 100644 mkrtos_user/lib/sys/src/u_vmam.c create mode 100644 mkrtos_user/server/init/src/test/malloc_test.c diff --git a/.vscode/settings.json b/.vscode/settings.json index 4794f5afe..9ee75d92f 100755 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -34,8 +34,31 @@ "u_sys.h": "c", "arch.h": "c", "*.in": "c", - "buddy.h": "c" + "buddy.h": "c", + "thread_arch.h": "c", + "random": "c", + "chrono": "c", + "compare": "c", + "functional": "c", + "ratio": "c", + "tuple": "c", + "type_traits": "c", + "variant": "c", + "mln_rbtree.h": "c", + "rbtree_mm.h": "c", + "early_boot.h": "c", + "obj_space.h": "c", + "mm.h": "c", + "asm_config.h": "c", + "u_types.h": "c", + "err.h": "c", + "u_prot.h": "c", + "vma.h": "c", + "thread.h": "c", + "thread_knl.h": "c" }, "cortex-debug.showRTOS": false, "cortex-debug.variableUseNaturalFormat": false, + "C_Cpp.default.systemIncludePath": [""], + "C_Cpp.default.forcedInclude": ["${workspaceFolder}/build/autoconf.h"] } \ No newline at end of file diff --git a/mkrtos_bootstrap/bsp/AARCH64_QEMU/link.lds b/mkrtos_bootstrap/bsp/AARCH64_QEMU/link.lds index 0634f49c4..f2e480ae3 100644 --- a/mkrtos_bootstrap/bsp/AARCH64_QEMU/link.lds +++ b/mkrtos_bootstrap/bsp/AARCH64_QEMU/link.lds @@ -1,7 +1,7 @@ ENTRY(_start); SECTIONS { - . = 0x40000000 + 0x01000000; + . = 0x40000000 + 0x1000; _text = .; .text : { diff --git a/mkrtos_bootstrap/bsp/AARCH64_QEMU/link.lds.S b/mkrtos_bootstrap/bsp/AARCH64_QEMU/link.lds.S index 3a91cc4de..7d767c02f 100755 --- a/mkrtos_bootstrap/bsp/AARCH64_QEMU/link.lds.S +++ b/mkrtos_bootstrap/bsp/AARCH64_QEMU/link.lds.S @@ -7,7 +7,7 @@ SECTIONS * * 这里“.”表示location counter,当前位置 */ - . = CONFIG_KNL_DATA_ADDR + 0x01000000; + . = CONFIG_KNL_DATA_ADDR + 0x1000; /* * text代码段 */ diff --git a/mkrtos_configs/aarch64_qemu_defconfig b/mkrtos_configs/aarch64_qemu_defconfig index a51fde2f0..e2341f37e 100644 --- a/mkrtos_configs/aarch64_qemu_defconfig +++ b/mkrtos_configs/aarch64_qemu_defconfig @@ -6,8 +6,8 @@ CONFIG_KNL_INFO=y CONFIG_KNL_TEXT_ADDR=0x1000 CONFIG_KNL_TEXT_SIZE=0x100000 CONFIG_KNL_DATA_ADDR=0x40000000 -CONFIG_KNL_DATA_SIZE=0x800000 -CONFIG_KNL_OFFSET=0x1000 +CONFIG_KNL_DATA_SIZE=0x7c000000 +CONFIG_KNL_OFFSET=0x1000000 CONFIG_INIT_TASK_OFFSET=0x10000 CONFIG_BOOTFS_OFFSET=0x02000000 CONFIG_MK_MPU_CFG=n @@ -119,3 +119,4 @@ CONFIG_PAGE_SHIFT=12 CONFIG_MMU=y CONFIG_KNL_TEST=n CONFIG_ELF_LAUNCH=y +CONFIG_THREAD_MSG_BUG_LEN=4096 diff --git a/mkrtos_knl/CMakeLists.txt b/mkrtos_knl/CMakeLists.txt index 4e38858da..a71bcc9c7 100755 --- a/mkrtos_knl/CMakeLists.txt +++ b/mkrtos_knl/CMakeLists.txt @@ -10,6 +10,10 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} \ ") message(编译参数:${CMAKE_C_FLAGS}) + +include_directories( + ${CMAKE_SOURCE_DIR}/mkrtos_knl/knl/mm +) add_subdirectory(arch) add_subdirectory(drivers) add_subdirectory(knl) diff --git a/mkrtos_knl/Kconfig b/mkrtos_knl/Kconfig index 64da2069c..4e8f66062 100644 --- a/mkrtos_knl/Kconfig +++ b/mkrtos_knl/Kconfig @@ -23,6 +23,9 @@ if SMP int "CPU Core number." default 1 endif + config THREAD_MSG_BUG_LEN + int "thread msg bud size" + default 128 config BUDDY_SLAB bool "use BUDDY & SLAB" default n diff --git a/mkrtos_knl/arch/aarch64/aarch64_qemu/arch.c b/mkrtos_knl/arch/aarch64/aarch64_qemu/arch.c index 87c57ffc8..2609520c1 100644 --- a/mkrtos_knl/arch/aarch64/aarch64_qemu/arch.c +++ b/mkrtos_knl/arch/aarch64/aarch64_qemu/arch.c @@ -68,7 +68,7 @@ extern char _rodata[], _erodata[]; extern char _data[], _edata[]; extern char _bss[], _ebss[]; extern char _buddy_data_start[]; -extern char _buddy_data_end[]; +// extern char _buddy_data_end[]; static void print_mem(void) { @@ -91,9 +91,8 @@ static void print_mem(void) printk(" .bss: 0x%08lx - 0x%08lx (%6ld B)\n", (unsigned long)_bss, (unsigned long)_ebss, (unsigned long)(_ebss - _bss)); - printk(" .buddy: 0x%08lx - 0x%08lx (%6ld B)\n", - (unsigned long)_buddy_data_start, (unsigned long)_buddy_data_end, - (unsigned long)(_buddy_data_end - _buddy_data_start)); + printk(" .buddy: 0x%08lx - \n", + (unsigned long)_buddy_data_start); } void arch_init(void) diff --git a/mkrtos_knl/arch/aarch64/aarch64_qemu/arch.h b/mkrtos_knl/arch/aarch64/aarch64_qemu/arch.h index ecc84594c..456b49724 100755 --- a/mkrtos_knl/arch/aarch64/aarch64_qemu/arch.h +++ b/mkrtos_knl/arch/aarch64/aarch64_qemu/arch.h @@ -60,6 +60,7 @@ typedef struct sp_info mword_t fp; // x29 mword_t sp; mword_t pc; + mword_t u_sp;//user_sp } sp_info_t; #define _barrier() __asm__ __volatile__("" : : : "memory") diff --git a/mkrtos_knl/arch/aarch64/aarch64_qemu/vector.S b/mkrtos_knl/arch/aarch64/aarch64_qemu/vector.S index 2170b4d3d..5f63802cf 100755 --- a/mkrtos_knl/arch/aarch64/aarch64_qemu/vector.S +++ b/mkrtos_knl/arch/aarch64/aarch64_qemu/vector.S @@ -243,7 +243,8 @@ cpu_switch_to: stp x25, x26, [x8], #16 stp x27, x28, [x8], #16 stp x29, x9, [x8], #16 - str lr, [x8] + mrs x9, sp_el1 + stp lr, x9, [x8] mov x8, x1 ldp x19, x20, [x8], #16 @@ -252,6 +253,8 @@ cpu_switch_to: ldp x25, x26, [x8], #16 ldp x27, x28, [x8], #16 ldp x29, x9, [x8], #16 - ldr lr, [x8] + ldr lr, [x8], #8 mov sp, x9 + ldr x9, [x8] + msr sp_el1, x9 ret diff --git a/mkrtos_knl/arch/aarch64/early_boot.c b/mkrtos_knl/arch/aarch64/early_boot.c index 69ce3f650..b5f2bad8e 100644 --- a/mkrtos_knl/arch/aarch64/early_boot.c +++ b/mkrtos_knl/arch/aarch64/early_boot.c @@ -24,16 +24,17 @@ extern char _edata_boot[]; extern char _ebss[]; extern char _text[]; extern char _buddy_data_start[]; -extern char _buddy_data_end[]; -#define BOOT_PAGER_NR 128 -// __ALIGN__(THREAD_BLOCK_SIZE) SECTION(DATA_BOOT_SECTION) uint8_t boot_stack[THREAD_BLOCK_SIZE] = {0}; +#define BOOT_PAGER_NR 64 static SECTION(DATA_BOOT_SECTION) __ALIGN__(PAGE_SIZE) uint8_t pages[BOOT_PAGER_NR * SYS_CPU_NUM][PAGE_SIZE]; static SECTION(DATA_BOOT_SECTION) uint8_t pages_used[BOOT_PAGER_NR * SYS_CPU_NUM]; static SECTION(TEXT_BOOT_SECTION) inline int boot_get_current_cpu_id(void) { return read_sysreg(mpidr_el1) & 0XFFUL; } +/** + * 启动时使用这个分配内存,buddy初始化完成后,使用buddy分配内存 + */ static SECTION(TEXT_BOOT_SECTION) void *page_alloc(void) { for (int i = 0; i < BOOT_PAGER_NR * SYS_CPU_NUM; i++) @@ -57,7 +58,12 @@ static SECTION(TEXT_BOOT_SECTION) void page_free(void *mem) } } } - +static page_alloc_fn page_alloc_cb = page_alloc; +SECTION(TEXT_BOOT_SECTION) +void mmu_page_alloc_set(page_alloc_fn fn) +{ + page_alloc_cb = fn; +} static SECTION(TEXT_BOOT_SECTION) void *boot_memset(void *dst, int s, size_t count) { register char *a = dst; @@ -89,22 +95,23 @@ void knl_pdir_init(page_entry_t *pdir, pte_t *dir, int page_deep) pdir->lv_shift_sizes[2] = 21; pdir->lv_shift_sizes[3] = 12; } - SECTION(TEXT_BOOT_SECTION) -pte_t *pages_walk(page_entry_t *pdir, addr_t virt_addr, mword_t size, void *(*fn_alloc)(void)) +pte_t *pages_walk(page_entry_t *pdir, addr_t virt_addr, mword_t order, void *(*fn_alloc)(void)) { int i; pte_t *next = &pdir->dir[(virt_addr >> pdir->lv_shift_sizes[(PAGE_DEEP - pdir->depth)]) & 0x1ffUL]; + // 找到所在深度 for (i = (PAGE_DEEP - pdir->depth); i < PAGE_DEEP; i++) { - if (pdir->lv_shift_sizes[i] == size) + if (pdir->lv_shift_sizes[i] == order) { break; } } assert(i != PAGE_DEEP); + // 向下循环查找,遇到没有分配的页表,则分配 for (int j = (PAGE_DEEP - pdir->depth); j < PAGE_DEEP; j++) { if (j == i) @@ -113,10 +120,20 @@ pte_t *pages_walk(page_entry_t *pdir, addr_t virt_addr, mword_t size, void *(*fn } if (next->pte == 0) { - next->pte = (mword_t)fn_alloc(); - assert(next->pte); - next->pte |= 3UL; - _dmb(ishst); + if (!fn_alloc) + { + return NULL; + } + else + { + next->pte = (mword_t)fn_alloc(); + if (!(next->pte)) + { + return NULL; + } + next->pte |= 3UL; + _dmb(ishst); + } } assert((j + 1) < PAGE_DEEP); next = &((pte_t *)(next->pte & ~3UL))[(virt_addr >> pdir->lv_shift_sizes[j + 1]) & 0x1ffUL]; @@ -124,17 +141,36 @@ pte_t *pages_walk(page_entry_t *pdir, addr_t virt_addr, mword_t size, void *(*fn assert(0); } SECTION(TEXT_BOOT_SECTION) -void map_mm(page_entry_t *pdir, addr_t virt_addr, addr_t phys_addr, - mword_t page_order, mword_t pfn_cn, mword_t attr) +int map_mm(page_entry_t *pdir, addr_t virt_addr, addr_t phys_addr, + mword_t page_order, mword_t pfn_cn, mword_t attr) { for (mword_t i = 0; i < pfn_cn; i++) { - pte_t *pte = pages_walk(pdir, virt_addr + (i << page_order), page_order, page_alloc); + pte_t *pte = pages_walk(pdir, virt_addr + (i << page_order), page_order, page_alloc_cb); - assert(pte); + if (pte == NULL) + { + return -ENOMEM; + } pte->pte = (phys_addr + (i << page_order)) | attr; _dmb(ishst); } + return 0; +} +SECTION(TEXT_BOOT_SECTION) +int unmap_mm(page_entry_t *pdir, addr_t virt_addr, mword_t page_order, mword_t pfn_cn) +{ + for (mword_t i = 0; i < pfn_cn; i++) + { + pte_t *pte = pages_walk(pdir, virt_addr + (i << page_order), page_order, NULL); + + if (pte != NULL) + { + pte->pte = 0; + _dmb(ishst); + } + } + return 0; } static SECTION(TEXT_BOOT_SECTION) void boot_init_pageing(page_entry_t *kpdir, bool_t init_pages) @@ -145,9 +181,19 @@ static SECTION(TEXT_BOOT_SECTION) void boot_init_pageing(page_entry_t *kpdir, bo write_sysreg(0x00ff4400, mair_el2); if (init_pages) { - map_mm(kpdir, CONFIG_KNL_DATA_ADDR, CONFIG_KNL_DATA_ADDR, 30, 1, 0x709); - // map_mm(kpdir, _text_boot, _text_boot, PAGE_SHIFT, ALIGN(_edata_boot - _text_boot, PAGE_SIZE) >> PAGE_SHIFT, 0x70b); - // map_mm(kpdir, _text, _edata_boot, PAGE_SHIFT, ALIGN(_buddy_data_end - _text, PAGE_SIZE) >> PAGE_SHIFT, 0x70b); + int i_ffs = ffs(CONFIG_KNL_DATA_SIZE) + (is_power_of_2(CONFIG_KNL_DATA_SIZE) ? 0 : 1); + int i_cn = 0; + + // 进行1比1映射 + do + { + map_mm(kpdir, CONFIG_KNL_DATA_ADDR + ((1U << 30) * i_cn), + CONFIG_KNL_DATA_ADDR + ((1U << 30) * i_cn), + i_ffs > 30 ? 30 : i_ffs, 1, 0x709); + i_ffs--; + i_cn++; + } while (i_ffs >= 30); + // 外设地址也是1比1映射 map_mm(kpdir, PBASE, PBASE, 21, DEVICE_SIZE >> 21, 0x709); } tmp = read_sysreg(ID_AA64MMFR0_EL1); diff --git a/mkrtos_knl/arch/aarch64/early_boot.h b/mkrtos_knl/arch/aarch64/early_boot.h index fde412d94..0abe10f1f 100644 --- a/mkrtos_knl/arch/aarch64/early_boot.h +++ b/mkrtos_knl/arch/aarch64/early_boot.h @@ -5,9 +5,14 @@ #include "asm/mm.h" #include "asm_config.h" #include + +typedef void *(*page_alloc_fn)(void); + pte_t *pages_walk(page_entry_t *pdir, addr_t virt_addr, mword_t size, void *(*fn_alloc)(void)); -void map_mm(page_entry_t *pdir, addr_t virt_addr, addr_t phys_addr, - mword_t page_order, mword_t pfn_cn, mword_t attr); +void mmu_page_alloc_set(page_alloc_fn fn); +int map_mm(page_entry_t *pdir, addr_t virt_addr, addr_t phys_addr, + mword_t page_order, mword_t pfn_cn, mword_t attr); +int unmap_mm(page_entry_t *pdir, addr_t virt_addr, mword_t page_order, mword_t pfn_cn); void per_cpu_boot_mapping(bool_t init_pages); page_entry_t *boot_get_pdir(void); void knl_pdir_init(page_entry_t *pdir, pte_t *dir, int page_deep); diff --git a/mkrtos_knl/arch/aarch64/link.lds b/mkrtos_knl/arch/aarch64/link.lds index cbfe2766d..cccd41fd7 100644 --- a/mkrtos_knl/arch/aarch64/link.lds +++ b/mkrtos_knl/arch/aarch64/link.lds @@ -1,7 +1,7 @@ ENTRY(_start); SECTIONS { - . = 0x40000000 +0x1000; + . = 0x40000000 +0x1000000; kernel_start = .; _text_boot = .; .text.boot : @@ -76,10 +76,4 @@ SECTIONS _ebss = .; . = ALIGN(4096); _buddy_data_start = .; - .buddy : - { - *(.buddy*) - . += 0x1000000; - } - _buddy_data_end = .; } diff --git a/mkrtos_knl/arch/aarch64/link.lds.S b/mkrtos_knl/arch/aarch64/link.lds.S index cdb3d6732..471280e92 100644 --- a/mkrtos_knl/arch/aarch64/link.lds.S +++ b/mkrtos_knl/arch/aarch64/link.lds.S @@ -7,10 +7,10 @@ SECTIONS * * 这里“.”表示location counter,当前位置 */ - . = CONFIG_KNL_DATA_ADDR+0x1000; + . = CONFIG_KNL_DATA_ADDR+CONFIG_KNL_OFFSET; kernel_start = .; /* - * 这里是第一个段text.boot,起始地址就是0x80000 + * 这里是第一个段text.boot * 这个段存放了benos的第一条指令 */ _text_boot = .; @@ -92,7 +92,7 @@ SECTIONS } _edata = .; - /* + /* * bss段 * * ALIGN(8)表示8个字节对齐 @@ -110,12 +110,14 @@ SECTIONS . = ALIGN(4096); _buddy_data_start = .; + /* .buddy : { *(.buddy*) . += 0x1000000; } _buddy_data_end = .; + */ } diff --git a/mkrtos_knl/arch/aarch64/mm_space.c b/mkrtos_knl/arch/aarch64/mm_space.c index 74fa3d316..169557374 100644 --- a/mkrtos_knl/arch/aarch64/mm_space.c +++ b/mkrtos_knl/arch/aarch64/mm_space.c @@ -14,9 +14,16 @@ #include "assert.h" #include #include -void mm_space_init(mm_space_t *mm_space, int is_knl) +static umword_t global_asid = 1; +int mm_space_init(mm_space_t *mm_space, int is_knl) { + int ret = 0; + page_entry_init(&mm_space->mem_dir); + mm_space->asid = global_asid++; + ret = task_vma_init(&mm_space->mem_vma); + + return ret; } bool_t mm_space_add(mm_space_t *m_space, umword_t addr, diff --git a/mkrtos_knl/arch/aarch64/sche_arch.c b/mkrtos_knl/arch/aarch64/sche_arch.c index 984c42017..ee19a761e 100644 --- a/mkrtos_knl/arch/aarch64/sche_arch.c +++ b/mkrtos_knl/arch/aarch64/sche_arch.c @@ -14,7 +14,7 @@ static void sw_mmu(thread_t *next_thread) if (p_curr_dir != p_next_dir) { _dsb(sy); - write_sysreg(p_next_dir | (1UL << 48) /*TODO:*/, vttbr_el2); + write_sysreg(p_next_dir | (next_task->mm_space.asid << 48) /*TODO:*/, vttbr_el2); // 切换用户态页表 _dsb(ish); _isb(); asm volatile("ic iallu"); diff --git a/mkrtos_knl/arch/aarch64/thread_aarch64.c b/mkrtos_knl/arch/aarch64/thread_aarch64.c index 3f38d013a..23b90387f 100644 --- a/mkrtos_knl/arch/aarch64/thread_aarch64.c +++ b/mkrtos_knl/arch/aarch64/thread_aarch64.c @@ -41,10 +41,12 @@ void thread_user_pf_set(thread_t *cur_th, void *pc, void *user_sp, void *ram, um pt->pstate = PSR_MODE_EL1h; pt->pc = (umword_t)pc; + pt->sp = (umword_t)user_sp; cur_th->sp.x19 = 0; - cur_th->sp.x20 = 0 /*arg*/; + cur_th->sp.x20 = 0; cur_th->sp.pc = (mword_t)ret_form_run; cur_th->sp.sp = (umword_t)pt; + cur_th->sp.u_sp = (umword_t)user_sp; } void task_knl_init(task_t *knl_tk) { diff --git a/mkrtos_knl/arch/aarch64/thread_armv8.c b/mkrtos_knl/arch/aarch64/thread_armv8.c index 9efe1b40a..70134f000 100644 --- a/mkrtos_knl/arch/aarch64/thread_armv8.c +++ b/mkrtos_knl/arch/aarch64/thread_armv8.c @@ -5,6 +5,8 @@ #include #include #include +#include +#include umword_t thread_get_pfa(void) { umword_t a; @@ -16,27 +18,30 @@ void thread_sync_entry(entry_frame_t *regs) { umword_t ec = arm_esr_ec(esr_get()); thread_t *th = thread_get_current(); + task_t *tk = thread_get_bind_task(th); switch (ec) { case 0x20: { - // mword_t addr = thread_get_pfa(); + mword_t addr = thread_get_pfa(); - // if (vma_page_fault(&tk->vmam, &tk->mem_dir, MASK_LSB(addr, PAGE_SHIFT)) == NULL) { - // //TODO: 如果是init进程则内核死机,否则干掉进程 - // MKRTOS_ASSERT(0); - // } + if (task_vma_page_fault(&tk->mm_space.mem_vma, ALIGN_DOWN(addr, PAGE_SIZE)) < 0) + { + printk("0x20 pfa:0x%x\n", addr); + task_knl_kill(th, FALSE); + } } return; case 0x24: { - // mword_t addr = thread_get_pfa(); + mword_t addr = thread_get_pfa(); - // if (vma_page_fault(&tk->vmam, &tk->mem_dir, MASK_LSB(addr, PAGE_SHIFT)) == NULL) { - // //TODO: 如果是init进程则内核死机,否则干掉进程 - // MKRTOS_ASSERT(0); - // } + if (task_vma_page_fault(&tk->mm_space.mem_vma, ALIGN_DOWN(addr, PAGE_SIZE)) < 0) + { + printk("0x24 pfa:0x%x\n", addr); + task_knl_kill(th, FALSE); + } } return; case 0x12: diff --git a/mkrtos_knl/inc/knl/kobject.h b/mkrtos_knl/inc/knl/kobject.h index 795c80094..3beed7451 100755 --- a/mkrtos_knl/inc/knl/kobject.h +++ b/mkrtos_knl/inc/knl/kobject.h @@ -44,6 +44,7 @@ enum knl_obj_type SYS_TYPE, FUTEX_TYPE, SHARE_MEM_TYPE, + VMAM_TYPE, }; typedef struct kobject diff --git a/mkrtos_knl/inc/knl/mm_space.h b/mkrtos_knl/inc/knl/mm_space.h index ba61e7487..4e03dc924 100644 --- a/mkrtos_knl/inc/knl/mm_space.h +++ b/mkrtos_knl/inc/knl/mm_space.h @@ -4,8 +4,9 @@ #include #include #include -#if CONFIG_MK_MPU_CFG +#if IS_ENABLED(CONFIG_MMU) #include +#include #endif #if !IS_ENABLED(CONFIG_MMU) typedef struct region_info @@ -24,34 +25,34 @@ typedef struct region_info #endif typedef struct mm_space { -#if CONFIG_MK_MPU_CFG +#if IS_ENABLED(CONFIG_MK_MPU_CFG) region_info_t pt_regions[CONFIG_REGION_NUM]; //!< mpu内存保护块 #endif #if IS_ENABLED(CONFIG_MMU) page_entry_t mem_dir; //!< MMU根映射表,存放映射信息 + task_vma_t mem_vma; + umword_t asid; #endif void *mm_block; //!< task 的私有内存块 size_t mm_block_size; //!< 私有内存块的大小 } mm_space_t; - enum region_rights { REGION_PRIV = 1, REGION_RO = 2, REGION_RWX = 3, }; -#if CONFIG_MK_MPU_CFG - +#if IS_ENABLED(CONFIG_MK_MPU_CFG) region_info_t *mm_space_alloc_pt_region(mm_space_t *m_space); void mm_space_free_pt_region(mm_space_t *m_space, region_info_t *ri); -void mm_space_init(mm_space_t *mm_space, int is_knl); +int mm_space_init(mm_space_t *mm_space, int is_knl); bool_t mm_space_add(mm_space_t *m_space, umword_t addr, umword_t size, uint8_t attrs); void mm_space_del(mm_space_t *m_space, umword_t addr); #else #if !IS_ENABLED(CONFIG_MMU) -static inline void mm_space_init(mm_space_t *mm_space, int is_knl) +static inline int mm_space_init(mm_space_t *mm_space, int is_knl) { } static inline bool_t mm_space_add(mm_space_t *m_space, umword_t addr, umword_t size, uint8_t attrs) @@ -62,7 +63,7 @@ static inline void mm_space_del(mm_space_t *m_space, umword_t addr) { } #else -void mm_space_init(mm_space_t *mm_space, int is_knl); +int mm_space_init(mm_space_t *mm_space, int is_knl); bool_t mm_space_add(mm_space_t *m_space, umword_t addr, umword_t size, uint8_t attrs); void mm_space_del(mm_space_t *m_space, umword_t addr); diff --git a/mkrtos_knl/inc/knl/mm_wrap.h b/mkrtos_knl/inc/knl/mm_wrap.h index 922840a4e..6d39e9143 100755 --- a/mkrtos_knl/inc/knl/mm_wrap.h +++ b/mkrtos_knl/inc/knl/mm_wrap.h @@ -13,6 +13,7 @@ void mm_info(size_t *total, size_t *free); #if IS_ENABLED(CONFIG_BUDDY_SLAB) #include +void *mm_buddy_alloc_one_page(void); void *mm_limit_alloc_buddy(ram_limit_t *limit, size_t size); void mm_limit_free_buddy(ram_limit_t *limit, void *mem, size_t size); #include diff --git a/mkrtos_knl/inc/knl/prot.h b/mkrtos_knl/inc/knl/prot.h index ccb7e136b..0bd6404c2 100755 --- a/mkrtos_knl/inc/knl/prot.h +++ b/mkrtos_knl/inc/knl/prot.h @@ -25,6 +25,7 @@ enum kobj_prot FUTEX_PROT, IRQ_PROT, SHARE_MEM_PROT, // 10 + VMA_PROT, MAX_PROT, }; diff --git a/mkrtos_knl/inc/knl/thread.h b/mkrtos_knl/inc/knl/thread.h index 69dadcca0..d2a4da307 100755 --- a/mkrtos_knl/inc/knl/thread.h +++ b/mkrtos_knl/inc/knl/thread.h @@ -21,10 +21,10 @@ typedef struct task task_t; struct thread; typedef struct thread thread_t; -#define THREAD_MSG_BUG_LEN 128UL //!< 最小的消息寄存器大小 -#define MSG_BUF_HAS_DATA_FLAGS 0x01U //!< 已经有数据了 -#define MSG_BUF_RECV_R_FLAGS 0x02U //!< 接收来自recv_th的消息 -#define MSG_BUF_REPLY_FLAGS 0x04U //!< 回复消息给send_th +#define THREAD_MSG_BUG_LEN CONFIG_THREAD_MSG_BUG_LEN //!< 最小的消息寄存器大小 +#define MSG_BUF_HAS_DATA_FLAGS 0x01U //!< 已经有数据了 +#define MSG_BUF_RECV_R_FLAGS 0x02U //!< 接收来自recv_th的消息 +#define MSG_BUF_REPLY_FLAGS 0x04U //!< 回复消息给send_th #define IPC_MSG_SIZE 96 #define MAP_BUF_SIZE 16 @@ -90,10 +90,12 @@ enum thread_ipc_state THREAD_IPC_ABORT, }; - typedef struct msg_buf { - void *msg; //!< buf,长度是固定的 @see THREAD_MSG_BUG_LEN + void *msg; //!< buf,长度是固定的 @see THREAD_MSG_BUG_LEN +#if IS_ENABLED(CONFIG_MMU) + void *umsg; //!< 消息对应的内核的地址 +#endif msg_tag_t tag; //!< 存放发送的临时标识 } msg_buf_t; @@ -121,11 +123,16 @@ typedef struct thread umword_t magic; //!< maigc } thread_t; -static inline void thread_set_msg_bug(thread_t *th, void *msg) +static inline void thread_set_msg_bug(thread_t *th, void *msg, void *umsg) { th->msg.msg = msg; + th->msg.umsg = umsg; } static inline void *thread_get_msg_buf(thread_t *th) +{ + return th->msg.umsg; +} +static inline void *thread_get_kmsg_buf(thread_t *th) { return th->msg.msg; } diff --git a/mkrtos_knl/inc/knl/util.h b/mkrtos_knl/inc/knl/util.h index 57e724a50..d99e6b0f6 100755 --- a/mkrtos_knl/inc/knl/util.h +++ b/mkrtos_knl/inc/knl/util.h @@ -15,7 +15,7 @@ #define ROUND_DOWN(a, b) ((a) / (b)) //!< a/b向下取整 #define GET_LSB(a, b) (a & (~((~0ULL) << (b)))) -#define MASK_LSB(a, b) (a & ((~0ULL) << (b))) //!< 屏蔽低位 +#define MASK_LSB(a, b) ((a >> (b)) << (b)) //!< 屏蔽低位 #define ARRARY_LEN(a) (sizeof(a) / sizeof((a)[0])) //!< 数组长度 diff --git a/mkrtos_knl/inc/knl/vma.h b/mkrtos_knl/inc/knl/vma.h new file mode 100644 index 000000000..0c961d7b1 --- /dev/null +++ b/mkrtos_knl/inc/knl/vma.h @@ -0,0 +1,141 @@ +#pragma once +#include +#include +#include +#include + +#define VMA_ADDR_RESV 0x1 //!< 保留内存 +#define VMA_ADDR_UNCACHE 0x2 //!< uncache内存 + +#define VMA_USED_NODE 0x1 //!< 该vma节点被使用,非空闲 + +typedef union vma_addr +{ + umword_t raw; + struct + { + umword_t prot : 4; + umword_t flags : 4; + umword_t resv : 4; + umword_t addr : (sizeof(void *) * 8 - PAGE_SHIFT); + }; +} vma_addr_t; +static inline vma_addr_t vam_addr_create_raw(umword_t raw) +{ + return (vma_addr_t){ + .raw = raw, + }; +} +static inline vma_addr_t vma_addr_create(uint8_t prot, uint8_t flags, umword_t addr) +{ + return (vma_addr_t){ + .prot = prot, + .flags = flags, + .resv = 0, + .addr = addr >> PAGE_SHIFT, + }; +} +static inline addr_t vma_addr_get_addr(vma_addr_t vaddr) +{ + return MASK_LSB(vaddr.raw, PAGE_SHIFT); +} +static inline void vma_addr_set_addr(vma_addr_t *vaddr, addr_t addr) +{ + vaddr->addr = addr >> PAGE_SHIFT; +} +static inline uint8_t vma_addr_get_prot(vma_addr_t vaddr) +{ + return vaddr.prot; +} +static inline void vma_addr_set_prot(vma_addr_t *vaddr, uint8_t prot) +{ + vaddr->prot = prot; +} +static inline uint8_t vma_addr_get_flags(vma_addr_t vaddr) +{ + return vaddr.flags; +} +static inline void vma_addr_set_flags(vma_addr_t *vaddr, uint8_t flags) +{ + vaddr->flags = flags; +} + +typedef struct vma +{ + vma_addr_t vaddr; + size_t size; //!< 节点的大小 + union + { + umword_t paddr_raw; + struct + { + umword_t flags : 12; + umword_t paddr : (sizeof(void *) * 8 - 12); //!< 被分配后的节点才使用改数据,表示分配的物理内存。 + }; + }; +} vma_t; + +static inline paddr_t vma_node_get_paddr(vma_t *data) +{ + return data->paddr << PAGE_SHIFT; +} +static inline bool_t vma_node_get_used(vma_t *data) +{ + return !!(data->flags & VMA_USED_NODE); +} +static inline void vma_node_set_used(vma_t *data) +{ + data->flags |= VMA_USED_NODE; +} +static inline void vma_node_set_unused(vma_t *data) +{ + data->flags &= ~(1 << VMA_USED_NODE); +} + +typedef struct task_vma +{ + mln_rbtree_t idle_tree; + mln_rbtree_t alloc_tree; +} task_vma_t; + +int task_vma_init(task_vma_t *vma); + +/** + * 分配步骤 + * 1.找到一个空闲的合适的虚拟内存区域 + * 2.用申请的区域去分割找到的区域 + * 3.将申请的区域插入回去,并设置属性 + */ +int task_vma_alloc(task_vma_t *task_vma, vma_addr_t vaddr, size_t size, + paddr_t paddr, vaddr_t *ret_vaddr); + +/** + * @brief 释放申请的虚拟内存,并释放已经申请的物理内存 + * 1.从分配树中找到需要的节点 + * 2.迭代释放物理内存 + * 3.设置节点为空闲节点,并与周围的合并 + * @param task_vma + * @param addr + * @param size + * @return int + */ +int task_vma_free(task_vma_t *task_vma, vaddr_t addr, size_t size); + +/** + * @brief 缺页的处理流程 + * 1.查找已经分配的表中是否存在 + * 2.分配物理内存 + * 3.插入到已分配树中去 + * @param task_vma + * @param addr + * @return int + */ +int task_vma_page_fault(task_vma_t *task_vma, vaddr_t addr); + +/** + * @brief 释放task_vma + * + * @param task_vma + * @return int + */ +int task_vma_clean(task_vma_t *task_vma); diff --git a/mkrtos_knl/inc/lib/types.h b/mkrtos_knl/inc/lib/types.h index 8d5568d28..170f07af6 100755 --- a/mkrtos_knl/inc/lib/types.h +++ b/mkrtos_knl/inc/lib/types.h @@ -26,6 +26,8 @@ typedef char bool_t; typedef unsigned long obj_addr_t; typedef umword_t uintptr_t; typedef umword_t addr_t; +typedef umword_t paddr_t; +typedef umword_t vaddr_t; typedef umword_t obj_handler_t; typedef umword_t time_t; typedef umword_t pid_t; diff --git a/mkrtos_knl/knl/CMakeLists.txt b/mkrtos_knl/knl/CMakeLists.txt index cf32430a3..aef8c6ae1 100755 --- a/mkrtos_knl/knl/CMakeLists.txt +++ b/mkrtos_knl/knl/CMakeLists.txt @@ -1,12 +1,16 @@ cmake_minimum_required(VERSION 3.13) -file(GLOB_RECURSE deps *.c *.S) +file(GLOB deps *.c *.S) -if (NOT ${CONFIG_SMP} STREQUAL "y" ) +if (NOT ${CONFIG_BUDDY_SLAB} STREQUAL "y") list(REMOVE_ITEM deps ${CMAKE_SOURCE_DIR}/mkrtos_knl/knl/buddy.c) list(REMOVE_ITEM deps ${CMAKE_SOURCE_DIR}/mkrtos_knl/knl/slab.c) endif() +if (${CONFIG_MMU} STREQUAL "y") + file(GLOB mm_src mm/*.c mm/*.S) + list(APPEND deps ${mm_src}) +endif() add_library(knl STATIC ${deps}) @@ -20,4 +24,6 @@ target_include_directories( ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/knl ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/inc ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/drv + + ${CMAKE_SOURCE_DIR}/mkrtos_knl/knl/mm ) diff --git a/mkrtos_knl/knl/buddy.c b/mkrtos_knl/knl/buddy.c index e7dbfb774..ae8db8936 100755 --- a/mkrtos_knl/knl/buddy.c +++ b/mkrtos_knl/knl/buddy.c @@ -8,9 +8,9 @@ #include #include #include -#define BUDDY_ENTRY_MAX_CN 1024 -static buddy_entry_t buddy_entry_simp_slab[BUDDY_ENTRY_MAX_CN]; +static buddy_entry_t *buddy_entry_simp_slab; +static size_t buddy_entry_cn = 0; static buddy_order_t buddy_kmem; static inline size_t to_size(size_t order); @@ -46,7 +46,7 @@ static inline void buddy_entry_clr_lr(buddy_entry_t *be) static buddy_entry_t *buddy_entry_alloc(void) { - for (int i = 0; i < BUDDY_ENTRY_MAX_CN; i++) + for (int i = 0; i < buddy_entry_cn; i++) { if (!BUDDY_ENTRY_VALID(&buddy_entry_simp_slab[i])) { @@ -77,12 +77,31 @@ int buddy_init(buddy_order_t *buddy, addr_t start_addr, size_t size) { return -1; } - buddy->heap_addr = start_addr; spinlock_init(&buddy->lock); for (int i = 0; i < BUDDY_MAX_ORDER; i++) { slist_init(&buddy->order_tab[i].b_order); } + size_t entry_cn = 0; + + int iffs = ffs(size); + if (!is_power_of_2(iffs)) + { + iffs++; + } + while (iffs >= PAGE_SHIFT) + { + entry_cn += ((1UL << iffs) >> PAGE_SHIFT); + iffs--; + } + buddy_entry_simp_slab = (void *)start_addr; + size_t entrys_size = ALIGN(entry_cn * (sizeof(buddy_entry_t)), PAGE_SIZE); + start_addr += entrys_size; + size -= entrys_size; + buddy->heap_addr = start_addr; + buddy_entry_cn = entry_cn; + + printk("buddy mem size:%dMB\n", size / 1024 / 1024); size_t remain_size = size; addr_t add_addr = buddy->heap_addr; @@ -92,16 +111,21 @@ int buddy_init(buddy_order_t *buddy, addr_t start_addr, size_t size) { int i_ffs = ffs(remain_size); i_ffs -= PAGE_SHIFT; + if (i_ffs >= BUDDY_MAX_ORDER) + { + i_ffs = BUDDY_MAX_ORDER; + } + buddy_entry_t *new_be = buddy_entry_alloc(); if (!new_be) { return -1; } buddy_entry_init(new_be, add_addr); - slist_add(&buddy->order_tab[i_ffs - 1].b_order, &new_be->next); + slist_add(&buddy->order_tab[i_ffs == 0 ? 1 : i_ffs - 1].b_order, &new_be->next); buddy->order_tab[i_ffs - 1].nr_free++; - remain_size = size - to_size(i_ffs); + remain_size -= to_size(i_ffs); add_addr += to_size(i_ffs); } buddy->heap_size = size; diff --git a/mkrtos_knl/knl/elf64.c b/mkrtos_knl/knl/elf64.c index 8bd9c8f21..f17a9ca3e 100644 --- a/mkrtos_knl/knl/elf64.c +++ b/mkrtos_knl/knl/elf64.c @@ -2,6 +2,11 @@ #include #include #include +#include +#include +#include +#include + typedef uint16_t Elf64_Half; typedef uint32_t Elf64_Word; typedef uint64_t Elf64_Addr; @@ -73,10 +78,7 @@ typedef struct #define ELFMAG "\177ELF" #define SELFMAG 4 -#include -#include -#include -#include + int elf_check(Elf64_Ehdr *ehdr) { if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0) @@ -142,7 +144,8 @@ int elf_load(task_t *task, umword_t elf_data, size_t size, addr_t *entry_addr) { if (elf_phdr->p_type == PT_LOAD) { - memcpy((char *)mem + (elf_phdr->p_vaddr - st_addr), (void *)(elf_data + elf_phdr->p_offset), + memcpy((char *)mem + (elf_phdr->p_vaddr - st_addr), + (void *)(elf_data + elf_phdr->p_offset), elf_phdr->p_filesz); offset += ALIGN(elf_phdr->p_memsz, elf_phdr->p_align); } diff --git a/mkrtos_knl/knl/factory.c b/mkrtos_knl/knl/factory.c index 693275e9a..51c773a2f 100755 --- a/mkrtos_knl/knl/factory.c +++ b/mkrtos_knl/knl/factory.c @@ -185,7 +185,7 @@ static factory_t *fatory_create(ram_limit_t *lim, umword_t max) factory_t *kobj = NULL; #if IS_ENABLED(CONFIG_BUDDY_SLAB) - kobj = slab_alloc(factory_slab); + kobj = mm_limit_alloc_slab(factory_slab, lim); #else kobj = mm_limit_alloc(lim, sizeof(factory_t)); #endif diff --git a/mkrtos_knl/knl/globals.c b/mkrtos_knl/knl/globals.c index c8198dcc0..fe18c088f 100755 --- a/mkrtos_knl/knl/globals.c +++ b/mkrtos_knl/knl/globals.c @@ -54,6 +54,7 @@ mem_t *mm_get_global(void) } #if CONFIG_BUDDY_SLAB #include +#include #endif /** * @brief 系统内存初始化 @@ -65,12 +66,14 @@ static void mem_sys_init(void) mem_init(&global_mem); #if CONFIG_BUDDY_SLAB extern char _buddy_data_start[]; - extern char _buddy_data_end[]; + // extern char _buddy_data_end[]; int ret; + size_t buddy_size = (size_t)CONFIG_KNL_DATA_SIZE - ((addr_t)_buddy_data_start - CONFIG_KNL_DATA_ADDR - CONFIG_KNL_OFFSET); ret = buddy_init(buddy_get_alloter(), (addr_t)_buddy_data_start, - (size_t)_buddy_data_end - (mword_t)_buddy_data_start); + buddy_size); assert(ret >= 0); + mmu_page_alloc_set(mm_buddy_alloc_one_page); #else #if CONFIG_KNL_EXRAM mem_heap_add(mm_get_global(), (void *)CONFIG_EX_RAM_ADDR, CONFIG_EX_RAM_SIZE); diff --git a/mkrtos_knl/knl/ipc.c b/mkrtos_knl/knl/ipc.c index 0ae858713..2be951655 100755 --- a/mkrtos_knl/knl/ipc.c +++ b/mkrtos_knl/knl/ipc.c @@ -36,7 +36,7 @@ typedef struct ipc_wait_bind_entry #if IS_ENABLED(CONFIG_BUDDY_SLAB) #include -static slab_t *ipc_slab; +slab_t *ipc_slab; #endif /** diff --git a/mkrtos_knl/knl/mm/mln_func.h b/mkrtos_knl/knl/mm/mln_func.h new file mode 100644 index 000000000..189f343cf --- /dev/null +++ b/mkrtos_knl/knl/mm/mln_func.h @@ -0,0 +1,180 @@ + +/* + * Copyright (C) Niklaus F.Schen. + */ +#ifndef __MLN_FUNC_H +#define __MLN_FUNC_H + +// #include + +typedef int (*mln_func_entry_cb_t)(const char *file, const char *func, int line, ...); +typedef void (*mln_func_exit_cb_t)(const char *file, const char *func, int line, void *ret, ...); + +#define MLN_FUNC_ERROR (~((long)0)) + +#if defined(MLN_FUNC_FLAG) +#if defined(MLN_C99) +#define MLN_FUNC_STRIP(...) __VA_OPT__(, ) __VA_ARGS__ +#define MLN_FUNC(scope, ret_type, name, params, args, ...) \ + scope ret_type name params; \ + scope ret_type __mln_func_##name params __VA_ARGS__ \ + scope ret_type name params \ + { \ + ret_type _r; \ + if (mln_func_entry != NULL) \ + { \ + if (mln_func_entry(__FILE__, __FUNCTION__, __LINE__ MLN_FUNC_STRIP args) < 0) \ + { \ + _r = (ret_type)MLN_FUNC_ERROR; \ + goto out; \ + } \ + } \ + _r = __mln_func_##name args; \ + out: \ + if (mln_func_exit != NULL) \ + mln_func_exit(__FILE__, __FUNCTION__, __LINE__, &_r MLN_FUNC_STRIP args); \ + return _r; \ + } +#define MLN_FUNC_VOID(scope, ret_type, name, params, args, ...) \ + scope ret_type name params; \ + scope ret_type __mln_func_##name params __VA_ARGS__ \ + scope ret_type name params \ + { \ + int _r = 0; \ + if (mln_func_entry != NULL) \ + { \ + if (mln_func_entry(__FILE__, __FUNCTION__, __LINE__ MLN_FUNC_STRIP args) < 0) \ + { \ + _r = (int)MLN_FUNC_ERROR; \ + goto out; \ + } \ + } \ + __mln_func_##name args; \ + out: \ + if (mln_func_exit != NULL) \ + mln_func_exit(__FILE__, __FUNCTION__, __LINE__, _r ? &_r : NULL MLN_FUNC_STRIP args); \ + } +#define MLN_FUNC_CUSTOM(entry, exit, scope, ret_type, name, params, args, ...) \ + scope ret_type name params; \ + scope ret_type __mln_func_##name params __VA_ARGS__ \ + scope ret_type name params \ + { \ + ret_type _r; \ + if (entry(__FILE__, __FUNCTION__, __LINE__ MLN_FUNC_STRIP args) < 0) \ + { \ + _r = (ret_type)MLN_FUNC_ERROR; \ + goto out; \ + } \ + _r = __mln_func_##name args; \ + out: \ + exit(__FILE__, __FUNCTION__, __LINE__, &_r MLN_FUNC_STRIP args); \ + return _r; \ + } +#define MLN_FUNC_VOID_CUSTOM(entry, exit, scope, ret_type, name, params, args, ...) \ + scope ret_type name params; \ + scope ret_type __mln_func_##name params __VA_ARGS__ \ + scope ret_type name params \ + { \ + int _r = 0; \ + if (entry(__FILE__, __FUNCTION__, __LINE__ MLN_FUNC_STRIP args) < 0) \ + { \ + _r = (int)MLN_FUNC_ERROR; \ + goto out; \ + } \ + __mln_func_##name args; \ + out: \ + exit(__FILE__, __FUNCTION__, __LINE__, _r ? &_r : NULL MLN_FUNC_STRIP args); \ + } + +#else +#define MLN_FUNC(scope, ret_type, name, params, args, ...) \ + scope ret_type name params; \ + scope ret_type __mln_func_##name params __VA_ARGS__ \ + scope ret_type name params \ + { \ + ret_type _r; \ + if (mln_func_entry != NULL) \ + { \ + if (mln_func_entry(__FILE__, __FUNCTION__, __LINE__) < 0) \ + { \ + _r = (ret_type)MLN_FUNC_ERROR; \ + goto out; \ + } \ + } \ + _r = __mln_func_##name args; \ + out: \ + if (mln_func_exit != NULL) \ + mln_func_exit(__FILE__, __FUNCTION__, __LINE__, &_r); \ + return _r; \ + } +#define MLN_FUNC_VOID(scope, ret_type, name, params, args, ...) \ + scope ret_type name params; \ + scope ret_type __mln_func_##name params __VA_ARGS__ \ + scope ret_type name params \ + { \ + int _r = 0; \ + if (mln_func_entry != NULL) \ + { \ + if (mln_func_entry(__FILE__, __FUNCTION__, __LINE__) < 0) \ + { \ + _r = (int)MLN_FUNC_ERROR; \ + goto out; \ + } \ + } \ + __mln_func_##name args; \ + out: \ + if (mln_func_exit != NULL) \ + mln_func_exit(__FILE__, __FUNCTION__, __LINE__, _r ? &_r : NULL); \ + } +#define MLN_FUNC_CUSTOM(entry, exit, scope, ret_type, name, params, args, ...) \ + scope ret_type name params; \ + scope ret_type __mln_func_##name params __VA_ARGS__ \ + scope ret_type name params \ + { \ + ret_type _r; \ + if (entry(__FILE__, __FUNCTION__, __LINE__) < 0) \ + { \ + _r = (ret_type)MLN_FUNC_ERROR; \ + goto out; \ + } \ + _r = __mln_func_##name args; \ + out: \ + exit(__FILE__, __FUNCTION__, __LINE__, &_r); \ + return _r; \ + } +#define MLN_FUNC_VOID_CUSTOM(entry, exit, scope, ret_type, name, params, args, ...) \ + scope ret_type name params; \ + scope ret_type __mln_func_##name params __VA_ARGS__ \ + scope ret_type name params \ + { \ + int _r = 0; \ + if (entry(__FILE__, __FUNCTION__, __LINE__) < 0) \ + { \ + _r = (int)MLN_FUNC_ERROR; \ + goto out; \ + } \ + __mln_func_##name args; \ + out: \ + exit(__FILE__, __FUNCTION__, __LINE__, _r ? &_r : NULL); \ + } +#endif +#else +#define MLN_FUNC(scope, ret_type, name, params, args, ...) \ + scope ret_type name params __VA_ARGS__ +#define MLN_FUNC_VOID(scope, ret_type, name, params, args, ...) \ + scope ret_type name params __VA_ARGS__ +#define MLN_FUNC_CUSTOM(entry, exit, scope, ret_type, name, params, args, ...) \ + scope ret_type name params __VA_ARGS__ +#define MLN_FUNC_VOID_CUSTOM(entry, exit, scope, ret_type, name, params, args, ...) \ + scope ret_type name params __VA_ARGS__ +#endif + +extern mln_func_entry_cb_t mln_func_entry; +extern mln_func_exit_cb_t mln_func_exit; + +extern void mln_func_entry_callback_set(mln_func_entry_cb_t cb); +extern mln_func_entry_cb_t mln_func_entry_callback_get(void); +extern void mln_func_exit_callback_set(mln_func_exit_cb_t cb); +extern mln_func_exit_cb_t mln_func_exit_callback_get(void); + +#endif diff --git a/mkrtos_knl/knl/mm/mln_rbtree.c b/mkrtos_knl/knl/mm/mln_rbtree.c new file mode 100644 index 000000000..e8bf0f52a --- /dev/null +++ b/mkrtos_knl/knl/mm/mln_rbtree.c @@ -0,0 +1,372 @@ + +/* + * Copyright (C) Niklaus F.Schen. + */ + +#include +#include "mln_rbtree.h" + +/*static declarations*/ +static inline mln_rbtree_node_t * +rbtree_minimum(mln_rbtree_t *t, mln_rbtree_node_t *n) __NONNULL2(1, 2); +static inline void +rbtree_transplant(mln_rbtree_t *t, mln_rbtree_node_t *u, mln_rbtree_node_t *v) __NONNULL3(1, 2, 3); +static inline void +rbtree_delete_fixup(mln_rbtree_t *t, mln_rbtree_node_t *n) __NONNULL2(1, 2); + +/*rbtree_init*/ +MLN_FUNC(, mln_rbtree_t *, mln_rbtree_new, (struct mln_rbtree_attr * attr), (attr), { + mln_rbtree_t *t; + t = (mln_rbtree_t *)attr->pool_alloc(attr->pool, sizeof(mln_rbtree_t)); + if (t == NULL) + return NULL; + if (attr == NULL) + { + t->pool = NULL; + t->pool_alloc = NULL; + t->pool_free = NULL; + t->cmp = NULL; + t->data_free = NULL; + } + else + { + t->pool = attr->pool; + t->pool_alloc = attr->pool_alloc; + t->pool_free = attr->pool_free; + t->cmp = attr->cmp; + t->data_free = attr->data_free; + } + t->nil.data = NULL; + t->nil.parent = &(t->nil); + t->nil.left = &(t->nil); + t->nil.right = &(t->nil); + t->nil.color = M_RB_BLACK; + t->root = &(t->nil); + t->min = &(t->nil); + t->head = t->tail = NULL; + t->iter = NULL; + t->nr_node = 0; + t->del = 0; + return t; +}) +/*rbtree_init*/ +MLN_FUNC(, mln_rbtree_t *, mln_rbtree_init, + (struct mln_rbtree_attr * attr, mln_rbtree_t *t), (attr, t), + { + if (t == NULL) + return NULL; + if (attr == NULL) + { + t->pool = NULL; + t->pool_alloc = NULL; + t->pool_free = NULL; + t->cmp = NULL; + t->data_free = NULL; + } + else + { + t->pool = attr->pool; + t->pool_alloc = attr->pool_alloc; + t->pool_free = attr->pool_free; + t->cmp = attr->cmp; + t->data_free = attr->data_free; + } + t->nil.data = NULL; + t->nil.parent = &(t->nil); + t->nil.left = &(t->nil); + t->nil.right = &(t->nil); + t->nil.color = M_RB_BLACK; + t->root = &(t->nil); + t->min = &(t->nil); + t->head = t->tail = NULL; + t->iter = NULL; + t->nr_node = 0; + t->del = 0; + return t; + }) +/*rbtree free*/ +MLN_FUNC_VOID(, void, mln_rbtree_free, (mln_rbtree_t * t), (t), { + if (t == NULL) + return; + + mln_rbtree_node_t *fr; + while ((fr = t->tail) != NULL) + { + mln_rbtree_chain_del(&(t->head), &(t->tail), fr); + if (t->data_free != NULL) + mln_rbtree_inline_node_free(t, fr, t->data_free); + else + mln_rbtree_node_free(t, fr); + } + t->pool_free(t); +}) + +/*rbtree reset*/ +MLN_FUNC_VOID(, void, mln_rbtree_reset, (mln_rbtree_t * t), (t), { + mln_rbtree_node_t *fr; + while ((fr = t->tail) != NULL) + { + mln_rbtree_chain_del(&(t->head), &(t->tail), fr); + if (t->data_free != NULL) + mln_rbtree_inline_node_free(t, fr, t->data_free); + else + mln_rbtree_node_free(t, fr); + } + t->root = &(t->nil); + t->min = &(t->nil); + t->iter = NULL; + t->nr_node = 0; + t->del = 0; +}) + +/*rbtree insert*/ +MLN_FUNC_VOID(, void, mln_rbtree_insert, (mln_rbtree_t * t, mln_rbtree_node_t *node), (t, node), { + mln_rbtree_node_t *y = &(t->nil); + mln_rbtree_node_t *x = t->root; + mln_rbtree_node_t *nil = &(t->nil); + while (x != nil) + { + y = x; + if (t->cmp(node->data, x->data) < 0) + x = x->left; + else + x = x->right; + } + node->parent = y; + if (y == nil) + t->root = node; + else if (t->cmp(node->data, y->data) < 0) + y->left = node; + else + y->right = node; + node->left = node->right = nil; + node->color = M_RB_RED; + rbtree_insert_fixup(t, node); + if (t->min == nil) + t->min = node; + else if (t->cmp(node->data, t->min->data) < 0) + t->min = node; + ++(t->nr_node); + mln_rbtree_chain_add(&(t->head), &(t->tail), node); +}) + +/*rbtree search*/ +MLN_FUNC(, mln_rbtree_node_t *, mln_rbtree_search, (mln_rbtree_t * t, void *key), (t, key), { + mln_rbtree_node_t *ret_node = t->root; + int ret; + while ((ret_node != &(t->nil)) && ((ret = t->cmp(key, ret_node->data)) != 0)) + { + if (ret < 0) + ret_node = ret_node->left; + else + ret_node = ret_node->right; + } + return ret_node; +}) + +/*rbtree successor*/ +MLN_FUNC(, mln_rbtree_node_t *, mln_rbtree_successor, + (mln_rbtree_t * t, mln_rbtree_node_t *n), (t, n), + { + if (n != &(t->nil) && n->right != &(t->nil)) + return rbtree_minimum(t, n->right); + mln_rbtree_node_t *tmp = n->parent; + while (tmp != &(t->nil) && n == tmp->right) + { + n = tmp; + tmp = tmp->parent; + } + return tmp; + }) + +/*rbtree node new*/ +MLN_FUNC(, mln_rbtree_node_t *, mln_rbtree_node_new, + (mln_rbtree_t * t, void *data), (t, data), + { + mln_rbtree_node_t *n; + + n = (mln_rbtree_node_t *)t->pool_alloc(t->pool, sizeof(mln_rbtree_node_t)); + if (n == NULL) + return NULL; + n->data = data; + n->nofree = 0; + return n; + }) + +/*rbtree node free*/ +MLN_FUNC_VOID(, void, mln_rbtree_node_free, (mln_rbtree_t * t, mln_rbtree_node_t *n), (t, n), { + mln_u32_t nofree = n->nofree; + if (n->data != NULL && t->data_free != NULL) + t->data_free(n->data); + if (!nofree) + { + t->pool_free(n); + } +}) + +/*Tree Minimum*/ +MLN_FUNC(static inline, mln_rbtree_node_t *, rbtree_minimum, + (mln_rbtree_t * t, mln_rbtree_node_t *n), (t, n), + { + while (n->left != &(t->nil)) + n = n->left; + return n; + }) + +/*transplant*/ +MLN_FUNC_VOID(static inline, void, rbtree_transplant, + (mln_rbtree_t * t, mln_rbtree_node_t *u, mln_rbtree_node_t *v), + (t, u, v), + { + if (u->parent == &(t->nil)) + t->root = v; + else if (u == u->parent->left) + u->parent->left = v; + else + u->parent->right = v; + v->parent = u->parent; + }) + +/*rbtree_delete*/ +MLN_FUNC_VOID(, void, mln_rbtree_delete, (mln_rbtree_t * t, mln_rbtree_node_t *n), (t, n), { + if (n == t->min) + t->min = mln_rbtree_successor(t, n); + enum rbtree_color y_original_color; + mln_rbtree_node_t *x, *y; + y = n; + y_original_color = y->color; + if (n->left == &(t->nil)) + { + x = n->right; + rbtree_transplant(t, n, n->right); + } + else if (n->right == &(t->nil)) + { + x = n->left; + rbtree_transplant(t, n, n->left); + } + else + { + y = rbtree_minimum(t, n->right); + y_original_color = y->color; + x = y->right; + if (y->parent == n) + x->parent = y; + else + { + rbtree_transplant(t, y, y->right); + y->right = n->right; + y->right->parent = y; + } + rbtree_transplant(t, n, y); + y->left = n->left; + y->left->parent = y; + y->color = n->color; + } + if (y_original_color == M_RB_BLACK) + rbtree_delete_fixup(t, x); + n->parent = n->left = n->right = &(t->nil); + --(t->nr_node); + if (t->iter != NULL && t->iter == n) + { + t->iter = n->next; + t->del = 1; + } + mln_rbtree_chain_del(&(t->head), &(t->tail), n); +}) + +/*rbtree_delete_fixup*/ +MLN_FUNC_VOID(static inline, void, rbtree_delete_fixup, + (mln_rbtree_t * t, mln_rbtree_node_t *n), (t, n), + { + mln_rbtree_node_t *tmp; + while ((n != t->root) && (n->color == M_RB_BLACK)) + { + if (n == n->parent->left) + { + tmp = n->parent->right; + if (tmp->color == M_RB_RED) + { + tmp->color = M_RB_BLACK; + n->parent->color = M_RB_RED; + mln_rbtree_left_rotate(t, n->parent); + tmp = n->parent->right; + } + if ((tmp->left->color == M_RB_BLACK) && (tmp->right->color == M_RB_BLACK)) + { + tmp->color = M_RB_RED; + n = n->parent; + continue; + } + else if (tmp->right->color == M_RB_BLACK) + { + tmp->left->color = M_RB_BLACK; + tmp->color = M_RB_RED; + mln_rbtree_right_rotate(t, tmp); + tmp = n->parent->right; + } + tmp->color = n->parent->color; + n->parent->color = M_RB_BLACK; + tmp->right->color = M_RB_BLACK; + mln_rbtree_left_rotate(t, n->parent); + n = t->root; + } + else + { + tmp = n->parent->left; + if (tmp->color == M_RB_RED) + { + tmp->color = M_RB_BLACK; + n->parent->color = M_RB_RED; + mln_rbtree_right_rotate(t, n->parent); + tmp = n->parent->left; + } + if ((tmp->right->color == M_RB_BLACK) && (tmp->left->color == M_RB_BLACK)) + { + tmp->color = M_RB_RED; + n = n->parent; + continue; + } + else if (tmp->left->color == M_RB_BLACK) + { + tmp->right->color = M_RB_BLACK; + tmp->color = M_RB_RED; + mln_rbtree_left_rotate(t, tmp); + tmp = n->parent->left; + } + tmp->color = n->parent->color; + n->parent->color = M_RB_BLACK; + tmp->left->color = M_RB_BLACK; + mln_rbtree_right_rotate(t, n->parent); + n = t->root; + } + } + n->color = M_RB_BLACK; + }) + +/*min*/ +MLN_FUNC(, mln_rbtree_node_t *, mln_rbtree_min, (mln_rbtree_t * t), (t), { + return t->min; +}) + +/*iterate*/ +MLN_FUNC(, int, mln_rbtree_iterate, + (mln_rbtree_t * t, rbtree_iterate_handler handler, void *udata), + (t, handler, udata), + { + for (t->iter = t->head; t->iter != NULL;) + { + if (handler(t->iter, udata) < 0) + return -1; + if (t->del) + { + t->del = 0; + continue; + } + else + { + t->iter = t->iter->next; + } + } + return 0; + }) diff --git a/mkrtos_knl/knl/mm/mln_rbtree.h b/mkrtos_knl/knl/mm/mln_rbtree.h new file mode 100644 index 000000000..8610336f5 --- /dev/null +++ b/mkrtos_knl/knl/mm/mln_rbtree.h @@ -0,0 +1,308 @@ + +/* + * Copyright (C) Niklaus F.Schen. + */ + +#ifndef __MLN_RBTREE_H +#define __MLN_RBTREE_H +#include "mln_types.h" +#include "mln_func.h" + +typedef struct mln_rbtree_node_s mln_rbtree_node_t; +/* + * >0 -- the first argument greater than the second. + * ==0 -- equal. + * <0 -- less. + */ +typedef int (*rbtree_cmp)(const void *, const void *); +typedef void (*rbtree_free_data)(void *); +typedef int (*rbtree_iterate_handler)(mln_rbtree_node_t *node, void *udata); +typedef void *(*rbtree_pool_alloc_handler)(void *, mln_size_t); +typedef void (*rbtree_pool_free_handler)(void *); + +enum rbtree_color +{ + M_RB_RED = 0, + M_RB_BLACK +}; + +struct mln_rbtree_attr +{ + void *pool; + rbtree_pool_alloc_handler pool_alloc; + rbtree_pool_free_handler pool_free; + rbtree_cmp cmp; + rbtree_free_data data_free; +}; + +struct mln_rbtree_node_s +{ + void *data; + struct mln_rbtree_node_s *prev; + struct mln_rbtree_node_s *next; + struct mln_rbtree_node_s *parent; + struct mln_rbtree_node_s *left; + struct mln_rbtree_node_s *right; + mln_u32_t nofree : 1; + mln_u32_t color : 31; +}; + +typedef struct rbtree_s +{ + void *pool; + rbtree_pool_alloc_handler pool_alloc; + rbtree_pool_free_handler pool_free; + rbtree_cmp cmp; + rbtree_free_data data_free; + mln_rbtree_node_t nil; + mln_rbtree_node_t *root; + mln_rbtree_node_t *min; + mln_rbtree_node_t *head; + mln_rbtree_node_t *tail; + mln_rbtree_node_t *iter; + mln_uauto_t nr_node; + mln_u32_t del : 1; +} mln_rbtree_t; + +MLN_CHAIN_FUNC_DECLARE(static inline, + mln_rbtree, + mln_rbtree_node_t, ); +MLN_CHAIN_FUNC_DEFINE(static inline, + mln_rbtree, + mln_rbtree_node_t, + prev, + next); + +/*Left rotate*/ +MLN_FUNC_VOID(static inline, void, mln_rbtree_left_rotate, + (mln_rbtree_t * t, mln_rbtree_node_t *n), (t, n), + { + if (n->right == &(t->nil)) + return; + mln_rbtree_node_t *tmp = n->right; + n->right = tmp->left; + if (tmp->left != &(t->nil)) + tmp->left->parent = n; + tmp->parent = n->parent; + if (n->parent == &(t->nil)) + t->root = tmp; + else if (n == n->parent->left) + n->parent->left = tmp; + else + n->parent->right = tmp; + tmp->left = n; + n->parent = tmp; + }) + +/*Right rotate*/ +MLN_FUNC_VOID(static inline, void, mln_rbtree_right_rotate, + (mln_rbtree_t * t, mln_rbtree_node_t *n), (t, n), + { + if (n->left == &(t->nil)) + return; + mln_rbtree_node_t *tmp = n->left; + n->left = tmp->right; + if (tmp->right != &(t->nil)) + tmp->right->parent = n; + tmp->parent = n->parent; + if (n->parent == &(t->nil)) + t->root = tmp; + else if (n == n->parent->right) + n->parent->right = tmp; + else + n->parent->left = tmp; + tmp->right = n; + n->parent = tmp; + }) + +/*insert fixup*/ +MLN_FUNC_VOID(static inline, void, rbtree_insert_fixup, + (mln_rbtree_t * t, mln_rbtree_node_t *n), (t, n), + { + mln_rbtree_node_t *tmp; + while (n->parent->color == M_RB_RED) + { + if (n->parent == n->parent->parent->left) + { + tmp = n->parent->parent->right; + if (tmp->color == M_RB_RED) + { + n->parent->color = M_RB_BLACK; + tmp->color = M_RB_BLACK; + n->parent->parent->color = M_RB_RED; + n = n->parent->parent; + continue; + } + else if (n == n->parent->right) + { + n = n->parent; + mln_rbtree_left_rotate(t, n); + } + n->parent->color = M_RB_BLACK; + n->parent->parent->color = M_RB_RED; + mln_rbtree_right_rotate(t, n->parent->parent); + } + else + { + tmp = n->parent->parent->left; + if (tmp->color == M_RB_RED) + { + n->parent->color = M_RB_BLACK; + tmp->color = M_RB_BLACK; + n->parent->parent->color = M_RB_RED; + n = n->parent->parent; + continue; + } + else if (n == n->parent->left) + { + n = n->parent; + mln_rbtree_right_rotate(t, n); + } + n->parent->color = M_RB_BLACK; + n->parent->parent->color = M_RB_RED; + mln_rbtree_left_rotate(t, n->parent->parent); + } + } + t->root->color = M_RB_BLACK; + }) + +/*Insert*/ +#define mln_rbtree_inline_insert(t, n, compare) ({ \ + mln_rbtree_t *tree = (t); \ + mln_rbtree_node_t *y = &(tree->nil); \ + mln_rbtree_node_t *x = tree->root; \ + mln_rbtree_node_t *nil = &(tree->nil); \ + while (x != nil) \ + { \ + y = x; \ + if (compare((n)->data, x->data) < 0) \ + x = x->left; \ + else \ + x = x->right; \ + } \ + (n)->parent = y; \ + if (y == nil) \ + tree->root = (n); \ + else if (compare((n)->data, y->data) < 0) \ + y->left = (n); \ + else \ + y->right = (n); \ + (n)->left = (n)->right = nil; \ + (n)->color = M_RB_RED; \ + rbtree_insert_fixup(tree, (n)); \ + if (tree->min == nil) \ + tree->min = (n); \ + else if (compare((n)->data, tree->min->data) < 0) \ + tree->min = (n); \ + ++(tree->nr_node); \ + mln_rbtree_chain_add(&(tree->head), &(tree->tail), (n)); \ +}) + +/*search*/ +#define mln_rbtree_inline_root_search(t, root, key, compare) ({ \ + mln_rbtree_t *tree = (t); \ + mln_rbtree_node_t *ret_node = (root); \ + int ret; \ + while ((ret_node != &(tree->nil)) && ((ret = compare(key, ret_node->data)) != 0)) \ + { \ + if (ret < 0) \ + ret_node = ret_node->left; \ + else \ + ret_node = ret_node->right; \ + } \ + ret_node; \ +}) + +#define mln_rbtree_inline_search(t, key, compare) ({ \ + mln_rbtree_t *tree = (t); \ + mln_rbtree_node_t *ret_node = tree->root; \ + int ret; \ + while ((ret_node != &(tree->nil)) && ((ret = compare(key, ret_node->data)) != 0)) \ + { \ + if (ret < 0) \ + ret_node = ret_node->left; \ + else \ + ret_node = ret_node->right; \ + } \ + ret_node; \ +}) + +/*rbtree free node*/ +#define mln_rbtree_inline_node_free(t, n, freer) ({ \ + mln_u32_t nofree = (n)->nofree; \ + if ((n)->data != NULL) \ + freer((n)->data); \ + if (!nofree) \ + { \ + (t)->pool_free((n)); \ + } \ +}) + +/*rbtree_destroy*/ +/* + * Warning: mln_lang_sys.c: mln_import is very dependent on this release order. + * This release order ensures that the resources of the dynamic extension library + * are released first, and then the import resources are released. + * If the import resource is released before the dynamic library resource, + * the function in the dynamic library cannot be read when the dynamic extension + * resource is released, and the program terminates abnormally. + */ +#define mln_rbtree_inline_free(t, freer) ({ \ + mln_rbtree_t *tree = (t); \ + if (tree != NULL) \ + { \ + mln_rbtree_node_t *fr; \ + while ((fr = tree->tail) != NULL) \ + { \ + mln_rbtree_chain_del(&(tree->head), &(tree->tail), fr); \ + mln_rbtree_inline_node_free(tree, fr, freer); \ + } \ + if (tree->pool != NULL) \ + tree->pool_free(tree); \ + else \ + free(tree); \ + } \ +}) + +#define mln_rbtree_inline_reset(t, freer) ({ \ + mln_rbtree_t *tree = (t); \ + mln_rbtree_node_t *fr; \ + while ((fr = tree->tail) != NULL) \ + { \ + mln_rbtree_chain_del(&(tree->head), &(tree->tail), fr); \ + mln_rbtree_inline_node_free(tree, fr, freer); \ + } \ + tree->root = &(tree->nil); \ + tree->min = &(tree->nil); \ + tree->iter = NULL; \ + tree->nr_node = 0; \ + tree->del = 0; \ +}) + +#define mln_rbtree_node_init(n, ud) ({ \ + (n)->data = (ud); \ + (n)->nofree = 1; \ + (n); \ +}) + +#define mln_rbtree_node_num(ptree) ((ptree)->nr_node) +#define mln_rbtree_null(ptr, ptree) ((ptr) == &((ptree)->nil)) +#define mln_rbtree_node_data_get(node) ((node)->data) +#define mln_rbtree_node_data_set(node, ud) ((node)->data = (ud)) +#define mln_rbtree_root(ptree) ((ptree)->root) + +extern mln_rbtree_t *mln_rbtree_new(struct mln_rbtree_attr *attr); +extern mln_rbtree_t *mln_rbtree_init(struct mln_rbtree_attr *attr, mln_rbtree_t *t); +extern void mln_rbtree_free(mln_rbtree_t *t); +extern void mln_rbtree_insert(mln_rbtree_t *t, mln_rbtree_node_t *node) __NONNULL2(1, 2); +mln_rbtree_node_t *mln_rbtree_search(mln_rbtree_t *t, void *key) __NONNULL2(1, 2); +extern void mln_rbtree_delete(mln_rbtree_t *t, mln_rbtree_node_t *n) __NONNULL2(1, 2); +extern mln_rbtree_node_t *mln_rbtree_successor(mln_rbtree_t *t, mln_rbtree_node_t *n) __NONNULL2(1, 2); +extern mln_rbtree_node_t *mln_rbtree_min(mln_rbtree_t *t) __NONNULL1(1); +extern void mln_rbtree_reset(mln_rbtree_t *t) __NONNULL1(1); + +extern mln_rbtree_node_t *mln_rbtree_node_new(mln_rbtree_t *t, void *data) __NONNULL2(1, 2); +extern void mln_rbtree_node_free(mln_rbtree_t *t, mln_rbtree_node_t *n) __NONNULL2(1, 2); + +extern int mln_rbtree_iterate(mln_rbtree_t *t, rbtree_iterate_handler handler, void *udata) __NONNULL2(1, 2); +#endif diff --git a/mkrtos_knl/knl/mm/mln_types.h b/mkrtos_knl/knl/mm/mln_types.h new file mode 100644 index 000000000..305576288 --- /dev/null +++ b/mkrtos_knl/knl/mm/mln_types.h @@ -0,0 +1,69 @@ + +/* + * Copyright (C) Niklaus F.Schen. + */ + +#ifndef __MLN_TYPES +#define __MLN_TYPES + +// #include +#include +// #include +#include "mln_utils.h" +#if defined(__GNUC__) && (__GNUC__ >= 4 && __GNUC_MINOR__ > 1) +typedef long mln_spin_t; +#elif defined(i386) || defined(__x86_64) +typedef unsigned long mln_spin_t; +#else +#include +typedef pthread_spinlock_t mln_spin_t; +#endif + +typedef unsigned char mln_u8_t; +typedef char mln_s8_t; +typedef unsigned short mln_u16_t; +typedef short mln_s16_t; +typedef unsigned int mln_u32_t; +typedef int mln_s32_t; +#if defined(i386) || defined(__arm__) || defined(__WIN32__) || defined(__wasm__) +typedef unsigned long long mln_u64_t; +typedef long long mln_s64_t; +#else +typedef unsigned long mln_u64_t; +typedef long mln_s64_t; +#endif +typedef char *mln_s8ptr_t; +typedef unsigned char *mln_u8ptr_t; +typedef short *mln_s16ptr_t; +typedef unsigned short *mln_u16ptr_t; +typedef int *mln_s32ptr_t; +typedef unsigned int *mln_u32ptr_t; +#if defined(i386) || defined(__arm__) || defined(__WIN32__) || defined(__wasm__) +typedef long long *mln_s64ptr_t; +typedef unsigned long long *mln_u64ptr_t; +#else +typedef long *mln_s64ptr_t; +typedef unsigned long *mln_u64ptr_t; +#endif +typedef size_t mln_size_t; +typedef long mln_off_t; +#if defined(__WIN32__) +#if defined(i386) || defined(__arm__) +typedef long mln_sptr_t; +typedef unsigned long mln_uptr_t; +typedef long mln_sauto_t; +typedef unsigned long mln_uauto_t; +#else +typedef long long mln_sptr_t; +typedef unsigned long long mln_uptr_t; +typedef long long mln_sauto_t; +typedef unsigned long long mln_uauto_t; +#endif +#else +typedef long mln_sptr_t; +typedef unsigned long mln_uptr_t; +typedef long mln_sauto_t; +typedef unsigned long mln_uauto_t; +#endif + +#endif diff --git a/mkrtos_knl/knl/mm/mln_utils.h b/mkrtos_knl/knl/mm/mln_utils.h new file mode 100644 index 000000000..40ff1a18b --- /dev/null +++ b/mkrtos_knl/knl/mm/mln_utils.h @@ -0,0 +1,166 @@ + +/* + * Copyright (C) Niklaus F.Schen. + */ +#ifndef __MLN_DEFS_H +#define __MLN_DEFS_H + +// #include +#include "mln_func.h" + +#ifdef __DEBUG__ +#include +#define ASSERT(x) assert(x) +#else +#define ASSERT(x); +#endif + +/* + * container_of and offsetof + */ +#define mln_offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#define mln_container_of(ptr, type, member) ({\ + type *__rptr = NULL;\ + if ((ptr) != NULL) {\ + __rptr = (type *)((char *)((const typeof(((type *)0)->member) *)(ptr)) - mln_offsetof(type, member));\ + }\ + __rptr;\ +}) + +/* + * nonnull attribute + */ +#if defined(__APPLE__) || defined(__WIN32__) || defined(__wasm__) +#define __NONNULL1(x) +#define __NONNULL2(x,y) +#define __NONNULL3(x,y,z) +#define __NONNULL4(w,x,y,z) +#define __NONNULL5(v,w,x,y,z) +#else +#define __NONNULL1(x) +#define __NONNULL2(x,y) +#define __NONNULL3(x,y,z) +#define __NONNULL4(w,x,y,z) +#define __NONNULL5(v,w,x,y,z) +#endif + +/* + * lock + */ +#if defined(__GNUC__) && (__GNUC__ >= 4 && __GNUC_MINOR__ > 1) + +extern void spin_lock(void *lock); +extern void spin_unlock(void *lock); +extern int spin_trylock(void *lock); +#define mln_spin_lock spin_lock +#define mln_spin_unlock spin_unlock +#define mln_spin_trylock spin_trylock +#define mln_spin_init(lock_ptr) (*(lock_ptr) = 0) +#define mln_spin_destroy(lock_ptr) (*(lock_ptr) = 0) + +#elif defined(i386) || defined(__x86_64) + +extern void spin_lock(void *lock); +extern void spin_unlock(void *lock); +extern int spin_trylock(void *lock); +#define mln_spin_lock spin_lock +#define mln_spin_unlock spin_unlock +#define mln_spin_trylock spin_trylock +#define mln_spin_init(lock_ptr) (*(lock_ptr) = 0) +#define mln_spin_destroy(lock_ptr) (*(lock_ptr) = 0) + +#else + +/* + * In FreeBSD, pthread_spin_init() will call calloc(), + * so we cannot use these interfaces in FreeBSD to + * implement malloc(). + */ +#define mln_spin_trylock pthread_spin_trylock +#define mln_spin_lock pthread_spin_lock +#define mln_spin_unlock pthread_spin_unlock +#define mln_spin_init(lock_ptr) \ + pthread_spin_init((lock_ptr), PTHREAD_PROCESS_PRIVATE) +#define mln_spin_destroy(lock_ptr) \ + pthread_spin_destroy((lock_ptr)) + +#endif + +/* + * Chain + */ +#define MLN_CHAIN_FUNC_DECLARE(scope,prefix,type,func_attr); \ + scope void prefix##_chain_add(type **head, type **tail, type *node) func_attr;\ + scope void prefix##_chain_del(type **head, type **tail, type *node) func_attr; + +#define MLN_CHAIN_FUNC_DEFINE(scope,prefix,type,prev_ptr,next_ptr); \ + MLN_FUNC_VOID(scope, void, prefix##_chain_add, (type **head, type **tail, type *node), (head, tail, node), { \ + node->next_ptr = NULL;\ + if (*head == NULL) {\ + *head = node;\ + } else {\ + (*tail)->next_ptr = node;\ + }\ + node->prev_ptr = (*tail);\ + *tail = node;\ + })\ + \ + MLN_FUNC_VOID(scope, void, prefix##_chain_del, (type **head, type **tail, type *node), (head, tail, node), { \ + if (*head == node) {\ + if (*tail == node) {\ + *head = *tail = NULL;\ + } else {\ + *head = node->next_ptr;\ + (*head)->prev_ptr = NULL;\ + }\ + } else {\ + if (*tail == node) {\ + *tail = node->prev_ptr;\ + (*tail)->next_ptr = NULL;\ + } else {\ + node->prev_ptr->next_ptr = node->next_ptr;\ + node->next_ptr->prev_ptr = node->prev_ptr;\ + }\ + }\ + node->prev_ptr = node->next_ptr = NULL;\ + }) + +#define mln_bigendian_encode(num,buf,Blen); \ +{\ + size_t i;\ + for (i = 0; i < Blen; ++i) {\ + *(buf)++ = ((mln_u64_t)(num) >> ((Blen-i-1) << 3)) & 0xff;\ + }\ +} + +#define mln_bigendian_decode(num,buf,Blen); \ +{\ + size_t i;\ + num = 0;\ + for (i = 0; i < Blen; ++i, ++buf) {\ + num |= ((((mln_u64_t)(*(buf))) & 0xff) << (((Blen)-i-1) << 3));\ + }\ +} + +#if defined(__WIN32__) +extern int pipe(int fds[2]); +extern int socketpair(int domain, int type, int protocol, int sv[2]); +#define mln_socket_close closesocket +#else +#define mln_socket_close close +#endif + +#define mln_isalpha(x) (((x) >= 'a' && (x) <= 'z') || ((x) >= 'A' && (x) <= 'Z')) +#define mln_isdigit(x) ((x) >= '0' && (x) <= '9') +#define mln_isascii(x) ((x) >= 0 && (x) <= 127) +#define mln_isprint(x) ((x) >= 32 && (x) <= 126) +#define mln_iswhitespace(x) ((x) == ' ' || (x) == '\t' || (x) == '\n' || (x) == '\f' || (x) == '\r' || (x) == '\v') + +#if defined(MLN_C99) && defined(__linux__) +extern void usleep(unsigned long usec); +#endif + +#define MLN_AUTHOR "Niklaus F.Schen" + +#endif + diff --git a/mkrtos_knl/knl/mm/rbtree_mm.c b/mkrtos_knl/knl/mm/rbtree_mm.c new file mode 100644 index 000000000..b863641a0 --- /dev/null +++ b/mkrtos_knl/knl/mm/rbtree_mm.c @@ -0,0 +1,64 @@ +#include "mln_rbtree.h" +#include +#include +#include +#include +#include +static slab_t *rbtree_node_slab; + +static void *mk_rbtree_pool_alloc_handler(void *pool, mln_size_t size) +{ + void *mem = NULL; + + assert(size < PAGE_SIZE); + + switch (size) + { + case sizeof(mln_rbtree_node_t): + mem = slab_alloc(rbtree_node_slab); + if (!mem) + { + return NULL; + } + *((size_t *)mem) = size; + mem = (char *)mem + sizeof(void *); + break; + default: + assert(0); + break; + } + return mem; +} +static void mk_rbtree_pool_free_handler(void *data) +{ + void *mem = (char *)data - sizeof(void *); + size_t size = *((size_t *)mem); + switch (size) + { + case sizeof(mln_rbtree_node_t): + slab_free(rbtree_node_slab, mem); + break; + default: + assert(0); + break; + } +} + +static void rbtree_node_slab_init(void) +{ + rbtree_node_slab = slab_create(sizeof(mln_rbtree_node_t) + sizeof(void *), + "rbtree node slab"); + assert(rbtree_node_slab); +} +INIT_KOBJ_MEM(rbtree_node_slab_init); + +void rbtree_mm_init(mln_rbtree_t *root_rbtree) +{ + struct mln_rbtree_attr rbattr; + + rbattr.pool_alloc = mk_rbtree_pool_alloc_handler; + rbattr.pool_free = mk_rbtree_pool_free_handler; + rbattr.cmp = NULL; + rbattr.data_free = NULL; + mln_rbtree_init(&rbattr, root_rbtree); +} \ No newline at end of file diff --git a/mkrtos_knl/knl/mm/rbtree_mm.h b/mkrtos_knl/knl/mm/rbtree_mm.h new file mode 100644 index 000000000..4f1cd2bd7 --- /dev/null +++ b/mkrtos_knl/knl/mm/rbtree_mm.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +void rbtree_mm_init(mln_rbtree_t *root_rbtree); diff --git a/mkrtos_knl/knl/mm/vma.c b/mkrtos_knl/knl/mm/vma.c new file mode 100644 index 000000000..9d2d8228f --- /dev/null +++ b/mkrtos_knl/knl/mm/vma.c @@ -0,0 +1,723 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static slab_t *vma_slab; + +/** + * @brief 在系统初始化时调用,初始化vma的内存 + * + */ +static void vma_slab_init(void) +{ + vma_slab = slab_create(sizeof(vma_t), "vma"); + assert(vma_slab); +} +INIT_KOBJ_MEM(vma_slab_init); + +static vma_t *vma_alloc(void) +{ + vma_t *pvma = slab_alloc(vma_slab); + + if (!pvma) + { + return NULL; + } + memset(pvma, 0, sizeof(*pvma)); + return pvma; +} +static void vma_free(vma_t *data) +{ + slab_free(vma_slab, data); +} +static mln_rbtree_node_t *vma_node_create(mln_rbtree_t *r_tree, vma_addr_t addr, size_t size, paddr_t paddr) +{ + mln_rbtree_node_t *node = NULL; + vma_t *data_vma = vma_alloc(); + + if (data_vma == NULL) + { + return NULL; + } + + data_vma->vaddr = addr; + data_vma->size = size; + data_vma->paddr_raw = paddr; + + node = mln_rbtree_node_new(r_tree, data_vma); + + if (mln_rbtree_null(node, r_tree)) + { + return NULL; + } + + return node; +} +static void vma_node_free(mln_rbtree_t *r_tree, mln_rbtree_node_t *node) +{ + vma_free(mln_rbtree_node_data_get(node)); + mln_rbtree_node_free(r_tree, node); +} + +int task_vma_init(task_vma_t *vma) +{ + rbtree_mm_init(&vma->idle_tree); + rbtree_mm_init(&vma->alloc_tree); + + mln_rbtree_node_t *node; + + node = vma_node_create(&vma->idle_tree, + vma_addr_create(0, 0, 0x1000), + 0x100000000 - 0x1000, + 0); + mln_rbtree_insert(&vma->idle_tree, node); +} + +static mln_rbtree_node_t *task_vma_tree_find(mln_rbtree_t *tree, rbtree_cmp cmp, void *data) +{ + mln_rbtree_node_t *rn; + + tree->cmp = cmp; + rn = mln_rbtree_search(tree, &data); + if (mln_rbtree_null(rn, tree)) + { + return NULL; + } + + return rn; +} + +typedef struct vma_idl_tree_insert_params +{ + vaddr_t addr; + size_t size; +} vma_idl_tree_insert_params_t; +/** + * 返回值: + * -1 第一个参数小于第二个参数 + * 0 两个参数相同 + * 1 第一个参数大于第二个参数 + */ +static int vma_idl_tree_insert_cmp_handler(const void *key, const void *data) +{ + vma_t *key_p = (vma_t *)key; + vma_t *data_p = (vma_t *)data; + + if (vma_addr_get_addr(key_p->vaddr) + key_p->size <= vma_addr_get_addr(data_p->vaddr)) + { + return -1; + } + else if (vma_addr_get_addr(key_p->vaddr) >= vma_addr_get_addr(data_p->vaddr) && + (vma_addr_get_addr(key_p->vaddr) + key_p->size) <= vma_addr_get_addr(data_p->vaddr) + data_p->size) + { + return 0; + } + else + { + return 1; + } +} +/** + * 返回值: + * -1 第一个参数小于第二个参数 + * 0 两个参数相同 + * 1 第一个参数大于第二个参数 + */ +static int vma_idl_tree_alloc_cmp_handler(const void *key, const void *data) +{ + vma_idl_tree_insert_params_t *key_p = (vma_idl_tree_insert_params_t *)key; + vma_t *data_p = (vma_t *)data; + + if (key_p->addr + key_p->size <= vma_addr_get_addr(data_p->vaddr)) + { + return -1; + } + else if (key_p->addr >= vma_addr_get_addr(data_p->vaddr) && + (key_p->addr + key_p->size) <= vma_addr_get_addr(data_p->vaddr) + data_p->size) + { + return 0; + } + else + { + return 1; + } +} +typedef struct vma_idl_tree_iter_params +{ + // vaddr_t addr; + size_t size; + + mln_rbtree_node_t *ret_node; +} vma_idl_tree_iter_params_t; +/** + * @brief 空闲块迭代查找需要的大小 + * + * @param node + * @param udata + * @return int + */ +static int rbtree_iterate_idle_tree_find(mln_rbtree_node_t *node, void *udata) +{ + vma_idl_tree_iter_params_t *param = udata; + vma_t *node_data = mln_rbtree_node_data_get(node); + + if (!(node_data->flags & VMA_USED_NODE)) + { + if (node_data->size >= param->size) + { + param->ret_node = node; + return -1; + } + } + return 0; +} +/** + * @brief 在空闲块中找到指定大小的节点 + * + * @param task_vma + * @param addr + * @param size + * @return mln_rbtree_node_t* + */ +static mln_rbtree_node_t *task_vma_idle_tree_find(task_vma_t *task_vma, size_t size) +{ + vma_idl_tree_iter_params_t param = { + .size = size, + }; + int ret; + + ret = mln_rbtree_iterate(&task_vma->idle_tree, rbtree_iterate_idle_tree_find, ¶m); + if (ret >= 0) + { + return NULL; + } + return param.ret_node; +} +/** + * @brief 分割节点 + * 1.删除原来的节点 + * 2.分割节点 分割时考虑三个情况 + * @param r_tree + * @param node + * @return int + */ +static int task_vma_node_split(mln_rbtree_t *r_tree, mln_rbtree_node_t *node, vaddr_t addr, size_t size) +{ + vma_t *data; + int ret = -EINVAL; + + assert(r_tree); + assert(node); + mln_rbtree_delete(r_tree, node); + data = mln_rbtree_node_data_get(node); + + assert((addr >= vma_addr_get_addr(data->vaddr)) && + addr + size <= vma_addr_get_addr(data->vaddr) + data->size); + //!< 检查地址在合理的范围之内 + + if (addr == vma_addr_get_addr(data->vaddr) && size == data->size) + { + /*大小正好相等,则什么都不用做*/ + } + else if (addr == vma_addr_get_addr(data->vaddr)) + { + //!< 左对齐 + mln_rbtree_node_t *r_node; + + r_node = vma_node_create(r_tree, + vma_addr_create(data->vaddr.prot, data->vaddr.flags, + vma_addr_get_addr(data->vaddr) + size), + data->size - size, 0); + if (r_node == NULL) + { + ret = -ENOMEM; + goto err_ret; + } + r_tree->cmp = vma_idl_tree_insert_cmp_handler; + mln_rbtree_insert(r_tree, r_node); + } + else if (addr + size == vma_addr_get_addr(data->vaddr) + data->size) + { + //!< 右对齐 + mln_rbtree_node_t *r_node; + + r_node = vma_node_create(r_tree, + vma_addr_create(data->vaddr.prot, data->vaddr.flags, + vma_addr_get_addr(data->vaddr)), + data->size - size, 0); + if (r_node == NULL) + { + ret = -ENOMEM; + goto err_ret; + } + r_tree->cmp = vma_idl_tree_insert_cmp_handler; + mln_rbtree_insert(r_tree, r_node); + } + else + { + // 在中间分割成两个 + mln_rbtree_node_t *r_node; + + r_node = vma_node_create(r_tree, + vma_addr_create(data->vaddr.prot, data->vaddr.flags, + vma_addr_get_addr(data->vaddr)), + addr - vma_addr_get_addr(data->vaddr), 0); + if (r_node == NULL) + { + ret = -ENOMEM; + goto err_ret; + } + + mln_rbtree_node_t *l_node; + + l_node = vma_node_create(r_tree, + vma_addr_create(data->vaddr.prot, data->vaddr.flags, + addr + size), + vma_addr_get_addr(data->vaddr) + data->size - (addr + size), 0); + if (l_node == NULL) + { + vma_node_free(r_tree, r_node); + ret = -ENOMEM; + goto err_ret; + } + r_tree->cmp = vma_idl_tree_insert_cmp_handler; + mln_rbtree_insert(r_tree, l_node); + mln_rbtree_insert(r_tree, r_node); + } + vma_addr_set_addr(&data->vaddr, addr); //!< 重设分割后的地址&大小 + data->size = size; + + ret = 0; + goto ret; +err_ret: + // 刚刚删除了这里要插入回去 + r_tree->cmp = vma_idl_tree_insert_cmp_handler; + mln_rbtree_insert(r_tree, node); +ret: + return ret; +} +mword_t task_vma_lock(task_vma_t *task_vma) +{ + task_t *task; + mword_t ret; + + task = container_of(container_of(task_vma, mm_space_t, mem_vma), task_t, mm_space); + + ret = spinlock_lock(&task->kobj.lock); + if (ret < 0) + { + return ret; + } + return ret; +} +void task_vma_unlock(task_vma_t *task_vma, mword_t status) +{ + task_t *task; + mword_t ret; + + task = container_of(container_of(task_vma, mm_space_t, mem_vma), task_t, mm_space); + spinlock_set(&task->kobj.lock, status); +} +/** + * 分配步骤 + * 1.找到一个空闲的合适的虚拟内存区域 + * 2.用申请的区域去分割找到的区域 + * 3.将申请的区域插入回去,并设置属性 + */ +int task_vma_alloc(task_vma_t *task_vma, vma_addr_t vaddr, size_t size, + paddr_t paddr, vaddr_t *ret_vaddr) +{ + int ret; + mln_rbtree_node_t *node; + vma_t *node_data; + mword_t lock_status; + vaddr_t alloc_addr; + + if ((size & (PAGE_SIZE - 1)) != 0) + { + return -EINVAL; + } + lock_status = task_vma_lock(task_vma); + if (lock_status < 0) + { + return lock_status; + } + if (vma_addr_get_addr(vaddr) == 0) + { + node = task_vma_idle_tree_find(task_vma, size); + if (!node) + { + ret = -ENOMEM; + goto end; + } + node_data = mln_rbtree_node_data_get(node); + alloc_addr = vma_addr_get_addr(node_data->vaddr); + } + else + { + alloc_addr = vma_addr_get_addr(vaddr); + + task_vma->idle_tree.cmp = vma_idl_tree_alloc_cmp_handler; + node = mln_rbtree_search( + &task_vma->idle_tree, + &(vma_idl_tree_insert_params_t){ + .size = size, + .addr = alloc_addr, + }); //!< 查找是否存在 + if (mln_rbtree_null(node, &task_vma->idle_tree)) + { + ret = -ENOENT; + goto end; + } + if (vma_node_get_used(mln_rbtree_node_data_get(node))) + { + ret = -EEXIST; + goto end; + } + node_data = mln_rbtree_node_data_get(node); + } + + ret = task_vma_node_split(&task_vma->idle_tree, node, + alloc_addr, size); + if (ret < 0) + { + goto end; + } + //!< 设置当前节点是使用节点,设置属性等,并插入到树中 + vma_node_set_used(node_data); + vma_addr_set_flags(&node_data->vaddr, vma_addr_get_flags(vaddr)); + vma_addr_set_prot(&node_data->vaddr, vma_addr_get_prot(vaddr)); + task_vma->idle_tree.cmp = vma_idl_tree_insert_cmp_handler; + mln_rbtree_insert(&task_vma->idle_tree, node); + + if (ret_vaddr) + { + //!< 设置分配后的地址 + *ret_vaddr = alloc_addr; + } + printk("alloc:[0x%x 0x%x]\n", alloc_addr, alloc_addr + size - 1); + ret = 0; +end: + task_vma_unlock(task_vma, lock_status); + return ret; +} +/** + * @brief 完全相等 + * 返回值: + * -1 第一个参数小于第二个参数 + * 0 两个参数相同 + * 1 第一个参数大于第二个参数 + */ +static int vma_idl_tree_free_cmp_handler(const void *key, const void *data) +{ + vma_idl_tree_insert_params_t *key_p = (vma_idl_tree_insert_params_t *)key; + vma_t *data_p = (vma_t *)data; + + if (key_p->addr + key_p->size <= vma_addr_get_addr(data_p->vaddr)) + { + return -1; + } + else if (key_p->addr == vma_addr_get_addr(data_p->vaddr) && + (key_p->addr + key_p->size) == vma_addr_get_addr(data_p->vaddr) + data_p->size) + { + return 0; + } + else + { + return 1; + } +} +/** + * @brief 合并节点 + * + * @param r_tree + * @param node + * @return int + */ +static int vma_node_merge(mln_rbtree_t *r_tree, mln_rbtree_node_t *node) +{ + assert(r_tree); + assert(node); + + mln_rbtree_node_t *rnode; + mln_rbtree_node_t *lnode; + vma_t *r_datanode; + vma_t *l_datanode; + vma_t *data_node; + + rnode = node->right; + lnode = node->left; + + r_tree->cmp = vma_idl_tree_insert_cmp_handler; + + data_node = mln_rbtree_node_data_get(node); + mln_rbtree_delete(r_tree, node); + + if (mln_rbtree_null(lnode, r_tree) && mln_rbtree_null(rnode, r_tree)) + { + // 左右都是空的 + return 0; + } + else if (mln_rbtree_null(lnode, r_tree)) + { + // 左边是空的 + r_datanode = mln_rbtree_node_data_get(rnode); + + if (vma_node_get_used(r_datanode) != vma_node_get_used(data_node)) + { + return 0; + } + data_node->size += r_datanode->size; + mln_rbtree_delete(r_tree, rnode); + vma_node_free(r_tree, rnode); + + mln_rbtree_insert(r_tree, node); + } + else if (mln_rbtree_null(rnode, r_tree)) + { + // 右边是空的 + r_datanode = mln_rbtree_node_data_get(rnode); + + if (vma_node_get_used(r_datanode) != vma_node_get_used(data_node)) + { + return 0; + } + mln_rbtree_delete(r_tree, rnode); + r_datanode->size += data_node->size; + vma_addr_set_addr(&r_datanode->vaddr, vma_addr_get_addr(data_node->vaddr)); + mln_rbtree_insert(r_tree, rnode); + vma_node_free(r_tree, node); + } + return 0; +} +typedef struct vma_idl_tree_iter_del_params +{ + vaddr_t addr; + size_t size; + mln_rbtree_t *r_tree; + mm_space_t *mm_space; +} vma_idl_tree_iter_del_params_t; +/** + * @brief 迭代删除 + * + * @param node + * @param udata + * @return int + */ +static int rbtree_iterate_alloc_tree_del(mln_rbtree_node_t *node, void *udata) +{ + vma_idl_tree_iter_del_params_t *param = udata; + vma_t *node_data = mln_rbtree_node_data_get(node); + + if (vma_addr_get_addr(node_data->vaddr) >= param->addr && + vma_addr_get_addr(node_data->vaddr) + node_data->size <= param->addr + param->size) + { + // 解除映射 + unmap_mm(mm_space_get_pdir(param->mm_space), vma_addr_get_addr(node_data->vaddr), PAGE_SHIFT, 1); + + // 从红黑树中删除 + mln_rbtree_delete(param->r_tree, node); + vma_node_free(param->r_tree, node); + } + return 0; +} +/** + * @brief 释放申请的虚拟内存,并释放已经申请的物理内存 + * 1.从分配树中找到需要的节点 + * 2.迭代释放物理内存 + * 3.设置节点为空闲节点,并与周围的合并 + * @param task_vma + * @param addr + * @param size + * @return int + */ +int task_vma_free(task_vma_t *task_vma, vaddr_t addr, size_t size) +{ + int ret = -EINVAL; + mln_rbtree_node_t *find_node; + vma_t *node_data; + mword_t lock_status; + + assert(task_vma); + lock_status = task_vma_lock(task_vma); + if (lock_status < 0) + { + return lock_status; + } + task_vma->idle_tree.cmp = vma_idl_tree_free_cmp_handler; + find_node = mln_rbtree_search( + &task_vma->idle_tree, + &(vma_idl_tree_insert_params_t){ + .size = size, + .addr = addr, + }); //!< 查找是否存在 + if (mln_rbtree_null(find_node, &task_vma->idle_tree)) + { + ret = -ENOENT; + goto end; + } + node_data = mln_rbtree_node_data_get(find_node); + if (!(node_data->flags & VMA_USED_NODE)) //!< 必须被分配的 + { + ret = -ENOENT; + goto end; + } + /*释放已经分配的物理内存,并解除mmu的映射*/ + vma_idl_tree_iter_del_params_t param = { + .r_tree = &task_vma->alloc_tree, + .mm_space = container_of(task_vma, mm_space_t, mem_vma), + .addr = addr, + .size = size, + }; + mln_rbtree_iterate(&task_vma->alloc_tree, rbtree_iterate_alloc_tree_del, ¶m); + vma_node_merge(&task_vma->idle_tree, find_node); + ret = 0; +end: + task_vma_unlock(task_vma, lock_status); + return ret; +} +/** + * 返回值: + * -1 第一个参数小于第二个参数 + * 0 两个参数相同 + * 1 第一个参数大于第二个参数 + */ +static int vma_idl_tree_wrap_cmp_handler(const void *key, const void *data) +{ + vma_idl_tree_insert_params_t *key_p = (vma_idl_tree_insert_params_t *)key; + vma_t *data_p = (vma_t *)data; + + if (key_p->addr + key_p->size <= vma_addr_get_addr(data_p->vaddr)) + { + return -1; + } + else if (key_p->addr >= vma_addr_get_addr(data_p->vaddr) && + (key_p->addr + key_p->size) <= vma_addr_get_addr(data_p->vaddr) + data_p->size) + { + return 0; + } + else + { + return 1; + } +} +/** + * @brief 缺页的处理流程 + * 1.查找已经分配的表中是否存在 + * 2.分配物理内存 + * 3.插入到已分配树中去 + * @param task_vma + * @param addr + * @return int + */ +int task_vma_page_fault(task_vma_t *task_vma, vaddr_t addr) +{ + mln_rbtree_node_t *find_node = NULL; + vma_t *node_data = NULL; + void *mem = NULL; + task_t *task; + mword_t lock_status; + int ret; + + assert(task_vma); + lock_status = task_vma_lock(task_vma); + if (lock_status < 0) + { + return lock_status; + } + printk("page fault:0x%x.\n", addr); + // 1.查找 + task = container_of(container_of(task_vma, mm_space_t, mem_vma), task_t, mm_space); + task_vma->idle_tree.cmp = vma_idl_tree_wrap_cmp_handler; + find_node = mln_rbtree_search( + &task_vma->idle_tree, + &(vma_idl_tree_insert_params_t){ + .size = PAGE_SIZE, + .addr = addr, + }); //!< 查找是否存在 + if (mln_rbtree_null(find_node, &task_vma->idle_tree)) + { + ret = -ENOENT; + goto end; + } + node_data = mln_rbtree_node_data_get(find_node); + if (!(node_data->flags & VMA_USED_NODE)) //!< 必须被分配的 + { + ret = -ENOENT; + goto end; + } + // 2.申请物理内存 + if (vma_addr_get_flags(node_data->vaddr) & VMA_ADDR_RESV) + { + if (!vma_node_get_paddr(node_data)) + { + mem = NULL; + } + else + { + mem = (void *)(addr - vma_addr_get_addr(node_data->vaddr) + + vma_node_get_paddr(node_data)); + } + } + else + { + mem = buddy_alloc(buddy_get_alloter(), PAGE_SIZE); + memset(mem, 0, PAGE_SIZE); + } + if (!mem) + { + ret = -ENOMEM; + goto end; + } + // 3.插入到分配树中 + mln_rbtree_node_t *alloc_node; + + alloc_node = vma_node_create(&task_vma->alloc_tree, + vma_addr_create(vma_addr_get_prot(node_data->vaddr), + vma_addr_get_flags(node_data->vaddr), addr), + PAGE_SIZE, (paddr_t)mem); + if (alloc_node == NULL) + { + if (!(vma_addr_get_flags(node_data->vaddr) & VMA_ADDR_RESV)) + { + buddy_free(buddy_get_alloter(), mem); + } + ret = -ENOMEM; + goto end; + } + // 4.进行映射 + ret = map_mm(mm_space_get_pdir(&task->mm_space), addr, + (addr_t)mem, PAGE_SHIFT, 1, 0x7ff); /*TODO:设置权限*/ + if (ret < 0) + { + ret = -ENOMEM; + goto end; + } + ret = 0; +end: + task_vma_unlock(task_vma, lock_status); + return ret; +} +/** + * @brief 释放task_vma + * + * @param task_vma + * @return int + */ +int task_vma_clean(task_vma_t *task_vma) +{ + /*TODO: */ + return 0; +} diff --git a/mkrtos_knl/knl/mm/vma_obj.c b/mkrtos_knl/knl/mm/vma_obj.c new file mode 100644 index 000000000..eb478e56e --- /dev/null +++ b/mkrtos_knl/knl/mm/vma_obj.c @@ -0,0 +1,107 @@ +/** + * @file irq_sender.c + * @author ATShining (1358745329@qq.com) + * @brief + * @version 0.1 + * @date 2023-09-29 + * + * @copyright Copyright (c) 2023 + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +typedef struct vma_obj +{ + kobject_t kobj; + vma_t vmam; +} vma_obj_t; + +enum +{ + VMA_ALLOC, + VMA_FREE, +}; + +static void vma_obj_syscall(kobject_t *kobj, syscall_prot_t sys_p, msg_tag_t in_tag, entry_frame_t *f) +{ + assert(kobj); + assert(f); + msg_tag_t tag = msg_tag_init4(0, 0, 0, -EINVAL); + thread_t *th = thread_get_current(); + task_t *tk = thread_get_current_task(); + vma_obj_t *irq = container_of(kobj, vma_obj_t, kobj); + + if (sys_p.prot != VMA_PROT) + { + f->regs[0] = msg_tag_init4(0, 0, 0, -EPROTO).raw; + return; + } + + switch (sys_p.op) + { + case VMA_ALLOC: + { + int ret; + vaddr_t ret_vaddr = 0; + + ret = task_vma_alloc(&tk->mm_space.mem_vma, vam_addr_create_raw(f->regs[0]), f->regs[1], + f->regs[2], &ret_vaddr); + f->regs[0] = msg_tag_init4(0, 0, 0, ret).raw; + f->regs[1] = ret_vaddr; + } + break; + case VMA_FREE: + { + int ret; + + task_vma_free(&tk->mm_space.mem_vma, f->regs[0], f->regs[1]); + f->regs[0] = msg_tag_init4(0, 0, 0, ret).raw; + } + break; + } +} +static bool_t vma_obj_put(kobject_t *kobj) +{ + return 0; +} +static void vma_obj_stage1(kobject_t *kobj) +{ +} +static void vma_obj_stage2(kobject_t *kobj) +{ +} +/** + * @brief 初始化 + * + * @param irq + */ +void vma_obj_init(vma_obj_t *obj) +{ + kobject_init(&obj->kobj, VMAM_TYPE); + obj->kobj.invoke_func = vma_obj_syscall; + obj->kobj.stage_1_func = vma_obj_stage1; + obj->kobj.stage_2_func = vma_obj_stage2; + obj->kobj.put_func = vma_obj_put; +} +static vma_obj_t vma_obj; +/** + * @brief 初始化一个根工厂对象 + * + */ +static void root_factory_init(void) +{ + vma_obj_init(&vma_obj); + global_reg_kobj(&vma_obj.kobj, VMA_PROT); +} +INIT_KOBJ(root_factory_init); diff --git a/mkrtos_knl/knl/mm/vma_obj.h b/mkrtos_knl/knl/mm/vma_obj.h new file mode 100644 index 000000000..3f59c932d --- /dev/null +++ b/mkrtos_knl/knl/mm/vma_obj.h @@ -0,0 +1,2 @@ +#pragma once + diff --git a/mkrtos_knl/knl/mm_wrap.c b/mkrtos_knl/knl/mm_wrap.c index 1822cccee..7a9d30f9e 100755 --- a/mkrtos_knl/knl/mm_wrap.c +++ b/mkrtos_knl/knl/mm_wrap.c @@ -83,6 +83,10 @@ void mm_limit_free_align(ram_limit_t *limit, void *mem, size_t size) } #if IS_ENABLED(CONFIG_BUDDY_SLAB) #include +void *mm_buddy_alloc_one_page(void) +{ + return buddy_alloc(buddy_get_alloter(), PAGE_SIZE); +} void *mm_limit_alloc_buddy(ram_limit_t *limit, size_t size) { if (ram_limit_alloc(limit, size) == FALSE) diff --git a/mkrtos_knl/knl/slab.c b/mkrtos_knl/knl/slab.c index cd4991877..5b0479439 100755 --- a/mkrtos_knl/knl/slab.c +++ b/mkrtos_knl/knl/slab.c @@ -27,6 +27,7 @@ slab_t *slab_create(size_t align_size, const char *name) { return NULL; } + printk("alloc addr 0x%x.\n", mem); slab_t *tmp_slab = (slab_t *)mem; spinlock_init(&tmp_slab->lock); @@ -39,6 +40,10 @@ slab_t *slab_create(size_t align_size, const char *name) for (size_t i = 0; i < alloc_size / (align_size + sizeof(slab_block_head_t)); i++) { + if ((i + 1) * (align_size + sizeof(slab_block_head_t)) + (align_size + sizeof(slab_block_head_t)) > alloc_size) + { + break; + } slab_block_head_t *slab_block = (slab_block_head_t *)((mem + sizeof(slab_t)) + (i * (align_size + sizeof(slab_block_head_t)))); diff --git a/mkrtos_knl/knl/task.c b/mkrtos_knl/knl/task.c index df7df794f..1396ec8c1 100755 --- a/mkrtos_knl/knl/task.c +++ b/mkrtos_knl/knl/task.c @@ -358,6 +358,10 @@ static void task_release_stage1(kobject_t *kobj) kobj_del_list_init(&kobj_list); obj_unmap_all(&tk->obj_space, &kobj_list); kobj_del_list_to_do(&kobj_list); + +#if IS_ENABLED(CONFIG_MMU) + task_vma_clean(&tk->mm_space.mem_vma); +#endif } static void task_release_stage2(kobject_t *kobj) { diff --git a/mkrtos_knl/knl/thread.c b/mkrtos_knl/knl/thread.c index dc99e4caf..765c915b5 100755 --- a/mkrtos_knl/knl/thread.c +++ b/mkrtos_knl/knl/thread.c @@ -780,7 +780,7 @@ static void thread_syscall(kobject_t *kobj, syscall_prot_t sys_p, msg_tag_t in_t { if (is_rw_access(thread_get_bind_task(tag_th), (void *)(f->regs[1]), THREAD_MSG_BUG_LEN, FALSE)) { - thread_set_msg_bug(tag_th, (void *)(f->regs[1])); + thread_set_msg_bug(tag_th, NULL /*TODO:*/, (void *)(f->regs[1])); tag = msg_tag_init4(0, 0, 0, 0); } else @@ -791,9 +791,9 @@ static void thread_syscall(kobject_t *kobj, syscall_prot_t sys_p, msg_tag_t in_t } case MSG_BUG_GET: { - f->regs[1] = (umword_t)(tag_th->msg.msg); + f->regs[1] = (umword_t)(thread_get_msg_buf(tag_th)); f->regs[2] = THREAD_MSG_BUG_LEN; - if (tag_th->msg.msg == NULL) + if (thread_get_msg_buf(tag_th) == NULL) { tag = msg_tag_init4(0, 0, 0, -EACCES); } diff --git a/mkrtos_knl/knl/thread_knl.c b/mkrtos_knl/knl/thread_knl.c index 16597237d..1161b4c6f 100755 --- a/mkrtos_knl/knl/thread_knl.c +++ b/mkrtos_knl/knl/thread_knl.c @@ -98,7 +98,7 @@ static void knl_init_1(void) task_knl_init(&knl_task); thread_knl_pf_set(knl_thread, knl_main); thread_bind(knl_thread, &knl_task.kobj); - thread_set_msg_bug(knl_thread, knl_msg_buf); + thread_set_msg_bug(knl_thread, knl_msg_buf, knl_msg_buf); thread_ready(knl_thread, FALSE); slist_init(&del_task_head); @@ -135,8 +135,12 @@ static void knl_init_2(void) ret_addr = cpio_find_file(cpio_images, (umword_t)(-1), "init.elf", &size); assert(ret_addr); elf_load(init_task, ret_addr, size, &entry); - thread_set_msg_bug(init_thread, NULL /*TODO:*/); - thread_user_pf_set(init_thread, (void *)(entry), NULL, + void *init_msg_buf = mm_buddy_alloc_one_page(); + assert(init_msg_buf); + map_mm(mm_space_get_pdir(&init_task->mm_space), 0xE0000000, + (addr_t)init_msg_buf, PAGE_SHIFT, 1, 0x7ff); + thread_set_msg_bug(init_thread, (void *)init_msg_buf, (void *)0xE0000000); + thread_user_pf_set(init_thread, (void *)(entry), (void *)0xdeaddead, NULL, 0); #else app_info_t *app = app_info_get((void *)(CONFIG_KNL_TEXT_ADDR + CONFIG_INIT_TASK_OFFSET)); @@ -145,7 +149,7 @@ static void knl_init_2(void) void *sp_addr = (char *)init_task->mm_space.mm_block + app->i.stack_offset - app->i.data_offset; void *sp_addr_top = (char *)sp_addr + app->i.stack_size; - thread_set_msg_bug(init_thread, (char *)(init_task->mm_space.mm_block) + app->i.ram_size); + thread_set_msg_bug(init_thread, (char *)(init_task->mm_space.mm_block) + app->i.ram_size, (char *)(init_task->mm_space.mm_block) + app->i.ram_size); thread_user_pf_set(init_thread, (void *)(CONFIG_KNL_TEXT_ADDR + CONFIG_INIT_TASK_OFFSET), (void *)((umword_t)sp_addr_top - 8), init_task->mm_space.mm_block, 0); #endif diff --git a/mkrtos_knl/test/kthread_test.c b/mkrtos_knl/test/kthread_test.c index 0d3f37b68..31301ca64 100644 --- a/mkrtos_knl/test/kthread_test.c +++ b/mkrtos_knl/test/kthread_test.c @@ -18,6 +18,7 @@ static void th_test(void *arg) printk("%d ", a[i]); } printk("\n"); + thread_sched(); } } static void th_test2(void *arg) @@ -34,6 +35,7 @@ static void th_test2(void *arg) printk("%d,", a[i]); } printk("\n"); + thread_sched(); } } void kthread_test_init(void) diff --git a/mkrtos_user/lib/libc_backend/inc/syscall_backend.h b/mkrtos_user/lib/libc_backend/inc/syscall_backend.h index 09ce81b73..c52f450d5 100644 --- a/mkrtos_user/lib/libc_backend/inc/syscall_backend.h +++ b/mkrtos_user/lib/libc_backend/inc/syscall_backend.h @@ -63,7 +63,7 @@ long be_ioctl(long fd, long req, void *args); long be_set_tid_address(int *val); long be_set_thread_area(void *p); umword_t be_munmap(void *start, size_t len); -umword_t be_mmap2(void *start, +umword_t be_mmap(void *start, size_t len, long prot, long flags, @@ -71,7 +71,7 @@ umword_t be_mmap2(void *start, long _offset); long be_clock_gettime(clockid_t clk_id, struct timespec *tp); -long sys_mmap2(va_list ap); +long sys_mmap(va_list ap); long sys_set_tid_address(va_list ap); long sys_set_thread_area(va_list ap); void sys_exit(va_list ap); diff --git a/mkrtos_user/lib/libc_backend/src/aarch64/mm_backend.c b/mkrtos_user/lib/libc_backend/src/aarch64/mm_backend.c new file mode 100644 index 000000000..b72247b6e --- /dev/null +++ b/mkrtos_user/lib/libc_backend/src/aarch64/mm_backend.c @@ -0,0 +1,79 @@ +#include "u_types.h" +#include "syscall_backend.h" +#include "u_prot.h" +#include "u_ipc.h" +#include "u_mm.h" +#include "u_app.h" +#include "cons_cli.h" +#include "u_arch.h" +#include "u_vmam.h" +#include +#undef hidden +#undef weak +#define hidden +#include +umword_t be_mmap(void *start, + size_t len, + long prot, + long flags, + long fd, + long _offset) +{ + addr_t addr; + + if (len == 0) + { + return 0; + } + len = ALIGN(len, PAGE_SIZE); + // if ((len & ((1UL << CONFIG_PAGE_SHIFT) - 1)) != 0) + // { + // return -EINVAL; + // } + if (fd != -1) + { + return -ENOSYS; + } + msg_tag_t tag; + + tag = u_vmam_alloc(VMA_PROT, vma_addr_create(0xf /*TODO:*/, 0, 0), + len, 0, &addr); + if (msg_tag_get_val(tag) < 0) + { + return (umword_t)msg_tag_get_val(tag); + } + return addr; +} +long sys_mmap(va_list ap) +{ + void *start; + size_t len; + long prot; + long flags; + long fd; + long _offset; + + ARG_6_BE(ap, start, void *, len, size_t, prot, long, flags, long, fd, long, _offset, long); + + return be_mmap(start, len, prot, flags, fd, _offset); +} +umword_t be_munmap(void *start, size_t len) +{ + if ((len & (CONFIG_PAGE_SHIFT - 1)) != 0) + { + return -EINVAL; + } + msg_tag_t tag; + + tag = u_vmam_free(VMA_PROT, (addr_t)start, len); + + return msg_tag_get_val(tag); +} +long sys_munmap(va_list ap) +{ + void *start; + size_t len; + + ARG_2_BE(ap, len, size_t, start, void *); + return be_munmap(start, len); +} diff --git a/mkrtos_user/lib/libc_backend/src/aarch64/syscall_backend.c b/mkrtos_user/lib/libc_backend/src/aarch64/syscall_backend.c index fc6b1f4d3..2f9070fb2 100644 --- a/mkrtos_user/lib/libc_backend/src/aarch64/syscall_backend.c +++ b/mkrtos_user/lib/libc_backend/src/aarch64/syscall_backend.c @@ -7,14 +7,14 @@ typedef long (*sys_call_func)(va_list ap); static const sys_call_func sys_call_list[] = { // TODO: add syscall func pointer. - // [SYS_munmap] = sys_munmap, - // [SYS_mmap2] = sys_mmap2, - [SYS_read] = sys_be_read, // - [SYS_write] = sys_be_write, // - [SYS_writev] = sys_be_writev, // - [SYS_ioctl] = sys_be_ioctl, // - [SYS_set_tid_address] = sys_set_tid_address, // - // [__ARM_NR_set_tls] = sys_set_thread_area, // + [SYS_munmap] = sys_munmap, + [SYS_mmap] = sys_mmap, + [SYS_read] = sys_be_read, + [SYS_write] = sys_be_write, + [SYS_writev] = sys_be_writev, + [SYS_ioctl] = sys_be_ioctl, + [SYS_set_tid_address] = sys_set_tid_address, + // [__ARM_NR_set_tls] = sys_set_thread_area, // [SYS_exit] = be_exit, }; diff --git a/mkrtos_user/lib/libc_backend/src/fd_map.c b/mkrtos_user/lib/libc_backend/src/fd_map.c index 8b3493553..db77e1075 100644 --- a/mkrtos_user/lib/libc_backend/src/fd_map.c +++ b/mkrtos_user/lib/libc_backend/src/fd_map.c @@ -7,9 +7,6 @@ #include #include -// #define CONFIG_FD_MAP_ROW_CN 16 -// #define CONFIG_FD_MAP_ROW_NR 16 - #define FD_MAP_TOTAL (CONFIG_FD_MAP_ROW_CN * CONFIG_FD_MAP_ROW_NR) typedef struct fd_map_row diff --git a/mkrtos_user/lib/libc_backend/src/fs_backend.c b/mkrtos_user/lib/libc_backend/src/fs_backend.c index 8d3d16ddd..30f454874 100644 --- a/mkrtos_user/lib/libc_backend/src/fs_backend.c +++ b/mkrtos_user/lib/libc_backend/src/fs_backend.c @@ -14,6 +14,7 @@ #include #include "fd_map.h" #include "u_sleep.h" +// AUTO_CALL(101) void fs_backend_init(void) { assert(fd_map_alloc(0, 0, FD_TTY) >= 0); diff --git a/mkrtos_user/lib/sys/inc/u_arch.h b/mkrtos_user/lib/sys/inc/u_arch.h index 08712d41f..caf736025 100644 --- a/mkrtos_user/lib/sys/inc/u_arch.h +++ b/mkrtos_user/lib/sys/inc/u_arch.h @@ -1,6 +1,8 @@ #pragma once #include "u_types.h" #include "u_arch_hard.h" + + #define MK_PAGE_SIZE (1UL << CONFIG_PAGE_SHIFT) #define WORD_BYTES (sizeof(void *)) #define WORD_BITS (WORD_BYTES * 8) diff --git a/mkrtos_user/lib/sys/inc/u_prot.h b/mkrtos_user/lib/sys/inc/u_prot.h index 5c4800092..50e47dac9 100644 --- a/mkrtos_user/lib/sys/inc/u_prot.h +++ b/mkrtos_user/lib/sys/inc/u_prot.h @@ -13,7 +13,8 @@ enum kobj_prot SYS_PROT, FUTEX_PROT, IRQ_PROT, - SHARE_MEM_PROT, + SHARE_MEM_PROT, // 10 + VMA_PROT, MAX_PROT, }; diff --git a/mkrtos_user/lib/sys/inc/u_vmam.h b/mkrtos_user/lib/sys/inc/u_vmam.h new file mode 100644 index 000000000..dd6f3fd6d --- /dev/null +++ b/mkrtos_user/lib/sys/inc/u_vmam.h @@ -0,0 +1,32 @@ +#pragma once +#include +#include +typedef union vma_addr +{ + umword_t raw; + struct + { + umword_t prot : 4; + umword_t flags : 4; + umword_t resv : 4; + umword_t addr : (sizeof(void *) * 8 - CONFIG_PAGE_SHIFT); + }; +} vma_addr_t; + +static inline vma_addr_t vam_addr_create_raw(umword_t raw) +{ + return (vma_addr_t){ + .raw = raw, + }; +} +static inline vma_addr_t vma_addr_create(uint8_t prot, uint8_t flags, umword_t addr) +{ + return (vma_addr_t){ + .prot = prot, + .flags = flags, + .resv = 0, + .addr = addr >> CONFIG_PAGE_SHIFT, + }; +} +msg_tag_t u_vmam_alloc(obj_handler_t obj, vma_addr_t addr, size_t size, addr_t paddr, addr_t *vaddr); +msg_tag_t u_vmam_free(obj_handler_t obj, addr_t addr, size_t size); diff --git a/mkrtos_user/lib/sys/src/u_thread.c b/mkrtos_user/lib/sys/src/u_thread.c index 89a580b0b..a26fccc83 100644 --- a/mkrtos_user/lib/sys/src/u_thread.c +++ b/mkrtos_user/lib/sys/src/u_thread.c @@ -183,6 +183,10 @@ msg_tag_t thread_run(obj_handler_t obj, uint8_t prio) 0, 0, 0); + asm __volatile__("" + : + : + : ARCH_REG_0); msg_tag_t tag = msg_tag_init(r0); return tag; diff --git a/mkrtos_user/lib/sys/src/u_vmam.c b/mkrtos_user/lib/sys/src/u_vmam.c new file mode 100644 index 000000000..d15dd7c78 --- /dev/null +++ b/mkrtos_user/lib/sys/src/u_vmam.c @@ -0,0 +1,52 @@ + +#include +#include +#include + +enum +{ + VMA_ALLOC, + VMA_FREE, +}; + +msg_tag_t u_vmam_alloc(obj_handler_t obj, vma_addr_t addr, size_t size, addr_t paddr, addr_t *vaddr) +{ + register volatile umword_t r0 asm(ARCH_REG_0); + register volatile umword_t r1 asm(ARCH_REG_1); + + mk_syscall(syscall_prot_create4(VMA_ALLOC, VMA_PROT, obj, FALSE).raw, + addr.raw, + size, + paddr, + 0, + 0, + 0); + asm __volatile__("" + : + : + : ARCH_REG_0, ARCH_REG_1); + if (vaddr) + { + *vaddr = r1; + } + + return msg_tag_init(r0); +} + +msg_tag_t u_vmam_free(obj_handler_t obj, addr_t addr, size_t size) +{ + register volatile umword_t r0 asm(ARCH_REG_0); + + mk_syscall(syscall_prot_create4(VMA_ALLOC, VMA_PROT, obj, FALSE).raw, + addr, + size, + 0, + 0, + 0, + 0); + asm __volatile__("" + : + : + : ARCH_REG_0); + return msg_tag_init(r0); +} diff --git a/mkrtos_user/server/init/src/cons.c b/mkrtos_user/server/init/src/cons.c index 2fc1132e3..d5c2d457d 100644 --- a/mkrtos_user/server/init/src/cons.c +++ b/mkrtos_user/server/init/src/cons.c @@ -16,7 +16,7 @@ #include #include -static ATTR_ALIGN(8) uint8_t cons_stack[512]; +static ATTR_ALIGN(8) uint8_t cons_stack[4096]; // static uint8_t cons_msg_buf[MSG_BUG_LEN]; static cons_t cons_obj; static obj_handler_t cons_th; @@ -48,9 +48,9 @@ void console_init(void) { cons_svr_obj_init(&cons_obj); meta_reg_svr_obj(&cons_obj.svr, CONS_PROT); - u_thread_create(&cons_th, (char *)cons_stack + sizeof(cons_stack), NULL, console_read_func); + u_thread_create(&cons_th, (char *)cons_stack + sizeof(cons_stack) - 8, NULL, console_read_func); u_thread_run(cons_th, 3); - // printf("cons svr init...\n"); + ulog_write_str(LOG_PROT, "cons svr init...\n"); } /** * @brief 向控制台写入数据 diff --git a/mkrtos_user/server/init/src/main.c b/mkrtos_user/server/init/src/main.c index cd357dd0d..7a4b4e8ba 100644 --- a/mkrtos_user/server/init/src/main.c +++ b/mkrtos_user/server/init/src/main.c @@ -35,8 +35,9 @@ static void test(void) { - printf_test(); + malloc_test(); #if 0 + printf_test(); mpu_test(); sharea_mem_test(); ulog_test(); @@ -71,8 +72,8 @@ int main(int argc, char *args[]) test(); - ret = parse_cfg(DEFAULT_INIT_CFG, env); - printf("run app num is %d.\n", ret); + // ret = parse_cfg(DEFAULT_INIT_CFG, env); + // printf("run app num is %d.\n", ret); namespace_loop(); return 0; } diff --git a/mkrtos_user/server/init/src/test/malloc_test.c b/mkrtos_user/server/init/src/test/malloc_test.c new file mode 100644 index 000000000..a30961082 --- /dev/null +++ b/mkrtos_user/server/init/src/test/malloc_test.c @@ -0,0 +1,13 @@ +#include +#include +#include +void malloc_test(void) +{ +#define TEST_MEM_SIZE 1024 * 1024 * 32 + void *mem = malloc(TEST_MEM_SIZE); + assert(mem); + memset(mem, 0, TEST_MEM_SIZE); + + free(mem); +#undef TEST_MEM_SIZE +} diff --git a/mkrtos_user/server/init/src/test/mm_test.c b/mkrtos_user/server/init/src/test/mm_test.c index 6de2bbc09..313489840 100644 --- a/mkrtos_user/server/init/src/test/mm_test.c +++ b/mkrtos_user/server/init/src/test/mm_test.c @@ -16,6 +16,4 @@ void mm_test(void) mm_free_page(MM_PROT, mem1, 2); mm_free_page(MM_PROT, mem, 2); printf("mm test success.\n"); - // memset(mem, 0, 512); - // memset(mem1, 0, 512); } diff --git a/mkrtos_user/server/init/src/test/test.h b/mkrtos_user/server/init/src/test/test.h index 4fe77c59a..0b61df8d9 100644 --- a/mkrtos_user/server/init/src/test/test.h +++ b/mkrtos_user/server/init/src/test/test.h @@ -18,3 +18,4 @@ void pthread_lock_test(void); int pthread_cond_lock_test(void); void sharea_mem_test(void); void ns_test(void); +void malloc_test(void);