--- /dev/null
+---
+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
+...
+
--- /dev/null
+# LunaixOS 源代码
+
+我知道这个目录结构看起来相当的劝退。特别是并没有像初代Linux那种一个文件夹里就只是一堆文件的简单朴素。但至少,就我而言,把结构细分一点儿总是好的。
+
+## 目录结构
+
++ `arch` 平台相关代码,LunaixOS的内核引导就在这里。
++ `hal` 硬件抽象层,存放主板相关的代码,提供了一些访问主板功能(比如CPU,计时器)的抽象
++ `includes` 所有头文件
++ `kernel` 这里就是内核了
+ + `asm` 共内核使用的,且平台相关的代码。
+ + `ds` 提供一些基本的数据结构支持。
+ + `mm` 各类内存管理器。
+ + `peripheral` 外部设备驱动(如键盘)。
+ + `time` 为内核提供基本的时间,计时服务。
+ + `tty` 提供基本的显存操作服务。
++ `lib` 一些内核使用的运行时库,主要提供是内核模式下的一些C标准库里的实现。
++ `link` 链接器脚本
\ No newline at end of file
__LXSYSCALL1(int, sbrk, void*, addr)
-__LXSYSCALL1(void*, brk, size_t, size)
+__LXSYSCALL1(void*, brk, unsigned long, size)
__LXSYSCALL(pid_t, getpid)
#include <arch/x86/vectors.h>
-#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)))
#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 */
#include <arch/x86/interrupts.h>
-#include <lunaix/mm/pmm.h>
+#include <lunaix/common.h>
#include <lunaix/mm/mm.h>
+#include <lunaix/mm/pmm.h>
#include <lunaix/mm/region.h>
#include <lunaix/mm/vmm.h>
-#include <lunaix/common.h>
-#include <lunaix/syslog.h>
-#include <lunaix/status.h>
#include <lunaix/sched.h>
+#include <lunaix/status.h>
+#include <lunaix/syslog.h>
-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) {
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;
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
call _kernel_init
- movl $KSTACK_TOP, %esp
-
- call _kernel_post_init
-
1:
hlt
jmp 1b
\ No newline at end of file
#include <lunaix/common.h>
#include <lunaix/tty/tty.h>
+#include <lunaix/clock.h>
+#include <lunaix/mm/kalloc.h>
#include <lunaix/mm/page.h>
#include <lunaix/mm/pmm.h>
#include <lunaix/mm/vmm.h>
-#include <lunaix/mm/kalloc.h>
+#include <lunaix/process.h>
+#include <lunaix/sched.h>
#include <lunaix/spike.h>
#include <lunaix/syslog.h>
#include <lunaix/timer.h>
-#include <lunaix/clock.h>
-#include <lunaix/peripheral/ps2kbd.h>
-#include <lunaix/process.h>
-#include <lunaix/sched.h>
-#include <lunaix/syscall.h>
#include <hal/rtc.h>
-#include <hal/apic.h>
-#include <hal/ioapic.h>
-#include <hal/acpi/acpi.h>
#include <arch/x86/boot/multiboot.h>
#include <arch/x86/idt.h>
#include <klibc/stdio.h>
#include <klibc/string.h>
-#include <stdint.h>
#include <stddef.h>
-
+#include <stdint.h>
extern uint8_t __kernel_start;
extern uint8_t __kernel_end;
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();
__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);
}
}
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
+}
#include <hal/cpu.h>
-#include <lunaix/syslog.h>
+#include <lunaix/clock.h>
+#include <lunaix/keyboard.h>
+#include <lunaix/lunistd.h>
#include <lunaix/mm/kalloc.h>
#include <lunaix/mm/vmm.h>
+#include <lunaix/proc.h>
#include <lunaix/spike.h>
-#include <lunaix/clock.h>
+#include <lunaix/syslog.h>
#include <lunaix/timer.h>
-#include <lunaix/keyboard.h>
#include <lunaix/tty/tty.h>
-#include <lunaix/lunistd.h>
-#include <lunaix/proc.h>
extern uint8_t __kernel_start;
for (;;) {
pid_t p;
if ((p = fork())) {
- kprintf(KDEBUG "Forked %d\n", p);
+ kprintf(KDEBUG "Pinkie Pie #%d: FUN!\n", p);
}
}
#endif
}
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);
}
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
--- /dev/null
+#include <arch/x86/boot/multiboot.h>
+#include <lunaix/common.h>
+#include <lunaix/lunistd.h>
+#include <lunaix/mm/vmm.h>
+#include <lunaix/peripheral/ps2kbd.h>
+#include <lunaix/spike.h>
+#include <lunaix/syscall.h>
+#include <lunaix/syslog.h>
+#include <stddef.h>
+
+#include <hal/acpi/acpi.h>
+#include <hal/apic.h>
+#include <hal/ioapic.h>
+
+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
-#include <lunaix/process.h>
-#include <lunaix/mm/vmm.h>
-#include <lunaix/mm/region.h>
+#include <klibc/string.h>
#include <lunaix/clock.h>
-#include <lunaix/syslog.h>
#include <lunaix/common.h>
-#include <lunaix/syscall.h>
+#include <lunaix/mm/region.h>
+#include <lunaix/mm/vmm.h>
+#include <lunaix/process.h>
#include <lunaix/spike.h>
-#include <klibc/string.h>
+#include <lunaix/syscall.h>
+#include <lunaix/syslog.h>
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;
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
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();
pcb->state = PROC_CREATED;
}
-pid_t dup_proc() {
+pid_t
+dup_proc()
+{
struct proc_info pcb;
init_proc(&pcb);
pcb.mm = __current->mm;
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
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);
// 如果写共享,则不作处理。
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);
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);
// 我们不需要分配内核的区域,因为所有的内核代码和数据段只能通过系统调用来访问,任何非法的访问
// 都会导致eip落在区域外面,从而segmentation fault.
-
- // 定义用户栈区域,但是不分配实际的物理页。我们会在Page fault handler里面实现动态分配物理页的逻辑。(虚拟内存的好处!)
+
+ // 定义用户栈区域,但是不分配实际的物理页。我们会在Page fault
+ // handler里面实现动态分配物理页的逻辑。(虚拟内存的好处!)
// FIXME: 这里应该放到spawn_proc里面。
// region_add(proc, USTACK_END, USTACK_SIZE, REGION_PRIVATE | REGION_RW);
-#include <lunaix/process.h>
-#include <lunaix/sched.h>
-#include <lunaix/mm/vmm.h>
-#include <lunaix/mm/kalloc.h>
-#include <hal/cpu.h>
#include <arch/x86/interrupts.h>
#include <arch/x86/tss.h>
#include <hal/apic.h>
+#include <hal/cpu.h>
+#include <lunaix/mm/kalloc.h>
+#include <lunaix/mm/vmm.h>
+#include <lunaix/process.h>
+#include <lunaix/sched.h>
#include <lunaix/spike.h>
#include <lunaix/status.h>
-#include <lunaix/syslog.h>
#include <lunaix/syscall.h>
+#include <lunaix/syslog.h>
#define MAX_PROCESS 512
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);
__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;
}
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;
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:
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];
// 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 <kernel/process.c>
-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);
}
}
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;
__kernel_end = ALIGN(4K);
__proc_table = ALIGN(4K);
- . += 128M;
+ . += 4M;
__kernel_heap_start = ALIGN(4K); /* 内核结束的地方即堆开始的地方 */
}
\ No newline at end of file