From 20097445f742afff2c263431efcb1c8b596076a8 Mon Sep 17 00:00:00 2001 From: Minep Date: Fri, 10 Jun 2022 22:37:05 +0100 Subject: [PATCH] refactor: Move the kernel post init stage into proc0 refactor: Add a linter config. Resolved #1 refactor: Formatted some source files. refactor: Shrink the process table size. --- lunaix-os/.clang-format | 137 +++++++++++++++ lunaix-os/README.md | 18 ++ lunaix-os/includes/lunaix/lunistd.h | 2 +- lunaix-os/includes/lunaix/syscall.h | 106 ++++++------ lunaix-os/kernel/asm/x86/pfault.c | 54 +++--- lunaix-os/kernel/asm/x86/prologue.S | 4 - lunaix-os/kernel/k_init.c | 250 ++++++++++++---------------- lunaix-os/kernel/lxinit.c | 38 +++-- lunaix-os/kernel/proc0.c | 109 ++++++++++++ lunaix-os/kernel/process.c | 116 +++++++------ lunaix-os/kernel/sched.c | 148 +++++++++------- lunaix-os/link/linker.ld | 2 +- 12 files changed, 632 insertions(+), 352 deletions(-) create mode 100644 lunaix-os/.clang-format create mode 100644 lunaix-os/README.md create mode 100644 lunaix-os/kernel/proc0.c diff --git a/lunaix-os/.clang-format b/lunaix-os/.clang-format new file mode 100644 index 0000000..a429ba1 --- /dev/null +++ b/lunaix-os/.clang-format @@ -0,0 +1,137 @@ +--- +Language: Cpp +# BasedOnStyle: Mozilla +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignConsecutiveMacros: false +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Right +AlignOperands: true +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Inline +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: TopLevel +AlwaysBreakAfterReturnType: TopLevel +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: false +BinPackParameters: false +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: false + AfterEnum: true + AfterFunction: true + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: false + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Mozilla +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeComma +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeComma +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 2 +ContinuationIndentWidth: 2 +Cpp11BracedListStyle: false +DeriveLineEnding: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: false +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + SortPriority: 0 + - Regex: '.*' + Priority: 1 + SortPriority: 0 +IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' +IndentCaseLabels: true +IndentGotoLabels: true +IndentPPDirectives: None +IndentWidth: 4 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: false +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerAlignment: Left +ReflowComments: true +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +Standard: Latest +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 8 +UseCRLF: false +UseTab: Never +... + diff --git a/lunaix-os/README.md b/lunaix-os/README.md new file mode 100644 index 0000000..234ea1b --- /dev/null +++ b/lunaix-os/README.md @@ -0,0 +1,18 @@ +# LunaixOS 源代码 + +我知道这个目录结构看起来相当的劝退。特别是并没有像初代Linux那种一个文件夹里就只是一堆文件的简单朴素。但至少,就我而言,把结构细分一点儿总是好的。 + +## 目录结构 + ++ `arch` 平台相关代码,LunaixOS的内核引导就在这里。 ++ `hal` 硬件抽象层,存放主板相关的代码,提供了一些访问主板功能(比如CPU,计时器)的抽象 ++ `includes` 所有头文件 ++ `kernel` 这里就是内核了 + + `asm` 共内核使用的,且平台相关的代码。 + + `ds` 提供一些基本的数据结构支持。 + + `mm` 各类内存管理器。 + + `peripheral` 外部设备驱动(如键盘)。 + + `time` 为内核提供基本的时间,计时服务。 + + `tty` 提供基本的显存操作服务。 ++ `lib` 一些内核使用的运行时库,主要提供是内核模式下的一些C标准库里的实现。 ++ `link` 链接器脚本 \ No newline at end of file diff --git a/lunaix-os/includes/lunaix/lunistd.h b/lunaix-os/includes/lunaix/lunistd.h index a7ac03b..fc1a535 100644 --- a/lunaix-os/includes/lunaix/lunistd.h +++ b/lunaix-os/includes/lunaix/lunistd.h @@ -8,7 +8,7 @@ __LXSYSCALL(pid_t, fork) __LXSYSCALL1(int, sbrk, void*, addr) -__LXSYSCALL1(void*, brk, size_t, size) +__LXSYSCALL1(void*, brk, unsigned long, size) __LXSYSCALL(pid_t, getpid) diff --git a/lunaix-os/includes/lunaix/syscall.h b/lunaix-os/includes/lunaix/syscall.h index 7faa7de..dc61f64 100644 --- a/lunaix-os/includes/lunaix/syscall.h +++ b/lunaix-os/includes/lunaix/syscall.h @@ -3,27 +3,26 @@ #include -#define __SYSCALL_fork 1 -#define __SYSCALL_yield 2 -#define __SYSCALL_sbrk 3 -#define __SYSCALL_brk 4 -#define __SYSCALL_getpid 5 -#define __SYSCALL_getppid 6 -#define __SYSCALL_sleep 7 -#define __SYSCALL__exit 8 -#define __SYSCALL_wait 9 - -#define __SYSCALL_MAX 0x100 +#define __SYSCALL_fork 1 +#define __SYSCALL_yield 2 +#define __SYSCALL_sbrk 3 +#define __SYSCALL_brk 4 +#define __SYSCALL_getpid 5 +#define __SYSCALL_getppid 6 +#define __SYSCALL_sleep 7 +#define __SYSCALL__exit 8 +#define __SYSCALL_wait 9 + +#define __SYSCALL_MAX 0x100 #ifndef __ASM__ -void syscall_install(); - -static void* syscall(unsigned int callcode) { - asm volatile( - "int %0" - ::"i"(LUNAIX_SYS_CALL), "D"(callcode) - :"eax" - ); +void +syscall_install(); + +static void* +syscall(unsigned int callcode) +{ + asm volatile("int %0" ::"i"(LUNAIX_SYS_CALL), "D"(callcode) : "eax"); } #define asmlinkage __attribute__((regparm(0))) @@ -35,57 +34,58 @@ static void* syscall(unsigned int callcode) { #define __PARAM_MAP5(t1, p1, ...) t1 p1, __PARAM_MAP4(__VA_ARGS__) #define __PARAM_MAP6(t1, p1, ...) t1 p1, __PARAM_MAP5(__VA_ARGS__) -#define ___DOINT33(callcode, rettype)\ - int v; \ - asm volatile ( \ - "int %1\n" \ - :"=a"(v) \ - :"i"(LUNAIX_SYS_CALL), "a"(callcode)); \ - return (rettype)v; \ +#define ___DOINT33(callcode, rettype) \ + int v; \ + asm volatile("int %1\n" : "=a"(v) : "i"(LUNAIX_SYS_CALL), "a"(callcode)); \ + return (rettype)v; -#define __DEFINE_LXSYSCALL(rettype, name) \ - asmlinkage rettype __lxsys_##name() +#define __DEFINE_LXSYSCALL(rettype, name) asmlinkage rettype __lxsys_##name() -#define __DEFINE_LXSYSCALL1(rettype, name, t1, p1) \ +#define __DEFINE_LXSYSCALL1(rettype, name, t1, p1) \ asmlinkage rettype __lxsys_##name(__PARAM_MAP1(t1, p1)) -#define __DEFINE_LXSYSCALL2(rettype, name, t1, p1, t2, p2) \ +#define __DEFINE_LXSYSCALL2(rettype, name, t1, p1, t2, p2) \ asmlinkage rettype __lxsys_##name(__PARAM_MAP2(t1, p1, t2, p2)) -#define __DEFINE_LXSYSCALL3(rettype, name, t1, p1, t2, p2, t3, p3) \ +#define __DEFINE_LXSYSCALL3(rettype, name, t1, p1, t2, p2, t3, p3) \ asmlinkage rettype __lxsys_##name(__PARAM_MAP3(t1, p1, t2, p2, t3, p3)); -#define __DEFINE_LXSYSCALL4(rettype, name, t1, p1, t2, p2, t3, p3, t4, p4) \ - asmlinkage rettype __lxsys_##nam (__PARAM_MAP4(t1, p1, t2, p2, t3, p3, t4, p4)) - +#define __DEFINE_LXSYSCALL4(rettype, name, t1, p1, t2, p2, t3, p3, t4, p4) \ + asmlinkage rettype __lxsys_##nam( \ + __PARAM_MAP4(t1, p1, t2, p2, t3, p3, t4, p4)) -#define __LXSYSCALL(rettype, name) \ - rettype name () { \ - ___DOINT33(__SYSCALL_##name, rettype) \ +#define __LXSYSCALL(rettype, name) \ + static rettype name() \ + { \ + ___DOINT33(__SYSCALL_##name, rettype) \ } -#define __LXSYSCALL1(rettype, name, t1, p1) \ - rettype name (__PARAM_MAP1(t1, p1)) { \ - asm (""::"b"(p1)); \ - ___DOINT33(__SYSCALL_##name, rettype) \ +#define __LXSYSCALL1(rettype, name, t1, p1) \ + static rettype name(__PARAM_MAP1(t1, p1)) \ + { \ + asm("" ::"b"(p1)); \ + ___DOINT33(__SYSCALL_##name, rettype) \ } -#define __LXSYSCALL2(rettype, name, t1, p1, t2, p2) \ - rettype name (__PARAM_MAP2(t1, p1, t2, p2)) { \ - asm ("\n"::"b"(p1), "c"(p2)); \ - ___DOINT33(__SYSCALL_##name, rettype) \ +#define __LXSYSCALL2(rettype, name, t1, p1, t2, p2) \ + static rettype name(__PARAM_MAP2(t1, p1, t2, p2)) \ + { \ + asm("\n" ::"b"(p1), "c"(p2)); \ + ___DOINT33(__SYSCALL_##name, rettype) \ } -#define __LXSYSCALL3(rettype, name, t1, p1, t2, p2, t3, p3) \ - rettype name (__PARAM_MAP3(t1, p1, t2, p2, t3, p3)) { \ - asm ("\n"::"b"(p1), "c"(p2), "d"(p3)); \ - ___DOINT33(__SYSCALL_##name, rettype) \ +#define __LXSYSCALL3(rettype, name, t1, p1, t2, p2, t3, p3) \ + static rettype name(__PARAM_MAP3(t1, p1, t2, p2, t3, p3)) \ + { \ + asm("\n" ::"b"(p1), "c"(p2), "d"(p3)); \ + ___DOINT33(__SYSCALL_##name, rettype) \ } -#define __LXSYSCALL4(rettype, name, t1, p1, t2, p2, t3, p3, t4, p4) \ - rettype name (__PARAM_MAP3(t1, p1, t2, p2, t3, p3, t4, p4)) { \ - asm ("\n"::"b"(p1), "c"(p2), "d"(p3), "D"(p4)); \ - ___DOINT33(__SYSCALL_##name, rettype) \ +#define __LXSYSCALL4(rettype, name, t1, p1, t2, p2, t3, p3, t4, p4) \ + static rettype name(__PARAM_MAP3(t1, p1, t2, p2, t3, p3, t4, p4)) \ + { \ + asm("\n" ::"b"(p1), "c"(p2), "d"(p3), "D"(p4)); \ + ___DOINT33(__SYSCALL_##name, rettype) \ } #endif #endif /* __LUNAIX_SYSCALL_H */ diff --git a/lunaix-os/kernel/asm/x86/pfault.c b/lunaix-os/kernel/asm/x86/pfault.c index c16385a..9d5e1d1 100644 --- a/lunaix-os/kernel/asm/x86/pfault.c +++ b/lunaix-os/kernel/asm/x86/pfault.c @@ -1,19 +1,27 @@ #include -#include +#include #include +#include #include #include -#include -#include -#include #include +#include +#include -static void kprintf(const char* fmt, ...) { va_list args; va_start(args, fmt); __kprintf("PFAULT", fmt, args); va_end(args); } +static void +kprintf(const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + __kprintf("PFAULT", fmt, args); + va_end(args); +} -extern void __print_panic_msg(const char* msg, const isr_param* param); +extern void +__print_panic_msg(const char* msg, const isr_param* param); void -intr_routine_page_fault (const isr_param* param) +intr_routine_page_fault(const isr_param* param) { uintptr_t ptr = cpu_rcr2(); if (!ptr) { @@ -27,18 +35,17 @@ intr_routine_page_fault (const isr_param* param) goto segv_term; } - // if (param->eip == ptr && !(hit_region->attr & REGION_EXEC)) { - // goto segv_term; - // } - - x86_pte_t* pte = CURPROC_PTE(ptr >> 12); + x86_pte_t* pte = PTE_MOUNTED(PD_REFERENCED, ptr >> 12); if (*pte & PG_PRESENT) { - if ((hit_region->attr & REGION_PERM_MASK) == (REGION_RSHARED | REGION_READ)) { + if ((hit_region->attr & REGION_PERM_MASK) == + (REGION_RSHARED | REGION_READ)) { // normal page fault, do COW - uintptr_t pa = (uintptr_t)vmm_dup_page(__current->pid, PG_ENTRY_ADDR(*pte)); - pmm_free_page(__current->pid, *pte & ~0xFFF); - *pte = (*pte & 0xFFF) | pa | PG_WRITE; - return; + cpu_invplg(pte); + uintptr_t pa = + (uintptr_t)vmm_dup_page(__current->pid, PG_ENTRY_ADDR(*pte)); + pmm_free_page(__current->pid, *pte & ~0xFFF); + *pte = (*pte & 0xFFF) | pa | PG_WRITE; + return; } // impossible cases or accessing privileged page goto segv_term; @@ -49,18 +56,25 @@ intr_routine_page_fault (const isr_param* param) goto segv_term; } uintptr_t loc = *pte & ~0xfff; - // a writable page, not present, pte attr is not null and no indication of cached page -> a new page need to be alloc + // a writable page, not present, pte attr is not null + // and no indication of cached page -> a new page need to be alloc if ((hit_region->attr & REGION_WRITE) && (*pte & 0xfff) && !loc) { + cpu_invplg(pte); uintptr_t pa = pmm_alloc_page(__current->pid, 0); *pte = *pte | pa | PG_PRESENT; return; } // page not present, bring it from disk or somewhere else __print_panic_msg("WIP page fault route", param); - while (1); + while (1) + ; segv_term: - kprintf(KERROR "(pid: %d) Segmentation fault on %p (%p:%p)\n", __current->pid, ptr, param->cs, param->eip); + kprintf(KERROR "(pid: %d) Segmentation fault on %p (%p:%p)\n", + __current->pid, + ptr, + param->cs, + param->eip); terminate_proc(LXSEGFAULT); // should not reach } \ No newline at end of file diff --git a/lunaix-os/kernel/asm/x86/prologue.S b/lunaix-os/kernel/asm/x86/prologue.S index ef559bb..6cdab40 100644 --- a/lunaix-os/kernel/asm/x86/prologue.S +++ b/lunaix-os/kernel/asm/x86/prologue.S @@ -61,10 +61,6 @@ call _kernel_init - movl $KSTACK_TOP, %esp - - call _kernel_post_init - 1: hlt jmp 1b \ No newline at end of file diff --git a/lunaix-os/kernel/k_init.c b/lunaix-os/kernel/k_init.c index 863f574..eee475f 100644 --- a/lunaix-os/kernel/k_init.c +++ b/lunaix-os/kernel/k_init.c @@ -1,23 +1,18 @@ #include #include +#include +#include #include #include #include -#include +#include +#include #include #include #include -#include -#include -#include -#include -#include #include -#include -#include -#include #include #include @@ -26,9 +21,8 @@ #include #include -#include #include - +#include extern uint8_t __kernel_start; extern uint8_t __kernel_end; @@ -45,18 +39,18 @@ struct proc_info tmp; LOG_MODULE("BOOT"); -extern void _lxinit_main(); -void spawn_lxinit(); -void _kernel_post_init(); +extern void +__proc0(); /* proc0.c */ void -setup_memory(multiboot_memory_map_t* map, size_t map_size); +spawn_proc0(); void -lock_reserved_memory(); +setup_memory(multiboot_memory_map_t* map, size_t map_size); void -_kernel_pre_init() { +_kernel_pre_init() +{ _init_idt(); intr_routine_init(); @@ -69,153 +63,126 @@ _kernel_pre_init() { __kernel_ptd = cpu_rcr3(); - tmp = (struct proc_info) { - .page_table = __kernel_ptd - }; + tmp = (struct proc_info){ .page_table = __kernel_ptd }; __current = &tmp; } void -_kernel_init() { +_kernel_init() +{ kprintf("[MM] Mem: %d KiB, Extended Mem: %d KiB\n", - _k_init_mb_info->mem_lower, - _k_init_mb_info->mem_upper); + _k_init_mb_info->mem_lower, + _k_init_mb_info->mem_upper); + + unsigned int map_size = + _k_init_mb_info->mmap_length / sizeof(multiboot_memory_map_t); - unsigned int map_size = _k_init_mb_info->mmap_length / sizeof(multiboot_memory_map_t); - setup_memory((multiboot_memory_map_t*)_k_init_mb_info->mmap_addr, map_size); // 为内核创建一个专属栈空间。 for (size_t i = 0; i < (KSTACK_SIZE >> PG_SIZE_BITS); i++) { - vmm_alloc_page(KERNEL_PID, (void*)(KSTACK_START + (i << PG_SIZE_BITS)), NULL, PG_PREM_RW, 0); + vmm_alloc_page(KERNEL_PID, + (void*)(KSTACK_START + (i << PG_SIZE_BITS)), + NULL, + PG_PREM_RW, + 0); } - kprintf(KINFO "[MM] Allocated %d pages for stack start at %p\n", KSTACK_SIZE>>PG_SIZE_BITS, KSTACK_START); + kprintf(KINFO "[MM] Allocated %d pages for stack start at %p\n", + KSTACK_SIZE >> PG_SIZE_BITS, + KSTACK_START); sched_init(); + + spawn_proc0(); } /** - * @brief 创建并运行init进程 - * + * @brief 创建并运行proc0进程 + * */ -void spawn_lxinit() { - struct proc_info kinit; - - init_proc(&kinit); - kinit.intr_ctx = (isr_param) { - .registers.esp = KSTACK_TOP - 20, - .cs = KCODE_SEG, - .eip = (void*)_lxinit_main, - .ss = KDATA_SEG, - .eflags = cpu_reflags() - }; - - setup_proc_mem(&kinit, PD_REFERENCED); - - // Ok... 准备fork进我们的init进程 +void +spawn_proc0() +{ + struct proc_info proc0; + + /** + * @brief + * 注意:这里和视频中说的不一样,属于我之后的一点微调。 + * 在视频中,spawn_proc0是在_kernel_post_init的末尾才调用的。并且是直接跳转到_proc0 + * + * 但是我后来发现,上述的方法会产生竞态条件。这是因为spawn_proc0被调用的时候,时钟中断已经开启, + * 而中断的产生会打乱栈的布局,从而使得下面的上下文设置代码产生未定义行为(Undefined + * Behaviour)。 为了保险起见,有两种办法: + * 1. 在创建proc0进程前关闭中断 + * 2. 将_kernel_post_init搬进proc0进程 + * (_kernel_post_init已经更名为init_platform) + * + * 目前的解决方案是两者都使用 + */ + + init_proc(&proc0); + proc0.intr_ctx = (isr_param){ .registers.esp = KSTACK_TOP - 20, + .cs = KCODE_SEG, + .eip = (void*)__proc0, + .ss = KDATA_SEG, + .eflags = cpu_reflags() }; + + // 必须在读取eflags之后禁用。否则当进程被调度时,中断依然是关闭的! + cpu_disable_interrupt(); + setup_proc_mem(&proc0, PD_REFERENCED); + + // Ok... 首先fork进我们的零号进程,而后由那里,我们fork进init进程。 /* 这里是一些栈的设置,因为我们将切换到一个新的地址空间里,并且使用一个全新的栈。 让iret满意! */ - asm volatile( - "movl %%cr3, %%eax\n" - "movl %%esp, %%ebx\n" - "movl %0, %%cr3\n" - "movl %1, %%esp\n" - "pushf\n" - "pushl %2\n" - "pushl %3\n" - "pushl $0\n" - "pushl $0\n" - "movl %%eax, %%cr3\n" - "movl %%ebx, %%esp\n" - ::"r"(kinit.page_table), "i"(KSTACK_TOP), "i"(KCODE_SEG), "r"(kinit.intr_ctx.eip) - :"%eax", "%ebx", "memory" - ); - - // 向调度器注册进程,然后这里阻塞等待调度器调度就好了。 - push_process(&kinit); - -} - -void -_kernel_post_init() { - assert_msg(kalloc_init(), "Fail to initialize heap"); - - size_t hhk_init_pg_count = ((uintptr_t)(&__init_hhk_end)) >> PG_SIZE_BITS; - kprintf(KINFO "[MM] Releaseing %d pages from 0x0.\n", hhk_init_pg_count); - - // Fuck it, I will no longer bother this little 1MiB - // I just release 4 pages for my APIC & IOAPIC remappings - for (size_t i = 0; i < 3; i++) { - vmm_unmap_page(KERNEL_PID, (void*)(i << PG_SIZE_BITS)); - } - - // 锁定所有系统预留页(内存映射IO,ACPI之类的),并且进行1:1映射 - lock_reserved_memory(); - - acpi_init(_k_init_mb_info); - uintptr_t ioapic_addr = acpi_get_context()->madt.ioapic->ioapic_addr; - pmm_mark_page_occupied(KERNEL_PID, FLOOR(__APIC_BASE_PADDR, PG_SIZE_BITS), 0); - pmm_mark_page_occupied(KERNEL_PID, FLOOR(ioapic_addr, PG_SIZE_BITS), 0); - - vmm_set_mapping(KERNEL_PID, APIC_BASE_VADDR, __APIC_BASE_PADDR, PG_PREM_RW); - vmm_set_mapping(KERNEL_PID, IOAPIC_BASE_VADDR, ioapic_addr, PG_PREM_RW); - - apic_init(); - ioapic_init(); - timer_init(SYS_TIMER_FREQUENCY_HZ); - clock_init(); - ps2_kbd_init(); - - syscall_install(); - - for (size_t i = 256; i < hhk_init_pg_count; i++) { - vmm_unmap_page(KERNEL_PID, (void*)(i << PG_SIZE_BITS)); - } - - spawn_lxinit(); - - spin(); -} - -void -lock_reserved_memory() { - multiboot_memory_map_t* mmaps = _k_init_mb_info->mmap_addr; - size_t map_size = _k_init_mb_info->mmap_length / sizeof(multiboot_memory_map_t); - for (unsigned int i = 0; i < map_size; i++) { - multiboot_memory_map_t mmap = mmaps[i]; - if (mmap.type == MULTIBOOT_MEMORY_AVAILABLE) { - continue; - } - uint8_t* pa = PG_ALIGN(mmap.addr_low); - size_t pg_num = CEIL(mmap.len_low, PG_SIZE_BITS); - for (size_t j = 0; j < pg_num; j++) - { - vmm_set_mapping(KERNEL_PID, (pa + (j << PG_SIZE_BITS)), (pa + (j << PG_SIZE_BITS)), PG_PREM_R); - } - } + asm volatile("movl %%cr3, %%eax\n" + "movl %%esp, %%ebx\n" + "movl %0, %%cr3\n" + "movl %1, %%esp\n" + "pushf\n" + "pushl %2\n" + "pushl %3\n" + "pushl $0\n" + "pushl $0\n" + "movl %%eax, %%cr3\n" + "movl %%ebx, %%esp\n" ::"r"(proc0.page_table), + "i"(KSTACK_TOP), + "i"(KCODE_SEG), + "r"(proc0.intr_ctx.eip) + : "%eax", "%ebx", "memory"); + + // 向调度器注册进程。 + push_process(&proc0); + + // 由于时钟中断未就绪,我们需要手动通知调度器进行第一次调度。这里也会同时隐式地恢复我们的eflags.IF位 + schedule(); + + /* Should not return */ + assert_msg(0, "Unexpected Return"); } // 按照 Memory map 标识可用的物理页 void -setup_memory(multiboot_memory_map_t* map, size_t map_size) { +setup_memory(multiboot_memory_map_t* map, size_t map_size) +{ // First pass, to mark the physical pages for (unsigned int i = 0; i < map_size; i++) { multiboot_memory_map_t mmap = map[i]; kprintf("[MM] Base: 0x%x, len: %u KiB, type: %u\n", - map[i].addr_low, - map[i].len_low >> 10, - map[i].type); + map[i].addr_low, + map[i].len_low >> 10, + map[i].type); if (mmap.type == MULTIBOOT_MEMORY_AVAILABLE) { // 整数向上取整除法 uintptr_t pg = map[i].addr_low + 0x0fffU; - pmm_mark_chunk_free(pg >> PG_SIZE_BITS, map[i].len_low >> PG_SIZE_BITS); + pmm_mark_chunk_free(pg >> PG_SIZE_BITS, + map[i].len_low >> PG_SIZE_BITS); kprintf(KINFO "[MM] Freed %u pages start from 0x%x\n", - map[i].len_low >> PG_SIZE_BITS, - pg & ~0x0fffU); + map[i].len_low >> PG_SIZE_BITS, + pg & ~0x0fffU); } } @@ -224,25 +191,22 @@ setup_memory(multiboot_memory_map_t* map, size_t map_size) { pmm_mark_chunk_occupied(KERNEL_PID, 0, pg_count, 0); kprintf(KINFO "[MM] Allocated %d pages for kernel.\n", pg_count); - size_t vga_buf_pgs = VGA_BUFFER_SIZE >> PG_SIZE_BITS; - + // 首先,标记VGA部分为已占用 - pmm_mark_chunk_occupied(KERNEL_PID, VGA_BUFFER_PADDR >> PG_SIZE_BITS, vga_buf_pgs, 0); - + pmm_mark_chunk_occupied( + KERNEL_PID, VGA_BUFFER_PADDR >> PG_SIZE_BITS, vga_buf_pgs, 0); + // 重映射VGA文本缓冲区(以后会变成显存,i.e., framebuffer) - for (size_t i = 0; i < vga_buf_pgs; i++) - { - vmm_map_page( - KERNEL_PID, - (void*)(VGA_BUFFER_VADDR + (i << PG_SIZE_BITS)), - (void*)(VGA_BUFFER_PADDR + (i << PG_SIZE_BITS)), - PG_PREM_URW - ); + for (size_t i = 0; i < vga_buf_pgs; i++) { + vmm_map_page(KERNEL_PID, + (void*)(VGA_BUFFER_VADDR + (i << PG_SIZE_BITS)), + (void*)(VGA_BUFFER_PADDR + (i << PG_SIZE_BITS)), + PG_PREM_URW); } - + // 更新VGA缓冲区位置至虚拟地址 tty_set_buffer((void*)VGA_BUFFER_VADDR); kprintf(KINFO "[MM] Mapped VGA to %p.\n", VGA_BUFFER_VADDR); -} \ No newline at end of file +} diff --git a/lunaix-os/kernel/lxinit.c b/lunaix-os/kernel/lxinit.c index e6ca67b..d951a9f 100644 --- a/lunaix-os/kernel/lxinit.c +++ b/lunaix-os/kernel/lxinit.c @@ -1,14 +1,14 @@ #include -#include +#include +#include +#include #include #include +#include #include -#include +#include #include -#include #include -#include -#include extern uint8_t __kernel_start; @@ -25,7 +25,7 @@ _lxinit_main() for (;;) { pid_t p; if ((p = fork())) { - kprintf(KDEBUG "Forked %d\n", p); + kprintf(KDEBUG "Pinkie Pie #%d: FUN!\n", p); } } #endif @@ -41,19 +41,21 @@ _lxinit_main() } int status; pid_t child = wait(&status); - kprintf("I am parent, my child (%d) terminated with code: %d.\n", child, status); + kprintf( + "I am parent, my child (%d) terminated with code: %d.\n", child, status); #endif - + + sleep(5); + // 这里是就是LunaixOS的第一个进程了! - for (size_t i = 0; i < 10; i++) - { + for (size_t i = 0; i < 10; i++) { pid_t pid = 0; if (!(pid = fork())) { sleep(i); if (i == 3) { - i = *(int*)0xdeadc0de; // seg fault! + i = *(int*)0xdeadc0de; // seg fault! } - tty_put_char('0'+i); + tty_put_char('0' + i); tty_put_char('\n'); _exit(0); } @@ -67,22 +69,22 @@ _lxinit_main() cpu_get_brand(buf); kprintf("CPU: %s\n\n", buf); - // no lxmalloc here! This can only be used within kernel, but here, we are in a dedicated process! - // any access to kernel method must be done via syscall + // no lxmalloc here! This can only be used within kernel, but here, we are + // in a dedicated process! any access to kernel method must be done via + // syscall struct kdb_keyinfo_pkt keyevent; - while (1) - { + while (1) { if (!kbd_recv_key(&keyevent)) { // yield(); continue; } - if ((keyevent.state & KBD_KEY_FPRESSED) && (keyevent.keycode & 0xff00) <= KEYPAD) { + if ((keyevent.state & KBD_KEY_FPRESSED) && + (keyevent.keycode & 0xff00) <= KEYPAD) { tty_put_char((char)(keyevent.keycode & 0x00ff)); tty_sync_cursor(); } } - spin(); } \ No newline at end of file diff --git a/lunaix-os/kernel/proc0.c b/lunaix-os/kernel/proc0.c new file mode 100644 index 0000000..a2102ae --- /dev/null +++ b/lunaix-os/kernel/proc0.c @@ -0,0 +1,109 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +LOG_MODULE("PROC0") + +extern void +_lxinit_main(); /* lxinit.c */ + +void +init_platform(); + +void +lock_reserved_memory(); + +/** + * @brief LunaixOS的零号进程,该进程永远为可执行。 + * + * 这主要是为了保证调度器在没有进程可调度时依然有事可做。 + * + * 同时,该进程也负责fork出我们的init进程。 + * + */ +void +__proc0() +{ + init_platform(); + if (!fork()) { + asm("jmp _lxinit_main"); + } + + asm("1: jmp 1b"); +} + +extern uint8_t __kernel_start; /* link/linker.ld */ +extern uint8_t __kernel_end; /* link/linker.ld */ +extern uint8_t __init_hhk_end; /* link/linker.ld */ +extern multiboot_info_t* _k_init_mb_info; /* k_init.c */ + +void +init_platform() +{ + assert_msg(kalloc_init(), "Fail to initialize heap"); + + size_t hhk_init_pg_count = ((uintptr_t)(&__init_hhk_end)) >> PG_SIZE_BITS; + kprintf(KINFO "[MM] Releaseing %d pages from 0x0.\n", hhk_init_pg_count); + + // Fuck it, I will no longer bother this little 1MiB + // I just release 4 pages for my APIC & IOAPIC remappings + for (size_t i = 0; i < 3; i++) { + vmm_unmap_page(KERNEL_PID, (void*)(i << PG_SIZE_BITS)); + } + + // 锁定所有系统预留页(内存映射IO,ACPI之类的),并且进行1:1映射 + lock_reserved_memory(); + + acpi_init(_k_init_mb_info); + uintptr_t ioapic_addr = acpi_get_context()->madt.ioapic->ioapic_addr; + pmm_mark_page_occupied( + KERNEL_PID, FLOOR(__APIC_BASE_PADDR, PG_SIZE_BITS), 0); + pmm_mark_page_occupied(KERNEL_PID, FLOOR(ioapic_addr, PG_SIZE_BITS), 0); + + vmm_set_mapping(KERNEL_PID, APIC_BASE_VADDR, __APIC_BASE_PADDR, PG_PREM_RW); + vmm_set_mapping(KERNEL_PID, IOAPIC_BASE_VADDR, ioapic_addr, PG_PREM_RW); + + apic_init(); + ioapic_init(); + timer_init(SYS_TIMER_FREQUENCY_HZ); + clock_init(); + ps2_kbd_init(); + + syscall_install(); + + for (size_t i = 256; i < hhk_init_pg_count; i++) { + vmm_unmap_page(KERNEL_PID, (void*)(i << PG_SIZE_BITS)); + } +} + +void +lock_reserved_memory() +{ + multiboot_memory_map_t* mmaps = _k_init_mb_info->mmap_addr; + size_t map_size = + _k_init_mb_info->mmap_length / sizeof(multiboot_memory_map_t); + for (unsigned int i = 0; i < map_size; i++) { + multiboot_memory_map_t mmap = mmaps[i]; + if (mmap.type == MULTIBOOT_MEMORY_AVAILABLE) { + continue; + } + uint8_t* pa = PG_ALIGN(mmap.addr_low); + size_t pg_num = CEIL(mmap.len_low, PG_SIZE_BITS); + for (size_t j = 0; j < pg_num; j++) { + vmm_set_mapping(KERNEL_PID, + (pa + (j << PG_SIZE_BITS)), + (pa + (j << PG_SIZE_BITS)), + PG_PREM_R); + } + } +} \ No newline at end of file diff --git a/lunaix-os/kernel/process.c b/lunaix-os/kernel/process.c index 5112ae1..87a7413 100644 --- a/lunaix-os/kernel/process.c +++ b/lunaix-os/kernel/process.c @@ -1,34 +1,34 @@ -#include -#include -#include +#include #include -#include #include -#include +#include +#include +#include #include -#include +#include +#include LOG_MODULE("PROC") -void* __dup_pagetable(pid_t pid, uintptr_t mount_point) { +void* +__dup_pagetable(pid_t pid, uintptr_t mount_point) +{ void* ptd_pp = pmm_alloc_page(pid, PP_FGPERSIST); x86_page_table* ptd = vmm_fmap_page(pid, PG_MOUNT_1, ptd_pp, PG_PREM_RW); - x86_page_table* pptd = (x86_page_table*) (mount_point | (0x3FF << 12)); + x86_page_table* pptd = (x86_page_table*)(mount_point | (0x3FF << 12)); - for (size_t i = 0; i < PG_MAX_ENTRIES - 1; i++) - { + for (size_t i = 0; i < PG_MAX_ENTRIES - 1; i++) { x86_pte_t ptde = pptd->entry[i]; if (!ptde || !(ptde & PG_PRESENT)) { ptd->entry[i] = ptde; continue; } - - x86_page_table* ppt = (x86_page_table*) (mount_point | (i << 12)); + + x86_page_table* ppt = (x86_page_table*)(mount_point | (i << 12)); void* pt_pp = pmm_alloc_page(pid, PP_FGPERSIST); x86_page_table* pt = vmm_fmap_page(pid, PG_MOUNT_2, pt_pp, PG_PREM_RW); - for (size_t j = 0; j < PG_MAX_ENTRIES; j++) - { + for (size_t j = 0; j < PG_MAX_ENTRIES; j++) { x86_pte_t pte = ppt->entry[j]; pmm_ref_page(pid, PG_ENTRY_ADDR(pte)); pt->entry[j] = pte; @@ -36,30 +36,30 @@ void* __dup_pagetable(pid_t pid, uintptr_t mount_point) { ptd->entry[i] = (uintptr_t)pt_pp | PG_PREM_RW; } - + ptd->entry[PG_MAX_ENTRIES - 1] = NEW_L1_ENTRY(T_SELF_REF_PERM, ptd_pp); return ptd_pp; } -void __del_pagetable(pid_t pid, uintptr_t mount_point) { - x86_page_table* pptd = (x86_page_table*) (mount_point | (0x3FF << 12)); +void +__del_pagetable(pid_t pid, uintptr_t mount_point) +{ + x86_page_table* pptd = (x86_page_table*)(mount_point | (0x3FF << 12)); - for (size_t i = 0; i < PG_MAX_ENTRIES - 1; i++) - { + for (size_t i = 0; i < PG_MAX_ENTRIES - 1; i++) { x86_pte_t ptde = pptd->entry[i]; if (!ptde || !(ptde & PG_PRESENT)) { continue; } - - x86_page_table* ppt = (x86_page_table*) (mount_point | (i << 12)); - for (size_t j = 0; j < PG_MAX_ENTRIES; j++) - { + x86_page_table* ppt = (x86_page_table*)(mount_point | (i << 12)); + + for (size_t j = 0; j < PG_MAX_ENTRIES; j++) { x86_pte_t pte = ppt->entry[j]; // free the 4KB data page if ((pte & PG_PRESENT)) { - pmm_free_page(pid,PG_ENTRY_ADDR(pte)); + pmm_free_page(pid, PG_ENTRY_ADDR(pte)); } } // free the L2 page table @@ -69,23 +69,30 @@ void __del_pagetable(pid_t pid, uintptr_t mount_point) { pmm_free_page(pid, PG_ENTRY_ADDR(pptd->entry[PG_MAX_ENTRIES - 1])); } -void* dup_pagetable(pid_t pid) { +void* +dup_pagetable(pid_t pid) +{ return __dup_pagetable(pid, PD_REFERENCED); } -__DEFINE_LXSYSCALL(pid_t, fork) { +__DEFINE_LXSYSCALL(pid_t, fork) +{ return dup_proc(); } -__DEFINE_LXSYSCALL(pid_t, getpid) { +__DEFINE_LXSYSCALL(pid_t, getpid) +{ return __current->pid; } -__DEFINE_LXSYSCALL(pid_t, getppid) { +__DEFINE_LXSYSCALL(pid_t, getppid) +{ return __current->parent->pid; } -void init_proc(struct proc_info *pcb) { +void +init_proc(struct proc_info* pcb) +{ memset(pcb, 0, sizeof(*pcb)); pcb->pid = alloc_pid(); @@ -93,7 +100,9 @@ void init_proc(struct proc_info *pcb) { pcb->state = PROC_CREATED; } -pid_t dup_proc() { +pid_t +dup_proc() +{ struct proc_info pcb; init_proc(&pcb); pcb.mm = __current->mm; @@ -101,7 +110,7 @@ pid_t dup_proc() { pcb.parent = __current; #ifdef USE_KERNEL_PG - setup_proc_mem(&pcb, PD_MOUNT_1); //挂载点#1是当前进程的页表 + setup_proc_mem(&pcb, PD_MOUNT_1); //挂载点#1是当前进程的页表 #else setup_proc_mem(&pcb, PD_REFERENCED); #endif @@ -110,9 +119,11 @@ pid_t dup_proc() { if (!__current->mm.regions) { goto not_copy; } - + + llist_init_head(&pcb.mm.regions); struct mm_region *pos, *n; - llist_for_each(pos, n, &__current->mm.regions->head, head) { + llist_for_each(pos, n, &__current->mm.regions->head, head) + { region_add(&pcb, pos->start, pos->end, pos->attr); // 如果写共享,则不作处理。 @@ -122,25 +133,23 @@ pid_t dup_proc() { uintptr_t start_vpn = PG_ALIGN(pos->start) >> 12; uintptr_t end_vpn = PG_ALIGN(pos->end) >> 12; - for (size_t i = start_vpn; i < end_vpn; i++) - { - x86_pte_t *curproc = &PTE_MOUNTED(PD_MOUNT_1, i); - x86_pte_t *newproc = &PTE_MOUNTED(PD_MOUNT_2, i); - cpu_invplg(curproc); + for (size_t i = start_vpn; i < end_vpn; i++) { + x86_pte_t* curproc = &PTE_MOUNTED(PD_MOUNT_1, i); + x86_pte_t* newproc = &PTE_MOUNTED(PD_MOUNT_2, i); cpu_invplg(newproc); if (pos->attr == REGION_RSHARED) { // 如果读共享,则将两者的都标注为只读,那么任何写入都将会应用COW策略。 + cpu_invplg(curproc); *curproc = *curproc & ~PG_WRITE; *newproc = *newproc & ~PG_WRITE; - } - else { + } else { // 如果是私有页,则将该页从新进程中移除。 *newproc = 0; } } } - + not_copy: vmm_unmount_pd(PD_MOUNT_2); @@ -154,24 +163,26 @@ not_copy: extern void __kernel_end; -void setup_proc_mem(struct proc_info* proc, uintptr_t usedMnt) { +void +setup_proc_mem(struct proc_info* proc, uintptr_t usedMnt) +{ // copy the entire kernel page table pid_t pid = proc->pid; void* pt_copy = __dup_pagetable(pid, usedMnt); - vmm_mount_pd(PD_MOUNT_2, pt_copy); // 将新进程的页表挂载到挂载点#2 + vmm_mount_pd(PD_MOUNT_2, pt_copy); // 将新进程的页表挂载到挂载点#2 // copy the kernel stack - for (size_t i = KSTACK_START >> 12; i <= KSTACK_TOP >> 12; i++) - { - volatile x86_pte_t *ppte = &PTE_MOUNTED(PD_MOUNT_2, i); + for (size_t i = KSTACK_START >> 12; i <= KSTACK_TOP >> 12; i++) { + volatile x86_pte_t* ppte = &PTE_MOUNTED(PD_MOUNT_2, i); /* - This is a fucking nightmare, the TLB caching keep the rewrite to PTE from updating. - Even the Nightmare Moon the Evil is far less nasty than this. - It took me hours of debugging to figure this out. + This is a fucking nightmare, the TLB caching keep the rewrite to PTE + from updating. Even the Nightmare Moon the Evil is far less nasty + than this. It took me hours of debugging to figure this out. - In the name of Celestia our glorious goddess, I will fucking HATE the TLB for the rest of my LIFE! + In the name of Celestia our glorious goddess, I will fucking HATE + the TLB for the rest of my LIFE! */ cpu_invplg(ppte); @@ -182,8 +193,9 @@ void setup_proc_mem(struct proc_info* proc, uintptr_t usedMnt) { // 我们不需要分配内核的区域,因为所有的内核代码和数据段只能通过系统调用来访问,任何非法的访问 // 都会导致eip落在区域外面,从而segmentation fault. - - // 定义用户栈区域,但是不分配实际的物理页。我们会在Page fault handler里面实现动态分配物理页的逻辑。(虚拟内存的好处!) + + // 定义用户栈区域,但是不分配实际的物理页。我们会在Page fault + // handler里面实现动态分配物理页的逻辑。(虚拟内存的好处!) // FIXME: 这里应该放到spawn_proc里面。 // region_add(proc, USTACK_END, USTACK_SIZE, REGION_PRIVATE | REGION_RW); diff --git a/lunaix-os/kernel/sched.c b/lunaix-os/kernel/sched.c index 758b157..8f65087 100644 --- a/lunaix-os/kernel/sched.c +++ b/lunaix-os/kernel/sched.c @@ -1,16 +1,16 @@ -#include -#include -#include -#include -#include #include #include #include +#include +#include +#include +#include +#include #include #include -#include #include +#include #define MAX_PROCESS 512 @@ -24,26 +24,27 @@ struct scheduler sched_ctx; LOG_MODULE("SCHED") -void sched_init() { +void +sched_init() +{ size_t pg_size = ROUNDUP(sizeof(struct proc_info) * MAX_PROCESS, 0x1000); - assert_msg( - vmm_alloc_pages(KERNEL_PID, &__proc_table, pg_size, PG_PREM_RW, PP_FGPERSIST), - "Fail to allocate proc table" - ); - - sched_ctx = (struct scheduler) { - ._procs = (struct proc_info*) &__proc_table, - .ptable_len = 0, - .procs_index = 0 - }; + assert_msg(vmm_alloc_pages( + KERNEL_PID, &__proc_table, pg_size, PG_PREM_RW, PP_FGPERSIST), + "Fail to allocate proc table"); + + sched_ctx = (struct scheduler){ ._procs = (struct proc_info*)&__proc_table, + .ptable_len = 0, + .procs_index = 0 }; } -void run(struct proc_info* proc) { +void +run(struct proc_info* proc) +{ if (!(__current->state & ~PROC_RUNNING)) { __current->state = PROC_STOPPED; } proc->state = PROC_RUNNING; - + // FIXME: 这里还是得再考虑一下。 // tss_update_esp(__current->intr_ctx.esp); @@ -51,19 +52,20 @@ void run(struct proc_info* proc) { __current = proc; cpu_lcr3(__current->page_table); // from now on, the we are in the kstack of another process - } - else { + } else { __current = proc; } apic_done_servicing(); - asm volatile ( - "pushl %0\n" - "jmp soft_iret\n"::"r"(&__current->intr_ctx): "memory"); + asm volatile("pushl %0\n" + "jmp soft_iret\n" ::"r"(&__current->intr_ctx) + : "memory"); } -void schedule() { +void +schedule() +{ if (!sched_ctx.ptable_len) { return; } @@ -75,20 +77,22 @@ void schedule() { do { ptr = (ptr + 1) % sched_ctx.ptable_len; next = &sched_ctx._procs[ptr]; - } while(next->state != PROC_STOPPED && ptr != prev_ptr); - - sched_ctx.procs_index = ptr; + } while (next->state != PROC_STOPPED && ptr != prev_ptr); + sched_ctx.procs_index = ptr; run(next); } -static void proc_timer_callback(struct proc_info* proc) { +static void +proc_timer_callback(struct proc_info* proc) +{ proc->timer = NULL; proc->state = PROC_STOPPED; } -__DEFINE_LXSYSCALL1(unsigned int, sleep, unsigned int, seconds) { +__DEFINE_LXSYSCALL1(unsigned int, sleep, unsigned int, seconds) +{ // FIXME: sleep的实现或许需要改一下。专门绑一个计时器好像没有必要…… if (!seconds) { return 0; @@ -97,34 +101,40 @@ __DEFINE_LXSYSCALL1(unsigned int, sleep, unsigned int, seconds) { return __current->timer->counter / timer_context()->running_frequency; } - struct lx_timer* timer = timer_run_second(seconds, proc_timer_callback, __current, 0); + struct lx_timer* timer = + timer_run_second(seconds, proc_timer_callback, __current, 0); __current->timer = timer; __current->intr_ctx.registers.eax = seconds; __current->state = PROC_BLOCKED; schedule(); } -__DEFINE_LXSYSCALL1(void, exit, int, status) { +__DEFINE_LXSYSCALL1(void, exit, int, status) +{ terminate_proc(status); } -__DEFINE_LXSYSCALL(void, yield) { +__DEFINE_LXSYSCALL(void, yield) +{ schedule(); } -__DEFINE_LXSYSCALL1(pid_t, wait, int*, status) { +__DEFINE_LXSYSCALL1(pid_t, wait, int*, status) +{ pid_t cur = __current->pid; struct proc_info *proc, *n; if (llist_empty(&__current->children)) { return -1; } repeat: - llist_for_each(proc, n, &__current->children, siblings) { + llist_for_each(proc, n, &__current->children, siblings) + { if (proc->state == PROC_TERMNAT) { goto done; } } - // FIXME: 除了循环,也许有更高效的办法…… (在这里进行schedule,需要重写context switch!) + // FIXME: 除了循环,也许有更高效的办法…… + // (在这里进行schedule,需要重写context switch!) goto repeat; done: @@ -132,27 +142,34 @@ done: return destroy_process(proc->pid); } -pid_t alloc_pid() { +pid_t +alloc_pid() +{ pid_t i = 0; - for (; i < sched_ctx.ptable_len && sched_ctx._procs[i].state != PROC_DESTROY; i++); + for (; + i < sched_ctx.ptable_len && sched_ctx._procs[i].state != PROC_DESTROY; + i++) + ; if (i == MAX_PROCESS) { - panick("Process table is full"); + panick("Panic in Ponyville shimmer!"); } - return i + 1; + return i; } -void push_process(struct proc_info* process) { - int index = process->pid - 1; +void +push_process(struct proc_info* process) +{ + int index = process->pid; if (index < 0 || index > sched_ctx.ptable_len) { __current->k_status = LXINVLDPID; return; } - + if (index == sched_ctx.ptable_len) { sched_ctx.ptable_len++; } - + sched_ctx._procs[index] = *process; process = &sched_ctx._procs[index]; @@ -162,30 +179,33 @@ void push_process(struct proc_info* process) { // every process is the child of first process (pid=1) if (process->parent) { llist_append(&process->parent->children, &process->siblings); - } - else { + } else { process->parent = &sched_ctx._procs[0]; } - process->state = PROC_STOPPED; + process->state = PROC_STOPPED; } // from -extern void __del_pagetable(pid_t pid, uintptr_t mount_point); +extern void +__del_pagetable(pid_t pid, uintptr_t mount_point); -pid_t destroy_process(pid_t pid) { - int index = pid - 1; +pid_t +destroy_process(pid_t pid) +{ + int index = pid; if (index <= 0 || index > sched_ctx.ptable_len) { __current->k_status = LXINVLDPID; return; } - struct proc_info *proc = &sched_ctx._procs[index]; + struct proc_info* proc = &sched_ctx._procs[index]; proc->state = PROC_DESTROY; llist_delete(&proc->siblings); if (proc->mm.regions) { struct mm_region *pos, *n; - llist_for_each(pos, n, &proc->mm.regions->head, head) { + llist_for_each(pos, n, &proc->mm.regions->head, head) + { lxfree(pos); } } @@ -199,27 +219,35 @@ pid_t destroy_process(pid_t pid) { return pid; } -void terminate_proc(int exit_code) { +void +terminate_proc(int exit_code) +{ __current->state = PROC_TERMNAT; __current->exit_code = exit_code; schedule(); } -struct proc_info* get_process(pid_t pid) { - int index = pid - 1; +struct proc_info* +get_process(pid_t pid) +{ + int index = pid; if (index < 0 || index > sched_ctx.ptable_len) { return NULL; } return &sched_ctx._procs[index]; } -int orphaned_proc(pid_t pid) { - if(!pid) return 0; - if(pid >= sched_ctx.ptable_len) return 0; - struct proc_info* proc = &sched_ctx._procs[pid-1]; +int +orphaned_proc(pid_t pid) +{ + if (!pid) + return 0; + if (pid >= sched_ctx.ptable_len) + return 0; + struct proc_info* proc = &sched_ctx._procs[pid]; struct proc_info* parent = proc->parent; - + // 如果其父进程的状态是terminated 或 destroy中的一种 // 或者其父进程是在该进程之后创建的,那么该进程为孤儿进程 return (parent->state & PROC_TERMMASK) || parent->created > proc->created; diff --git a/lunaix-os/link/linker.ld b/lunaix-os/link/linker.ld index f61e368..958082a 100644 --- a/lunaix-os/link/linker.ld +++ b/lunaix-os/link/linker.ld @@ -62,6 +62,6 @@ SECTIONS { __kernel_end = ALIGN(4K); __proc_table = ALIGN(4K); - . += 128M; + . += 4M; __kernel_heap_start = ALIGN(4K); /* 内核结束的地方即堆开始的地方 */ } \ No newline at end of file -- 2.27.0