📄 main.c
字号:
/* Copyright (C) 2004 The SOS Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* Include definitions of the multiboot standard */#include <bootstrap/multiboot.h>#include <hwcore/idt.h>#include <hwcore/gdt.h>#include <hwcore/irq.h>#include <hwcore/exception.h>#include <hwcore/i8254.h>#include <sos/list.h>#include <sos/physmem.h>#include <hwcore/paging.h>#include <hwcore/mm_context.h>#include <hwcore/swintr.h>#include <sos/kmem_vmm.h>#include <sos/kmalloc.h>#include <sos/time.h>#include <sos/thread.h>#include <sos/process.h>#include <sos/klibc.h>#include <sos/assert.h>#include <drivers/x86_videomem.h>#include <drivers/bochs.h>#include <sos/calcload.h>/* Helper function to display each bits of a 32bits integer on the screen as dark or light carrets */void display_bits(unsigned char row, unsigned char col, unsigned char attribute, sos_ui32_t integer){ int i; /* Scan each bit of the integer, MSb first */ for (i = 31 ; i >= 0 ; i--) { /* Test if bit i of 'integer' is set */ int bit_i = (integer & (1 << i)); /* Ascii 219 => dark carret, Ascii 177 => light carret */ unsigned char ascii_code = bit_i?219:177; sos_x86_videomem_putchar(row, col++, attribute, ascii_code); }}/* Clock IRQ handler */static void clk_it(int intid){ static sos_ui32_t clock_count = 0; display_bits(0, 48, SOS_X86_VIDEO_FG_LTGREEN | SOS_X86_VIDEO_BG_BLUE, clock_count); clock_count++; /* Execute the expired timeout actions (if any) */ sos_time_do_tick(); /* Update scheduler statistics and status */ sos_sched_do_timer_tick();}/* ====================================================================== * Page fault exception handling *//* Page fault exception handler with demand paging for the kernel */static void pgflt_ex(int intid, struct sos_cpu_state *ctxt){ static sos_ui32_t demand_paging_count = 0; sos_vaddr_t faulting_vaddr = sos_cpu_context_get_EX_faulting_vaddr(ctxt); sos_paddr_t ppage_paddr; if (sos_cpu_context_is_in_user_mode(ctxt)) { /* User-mode page faults are considered unresolved for the moment */ sos_bochs_printf("Unresolved USER page Fault at instruction 0x%x on access to address 0x%x (info=%x)!\n", sos_cpu_context_get_PC(ctxt), (unsigned)faulting_vaddr, (unsigned)sos_cpu_context_get_EX_info(ctxt)); sos_bochs_printf("Terminating User thread\n"); sos_thread_exit(); } /* Check if address is covered by any VMM range */ if (! sos_kmem_vmm_is_valid_vaddr(faulting_vaddr)) { /* No: The page fault is out of any kernel virtual region. For the moment, we don't handle this. */ sos_display_fatal_error("Unresolved page Fault at instruction 0x%x on access to address 0x%x (info=%x)!", sos_cpu_context_get_PC(ctxt), (unsigned)faulting_vaddr, (unsigned)sos_cpu_context_get_EX_info(ctxt)); SOS_ASSERT_FATAL(! "Got page fault (note: demand paging is disabled)"); } /* * Demand paging in kernel space */ /* Update the number of demand paging requests handled */ demand_paging_count ++; display_bits(0, 0, SOS_X86_VIDEO_FG_LTRED | SOS_X86_VIDEO_BG_BLUE, demand_paging_count); /* Allocate a new page for the virtual address */ ppage_paddr = sos_physmem_ref_physpage_new(FALSE); if (! ppage_paddr) SOS_ASSERT_FATAL(! "TODO: implement swap. (Out of mem in demand paging because no swap for kernel yet !)"); SOS_ASSERT_FATAL(SOS_OK == sos_paging_map(ppage_paddr, SOS_PAGE_ALIGN_INF(faulting_vaddr), FALSE, SOS_VM_MAP_PROT_READ | SOS_VM_MAP_PROT_WRITE | SOS_VM_MAP_ATOMIC)); sos_physmem_unref_physpage(ppage_paddr); /* Ok, we can now return to interrupted context */}/* ====================================================================== * Demonstrate the use of SOS kernel threads * - Kernel Threads are created with various priorities and their * state is printed on both the console and the bochs' 0xe9 port * - For tests regarding threads' synchronization, see mouse_sim.c */struct thr_arg{ char character; int color; int col; int row;};static void demo_thread(void *arg){ struct thr_arg *thr_arg = (struct thr_arg*)arg; int progress = 0; sos_bochs_printf("start %c", thr_arg->character); while (1) { progress ++; display_bits(thr_arg->row, thr_arg->col+1, thr_arg->color, progress); sos_bochs_putchar(thr_arg->character); /* Yield the CPU to another thread sometimes... */ if ((random() % 100) == 0) { sos_bochs_printf("[37myield(%c)[m\n", thr_arg->character); sos_x86_videomem_putchar(thr_arg->row, thr_arg->col, 0x1e, 'Y'); SOS_ASSERT_FATAL(SOS_OK == sos_thread_yield()); sos_x86_videomem_putchar(thr_arg->row, thr_arg->col, 0x1e, 'R'); } /* Go to sleep some other times... */ else if ((random() % 200) == 0) { struct sos_time t = (struct sos_time){ .sec=0, .nanosec=50000000 }; sos_bochs_printf("[37msleep1(%c)[m\n", thr_arg->character); sos_x86_videomem_putchar(thr_arg->row, thr_arg->col, 0x1e, 's'); SOS_ASSERT_FATAL(SOS_OK == sos_thread_sleep(& t)); SOS_ASSERT_FATAL(sos_time_is_zero(& t)); sos_x86_videomem_putchar(thr_arg->row, thr_arg->col, 0x1e, 'R'); } /* Go to sleep for a longer time some other times... */ else if ((random() % 300) == 0) { struct sos_time t = (struct sos_time){ .sec=0, .nanosec=300000000 }; sos_bochs_printf("[37msleep2(%c)[m\n", thr_arg->character); sos_x86_videomem_putchar(thr_arg->row, thr_arg->col, 0x1e, 'S'); SOS_ASSERT_FATAL(SOS_OK == sos_thread_sleep(& t)); SOS_ASSERT_FATAL(sos_time_is_zero(& t)); sos_x86_videomem_putchar(thr_arg->row, thr_arg->col, 0x1e, 'R'); } /* Infinite loop otherwise */ }}static void test_thread(){ /* "static" variables because we want them to remain even when the function returns */ static struct thr_arg arg_b, arg_c, arg_d, arg_e, arg_R, arg_S; sos_ui32_t flags; sos_disable_IRQs(flags); arg_b = (struct thr_arg) { .character='b', .col=0, .row=21, .color=0x14 }; sos_create_kernel_thread("YO[b]", demo_thread, (void*)&arg_b, SOS_SCHED_PRIO_TS_LOWEST); arg_c = (struct thr_arg) { .character='c', .col=46, .row=21, .color=0x14 }; sos_create_kernel_thread("YO[c]", demo_thread, (void*)&arg_c, SOS_SCHED_PRIO_TS_LOWEST); arg_d = (struct thr_arg) { .character='d', .col=0, .row=20, .color=0x14 }; sos_create_kernel_thread("YO[d]", demo_thread, (void*)&arg_d, SOS_SCHED_PRIO_TS_LOWEST-1); arg_e = (struct thr_arg) { .character='e', .col=0, .row=19, .color=0x14 }; sos_create_kernel_thread("YO[e]", demo_thread, (void*)&arg_e, SOS_SCHED_PRIO_TS_LOWEST-2); arg_R = (struct thr_arg) { .character='R', .col=0, .row=17, .color=0x1c }; sos_create_kernel_thread("YO[R]", demo_thread, (void*)&arg_R, SOS_SCHED_PRIO_RT_LOWEST); arg_S = (struct thr_arg) { .character='S', .col=0, .row=16, .color=0x1c }; sos_create_kernel_thread("YO[S]", demo_thread, (void*)&arg_S, SOS_SCHED_PRIO_RT_LOWEST-1); sos_restore_IRQs(flags);}/* ====================================================================== * An operating system MUST always have a ready thread ! Otherwise: * what would the CPU have to execute ?! */static void idle_thread(){ sos_ui32_t idle_twiddle = 0; while (1) { /* Remove this instruction if you get an "Invalid opcode" CPU exception (old 80386 CPU) */ asm("hlt\n"); idle_twiddle ++; display_bits(0, 0, SOS_X86_VIDEO_FG_GREEN | SOS_X86_VIDEO_BG_BLUE, idle_twiddle);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -