├── .gitignore ├── CMakeLists.txt ├── README.md ├── boot ├── __init__.py ├── __main__.py ├── boot.py ├── kernel.py └── screen.py ├── dev ├── device.cpp ├── device.h ├── device_list.cpp ├── device_list.h ├── devices │ ├── clock │ │ ├── clock.cpp │ │ └── clock.h │ ├── device_t.cpp │ ├── device_t.h │ ├── input │ │ ├── input.cpp │ │ ├── input.h │ │ ├── input_screen.cpp │ │ ├── input_screen.h │ │ ├── input_terminal.cpp │ │ └── input_terminal.h │ ├── null │ │ ├── null.cpp │ │ └── null.h │ ├── output │ │ ├── output.cpp │ │ ├── output.h │ │ ├── output_screen.cpp │ │ ├── output_screen.h │ │ ├── output_terminal.cpp │ │ └── output_terminal.h │ └── screen │ │ ├── screen.cpp │ │ └── screen.h └── utils │ ├── create_io_device_helper.cpp │ └── create_io_device_helper.h ├── docs ├── 4user │ ├── memory.md │ ├── process.md │ ├── program.md │ └── utils.md ├── readme.md └── report.md ├── entry.py ├── requirements.txt ├── screen ├── __init__.py ├── __main__.py ├── data.py ├── input │ ├── __init__.py │ └── keyboard_event.py ├── interact │ ├── __init__.py │ ├── read.py │ └── write.py ├── message │ ├── __init__.py │ └── print_msg.py ├── output │ ├── __init__.py │ └── write.py └── screen │ ├── __init__.py │ ├── app.py │ ├── console.py │ ├── key_bindings.py │ ├── key_bindings_with_any.py │ ├── utils.py │ └── windows.py ├── src ├── apic │ ├── interrupt_affinity.cpp │ ├── interrupt_affinity.h │ ├── interrupt_queue.cpp │ ├── interrupt_queue.h │ ├── io_apic.cpp │ ├── io_apic.h │ ├── local_apic.cpp │ └── local_apic.h ├── context │ ├── context.cpp │ └── context.h ├── core │ ├── core.cpp │ ├── core.h │ ├── cpus.cpp │ └── cpus.h ├── destroy │ ├── destroy.cpp │ └── destroy.h ├── env │ ├── env.cpp │ └── env.h ├── init │ ├── init.cpp │ └── init.h ├── interrupt │ ├── interrupt.cpp │ ├── interrupt.h │ ├── interrupt_id.cpp │ ├── interrupt_id.h │ ├── interrupts │ │ ├── clock_interrupt.cpp │ │ ├── clock_interrupt.h │ │ ├── disable_io_apic.cpp │ │ ├── disable_io_apic.h │ │ ├── disable_lapic.cpp │ │ ├── disable_lapic.h │ │ ├── double_internal_test.cpp │ │ ├── double_internal_test.h │ │ ├── end_of_interrupt.cpp │ │ ├── end_of_interrupt.h │ │ ├── external_interrupt_t.cpp │ │ ├── external_interrupt_t.h │ │ ├── internal_interrupt_t.cpp │ │ ├── internal_interrupt_t.h │ │ ├── internal_test.cpp │ │ ├── internal_test.h │ │ ├── interrupt_t.cpp │ │ ├── interrupt_t.h │ │ ├── intr_pagefault.cpp │ │ ├── intr_pagefault.h │ │ ├── io_apic_end_of_interrupt.cpp │ │ ├── io_apic_end_of_interrupt.h │ │ ├── io_apic_signal_t.cpp │ │ ├── io_apic_signal_t.h │ │ ├── keyboard_interrupt.cpp │ │ ├── keyboard_interrupt.h │ │ ├── lapic_process_interrupt_signal.cpp │ │ ├── lapic_process_interrupt_signal.h │ │ ├── lapic_signal_t.cpp │ │ ├── lapic_signal_t.h │ │ ├── syscall_interrupt.cpp │ │ └── syscall_interrupt.h │ ├── trap.cpp │ └── trap.h ├── io │ ├── io.cpp │ ├── io.h │ ├── special_keys.cpp │ ├── special_keys.h │ ├── stdio.cpp │ └── stdio.h ├── logging │ ├── log_helper.cpp │ ├── log_helper.h │ ├── logging.cpp │ └── logging.h ├── main.cpp ├── message │ ├── message.cpp │ ├── message.h │ ├── msg_helper.cpp │ └── msg_helper.h ├── mm │ ├── page_table.cpp │ ├── page_table.h │ ├── pmem.cpp │ ├── pmem.h │ ├── pmem_info.cpp │ ├── pmem_info.h │ ├── pmm.cpp │ └── pmm.h ├── mmu │ ├── mmu.cpp │ └── mmu.h ├── motherboard │ ├── motherboard.cpp │ └── motherboard.h ├── process │ ├── idle.cpp │ ├── idle.h │ ├── proc_dmm.cpp │ ├── process.cpp │ ├── process.h │ ├── process_load.cpp │ ├── process_t.cpp │ └── process_t.h ├── program │ ├── alloc.cpp │ ├── dmm.cpp │ ├── dmm.h │ ├── lib.cpp │ ├── lib.h │ ├── program.cpp │ ├── program.h │ ├── program_manager.cpp │ ├── program_manager.h │ ├── sys_t.cpp │ └── sys_t.h ├── schedule │ ├── sched_msg.cpp │ ├── sched_msg.h │ ├── schedule.cpp │ ├── schedule.h │ ├── signal.cpp │ └── signal.h ├── status │ ├── status.cpp │ └── status.h ├── syscall │ ├── syscall.cpp │ ├── syscall.h │ ├── syscall_id.cpp │ ├── syscall_id.h │ └── syscalls │ │ ├── sys_clock.cpp │ │ ├── sys_clock.h │ │ ├── sys_create_proc.cpp │ │ ├── sys_create_proc.h │ │ ├── sys_exec_prog.cpp │ │ ├── sys_exec_prog.h │ │ ├── sys_exit.cpp │ │ ├── sys_exit.h │ │ ├── sys_parent.cpp │ │ ├── sys_parent.h │ │ ├── sys_pid.cpp │ │ ├── sys_pid.h │ │ ├── sys_read.cpp │ │ ├── sys_read.h │ │ ├── sys_wait.cpp │ │ ├── sys_wait.h │ │ ├── sys_write.cpp │ │ ├── sys_write.h │ │ ├── sys_yield.cpp │ │ ├── sys_yield.h │ │ ├── syscall_t.cpp │ │ ├── syscall_t.h │ │ ├── syscall_test.cpp │ │ └── syscall_test.h └── utils │ ├── allocator │ ├── allocator.cpp │ ├── allocator.h │ ├── ffma.cpp │ └── ffma.h │ ├── assert.h │ ├── bus │ └── bus.h │ ├── check.cpp │ ├── check.h │ ├── pagerepl │ ├── fifo.cpp │ ├── fifo.h │ ├── pagerepl.cpp │ └── pagerepl.h │ ├── panic.cpp │ ├── panic.h │ ├── safe_condition_variable │ ├── safe_condition_variable.cpp │ └── safe_condition_variable.h │ └── thread_safe_queue │ └── thread_safe_queue.h ├── test ├── test.cpp ├── test.h ├── test_devices.cpp ├── test_devices.h ├── test_ffma.cpp ├── test_ffma.h ├── test_heap.cpp ├── test_heap.h ├── test_interrupt.cpp ├── test_interrupt.h ├── test_message.cpp ├── test_message.h ├── test_multiproc.cpp ├── test_multiproc.h ├── test_pm.cpp ├── test_pm.h ├── test_pmm.cpp ├── test_pmm.h ├── test_process.cpp ├── test_process.h ├── test_program_manager.cpp ├── test_program_manager.h ├── test_syscall.cpp └── test_syscall.h └── user ├── demo_interrupt ├── demo_interrupt.cpp └── demo_interrupt.h ├── demo_pagefault ├── demo_pagefault.cpp └── demo_pagefault.h ├── demo_process ├── demo_process.cpp └── demo_process.h ├── elephant ├── elephant.cpp ├── elephant.h ├── elephant_boom.cpp └── elephant_boom.h ├── hyperlib.h ├── hyperstd.h ├── keymap.h ├── lp ├── lp.cpp └── lp.h ├── matrix ├── matrix.cpp └── matrix.h └── shell ├── shell.cpp ├── shell.h ├── shell_exec.cpp ├── shell_help.cpp ├── shell_msg.cpp ├── shell_prog.cpp └── shell_utils.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | 3 | bin 4 | CMakeFiles 5 | 6 | *.vcxproj* 7 | Debug 8 | 9 | cmake_install.cmake 10 | CmakeFiles 11 | CMakeCache.txt 12 | Makefile 13 | 14 | *~ 15 | 16 | *.log 17 | 18 | __pycache__ 19 | debug_entry.py 20 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED ( VERSION 3.1 ) 2 | 3 | SET ( CMAKE_CXX_STANDARD 11 ) 4 | 5 | PROJECT ( HYPER-OS ) 6 | 7 | FILE ( GLOB_RECURSE src_list "user/*.cpp" "src/*.cpp" "test/*.cpp" "dev/*.cpp" ) 8 | 9 | SET ( prog_name hos ) 10 | 11 | SET ( CMAKE_INSTALL_PREFIX ) 12 | 13 | SET ( EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin ) 14 | ADD_EXECUTABLE ( ${prog_name} ${src_list} ) 15 | 16 | target_link_libraries( ${prog_name} pthread ) 17 | 18 | if (WIN32) 19 | if(CMAKE_COMPILER_IS_GNUCXX) 20 | set(CMAKE_CXX_FLAGS "-Wall -O2") 21 | endif(CMAKE_COMPILER_IS_GNUCXX) 22 | else () 23 | if(CMAKE_COMPILER_IS_GNUCXX) 24 | set(CMAKE_CXX_FLAGS "-Wall -O2 -fsanitize=undefined ${CMAKE_CXX_FLAGS}") 25 | endif(CMAKE_COMPILER_IS_GNUCXX) 26 | endif () 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Hyper-OS 2 | 3 | Hyper-OS(HOS) is an Operating System Simulator for teaching and research use. It contains basic virtual hardwares (such as CPU, APIC, MMU, etc) and a tiny kernel. Different from other teaching OSes, Hyper-OS is not running on a real machine, so that it's easy enough for students without hardware knowledges. HOS can show the principle of interrupt, paging, memory allocation, process scheduling and symmetrical multi-processing by writing simple user-time programs. 4 | 5 | ## Build 6 | 7 | ### Linux 8 | #### Requirements 9 | - `Python3` 10 | - `python3-pip` 11 | - `CMake >= 3.1` 12 | - `GNU Make` 13 | 14 | #### Get dependencies with python-pip 15 | Install dependencies with the following command: 16 | ``` 17 | pip3 install -r requirements.txt 18 | ``` 19 | 20 | #### Compile hos kernel 21 | Compile HOS using CMake and GNU make 22 | ``` 23 | mkdir build 24 | cd build 25 | cmake .. 26 | make 27 | cd .. 28 | cp build/bin/hos bin/hos 29 | ``` 30 | 31 | the binary file is located in `bin/hos`. 32 | 33 | #### Run the kernel 34 | Just run the `entry.py` script, and have fun: 35 | ``` 36 | python3 entry.py 37 | ``` 38 | 39 | ### Windows 40 | #### Requirements 41 | - `Python3` 42 | - `python3-pip` 43 | - `CMake >= 3.1` 44 | - `Visual Studio 2017` or `Visual Studio 2019` 45 | 46 | Notes: 47 | - Remember to add `python` to `PATH` 48 | 49 | #### Get dependencies with python-pip 50 | Install dependencies with the following command: 51 | ``` 52 | pip install -r requirements.txt 53 | ``` 54 | 55 | #### Compile hos kernel 56 | Generate the Visual Studio Solution using cmake in PowerShell: 57 | ``` 58 | mkdir build 59 | cd build 60 | cmake .. 61 | ``` 62 | Then you need to compile HOS using Visual Studio. You may need to copy the executable file generated to `bin/hos`. 63 | 64 | #### Run the kernel 65 | Just run the `entry.py` script, and have fun: 66 | ``` 67 | python entry.py 68 | ``` 69 | -------------------------------------------------------------------------------- /boot/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | boot.__init__ 5 | """ 6 | -------------------------------------------------------------------------------- /boot/__main__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | boot.__main__ 5 | """ 6 | 7 | from boot import boot 8 | 9 | 10 | def main (): 11 | boot.main () 12 | -------------------------------------------------------------------------------- /boot/boot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | boot.boot 5 | Boot Hyper-OS 6 | """ 7 | 8 | 9 | import os 10 | import subprocess 11 | 12 | from boot import kernel 13 | from boot import screen 14 | 15 | 16 | def start (): 17 | kernel.start () 18 | screen.start () 19 | 20 | def stop (): 21 | kernel.kern_proc.kill () 22 | try: 23 | kernel.kern_proc.wait (timeout=1) 24 | except subprocess.TimeoutExpired: 25 | kernel.kern_proc.terminate () 26 | 27 | os._exit (0) 28 | 29 | 30 | def main (): 31 | start () 32 | 33 | stop () 34 | -------------------------------------------------------------------------------- /boot/kernel.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | boot.kernel 5 | Boot the kernel 6 | """ 7 | 8 | 9 | import subprocess 10 | import threading 11 | import os 12 | import pathlib 13 | 14 | import screen 15 | 16 | 17 | kern_proc = None 18 | kern_up_event = threading.Event () 19 | 20 | 21 | def daemon_thread (): 22 | kern_path = os.path.join (os.path.dirname(os.path.abspath (__file__)), '..', 'bin', 'hos') 23 | 24 | global kern_proc 25 | 26 | try: 27 | kern_proc = subprocess.Popen ( 28 | args = [kern_path], 29 | stdin = subprocess.PIPE, 30 | stdout = subprocess.PIPE, 31 | stderr = subprocess.PIPE 32 | ) 33 | except FileNotFoundError: 34 | print ('Error: cannot open kernel, check if kernel executable file is at bin/hos.') 35 | os._exit (0) 36 | 37 | kern_up_event.set () 38 | 39 | kern_proc.wait () 40 | 41 | screen.screen_exit () 42 | 43 | os._exit (0) 44 | 45 | 46 | def start (): 47 | kern_thr = threading.Thread (target=daemon_thread) 48 | kern_thr.start () 49 | kern_up_event.wait () 50 | -------------------------------------------------------------------------------- /boot/screen.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | boot.screen 5 | Boot the screen 6 | """ 7 | 8 | 9 | import multiprocessing 10 | 11 | from screen import __main__ as screen_main 12 | from boot import kernel 13 | 14 | 15 | def start (): 16 | screen_main.main (kernel.kern_proc) 17 | -------------------------------------------------------------------------------- /dev/device.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * dev/device.cpp 3 | * Devices 4 | */ 5 | 6 | #include "device.h" 7 | #include "device_list.h" 8 | #include "../src/motherboard/motherboard.h" 9 | #include "../src/logging/logging.h" 10 | 11 | void init_devices () 12 | { 13 | logging::info << "Initializing " << device_list.size () << " device(s)" << logging::log_endl; 14 | for ( int i = 0; i < static_cast < int > ( device_list.size () ); ++i ) { 15 | device_list[i]->init_motherboard (); 16 | logging::info << "Initializing device #" << i << " : " << device_list[i]->to_string () << ", on motherboard #" << device_list[i]->get_motherboard ()->get_id () << logging::log_endl; 17 | device_list[i]->set_id ( i ); 18 | device_list[i]->init (); 19 | } 20 | } 21 | 22 | void destroy_devices () 23 | { 24 | logging::info << "Destroying device(s)" << logging::log_endl; 25 | for ( int i = 0; i < static_cast < int > ( device_list.size () ); ++i ) { 26 | device_list[i]->destroy (); 27 | delete device_list[i]; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /dev/device.h: -------------------------------------------------------------------------------- 1 | /** 2 | * dev/device.h 3 | * Devices 4 | */ 5 | 6 | #pragma once 7 | 8 | void init_devices (); 9 | void destroy_devices (); 10 | -------------------------------------------------------------------------------- /dev/device_list.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * dev/device_list.cpp 3 | * Devices list 4 | */ 5 | 6 | #include "device_list.h" 7 | 8 | #include "devices/null/null.h" 9 | #include "devices/clock/clock.h" 10 | #include "utils/create_io_device_helper.h" 11 | #include "../src/env/env.h" 12 | 13 | std::vector < device_t * > device_list ( { 14 | new dev_null ( 0 ), 15 | new dev_clock ( 0, std::chrono::milliseconds ( CLOCK_INTERVAL ) ), 16 | make_input_device ( 0 ), 17 | make_output_device ( 0 ), 18 | new dev_screen ( 0 ) 19 | } ); 20 | 21 | 22 | 23 | namespace device_desc 24 | { 25 | dev_input *standard_input = dynamic_cast < dev_input * > ( device_list[2] ); 26 | dev_output *standard_output = dynamic_cast < dev_output * > ( device_list[3] ); 27 | 28 | dev_screen *device_screen = dynamic_cast < dev_screen * > ( device_list[4] ); 29 | } 30 | -------------------------------------------------------------------------------- /dev/device_list.h: -------------------------------------------------------------------------------- 1 | /** 2 | * dev/device_list.h 3 | * Devices list 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "devices/device_t.h" 9 | #include "devices/input/input.h" 10 | #include "devices/output/output.h" 11 | #include "devices/screen/screen.h" 12 | #include 13 | 14 | extern std::vector < device_t * > device_list; 15 | 16 | namespace device_desc 17 | { 18 | extern dev_input *standard_input; 19 | extern dev_output *standard_output; 20 | 21 | extern dev_screen *device_screen; 22 | } 23 | -------------------------------------------------------------------------------- /dev/devices/clock/clock.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * dev/devices/clock/clock.cpp 3 | * Device clock 4 | */ 5 | 6 | #include "clock.h" 7 | #include "../../../src/motherboard/motherboard.h" 8 | #include "../../../src/interrupt/interrupts/clock_interrupt.h" 9 | #include 10 | #include "../../../src/logging/logging.h" 11 | #include "../../../src/message/message.h" 12 | 13 | dev_clock::dev_clock ( int __motherboard_id, std::chrono::nanoseconds _tick_duration ) 14 | : device_t ( __motherboard_id ) 15 | , tick_duration ( _tick_duration ) 16 | { 17 | } 18 | 19 | void dev_clock::init () 20 | { 21 | device_t::init (); 22 | 23 | device_thread = std::thread ( &dev_clock::device_thread_entry, this, status ); 24 | } 25 | 26 | void dev_clock::destroy () 27 | { 28 | device_t::destroy (); 29 | 30 | prom.set_value ( 0 ); 31 | device_thread.join (); 32 | } 33 | 34 | std::string dev_clock::to_string () const 35 | { 36 | return "clock"; 37 | } 38 | 39 | void dev_clock::device_thread_event_loop () 40 | { 41 | logging::debug << "Device clock entered event loop" << logging::log_endl; 42 | auto wait_future = prom.get_future (); 43 | while ( true ) { 44 | if ( wait_future.wait_for ( tick_duration ) == std::future_status::timeout ) { 45 | logging::debug << "Device clock sending a tick" << logging::log_endl; 46 | message::interrupt ( "dev clock" ) << "Device clock sending a tick" << message::msg_endl; 47 | get_motherboard ()->send_interrupt ( new clock_interrupt () ); 48 | } else { 49 | logging::debug << "Device clock received kill signal" << logging::log_endl; 50 | return; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /dev/devices/clock/clock.h: -------------------------------------------------------------------------------- 1 | /** 2 | * dev/devices/clock/clock.h 3 | * Device clock 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "../device_t.h" 9 | #include 10 | #include 11 | #include "../../../src/status/status.h" 12 | 13 | class dev_clock : public device_t 14 | { 15 | public: 16 | dev_clock ( int __motherboard_id, std::chrono::nanoseconds _tick_duration = std::chrono::milliseconds ( 1 ) ); 17 | 18 | virtual void init (); 19 | virtual void destroy (); 20 | 21 | virtual std::string to_string () const; 22 | 23 | private: 24 | virtual void device_thread_event_loop (); 25 | 26 | std::chrono::nanoseconds tick_duration; 27 | 28 | std::promise < int > prom; 29 | }; 30 | -------------------------------------------------------------------------------- /dev/devices/device_t.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * dev/device_t.cpp 3 | * Devices base class 4 | */ 5 | 6 | #include "device_t.h" 7 | #include "../../src/motherboard/motherboard.h" 8 | #include "../../src/logging/logging.h" 9 | #include 10 | 11 | device_t::device_t () 12 | { 13 | } 14 | 15 | device_t::device_t ( int __motherboard_id ) 16 | : _motherboard_id ( __motherboard_id ) 17 | { 18 | } 19 | 20 | device_t::device_t ( motherboard_t * _motherboard ) 21 | : motherboard ( _motherboard ) 22 | { 23 | } 24 | 25 | device_t::~device_t () 26 | { 27 | } 28 | 29 | void device_t::set_id ( int _id ) 30 | { 31 | id = _id; 32 | } 33 | 34 | int device_t::get_id () const 35 | { 36 | return id; 37 | } 38 | 39 | void device_t::init_motherboard () 40 | { 41 | motherboard = &motherboards[_motherboard_id]; 42 | } 43 | 44 | void device_t::set_motherboard ( motherboard_t * _motherboard ) 45 | { 46 | motherboard = _motherboard; 47 | } 48 | 49 | motherboard_t * device_t::get_motherboard () const 50 | { 51 | return motherboard; 52 | } 53 | 54 | void device_t::init () 55 | { 56 | logging::debug << "Initializing device " << to_string () << logging::log_endl; 57 | } 58 | 59 | void device_t::destroy () 60 | { 61 | logging::debug << "Destroying device " << to_string () << logging::log_endl; 62 | } 63 | 64 | std::string device_t::to_string () const 65 | { 66 | return ""; 67 | } 68 | 69 | void device_t::device_thread_entry ( status_t father_thread_status ) 70 | { 71 | status = father_thread_status; 72 | status.set_core ( NULL ); 73 | std::stringstream string_helper; 74 | string_helper << "device #" << get_id () << " (" << to_string () << ")"; 75 | status.set_name ( string_helper.str () ); 76 | logging::debug << "Device #" << get_id () << " (" << to_string () << ") created" << logging::log_endl; 77 | 78 | device_thread_event_loop (); 79 | } 80 | 81 | void device_t::device_thread_event_loop () 82 | { 83 | logging::error << "Device thread event loop of device " << to_string () << " not implemented" << logging::log_endl; 84 | } 85 | -------------------------------------------------------------------------------- /dev/devices/device_t.h: -------------------------------------------------------------------------------- 1 | /** 2 | * dev/device_t.h 3 | * Devices base class 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include "../../src/status/status.h" 11 | 12 | class motherboard_t; 13 | 14 | class device_t 15 | { 16 | public: 17 | device_t (); 18 | device_t ( int __motherboard_id ); // initialize with motherboard ID 19 | device_t ( motherboard_t *_motherboard ); // initialize with a specific motherboard 20 | virtual ~device_t (); 21 | 22 | void set_id ( int _id ); 23 | int get_id () const; 24 | 25 | void init_motherboard (); // set motherboard using motherboard ID; 26 | 27 | void set_motherboard ( motherboard_t *_motherboard ); 28 | motherboard_t * get_motherboard () const; 29 | 30 | virtual void init (); 31 | virtual void destroy (); 32 | 33 | virtual std::string to_string () const; 34 | 35 | protected: 36 | void device_thread_entry ( status_t father_thread_status ); // device daemon thread entry 37 | virtual void device_thread_event_loop (); // device daemon thread entry 38 | 39 | int id; // device ID 40 | 41 | int _motherboard_id; 42 | motherboard_t *motherboard; // motherboard on which the device is 43 | 44 | std::thread device_thread; // device daemon thread 45 | }; 46 | -------------------------------------------------------------------------------- /dev/devices/input/input.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * dev/devices/input/input.h 3 | * Device input 4 | */ 5 | 6 | #include "input.h" 7 | #include "../../../src/logging/logging.h" 8 | 9 | dev_input::dev_input ( int __motherboard_id ) 10 | : device_t ( __motherboard_id ) 11 | { 12 | } 13 | 14 | std::string dev_input::to_string () const 15 | { 16 | return "input"; 17 | } 18 | -------------------------------------------------------------------------------- /dev/devices/input/input.h: -------------------------------------------------------------------------------- 1 | /** 2 | * dev/devices/input/input.h 3 | * Device input 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "../device_t.h" 9 | #include "../../../src/status/status.h" 10 | #include 11 | 12 | class dev_input : public device_t 13 | { 14 | public: 15 | dev_input ( int __motherboard_id ); 16 | 17 | virtual std::string to_string () const; 18 | 19 | virtual int read () = 0; 20 | 21 | private: 22 | }; 23 | -------------------------------------------------------------------------------- /dev/devices/input/input_screen.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * dev/devices/input/input_screen.cpp 3 | * Device input 4 | * Input from module screen 5 | */ 6 | 7 | #include "input_screen.h" 8 | #include "../../../src/logging/logging.h" 9 | #include "../../../src/message/message.h" 10 | #include "../../../src/process/process.h" 11 | #include "../../../src/schedule/signal.h" 12 | #include "../../../src/status/status.h" 13 | #include "../../../src/core/core.h" 14 | #include "../../../src/motherboard/motherboard.h" 15 | #include "../../../src/interrupt/interrupts/keyboard_interrupt.h" 16 | 17 | dev_input_screen::dev_input_screen ( int __motherboard_id ) 18 | : dev_input ( __motherboard_id ) 19 | { 20 | } 21 | 22 | void dev_input_screen::init () 23 | { 24 | logging::debug << "Initializing device input, mode: screen" << logging::log_endl; 25 | 26 | device_thread = std::thread ( &dev_input_screen::device_thread_entry, this, status ); 27 | } 28 | 29 | void dev_input_screen::destroy () 30 | { 31 | logging::debug << "Destroying device input, mode: screen" << logging::log_endl; 32 | 33 | event_queue.push_front ( "" ); // Send exit signal 34 | device_thread.join (); 35 | } 36 | 37 | int dev_input_screen::read () 38 | { 39 | if ( status.get_core ()->get_current () == nullptr ) { 40 | logging::error << "Read from kernel is not implemented" << logging::log_endl; 41 | return 0; 42 | } 43 | proc_wait ( signal_id::KEYBOARD ); 44 | return 0; 45 | } 46 | 47 | void dev_input_screen::send_key ( std::string key ) 48 | { 49 | event_queue.push_back ( key ); 50 | } 51 | 52 | void dev_input_screen::device_thread_event_loop () 53 | { 54 | while ( 1 ) { 55 | std::string data = event_queue.pop_front (); 56 | 57 | if ( data == "" ) { // Handle exit signal 58 | break; 59 | } 60 | 61 | logging::info << "device input received line : \"" << data << "\"" << logging::log_endl; 62 | message::test ( "dev input" ) << "device input received line : \"" << data << "\"" << message::msg_endl; 63 | 64 | get_motherboard ()->send_interrupt ( new keyboard_interrupt ( data ) ); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /dev/devices/input/input_screen.h: -------------------------------------------------------------------------------- 1 | /** 2 | * dev/devices/input/input_screen.h 3 | * Device input 4 | * Input from module screen 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "input.h" 10 | #include "../../../src/status/status.h" 11 | #include "../../../src/utils/thread_safe_queue/thread_safe_queue.h" 12 | #include 13 | 14 | class dev_input_screen : public dev_input 15 | { 16 | public: 17 | dev_input_screen ( int __motherboard_id ); 18 | 19 | virtual void init (); 20 | virtual void destroy (); 21 | 22 | virtual int read (); 23 | 24 | virtual void send_key ( std::string key ); 25 | 26 | private: 27 | virtual void device_thread_event_loop (); 28 | 29 | thread_safe_queue < std::string > event_queue; 30 | }; 31 | -------------------------------------------------------------------------------- /dev/devices/input/input_terminal.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * dev/devices/input/input_terminal.cpp 3 | * Device input 4 | * Input directly from teminal 5 | */ 6 | 7 | #include "input_terminal.h" 8 | #include "../../../src/logging/logging.h" 9 | #include "../../../src/status/status.h" 10 | #include "../../../src/core/core.h" 11 | 12 | dev_input_terminal::dev_input_terminal ( int __motherboard_id ) 13 | : dev_input ( __motherboard_id ) 14 | { 15 | } 16 | 17 | void dev_input_terminal::init () 18 | { 19 | logging::debug << "Initializing device input, mode: terminal" << logging::log_endl; 20 | } 21 | 22 | void dev_input_terminal::destroy () 23 | { 24 | logging::debug << "Destroying device input, mode: terminal" << logging::log_endl; 25 | } 26 | 27 | int dev_input_terminal::read () 28 | { 29 | if ( status.get_core ()->get_current () == nullptr ) { 30 | logging::error << "Read from kernel is not implemented" << logging::log_endl; 31 | return 0; 32 | } 33 | logging::debug << "Reading character from device input" << logging::log_endl; 34 | char ch; 35 | ch = getchar (); 36 | status.get_core ()->get_current ()->set_signal_data ( ch ); 37 | if ( ch >= 32 ) { 38 | logging::debug << "Device input received character '" << ch << "' ( ASCII " << static_cast < int > ( ch ) << " ) " << logging::log_endl; 39 | } else { 40 | logging::debug << "Device input received unvisible character ( ASCII " << static_cast < int > ( ch ) << " ) " << logging::log_endl; 41 | } 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /dev/devices/input/input_terminal.h: -------------------------------------------------------------------------------- 1 | /** 2 | * dev/devices/input/input_terminal.h 3 | * Device input 4 | * Input directly from teminal 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "input.h" 10 | #include "../../../src/status/status.h" 11 | #include 12 | 13 | class dev_input_terminal : public dev_input 14 | { 15 | public: 16 | dev_input_terminal ( int __motherboard_id ); 17 | 18 | virtual void init (); 19 | virtual void destroy (); 20 | 21 | virtual int read (); 22 | 23 | private: 24 | }; 25 | -------------------------------------------------------------------------------- /dev/devices/null/null.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * dev/devices/null/null.cpp 3 | * Device NULL 4 | */ 5 | 6 | #include "null.h" 7 | #include "../../../src/logging/logging.h" 8 | 9 | dev_null::dev_null ( int __motherboard_id ) 10 | : device_t ( __motherboard_id ) 11 | { 12 | } 13 | 14 | std::string dev_null::to_string () const 15 | { 16 | return "NULL"; 17 | } 18 | -------------------------------------------------------------------------------- /dev/devices/null/null.h: -------------------------------------------------------------------------------- 1 | /** 2 | * dev/devices/null/null.h 3 | * Device NULL 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "../device_t.h" 9 | 10 | class dev_null : public device_t 11 | { 12 | public: 13 | dev_null ( int __motherboard_id ); 14 | 15 | virtual std::string to_string () const; 16 | 17 | private: 18 | }; 19 | -------------------------------------------------------------------------------- /dev/devices/output/output.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * dev/devices/output/output.h 3 | * Device output 4 | */ 5 | 6 | #include "output.h" 7 | #include "../../../src/logging/logging.h" 8 | 9 | dev_output::dev_output ( int __motherboard_id ) 10 | : device_t ( __motherboard_id ) 11 | { 12 | } 13 | 14 | std::string dev_output::to_string () const 15 | { 16 | return "output"; 17 | } 18 | 19 | void dev_output::write ( std::string str ) 20 | { 21 | for ( auto x : str ) { 22 | write ( x ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /dev/devices/output/output.h: -------------------------------------------------------------------------------- 1 | /** 2 | * dev/devices/output/output.h 3 | * Device output 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "../device_t.h" 9 | #include "../../../src/status/status.h" 10 | #include 11 | 12 | class dev_output : public device_t 13 | { 14 | public: 15 | dev_output ( int __motherboard_id ); 16 | 17 | virtual std::string to_string () const; 18 | 19 | virtual void write ( int ch ) = 0; 20 | virtual void write ( std::string str ); 21 | 22 | private: 23 | }; 24 | -------------------------------------------------------------------------------- /dev/devices/output/output_screen.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * dev/devices/output/output_screen.h 3 | * Device output 4 | * Output to module teminal 5 | */ 6 | 7 | #include "output_screen.h" 8 | #include "../../../src/logging/logging.h" 9 | #include "../../device_list.h" 10 | #include "../../../src/io/special_keys.h" 11 | 12 | dev_output_screen::dev_output_screen ( int __motherboard_id ) 13 | : dev_output ( __motherboard_id ) 14 | { 15 | } 16 | 17 | void dev_output_screen::init () 18 | { 19 | logging::debug << "Initializing device output, mode: screen" << logging::log_endl; 20 | } 21 | 22 | void dev_output_screen::destroy () 23 | { 24 | logging::debug << "Destroying device output, mode: screen" << logging::log_endl; 25 | } 26 | 27 | void dev_output_screen::write ( int ch ) 28 | { 29 | if ( ch >= 0 ) { 30 | if ( ch >= 32 ) { 31 | logging::debug << "Device output received character '" << ch << "' ( ASCII " << static_cast < int > ( ch ) << " ) " << logging::log_endl; 32 | } else { 33 | logging::debug << "Device output received unvisible character ( ASCII " << static_cast < int > ( ch ) << " ) " << logging::log_endl; 34 | } 35 | 36 | if ( ch == '\b' ) { // handle backspace 37 | device_desc::device_screen->backspace (); 38 | } else if ( ch == '\n' ) { 39 | device_desc::device_screen->newline (); 40 | } else { 41 | device_desc::device_screen->write_char ( static_cast < char > ( ch ) ); 42 | } 43 | } else { 44 | special_keys key = static_cast < special_keys > ( -ch ); 45 | logging::debug << "Device output received special key <" << get_key_str ( key ) << ">" << logging::log_endl; 46 | 47 | switch ( key ) { 48 | case special_keys::LEFT: 49 | device_desc::device_screen->cursor_move_left (); 50 | break; 51 | 52 | case special_keys::RIGHT: 53 | device_desc::device_screen->cursor_move_right (); 54 | break; 55 | 56 | default: 57 | logging::warning << "Special key <" << get_key_str ( key ) << "> not handled" << logging::log_endl; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /dev/devices/output/output_screen.h: -------------------------------------------------------------------------------- 1 | /** 2 | * dev/devices/output/output_screen.h 3 | * Device output 4 | * Output to module screen 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "output.h" 10 | #include "../../../src/status/status.h" 11 | #include 12 | 13 | class dev_output_screen : public dev_output 14 | { 15 | public: 16 | dev_output_screen ( int __motherboard_id ); 17 | 18 | virtual void init (); 19 | virtual void destroy (); 20 | 21 | virtual void write ( int ch ); 22 | 23 | private: 24 | }; 25 | -------------------------------------------------------------------------------- /dev/devices/output/output_terminal.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * dev/devices/output/output_terminal.h 3 | * Device output 4 | * Output directly to teminal 5 | */ 6 | 7 | #include "output_terminal.h" 8 | #include "../../../src/logging/logging.h" 9 | 10 | dev_output_terminal::dev_output_terminal ( int __motherboard_id ) 11 | : dev_output ( __motherboard_id ) 12 | { 13 | } 14 | 15 | void dev_output_terminal::init () 16 | { 17 | logging::debug << "Initializing device output, mode: terminal" << logging::log_endl; 18 | } 19 | 20 | void dev_output_terminal::destroy () 21 | { 22 | logging::debug << "Destroying device output, mode: terminal" << logging::log_endl; 23 | } 24 | 25 | void dev_output_terminal::write ( int ch ) 26 | { 27 | if ( ch >= 32 ) { 28 | logging::debug << "Device output received character '" << ch << "' ( ASCII " << static_cast < int > ( ch ) << " ) " << logging::log_endl; 29 | } else { 30 | logging::debug << "Device output received unvisible character ( ASCII " << static_cast < int > ( ch ) << " ) " << logging::log_endl; 31 | } 32 | putchar ( ch ); 33 | fflush ( stdout ); 34 | } 35 | -------------------------------------------------------------------------------- /dev/devices/output/output_terminal.h: -------------------------------------------------------------------------------- 1 | /** 2 | * dev/devices/output/output_terminal.h 3 | * Device output 4 | * Output directly to teminal 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "output.h" 10 | #include "../../../src/status/status.h" 11 | #include 12 | 13 | class dev_output_terminal : public dev_output 14 | { 15 | public: 16 | dev_output_terminal ( int __motherboard_id ); 17 | 18 | virtual void init (); 19 | virtual void destroy (); 20 | 21 | virtual void write ( int ch ); 22 | 23 | private: 24 | }; 25 | -------------------------------------------------------------------------------- /dev/devices/screen/screen.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * dev/devices/screen/screen 3 | * Device screen 4 | * Low-level interact methods with screen 5 | */ 6 | 7 | #include "screen.h" 8 | #include "../../../src/env/env.h" 9 | #include "../../../src/status/status.h" 10 | #include "../../../src/logging/logging.h" 11 | #include "../../device_list.h" 12 | #include "../input/input_screen.h" 13 | #include 14 | 15 | dev_screen::dev_screen ( int __motherboard_id ) 16 | : device_t ( __motherboard_id ) 17 | { 18 | } 19 | 20 | void dev_screen::init () 21 | { 22 | logging::debug << "Initializing device screen" << logging::log_endl; 23 | 24 | device_thread = std::thread ( &dev_screen::device_thread_entry, this, status ); 25 | } 26 | 27 | void dev_screen::destroy () 28 | { 29 | logging::debug << "Destroying device screen" << logging::log_endl; 30 | 31 | if ( IO_DEVICE ) { 32 | write ( "s", "shutdown" ); 33 | } 34 | device_thread.join (); 35 | } 36 | 37 | std::string dev_screen::to_string () const 38 | { 39 | return "screen"; 40 | } 41 | 42 | int dev_screen::read () 43 | { 44 | return 0; 45 | } 46 | 47 | void dev_screen::write ( std::string type, std::string data ) 48 | { 49 | std::unique_lock < std::mutex > lck ( write_lock ); 50 | 51 | std::cout << type << "[" << data << "]" << std::endl; 52 | } 53 | 54 | void dev_screen::write ( std::string type, std::string config, std::string data ) 55 | { 56 | std::unique_lock < std::mutex > lck ( write_lock ); 57 | 58 | std::cout << type << "{" << config << "}" << "[" << data << "]" << std::endl; 59 | } 60 | 61 | void dev_screen::write_char ( char ch ) 62 | { 63 | std::string str; 64 | str = ch; 65 | write ( "w", str ); 66 | } 67 | 68 | void dev_screen::backspace () 69 | { 70 | write ( "c", "backspace" ); 71 | } 72 | 73 | void dev_screen::newline () 74 | { 75 | write ( "c", "newline" ); 76 | } 77 | 78 | void dev_screen::cursor_move_left () 79 | { 80 | write ( "c", "cursor_move_left" ); 81 | } 82 | 83 | void dev_screen::cursor_move_right () 84 | { 85 | write ( "c", "cursor_move_right" ); 86 | } 87 | 88 | void dev_screen::device_thread_event_loop () 89 | { 90 | if ( IO_DEVICE ) { 91 | logging::debug << "device screen daemon thread up" << logging::log_endl; 92 | std::string line; 93 | while ( std::getline ( std::cin, line ) ) { 94 | logging::debug << "device screen received line : \"" << line << "\"" << logging::log_endl; 95 | 96 | std::string data = line.substr ( 1 ); 97 | if ( data[0] == '[' && data[data.size () - 1] == ']' ) { 98 | data = data.substr ( 1, data.size () - 2 ); 99 | } 100 | 101 | switch ( line[0] ) { 102 | case 'k': 103 | dynamic_cast < dev_input_screen * > ( device_desc::standard_input )->send_key ( data ); 104 | break; 105 | 106 | case 's': 107 | if ( data == "shutdown" ) { 108 | return; 109 | } 110 | logging::warning << "device screen received unexpected system command : " << data << logging::log_endl; 111 | break; 112 | 113 | default: 114 | logging::error << "device screen receive type " << line[0] << " which is not implemented" << logging::log_endl; 115 | } 116 | } 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /dev/devices/screen/screen.h: -------------------------------------------------------------------------------- 1 | /** 2 | * dev/devices/screen/screen 3 | * Device screen 4 | * Low-level interact methods with screen 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "../device_t.h" 10 | #include "../../../src/status/status.h" 11 | #include 12 | #include 13 | 14 | class dev_screen : public device_t 15 | { 16 | public: 17 | dev_screen ( int __motherboard_id ); 18 | 19 | void init (); 20 | void destroy (); 21 | 22 | virtual std::string to_string () const; 23 | 24 | virtual int read (); 25 | virtual void write ( std::string type, std::string data ); 26 | virtual void write ( std::string type, std::string config, std::string data ); 27 | 28 | virtual void write_char ( char ch ); 29 | virtual void backspace (); 30 | virtual void newline (); 31 | virtual void cursor_move_left (); 32 | virtual void cursor_move_right (); 33 | 34 | private: 35 | virtual void device_thread_event_loop (); 36 | 37 | std::mutex write_lock; 38 | }; 39 | -------------------------------------------------------------------------------- /dev/utils/create_io_device_helper.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * dev/utils/create_io_device_helper.cpp 3 | * Helper functions to create I/O Devices 4 | */ 5 | 6 | #include "create_io_device_helper.h" 7 | #include "../devices/input/input_terminal.h" 8 | #include "../devices/input/input_screen.h" 9 | #include "../devices/output/output_terminal.h" 10 | #include "../devices/output/output_screen.h" 11 | #include "../../src/env/env.h" 12 | 13 | device_t * make_input_device ( int motherboard_id ) 14 | { 15 | if ( IO_DEVICE ) { 16 | return new dev_input_screen ( motherboard_id ); 17 | } else { 18 | return new dev_input_terminal ( motherboard_id ); 19 | } 20 | } 21 | 22 | device_t * make_output_device ( int motherboard_id ) 23 | { 24 | if ( IO_DEVICE ) { 25 | return new dev_output_screen ( motherboard_id ); 26 | } else { 27 | return new dev_output_terminal ( motherboard_id ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /dev/utils/create_io_device_helper.h: -------------------------------------------------------------------------------- 1 | /** 2 | * dev/utils/create_io_device_helper.h 3 | * Helper functions to create I/O Devices 4 | */ 5 | 6 | #pragma once 7 | 8 | class device_t; 9 | 10 | device_t * make_input_device ( int motherboard_id ); 11 | device_t * make_output_device ( int motherboard_id ); 12 | -------------------------------------------------------------------------------- /docs/4user/utils.md: -------------------------------------------------------------------------------- 1 | ## Utilities 2 | 3 | ### Allocator 4 | 5 | `Allocator` is Interface for continuous memory allocation algorithms. Each allocation algorithm is a derived class of `class Allocator`, which implements two virtual functions. 6 | 7 | 1. `size_t malloc(size_t len)`: allocate continuous memory of length `@len`, return the start of it. 8 | 2. `void free(size_t ptr)`: free continuous memory starting from `@ptr`. 9 | 10 | `FFMA` is a simple first fit memory allocator, it maintains a list of free memory segments. When it needs to allocate continuous memory, the first segment that is large enough will be selected. -------------------------------------------------------------------------------- /docs/readme.md: -------------------------------------------------------------------------------- 1 | ## Hyper-OS 2 | 3 | Hyper-OS 的核心思想是使用线程和线程间的同步模拟处理器控制流和异常控制流,在这个模拟的硬件环境下完成一个足够简单和抽象的操作系统,从而达到揭示操作系统基本功能和原理的目的。 4 | 5 | 在Hyper-OS中,每个硬件运行在单独的线程上,每个正在运行的用户进程运行在一个线程上,每个处于等待状态的用户进程运行在一个线程上,但等在所在线程的条件变量`cond_var`上。 6 | 7 | ## 硬件 8 | 9 | Hyper-OS 的使用一个线程模拟一个逻辑上的硬件,例如物理内存、键盘、时钟等。这种线程称为硬件线程。硬件线程在初始化时被创建出来,并持续工作,利用“总线”、“中断”等方式与“处理器”协同工作。 10 | 11 | ## 进程和处理器 12 | 13 | 我们称Hyper-OS中提供的进程为用户进程。Hyper-OS不模拟处理器,而是将处理器看作某种”资源“。用户进程在运行时获取这个资源,并通过同步互斥机制,保证任何时候只有一个进程拥有某个处理器。 14 | 15 | 具体而言,每个处理器拥有一个互斥锁`cpu_mutex`,逻辑上运行在某个处理器的用户进程拥有这个锁。当其由于某种原因(例如被中断打断需要进入内核态)需要放弃处理器时,它放弃这个锁。 16 | 17 | 操作系统通过`create_process`创建一个逻辑进程,使用`exec_process`将某个应用程序加载到内存中执行。 18 | 19 | ## 中断 20 | 21 | 中断是硬件提供的打断当前控制流并进入对应中断处理例程的机制。在Hyper-OS中,中断信号的分发和处理是由APIC和LPIC实现的。 22 | 23 | TODO 24 | 25 | 用户进程通过在访存语句的末尾检查中断标记确定中断的发生。当检测到中断发生时,用于进程放弃CPU访问权,中断处理例程接管CPU并响应中断。 26 | 27 | ## 页机制 28 | 29 | Hyper-OS默认使用页机制管理内存。MMU通过页表查询虚拟地址对应的物理地址,并完成地址翻译。操作系统在每个进程创建时(`create_process`)建立其页表,并完成初始化工作。 30 | 31 | 当MMU发现页错误时,它会向所在的CPU发送一个页错误中断。 32 | 33 | ## 应用程序 34 | 35 | Hyper-OS使用一种简单的应用程序结构。 36 | 37 | 每一个应用程序是继承自抽象类`program`的一个类,实现两个函数: 38 | -------------------------------------------------------------------------------- /entry.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from boot import __main__ 4 | 5 | def main (): 6 | __main__.main () 7 | 8 | if __name__ == "__main__": 9 | main () 10 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | typing==3.6.6 2 | six==1.10.0 3 | prompt_toolkit==2.0.9 4 | -------------------------------------------------------------------------------- /screen/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | screen.__init__ 5 | """ 6 | 7 | 8 | from prompt_toolkit import eventloop 9 | 10 | from screen import data 11 | 12 | 13 | def screen_exit (): 14 | def application_exit (): 15 | data.application.exit () 16 | data.screen_down_event.set () 17 | eventloop.get_event_loop ().call_from_executor (application_exit) 18 | data.screen_down_event.wait () 19 | while data.application.is_running: 20 | pass 21 | -------------------------------------------------------------------------------- /screen/__main__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | screen.__main__ 5 | """ 6 | 7 | from screen import data 8 | from screen import screen 9 | from screen import interact 10 | 11 | 12 | def main (kern_proc): 13 | data.kern_proc = kern_proc 14 | 15 | interact.init () 16 | screen.init () 17 | 18 | screen.run () 19 | -------------------------------------------------------------------------------- /screen/data.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | screen.screen.data 5 | Data in screen application 6 | """ 7 | 8 | 9 | import threading 10 | 11 | import prompt_toolkit 12 | from prompt_toolkit import layout 13 | from prompt_toolkit import widgets 14 | from prompt_toolkit.key_binding import KeyBindings 15 | 16 | 17 | application = prompt_toolkit.Application () 18 | 19 | app_layout = None 20 | 21 | console_window = widgets.TextArea () 22 | messages_window = widgets.TextArea () 23 | app_windows = [] 24 | 25 | screen_up_event = threading.Event () 26 | screen_down_event = threading.Event () 27 | 28 | key_binding = KeyBindings () 29 | message_window_key_binding = KeyBindings () 30 | 31 | key_seq = [] 32 | 33 | kern_proc = None 34 | 35 | output_lock = threading.Lock () 36 | -------------------------------------------------------------------------------- /screen/input/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | screen.input.__init__ 5 | Input module 6 | """ 7 | -------------------------------------------------------------------------------- /screen/input/keyboard_event.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | screen.input.keyboard_event 5 | Handle keyboard events 6 | """ 7 | 8 | from screen import data 9 | from screen.screen import utils 10 | from screen import interact 11 | 12 | from prompt_toolkit import document 13 | 14 | def handle_keyboard_event (event): 15 | current_key = event.key_sequence[0].key 16 | current_data = event.key_sequence[0].data 17 | utils.move_cursor_to_end (data.messages_window.buffer) 18 | data.key_seq.append (current_key) 19 | if len(data.key_seq) > 100: 20 | data.key_seq.pop ( 0 ) 21 | interact.write.write ('k', '{}'.format (current_key)) 22 | -------------------------------------------------------------------------------- /screen/interact/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | screen.interact.__init__ 5 | Input/Output stream to interact with kernel 6 | """ 7 | 8 | 9 | from screen.interact import read 10 | from screen.interact import write 11 | 12 | 13 | def init (): 14 | read.init () 15 | write.init () 16 | -------------------------------------------------------------------------------- /screen/interact/read.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | screen.interact.read 5 | Read service to read from kernel 6 | """ 7 | 8 | 9 | import threading 10 | import os 11 | 12 | import json 13 | 14 | from screen import data 15 | from screen.output import write 16 | from screen import message 17 | from screen import interact 18 | 19 | 20 | read_thr = None 21 | 22 | 23 | def init (): 24 | read_thr = threading.Thread (target=read_thread_entry) 25 | read_thr.start () 26 | 27 | 28 | def read_thread_entry (): 29 | data.screen_up_event.wait () 30 | while not data.application.is_running: # Wait for the applicate to run 31 | pass 32 | for line in data.kern_proc.stdout: 33 | current_data = line.decode ('utf-8').strip () 34 | 35 | if len(current_data) == 0: 36 | continue 37 | 38 | current_type = current_data[0] 39 | current_data = current_data[1:] 40 | 41 | count_brac = 0 42 | config_split_i = 0 43 | for i in current_data: 44 | if i == '{': 45 | count_brac += 1 46 | elif i == '}': 47 | count_brac -= 1 48 | if count_brac == 0: 49 | break 50 | config_split_i += 1 51 | 52 | current_config = current_data[:config_split_i] 53 | current_data = current_data[config_split_i:] 54 | 55 | if current_config == '': 56 | current_config = {} 57 | else: 58 | current_config = json.loads (current_config) 59 | 60 | # TODO: Check that input has correct format 61 | 62 | if current_data[0] == '[' and current_data[-1] == ']': 63 | current_data = current_data[1:-1] 64 | 65 | if current_type == 'w': 66 | if len(current_data) == 1: 67 | write.putchar (current_data) 68 | elif current_data == '\\n': 69 | write.newline () 70 | elif current_type == 'm': 71 | message.print_message (current_data) 72 | elif current_type == 'c': 73 | if current_data == 'backspace': 74 | write.backspace () 75 | elif current_data == 'newline': 76 | write.newline () 77 | elif current_data == 'cursor_move_left': 78 | write.cursor_move_left () 79 | elif current_data == 'cursor_move_right': 80 | write.cursor_move_right () 81 | elif current_type == 's': 82 | if current_data == 'shutdown': 83 | interact.write.write ('s', 'shutdown') 84 | break 85 | -------------------------------------------------------------------------------- /screen/interact/write.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | screen.interact.write 5 | Write service to write to kernel 6 | """ 7 | 8 | 9 | import threading 10 | import os 11 | 12 | from screen import data 13 | 14 | 15 | def init (): 16 | pass 17 | 18 | 19 | def write (val_type, value): 20 | with data.output_lock: 21 | data.kern_proc.stdin.write (('{}[{}]\n'.format (val_type, value)).encode ('utf-8')) 22 | data.kern_proc.stdin.flush () 23 | -------------------------------------------------------------------------------- /screen/message/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | message.__init__ 5 | Message service 6 | """ 7 | 8 | 9 | from screen.message.print_msg import print_message 10 | -------------------------------------------------------------------------------- /screen/message/print_msg.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | screen.message.print_msg 5 | Print messages 6 | """ 7 | 8 | 9 | from screen import data 10 | from screen.screen import utils 11 | 12 | 13 | def print_message (msg): 14 | utils.move_cursor_to_end (data.messages_window.buffer) 15 | data.messages_window.buffer.insert_text (msg) 16 | data.messages_window.buffer.newline () 17 | -------------------------------------------------------------------------------- /screen/output/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | screen.output.__init__ 5 | Output module 6 | """ 7 | -------------------------------------------------------------------------------- /screen/output/write.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | screen.output.write 5 | Write to screen 6 | """ 7 | 8 | 9 | from screen import data 10 | from screen.screen import utils 11 | 12 | 13 | def putchar (ch): 14 | data.console_window.buffer.insert_text (ch) 15 | 16 | def newline (): 17 | data.console_window.buffer.newline () 18 | utils.move_cursor_to_line_start (data.console_window.buffer) 19 | 20 | def backspace (): 21 | data.console_window.buffer.delete_before_cursor () 22 | 23 | def cursor_move_left (): 24 | data.console_window.buffer.cursor_left () 25 | 26 | def cursor_move_right (): 27 | data.console_window.buffer.cursor_right () 28 | -------------------------------------------------------------------------------- /screen/screen/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | screen.screen.__init__ 5 | Process the screen 6 | """ 7 | 8 | from . import app 9 | from . import windows 10 | from . import key_bindings 11 | 12 | def init (): 13 | key_bindings.init () 14 | windows.init () 15 | app.init () 16 | 17 | def run (): 18 | app.run () 19 | -------------------------------------------------------------------------------- /screen/screen/app.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | screen.screen.app 5 | Application 6 | """ 7 | 8 | 9 | import prompt_toolkit 10 | from prompt_toolkit import layout 11 | from prompt_toolkit.layout import containers 12 | from prompt_toolkit import widgets 13 | from prompt_toolkit.key_binding import key_processor 14 | 15 | from screen import data 16 | from screen.screen import key_bindings 17 | from screen.screen import utils 18 | 19 | 20 | def init (): 21 | root_container = containers.VSplit (data.app_windows) 22 | 23 | data.app_layout = layout.Layout (root_container) 24 | 25 | data.application = prompt_toolkit.Application (layout=data.app_layout, full_screen=True, mouse_support=True) 26 | 27 | def run (): 28 | data.screen_up_event.set () 29 | 30 | data.application.run () 31 | -------------------------------------------------------------------------------- /screen/screen/console.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tqyaaaaang/Hyper-OS/7fe501e2173425c7d08b5457c08ee8ebf5261ba0/screen/screen/console.py -------------------------------------------------------------------------------- /screen/screen/utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | screen.screen.utils 5 | """ 6 | 7 | 8 | import prompt_toolkit 9 | from prompt_toolkit import document 10 | 11 | 12 | def move_cursor_to_end (buffer): 13 | doc = buffer.document 14 | buffer.set_document (document.Document (doc.text, doc.cursor_position + doc.get_end_of_document_position ())) 15 | 16 | def move_cursor_to_line_start (buffer): 17 | doc = buffer.document 18 | buffer.set_document (document.Document (doc.text, doc.cursor_position + doc.get_start_of_line_position ())) 19 | -------------------------------------------------------------------------------- /screen/screen/windows.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | screen.screen.windows 5 | Window objects 6 | """ 7 | 8 | 9 | import prompt_toolkit 10 | from prompt_toolkit import layout 11 | from prompt_toolkit.layout import containers 12 | from prompt_toolkit import widgets 13 | 14 | from screen import data 15 | 16 | 17 | def init (): 18 | data.console_window = widgets.TextArea (focus_on_click=True) 19 | data.messages_window = widgets.TextArea (scrollbar=True, focus_on_click=True) 20 | 21 | data.app_windows = [ 22 | containers.VSplit([widgets.Frame (data.console_window, title='console')], key_bindings=data.key_binding), 23 | containers.VSplit([widgets.Frame (data.messages_window, title='messages')], key_bindings=data.message_window_key_binding) 24 | ] 25 | -------------------------------------------------------------------------------- /src/apic/interrupt_affinity.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * apic/interrupt_affinity.cpp 3 | * Affinity of interrupts 4 | */ 5 | 6 | #include "interrupt_affinity.h" 7 | #include "../logging/logging.h" 8 | 9 | namespace interrupt_affinity_namespace 10 | { 11 | std::map < interrupt_id_t, int > interrupt_affinity; 12 | const int DEFAULT = 0; 13 | std::mutex mut; 14 | } 15 | 16 | using namespace interrupt_affinity_namespace; 17 | 18 | void init_interrupt_affinity () 19 | { 20 | logging::debug << "Initializing interrupt affinity information" << logging::log_endl; 21 | } 22 | 23 | void set_interrupt_affinity ( interrupt_id_t interrupt_id, int core_id ) 24 | { 25 | std::unique_lock < std::mutex > lock ( mut ); 26 | logging::info << "Setting the affinity of interrupt " << static_cast < int > ( interrupt_id ) << " to CPU core #" << core_id << logging::log_endl; 27 | interrupt_affinity[interrupt_id] = core_id; 28 | } 29 | 30 | int get_interrupt_affinity ( interrupt_id_t interrupt_id ) 31 | { 32 | std::unique_lock < std::mutex > lock ( mut ); 33 | logging::debug << "Trying to get interrupt affinity of id " << static_cast < int > ( interrupt_id ) << logging::log_endl; 34 | std::map < interrupt_id_t, int > ::iterator result = interrupt_affinity.find ( interrupt_id ); 35 | if ( result != interrupt_affinity.end () ) { 36 | logging::debug << "Find result, assigned to CPU core #" << result->second << logging::log_endl; 37 | return result->second; 38 | } else { 39 | logging::debug << "Result not found, assigned to default CPU core #" << DEFAULT << logging::log_endl; 40 | return DEFAULT; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/apic/interrupt_affinity.h: -------------------------------------------------------------------------------- 1 | /** 2 | * apic/interrupt_affinity.h 3 | * Affinity of interrupts 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include "../interrupt/interrupt_id.h" 11 | 12 | namespace interrupt_affinity_namespace 13 | { 14 | extern std::map < interrupt_id_t, int > interrupt_affinity; 15 | extern const int DEFAULT; 16 | extern std::mutex mut; 17 | } 18 | 19 | void init_interrupt_affinity (); 20 | 21 | void set_interrupt_affinity ( interrupt_id_t interrupt_id, int core_id ); 22 | int get_interrupt_affinity ( interrupt_id_t interrupt_id ); 23 | -------------------------------------------------------------------------------- /src/apic/interrupt_queue.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * apic/interrupt_queue.h 3 | * Queue of interrupts 4 | */ 5 | 6 | #include "interrupt_queue.h" 7 | #include "../interrupt/interrupts/interrupt_t.h" 8 | 9 | interrupt_queue_t::interrupt_queue_t () 10 | : time_id ( 0 ) 11 | { 12 | } 13 | 14 | interrupt_queue_t::~interrupt_queue_t () 15 | { 16 | } 17 | 18 | void interrupt_queue_t::push ( interrupt_t * current_interrupt ) 19 | { 20 | ++time_id; 21 | int interrupt_type; 22 | if ( current_interrupt->is_internal_interrupt () ) { 23 | interrupt_type = 0; 24 | } else { 25 | interrupt_type = 1; 26 | } 27 | interrupt_queue.push ( std::make_pair ( std::make_pair ( interrupt_type, std::make_pair ( static_cast < int > ( current_interrupt->get_interrupt_id () ) >> 4, time_id ) ), current_interrupt ) ); 28 | } 29 | 30 | interrupt_t * interrupt_queue_t::front () const 31 | { 32 | return interrupt_queue.top ().second; 33 | } 34 | 35 | void interrupt_queue_t::pop () 36 | { 37 | interrupt_queue.pop (); 38 | } 39 | 40 | bool interrupt_queue_t::empty () const 41 | { 42 | return interrupt_queue.empty (); 43 | } 44 | 45 | void interrupt_queue_t::clear () 46 | { 47 | while ( !empty () ) { 48 | pop (); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/apic/interrupt_queue.h: -------------------------------------------------------------------------------- 1 | /** 2 | * apic/interrupt_queue.h 3 | * Queue of interrupts 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | class interrupt_t; 13 | 14 | class interrupt_queue_t 15 | { 16 | public: 17 | interrupt_queue_t (); 18 | ~interrupt_queue_t (); 19 | 20 | void push ( interrupt_t * current_interrupt ); 21 | interrupt_t * front () const; 22 | void pop (); 23 | 24 | bool empty () const; 25 | void clear (); 26 | 27 | private: 28 | typedef std::pair < std::pair < int, std::pair < int, long long > >, interrupt_t * > queue_element_t; // format: ((type, (priroity, time)), interrupt) 29 | std::priority_queue < queue_element_t, std::vector < queue_element_t >, std::greater < queue_element_t > > interrupt_queue; 30 | 31 | long long time_id; 32 | }; 33 | -------------------------------------------------------------------------------- /src/apic/io_apic.h: -------------------------------------------------------------------------------- 1 | /** 2 | * apic/io_apic.h 3 | * I/O APIC 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "../utils/thread_safe_queue/thread_safe_queue.h" 14 | 15 | class external_interrupt_t; 16 | class status_t; 17 | class motherboard_t; 18 | 19 | /** 20 | * class io_apic 21 | * Each instance of this class simulates an I/O APIC 22 | * and monitor interrupts from a certain external device 23 | */ 24 | class io_apic 25 | { 26 | public: 27 | io_apic (); 28 | io_apic ( motherboard_t *_motherboard ); 29 | ~io_apic (); 30 | 31 | void enable (); 32 | void disable (); 33 | 34 | bool is_enabled () const; 35 | 36 | void set_motherboard ( motherboard_t *_motherboard ); 37 | motherboard_t * get_motherboard () const; 38 | 39 | void interrupt ( external_interrupt_t *current_interrupt ); 40 | 41 | private: 42 | void send_disable_signal (); 43 | 44 | void io_apic_thread_entry ( status_t father_thread_status ); 45 | void io_apic_thread_event_loop (); 46 | 47 | bool do_events ( external_interrupt_t *current_interrupt ); 48 | 49 | motherboard_t *motherboard; // Motherboard 50 | 51 | bool enabled; // is I/O APIC enabled 52 | std::thread io_apic_thread; // I/O APIC daemon thread 53 | 54 | thread_safe_queue < external_interrupt_t * > event_queue; // event queue 55 | }; 56 | 57 | void init_io_apic (); 58 | -------------------------------------------------------------------------------- /src/apic/local_apic.h: -------------------------------------------------------------------------------- 1 | /** 2 | * apic/local_apic.h 3 | * Local APIC 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "interrupt_queue.h" 14 | #include "../utils/thread_safe_queue/thread_safe_queue.h" 15 | 16 | class CPU_core; 17 | class status_t; 18 | class interrupt_t; 19 | 20 | /** 21 | * class local_apic 22 | * Each instance of this class simulates an Local APIC 23 | * and send interrupts to a certain CPU core 24 | */ 25 | class local_apic 26 | { 27 | public: 28 | local_apic ( CPU_core *_core ); 29 | ~local_apic (); 30 | 31 | void enable (); // Enable interrupt 32 | void disable (); // Disable interrupt 33 | 34 | bool is_enabled () const; 35 | 36 | int interrupt ( interrupt_t *current_interrupt, bool blocked = true ); // @return: whether the interrupt is processed 37 | void send_end_of_interrupt ( int return_value ); // send an end_of_interrupt signal 38 | 39 | void try_process_interrupt (); // check if there is a interrupt waiting and give up current CPU to process it if yes 40 | 41 | private: 42 | int wait_interrupt_return ( interrupt_t *current_interrupt ); 43 | 44 | void send_process_interrupt_signal (); // send a signal to LAPIC to try to process a new interrupt 45 | void send_disable_signal (); // send disable LAPIC signal 46 | 47 | void lapic_thread_entry ( status_t father_thread_status ); // LAPIC daemon thread entry 48 | void lapic_thread_event_loop (); 49 | 50 | bool do_events ( interrupt_t *current_interrupt ); // return true to stop the LAPIC thread 51 | void schedule ( bool internal_only ); // choose a new interrupt to run 52 | void run_isr ( interrupt_t *current_interrupt ); // run ISR of an interrupt 53 | 54 | CPU_core *core; // CPU core in which it affliate 55 | bool enabled; // is LAPIC enabled 56 | std::thread lapic_thread; // LAPIC daemon thread 57 | 58 | std::stack < std::pair < interrupt_t *, std::thread > > isr_stack; // stack of current running ISRs 59 | interrupt_queue_t interrupt_queue; // interrupts waiting 60 | thread_safe_queue < interrupt_t * > event_queue; // event queue 61 | }; 62 | -------------------------------------------------------------------------------- /src/context/context.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * context/context.h 3 | * running context of cpu 4 | */ 5 | #include "context.h" 6 | 7 | void context_t::set_page_table(page_table *pg) 8 | { 9 | this->pg = pg; 10 | } 11 | 12 | page_table* context_t::get_page_table() const 13 | { 14 | return this->pg; 15 | } 16 | 17 | void context_t::free_all_pages() 18 | { 19 | for (size_t i = 0; i < VPAGE_NUM; i++) 20 | pg->free_pte(i); 21 | } 22 | -------------------------------------------------------------------------------- /src/context/context.h: -------------------------------------------------------------------------------- 1 | /** 2 | * context/context.h 3 | * running context of cpu 4 | */ 5 | #pragma once 6 | #include "../mm/page_table.h" 7 | 8 | class context_t { 9 | public: 10 | 11 | void set_page_table( page_table *pg ); 12 | page_table * get_page_table() const; 13 | 14 | void free_all_pages(); 15 | size_t esp; 16 | size_t brk; 17 | 18 | private: 19 | page_table *pg; 20 | }; 21 | -------------------------------------------------------------------------------- /src/core/core.h: -------------------------------------------------------------------------------- 1 | /** 2 | * core/core.h 3 | * CPU Core 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include "../mmu/mmu.h" 10 | #include "../apic/local_apic.h" 11 | #include "../context/context.h" 12 | #include "../process/process_t.h" 13 | #include "../process/process.h" 14 | 15 | class CPU_mmu; 16 | 17 | /** 18 | * class CPU_core 19 | * Each instance of this class is an unique cpu core 20 | * member function start () 21 | */ 22 | class CPU_core 23 | { 24 | public: 25 | CPU_core (); 26 | ~CPU_core (); 27 | 28 | /** 29 | * CPU_core.set_enabled 30 | * set the CPU status 31 | */ 32 | void set_enabled ( bool status ); 33 | 34 | /** 35 | * CPU_core.enable 36 | * enable the CPU 37 | */ 38 | void enable (); 39 | 40 | /** 41 | * CPU_core.disable 42 | * disable the CPU 43 | */ 44 | void disable (); 45 | 46 | /** 47 | * CPU_core.is_enabled 48 | * check if the core is enabled 49 | */ 50 | bool is_enabled () const; 51 | 52 | /** 53 | * CPU_core.set_interrupt_enabled 54 | * set the CPU interrupt status 55 | */ 56 | void set_interrupt_enabled ( bool status ); 57 | 58 | /** 59 | * CPU_core.enable_interrupt 60 | * enable interrupt 61 | */ 62 | void enable_interrupt (); 63 | 64 | /** 65 | * CPU_core.disable_interrupt 66 | * disable interrupt 67 | */ 68 | void disable_interrupt (); 69 | 70 | /** 71 | * CPU_core.is_interrupt_enabled 72 | * check if the interrupt is enabled 73 | */ 74 | bool is_interrupt_enabled () const; 75 | 76 | /** 77 | * CPU_core.inc_interrupt_depth () 78 | * increase the depth of the interrupt stack 79 | */ 80 | void inc_interrupt_depth (); 81 | 82 | /** 83 | * CPU_core.dec_interrupt_depth () 84 | * decrease the depth of the interrupt stack 85 | */ 86 | void dec_interrupt_depth (); 87 | 88 | /** 89 | * CPU_core.get_interrupt_depth () 90 | * get the depth of the interrupt stack 91 | */ 92 | int get_interrupt_depth () const; 93 | 94 | /** 95 | * CPU_core.set_interrupt_flag 96 | * Set interrupt waiting flag 97 | * Process get mark and yeild in tail-check 98 | */ 99 | void set_interrupt_waiting_flag(); 100 | 101 | /** 102 | * CPU_core.unset_interrupt_flag 103 | * Unet interrupt waiting flag 104 | */ 105 | void unset_interrupt_waiting_flag(); 106 | 107 | /** 108 | * CPU_core.get_interrupt_flag 109 | * Get interrupt waiting flag 110 | */ 111 | int get_interrupt_waiting_flag() const; 112 | 113 | 114 | void set_core_id ( int id ); // Set the CPU core id 115 | int get_core_id () const; // Get the CPU core id 116 | 117 | local_apic & get_lapic (); // Get the Loacl APIC of this core 118 | 119 | void acquire (); // Acquire the ownership of this CPU 120 | void release (); // Release the ownership of this CPU 121 | 122 | std::mutex & get_cpu_lock (); // Get CPU lock mutex 123 | 124 | void set_context(const context_t &context); 125 | context_t get_context() const; 126 | 127 | void set_current(process_t *current); 128 | process_t* get_current() const; 129 | 130 | void vm_read(char *buf, size_t la_begin, size_t la_end); 131 | void vm_write(size_t addr, const char *buf_begin, const char *buf_end); 132 | 133 | private: 134 | bool enabled_flag; 135 | bool interrupt_enabled_flag; 136 | bool _preserved_interrupt_enabled_flag; 137 | int core_id; 138 | 139 | local_apic lapic; 140 | 141 | int interrupt_depth; 142 | 143 | std::mutex cpu_lock; 144 | 145 | CPU_mmu mmu; 146 | context_t context; 147 | process_t *current; 148 | 149 | int interrupt_waiting_flag; 150 | mutable std::mutex interrupt_waiting_flag_mutex; 151 | }; 152 | -------------------------------------------------------------------------------- /src/core/cpus.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * core/cpus.cpp 3 | * CPU Cores 4 | */ 5 | 6 | #include "cpus.h" 7 | #include "../logging/logging.h" 8 | #include 9 | 10 | CPU_core *cores; // List of CPU cores 11 | 12 | static int core_num = 0; 13 | 14 | int get_core_num () 15 | { 16 | assert(core_num != 0); 17 | return core_num; 18 | } 19 | 20 | void init_cpus ( int n ) 21 | { 22 | logging::info << "Initializing " << n << " CPU(s)" << logging::log_endl; 23 | core_num = n; 24 | cores = new CPU_core[n]; 25 | for ( int i = 0; i < n; ++i ){ 26 | logging::debug << "Initializing CPU #" << i << logging::log_endl; 27 | cores[i].set_core_id ( i ); 28 | cores[i].enable (); 29 | cores[i].enable_interrupt (); 30 | } 31 | } 32 | 33 | void destroy_cpus () 34 | { 35 | logging::debug << "Destorying CPUs" << logging::log_endl; 36 | delete[] cores; 37 | } 38 | -------------------------------------------------------------------------------- /src/core/cpus.h: -------------------------------------------------------------------------------- 1 | /** 2 | * core/cpus.h 3 | * CPU Cores 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "core.h" 9 | 10 | extern CPU_core *cores; // List of CPU cores 11 | 12 | /** 13 | * get_core_num () 14 | * @return: number of cores 15 | */ 16 | 17 | int get_core_num(); 18 | 19 | /** 20 | * init_cpus ( int n ) 21 | * Arguments 22 | * @n: the number of cpus 23 | */ 24 | void init_cpus ( int n ); 25 | 26 | /** 27 | destroy_cpus () 28 | */ 29 | void destroy_cpus (); 30 | -------------------------------------------------------------------------------- /src/destroy/destroy.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * destroy/destroy.h 3 | * Call destructor 4 | */ 5 | 6 | #include "destroy.h" 7 | #include "../mm/pmm.h" 8 | #include "../core/cpus.h" 9 | #include "../motherboard/motherboard.h" 10 | #include "../logging/logging.h" 11 | #include "../message/message.h" 12 | #include "../schedule/schedule.h" 13 | #include "../program/program_manager.h" 14 | #include "../../dev/device.h" 15 | 16 | void destroy () 17 | { 18 | destroy_pmm (); 19 | destroy_schedule (); 20 | 21 | destroy_devices (); 22 | destroy_motherboards (); 23 | destroy_cpus (); 24 | 25 | destroy_message (); 26 | 27 | destroy_logger (); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/destroy/destroy.h: -------------------------------------------------------------------------------- 1 | /** 2 | * destroy/destroy.h 3 | * Call destructor 4 | */ 5 | 6 | #pragma once 7 | 8 | void destroy (); 9 | -------------------------------------------------------------------------------- /src/env/env.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * env.cpp 3 | * Environment Variables 4 | */ 5 | 6 | #include "env.h" 7 | #include 8 | 9 | // CPU Information 10 | const int CPU_CORES = 1; // Number of CPU cores 11 | 12 | // Memory information 13 | const size_t MEMORY_SIZE = ( size_t ) 1 << 30; // The size of the physical memory 14 | 15 | // Motherboard information 16 | const int MOTHERBOARD_NUM = 1; // The number of motherboards 17 | 18 | // Logging 19 | const char *LOG_FILE_NAME = "hos.log"; // File name to write log, NULL if write to stdout 20 | 21 | const int LOG_LEVEL = LOGGING_LEVEL::DEBUG; // Logging level to be used 22 | 23 | // Message service 24 | const char *MESSAGE_FILE_NAME = "msg.log"; // File name to write messages, write to stdout if is NULL and IO_DEVICE is 0 25 | 26 | // Unittest 27 | const bool TEST = false; 28 | 29 | // I/O Device 30 | extern const int IO_DEVICE = 1; // I/O Device method, 0 if directly to terminal, 1 if to module screen 31 | 32 | // Tick interval of clock device ( ms ) 33 | const int CLOCK_INTERVAL = 20; 34 | -------------------------------------------------------------------------------- /src/env/env.h: -------------------------------------------------------------------------------- 1 | /** 2 | * env.h 3 | * Environment Variables 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | 11 | // CPU Information 12 | extern const int CPU_CORES; // Number of CPU cores 13 | 14 | // Memory information 15 | extern const size_t MEMORY_SIZE; // The size of the physical memory 16 | 17 | // Motherboard information 18 | extern const int MOTHERBOARD_NUM; // The number of motherboards 19 | 20 | // Logging 21 | extern const char *LOG_FILE_NAME; // File name to write log, NULL if write to stdout 22 | 23 | enum LOGGING_LEVEL // Logging levels 24 | { 25 | NONE, 26 | CRITICAL, 27 | ERROR, 28 | WARNING, 29 | INFO, 30 | DEBUG 31 | }; 32 | extern const int LOG_LEVEL; // Logging level to be used 33 | 34 | // Message service 35 | extern const char *MESSAGE_FILE_NAME; // File name to write messages, write to stdout if is NULL and IO_DEVICE is 0 36 | 37 | // Unittest 38 | extern const bool TEST; // test = true <=> run unit test 39 | 40 | // I/O Device 41 | extern const int IO_DEVICE; // I/O Device method 42 | 43 | // Tick interval of clock device ( ms ) 44 | extern const int CLOCK_INTERVAL; 45 | -------------------------------------------------------------------------------- /src/init/init.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * init/init.cpp 3 | * Initialize the system 4 | */ 5 | 6 | #include "init.h" 7 | 8 | #include "../core/cpus.h" 9 | #include "../status/status.h" 10 | #include "../env/env.h" 11 | #include "../logging/logging.h" 12 | #include "../message/message.h" 13 | #include "../motherboard/motherboard.h" 14 | #include "../apic/io_apic.h" 15 | #include "../mm/pmm.h" 16 | #include "../io/io.h" 17 | #include "../../dev/device.h" 18 | #include "../schedule/schedule.h" 19 | #include "../process/process.h" 20 | #include "../program/program_manager.h" 21 | 22 | void init () 23 | { 24 | init_logger (); 25 | 26 | init_message (); 27 | 28 | init_status_phase_1 (); 29 | 30 | init_cpus ( CPU_CORES ); 31 | init_status_phase_2 (); 32 | init_motherboards ( MOTHERBOARD_NUM ); 33 | init_io_apic (); 34 | 35 | init_io (); 36 | 37 | init_devices (); 38 | 39 | init_pmm ( ); 40 | 41 | init_schedule (); 42 | 43 | init_program_manager( ); 44 | 45 | init_proc(); 46 | } 47 | -------------------------------------------------------------------------------- /src/init/init.h: -------------------------------------------------------------------------------- 1 | /** 2 | * init/init.h 3 | * Initialize the system 4 | */ 5 | 6 | #pragma once 7 | 8 | void init (); 9 | -------------------------------------------------------------------------------- /src/interrupt/interrupt.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/interrupt.h 3 | * Interrupt entry 4 | */ 5 | 6 | #include "interrupt.h" 7 | 8 | #include "interrupts/interrupt_t.h" 9 | #include "../status/status.h" 10 | #include "../core/core.h" 11 | #include "../apic/local_apic.h" 12 | 13 | int interrupt ( interrupt_t * current_interrupt ) 14 | { 15 | return status.get_core ()->get_lapic ().interrupt ( current_interrupt ); 16 | } 17 | 18 | void check_interrupt () 19 | { 20 | status.get_core ()->get_lapic ().try_process_interrupt (); 21 | } 22 | -------------------------------------------------------------------------------- /src/interrupt/interrupt.h: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/interrupt.h 3 | * Interrupt entry 4 | */ 5 | 6 | #pragma once 7 | 8 | class interrupt_t; 9 | 10 | int interrupt ( interrupt_t *current_interrupt ); 11 | 12 | void check_interrupt (); 13 | -------------------------------------------------------------------------------- /src/interrupt/interrupt_id.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/interrupt_id.cpp 3 | * Interrupt IDs 4 | */ 5 | 6 | #include "interrupt_id.h" 7 | -------------------------------------------------------------------------------- /src/interrupt/interrupt_id.h: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/interrupt_id.h 3 | * Interrupt IDs 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | 10 | enum class interrupt_id_t 11 | { 12 | DIVIDE = 0, 13 | DEBUG, 14 | NMI, 15 | BREAKPOINT, 16 | OFLOW, 17 | BOUND, 18 | ILLEGAL_OPCODE, 19 | DEVICE, 20 | DOUBLE_FALUT, 21 | COPROC, 22 | TSS, 23 | SEGNP, 24 | STACK, 25 | GPFLT, 26 | PGFLT, 27 | RESERVED_15, 28 | FPERR, 29 | ALIGN, 30 | MCHK, 31 | SIMDERR, 32 | 33 | DOUBLE_INTERNAL_TEST = 30, 34 | INTERNAL_TEST = 31, 35 | 36 | CLOCK_INTERRUPT = 32, 37 | KEYBOARD_INTERRUPT = 33, 38 | 39 | SYSCALL = 80, 40 | 41 | END_OF_INTERRUPT = -1, 42 | DISABLE_LAPIC = -2, 43 | LAPIC_PROCESS_INTERRUPT = -3, 44 | 45 | IO_APIC_END_OF_INTERRUPT = -100, 46 | DISABLE_IO_APIC = -101 47 | }; 48 | -------------------------------------------------------------------------------- /src/interrupt/interrupts/clock_interrupt.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/interrupts/clock_interrupt.h 3 | * Interrupt classes 4 | * Clock interrupt 5 | */ 6 | 7 | #include "clock_interrupt.h" 8 | #include "../../status/status.h" 9 | #include "../../core/core.h" 10 | #include "../../logging/logging.h" 11 | #include "../../core/cpus.h" 12 | 13 | #include 14 | #include 15 | 16 | clock_interrupt::clock_interrupt () 17 | : external_interrupt_t ( interrupt_id_t::CLOCK_INTERRUPT ) 18 | { 19 | } 20 | 21 | void clock_interrupt::process () 22 | { 23 | logging::debug << "CPU #" << status.get_core ()->get_core_id () << " received a clock tick" << logging::log_endl; 24 | 25 | size_t id = status.get_core()->get_core_id(); 26 | process_t *current = cores[id].get_current(); 27 | if (current != nullptr) { 28 | if (current->tick()) { 29 | current->set_resched(true); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/interrupt/interrupts/clock_interrupt.h: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/interrupts/clock_interrupt.h 3 | * Interrupt classes 4 | * Clock interrupt 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "external_interrupt_t.h" 10 | 11 | class clock_interrupt : public external_interrupt_t 12 | { 13 | public: 14 | clock_interrupt (); 15 | 16 | virtual void process (); 17 | }; 18 | -------------------------------------------------------------------------------- /src/interrupt/interrupts/disable_io_apic.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/interrupts/disable_io_apic.cpp 3 | * Interrupt classes 4 | * Disable the I/O APIC 5 | */ 6 | 7 | #include "disable_io_apic.h" 8 | 9 | disable_io_apic::disable_io_apic () 10 | : io_apic_signal_t ( interrupt_id_t::DISABLE_IO_APIC ) 11 | { 12 | } 13 | 14 | void disable_io_apic::process () 15 | { 16 | } 17 | -------------------------------------------------------------------------------- /src/interrupt/interrupts/disable_io_apic.h: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/interrupts/disable_io_apic.h 3 | * Interrupt classes 4 | * Disable the I/O APIC 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "io_apic_signal_t.h" 10 | 11 | class disable_io_apic : public io_apic_signal_t 12 | { 13 | public: 14 | disable_io_apic (); 15 | 16 | virtual void process (); 17 | }; 18 | -------------------------------------------------------------------------------- /src/interrupt/interrupts/disable_lapic.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/interrupts/disable_lapic.cpp 3 | * Interrupt classes 4 | * Disable the LAPIC 5 | */ 6 | 7 | #include "disable_lapic.h" 8 | 9 | disable_lapic::disable_lapic () 10 | : lapic_signal_t ( interrupt_id_t::DISABLE_LAPIC ) 11 | { 12 | } 13 | 14 | void disable_lapic::process () 15 | { 16 | } 17 | -------------------------------------------------------------------------------- /src/interrupt/interrupts/disable_lapic.h: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/interrupts/disable_lapic.h 3 | * Interrupt classes 4 | * Disable the LAPIC 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "lapic_signal_t.h" 10 | 11 | class disable_lapic : public lapic_signal_t 12 | { 13 | public: 14 | disable_lapic (); 15 | 16 | virtual void process (); 17 | }; 18 | -------------------------------------------------------------------------------- /src/interrupt/interrupts/double_internal_test.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/interrupts/double_internal_test.cpp 3 | * Interrupt classes 4 | * Double internal test interrupt 5 | */ 6 | 7 | #include "double_internal_test.h" 8 | 9 | #include "../../logging/logging.h" 10 | #include "../interrupt.h" 11 | #include "internal_test.h" 12 | 13 | double_internal_test_interrupt::double_internal_test_interrupt () 14 | : internal_interrupt_t ( interrupt_id_t::DOUBLE_INTERNAL_TEST ) 15 | { 16 | } 17 | 18 | void double_internal_test_interrupt::process () 19 | { 20 | logging::info << "ISR of DOUBLE INTERNAL TEST interrupt started" << logging::log_endl; 21 | interrupt ( new internal_test_interrupt () ); 22 | logging::info << "ISR of DOUBLE INTERNAL TEST interrupt finished" << logging::log_endl; 23 | } 24 | -------------------------------------------------------------------------------- /src/interrupt/interrupts/double_internal_test.h: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/interrupts/double_internal_test.h 3 | * Interrupt classes 4 | * Double internal test interrupt 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "internal_interrupt_t.h" 10 | 11 | class double_internal_test_interrupt : public internal_interrupt_t 12 | { 13 | public: 14 | double_internal_test_interrupt (); 15 | 16 | virtual void process (); 17 | }; 18 | -------------------------------------------------------------------------------- /src/interrupt/interrupts/end_of_interrupt.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/interrupts/end_of_interrupt.cpp 3 | * Interrupt classes 4 | * End of Interrupt signal to Local APIC 5 | */ 6 | 7 | #include "end_of_interrupt.h" 8 | 9 | end_of_interrupt::end_of_interrupt ( int _return_value ) 10 | : lapic_signal_t ( interrupt_id_t::END_OF_INTERRUPT ) 11 | , return_value ( _return_value ) 12 | { 13 | } 14 | 15 | void end_of_interrupt::set_return_value ( int _return_value ) 16 | { 17 | return_value = _return_value; 18 | } 19 | 20 | int end_of_interrupt::get_return_value () const 21 | { 22 | return return_value; 23 | } 24 | 25 | void end_of_interrupt::process () 26 | { 27 | } 28 | -------------------------------------------------------------------------------- /src/interrupt/interrupts/end_of_interrupt.h: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/interrupts/end_of_interrupt.h 3 | * Interrupt classes 4 | * End of Interrupt signal to Local APIC 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "lapic_signal_t.h" 10 | 11 | class end_of_interrupt : public lapic_signal_t 12 | { 13 | public: 14 | end_of_interrupt ( int _return_value ); 15 | 16 | void set_return_value ( int _return_value ); 17 | int get_return_value () const; 18 | 19 | virtual void process (); 20 | 21 | private: 22 | int return_value; 23 | }; 24 | -------------------------------------------------------------------------------- /src/interrupt/interrupts/external_interrupt_t.cpp: -------------------------------------------------------------------------------- 1 | #include "external_interrupt_t.h" 2 | /** 3 | * interrupt/interrupts/external_interrupt_t.cpp 4 | * Interrupt classes 5 | * Abstract base class external_interrupt_t 6 | * External interrupts 7 | */ 8 | 9 | #include "external_interrupt_t.h" 10 | 11 | external_interrupt_t::external_interrupt_t ( interrupt_id_t interrupt_id ) 12 | : interrupt_t ( interrupt_id ) 13 | { 14 | } 15 | 16 | bool external_interrupt_t::is_external_interrupt () const 17 | { 18 | return true; 19 | } 20 | -------------------------------------------------------------------------------- /src/interrupt/interrupts/external_interrupt_t.h: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/interrupts/external_interrupt_t.h 3 | * Interrupt classes 4 | * Abstract base class external_interrupt_t 5 | * External interrupts 6 | */ 7 | 8 | #pragma once 9 | 10 | #include "interrupt_t.h" 11 | 12 | class external_interrupt_t : public interrupt_t 13 | { 14 | public: 15 | external_interrupt_t ( interrupt_id_t interrupt_id ); 16 | 17 | virtual bool is_external_interrupt () const; 18 | }; 19 | -------------------------------------------------------------------------------- /src/interrupt/interrupts/internal_interrupt_t.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/interrupts/internal_interrupt_t.cpp 3 | * Interrupt classes 4 | * Abstract base class internal_interrupt_t 5 | * Internal interrupts 6 | */ 7 | 8 | #include "internal_interrupt_t.h" 9 | 10 | internal_interrupt_t::internal_interrupt_t ( interrupt_id_t interrupt_id ) 11 | : interrupt_t ( interrupt_id ) 12 | { 13 | } 14 | 15 | bool internal_interrupt_t::is_internal_interrupt () const 16 | { 17 | return true; 18 | } 19 | -------------------------------------------------------------------------------- /src/interrupt/interrupts/internal_interrupt_t.h: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/interrupts/internal_interrupt_t.h 3 | * Interrupt classes 4 | * Abstract base class internal_interrupt_t 5 | * Internal interrupts 6 | */ 7 | 8 | #pragma once 9 | 10 | #include "interrupt_t.h" 11 | 12 | class internal_interrupt_t : public interrupt_t 13 | { 14 | public: 15 | internal_interrupt_t ( interrupt_id_t interrupt_id ); 16 | 17 | virtual bool is_internal_interrupt () const; 18 | }; 19 | -------------------------------------------------------------------------------- /src/interrupt/interrupts/internal_test.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/interrupts/internal_test.cpp 3 | * Interrupt classes 4 | * Internal test interrupt 5 | */ 6 | 7 | #include "internal_test.h" 8 | 9 | #include "../../logging/logging.h" 10 | 11 | internal_test_interrupt::internal_test_interrupt () 12 | : internal_interrupt_t ( interrupt_id_t::INTERNAL_TEST ) 13 | { 14 | } 15 | 16 | void internal_test_interrupt::process () 17 | { 18 | logging::info << "Running ISR of INTERNAL TEST interrupt" << logging::log_endl; 19 | } 20 | -------------------------------------------------------------------------------- /src/interrupt/interrupts/internal_test.h: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/interrupts/internal_test.h 3 | * Interrupt classes 4 | * Internal test interrupt 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "internal_interrupt_t.h" 10 | 11 | class internal_test_interrupt : public internal_interrupt_t 12 | { 13 | public: 14 | internal_test_interrupt (); 15 | 16 | virtual void process (); 17 | }; 18 | -------------------------------------------------------------------------------- /src/interrupt/interrupts/interrupt_t.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/interrupts/interrupt_t.h 3 | * Interrupt classes 4 | * Abstract base class interrupt_t 5 | */ 6 | 7 | #include "interrupt_t.h" 8 | 9 | #include 10 | 11 | interrupt_t::interrupt_t ( interrupt_id_t id ) 12 | : interrupt_id ( id ) 13 | { 14 | } 15 | 16 | interrupt_t::~interrupt_t () 17 | { 18 | } 19 | 20 | void interrupt_t::set_interrupt_id ( interrupt_id_t id ) 21 | { 22 | interrupt_id = id; 23 | } 24 | 25 | interrupt_id_t interrupt_t::get_interrupt_id () const 26 | { 27 | return interrupt_id; 28 | } 29 | 30 | std::promise < int > & interrupt_t::get_return_promise () 31 | { 32 | return return_promise; 33 | } 34 | 35 | bool interrupt_t::is_internal_interrupt () const 36 | { 37 | return false; 38 | } 39 | 40 | bool interrupt_t::is_external_interrupt () const 41 | { 42 | return false; 43 | } 44 | 45 | bool interrupt_t::is_lapic_signal () const 46 | { 47 | return false; 48 | } 49 | 50 | bool interrupt_t::is_io_apic_signal () const 51 | { 52 | return false; 53 | } 54 | 55 | std::string interrupt_t::to_string () 56 | { 57 | std::stringstream string_buf; 58 | string_buf << "id : " << static_cast < int > ( get_interrupt_id () ); 59 | return string_buf.str (); 60 | } 61 | -------------------------------------------------------------------------------- /src/interrupt/interrupts/interrupt_t.h: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/interrupts/interrupt_t.h 3 | * Interrupt classes 4 | * Abstract base class interrupt_t 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "../interrupt_id.h" 10 | #include 11 | #include 12 | 13 | class interrupt_t 14 | { 15 | public: 16 | interrupt_t ( interrupt_id_t id ); 17 | virtual ~interrupt_t (); 18 | 19 | void set_interrupt_id ( interrupt_id_t id ); 20 | interrupt_id_t get_interrupt_id () const; 21 | 22 | std::promise < int > & get_return_promise (); 23 | 24 | virtual bool is_internal_interrupt () const; // check whether the interrupt is an internal CPU exception 25 | virtual bool is_external_interrupt () const; // check whether the interrupt is an external CPU exception 26 | virtual bool is_lapic_signal () const; // check whether the interrupt is a signal to Local APIC 27 | virtual bool is_io_apic_signal () const; // check whether the interrupt is a signal to I/O APIC 28 | 29 | virtual void process () = 0; 30 | 31 | virtual std::string to_string (); 32 | 33 | private: 34 | interrupt_id_t interrupt_id; 35 | 36 | std::promise < int > return_promise; 37 | }; 38 | -------------------------------------------------------------------------------- /src/interrupt/interrupts/intr_pagefault.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * #PF : page fault. 3 | * trigger when: 4 | * - access a page outside memory 5 | * - write a read-only page 6 | * - access a super-user-only page 7 | */ 8 | 9 | #include "intr_pagefault.h" 10 | #include "../interrupt_id.h" 11 | #include "../../mm/page_table.h" 12 | #include "../../process/process_t.h" 13 | #include "../../status/status.h" 14 | #include "../../logging/logging.h" 15 | #include "../../core/core.h" 16 | #include 17 | #include 18 | #include "../../message/message.h" 19 | 20 | using std::string; 21 | 22 | typedef intr_pagefault_t::error_info error_info; 23 | 24 | error_info::error_info() 25 | { 26 | present = write = super = 0; 27 | } 28 | 29 | error_info::error_info(size_t la, bool present, bool write, bool super) 30 | { 31 | this->la = la; 32 | this->present = present; 33 | this->write = write; 34 | this->super = super; 35 | } 36 | 37 | error_info::error_info(size_t la, int info) 38 | { 39 | present = write = super = false; 40 | this->la = la; 41 | if (info & intr_pagefault_t::E_PRESENT) 42 | present = true; 43 | if (info & intr_pagefault_t::E_WRITE) 44 | write = true; 45 | if (info & intr_pagefault_t::E_SUPER) 46 | super = true; 47 | } 48 | 49 | string error_info::to_string() 50 | { 51 | string str; 52 | str += present ? string("P") : string("-"); 53 | str += write ? string("W") : string("-"); 54 | str += super ? string("S") : string("-"); 55 | return str; 56 | } 57 | 58 | intr_pagefault_t::intr_pagefault_t(const error_info &info) 59 | : internal_interrupt_t ( interrupt_id_t::PGFLT ) 60 | { 61 | this->info = info; 62 | } 63 | 64 | void intr_pagefault_t::process() 65 | { 66 | logging::info << "ISR of #PF started : " << info.super << " " << info.write << " " << info.present << logging::log_endl; 67 | if (info.super || info.write) { 68 | assert(false); 69 | } else if (info.present) { 70 | process_t *proc = status.get_core()->get_current(); 71 | pte_t *pte = proc->get_context().get_page_table() 72 | ->get_pte(info.la); 73 | message::memory(message::wrap_core_info("kern ISR(#PF)")) 74 | << "swap-in or create page for linear address " 75 | << info.la << ", page " 76 | << info.la / PAGE_SIZE << " is now in physical page frame [" 77 | << pte->paddr << ", " << pte->paddr + PAGE_SIZE << ")" 78 | << message::msg_endl; 79 | pte->user = true; 80 | pte->write = true; 81 | assert(pte != nullptr); 82 | } else { 83 | assert(false); 84 | } 85 | logging::info << "ISR of #PF finished" << logging::log_endl; 86 | } 87 | 88 | string intr_pagefault_t::to_string() 89 | { 90 | return "#PF : " + info.to_string(); 91 | } 92 | 93 | -------------------------------------------------------------------------------- /src/interrupt/interrupts/intr_pagefault.h: -------------------------------------------------------------------------------- 1 | /* 2 | * #PF : page fault. 3 | * trigger when: 4 | * - access a page outside memory 5 | * - write a read-only page 6 | * - access a super-user-only page 7 | */ 8 | 9 | #pragma once 10 | 11 | #include "internal_interrupt_t.h" 12 | 13 | class intr_pagefault_t : public internal_interrupt_t { 14 | public: 15 | 16 | struct error_info { 17 | size_t la; 18 | bool present; 19 | bool write; 20 | bool super; 21 | error_info(); 22 | error_info(size_t, bool, bool, bool); 23 | error_info(size_t, int); 24 | std::string to_string(); 25 | }; 26 | 27 | intr_pagefault_t(const error_info&); 28 | virtual void process(); 29 | virtual std::string to_string(); 30 | 31 | static const int E_PRESENT = 1; 32 | static const int E_WRITE = 2; 33 | static const int E_SUPER = 4; 34 | 35 | private: 36 | 37 | error_info info; 38 | }; 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/interrupt/interrupts/io_apic_end_of_interrupt.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/interrupts/io_apic_end_of_interrupt.cpp 3 | * Interrupt classes 4 | * End of Interrupt signal to I/O APIC 5 | */ 6 | 7 | #include "io_apic_end_of_interrupt.h" 8 | #include "../interrupt_id.h" 9 | 10 | io_apic_end_of_interrupt::io_apic_end_of_interrupt ( int _return_value ) 11 | : io_apic_signal_t ( interrupt_id_t::IO_APIC_END_OF_INTERRUPT ) 12 | , return_value ( _return_value ) 13 | { 14 | } 15 | 16 | void io_apic_end_of_interrupt::set_return_value ( int _return_value ) 17 | { 18 | return_value = _return_value; 19 | } 20 | 21 | int io_apic_end_of_interrupt::get_return_value () const 22 | { 23 | return return_value; 24 | } 25 | 26 | void io_apic_end_of_interrupt::process () 27 | { 28 | } 29 | -------------------------------------------------------------------------------- /src/interrupt/interrupts/io_apic_end_of_interrupt.h: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/interrupts/io_apic_end_of_interrupt.h 3 | * Interrupt classes 4 | * End of Interrupt signal to I/O APIC 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "io_apic_signal_t.h" 10 | 11 | class io_apic_end_of_interrupt : public io_apic_signal_t 12 | { 13 | public: 14 | io_apic_end_of_interrupt ( int _return_value ); 15 | 16 | void set_return_value ( int _return_value ); 17 | int get_return_value () const; 18 | 19 | virtual void process (); 20 | 21 | private: 22 | external_interrupt_t * current_interrupt; 23 | int return_value; 24 | }; 25 | -------------------------------------------------------------------------------- /src/interrupt/interrupts/io_apic_signal_t.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/interrupts/io_apic_signal_t.cpp 3 | * Interrupt classes 4 | * Abstract base class io_apic_signal_t 5 | * I/O APIC signals 6 | */ 7 | 8 | #include "io_apic_signal_t.h" 9 | 10 | io_apic_signal_t::io_apic_signal_t ( interrupt_id_t interrupt_id ) 11 | : external_interrupt_t ( interrupt_id ) 12 | { 13 | } 14 | 15 | bool io_apic_signal_t::is_io_apic_signal () const 16 | { 17 | return true; 18 | } 19 | -------------------------------------------------------------------------------- /src/interrupt/interrupts/io_apic_signal_t.h: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/interrupts/io_apic_signal_t.h 3 | * Interrupt classes 4 | * Abstract base class io_apic_signal_t 5 | * I/O APIC signals 6 | */ 7 | 8 | #pragma once 9 | 10 | #include "external_interrupt_t.h" 11 | 12 | class io_apic_signal_t : public external_interrupt_t 13 | { 14 | public: 15 | io_apic_signal_t ( interrupt_id_t interrupt_id ); 16 | 17 | virtual bool is_io_apic_signal () const; 18 | }; 19 | -------------------------------------------------------------------------------- /src/interrupt/interrupts/keyboard_interrupt.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/interrupts/keyboard_interrupt.cpp 3 | * Interrupt classes 4 | * Keyboard interrupt 5 | */ 6 | 7 | #include "keyboard_interrupt.h" 8 | #include "../../env/env.h" 9 | #include "../../logging/logging.h" 10 | #include "../../schedule/signal.h" 11 | #include "../../io/special_keys.h" 12 | #include "../../io/stdio.h" 13 | 14 | keyboard_interrupt::keyboard_interrupt ( std::string _data ) 15 | : external_interrupt_t ( interrupt_id_t::KEYBOARD_INTERRUPT ) 16 | , data ( _data ) 17 | { 18 | } 19 | 20 | void keyboard_interrupt::process () 21 | { 22 | if ( !IO_DEVICE ) { 23 | logging::error << "Process keyboard interrupt with I/O Device directly connect to terminal" << logging::log_endl; 24 | return; 25 | } 26 | 27 | if ( data.size () == 1 ) { 28 | signal_data ( data[0] ); 29 | } else { 30 | special_keys current_key = get_key_id ( data ); 31 | int handle_flag = handle_special_key ( current_key ); 32 | if ( handle_flag == -2 ) { 33 | signal_data ( -static_cast < int > ( current_key ) ); 34 | } else if ( handle_flag >= 0 ) { 35 | signal_data ( handle_flag ); 36 | } 37 | } 38 | } 39 | 40 | void keyboard_interrupt::signal_data ( int data ) 41 | { 42 | logging::debug << "Sending KEYBOARD signal with data " << data << " to process" << logging::log_endl; 43 | receive_keyboard ( data ); 44 | } 45 | -------------------------------------------------------------------------------- /src/interrupt/interrupts/keyboard_interrupt.h: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/interrupts/keyboard_interrupt.h 3 | * Interrupt classes 4 | * Keyboard interrupt 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "external_interrupt_t.h" 10 | 11 | class keyboard_interrupt : public external_interrupt_t 12 | { 13 | public: 14 | keyboard_interrupt ( std::string _data ); 15 | 16 | virtual void process (); 17 | 18 | private: 19 | void signal_data ( int data ); 20 | 21 | std::string data; 22 | }; 23 | -------------------------------------------------------------------------------- /src/interrupt/interrupts/lapic_process_interrupt_signal.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/interrupts/lapic_process_interrupt_signal.cpp 3 | * Interrupt classes 4 | * Signal to let Local APIC send a new interrupt 5 | */ 6 | 7 | #include "lapic_process_interrupt_signal.h" 8 | 9 | lapic_process_interrupt_signal::lapic_process_interrupt_signal () 10 | : lapic_signal_t ( interrupt_id_t::LAPIC_PROCESS_INTERRUPT ) 11 | { 12 | } 13 | 14 | void lapic_process_interrupt_signal::process () 15 | { 16 | } 17 | -------------------------------------------------------------------------------- /src/interrupt/interrupts/lapic_process_interrupt_signal.h: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/interrupts/lapic_process_interrupt_signal.h 3 | * Interrupt classes 4 | * Signal to let Local APIC send a new interrupt 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "lapic_signal_t.h" 10 | 11 | class lapic_process_interrupt_signal : public lapic_signal_t 12 | { 13 | public: 14 | lapic_process_interrupt_signal (); 15 | 16 | virtual void process (); 17 | }; 18 | -------------------------------------------------------------------------------- /src/interrupt/interrupts/lapic_signal_t.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/interrupts/lapic_signal_t.cpp 3 | * Interrupt classes 4 | * Abstract base class lapic_signal_t 5 | * LAPIC signals 6 | */ 7 | 8 | #include "lapic_signal_t.h" 9 | 10 | lapic_signal_t::lapic_signal_t ( interrupt_id_t interrupt_id ) 11 | : interrupt_t ( interrupt_id ) 12 | { 13 | } 14 | 15 | bool lapic_signal_t::is_lapic_signal () const 16 | { 17 | return true; 18 | } 19 | -------------------------------------------------------------------------------- /src/interrupt/interrupts/lapic_signal_t.h: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/interrupts/lapic_signal_t.h 3 | * Interrupt classes 4 | * Abstract base class lapic_signal_t 5 | * LAPIC signals 6 | */ 7 | 8 | #pragma once 9 | 10 | #include "interrupt_t.h" 11 | 12 | class lapic_signal_t : public interrupt_t 13 | { 14 | public: 15 | lapic_signal_t ( interrupt_id_t interrupt_id ); 16 | 17 | virtual bool is_lapic_signal () const; 18 | }; 19 | -------------------------------------------------------------------------------- /src/interrupt/interrupts/syscall_interrupt.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/interrupts/syscall_interrupt.h 3 | * Interrupt classes 4 | * System call interrupt 5 | */ 6 | 7 | #include "syscall_interrupt.h" 8 | #include "../../syscall/syscalls/syscall_t.h" 9 | #include "../../message/message.h" 10 | #include 11 | 12 | static void msg_intr(std::string str) 13 | { 14 | message::interrupt 15 | (message::wrap_core_info("kern syscall")) 16 | << str 17 | << message::msg_endl; 18 | } 19 | 20 | syscall_interrupt::syscall_interrupt ( syscall_t * _syscall ) 21 | : internal_interrupt_t ( interrupt_id_t::SYSCALL ) 22 | , syscall ( _syscall ) 23 | { 24 | } 25 | 26 | void syscall_interrupt::set_syscall ( syscall_t * _syscall ) 27 | { 28 | syscall = _syscall; 29 | } 30 | 31 | syscall_t * syscall_interrupt::get_syscall () 32 | { 33 | return syscall; 34 | } 35 | 36 | void syscall_interrupt::process () 37 | { 38 | msg_intr("Interrupt Service Routine start to serve syscall"); 39 | int return_value = syscall->process (); 40 | syscall->set_return_value ( return_value ); 41 | } 42 | -------------------------------------------------------------------------------- /src/interrupt/interrupts/syscall_interrupt.h: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/interrupts/syscall_interrupt.h 3 | * Interrupt classes 4 | * System call interrupt 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "internal_interrupt_t.h" 10 | 11 | class syscall_t; 12 | 13 | class syscall_interrupt : public internal_interrupt_t 14 | { 15 | public: 16 | syscall_interrupt ( syscall_t *_syscall ); 17 | 18 | void set_syscall ( syscall_t *_syscall ); 19 | syscall_t * get_syscall (); 20 | 21 | virtual void process (); 22 | 23 | private: 24 | syscall_t *syscall; 25 | }; 26 | -------------------------------------------------------------------------------- /src/interrupt/trap.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/trap.cpp 3 | * Interrupt Service Routine 4 | */ 5 | 6 | #include "trap.h" 7 | 8 | #include 9 | #include 10 | #include "interrupts/interrupt_t.h" 11 | #include "../logging/logging.h" 12 | #include "../core/core.h" 13 | #include "../process/process_t.h" 14 | #include "../schedule/schedule.h" 15 | #include "../message/message.h" 16 | #include "../process/idle.h" 17 | #include 18 | 19 | using std::string; 20 | 21 | /** 22 | * schedule process 23 | * RR 24 | */ 25 | static void trap_exit() 26 | { 27 | try { 28 | schedule(status.get_core()->get_core_id()); 29 | process_t *proc = status.get_core()->get_current(); 30 | if ((proc == nullptr || proc->get_prog () == nullptr) && !TEST) { // is nullptr or is idle 31 | logging::debug << "No process need to run, signal idle to run" << logging::log_endl; 32 | signal_idle(); 33 | } 34 | } catch(int id) { 35 | logging::info << "idle exit with id : " << id << logging::log_endl; 36 | } 37 | } 38 | 39 | /** 40 | * trap entry 41 | * apic/lpic call this function when receiveing an interrupt 42 | * running on kernel mode of current process of the interrupt 43 | */ 44 | void interrupt_trap_entry ( status_t thread_status, interrupt_t * current_interrupt ) 45 | { 46 | clock_t c = clock(); 47 | status = thread_status; 48 | 49 | message::interrupt ( message::wrap_core_info ( "kern trap" ) ) << "(switch to kernel mode) trap entry of interrupt : " << current_interrupt->to_string () << message::msg_endl; 50 | logging::debug << "Interrupt Service Routine for CPU #" << status.get_core ()->get_core_id () << " created" << logging::log_endl; 51 | 52 | logging::debug << "CPU #" << status.get_core ()->get_core_id () << " received interrupt : " << current_interrupt->to_string () << logging::log_endl; 53 | 54 | process_t *cur = status.get_core()->get_current(); 55 | 56 | status.get_core()->acquire(); 57 | status.get_core ()->inc_interrupt_depth (); 58 | 59 | if (cur != nullptr) { 60 | //make sure current proc slept successfully 61 | cur->cond_mutex.lock(); 62 | cur->cond_mutex.unlock(); 63 | logging::debug << "CPU #" << status.get_core()->get_core_id() << " trap into kernel mode of " << cur->get_name() << logging::log_endl; 64 | 65 | } else { 66 | logging::debug << "CPU #" << status.get_core()->get_core_id() << " trap into kernel mode of idle" << logging::log_endl; 67 | } 68 | if (cur != nullptr) { 69 | logging::info << "trap of " << cur->get_name() << " " << cur->get_pid() << " start process." << logging::log_endl; 70 | } 71 | current_interrupt->process (); 72 | trap_exit(); 73 | 74 | message::interrupt ( message::wrap_core_info ( "kern trap" ) ) << "(switch to user mode) trap exit, restore context of current process" << message::msg_endl; 75 | 76 | status.get_core ()->dec_interrupt_depth (); 77 | status.get_core()->release (); 78 | 79 | status.get_core ()->get_lapic ().send_end_of_interrupt ( 0 ); 80 | 81 | clock_t e = clock(); 82 | logging::debug << "interrupt : " << 1.0*(e-c)/CLOCKS_PER_SEC << logging::log_endl; 83 | } 84 | 85 | -------------------------------------------------------------------------------- /src/interrupt/trap.h: -------------------------------------------------------------------------------- 1 | /** 2 | * interrupt/trap.h 3 | * Interrupt Service Routine 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "../status/status.h" 9 | 10 | class interrupt_t; 11 | 12 | void interrupt_trap_entry ( status_t thread_status, interrupt_t *current_interrupt ); 13 | -------------------------------------------------------------------------------- /src/io/io.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * io/io.cpp 3 | * Handle input and output 4 | */ 5 | 6 | #include "io.h" 7 | #include "special_keys.h" 8 | #include "../logging/logging.h" 9 | 10 | void init_io () 11 | { 12 | logging::debug << "Initializing I/O service" << logging::log_endl; 13 | 14 | init_special_keys (); 15 | } 16 | -------------------------------------------------------------------------------- /src/io/io.h: -------------------------------------------------------------------------------- 1 | /** 2 | * io/io.h 3 | * Handle input and output 4 | */ 5 | 6 | #pragma once 7 | 8 | void init_io (); 9 | -------------------------------------------------------------------------------- /src/io/special_keys.h: -------------------------------------------------------------------------------- 1 | /** 2 | * io/special_keys.h 3 | * Special keys 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | enum class special_keys 13 | { 14 | ESCAPE = 1, 15 | CTRL_A, 16 | CTRL_B, 17 | CTRL_C, 18 | CTRL_D, 19 | CTRL_E, 20 | CTRL_F, 21 | CTRL_G, 22 | CTRL_H, 23 | CTRL_I, 24 | CTRL_J, 25 | CTRL_K, 26 | CTRL_L, 27 | CTRL_M, 28 | CTRL_N, 29 | CTRL_O, 30 | CTRL_P, 31 | CTRL_Q, 32 | CTRL_R, 33 | CTRL_S, 34 | CTRL_T, 35 | CTRL_U, 36 | CTRL_V, 37 | CTRL_W, 38 | CTRL_X, 39 | CTRL_Y, 40 | CTRL_Z, 41 | F1, 42 | F2, 43 | F3, 44 | F4, 45 | F5, 46 | F6, 47 | F7, 48 | F8, 49 | F9, 50 | F10, 51 | F11, 52 | F12, 53 | F13, 54 | F14, 55 | F15, 56 | F16, 57 | F17, 58 | F18, 59 | F19, 60 | F20, 61 | CTRL_SPACE, 62 | CTRL_BACKSLASH, 63 | CTRL_R_SQR_BRAC, 64 | CTRL_CARET, 65 | CTRL_UNDERSCORE, 66 | BACKSPACE, 67 | UP, 68 | DOWN, 69 | RIGHT, 70 | LEFT, 71 | S_UP, 72 | S_DOWN, 73 | S_RIGHT, 74 | S_LEFT, 75 | HOME, 76 | END, 77 | DELETE, 78 | S_DELETE, 79 | CTRL_DELETE, 80 | PAGE_UP, 81 | PAGE_DOWN, 82 | S_TAB, 83 | TAB, 84 | CTRL_LEFT, 85 | CTRL_RIGHT, 86 | CTRL_UP, 87 | CTRL_DOWN, 88 | INSERT 89 | }; 90 | 91 | extern std::vector < std::string > special_keys_list; 92 | extern std::unordered_map < std::string, special_keys > special_keys_map; 93 | 94 | void init_special_keys (); 95 | 96 | std::string get_key_str ( special_keys key ); 97 | special_keys get_key_id ( std::string str ); 98 | 99 | /** 100 | * @return: whether to pass the key to waiting process 101 | * -2: pass as special_key ( like LEFT and RIGHT ) 102 | * -1: not pass ( like CTRL_C ) 103 | * >=0: pass as character ( like ENTER and BACKSPACE ) 104 | */ 105 | int handle_special_key ( special_keys key ); 106 | -------------------------------------------------------------------------------- /src/io/stdio.cpp: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | #include "special_keys.h" 3 | #include 4 | #include "../../dev/device_list.h" 5 | #include "../../dev/devices/output/output.h" 6 | #include "../logging/logging.h" 7 | #include "../schedule/signal.h" 8 | #include "../message/message.h" 9 | #include 10 | #include 11 | 12 | std::vector buffer; 13 | size_t ptr = 0; 14 | 15 | using device_desc::standard_output; 16 | 17 | static void new_line() 18 | { 19 | logging::debug << "stdio receive new-line" << logging::log_endl; 20 | assert(ptr <= buffer.size()); 21 | while (ptr < buffer.size()) { 22 | standard_output->write(-static_cast(special_keys::RIGHT)); 23 | ptr++; 24 | } 25 | standard_output->write('\n'); 26 | for (int i : buffer) { 27 | logging::debug << "buffer is sending signal : " << i << logging::log_endl; 28 | send_signal(signal_id::KEYBOARD, i); 29 | } 30 | send_signal(signal_id::KEYBOARD, '\n'); 31 | buffer.clear(); 32 | ptr = 0; 33 | } 34 | 35 | static void back_space() 36 | { 37 | logging::debug << "stdio receive back space" << logging::log_endl; 38 | if (ptr > 0) { 39 | standard_output->write('\b'); 40 | ptr--; 41 | for (size_t i = ptr; i+1 != buffer.size(); i++) { 42 | buffer[i] = buffer[i + 1]; 43 | } 44 | buffer.pop_back(); 45 | } else { 46 | logging::debug << "backspace while the cursor is at the beginning of buffer" << logging::log_endl; 47 | } 48 | } 49 | 50 | static void normal_character(int data) 51 | { 52 | standard_output->write(data); 53 | buffer.push_back(0); 54 | for (size_t i = buffer.size() - 1; i != ptr; i--) { 55 | buffer[i] = buffer[i-1]; 56 | } 57 | buffer[ptr++] = data; 58 | } 59 | 60 | void move_left() 61 | { 62 | if (ptr > 0) { 63 | ptr--; 64 | standard_output->write(-static_cast(special_keys::LEFT)); 65 | } 66 | } 67 | 68 | void move_right() 69 | { 70 | if (ptr < buffer.size()) { 71 | ptr++; 72 | standard_output->write(-static_cast(special_keys::RIGHT)); 73 | } 74 | } 75 | 76 | void receive_keyboard(int data) 77 | { 78 | switch(data) { 79 | case -static_cast(special_keys::LEFT): 80 | move_left(); 81 | break; 82 | case -static_cast(special_keys::RIGHT): 83 | move_right(); 84 | break; 85 | case '\n': 86 | new_line(); 87 | break; 88 | case '\b': 89 | back_space(); 90 | break; 91 | default: 92 | normal_character(data); 93 | break; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/io/stdio.h: -------------------------------------------------------------------------------- 1 | /** 2 | * io/stdio.h 3 | * std in/out 4 | */ 5 | #pragma once 6 | 7 | void receive_keyboard(int data); 8 | -------------------------------------------------------------------------------- /src/logging/log_helper.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * logging/log_helper.cpp 3 | * Helper functions for logging 4 | */ 5 | 6 | #include "log_helper.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "../env/env.h" 15 | #include "../status/status.h" 16 | 17 | 18 | 19 | std::string logging::get_time () 20 | { 21 | time_t cur_time = time ( NULL ); 22 | 23 | struct tm * data = localtime ( &cur_time ); 24 | 25 | std::stringstream string_helper; 26 | 27 | string_helper << std::setw ( 4 ) << std::setfill ( '0' ) << data->tm_year + 1900 << "-" 28 | << std::setw ( 2 ) << std::setfill ( '0' ) << data->tm_mon + 1 << "-" 29 | << std::setw ( 2 ) << std::setfill ( '0' ) << data->tm_mday << " " 30 | << std::setw ( 2 ) << std::setfill ( '0' ) << data->tm_hour << ":" 31 | << std::setw ( 2 ) << std::setfill ( '0' ) << data->tm_min << ":" 32 | << std::setw ( 2 ) << std::setfill ( '0' ) << data->tm_sec << std::endl; 33 | std::string result; 34 | getline ( string_helper, result ); 35 | 36 | return result; 37 | } 38 | 39 | std::string logging::get_level ( int level ) 40 | { 41 | std::string result; 42 | switch ( level ) { 43 | case LOGGING_LEVEL::CRITICAL: 44 | result = "CRITICAL"; 45 | break; 46 | case LOGGING_LEVEL::ERROR: 47 | result = "ERROR"; 48 | break; 49 | case LOGGING_LEVEL::WARNING: 50 | result = "WARNING"; 51 | break; 52 | case LOGGING_LEVEL::INFO: 53 | result = "INFO"; 54 | break; 55 | case LOGGING_LEVEL::DEBUG: 56 | result = "DEBUG"; 57 | break; 58 | default: 59 | std::stringstream string_helper; 60 | string_helper << level; 61 | string_helper >> result; 62 | break; 63 | } 64 | std::stringstream string_helper; 65 | string_helper << std::setw ( 7 ) << std::left << result; 66 | getline ( string_helper, result ); 67 | return result; 68 | } 69 | 70 | std::string logging::get_thread () 71 | { 72 | std::stringstream string_helper; 73 | string_helper << std::this_thread::get_id () << " ("; 74 | if ( status.get_name () != "" ) { 75 | string_helper << " " << status.get_name () << " "; 76 | } 77 | string_helper << ")"; 78 | std::string result; 79 | getline ( string_helper, result ); 80 | return result; 81 | } 82 | 83 | std::string logging::get_prefix ( int level ) 84 | { 85 | return get_time () + " : " + get_level ( level ) + " : " + get_thread () + " : "; 86 | } 87 | -------------------------------------------------------------------------------- /src/logging/log_helper.h: -------------------------------------------------------------------------------- 1 | /** 2 | * logging/log_helper.h 3 | * Helper functions for logging 4 | */ 5 | 6 | #include 7 | 8 | namespace logging 9 | { 10 | std::string get_time (); 11 | std::string get_level ( int level ); 12 | std::string get_thread (); 13 | 14 | std::string get_prefix ( int level ); 15 | } 16 | -------------------------------------------------------------------------------- /src/logging/logging.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * logging/logging.cpp 3 | * Logging module 4 | */ 5 | 6 | #include 7 | #include 8 | #include "logging.h" 9 | #include "../env/env.h" 10 | 11 | namespace logging 12 | { 13 | thread_local std::string BUF; 14 | std::ostream *OUT; 15 | std::mutex output_lock; 16 | 17 | logger critical; 18 | logger error; 19 | logger warning; 20 | logger info; 21 | logger debug; 22 | 23 | log_endl_t log_endl; 24 | } 25 | 26 | void logging::add_string ( std::string str ) 27 | { 28 | BUF += str; 29 | } 30 | 31 | std::string logging::get_string () 32 | { 33 | return BUF; 34 | } 35 | 36 | void logging::clear_string () 37 | { 38 | BUF.clear (); 39 | } 40 | 41 | logging::logger::logger () 42 | : level ( 0 ), visible ( false ) 43 | { 44 | } 45 | 46 | logging::logger::logger ( int _level ) 47 | : level ( _level ), visible ( _level <= LOG_LEVEL ) 48 | { 49 | } 50 | 51 | logging::logger::~logger () 52 | { 53 | } 54 | 55 | void init_logger () 56 | { 57 | if ( LOG_FILE_NAME == NULL ) { 58 | logging::OUT = &std::cout; 59 | } else { 60 | logging::OUT = new std::ofstream ( LOG_FILE_NAME ); 61 | } 62 | 63 | logging::critical = logging::logger ( LOGGING_LEVEL::CRITICAL ); 64 | logging::error = logging::logger ( LOGGING_LEVEL::ERROR ); 65 | logging::warning = logging::logger ( LOGGING_LEVEL::WARNING ); 66 | logging::info = logging::logger ( LOGGING_LEVEL::INFO ); 67 | logging::debug = logging::logger ( LOGGING_LEVEL::DEBUG ); 68 | 69 | logging::debug << "Logger initialized" << logging::log_endl; 70 | } 71 | 72 | void destroy_logger () 73 | { 74 | logging::debug << "Logger destroyed" << logging::log_endl; 75 | 76 | if ( LOG_FILE_NAME != NULL && logging::OUT != NULL ) { 77 | delete logging::OUT; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/logging/logging.h: -------------------------------------------------------------------------------- 1 | /** 2 | * logging/logging.h 3 | * Logging module 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "log_helper.h" 14 | 15 | namespace logging 16 | { 17 | extern thread_local std::string BUF; 18 | extern std::ostream *OUT; 19 | extern std::mutex output_lock; 20 | 21 | void add_string ( std::string str ); 22 | std::string get_string (); 23 | void clear_string (); 24 | 25 | /** 26 | * class log_endl_t 27 | * identifier to end a logger line 28 | */ 29 | class log_endl_t 30 | { 31 | 32 | }; 33 | 34 | /** 35 | * class logger 36 | * can be used to write logs 37 | */ 38 | class logger 39 | { 40 | public: 41 | logger (); 42 | logger ( int _level ); 43 | ~logger (); 44 | 45 | template < typename T > 46 | friend logger & operator << ( logger &buf, T a ) 47 | { 48 | if ( buf.visible ) { 49 | std::stringstream SS_BUF; 50 | SS_BUF << a; 51 | add_string ( SS_BUF.str () ); 52 | } 53 | return buf; 54 | } 55 | 56 | friend logger & operator << ( logger &buf, log_endl_t a ) 57 | { 58 | if ( buf.visible ) { 59 | { 60 | std::lock_guard < std::mutex > lock ( output_lock ); 61 | 62 | ( *OUT ) << get_prefix ( buf.level ) << get_string () << std::endl; 63 | } 64 | clear_string (); 65 | } 66 | return buf; 67 | } 68 | 69 | private: 70 | int level; 71 | bool visible; 72 | }; 73 | 74 | extern logger critical; 75 | extern logger error; 76 | extern logger warning; 77 | extern logger info; 78 | extern logger debug; 79 | 80 | extern log_endl_t log_endl; 81 | } 82 | 83 | void init_logger (); // Initialize the logger 84 | void destroy_logger (); // Destory the logger 85 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * main.cpp 3 | * Main entrance to the Operating System 4 | */ 5 | 6 | #include "init/init.h" 7 | #include "destroy/destroy.h" 8 | #include "../test/test.h" 9 | #include "env/env.h" 10 | 11 | int main () 12 | { 13 | init (); 14 | if (TEST) { 15 | test (); 16 | } 17 | destroy (); 18 | } 19 | -------------------------------------------------------------------------------- /src/message/msg_helper.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * message/msg_helper.h 3 | * Helper functions for message 4 | */ 5 | 6 | #include "msg_helper.h" 7 | #include "message.h" 8 | #include "../status/status.h" 9 | #include "../core/core.h" 10 | #include "../../dev/device_list.h" 11 | #include 12 | 13 | std::string message::get_prefix ( const msg_info_t & info, std::string source ) 14 | { 15 | std::stringstream string_helper; 16 | string_helper << source; 17 | while ( string_helper.str ().size () < 20 ) { 18 | string_helper << " "; 19 | } 20 | string_helper << " : "; 21 | return string_helper.str (); 22 | } 23 | 24 | std::string message::get_suffix ( const msg_info_t & info, std::string source ) 25 | { 26 | std::stringstream string_helper; 27 | return string_helper.str (); 28 | } 29 | 30 | void message::output_message ( std::string msg ) 31 | { 32 | if ( OUT != nullptr ) { 33 | ( *OUT ) << msg << std::endl; 34 | } 35 | if ( IO_DEVICE ) { 36 | device_desc::device_screen->write ( "m", msg ); 37 | } 38 | } 39 | 40 | std::string message::wrap_core_info ( std::string str ) 41 | { 42 | return wrap_core_info ( str, status.get_core ()->get_core_id () ); 43 | } 44 | 45 | std::string message::wrap_core_info ( std::string str, int core_id ) 46 | { 47 | std::stringstream string_helper; 48 | string_helper << str << " (" << core_id << ")"; 49 | return string_helper.str (); 50 | } 51 | -------------------------------------------------------------------------------- /src/message/msg_helper.h: -------------------------------------------------------------------------------- 1 | /** 2 | * message/msg_helper.h 3 | * Helper functions for message 4 | */ 5 | 6 | #include 7 | 8 | namespace message 9 | { 10 | class msg_info_t; 11 | 12 | std::string get_prefix ( const msg_info_t &info, std::string source ); 13 | std::string get_suffix ( const msg_info_t &info, std::string source ); 14 | 15 | void output_message ( std::string msg ); 16 | 17 | std::string wrap_core_info ( std::string str ); 18 | std::string wrap_core_info ( std::string str, int core_id ); 19 | } 20 | -------------------------------------------------------------------------------- /src/mm/page_table.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Data Structure For Page Table 3 | */ 4 | 5 | #include "page_table.h" 6 | #include "../logging/logging.h" 7 | #include "../utils/panic.h" 8 | #include "../utils/pagerepl/fifo.h" 9 | #include "pmm.h" 10 | #include 11 | 12 | pte_t::pte_t() 13 | { 14 | present = 0; 15 | access = 0; 16 | dirty = 0; 17 | write = user = 0; 18 | paddr = 0; 19 | } 20 | 21 | page_table::page_table() 22 | { 23 | table = new pte_t[VPAGE_NUM]; 24 | page_rp = new fifo_repl(PAGE_NUM); 25 | } 26 | 27 | page_table::~page_table() 28 | { 29 | assert(table != nullptr); 30 | delete[] table; 31 | delete page_rp; 32 | } 33 | 34 | pte_t* page_table::get_pte(size_t la) 35 | { 36 | size_t id = la / PAGE_SIZE; 37 | assert(id < VPAGE_NUM); 38 | if (table[id].present) { 39 | return table + id; 40 | } else { 41 | size_t pg; 42 | page_frame* page; 43 | pmm_require_lock(); 44 | { 45 | if (page_rp->full()) { 46 | pg = page_rp->swap_out(); 47 | swap_out_nlock(pte2page(table + pg)); 48 | page = alloc_page_nlock(); 49 | } else { 50 | page = alloc_page_nlock(); 51 | pg = page2id(page); 52 | } 53 | } 54 | pmm_release_lock(); 55 | assert(page != nullptr); 56 | page_rp->swap_in(pg); 57 | page->ref(); 58 | table[id].present = 1; 59 | table[id].user = 1; 60 | if (table[id].paddr != 0) { 61 | swap_in(table + pg, page); 62 | table[id].paddr = page->paddr; 63 | } else { 64 | table[id].paddr = page->paddr; 65 | logging::info << "SET TABLE : id " << id << ", paddr = " << (page-pages)*PAGE_SIZE << "," << page->paddr << logging::log_endl; 66 | } 67 | return table + id; 68 | } 69 | } 70 | 71 | pte_t* page_table::get_pte_try(size_t la) 72 | { 73 | size_t id = la / PAGE_SIZE; 74 | assert(id < VPAGE_NUM); 75 | return table + id; 76 | } 77 | 78 | void page_table::free_pte(size_t id) 79 | { 80 | assert(id < VPAGE_NUM); 81 | pte_t *page = table + id; 82 | if (page->present) { 83 | free_page(id2page(page->paddr/PAGE_SIZE)); 84 | } else if (page->paddr != 0) { 85 | // free page in swap 86 | } 87 | } 88 | 89 | void page_table::set_pte(size_t id, const pte_t &pte) 90 | { 91 | assert(id < VPAGE_NUM); 92 | table[id] = pte; 93 | } 94 | 95 | page_frame* pte2page(pte_t *pte) 96 | { 97 | assert(pte->present); 98 | return pa2page(pte->paddr); 99 | } 100 | -------------------------------------------------------------------------------- /src/mm/page_table.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Data Structures for Page Table 3 | */ 4 | 5 | #pragma once 6 | #include 7 | #include 8 | #include 9 | #include "pmem_info.h" 10 | #include "../env/env.h" 11 | #include "../utils/pagerepl/pagerepl.h" 12 | 13 | class page_frame; 14 | 15 | /* type of page table entry */ 16 | struct pte_t { 17 | bool present; // true if the page is inside memory 18 | bool access; // true if the page is accessed 19 | bool dirty; // true if the page is modified 20 | bool write; // true if the page is writable 21 | bool user; // true if the page can be accessed in user mode 22 | size_t paddr; // if (present) : physical address of the page 23 | // else : physical address in swap 24 | // if !present && paddr == 0 : uninited 25 | std::list::iterator linker; 26 | pte_t(); 27 | }; 28 | 29 | class page_table { 30 | public: 31 | 32 | page_table(); 33 | ~page_table(); 34 | 35 | pte_t* get_pte(size_t la); // get pte, if failed, try swap in 36 | pte_t* get_pte_try(size_t la); // get pte, if failed, return nullptr 37 | 38 | void set_pte(size_t id, const pte_t &pte); 39 | void free_pte(size_t id); 40 | 41 | private: 42 | 43 | pte_t *table; 44 | page_repl *page_rp; 45 | }; 46 | 47 | page_frame* pte2page(pte_t *pte); 48 | -------------------------------------------------------------------------------- /src/mm/pmem.h: -------------------------------------------------------------------------------- 1 | /* physical memory */ 2 | #pragma once 3 | 4 | namespace pm { 5 | 6 | // interface for simulater 7 | char read(size_t paddr); 8 | void write(size_t paddr, char data); 9 | 10 | } 11 | 12 | // interface for os 13 | void init_pm(); 14 | void destroy_pm(); 15 | -------------------------------------------------------------------------------- /src/mm/pmem_info.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Memory Infomations 3 | */ 4 | 5 | #include "pmem_info.h" 6 | #include "../env/env.h" 7 | 8 | const size_t PAGE_SIZE = 1 << 12; 9 | const size_t PAGE_NUM = MEMORY_SIZE / PAGE_SIZE; 10 | const size_t VM_SIZE = 1u << 31; 11 | const size_t VPAGE_NUM = VM_SIZE / PAGE_SIZE; 12 | -------------------------------------------------------------------------------- /src/mm/pmem_info.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Memory Infomations 3 | */ 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | extern const size_t PAGE_SIZE; // Size of each page 10 | extern const size_t PAGE_NUM; // Number of pages 11 | extern const size_t MEMORY_SIZE; // Size of memory 12 | extern const size_t VM_SIZE; // Size of process virtual address space 13 | extern const size_t VPAGE_NUM; // Number of VM Pages 14 | -------------------------------------------------------------------------------- /src/mm/pmm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "pmem_info.h" 3 | #include "../env/env.h" 4 | #include "page_table.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class page_frame { 11 | public: 12 | 13 | size_t paddr; // start point of page 14 | int length; // length of the page block 15 | bool alloced; // if alloced 16 | page_frame(); 17 | 18 | void ref(); // refer counter ++ 19 | void free(); // refer counter -- 20 | bool die(); // refer counter == 0 21 | 22 | std::list link; 23 | // pte point to current page frame 24 | private: 25 | 26 | int refer; // ref counter 27 | } ; 28 | 29 | extern page_frame *pages; 30 | 31 | // init function 32 | void init_pmm(); 33 | void destroy_pmm(); 34 | 35 | // interface for OS 36 | 37 | /** 38 | * swap the page @pg out 39 | */ 40 | void swap_out(page_frame* pg); 41 | void swap_out_nlock(page_frame* pg); 42 | 43 | /** 44 | * swap the page @pg into memory 45 | */ 46 | void swap_in(pte_t *pte, page_frame *pg); 47 | void swap_in_nlock(pte_t *pte, page_frame *pg); 48 | 49 | page_frame* alloc_pages(int n); 50 | page_frame* alloc_page(); 51 | page_frame* alloc_page_nlock(); 52 | page_frame* alloc_pages_nlock(int n); 53 | 54 | void free_pages(page_frame *pg); 55 | void free_page(page_frame *pg); 56 | 57 | int page2id(page_frame *pg); 58 | page_frame* id2page(int id); 59 | page_frame* pa2page(size_t pa); 60 | 61 | void pmm_require_lock(); 62 | void pmm_release_lock(); 63 | 64 | void pte_link_pf(pte_t *pte, page_frame *pg); 65 | -------------------------------------------------------------------------------- /src/mmu/mmu.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Memory Manage Unit 3 | * Protection: when process access invalid address, trigger a #GP 4 | * Paging: when process access a page not loaded in memory, trigger a #PF 5 | */ 6 | 7 | #pragma once 8 | #include 9 | #include 10 | #include "../mm/page_table.h" 11 | 12 | class CPU_core; 13 | 14 | /** 15 | * class CPU_mmu 16 | * Each instance of this class is a mmu of a core 17 | */ 18 | class CPU_mmu { 19 | public: 20 | 21 | CPU_mmu(); 22 | CPU_mmu(CPU_core *core); 23 | ~CPU_mmu(); 24 | 25 | char read(size_t la); 26 | void write(size_t la, char data); 27 | private: 28 | 29 | CPU_core *core; 30 | bool check(size_t la, pte_t *pte, bool write); 31 | }; 32 | -------------------------------------------------------------------------------- /src/motherboard/motherboard.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * motherboard/motherboard.cpp 3 | * Motherboard 4 | */ 5 | 6 | #include "motherboard.h" 7 | #include "../logging/logging.h" 8 | 9 | motherboard_t *motherboards; // List of motherboards 10 | 11 | motherboard_t::motherboard_t () 12 | : ioapic ( this ) 13 | { 14 | } 15 | 16 | motherboard_t::~motherboard_t () 17 | { 18 | } 19 | 20 | void motherboard_t::set_id ( int _id ) 21 | { 22 | } 23 | 24 | int motherboard_t::get_id () const 25 | { 26 | return 0; 27 | } 28 | 29 | io_apic & motherboard_t::get_io_apic () 30 | { 31 | return ioapic; 32 | } 33 | 34 | void motherboard_t::send_interrupt ( external_interrupt_t * current_interrupt ) 35 | { 36 | get_io_apic ().interrupt ( current_interrupt ); 37 | } 38 | 39 | 40 | 41 | void init_motherboards ( int n ) 42 | { 43 | logging::info << "Initializing " << n << " motherboards" << logging::log_endl; 44 | motherboards = new motherboard_t[n]; 45 | for ( int i = 0; i < n; ++i ) { 46 | logging::debug << "Initializing motherboard #" << i << logging::log_endl; 47 | motherboards[i].set_id ( i ); 48 | motherboards[i].get_io_apic ().enable (); 49 | } 50 | } 51 | 52 | void destroy_motherboards () 53 | { 54 | logging::debug << "Destroying motherboards" << logging::log_endl; 55 | 56 | delete[] motherboards; 57 | } 58 | -------------------------------------------------------------------------------- /src/motherboard/motherboard.h: -------------------------------------------------------------------------------- 1 | /** 2 | * motherboard/motherboard.h 3 | * Motherboard 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "../apic/io_apic.h" 9 | 10 | class motherboard_t 11 | { 12 | public: 13 | motherboard_t (); 14 | ~motherboard_t (); 15 | 16 | void set_id ( int _id ); 17 | int get_id () const; 18 | 19 | io_apic & get_io_apic (); 20 | 21 | void send_interrupt ( external_interrupt_t *current_interrupt ); 22 | 23 | private: 24 | io_apic ioapic; 25 | int id; 26 | }; 27 | 28 | extern motherboard_t *motherboards; // List of motherboards 29 | 30 | /** 31 | * init_motherboards ( int n ) 32 | * Arguments 33 | * @n: the number of motherboards 34 | */ 35 | void init_motherboards ( int n ); 36 | 37 | /** 38 | * destroy_motherboards () 39 | */ 40 | void destroy_motherboards (); 41 | -------------------------------------------------------------------------------- /src/process/idle.cpp: -------------------------------------------------------------------------------- 1 | #include "idle.h" 2 | #include "process_t.h" 3 | #include 4 | #include 5 | #include "../core/cpus.h" 6 | #include "../interrupt/interrupt.h" 7 | #include "../status/status.h" 8 | 9 | using std::mutex; 10 | using std::unique_lock; 11 | using std::lock_guard; 12 | using std::thread; 13 | 14 | /** 15 | * idle use this process 16 | * proc->get_proc == nullptr <==> proc is idle 17 | */ 18 | process_t proc; 19 | 20 | static mutex flag_mut; 21 | 22 | static void idle_main() 23 | { 24 | status.set_core(proc.get_core()); 25 | status.set_name(proc.get_name()); 26 | proc.get_core()->acquire(); 27 | while (1) { 28 | lock_guard lk(flag_mut); 29 | if (proc.get_exit_flag()) 30 | break; 31 | proc.get_core()->set_current(&proc); 32 | check_interrupt(); 33 | std::this_thread::sleep_for ( std::chrono::milliseconds ( 20 ) ); 34 | } 35 | } 36 | 37 | void signal_idle() 38 | { 39 | proc.get_core()->set_current(&proc); 40 | proc.cond_var.notify_one(); 41 | } 42 | 43 | void idle_exit() 44 | { 45 | if (1) { 46 | lock_guard lk(flag_mut); 47 | proc.set_exit_flag(); 48 | } 49 | proc.th->join(); 50 | delete proc.th; 51 | } 52 | 53 | void init_idle() 54 | { 55 | proc.set_name("idle"); 56 | proc.set_core(cores + 0); 57 | proc.set_prog(nullptr); 58 | proc.set_pid(0); 59 | status.get_core()->set_current(&proc); 60 | proc.th = new thread(idle_main); 61 | } 62 | 63 | -------------------------------------------------------------------------------- /src/process/idle.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void init_idle(); 4 | void signal_idle(); 5 | void idle_exit(); 6 | -------------------------------------------------------------------------------- /src/process/proc_dmm.cpp: -------------------------------------------------------------------------------- 1 | #include "process_t.h" 2 | #include "../utils/allocator/ffma.h" 3 | #include 4 | #include "../logging/logging.h" 5 | 6 | using logging::info; 7 | using logging::debug; 8 | using logging::log_endl; 9 | 10 | /** 11 | * init dynamic memory manager 12 | */ 13 | void process_t::init_dmm() 14 | { 15 | info << "init dmm." << log_endl; 16 | heap_allocator = new 17 | ffma(VM_SIZE - prog->get_data_size() 18 | - prog->get_bss_size()); 19 | info << "finished." << log_endl; 20 | } 21 | 22 | /** 23 | * malloc continuous memory of @len bytes 24 | * using ffma algorithm 25 | * @len : length of continuous memory 26 | * @return : address of the start of the memory 27 | */ 28 | size_t process_t::heap_malloc(size_t len) 29 | { 30 | size_t offset = prog->get_data_size() 31 | + prog->get_bss_size() + sizeof(size_t); 32 | size_t ptr = offset + heap_allocator-> 33 | malloc(len + sizeof(size_t)); 34 | vm_write(ptr - sizeof(size_t), 35 | (const char*)&len, 36 | (const char*)((&len) + 1)); 37 | return ptr; 38 | } 39 | 40 | /** 41 | * free continuous memory start from @ptr 42 | * @ptr : start of the memory 43 | */ 44 | void process_t::heap_free(size_t ptr) 45 | { 46 | size_t len = -1; 47 | char *pt = (char*)&len; 48 | vm_read(pt, 49 | ptr - sizeof(size_t), 50 | ptr); 51 | assert(len != (size_t)-1); 52 | size_t offset = prog->get_data_size() 53 | + prog->get_bss_size(); 54 | ptr -= offset + sizeof(size_t); 55 | heap_allocator->free(ptr, len + sizeof(size_t)); 56 | } 57 | 58 | /** 59 | * push stack 60 | * @size : the size of object to push 61 | * @return : the address of new stack top 62 | */ 63 | size_t process_t::stack_push(size_t size) 64 | { 65 | info << "push : " << size << log_endl; 66 | context.esp -= size; 67 | return context.esp; 68 | } 69 | 70 | /** 71 | * pop stack 72 | * @size : the size of object to pop 73 | * @return : the address of new stack top 74 | */ 75 | size_t process_t::stack_pop(size_t size) 76 | { 77 | info << "pop : " << size << log_endl; 78 | context.esp += size; 79 | return context.esp; 80 | } 81 | -------------------------------------------------------------------------------- /src/process/process.h: -------------------------------------------------------------------------------- 1 | /** 2 | * process/process.h 3 | * operations to processes 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "process_t.h" 9 | 10 | int proc_create_process(); 11 | int proc_exec_program(int pid, program *prog); 12 | int proc_yield(); 13 | int proc_wait(int pid); 14 | int proc_exit(); 15 | int proc_sleep(); 16 | 17 | void init_proc(); 18 | void destroy_proc(); 19 | -------------------------------------------------------------------------------- /src/process/process_load.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * process/process_load.cpp 3 | * init runtime environment 4 | */ 5 | 6 | #include "process_t.h" 7 | #include "../mm/pmm.h" 8 | #include "../mm/page_table.h" 9 | #include "../context/context.h" 10 | #include 11 | #include "../mm/pmem.h" 12 | #include "../logging/logging.h" 13 | 14 | /** 15 | * alloc page table for @this 16 | */ 17 | void process_t::init_context() 18 | { 19 | logging::info << "init context." << logging::log_endl; 20 | context.set_page_table(new page_table); 21 | context.esp = VM_SIZE; 22 | context.brk = prog->get_data_size() + prog->get_bss_size(); 23 | logging::info << "init context finish" << logging::log_endl; 24 | } 25 | 26 | /** 27 | * alloc pages for .data and copy 28 | */ 29 | void process_t::init_data() 30 | { 31 | size_t data_size = prog->get_data_size(); 32 | assert(data_size % PAGE_SIZE == 0); 33 | assert(prog != nullptr); 34 | size_t page_number = data_size / PAGE_SIZE; 35 | page_table *pt = context.get_page_table(); 36 | assert(pt != nullptr); 37 | size_t id = 0; 38 | for (size_t i = 0; i < page_number; i++) { 39 | pte_t pte; 40 | page_frame *pf = alloc_page(); 41 | assert(pf != nullptr); 42 | pte.present = true; 43 | pte.access = pte.dirty = false; 44 | pte.write = pte.user = true; 45 | pte.paddr = pf->paddr; 46 | pt->set_pte(i, pte); 47 | pte_t *pte_new = pt->get_pte(i * PAGE_SIZE); 48 | assert(pte_new != nullptr); 49 | pte_link_pf(pte_new, pf); 50 | pf->ref(); 51 | for (size_t j = 0; j < PAGE_SIZE && id < data_size; j++) { 52 | pm::write(pf->paddr + j, prog->get_data(id)); 53 | id++; 54 | } 55 | } 56 | } 57 | 58 | /** 59 | * alloc pages for .bss and clear 60 | */ 61 | void process_t::init_bss() 62 | { 63 | size_t bss_size = prog->get_bss_size(); 64 | size_t start = prog->get_data_size() / PAGE_SIZE; 65 | assert(bss_size % PAGE_SIZE == 0); 66 | assert(prog != nullptr); 67 | size_t page_number = bss_size / PAGE_SIZE; 68 | page_table *pt = context.get_page_table(); 69 | assert(pt != nullptr); 70 | for (size_t i = 0; i < page_number; i++) { 71 | pte_t pte; 72 | page_frame *pf = alloc_page(); 73 | assert(pf != nullptr); 74 | pte.present = true; 75 | pte.access = pte.dirty = false; 76 | pte.write = pte.user = true; 77 | pte.paddr = pf->paddr; 78 | pt->set_pte(start + i, pte); 79 | pte_t *pte_new = pt->get_pte((start + i) * PAGE_SIZE); 80 | assert(pte_new != nullptr); 81 | pte_link_pf(pte_new, pf); 82 | pf->ref(); 83 | for (size_t j = 0; j < PAGE_SIZE; j++) { 84 | pm::write(pf->paddr + j, 0); 85 | } 86 | } 87 | } 88 | 89 | /** 90 | * clean process and exit 91 | * free context 92 | */ 93 | void process_t::clean() 94 | { 95 | if (heap_allocator != nullptr) { 96 | delete heap_allocator; 97 | heap_allocator = nullptr; 98 | } 99 | context.free_all_pages(); 100 | } 101 | -------------------------------------------------------------------------------- /src/process/process_t.h: -------------------------------------------------------------------------------- 1 | /** 2 | * process/process_t.h 3 | * basic information of process_t 4 | */ 5 | 6 | #pragma once 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include "../context/context.h" 17 | #include "../program/program.h" 18 | #include "../utils/allocator/allocator.h" 19 | 20 | class CPU_core; 21 | 22 | class process_t { 23 | public: 24 | 25 | enum state { 26 | UNINIT, 27 | SLEEPING, 28 | RUNABLE, 29 | ZOMBIE 30 | }; 31 | 32 | process_t(); 33 | ~process_t(); 34 | 35 | // set/get process id 36 | void set_pid(int pid); 37 | int get_pid() const; 38 | 39 | // set/get process state 40 | state get_state() const; 41 | void set_state(state stat); 42 | 43 | // set/get process name 44 | void set_name(const std::string &name); 45 | std::string get_name() const; 46 | 47 | // set/get program of process 48 | void set_prog(program *prog); 49 | program* get_prog() const; 50 | 51 | // exec current process, return promise when start 52 | void exec(std::promise &fin_code); 53 | 54 | // set/get context of process (page table, ...) 55 | context_t get_context() const; 56 | void set_context(const context_t &context); 57 | 58 | // set/get parent and children of process 59 | void add_chl(int pid); 60 | void set_par(int pid); 61 | bool is_chl(int pid) const; 62 | int get_par() const; 63 | 64 | // set time slice, or minus 1 (tick) 65 | bool tick(); 66 | void set_slice(size_t slice); 67 | 68 | // set/get core 69 | void set_core(CPU_core *core); 70 | CPU_core* get_core() const; 71 | 72 | // condition variable to break control flow 73 | std::condition_variable cond_var; 74 | std::mutex cond_mutex; 75 | 76 | // linker to state list 77 | std::list::iterator linker; 78 | 79 | // init 80 | void init_context(); 81 | void init_data(); 82 | void init_bss(); 83 | void init_dmm(); 84 | 85 | // set/get need_resched 86 | void set_resched(bool resch); 87 | bool get_resched() const; 88 | 89 | // vm read/write opertions 90 | void vm_read(char *buf, size_t la_begin, size_t la_end); 91 | void vm_write(size_t addr, const char *buf_begin, const char *buf_end); 92 | 93 | // heap & stack operations 94 | size_t heap_malloc(size_t len); 95 | void heap_free(size_t ptr); 96 | size_t stack_push(size_t size); 97 | size_t stack_pop(size_t size); 98 | 99 | // clean process when exit 100 | void clean(); 101 | 102 | // thread of current process 103 | std::thread *th; 104 | 105 | // set/get exit flag 106 | void set_exit_flag(); 107 | bool get_exit_flag() const; 108 | 109 | // set/get signal data (for wait/signal) 110 | void set_signal_data(size_t data); 111 | size_t get_signal_data() const; 112 | 113 | int get_clock_counter() const; 114 | 115 | bool is_idle() const; 116 | 117 | private: 118 | 119 | int pid; 120 | std::string name; 121 | program *prog; 122 | state pstat; 123 | context_t context; 124 | 125 | bool need_resched; 126 | size_t slice; 127 | 128 | size_t ptr_par; 129 | std::set ptr_chl; 130 | 131 | CPU_core *core; 132 | allocator *heap_allocator; 133 | 134 | bool exit_flag; 135 | size_t signal_data; 136 | 137 | int clock_counter; 138 | // count time slice @this use 139 | }; 140 | -------------------------------------------------------------------------------- /src/program/dmm.cpp: -------------------------------------------------------------------------------- 1 | #include "program.h" 2 | #include "../utils/allocator/allocator.h" 3 | #include "../utils/allocator/ffma.h" 4 | #include "../process/process_t.h" 5 | 6 | /* temp */ 7 | size_t program::heap_malloc(size_t len) 8 | { 9 | return cur_proc->heap_malloc(len); 10 | } 11 | 12 | /* temp */ 13 | void program::heap_free(size_t ptr) 14 | { 15 | cur_proc->heap_free(ptr); 16 | } 17 | 18 | size_t program::stack_push(size_t size) 19 | { 20 | return cur_proc->stack_push(size); 21 | } 22 | 23 | size_t program::stack_pop(size_t size) 24 | { 25 | if (cur_proc->get_exit_flag()) { 26 | return 0; 27 | } 28 | return cur_proc->stack_pop(size); 29 | } 30 | 31 | -------------------------------------------------------------------------------- /src/program/dmm.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tqyaaaaang/Hyper-OS/7fe501e2173425c7d08b5457c08ee8ebf5261ba0/src/program/dmm.h -------------------------------------------------------------------------------- /src/program/lib.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * program/lib.h 3 | * standard library for hos 4 | */ 5 | 6 | #include "lib.h" 7 | #include "sys_t.h" 8 | #include "program.h" 9 | #include "../logging/logging.h" 10 | #include "../message/message.h" 11 | 12 | using std::string; 13 | using message::wrap_core_info; 14 | 15 | static void msg_intr(string str) 16 | { 17 | message::interrupt(wrap_core_info("user stdlib")) 18 | << str 19 | << message::msg_endl; 20 | } 21 | 22 | hos_std_t::hos_std_t(program *prog) 23 | { 24 | this->prog = prog; 25 | } 26 | 27 | hos_std_t::~hos_std_t() 28 | { 29 | 30 | } 31 | 32 | void hos_std_t::init() 33 | { 34 | 35 | } 36 | 37 | void hos_std_t::println(string str) 38 | { 39 | msg_intr("call function \'println\' in standard library"); 40 | sys_t *sys = this->prog->sys; 41 | for (char i : str) { 42 | sys->write(sys->std_output(), i); 43 | } 44 | sys->write(sys->std_output(), '\n'); 45 | } 46 | 47 | void hos_std_t::print(string str) 48 | { 49 | msg_intr("call function \'print\' in standard library"); 50 | sys_t *sys = this->prog->sys; 51 | for (char i : str) { 52 | sys->write(sys->std_output(), i); 53 | } 54 | } 55 | 56 | void hos_std_t::putchar(handle c) 57 | { 58 | sys_t *sys = prog->sys; 59 | sys->write(sys->std_output(), (char)c); 60 | } 61 | 62 | void hos_std_t::print(handle str) 63 | { 64 | msg_intr("call function \'print\' in standard library"); 65 | for (size_t i = 0; str[i] != '\0'; i++) { 66 | this->putchar(str[i]); 67 | } 68 | } 69 | 70 | void hos_std_t::println(handle str) 71 | { 72 | msg_intr("call function \'println\' in standard library"); 73 | for (size_t i = 0; str[i] != '\0'; i++) { 74 | this->putchar(str[i]); 75 | } 76 | this->putchar('\n'); 77 | } 78 | 79 | int hos_std_t::getchar() 80 | { 81 | sys_t *sys = prog->sys; 82 | handle data = sys->read(sys->std_input()); 83 | return (int)data; 84 | } 85 | 86 | int hos_std_t::read_int() 87 | { 88 | msg_intr("call function \'read_int\' in standard library"); 89 | handle result = 0; 90 | handle ch = (int)0; 91 | handle flag = 1; 92 | while ((ch < '0' || ch > '9') && ch != '-') { 93 | ch = this->getchar(); 94 | } 95 | if (ch == '-') { 96 | flag = -1; 97 | ch = this->getchar(); 98 | } 99 | do { 100 | result = result * 10 + (int)(ch - '0'); 101 | ch = this->getchar(); 102 | } while ('0' <= ch && ch <= '9'); 103 | int dat = result * flag; 104 | logging::debug << "read a int : " << dat << logging::log_endl; 105 | return result * flag; 106 | } 107 | 108 | void hos_std_t::write_recur(handle dat) 109 | { 110 | if (dat != 0) { 111 | write_recur(dat / 10); 112 | msg_intr("call function \'print\' in standard library"); 113 | this->putchar((int)((dat % 10) + '0')); 114 | } 115 | } 116 | 117 | void hos_std_t::write_int(int data) 118 | { 119 | msg_intr("call function \'write_int\' in standard library"); 120 | if (data < 0) { 121 | this->putchar('-'); 122 | data = -data; 123 | } 124 | handle num = data; 125 | if (num == 0) { 126 | this->putchar('0'); 127 | } else { 128 | write_recur((int)num); 129 | } 130 | logging::debug << "write a int : " << num << logging::log_endl; 131 | } 132 | 133 | -------------------------------------------------------------------------------- /src/program/lib.h: -------------------------------------------------------------------------------- 1 | /** 2 | * program/lib.h 3 | * standard library for hos 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include "program.h" 10 | 11 | class hos_std_t { 12 | public: 13 | 14 | hos_std_t(program *prog); 15 | virtual ~hos_std_t(); 16 | virtual void println(std::string str); 17 | virtual void print(std::string str); 18 | virtual void println(handle str); 19 | virtual void print(handle str); 20 | virtual void putchar(handle c); 21 | virtual int getchar(); 22 | virtual int read_int(); 23 | virtual void write_int(int data); 24 | virtual void init(); 25 | 26 | private: 27 | 28 | program *prog; 29 | void write_recur(handle dat); 30 | 31 | }; 32 | -------------------------------------------------------------------------------- /src/program/program_manager.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * program/program_manager.h 3 | * find program by name 4 | */ 5 | 6 | #include "program_manager.h" 7 | #include "../logging/logging.h" 8 | #include "../../user/shell/shell.h" 9 | #include "../../user/lp/lp.h" 10 | #include "../../user/elephant/elephant.h" 11 | #include "../../user/matrix/matrix.h" 12 | #include "../../user/demo_interrupt/demo_interrupt.h" 13 | #include "../../user/demo_pagefault/demo_pagefault.h" 14 | #include "../../user/demo_process/demo_process.h" 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | using std::vector; 21 | using std::map; 22 | using std::pair; 23 | using std::string; 24 | using std::make_pair; 25 | using std::function; 26 | 27 | map prog_table; 28 | vector prog_name; 29 | 30 | void register_program(string name, program* (*gen)() ) 31 | { 32 | assert(!prog_table.count(name)); 33 | prog_table[name] = gen; 34 | prog_name.push_back(name); 35 | } 36 | 37 | bool is_program(string name) 38 | { 39 | return prog_table.count(name); 40 | } 41 | 42 | program* get_program(string name) 43 | { 44 | if (!prog_table.count(name)) { 45 | logging::warning << "program " << name 46 | << " not found." << logging::log_endl; 47 | return nullptr; 48 | } 49 | program* (*gen)() = prog_table[name]; 50 | program* prog = gen(); 51 | prog->build(); 52 | return prog; 53 | } 54 | 55 | void destroy_program_manager() 56 | { 57 | } 58 | 59 | void init_program_manager() 60 | { 61 | register_shell(); 62 | register_lp(); 63 | register_elephant(); 64 | register_matrix(); 65 | register_demo_syscall(); 66 | register_demo_pagefault(); 67 | register_demo_process(); 68 | } 69 | -------------------------------------------------------------------------------- /src/program/program_manager.h: -------------------------------------------------------------------------------- 1 | /** 2 | * program/program_manager.h 3 | * find program by name 4 | */ 5 | #pragma once 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "program.h" 14 | 15 | /** 16 | * register a program 17 | * @name : name of program 18 | * @gen : program generator 19 | */ 20 | void register_program(std::string name, 21 | program* (*gen)()); 22 | 23 | program* get_program(std::string name); 24 | bool is_program(std::string name); 25 | 26 | void init_program_manager(); 27 | void destroy_program_manager(); 28 | -------------------------------------------------------------------------------- /src/program/sys_t.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * program/sys_t.cpp 3 | * syscall interface for user-mode programs 4 | */ 5 | 6 | #include "sys_t.h" 7 | #include "program_manager.h" 8 | #include "../../dev/device_list.h" 9 | #include "../../dev/devices/output/output.h" 10 | #include "../../dev/devices/input/input.h" 11 | #include "../process/process.h" 12 | #include "../process/process_t.h" 13 | #include "../interrupt/interrupt.h" 14 | #include "../syscall/syscall.h" 15 | #include "../syscall/syscalls/sys_create_proc.h" 16 | #include "../syscall/syscalls/sys_exec_prog.h" 17 | #include "../syscall/syscalls/sys_write.h" 18 | #include "../syscall/syscalls/sys_read.h" 19 | #include "../syscall/syscalls/sys_exit.h" 20 | #include "../syscall/syscalls/sys_wait.h" 21 | #include "../syscall/syscalls/sys_yield.h" 22 | #include "../syscall/syscalls/sys_pid.h" 23 | #include "../syscall/syscalls/sys_parent.h" 24 | #include "../syscall/syscalls/sys_clock.h" 25 | #include "../interrupt/interrupts/syscall_interrupt.h" 26 | #include "../logging/logging.h" 27 | #include "../message/message.h" 28 | #include "program.h" 29 | #include 30 | #include 31 | 32 | using std::string; 33 | 34 | extern std::unordered_map zombie_map; 35 | 36 | static void msg_intr(string str) 37 | { 38 | message::interrupt 39 | (message::wrap_core_info("user syscall")) 40 | << str 41 | << message::msg_endl; 42 | } 43 | 44 | sys_t::sys_t(program *prog) 45 | { 46 | this->prog = prog; 47 | } 48 | 49 | int sys_t::intr(syscall_t *sys) 50 | { 51 | msg_intr("syscall function trigger INTR #80 using \'INT 80\' instruction"); 52 | syscall(sys); 53 | int return_value = sys->get_return_value(); 54 | delete sys; 55 | check_interrupt (); 56 | return return_value; 57 | } 58 | 59 | int sys_t::create_process() 60 | { 61 | return intr(new sys_create_proc()); 62 | } 63 | 64 | int sys_t::exec_program(int pid, handle name) 65 | { 66 | std::string str; 67 | for (size_t i = 0; name[i] != '\0'; i++) 68 | str = str + (char)name[i]; 69 | return intr(new sys_exec_prog(pid, get_program(str))); 70 | } 71 | 72 | int sys_t::yield() 73 | { 74 | return intr(new sys_yield()); 75 | } 76 | 77 | int sys_t::exit() 78 | { 79 | return intr(new sys_exit()); 80 | } 81 | 82 | int sys_t::wait(int pid) 83 | { 84 | int w = intr(new sys_wait(pid)); 85 | if (w == 0 && zombie_map.count(pid)) { 86 | process_t *proc = zombie_map[pid]; 87 | zombie_map.erase(pid); 88 | proc->cond_var.notify_one(); 89 | proc->th->join(); 90 | logging::info << "sys_wait kill process :"<< pid << logging::log_endl; 91 | delete proc->th; 92 | delete proc; 93 | } 94 | return w; 95 | } 96 | 97 | int sys_t::read(dev_input *device) 98 | { 99 | int w = intr(new sys_read(device)); 100 | assert(w == 0); 101 | assert(prog != nullptr); 102 | assert(prog->cur_proc != nullptr); 103 | return prog->cur_proc->get_signal_data(); 104 | } 105 | 106 | int sys_t::write(dev_output *device, char data) 107 | { 108 | return intr(new sys_write(device, data)); 109 | } 110 | 111 | dev_output* sys_t::std_output() 112 | { 113 | return device_desc::standard_output; 114 | } 115 | 116 | dev_input* sys_t::std_input() 117 | { 118 | return device_desc::standard_input; 119 | } 120 | 121 | int sys_t::pid() 122 | { 123 | return intr(new sys_pid); 124 | } 125 | 126 | int sys_t::clock() 127 | { 128 | return intr(new sys_clock); 129 | } 130 | 131 | int sys_t::parent() 132 | { 133 | return intr(new sys_parent); 134 | } 135 | -------------------------------------------------------------------------------- /src/program/sys_t.h: -------------------------------------------------------------------------------- 1 | /** 2 | * program/sys_t.h 3 | * syscall interface for user-mode programs 4 | */ 5 | #pragma once 6 | #include 7 | #include "program.h" 8 | 9 | class syscall_t; 10 | class program; 11 | class dev_output; 12 | class dev_input; 13 | 14 | class sys_t { 15 | public: 16 | 17 | sys_t(program *prog); 18 | int create_process(); 19 | int exec_program(int pid, handle name); 20 | int yield(); 21 | int exit(); 22 | int wait(int pid); 23 | int read(dev_input *device); 24 | int write(dev_output *device, char data); 25 | int intr(syscall_t *sys); 26 | dev_output* std_output(); 27 | dev_input* std_input(); 28 | int pid(); 29 | int parent(); 30 | int clock(); 31 | 32 | private: 33 | 34 | program *prog; 35 | }; 36 | 37 | -------------------------------------------------------------------------------- /src/schedule/sched_msg.cpp: -------------------------------------------------------------------------------- 1 | #include "sched_msg.h" 2 | #include "../process/process_t.h" 3 | #include "../utils/panic.h" 4 | #include 5 | 6 | using std::string; 7 | typedef process_t::state state; 8 | 9 | void msg_proc(string str) 10 | { 11 | message::process 12 | (message::wrap_core_info("kern scheduler")) 13 | << str 14 | << message::msg_endl; 15 | } 16 | 17 | string to_string(int dat) 18 | { 19 | if (dat == 0) 20 | return "0"; 21 | string str = ""; 22 | while (dat) { 23 | str = char(dat % 10 + '0') + str; 24 | dat /= 10; 25 | } 26 | return str; 27 | } 28 | 29 | string proc_info(process_t *proc) 30 | { 31 | if (proc == nullptr) 32 | return ""; 33 | return proc->get_name() 34 | + "(pid = " 35 | + to_string(proc->get_pid()) 36 | + ")"; 37 | } 38 | 39 | string proc_state(process_t *proc) 40 | { 41 | switch(proc->get_state()) { 42 | case state::RUNABLE: 43 | return "runable"; 44 | break; 45 | case state::UNINIT: 46 | return "uninit"; 47 | break; 48 | case state::SLEEPING: 49 | return "sleeping"; 50 | break; 51 | case state::ZOMBIE: 52 | return "zombie"; 53 | break; 54 | } 55 | panic ( "unknown process state" ); 56 | return ""; 57 | } 58 | -------------------------------------------------------------------------------- /src/schedule/sched_msg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../message/message.h" 4 | #include 5 | 6 | class process_t; 7 | 8 | void msg_proc(std::string str); 9 | std::string to_string(int dat); 10 | std::string proc_info(process_t *proc); 11 | std::string proc_state(process_t *proc); 12 | -------------------------------------------------------------------------------- /src/schedule/schedule.h: -------------------------------------------------------------------------------- 1 | /** 2 | * schedule/schedule.h 3 | * schedule processes and cpus 4 | */ 5 | 6 | #pragma once 7 | #include "../process/process_t.h" 8 | 9 | void sched_init_proc(process_t *proc); 10 | void sched_set_core(process_t *proc); 11 | void sched_set_runable(process_t *proc); 12 | void sched_set_wait(process_t *proc, int pid); 13 | void sched_set_exit(process_t *proc); 14 | void sched_set_sleep(process_t *proc); 15 | 16 | void schedule(int core_id); 17 | 18 | void init_schedule(); 19 | void destroy_schedule(); 20 | -------------------------------------------------------------------------------- /src/schedule/signal.h: -------------------------------------------------------------------------------- 1 | /** 2 | * schedule/signal.h 3 | * signals to wake up sleeping process 4 | */ 5 | #include 6 | #include 7 | 8 | class process_t; 9 | 10 | class signal_t { 11 | 12 | public: 13 | 14 | signal_t(); 15 | signal_t(int id); 16 | ~signal_t(); 17 | void notify(int data); 18 | void wait(process_t *proc); 19 | 20 | private: 21 | 22 | std::mutex mut; 23 | std::queue proc; 24 | std::queue que; 25 | int signal_id; 26 | bool check_keyboard_signal(int data, process_t *proc); 27 | }; 28 | 29 | namespace signal_id { 30 | extern const int WAIT_EXIT; 31 | extern const int KEYBOARD; 32 | } 33 | 34 | void init_signal (); 35 | void destroy_signal (); 36 | 37 | /** 38 | * send/wait on a signal 39 | * @return : 0 ok 40 | * -1 not valid signal id 41 | */ 42 | int send_signal(int signal_id, int data); 43 | int wait_signal(int signal_id, process_t *proc); 44 | 45 | int register_signal(); 46 | 47 | -------------------------------------------------------------------------------- /src/status/status.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * status/status.cpp 3 | * Context of the current thread 4 | */ 5 | 6 | #include "status.h" 7 | #include "../core/cpus.h" 8 | #include "../logging/logging.h" 9 | #include "../core/core.h" 10 | 11 | status_t::status_t () 12 | : current_core ( NULL ) 13 | , name ( "" ) 14 | { 15 | } 16 | 17 | void status_t::set_core ( CPU_core * core ) 18 | { 19 | current_core = core; 20 | } 21 | 22 | CPU_core * status_t::get_core () const 23 | { 24 | return current_core; 25 | } 26 | 27 | void status_t::set_name ( std::string _name ) 28 | { 29 | name = _name; 30 | } 31 | 32 | std::string status_t::get_name () const 33 | { 34 | return name; 35 | } 36 | 37 | thread_local status_t status; 38 | 39 | void init_status_phase_1 () 40 | { 41 | logging::debug << "Setting initial thread status - Phase 1" << logging::log_endl; 42 | status.set_name ( "main thread" ); 43 | } 44 | 45 | void init_status_phase_2 () 46 | { 47 | logging::debug << "Setting initial thread status - Phase 2" << logging::log_endl; 48 | status.set_core ( &cores[0] ); 49 | } 50 | -------------------------------------------------------------------------------- /src/status/status.h: -------------------------------------------------------------------------------- 1 | /** 2 | * status/status.h 3 | * Context of the current thread 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | 10 | class CPU_core; 11 | 12 | class status_t 13 | { 14 | public: 15 | status_t (); 16 | 17 | void set_core ( CPU_core *core ); 18 | CPU_core * get_core () const; 19 | 20 | void set_name ( std::string _name ); 21 | std::string get_name () const; 22 | 23 | private: 24 | CPU_core *current_core; 25 | 26 | std::string name; 27 | }; 28 | 29 | extern thread_local status_t status; 30 | 31 | void init_status_phase_1 (); 32 | void init_status_phase_2 (); 33 | -------------------------------------------------------------------------------- /src/syscall/syscall.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * syscall/syscall.cpp 3 | * System call entry 4 | */ 5 | 6 | #include "syscall.h" 7 | #include "../interrupt/interrupt.h" 8 | #include "../interrupt/interrupts/syscall_interrupt.h" 9 | 10 | int syscall ( syscall_t * current_syscall ) 11 | { 12 | return interrupt ( new syscall_interrupt ( current_syscall ) ); 13 | } 14 | -------------------------------------------------------------------------------- /src/syscall/syscall.h: -------------------------------------------------------------------------------- 1 | /** 2 | * syscall/syscall.h 3 | * System call entry 4 | */ 5 | 6 | #pragma once 7 | 8 | class syscall_t; 9 | 10 | int syscall ( syscall_t *current_syscall ); 11 | -------------------------------------------------------------------------------- /src/syscall/syscall_id.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * syscall/syscall_id.cpp 3 | * System call IDs 4 | */ 5 | 6 | #include "syscall_id.h" 7 | -------------------------------------------------------------------------------- /src/syscall/syscall_id.h: -------------------------------------------------------------------------------- 1 | /** 2 | * syscall/syscall_id.h 3 | * System call IDs 4 | */ 5 | 6 | #pragma once 7 | 8 | enum class syscall_id_t 9 | { 10 | SYSCALL_TEST = 0, 11 | CREATE_PROC, 12 | EXEC_PROGRAM, 13 | YIELD, 14 | WAIT, 15 | EXIT, 16 | READ, 17 | WRITE, 18 | PID, 19 | CLOCK, 20 | PARENT 21 | }; 22 | -------------------------------------------------------------------------------- /src/syscall/syscalls/sys_clock.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * syscall/syscalls/sys_clock.cpp 3 | * clock() 4 | */ 5 | #include "sys_clock.h" 6 | #include "../../core/core.h" 7 | #include "../../status/status.h" 8 | #include "../../process/process_t.h" 9 | #include "../syscall_id.h" 10 | 11 | sys_clock::sys_clock() 12 | : syscall_t(syscall_id_t::CLOCK) 13 | { 14 | 15 | } 16 | 17 | int sys_clock::process() 18 | { 19 | return status.get_core()->get_current()->get_clock_counter(); 20 | } 21 | -------------------------------------------------------------------------------- /src/syscall/syscalls/sys_clock.h: -------------------------------------------------------------------------------- 1 | /** 2 | * syscall/syscalls/sys_clock.h 3 | * clock() 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "../../process/process.h" 9 | #include "syscall_t.h" 10 | 11 | class sys_clock : public syscall_t { 12 | public: 13 | 14 | sys_clock(); 15 | virtual int process(); 16 | 17 | private: 18 | 19 | }; 20 | 21 | -------------------------------------------------------------------------------- /src/syscall/syscalls/sys_create_proc.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * syscall/syscalls/sys_create_proc.cpp 3 | * create_proc syscall 4 | */ 5 | #include "sys_create_proc.h" 6 | 7 | sys_create_proc::sys_create_proc() 8 | :syscall_t(syscall_id_t::CREATE_PROC) 9 | {} 10 | 11 | int sys_create_proc::process() 12 | { 13 | return proc_create_process(); 14 | } 15 | -------------------------------------------------------------------------------- /src/syscall/syscalls/sys_create_proc.h: -------------------------------------------------------------------------------- 1 | /** 2 | * syscall/syscalls/sys_create_proc.h 3 | * create_proc syscall 4 | */ 5 | #pragma once 6 | 7 | #include "syscall_t.h" 8 | #include "../../process/process.h" 9 | 10 | class sys_create_proc : public syscall_t { 11 | public: 12 | 13 | sys_create_proc(); 14 | virtual int process(); 15 | }; 16 | 17 | -------------------------------------------------------------------------------- /src/syscall/syscalls/sys_exec_prog.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * syscall/syscalls/sys_exec_prog.cpp 3 | * create_proc syscall 4 | */ 5 | #include "sys_exec_prog.h" 6 | 7 | sys_exec_prog::sys_exec_prog(int pid, program *prog) 8 | : syscall_t(syscall_id_t::EXEC_PROGRAM) 9 | { 10 | this->pid = pid; 11 | this->prog = prog; 12 | } 13 | 14 | int sys_exec_prog::process() 15 | { 16 | return proc_exec_program(pid, prog); 17 | } 18 | -------------------------------------------------------------------------------- /src/syscall/syscalls/sys_exec_prog.h: -------------------------------------------------------------------------------- 1 | /** 2 | * syscall/syscalls/sys_exec_prog.h 3 | * create_proc syscall 4 | */ 5 | #pragma once 6 | 7 | #include "syscall_t.h" 8 | #include "../../process/process.h" 9 | 10 | class sys_exec_prog : public syscall_t { 11 | public: 12 | 13 | sys_exec_prog(int pid, program *prog); 14 | virtual int process(); 15 | 16 | private: 17 | int pid; 18 | program *prog; 19 | }; 20 | 21 | -------------------------------------------------------------------------------- /src/syscall/syscalls/sys_exit.cpp: -------------------------------------------------------------------------------- 1 | #include "sys_exit.h" 2 | 3 | sys_exit::sys_exit() 4 | :syscall_t(syscall_id_t::EXIT) 5 | {} 6 | 7 | int sys_exit::process() 8 | { 9 | return proc_exit(); 10 | } 11 | -------------------------------------------------------------------------------- /src/syscall/syscalls/sys_exit.h: -------------------------------------------------------------------------------- 1 | /** 2 | * syscall/syscalls/sys_exit.h 3 | * exit syscall 4 | */ 5 | #pragma once 6 | 7 | #include "../../process/process.h" 8 | #include "syscall_t.h" 9 | 10 | class sys_exit : public syscall_t { 11 | public: 12 | 13 | sys_exit(); 14 | virtual int process(); 15 | 16 | }; 17 | 18 | -------------------------------------------------------------------------------- /src/syscall/syscalls/sys_parent.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * syscall/syscalls/sys_parent.cpp 3 | * get process id of parent 4 | */ 5 | 6 | #include "sys_parent.h" 7 | #include "../../process/process.h" 8 | #include "../../logging/logging.h" 9 | #include "../../status/status.h" 10 | #include "../../core/core.h" 11 | 12 | sys_parent::sys_parent() 13 | :syscall_t(syscall_id_t::PARENT) 14 | { 15 | } 16 | 17 | int sys_parent::process() 18 | { 19 | int res = status.get_core()->get_current()->get_par(); 20 | logging::debug << "get pid : " << res << logging::log_endl; 21 | return res; 22 | } 23 | -------------------------------------------------------------------------------- /src/syscall/syscalls/sys_parent.h: -------------------------------------------------------------------------------- 1 | /** 2 | * syscall/syscalls/sys_parent.h 3 | * get pid of parent process 4 | */ 5 | #pragma once 6 | 7 | #include "../../process/process.h" 8 | #include "syscall_t.h" 9 | 10 | class sys_parent : public syscall_t { 11 | public: 12 | 13 | sys_parent(); 14 | virtual int process(); 15 | private: 16 | 17 | }; 18 | 19 | -------------------------------------------------------------------------------- /src/syscall/syscalls/sys_pid.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * syscall/syscalls/sys_pid.cpp 3 | * get process id 4 | */ 5 | 6 | #include "sys_pid.h" 7 | #include 8 | #include "../../process/process.h" 9 | #include "../../logging/logging.h" 10 | #include "../../status/status.h" 11 | #include "../../core/core.h" 12 | 13 | sys_pid::sys_pid() 14 | :syscall_t(syscall_id_t::PID) 15 | { 16 | } 17 | 18 | int sys_pid::process() 19 | { 20 | int res = status.get_core()->get_current()->get_pid(); 21 | logging::debug << "get pid : " << res << logging::log_endl; 22 | return res; 23 | } 24 | -------------------------------------------------------------------------------- /src/syscall/syscalls/sys_pid.h: -------------------------------------------------------------------------------- 1 | /** 2 | * syscall/syscalls/sys_pid.h 3 | * get pid of current process 4 | */ 5 | #pragma once 6 | 7 | #include "../../process/process.h" 8 | #include "syscall_t.h" 9 | 10 | class sys_pid : public syscall_t { 11 | public: 12 | 13 | sys_pid(); 14 | virtual int process(); 15 | private: 16 | 17 | }; 18 | 19 | -------------------------------------------------------------------------------- /src/syscall/syscalls/sys_read.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * syscall/syscalls/sys_read.h 3 | * read from device syscall 4 | */ 5 | 6 | #include "sys_read.h" 7 | #include "../../logging/logging.h" 8 | #include "../../../dev/device_list.h" 9 | 10 | sys_read::sys_read ( dev_input * device ) 11 | : syscall_t ( syscall_id_t::READ ) 12 | , device ( device ) 13 | { 14 | } 15 | 16 | int sys_read::process () 17 | { 18 | logging::debug << "Processing syscall READ" << logging::log_endl; 19 | device_desc::standard_input->read (); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /src/syscall/syscalls/sys_read.h: -------------------------------------------------------------------------------- 1 | /** 2 | * syscall/syscalls/sys_read.h 3 | * read from device syscall 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "../../process/process.h" 9 | #include "syscall_t.h" 10 | #include "../../../dev/device_list.h" 11 | #include "../../../dev/devices/input/input.h" 12 | 13 | class sys_read : public syscall_t { 14 | public: 15 | 16 | sys_read(dev_input *device); 17 | virtual int process(); 18 | 19 | private: 20 | 21 | dev_input *device; 22 | }; 23 | 24 | -------------------------------------------------------------------------------- /src/syscall/syscalls/sys_wait.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * syscall/syscalls/sys_wait.cpp 3 | * wait process 4 | */ 5 | 6 | #include "sys_wait.h" 7 | #include 8 | #include "../../process/process.h" 9 | #include "../../logging/logging.h" 10 | #include "../../schedule/signal.h" 11 | #include "../../status/status.h" 12 | 13 | sys_wait::sys_wait(int pid) 14 | :syscall_t(syscall_id_t::WAIT) 15 | { 16 | this->pid = pid; 17 | } 18 | 19 | int sys_wait::process() 20 | { 21 | logging::debug << "sys_wait : " << pid << logging::log_endl; 22 | int res = proc_wait(pid); 23 | logging::debug << "sys_wait finish." << logging::log_endl; 24 | return res; 25 | } 26 | -------------------------------------------------------------------------------- /src/syscall/syscalls/sys_wait.h: -------------------------------------------------------------------------------- 1 | /** 2 | * syscall/syscalls/sys_wait.h 3 | * wait syscall 4 | */ 5 | #pragma once 6 | 7 | #include "../../process/process.h" 8 | #include "syscall_t.h" 9 | 10 | class sys_wait : public syscall_t { 11 | public: 12 | 13 | sys_wait(int pid); 14 | virtual int process(); 15 | private: 16 | 17 | int pid; 18 | }; 19 | 20 | -------------------------------------------------------------------------------- /src/syscall/syscalls/sys_write.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * syscall/syscalls/sys_write.cpp 3 | * write to device syscall 4 | */ 5 | 6 | #include "sys_write.h" 7 | #include "../../logging/logging.h" 8 | 9 | sys_write::sys_write ( dev_output *device, char data ) 10 | : syscall_t ( syscall_id_t::WRITE ) 11 | { 12 | this->device = device; 13 | this->data = data; 14 | } 15 | 16 | int sys_write::process () 17 | { 18 | logging::debug << "Writing character " << static_cast < int > ( data ) << " to output device" << logging::log_endl; 19 | device->write ( data ); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /src/syscall/syscalls/sys_write.h: -------------------------------------------------------------------------------- 1 | /** 2 | * syscall/syscalls/sys_write.h 3 | * write to device syscall 4 | */ 5 | #pragma once 6 | 7 | #include "../../process/process.h" 8 | #include "syscall_t.h" 9 | #include "../../../dev/device_list.h" 10 | #include "../../../dev/devices/output/output.h" 11 | 12 | class sys_write : public syscall_t { 13 | public: 14 | 15 | sys_write(dev_output *device, char data); 16 | virtual int process(); 17 | 18 | private: 19 | 20 | dev_output *device; 21 | char data; 22 | }; 23 | 24 | -------------------------------------------------------------------------------- /src/syscall/syscalls/sys_yield.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * syscall/syscalls/sys_yield.cpp 3 | * create_proc syscall 4 | */ 5 | 6 | #include "sys_yield.h" 7 | #include "../../process/process.h" 8 | 9 | sys_yield::sys_yield() 10 | :syscall_t(syscall_id_t::YIELD) 11 | {} 12 | 13 | int sys_yield::process() 14 | { 15 | return proc_yield(); 16 | } 17 | -------------------------------------------------------------------------------- /src/syscall/syscalls/sys_yield.h: -------------------------------------------------------------------------------- 1 | /** 2 | * syscall/syscalls/sys_yield.h 3 | * create_proc syscall 4 | */ 5 | #pragma once 6 | 7 | #include "../../process/process.h" 8 | #include "syscall_t.h" 9 | 10 | class sys_yield : public syscall_t { 11 | public: 12 | 13 | sys_yield(); 14 | virtual int process(); 15 | }; 16 | 17 | -------------------------------------------------------------------------------- /src/syscall/syscalls/syscall_t.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * syscall/syscalls/syscall_t.h 3 | * System call classes 4 | * Abstract base class syscall_t 5 | */ 6 | 7 | #include "syscall_t.h" 8 | 9 | #include 10 | 11 | syscall_t::syscall_t ( syscall_id_t id ) 12 | : syscall_id ( id ) 13 | { 14 | } 15 | 16 | syscall_t::~syscall_t () 17 | { 18 | 19 | } 20 | 21 | void syscall_t::set_syscalL_id ( syscall_id_t id ) 22 | { 23 | syscall_id = id; 24 | } 25 | 26 | syscall_id_t syscall_t::get_syscall_id () const 27 | { 28 | return syscall_id; 29 | } 30 | 31 | void syscall_t::set_return_value ( int value ) 32 | { 33 | return_value = value; 34 | } 35 | 36 | int syscall_t::get_return_value () const 37 | { 38 | return return_value; 39 | } 40 | 41 | std::string syscall_t::to_string () 42 | { 43 | std::stringstream string_buf; 44 | string_buf << "id : " << static_cast < int > ( get_syscall_id () ); 45 | return string_buf.str (); 46 | } 47 | -------------------------------------------------------------------------------- /src/syscall/syscalls/syscall_t.h: -------------------------------------------------------------------------------- 1 | /** 2 | * syscall/syscalls/syscall_t.h 3 | * System call classes 4 | * Abstract base class syscall_t 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "../syscall_id.h" 10 | #include 11 | 12 | class syscall_t 13 | { 14 | public: 15 | syscall_t ( syscall_id_t id ); 16 | virtual ~syscall_t(); 17 | 18 | void set_syscalL_id ( syscall_id_t id ); 19 | syscall_id_t get_syscall_id () const; 20 | 21 | void set_return_value ( int value ); 22 | int get_return_value () const; 23 | 24 | virtual int process () = 0; 25 | 26 | virtual std::string to_string (); 27 | 28 | protected: 29 | syscall_id_t syscall_id; 30 | int return_value; 31 | }; 32 | -------------------------------------------------------------------------------- /src/syscall/syscalls/syscall_test.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * syscall/syscalls/syscall_test.h 3 | * System call classes 4 | * System call test 5 | */ 6 | 7 | #include "syscall_test.h" 8 | #include "../../logging/logging.h" 9 | 10 | syscall_test::syscall_test () 11 | : syscall_t ( syscall_id_t::SYSCALL_TEST ) 12 | { 13 | } 14 | 15 | int syscall_test::process () 16 | { 17 | logging::info << "Processing system call TEST" << logging::log_endl; 18 | return 31415926; 19 | } 20 | -------------------------------------------------------------------------------- /src/syscall/syscalls/syscall_test.h: -------------------------------------------------------------------------------- 1 | /** 2 | * syscall/syscalls/syscall_test.h 3 | * System call classes 4 | * System call test 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "syscall_t.h" 10 | 11 | class syscall_test : public syscall_t 12 | { 13 | public: 14 | syscall_test (); 15 | 16 | virtual int process (); 17 | }; 18 | -------------------------------------------------------------------------------- /src/utils/allocator/allocator.cpp: -------------------------------------------------------------------------------- 1 | #include "allocator.h" 2 | 3 | allocator::allocator() 4 | {} 5 | 6 | allocator::~allocator() 7 | {} 8 | 9 | allocator::allocator(size_t n) 10 | { 11 | set_size(n); 12 | } 13 | 14 | void allocator::set_size(size_t n) 15 | { 16 | this->n = n; 17 | } 18 | 19 | int allocator::get_size() 20 | { 21 | return n; 22 | } 23 | 24 | allocator::segment::segment() 25 | { 26 | start = 0, length = 0; 27 | } 28 | 29 | void allocator::free(const allocator::segment &seg) 30 | { 31 | this->free(seg.start, seg.length); 32 | } 33 | 34 | allocator::segment::segment(size_t start, size_t length) 35 | { 36 | this->start = start; 37 | this->length = length; 38 | } 39 | -------------------------------------------------------------------------------- /src/utils/allocator/allocator.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Interface for General Memory Allocator 3 | */ 4 | 5 | #pragma once 6 | #include 7 | #include 8 | 9 | class allocator { 10 | 11 | size_t n; 12 | 13 | public: 14 | 15 | allocator(); 16 | allocator(size_t); 17 | virtual ~allocator(); 18 | 19 | // set memory size 20 | void set_size(size_t n); 21 | int get_size(); 22 | 23 | // alloc continous memory with length @len 24 | // return start position 25 | virtual size_t malloc(size_t len) = 0; 26 | 27 | // free continous memory start frome @addr 28 | // with length @len 29 | // limited correction check for @len 30 | virtual void free(size_t addr, size_t len) = 0; 31 | 32 | struct segment { 33 | size_t start; 34 | size_t length; 35 | segment(); 36 | segment(size_t, size_t); 37 | }; 38 | 39 | void free(const segment &seg); 40 | }; 41 | 42 | -------------------------------------------------------------------------------- /src/utils/allocator/ffma.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * First Fit memory allocation 3 | */ 4 | 5 | #include "allocator.h" 6 | #include "ffma.h" 7 | #include 8 | #include 9 | #include "../panic.h" 10 | #include "../../logging/logging.h" 11 | 12 | using std::list; 13 | using logging::debug; 14 | using logging::log_endl; 15 | 16 | typedef allocator::segment segment; 17 | 18 | ffma::ffma(size_t n) 19 | { 20 | assert(n > 0); 21 | set_size(n); 22 | free_list.push_back(segment(0, n)); 23 | } 24 | 25 | /** 26 | * return -1 if failed 27 | */ 28 | size_t ffma::malloc(size_t len) 29 | { 30 | assert(len > 0); 31 | auto pos = free_list.end(); 32 | for (list::iterator i = free_list.begin(); 33 | i != free_list.end(); i++) { 34 | if (i->length >= len) { 35 | pos = i; 36 | break; 37 | } 38 | } 39 | if (pos == free_list.end()) { 40 | return -1; 41 | } 42 | if (pos->length == len) { 43 | size_t start = pos->start; 44 | free_list.erase(pos); 45 | return start; 46 | } else { 47 | size_t start = pos->start; 48 | segment remained(start + len, pos->length - len); 49 | auto nxt = pos; 50 | free_list.insert(++nxt, remained); 51 | free_list.erase(pos); 52 | logging::info << "malloc : " << start << logging::log_endl; 53 | return start; 54 | } 55 | } 56 | 57 | void ffma::merge(list::iterator pos) 58 | { 59 | if (pos != free_list.begin() 60 | && pos != free_list.end()) { 61 | auto bef = pos; 62 | bef--; 63 | if (bef->start + bef->length == pos->start) { 64 | bef->length += pos->length; 65 | free_list.erase(pos); 66 | } 67 | } 68 | } 69 | 70 | void ffma::free(size_t addr, size_t len) 71 | { 72 | assert(len > 0); 73 | auto pos = free_list.end(); 74 | segment seg(addr, len); 75 | for (auto i = free_list.begin(); i != free_list.end(); i++) 76 | if (i->start >= addr) { 77 | pos = i; 78 | break; 79 | } 80 | free_list.insert(pos, seg); 81 | merge(pos); 82 | } 83 | 84 | -------------------------------------------------------------------------------- /src/utils/allocator/ffma.h: -------------------------------------------------------------------------------- 1 | /* 2 | * First-Fit memory allocation 3 | */ 4 | #pragma once 5 | #include "allocator.h" 6 | #include 7 | #include 8 | #include 9 | 10 | class ffma : public allocator { 11 | 12 | std::list free_list; 13 | 14 | void merge(std::list::iterator seg); 15 | 16 | public: 17 | 18 | ffma(size_t n); 19 | virtual size_t malloc(size_t len); 20 | virtual void free(size_t addr, size_t len); 21 | }; 22 | 23 | -------------------------------------------------------------------------------- /src/utils/assert.h: -------------------------------------------------------------------------------- 1 | /** 2 | * utils/assert.h 3 | */ 4 | 5 | #pragma once 6 | 7 | #define kern_assert(x) if (!x) { \ 8 | printf("assertion fail : %s", #(x)); \ 9 | exit(1); 10 | -------------------------------------------------------------------------------- /src/utils/bus/bus.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | template 9 | class bus { 10 | public: 11 | 12 | T read(); 13 | void write(const T&); 14 | bool empty(); 15 | 16 | private: 17 | std::queue q; 18 | mutable std::mutex mutex_lock; 19 | }; 20 | 21 | template 22 | bool bus::empty() 23 | { 24 | std::lock_guard locker(mutex_lock); 25 | return q.empty(); 26 | } 27 | 28 | template 29 | T bus::read() 30 | { 31 | while (1) { 32 | mutex_lock.lock(); 33 | if (q.empty()) { 34 | mutex_lock.unlock(); 35 | std::this_thread::yield(); 36 | } else break; 37 | } 38 | T cur = q.front(); 39 | q.pop(); 40 | mutex_lock.unlock(); 41 | return cur; 42 | } 43 | 44 | template 45 | void bus::write(const T &data) 46 | { 47 | std::lock_guard locker(mutex_lock); 48 | q.push(data); 49 | } 50 | 51 | 52 | -------------------------------------------------------------------------------- /src/utils/check.cpp: -------------------------------------------------------------------------------- 1 | #include "check.h" 2 | #include "../mm/pmem_info.h" 3 | #include "../env/env.h" 4 | 5 | bool add_check(size_t a, size_t b) 6 | { 7 | return b <= (size_t)(-1) - a; 8 | } 9 | 10 | bool mul_check(size_t a, size_t b) 11 | { 12 | return a == 0 || (size_t)(-1) / a >= b; 13 | } 14 | 15 | void round2page(size_t &size) 16 | { 17 | size = (size / PAGE_SIZE 18 | + (size % PAGE_SIZE != 0)) * PAGE_SIZE; 19 | } 20 | -------------------------------------------------------------------------------- /src/utils/check.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | bool add_check(size_t a, size_t b); 7 | bool mul_check(size_t a, size_t b); 8 | void round2page(size_t &size); 9 | -------------------------------------------------------------------------------- /src/utils/pagerepl/fifo.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * pagerepl/fifo.h 3 | * fifo replacement algorithm 4 | */ 5 | 6 | 7 | #include "fifo.h" 8 | #include 9 | 10 | fifo_repl::fifo_repl(size_t page_num) 11 | { 12 | set_page_num(page_num); 13 | } 14 | 15 | fifo_repl::~fifo_repl() 16 | { 17 | 18 | } 19 | 20 | void fifo_repl::page_swap_in(size_t id) 21 | { 22 | assert(!full()); 23 | que.push(id); 24 | } 25 | 26 | size_t fifo_repl::page_swap_out() 27 | { 28 | assert(!que.empty()); 29 | size_t pg = que.front(); 30 | que.pop(); 31 | return pg; 32 | } 33 | 34 | -------------------------------------------------------------------------------- /src/utils/pagerepl/fifo.h: -------------------------------------------------------------------------------- 1 | /** 2 | * pagerepl/fifo.h 3 | * fifo replacement algorithm 4 | */ 5 | #pragma once 6 | #include "pagerepl.h" 7 | #include 8 | 9 | class fifo_repl : public page_repl { 10 | 11 | public: 12 | 13 | fifo_repl(size_t page_num); 14 | virtual ~fifo_repl(); 15 | virtual void page_swap_in(size_t id); 16 | virtual size_t page_swap_out(); 17 | 18 | private: 19 | 20 | std::queue que; 21 | }; 22 | 23 | -------------------------------------------------------------------------------- /src/utils/pagerepl/pagerepl.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * utils/pagerepl/pagerepl.cpp 3 | * page replacement algorithm's interface 4 | */ 5 | 6 | #include "pagerepl.h" 7 | #include 8 | 9 | page_repl::page_repl() 10 | { 11 | cur_num = page_num = 0; 12 | } 13 | 14 | page_repl::~page_repl() 15 | { 16 | 17 | } 18 | 19 | bool page_repl::full() 20 | { 21 | return cur_num == page_num; 22 | } 23 | 24 | void page_repl::swap_in(size_t id) 25 | { 26 | assert(!full()); 27 | cur_num++; 28 | page_swap_in(id); 29 | } 30 | 31 | size_t page_repl::swap_out() 32 | { 33 | size_t return_value = page_swap_out(); 34 | cur_num--; 35 | return return_value; 36 | } 37 | 38 | size_t page_repl::get_page_num() const 39 | { 40 | return page_num; 41 | } 42 | 43 | void page_repl::set_page_num(size_t page_num) 44 | { 45 | this->page_num = page_num; 46 | } 47 | 48 | -------------------------------------------------------------------------------- /src/utils/pagerepl/pagerepl.h: -------------------------------------------------------------------------------- 1 | /** 2 | * utils/pagerepl/pagerepl.h 3 | * page replacement algorithm's interface 4 | */ 5 | #pragma once 6 | #include 7 | #include 8 | 9 | class page_repl { 10 | public: 11 | 12 | page_repl(); 13 | virtual ~page_repl(); 14 | 15 | /** 16 | * swap in page @id 17 | */ 18 | virtual void page_swap_in(size_t id) = 0; 19 | 20 | /** 21 | * swap out a page 22 | * @return : the page to swap out 23 | */ 24 | virtual size_t page_swap_out() = 0; 25 | 26 | bool full(); 27 | void swap_in(size_t id); 28 | size_t swap_out(); 29 | 30 | size_t get_page_num() const; 31 | void set_page_num(size_t page_num); 32 | 33 | private: 34 | size_t cur_num; 35 | size_t page_num; 36 | }; 37 | -------------------------------------------------------------------------------- /src/utils/panic.cpp: -------------------------------------------------------------------------------- 1 | #include "panic.h" 2 | #include 3 | #include 4 | using std::string; 5 | 6 | void panic(const string &str) 7 | { 8 | logging::debug << "System Panic. info = " << str << logging::log_endl; 9 | exit(1); 10 | } 11 | 12 | void panic() 13 | { 14 | panic("null"); 15 | } 16 | -------------------------------------------------------------------------------- /src/utils/panic.h: -------------------------------------------------------------------------------- 1 | /* 2 | * System panic 3 | */ 4 | #pragma once 5 | #include "../logging/logging.h" 6 | #include 7 | 8 | void panic(const std::string &panic_info); 9 | void panic(); 10 | 11 | -------------------------------------------------------------------------------- /src/utils/safe_condition_variable/safe_condition_variable.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tqyaaaaang/Hyper-OS/7fe501e2173425c7d08b5457c08ee8ebf5261ba0/src/utils/safe_condition_variable/safe_condition_variable.cpp -------------------------------------------------------------------------------- /src/utils/safe_condition_variable/safe_condition_variable.h: -------------------------------------------------------------------------------- 1 | /** 2 | * utils/safe_condition_variable/safe_condition_variable.h 3 | * Safe condition variable 4 | * which can save notifications if no threads are waiting 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | class safe_condition_variable 14 | { 15 | public: 16 | void notify () 17 | { 18 | std::unique_lock < std::mutex > lock ( mut ); 19 | --count; 20 | if ( count >= 0 ) { // There are threads waiting 21 | cv.notify_one (); 22 | } 23 | } 24 | 25 | void wait () 26 | { 27 | std::unique_lock < std::mutex > lock ( mut ); 28 | ++count; 29 | if ( count > 0 ) { // There aren't any spare notifications 30 | cv.wait ( lock ); 31 | } 32 | } 33 | 34 | private: 35 | std::mutex mut; // lock 36 | std::condition_variable cv; // condition variable 37 | int count; // waiting count of the condition variable, < 0 if there are spare notifications, > 0 if there are waiting threads 38 | }; 39 | -------------------------------------------------------------------------------- /src/utils/thread_safe_queue/thread_safe_queue.h: -------------------------------------------------------------------------------- 1 | /** 2 | * utils/thread_safe_queue/thread_safe_queue.h 3 | * thread-safe queue 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | template < typename T > 13 | class thread_safe_queue 14 | { 15 | public: 16 | void push_back ( T t ); 17 | void push_front ( T t ); 18 | T pop_back (); 19 | T pop_front (); 20 | 21 | bool empty (); 22 | 23 | void clear (); 24 | 25 | private: 26 | std::deque < T > q; 27 | mutable std::mutex mut; 28 | std::condition_variable cv; 29 | }; 30 | 31 | 32 | 33 | template 34 | void thread_safe_queue::push_back ( T t ) 35 | { 36 | std::unique_lock < std::mutex > lock ( mut ); 37 | q.push_back ( t ); 38 | cv.notify_one (); 39 | } 40 | 41 | template 42 | void thread_safe_queue::push_front ( T t ) 43 | { 44 | std::unique_lock < std::mutex > lock ( mut ); 45 | q.push_front ( t ); 46 | cv.notify_one (); 47 | } 48 | 49 | template 50 | T thread_safe_queue::pop_back () 51 | { 52 | std::unique_lock < std::mutex > lock ( mut ); 53 | while ( q.empty () ) { 54 | cv.wait ( lock ); 55 | } 56 | T return_value = q.back (); 57 | q.pop_back (); 58 | return return_value; 59 | } 60 | 61 | template 62 | T thread_safe_queue::pop_front () 63 | { 64 | std::unique_lock < std::mutex > lock ( mut ); 65 | while ( q.empty () ) { 66 | cv.wait ( lock ); 67 | } 68 | T return_value = q.front (); 69 | q.pop_front (); 70 | return return_value; 71 | } 72 | 73 | template 74 | bool thread_safe_queue::empty () 75 | { 76 | std::unique_lock < std::mutex > lock ( mut ); 77 | return q.empty (); 78 | } 79 | 80 | template 81 | inline void thread_safe_queue::clear () 82 | { 83 | std::unique_lock < std::mutex > lock ( mut ); 84 | cv.notify_all (); 85 | q.clear (); 86 | } 87 | -------------------------------------------------------------------------------- /test/test.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * test/test.cpp 3 | * Unittest entry 4 | */ 5 | 6 | #include "test.h" 7 | #include "test_message.h" 8 | #include "test_interrupt.h" 9 | #include "test_syscall.h" 10 | #include "test_devices.h" 11 | #include "test_pmm.h" 12 | #include "test_pm.h" 13 | #include "test_ffma.h" 14 | #include "test_process.h" 15 | #include "test_multiproc.h" 16 | #include "test_program_manager.h" 17 | #include "test_heap.h" 18 | #include "../src/env/env.h" 19 | #include "../src/mm/pmm.h" 20 | #include "../src/logging/logging.h" 21 | #include "../src/utils/allocator/ffma.h" 22 | #include "../src/program/program_manager.h" 23 | 24 | void test() 25 | { 26 | if ( TEST ) { 27 | logging::info << "Testing the system" << logging::log_endl; 28 | 29 | test_message (); 30 | 31 | test_interrupt (); 32 | test_syscall (); 33 | 34 | test_devices (); 35 | 36 | test_pm (); 37 | test_pmm (); 38 | test_ffma (); 39 | test_program_manager (); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /test/test.h: -------------------------------------------------------------------------------- 1 | /** 2 | * test/test.h 3 | * Unittest entry 4 | */ 5 | 6 | #pragma once 7 | 8 | void test (); 9 | -------------------------------------------------------------------------------- /test/test_devices.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * test/test_devices.cpp 3 | * Test devices 4 | */ 5 | 6 | #include "test_devices.h" 7 | #include 8 | #include "../src/logging/logging.h" 9 | #include "../dev/device_list.h" 10 | 11 | void test_devices () 12 | { 13 | logging::debug << "Testing devices" << logging::log_endl; 14 | 15 | test_output_device (); 16 | } 17 | 18 | void test_output_device () 19 | { 20 | logging::debug << "Testing output device" << logging::log_endl; 21 | 22 | std::string str = "output device ok.\n"; 23 | for ( auto x : str ) { 24 | device_desc::standard_output->write ( x ); 25 | } 26 | device_desc::standard_output->write ( str ); 27 | 28 | // device_desc::standard_output->write ( "Please input a character: " ); 29 | // char ch = device_desc::standard_input->read (); 30 | // device_desc::standard_output->write ( "input read : " ); 31 | // device_desc::standard_output->write ( ch ); 32 | // device_desc::standard_output->write ( '\n' ); 33 | 34 | logging::debug << "Test on output device succeeded" << logging::log_endl; 35 | } -------------------------------------------------------------------------------- /test/test_devices.h: -------------------------------------------------------------------------------- 1 | /** 2 | * test/test_devices.h 3 | * Test devices 4 | */ 5 | 6 | #pragma once 7 | 8 | void test_devices (); 9 | 10 | void test_output_device (); 11 | -------------------------------------------------------------------------------- /test/test_ffma.cpp: -------------------------------------------------------------------------------- 1 | #include "test_ffma.h" 2 | #include "../src/utils/allocator/ffma.h" 3 | #include "../src/logging/logging.h" 4 | #include 5 | 6 | using logging::debug; 7 | using logging::log_endl; 8 | typedef allocator::segment segment; 9 | 10 | void test_ffma() 11 | { 12 | allocator *ffma_allocator = new ffma(100); 13 | segment segs[10]; 14 | for (int i = 0; i < 10; i++) { 15 | segs[i] = segment(ffma_allocator->malloc(i + 1), i+1); 16 | assert((int)segs[i].start == i*(i+1)/2); 17 | } 18 | int ans[] = {63, 54, 46, 6, 38, 15, 21, 28, 36, 45}; 19 | for (int i = 9; i >= 0; i--) { 20 | ffma_allocator->free(segs[i]); 21 | segs[i] = segment(ffma_allocator->malloc(10 - i), 10 - i); 22 | assert((int)segs[i].start == ans[i]); 23 | } 24 | delete ffma_allocator; 25 | debug << "ffma check ok." << log_endl; 26 | } 27 | -------------------------------------------------------------------------------- /test/test_ffma.h: -------------------------------------------------------------------------------- 1 | /* test ffma algorithm*/ 2 | 3 | void test_ffma(); 4 | -------------------------------------------------------------------------------- /test/test_heap.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * test/test.h 3 | * test heap 4 | */ 5 | 6 | #include "test_multiproc.h" 7 | #include "../src/program/program.h" 8 | #include "../src/process/process.h" 9 | #include "../src/logging/logging.h" 10 | #include "../src/schedule/schedule.h" 11 | #include "../src/status/status.h" 12 | #include "../src/core/core.h" 13 | #include 14 | #include 15 | 16 | using logging::info; 17 | using logging::log_endl; 18 | using std::cout; 19 | using std::endl; 20 | 21 | class merge_sort : public program { 22 | private: 23 | 24 | handle arr; 25 | int n; 26 | 27 | void merge_sort_fun(handle arr, handle L, handle R) 28 | { 29 | if (L >= R) { 30 | return; 31 | } else { 32 | handle mid = 0; 33 | handle tmp = alloc_heap(R - L + 1); 34 | 35 | mid = (L+R)>>1; 36 | merge_sort_fun(arr, (int)L, (int)mid); 37 | merge_sort_fun(arr, (int)mid+1, (int)R); 38 | handle Lp = (int)L, Rp = (int)mid+1; 39 | handle top = 0; 40 | while (Lp <= mid && Rp <= R) { 41 | if (arr[Lp] <= arr[Rp]) { 42 | tmp[top] = (int)(arr[Lp]); 43 | Lp = Lp + 1; 44 | top = top + 1; 45 | } else { 46 | tmp[top] = (int)(arr[Rp]); 47 | Rp = Rp + 1; 48 | top = top + 1; 49 | } 50 | } 51 | while (Lp <= mid) { 52 | tmp[top] = (int)(arr[Lp]); 53 | Lp = Lp + 1; 54 | top = top + 1; 55 | } 56 | while (Rp <= R) { 57 | tmp[top] = (int)(arr[Rp]); 58 | Rp = Rp + 1; 59 | top = top + 1; 60 | } 61 | for (handle i = 0; i < top; i = i + 1) { 62 | arr[L + i] = (int)(tmp[i]); 63 | } 64 | free_heap(tmp); 65 | } 66 | } 67 | 68 | public: 69 | 70 | merge_sort() 71 | { 72 | build(); 73 | } 74 | 75 | virtual void static_init() 76 | { 77 | set_name("merge_sort"); 78 | n = 10; 79 | arr = alloc_static(n); 80 | size_t a = 31, b = 19260817, x = 0; 81 | for (int i = 0; i < n; i++) { 82 | info << (int)x << log_endl; 83 | arr[i].modify_in_compile(x); 84 | x = a * x + b; 85 | } 86 | } 87 | 88 | virtual void main() 89 | { 90 | cout << "merge_sort start." << endl; 91 | merge_sort_fun(arr, 0, n-1); 92 | for (handle i = 0; i < n; i = i + 1) { 93 | info << (int)arr[i] << log_endl; 94 | } 95 | cout << "merge_sort ok." << endl; 96 | } 97 | }; 98 | 99 | void test_heap() 100 | { 101 | program *prog = new merge_sort; 102 | size_t pid = proc_create_process(); 103 | proc_exec_program(pid, prog); 104 | schedule(0); 105 | while (1) { 106 | std::this_thread::yield(); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /test/test_heap.h: -------------------------------------------------------------------------------- 1 | /** 2 | * test/test.h 3 | * test heap 4 | */ 5 | #pragma once 6 | 7 | void test_heap(); 8 | -------------------------------------------------------------------------------- /test/test_interrupt.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * test/test_interrupt.h 3 | * Test interrupt 4 | */ 5 | 6 | #include "test_interrupt.h" 7 | 8 | #include 9 | #include "../src/logging/logging.h" 10 | #include "../src/core/core.h" 11 | #include "../src/status/status.h" 12 | #include "../src/interrupt/interrupt.h" 13 | #include "../src/interrupt/interrupts/internal_test.h" 14 | #include "../src/interrupt/interrupts/double_internal_test.h" 15 | 16 | void test_interrupt () 17 | { 18 | logging::debug << "Testing interrupts" << logging::log_endl; 19 | 20 | status.get_core ()->acquire (); 21 | test_internal_interrupt (); 22 | status.get_core ()->release (); 23 | } 24 | 25 | void test_internal_interrupt () 26 | { 27 | logging::debug << "Testing internal interrupts" << logging::log_endl; 28 | int return_value; 29 | 30 | return_value = interrupt ( new internal_test_interrupt () ); 31 | logging::info << "Test on INTERNAL TEST interrupt succeeded, return value : " << return_value << logging::log_endl; 32 | 33 | return_value = interrupt ( new double_internal_test_interrupt () ); 34 | logging::info << "Test on DOUBLE INTERNAL TEST interrupt succeeded, return value : " << return_value << logging::log_endl; 35 | } 36 | -------------------------------------------------------------------------------- /test/test_interrupt.h: -------------------------------------------------------------------------------- 1 | /** 2 | * test/test_interrupt.h 3 | * Test interrupt 4 | */ 5 | 6 | #pragma once 7 | 8 | void test_interrupt (); 9 | 10 | void test_internal_interrupt (); 11 | -------------------------------------------------------------------------------- /test/test_message.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * test/test_message.h 3 | * Test message service 4 | */ 5 | 6 | #include "test_message.h" 7 | #include "../src/message/message.h" 8 | #include "../src/logging/logging.h" 9 | 10 | void test_message () 11 | { 12 | logging::debug << "Testing message service" << logging::log_endl; 13 | 14 | message::test ( message::wrap_core_info ( "kern test" ) ) << "This is a test message" << message::msg_endl; 15 | } 16 | -------------------------------------------------------------------------------- /test/test_message.h: -------------------------------------------------------------------------------- 1 | /** 2 | * test/test_message.h 3 | * Test message service 4 | */ 5 | 6 | #pragma once 7 | 8 | void test_message (); 9 | -------------------------------------------------------------------------------- /test/test_multiproc.cpp: -------------------------------------------------------------------------------- 1 | #include "test_multiproc.h" 2 | #include "../src/program/program.h" 3 | #include "../src/process/process.h" 4 | #include "../src/logging/logging.h" 5 | #include "../src/schedule/schedule.h" 6 | #include "../src/status/status.h" 7 | #include "../src/core/core.h" 8 | #include 9 | #include 10 | 11 | using logging::info; 12 | using logging::log_endl; 13 | using std::cout; 14 | using std::endl; 15 | 16 | static int id = 0; 17 | 18 | class tick_prog : public program { 19 | private: 20 | handle tick; 21 | handle str; 22 | int this_id; 23 | 24 | public: 25 | 26 | tick_prog() 27 | { 28 | this_id = id++; 29 | info << "build " << id << log_endl; 30 | build(); 31 | } 32 | 33 | virtual void static_init() 34 | { 35 | set_name("tick-prog"); 36 | tick = alloc_bss(); 37 | str = alloc_static(12); 38 | char s[] = "hello world"; 39 | for (int i = 0; i < 11; i++) 40 | str[i].modify_in_compile(s[i]); 41 | } 42 | 43 | virtual void main() 44 | { 45 | cout << this_id << " start." << endl; 46 | for (int i = 0; i < 11; i++) 47 | cout << str[i]; 48 | cout << endl; 49 | while (tick < 100000) { 50 | tick = tick + 1; 51 | if (tick % 10000 == 0) { 52 | handle st = (int)tick; 53 | st = st + 1; 54 | // st is in stack 55 | int tmp = st; 56 | cout << "tick " << tmp << " from " << this_id << endl; 57 | } 58 | } 59 | cout << "tick " << this_id << " finished." << endl; 60 | } 61 | }; 62 | 63 | void test_multiproc() 64 | { 65 | info << "start multi process test" << log_endl; 66 | program *prox[10]; 67 | for (int i = 0; i < 10; i++) 68 | prox[i] = new tick_prog; 69 | size_t x[10]; 70 | for (int i = 0; i < 10; i++) { 71 | info << "cr " << i << log_endl; 72 | x[i] = proc_create_process(); 73 | } 74 | for (int i = 0; i < 10; i++) { 75 | proc_exec_program(x[i], prox[i]); 76 | } 77 | schedule(0); 78 | while (1) { 79 | std::this_thread::yield(); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /test/test_multiproc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void test_multiproc(); 4 | -------------------------------------------------------------------------------- /test/test_pm.cpp: -------------------------------------------------------------------------------- 1 | #include "test_pm.h" 2 | #include "../src/mm/pmm.h" 3 | #include "../src/mm/pmem.h" 4 | #include "../src/logging/logging.h" 5 | #include 6 | 7 | using logging::debug; 8 | using logging::log_endl; 9 | using pm::read; 10 | using pm::write; 11 | 12 | void test_pm() 13 | { 14 | write(10, 1); 15 | assert(read(10) == 1); 16 | write(1 << 20, 127); 17 | write(1 << 29 | 1, 2); 18 | assert(read(1 << 20) == 127); 19 | assert(read(1 << 29 | 1) == 2); 20 | write(10, 0); 21 | write(1 << 20, 0); 22 | write(1 << 29 | 1, 0); 23 | debug << "pm check ok." << log_endl; 24 | } 25 | -------------------------------------------------------------------------------- /test/test_pm.h: -------------------------------------------------------------------------------- 1 | /* test memory */ 2 | 3 | void test_pm(); 4 | -------------------------------------------------------------------------------- /test/test_pmm.cpp: -------------------------------------------------------------------------------- 1 | #include "test_pmm.h" 2 | #include "../src/mm/pmm.h" 3 | #include "../src/mm/pmem.h" 4 | #include "../src/logging/logging.h" 5 | #include 6 | 7 | using logging::debug; 8 | using logging::log_endl; 9 | 10 | void test_pmm() 11 | { 12 | page_frame* pg[8]; 13 | for (int i = 0; i < 8; i++) { 14 | pg[i] = alloc_pages((i + 1) * 10); 15 | pg[i]->ref(); 16 | } 17 | for (int i = 0; i < 8; i++) 18 | for (int j = i + 1; j < 8; j++) { 19 | assert(page2id(pg[i]) + pg[i]->length <= page2id(pg[j]) 20 | || page2id(pg[j]) + pg[j]->length <= page2id(pg[i])); 21 | } 22 | for (int i = 0; i < 8; i++) 23 | free_pages(pg[i]); 24 | debug << "pmm check ok." << log_endl; 25 | } 26 | -------------------------------------------------------------------------------- /test/test_pmm.h: -------------------------------------------------------------------------------- 1 | /* test pmm & memory */ 2 | 3 | void test_pmm(); 4 | -------------------------------------------------------------------------------- /test/test_process.cpp: -------------------------------------------------------------------------------- 1 | #include "test_process.h" 2 | #include "../src/program/program.h" 3 | #include "../src/process/process.h" 4 | #include "../src/logging/logging.h" 5 | #include "../src/schedule/schedule.h" 6 | #include "../src/status/status.h" 7 | #include "../src/core/core.h" 8 | #include 9 | 10 | using logging::info; 11 | using logging::log_endl; 12 | 13 | class hello_world : public program { 14 | private: 15 | handle str[12]; 16 | handle ptr; 17 | 18 | public: 19 | 20 | hello_world() 21 | { 22 | build(); 23 | } 24 | 25 | virtual void static_init() 26 | { 27 | set_name("hello, world"); 28 | char s[13] = "hello, world"; 29 | for (size_t i = 0; i < 12; i++) { 30 | str[i].alias(alloc_static()); 31 | str[i].modify_in_compile(s[i]); 32 | } 33 | ptr.alias(alloc_bss()); 34 | info << "STATIC FINISH " << get_name() << log_endl; 35 | } 36 | 37 | virtual void main() 38 | { 39 | info << "Running on Core : " << status.get_core()->get_core_id() << log_endl; 40 | for (size_t i = 0; i < 12; i++) 41 | info << (char)str[i]; 42 | info << log_endl; 43 | assert(ptr == 0); 44 | info << (int)ptr << log_endl; 45 | ptr = 10; 46 | for (size_t i = 0; i < 12; i++) 47 | info << (char)str[i]; 48 | info << log_endl; 49 | info << (int)ptr << log_endl; 50 | while (1) { 51 | ptr = ptr + 1; 52 | } 53 | } 54 | 55 | }; 56 | 57 | void test_process() 58 | { 59 | info << "start test process." << log_endl; 60 | program *prog = new hello_world; 61 | size_t pid = proc_create_process(); 62 | proc_exec_program(pid, prog); 63 | // set to runable 64 | schedule(0); 65 | // run! 66 | info << "process " << pid << " may start." << log_endl; 67 | while (1); 68 | } 69 | -------------------------------------------------------------------------------- /test/test_process.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void test_process(); 4 | -------------------------------------------------------------------------------- /test/test_program_manager.cpp: -------------------------------------------------------------------------------- 1 | #include "test_program_manager.h" 2 | #include "../src/program/program.h" 3 | #include "../src/process/process.h" 4 | #include "../src/program/program_manager.h" 5 | #include "../src/program/lib.h" 6 | #include "../src/logging/logging.h" 7 | #include "../src/program/sys_t.h" 8 | #include 9 | #include 10 | 11 | using std::string; 12 | 13 | class prog_a : public program { 14 | public: 15 | 16 | virtual ~prog_a() 17 | { } 18 | 19 | virtual void static_init() 20 | { 21 | set_name("prog_a"); 22 | name = alloc_static(20); 23 | char str[] = "prog b"; 24 | for (size_t i = 0, size = 6; i < size; i++) 25 | name[i].modify_in_compile(str[i]); 26 | } 27 | 28 | virtual void main() 29 | { 30 | hos_std->println("prog a start."); 31 | int pid = sys->create_process(); 32 | logging::info << "pid : " << pid << logging::log_endl; 33 | hos_std->println(name); 34 | sys->exec_program(pid, name); 35 | sys->wait(pid); 36 | logging::info << "prog b finished." << logging::log_endl; 37 | hos_std->println("prog b finish."); 38 | pid = sys->create_process(); 39 | sys->exec_program(pid, name); 40 | sys->wait(pid); 41 | hos_std->println("prog b finish."); 42 | } 43 | 44 | private: 45 | 46 | handle name; 47 | }; 48 | 49 | class prog_b : public program { 50 | public: 51 | 52 | virtual ~prog_b() 53 | { } 54 | 55 | virtual void static_init() 56 | { 57 | set_name("prog_b"); 58 | } 59 | 60 | virtual void main() 61 | { 62 | logging::info << "prog b start." << logging::log_endl; 63 | hos_std->println("prog b start."); 64 | } 65 | }; 66 | 67 | program* gen_a() 68 | { return new prog_a; } 69 | 70 | program* gen_b() 71 | { return new prog_b; } 72 | 73 | void test_program_manager() 74 | { 75 | register_program("prog a", gen_a); 76 | register_program("prog b", gen_b); 77 | int id = proc_create_process(); 78 | proc_exec_program(id, get_program("prog a")); 79 | while (1) { 80 | std::this_thread::yield(); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /test/test_program_manager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void test_program_manager(); 4 | -------------------------------------------------------------------------------- /test/test_syscall.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * test/test_syscall.cpp 3 | * Test system call 4 | */ 5 | 6 | #include "test_syscall.h" 7 | 8 | #include "../src/logging/logging.h" 9 | #include "../src/core/core.h" 10 | #include "../src/status/status.h" 11 | #include "../src/syscall/syscall.h" 12 | #include "../src/syscall/syscalls/syscall_test.h" 13 | #include "../src/syscall/syscalls/sys_read.h" 14 | #include "../src/syscall/syscalls/sys_write.h" 15 | #include "../dev/device_list.h" 16 | 17 | void test_syscall () 18 | { 19 | logging::debug << "Testing system calls" << logging::log_endl; 20 | int return_value; 21 | 22 | status.get_core ()->acquire (); 23 | 24 | { 25 | syscall_test current_syscall; 26 | return_value = syscall ( ¤t_syscall ); 27 | logging::info << "Test on SYSCALL TEST system call succeeded, interrupt return value : " << return_value << ", syscall return value : " << current_syscall.get_return_value () << logging::log_endl; 28 | } 29 | 30 | //{ 31 | // sys_read read_syscall ( device_desc::standard_input ); 32 | // return_value = syscall ( &read_syscall ); 33 | // logging::info << "Test on SYSCALL READ succeeded, interrupt return value : " << return_value << ", syscall return value : " << read_syscall.get_return_value () << logging::log_endl; 34 | 35 | // sys_write write_syscall ( device_desc::standard_output, read_syscall.get_return_value () ); 36 | // return_value = syscall ( &write_syscall ); 37 | // logging::info << "Test on SYSCALL WRITE succeeded, interrupt return value : " << return_value << ", syscall return value : " << write_syscall.get_return_value () << logging::log_endl; 38 | //} 39 | 40 | status.get_core ()->release (); 41 | } 42 | -------------------------------------------------------------------------------- /test/test_syscall.h: -------------------------------------------------------------------------------- 1 | /** 2 | * test/test_syscall.h 3 | * Test system call 4 | */ 5 | 6 | #pragma once 7 | 8 | void test_syscall (); 9 | -------------------------------------------------------------------------------- /user/demo_interrupt/demo_interrupt.cpp: -------------------------------------------------------------------------------- 1 | #include "demo_interrupt.h" 2 | #include "../../src/program/program_manager.h" 3 | #include "../../src/message/message.h" 4 | #include "../../src/interrupt/interrupt.h" 5 | #include "../../src/interrupt/interrupts/double_internal_test.h" 6 | #include 7 | 8 | static program* gen() 9 | { 10 | return new demo_interrupt; 11 | } 12 | 13 | void register_demo_syscall() 14 | { 15 | register_program("demo-interrupt", gen); 16 | } 17 | 18 | demo_interrupt::demo_interrupt() 19 | { } 20 | 21 | demo_interrupt::~demo_interrupt() 22 | { } 23 | 24 | void demo_interrupt::static_init() 25 | { 26 | set_name("demo-interrupt"); 27 | hello = alloc_static(2); 28 | hello.modify_in_compile('~'); 29 | hello[1].modify_in_compile('\0'); 30 | } 31 | 32 | void demo_interrupt::main() 33 | { 34 | message::set_interrupt_message(true); 35 | message::set_process_message(false); 36 | message::set_memory_message(false); 37 | 38 | message::interrupt ( "user demo_interrupt" ) << "Sending interrupt DOUBLE_INTERRUPT_TEST" << message::msg_endl; 39 | int return_value = interrupt ( new double_internal_test_interrupt () ); 40 | message::interrupt ( "user demo_interrupt" ) << "Interrupt DOUBLE_INTERRUPT_TEST return value : " << return_value << message::msg_endl; 41 | 42 | message::interrupt ( "user demo_interrupt" ) << "Sending syscalls to print \"~\\n\"" << message::msg_endl; 43 | hos_std->println(hello); 44 | message::interrupt ( "user demo_interrupt" ) << "Print completed" << message::msg_endl; 45 | 46 | message::interrupt ( "user demo_interrupt" ) << "Waiting for clock interrupt" << message::msg_endl; 47 | handle < int > timer = alloc_stack < int > (); 48 | handle < int > answer = alloc_stack < int > (); 49 | answer = 0; 50 | for ( timer = 0; timer < 10; timer = timer + 1 ) { 51 | answer = answer + ( ( timer >> 3 ) ^ ( timer << 7 ) ); 52 | } 53 | message::interrupt ( "user demo_interrupt" ) << "Waiting completed" << message::msg_endl; 54 | 55 | message::set_interrupt_message(false); 56 | message::set_process_message(false); 57 | message::set_memory_message(false); 58 | } 59 | -------------------------------------------------------------------------------- /user/demo_interrupt/demo_interrupt.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../hyperstd.h" 4 | #include "../hyperlib.h" 5 | 6 | class demo_interrupt : public program { 7 | public: 8 | 9 | demo_interrupt(); 10 | virtual ~demo_interrupt(); 11 | virtual void static_init(); 12 | virtual void main(); 13 | 14 | private: 15 | 16 | handle hello; 17 | }; 18 | 19 | void register_demo_syscall(); 20 | -------------------------------------------------------------------------------- /user/demo_pagefault/demo_pagefault.cpp: -------------------------------------------------------------------------------- 1 | #include "demo_pagefault.h" 2 | #include "../../src/program/program_manager.h" 3 | #include "../../src/message/message.h" 4 | 5 | static program* gen() 6 | { 7 | return new demo_pagefault; 8 | } 9 | 10 | void register_demo_pagefault() 11 | { 12 | register_program("demo-pf", gen); 13 | } 14 | 15 | demo_pagefault::demo_pagefault() 16 | { } 17 | 18 | demo_pagefault::~demo_pagefault() 19 | { } 20 | 21 | void demo_pagefault::static_init() 22 | { 23 | set_name("demo_pagefault"); 24 | } 25 | 26 | void demo_pagefault::main() 27 | { 28 | message::set_interrupt_message(false); 29 | message::set_process_message(false); 30 | message::set_memory_message(true); 31 | handle variable_on_stack = '1'; 32 | message::set_interrupt_message(false); 33 | message::set_process_message(false); 34 | message::set_memory_message(false); 35 | } 36 | -------------------------------------------------------------------------------- /user/demo_pagefault/demo_pagefault.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../hyperstd.h" 3 | #include "../hyperlib.h" 4 | 5 | class demo_pagefault : public program { 6 | public: 7 | 8 | demo_pagefault(); 9 | virtual ~demo_pagefault(); 10 | virtual void main(); 11 | virtual void static_init(); 12 | 13 | private: 14 | 15 | 16 | }; 17 | 18 | void register_demo_pagefault(); 19 | -------------------------------------------------------------------------------- /user/demo_process/demo_process.cpp: -------------------------------------------------------------------------------- 1 | #include "demo_process.h" 2 | #include "../../src/program/program_manager.h" 3 | #include "../../src/message/message.h" 4 | #include 5 | 6 | static program* gen() 7 | { return new demo_process; } 8 | 9 | void register_demo_process() 10 | { 11 | register_program("demo-proc", gen); 12 | } 13 | 14 | demo_process::demo_process() 15 | { } 16 | 17 | demo_process::~demo_process() 18 | { } 19 | 20 | void demo_process::static_init() 21 | { 22 | set_name("demo-proc"); 23 | const char str[] = "elephant"; 24 | size_t size = strlen(str) + 1; 25 | name = alloc_static(size); 26 | for (size_t i = 0; i < size; i++) 27 | name[i].modify_in_compile(str[i]); 28 | } 29 | 30 | void demo_process::main() 31 | { 32 | message::set_interrupt_message(false); 33 | message::set_process_message(true); 34 | message::set_memory_message(false); 35 | 36 | handle pid = sys->create_process(); 37 | sys->exec_program(pid, name); 38 | sys->wait(pid); 39 | 40 | hos_std->println(name); 41 | message::set_interrupt_message(false); 42 | message::set_process_message(false); 43 | message::set_memory_message(false); 44 | } 45 | -------------------------------------------------------------------------------- /user/demo_process/demo_process.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../hyperstd.h" 3 | #include "../hyperlib.h" 4 | 5 | class demo_process : public program { 6 | public: 7 | 8 | demo_process(); 9 | virtual ~demo_process(); 10 | virtual void main(); 11 | virtual void static_init(); 12 | 13 | private: 14 | 15 | handle name; 16 | }; 17 | 18 | void register_demo_process(); 19 | -------------------------------------------------------------------------------- /user/elephant/elephant.cpp: -------------------------------------------------------------------------------- 1 | #include "elephant.h" 2 | #include "../../src/program/program_manager.h" 3 | #include "elephant_boom.h" 4 | #include 5 | 6 | static program* gen() 7 | { 8 | return new elephant; 9 | } 10 | 11 | static program* gen_boom() 12 | { 13 | return new elephant_boom; 14 | } 15 | 16 | void register_elephant() 17 | { 18 | register_program("elephant", gen); 19 | register_program("elephant-boom", gen_boom); 20 | } 21 | 22 | elephant::elephant() 23 | { } 24 | 25 | elephant::~elephant() 26 | { } 27 | 28 | void elephant::static_init() 29 | { 30 | set_name("elephant"); 31 | const char str[] = 32 | "--------------------------------------------------------------------\n" 33 | " // / / // ) ) // ) \n" 34 | " //___ / / ___ ___ __ // / / (( \n" 35 | " / ___ // / / // ) ) //___) ) // ) ) // / / \\ \n" 36 | " // / ((___/ / //___/ / // // // / / )) \n" 37 | "// / / / / // ((____ // ((___/ / ((___ // \n" 38 | "--------------------------------------------------------------------\0"; 39 | size_t size = strlen(str) + 1; 40 | graph = alloc_static(size); 41 | for (size_t i = 0; i < size; i++) 42 | graph[i].modify_in_compile(str[i]); 43 | const char ele[] = "elephant\0"; 44 | size = strlen(ele) + 1; 45 | elep = alloc_static(size); 46 | for (size_t i = 0; i < size; i++) 47 | elep[i].modify_in_compile(ele[i]); 48 | } 49 | 50 | void elephant::main() 51 | { 52 | hos_std->write_int(sys->pid()); 53 | hos_std->println(" in."); 54 | hos_std->println(graph); 55 | handle pid = sys->create_process(); 56 | if (sys->pid() < 3) { 57 | sys->exec_program(pid, elep); 58 | sys->wait(pid); 59 | } 60 | hos_std->write_int(sys->pid()); 61 | hos_std->println(" exit."); 62 | } 63 | -------------------------------------------------------------------------------- /user/elephant/elephant.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../hyperstd.h" 4 | #include "../hyperlib.h" 5 | 6 | class elephant : public program { 7 | public: 8 | 9 | elephant(); 10 | virtual ~elephant(); 11 | virtual void main(); 12 | virtual void static_init(); 13 | 14 | protected: 15 | 16 | handle graph; 17 | handle elep; 18 | }; 19 | 20 | void register_elephant(); 21 | -------------------------------------------------------------------------------- /user/elephant/elephant_boom.cpp: -------------------------------------------------------------------------------- 1 | #include "elephant_boom.h" 2 | #include 3 | 4 | void elephant_boom::static_init() 5 | { 6 | set_name("elephant-boom"); 7 | const char str[] = 8 | "--------------------------------------------------------------------\n" 9 | " // / / // ) ) // ) \n" 10 | " //___ / / ___ ___ __ // / / (( \n" 11 | " / ___ // / / // ) ) //___) ) // ) ) // / / \\ \n" 12 | " // / ((___/ / //___/ / // // // / / )) \n" 13 | "// / / / / // ((____ // ((___/ / ((___ // \n" 14 | "--------------------------------------------------------------------\0"; 15 | size_t size = strlen(str) + 1; 16 | graph = alloc_static(size); 17 | for (size_t i = 0; i < size; i++) 18 | graph[i].modify_in_compile(str[i]); 19 | const char ele[] = "elephant-boom\0"; 20 | size = strlen(ele) + 1; 21 | elep = alloc_static(size); 22 | for (size_t i = 0; i < size; i++) 23 | elep[i].modify_in_compile(ele[i]); 24 | 25 | } 26 | 27 | void elephant_boom::main() 28 | { 29 | handle pid = sys->create_process(); 30 | sys->exec_program(pid, elep); 31 | hos_std->println(graph); 32 | hos_std->write_int(sys->pid()); 33 | hos_std->println(""); 34 | while (1) { 35 | sys->yield(); 36 | hos_std->write_int(sys->pid()); 37 | hos_std->println(" tick."); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /user/elephant/elephant_boom.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "elephant.h" 3 | 4 | class elephant_boom : public elephant { 5 | 6 | public: 7 | 8 | virtual void main(); 9 | virtual void static_init(); 10 | }; 11 | -------------------------------------------------------------------------------- /user/hyperlib.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../src/program/lib.h" 4 | -------------------------------------------------------------------------------- /user/hyperstd.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../src/program/program.h" 4 | #include "../src/process/process_t.h" 5 | #include "../src/process/process.h" 6 | #include "../src/program/sys_t.h" 7 | 8 | extern const int CLOCK_INTERVAL; 9 | 10 | -------------------------------------------------------------------------------- /user/keymap.h: -------------------------------------------------------------------------------- 1 | #include "../src/io/special_keys.h" 2 | 3 | -------------------------------------------------------------------------------- /user/lp/lp.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * (l)ist all (p)rograms 3 | * list all programs 4 | */ 5 | #include "lp.h" 6 | #include "../../src/program/program_manager.h" 7 | #include 8 | #include 9 | #include 10 | 11 | using std::string; 12 | using std::vector; 13 | 14 | extern vector prog_name; 15 | 16 | static program* gen() 17 | { 18 | return new lp(); 19 | } 20 | 21 | void register_lp() 22 | { 23 | register_program("lp", gen); 24 | } 25 | 26 | lp::lp() 27 | { } 28 | 29 | lp::~lp() 30 | { } 31 | 32 | void lp::static_init() 33 | { 34 | set_name("lp"); 35 | } 36 | 37 | void lp::main() 38 | { 39 | handle i = 0; 40 | handle size = (int)prog_name.size(); 41 | for (i = 0; i < size; i = i + 1) { 42 | hos_std->print(prog_name[i] + " "); 43 | } 44 | hos_std->println(""); 45 | } 46 | -------------------------------------------------------------------------------- /user/lp/lp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../hyperstd.h" 4 | #include "../hyperlib.h" 5 | 6 | class lp : public program { 7 | public: 8 | 9 | lp(); 10 | virtual ~lp(); 11 | virtual void static_init(); 12 | virtual void main(); 13 | 14 | private: 15 | 16 | 17 | }; 18 | 19 | void register_lp(); 20 | -------------------------------------------------------------------------------- /user/matrix/matrix.cpp: -------------------------------------------------------------------------------- 1 | #include "matrix.h" 2 | #include "../../src/program/program_manager.h" 3 | 4 | program* gen() 5 | { 6 | return new matrix; 7 | } 8 | 9 | void register_matrix() 10 | { 11 | register_program("matrix", gen); 12 | } 13 | 14 | matrix::matrix() 15 | { } 16 | 17 | matrix::~matrix() 18 | { } 19 | 20 | void matrix::static_init() 21 | { } 22 | 23 | void matrix::hint(handle n, handle m) 24 | { 25 | hos_std->print("input a "); 26 | hos_std->write_int(n); 27 | hos_std->print(" x "); 28 | hos_std->write_int(m); 29 | hos_std->println(" matrix"); 30 | } 31 | 32 | handle matrix::at(handle< handle > A, handle i, handle j) 33 | { 34 | return ((handle)A[i])[j]; 35 | } 36 | 37 | void matrix::read_matrix(handle n, handle m, 38 | handle< handle > &A) 39 | { 40 | for (handle i = 0; i < n; i = i + 1) { 41 | for (handle j = 0; j < m; j = j + 1) { 42 | at(A, i, j) = hos_std->read_int(); 43 | } 44 | } 45 | } 46 | 47 | void matrix::write_matrix(handle n, handle m, 48 | handle< handle > A) 49 | { 50 | for (handle i = 0; i < n; i = i + 1) { 51 | for (handle j = 0; j < m; j = j + 1) { 52 | hos_std->write_int(at(A, i, j)); 53 | hos_std->print(" "); 54 | } 55 | hos_std->println(""); 56 | } 57 | } 58 | 59 | void matrix::alloc_matrix(handle n, handle m, 60 | handle< handle > &A) 61 | { 62 | A = alloc_heap< handle >( (int)n ); 63 | for (handle i = 0; i < n; i = i + 1) { 64 | A[i] = alloc_heap (m); 65 | for (handle j = 0; j < m; j = j + 1) { 66 | at(A, i, j) = alloc_heap(); 67 | } 68 | } 69 | } 70 | 71 | void matrix::matrix_mul(handle< handle > &C, handle< handle > A, handle< handle > B, handle n, handle m, handle q) 72 | { 73 | for (handle i = 0; i < n; i = i + 1) 74 | for (handle j = 0; j < q; j = j + 1) 75 | at(C, i, j) = 0; 76 | for (handle k = 0; k < m; k = k + 1) { 77 | for (handle i = 0; i < n; i = i + 1) { 78 | for (handle j = 0; j < q; j = j + 1) { 79 | at(C, i, j) = at(C, i, j) + at(A, i, k) * at(B, k, j); 80 | } 81 | } 82 | } 83 | } 84 | 85 | void matrix::main() 86 | { 87 | handle< handle > A, B, C; 88 | hos_std->println("input matrix size : n, m, k"); 89 | handle n = hos_std->read_int(); 90 | handle m = hos_std->read_int(); 91 | handle k = hos_std->read_int(); 92 | hint(n, m); 93 | alloc_matrix(n, m, A); 94 | read_matrix(n, m, A); 95 | hint(m, k); 96 | alloc_matrix(m, k, B); 97 | read_matrix(m, k, B); 98 | alloc_matrix(n, k, C); 99 | matrix_mul(C, A, B, n, m, k); 100 | hos_std->println("result matrix"); 101 | write_matrix(n, k, C); 102 | hos_std->print("computation finished in : "); 103 | hos_std->write_int(sys->clock() * CLOCK_INTERVAL); 104 | hos_std->println(" ms."); 105 | } 106 | 107 | -------------------------------------------------------------------------------- /user/matrix/matrix.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../hyperstd.h" 4 | #include "../hyperlib.h" 5 | 6 | class matrix : public program { 7 | public: 8 | 9 | matrix(); 10 | virtual ~matrix(); 11 | virtual void main(); 12 | virtual void static_init(); 13 | 14 | private: 15 | 16 | void hint(handle n, handle m); 17 | void read_matrix(handle n, handle m, handle< handle > &A); 18 | void write_matrix(handle n, handle m, handle< handle > A); 19 | void alloc_matrix(handle n, handle m, handle< handle > &A); 20 | 21 | handle at(handle< handle > A, handle i, handle j); 22 | void matrix_mul(handle< handle > &C, handle< handle > A, handle< handle > B, handle n, handle m, handle q); 23 | }; 24 | 25 | void register_matrix(); 26 | -------------------------------------------------------------------------------- /user/shell/shell.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * shell for hos 3 | * -------------------- 4 | * - run prog by name 5 | */ 6 | #include "shell.h" 7 | #include "../../src/program/program_manager.h" 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "../../src/logging/logging.h" 13 | #include "../keymap.h" 14 | 15 | using std::string; 16 | 17 | static program* gen() 18 | { return new hyper_shell; } 19 | 20 | void register_shell() 21 | { 22 | register_program("shell", gen); 23 | } 24 | 25 | hyper_shell::hyper_shell() 26 | { } 27 | 28 | hyper_shell::~hyper_shell() 29 | { } 30 | 31 | void hyper_shell::static_init() 32 | { 33 | set_name("shell"); 34 | argc = alloc_bss(); 35 | for (size_t i = 0; i < 20; i++) 36 | argv[i] = alloc_bss(30); 37 | } 38 | 39 | void hyper_shell::main() 40 | { 41 | logging::info << "shell start." << logging::log_endl; 42 | while (1) { 43 | hos_std->print("hyper-shell:$ "); 44 | handle res = (int)parse(); 45 | if (res == 0) { 46 | logging::info << "operation success." << logging::log_endl; 47 | } else if (res == -1) { 48 | sys->exit(); 49 | break; 50 | } else if (res == -2) { 51 | logging::info << "operation failed." << logging::log_endl; 52 | } 53 | } 54 | } 55 | 56 | handle hyper_shell::parse() 57 | { 58 | handle c; 59 | handle top = 0; 60 | argc = 0; 61 | while (1) { 62 | c = get(); 63 | if (argc == 20 || top == 30) { 64 | while (c != '\n') { 65 | c = get(); 66 | } 67 | too_long_error(); 68 | return -2; 69 | } 70 | if (c == '\n') { 71 | argv[argc][top] = '\0'; 72 | argc = argc + 1; 73 | break; 74 | } else if (c == ' ') { 75 | argv[argc][top] = '\0'; 76 | argc = argc + 1; 77 | top = 0; 78 | } else if (c == '\b') { 79 | if (top > 0) { 80 | top = top - 1; 81 | } else if (argc > 0) { 82 | argc = argc - 1; 83 | top = 0; 84 | while (argv[argc][top] != '\0') 85 | top = top + 1; 86 | } 87 | } else { 88 | argv[argc][top] = c; 89 | top = top + 1; 90 | } 91 | } 92 | if (argc == 1 && top == 0) { 93 | return 0; 94 | } 95 | assert(argc > 0); 96 | return (int)servant(argv[0]); 97 | } 98 | 99 | handle hyper_shell::get() 100 | { 101 | handle ch = alloc_heap(); 102 | logging::debug << "waiting for input" << logging::log_endl; 103 | ch = hos_std->getchar(); 104 | logging::debug << "input char from shell : " << (char)ch << logging::log_endl; 105 | return ch; 106 | } 107 | 108 | handle hyper_shell::servant(handle cmd) 109 | { 110 | string str = to_string(cmd); 111 | if (str == "exit") { 112 | return -1; 113 | } else if (str == "help") { 114 | help_prog(); 115 | } else if (str == "msg") { 116 | msg_prog(); 117 | } else if (str == "pid") { 118 | pid_prog(); 119 | } else if (is_program(to_string(cmd))) { 120 | exec(); 121 | } else { 122 | program_not_found_error(); 123 | } 124 | return 0; 125 | } 126 | -------------------------------------------------------------------------------- /user/shell/shell.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../hyperstd.h" 4 | #include "../hyperlib.h" 5 | #include "../../src/logging/logging.h" 6 | #include 7 | 8 | class hyper_shell : public program { 9 | public: 10 | 11 | hyper_shell(); 12 | virtual ~hyper_shell(); 13 | virtual void main(); 14 | virtual void static_init(); 15 | 16 | private: 17 | 18 | handle argc; 19 | handle argv[20]; 20 | 21 | handle servant(handle cmd); 22 | void exec(); 23 | handle parse(); 24 | handle get(); 25 | 26 | void program_not_found_error(); 27 | void too_long_error(); 28 | void format_error(); 29 | void argv_error(handle id); 30 | 31 | std::string to_string(handle str); 32 | 33 | void help_prog(); 34 | void msg_prog(); 35 | void pid_prog(); 36 | 37 | void general_help(); 38 | 39 | void help_exit_title(); 40 | void help_exec_title(); 41 | void help_msg_title(); 42 | void help_pid_title(); 43 | 44 | void help_msg_body(); 45 | void help_pid_body(); 46 | }; 47 | 48 | void register_shell(); 49 | -------------------------------------------------------------------------------- /user/shell/shell_exec.cpp: -------------------------------------------------------------------------------- 1 | #include "shell.h" 2 | 3 | void hyper_shell::exec() 4 | { 5 | int pid = sys->create_process(); 6 | logging::debug << "create process pid" << logging::log_endl; 7 | // program *prog = get_program(to_string(argv[0])); 8 | logging::debug << "get program : " << to_string(argv[0]) << " pid : " << pid << logging::log_endl; 9 | sys->exec_program(pid, argv[0]); 10 | logging::debug << "sub program start." << logging::log_endl; 11 | sys->wait(pid); 12 | logging::debug << "sub program exit." << logging::log_endl; 13 | } 14 | -------------------------------------------------------------------------------- /user/shell/shell_help.cpp: -------------------------------------------------------------------------------- 1 | #include "shell.h" 2 | 3 | void hyper_shell::help_prog() 4 | { 5 | if (argc == 1) { 6 | general_help(); 7 | } else { 8 | hos_std->println("not supported yet"); 9 | } 10 | } 11 | 12 | void hyper_shell::general_help() 13 | { 14 | hos_std->println("Hyper-OS Shell, Version 0.1"); 15 | hos_std->println("--- Supported Commands ---"); 16 | help_exit_title(); 17 | help_msg_title(); 18 | help_pid_title(); 19 | help_exec_title(); 20 | } 21 | 22 | void hyper_shell::help_exit_title() 23 | { 24 | hos_std->println("[exit] : exit the shell"); 25 | } 26 | 27 | void hyper_shell::help_exec_title() 28 | { 29 | hos_std->println("[program-name] : run program by name"); 30 | } 31 | 32 | void hyper_shell::help_msg_title() 33 | { 34 | hos_std->println("[msg] : enable or disable message"); 35 | } 36 | 37 | void hyper_shell::help_pid_title() 38 | { 39 | hos_std->println("[pid] : show pid of current or parent process"); 40 | } 41 | -------------------------------------------------------------------------------- /user/shell/shell_msg.cpp: -------------------------------------------------------------------------------- 1 | #include "shell.h" 2 | #include "../../src/message/message.h" 3 | 4 | using std::string; 5 | using message::set_interrupt_message; 6 | using message::set_process_message; 7 | using message::set_memory_message; 8 | using message::set_test_message; 9 | 10 | static void set_all(bool type) 11 | { 12 | set_interrupt_message(type); 13 | set_process_message(type); 14 | set_memory_message(type); 15 | set_test_message(type); 16 | } 17 | 18 | void hyper_shell::msg_prog() 19 | { 20 | if (argc == 1) { 21 | help_msg_title(); 22 | help_msg_body(); 23 | } else if (argc == 3) { 24 | string str = to_string(argv[1]), type = to_string(argv[2]); 25 | int flag = -1; 26 | if (str == "enable") { 27 | flag = 1; 28 | } else if (str == "disable") { 29 | flag = 0; 30 | } else { 31 | argv_error(1); 32 | } 33 | if (flag != -1) { 34 | if (type == "all") { 35 | set_all(flag); 36 | } else if (type == "interrupt") { 37 | set_interrupt_message(flag); 38 | } else if (type == "process") { 39 | set_process_message(flag); 40 | } else if (type == "memory") { 41 | set_memory_message(flag); 42 | } else if (type == "test") { 43 | set_test_message(flag); 44 | } else { 45 | argv_error(2); 46 | } 47 | } 48 | } else { 49 | format_error(); 50 | } 51 | } 52 | 53 | void hyper_shell::help_msg_body() 54 | { 55 | hos_std->println("- Format : msg [enable/disable] {type}"); 56 | hos_std->println("- {type} : interrupt, process, memory, test, all"); 57 | } 58 | 59 | -------------------------------------------------------------------------------- /user/shell/shell_prog.cpp: -------------------------------------------------------------------------------- 1 | #include "shell.h" 2 | #include 3 | using std::string; 4 | 5 | void hyper_shell::pid_prog() 6 | { 7 | if (argc > 2) { 8 | format_error(); 9 | } else { 10 | if (argc == 1) { 11 | help_pid_title(); 12 | help_pid_body(); 13 | } else { 14 | string str = to_string(argv[1]); 15 | int result = 0; 16 | if (str == "parent") { 17 | result = sys->parent(); 18 | } else if (str == "current") { 19 | result = sys->pid(); 20 | } else { 21 | argv_error(1); 22 | return; 23 | } 24 | hos_std->write_int(result); 25 | hos_std->putchar('\n'); 26 | } 27 | } 28 | } 29 | 30 | void hyper_shell::help_pid_body() 31 | { 32 | hos_std->println("- Format : pid [{which}]"); 33 | hos_std->println("- {which} : parent, current"); 34 | } 35 | -------------------------------------------------------------------------------- /user/shell/shell_utils.cpp: -------------------------------------------------------------------------------- 1 | #include "shell.h" 2 | 3 | using std::string; 4 | 5 | string hyper_shell::to_string(handle str) 6 | { 7 | string tar; 8 | for (size_t i = 0; str[i] != '\0'; i++) { 9 | tar = tar + (char)(str[i]); 10 | } 11 | return tar; 12 | } 13 | 14 | void hyper_shell::program_not_found_error() 15 | { 16 | hos_std->print("invalid program name \'"); 17 | hos_std->print(argv[0]); 18 | hos_std->println("\'"); 19 | } 20 | 21 | void hyper_shell::too_long_error() 22 | { 23 | hos_std->println("command is too long"); 24 | } 25 | 26 | void hyper_shell::format_error() 27 | { 28 | hos_std->print("command ["); 29 | hos_std->print(argv[0]); 30 | hos_std->println("], format error"); 31 | } 32 | 33 | void hyper_shell::argv_error(handle id) 34 | { 35 | hos_std->print("command ["); 36 | hos_std->print(argv[0]); 37 | hos_std->print("], argv "); 38 | hos_std->write_int(id); 39 | hos_std->println(" error"); 40 | } 41 | --------------------------------------------------------------------------------