Merge pull request '重写rust核心库,构建中断处理框架' (#6) from pointer-to-bios/metaverse-dev:main into main
Reviewed-on: metaverse/kernel-dev#6
This commit is contained in:
commit
87f2767499
|
@ -0,0 +1,2 @@
|
|||
[build]
|
||||
target = ["x86_64-unknown-none"]
|
|
@ -1,5 +1,7 @@
|
|||
.vscode
|
||||
/test/metaverse.img
|
||||
*.o
|
||||
*.tfo
|
||||
*.map
|
||||
*.elf
|
||||
metaverse_kernel
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
[submodule "rustlib"]
|
||||
path = rustlib
|
||||
url = http://git.suthby.org:2024/metaverse/rustenv
|
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Linux",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/include"
|
||||
],
|
||||
"defines": [],
|
||||
"compilerPath": "/usr/bin/gcc",
|
||||
"cStandard": "c17",
|
||||
"intelliSenseMode": "linux-gcc-x64",
|
||||
"configurationProvider": "ms-vscode.makefile-tools"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"C_Cpp.errorSquiggles": "disabled",
|
||||
"files.associations": {
|
||||
"*.s": "nasm",
|
||||
"LICENCE": "plaintext",
|
||||
"*.h": "c"
|
||||
},
|
||||
"rust-analyzer.imports.preferNoStd" : true,
|
||||
}
|
|
@ -2,10 +2,10 @@
|
|||
name = "metaverse"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
crate-type = ["staticlib"]
|
||||
test = false
|
||||
|
||||
# 此Cargo.toml仅用于rust-analyzer识别rust部分的代码
|
||||
# 不应使用cargo编译
|
||||
|
||||
[target.'cfg(target_arch = "x86_64")']
|
||||
target = "x86_64-unknown-none"
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
======== 04-21 16:50 ========
|
||||
Hit null pointer at 0x100370a
|
||||
Stack trace:
|
||||
1 0x0000000001007b90 -> interrupt_req_DE
|
||||
2 0x00000000010072b0 -> metaverse::kernel::tty::tty::MessageBuilder::message_mut
|
||||
3 0x0000000001007e60 -> <metaverse::libk::alloc::string::String as core::iter::traits::collect::FromIterator::<char>>::from_iter
|
||||
4 0x0000000001005eb0 -> <alloc::string::String as core::iter::traits::collect::FromIterator<char>>::from_iter
|
||||
5 0x0000000001005d80 -> <alloc::string::String as core::iter::traits::collect::Extend<char>>::extend
|
||||
6 0x0000000001004840 -> alloc::vec::Vec::reserve
|
||||
7 0x0000000001005900 -> alloc::raw_vec::RawVec::reserve::{do_reserve_and_handle}
|
||||
8 0x00000000010055c0 -> alloc::raw_vec::RawVec::grow_amortized
|
||||
9 0x00000000010051e0 -> alloc::raw_vec::finish_grow
|
||||
10 0x0000000001005a90 -> <alloc::alloc::Global as core::alloc::Allocator>::allocate
|
||||
11 0x0000000001004900 -> alloc::alloc::Global::alloc_impl
|
||||
12 0x00000000010048a0 -> alloc::alloc::alloc
|
||||
13 0x00000000010036e0 -> core::ptr::read_volatile::precondition_check
|
||||
使用了core crate中的String,导致最终调用了一个含有未正确链接的函数。
|
||||
|
||||
======== 04-23 13:55 ========
|
||||
Hit null pointer at 0x100351a.
|
||||
Stack trace:
|
||||
0x00000000010054d0 -> metaverse::kernel::tty::tty::MessageBuilder::message_mut
|
||||
0x0000000001006170 -> <str as metaverse::libk::alloc::string::ToString>::to_string
|
||||
0x0000000001006080 -> <metaverse::libk::alloc::string::String as core::iter::traits::collect::FromIterator<char>>::from_iter
|
||||
0x0000000001007450 -> <metaverse::libk::alloc::vec::Vec as core::iter::traits::collect::FromIterator>::from_iter
|
||||
0x0000000001006a10 -> metaverse::libk::alloc::vec::Vec::push
|
||||
0x0000000001003f60 -> alloc::alloc::alloc
|
||||
0x00000000010034f0 -> core::ptr::read_volatile::precondition_check
|
||||
使用了core crate的alloc函数,其中含有未正确链接的函数。
|
||||
|
||||
======== 04-26 02:56 ========
|
||||
Hit null pointer in metaverse::libk::alloc::string::String::clone()
|
||||
Stack trace:
|
||||
0x0000000001005520 -> metaverse::kernel::tty::tty::format_message
|
||||
0x00000000010052f0 -> metaverse::kernel::tty::tty::MessageBuilder::message_mut
|
||||
0x00000000010073f0 -> <metaverse::libk::alloc::string::String as metaverse::libk::alloc::string::ToString>::to_string
|
||||
0x0000000001009a90 -> <metaverse::libk::alloc::string::String as core::clone::Clone>::clone
|
||||
使用了Clone的derive宏,含有未正确链接的函数。
|
||||
|
||||
======== 04-26 15:55 ========
|
||||
Hit null pointer at 0x1003672.
|
||||
Stack trace:
|
||||
0x0000000001007600 -> <u64 as metaverse::libk::alloc::string::ToString>::to_string
|
||||
0x0000000001007030 -> metaverse::libk::alloc::string::String::insert
|
||||
0x0000000001008330 -> metaverse::libk::alloc::vec::Vec::insert
|
||||
0x0000000001007950 -> metaverse::libk::alloc::vec::Vec::extend_capacity
|
||||
0x0000000001003630 -> core::intrinsics::copy::precondition_check
|
||||
将*mut u8转换为*mut T时调用了此函数,导致调用了一个未正确链接的函数。
|
||||
|
||||
======== 04-27 16:06 ========
|
||||
Trapped into a infinite loop.
|
||||
Stack trace:
|
||||
0x0000000001006c30 -> interrupt_req_DE
|
||||
0x0000000001005420 -> metaverse::kernel::tty::tty::MessageBuilder::append
|
||||
0x0000000001008410 -> metaverse::libk::alloc::vec::Vec::append
|
|
@ -12,9 +12,22 @@
|
|||
|
||||
若你的代码通过审核,将会把你的PR合并到主分支中。
|
||||
|
||||
## 需要注意的还未解决的问题
|
||||
## 开发引导
|
||||
|
||||
* rust中所有有关字符串格式化的宏中,出现超过一个不止是`{}`的格式化占位符时内核必然崩溃。
|
||||
* rust中所有有关字符串格式化的宏中,出现需要调用自定义的`Debug trait`的类型时内核必然崩溃,推荐定义`ToString trait`并调用`.to_string()`后传入宏参数。
|
||||
* 鉴于以上两条原因,不建议在复杂的字符串格式化任务中使用`format!()`宏。推荐通过使用`::kernel::tty::tty::MessageBuilder`构造`kernel::tty::tty::Message`对象,或使用
|
||||
`message`宏,并调用此对象的`.to_string()`方法实现格式化字符串。
|
||||
## vscode
|
||||
|
||||
vscode下的`rust-analyzer`插件会在`src/lib.rs`中误报`can't find crate for test`,实际上在`Cargo.toml`中已经增加了`test = false`选项。
|
||||
|
||||
解决方法是在`.vscode/settings.json`中增加两项:
|
||||
|
||||
```json
|
||||
"rust-analyzer.cargo.allTargets": false,
|
||||
"rust-analyzer.cargo.extraArgs": [
|
||||
"--target",
|
||||
"开发的目标平台的unknown-none类型目标(如x86_64-unknown-none)"
|
||||
]
|
||||
```
|
||||
|
||||
## 需要注意的问题
|
||||
|
||||
* 在任何情况下不要使用Rust的panic。
|
||||
|
|
|
@ -77,11 +77,13 @@ typedef void (*interrupt_request)(u64 rip, u64 rsp, u64 errcode);
|
|||
#define DE
|
||||
#define NMI
|
||||
#define BP
|
||||
#define OF
|
||||
|
||||
interrupt_entry_gen(UNSUPPORTED);
|
||||
|
||||
interrupt_entry_gen(DE);
|
||||
interrupt_entry_gen(NMI);
|
||||
interrupt_entry_gen(BP);
|
||||
interrupt_entry_gen(DE); // irq0
|
||||
interrupt_entry_gen(NMI); // irq2
|
||||
interrupt_entry_gen(BP); // irq3
|
||||
interrupt_entry_gen(OF); // ira4
|
||||
|
||||
#endif
|
||||
|
|
|
@ -156,6 +156,7 @@ void tty_disable(tty *ttyx);
|
|||
|
||||
typedef struct __tty_font_t
|
||||
{
|
||||
bool initialized;
|
||||
u16 char_width, char_height;
|
||||
u64 **font;
|
||||
} tty_font_t;
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
[toolchain]
|
||||
channel = "stable"
|
||||
channel = "nightly"
|
||||
|
|
1
rustlib
1
rustlib
|
@ -1 +0,0 @@
|
|||
Subproject commit 6a2ca2afcd651e46f1c19f8d8a3f685fd982d824
|
|
@ -0,0 +1,57 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
from io import TextIOWrapper
|
||||
import sys
|
||||
import struct
|
||||
|
||||
|
||||
def main(infile: TextIOWrapper, outfile: TextIOWrapper):
|
||||
size = infile.readline().strip().split(",")
|
||||
size = (int(size[0].strip()), int(size[1].strip()))
|
||||
outfile.write(struct.pack('q', size[0]))
|
||||
outfile.write(struct.pack('q', size[1]))
|
||||
for _ in range(62):
|
||||
outfile.write(struct.pack('q', int(0)))
|
||||
in_char = False
|
||||
char_buffer = []
|
||||
char_count = 0
|
||||
for line in infile:
|
||||
line = line.split("//")[0].strip()
|
||||
if len(line) == 0:
|
||||
continue
|
||||
if line.startswith("{"):
|
||||
char_buffer = []
|
||||
line = line[1:]
|
||||
in_char = True
|
||||
if line.endswith("},"):
|
||||
i = 0
|
||||
for d in char_buffer:
|
||||
outfile.write(struct.pack('q', d))
|
||||
i += 1
|
||||
while i < 64:
|
||||
outfile.write(struct.pack('q', int(0)))
|
||||
i += 1
|
||||
char_count += 1
|
||||
in_char = False
|
||||
continue
|
||||
if len(line) == 0:
|
||||
continue
|
||||
if in_char:
|
||||
data = line.split(",")[0].strip()
|
||||
data = int(data, 2)
|
||||
char_buffer.append(data)
|
||||
while char_count < 256:
|
||||
for _ in range(64):
|
||||
outfile.write(struct.pack('q', int(0)))
|
||||
char_count += 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 3:
|
||||
print("tfgen: Input file and Output file needed.")
|
||||
exit(1)
|
||||
infile_name = sys.argv[1]
|
||||
outfile_name = sys.argv[2]
|
||||
with open(infile_name) as infile:
|
||||
with open(outfile_name, "wb") as outfile:
|
||||
main(infile, outfile)
|
43
src/Makefile
43
src/Makefile
|
@ -12,11 +12,15 @@ ifdef release
|
|||
release = 1
|
||||
endif
|
||||
|
||||
ifndef ttyfont
|
||||
ttyfont = metamono
|
||||
endif
|
||||
|
||||
ALLOCATOR_MAGIC = $(shell "${SOURCE}/magicgen" | sha512sum | head -c 128 | md5sum | head -c 8)
|
||||
|
||||
BUILD_ID = $(shell "${SOURCE}/magicgen" | sha512sum | head -c 128 | md5sum | head -c 4)
|
||||
BUILD_ID = $(shell "${SOURCE}/magicgen" | sha512sum | head -c 128 | md5sum | head -c 8)
|
||||
|
||||
SUBOBJS = kernel/kernel.o libk/libk.o rust.o
|
||||
SUBOBJS = kernel/kernel.o libk/libk.o rust.o font_file.o
|
||||
|
||||
DEFINES = ARCH="${ARCH}" ASM="${ASM}" ASMFLAGS="${ASMFLAGS}" SOURCE="${SOURCE}" PWD="${PWD}" \
|
||||
ALLOCATOR_MAGIC="${ALLOCATOR_MAGIC}" BUILD_ID="${BUILD_ID}"
|
||||
|
@ -27,16 +31,24 @@ endif
|
|||
################################
|
||||
# rust语言环境变量
|
||||
|
||||
TARGET_TRIPLE =
|
||||
|
||||
ifeq (${ARCH},x86_64)
|
||||
TARGET_TRIPLE := x86_64-unknown-none
|
||||
endif
|
||||
|
||||
RUSTLIB_PATH = ../target/sysroot/lib/rustlib/${TARGET_TRIPLE}/lib
|
||||
RUST_LIBS = $(shell ls -d ${RUSTLIB_PATH}/lib*.rlib)
|
||||
|
||||
RSCFLAGS = --emit obj --crate-type staticlib --verbose \
|
||||
--crate-name=metaverse \
|
||||
--edition 2021 \
|
||||
-L crate="${PWD}/../rustlib/src/" \
|
||||
-C code-model=large \
|
||||
-C relocation-model=static \
|
||||
-C embed-bitcode=no
|
||||
-C embed-bitcode=no \
|
||||
-C panic=abort
|
||||
|
||||
ifeq (${ARCH},x86_64)
|
||||
RSCFLAGS := ${RSCFLAGS} --target x86_64-unknown-none
|
||||
RSCFLAGS := ${RSCFLAGS} -C target-feature=-sse
|
||||
endif
|
||||
|
||||
|
@ -44,18 +56,14 @@ ifdef release
|
|||
RSCFLAGS := ${RSCFLAGS} -O
|
||||
endif
|
||||
|
||||
RUSTLIB_PATH = ../rustlib/${ARCH}
|
||||
RUST_LIBS = "${RUSTLIB_PATH}/liballoc.rlib" "${RUSTLIB_PATH}/libcompiler_builtins.rlib" \
|
||||
"${RUSTLIB_PATH}/libcore.rlib" "${RUSTLIB_PATH}/librustc_std_workspace_core.rlib"
|
||||
|
||||
################################
|
||||
|
||||
metaverse.elf: kernel libk rust metaverse.lds
|
||||
metaverse.elf: kernel libk rust metaverse.lds font_file.o
|
||||
@echo -e "\e[1;33mld\e[0m \e[1;32m$@\e[0m \e[34m<--\e[0m \e[32m${SUBOBJS}\e[0m"
|
||||
@ld -T metaverse.lds -Map=metaverse.map -unresolved-symbols=ignore-all -o $@ ${SUBOBJS} ${RUST_LIBS} \
|
||||
2>&1 | "${SOURCE}/colorize" "warning:=yellow" "error:=red" "ld=lyellow"
|
||||
2>&1 | "${SOURCE}/colorize" "warning:=lpink" "error:=red" "ld=lyellow"
|
||||
|
||||
.PHONY: kernel libk all clear postproc rust
|
||||
.PHONY: kernel libk all clear postproc rust rustlib
|
||||
|
||||
all: postproc metaverse.elf
|
||||
@echo -e "Build \e[1;32msucceeded\e[0m."
|
||||
|
@ -88,11 +96,18 @@ libk:
|
|||
echo -e "\e[33m-------------------------\e[0m"; \
|
||||
fi
|
||||
|
||||
rust: postproc
|
||||
../target:
|
||||
@-cargo xbuild --target ${TARGET_TRIPLE} --release
|
||||
|
||||
rust: postproc ../target
|
||||
@echo -e "\e[1m\e[33mrustc\e[0m \e[34m-->\e[0m \e[1m\e[32m$@.o\e[0m"
|
||||
@rustc ${RSCFLAGS} lib.rs -o rust.o
|
||||
|
||||
font_file.o: ttyfonts/${ttyfont}.tfn
|
||||
@"${SOURCE}/tfgen" $< font_file.tfo
|
||||
@ld -r -b binary -o $@ font_file.tfo
|
||||
|
||||
clear:
|
||||
@make -C kernel clear --no-print-directory ${DEFINES}
|
||||
@make -C libk clear --no-print-directory ${DEFINES}
|
||||
@-rm metaverse.elf metaverse.map rust.o
|
||||
@-rm metaverse.elf metaverse.map rust.o font_file.{o,tfo}
|
||||
|
|
|
@ -13,8 +13,7 @@ ifdef release
|
|||
CCFLAGS := ${CCFLAGS} -O2
|
||||
endif
|
||||
|
||||
C_SRCS = main.c tty.c font.c memm.c memm_${ARCH}.c raw.c time.c syscall_${ARCH}.c interrupt_${ARCH}.c \
|
||||
interrupt_procs.c
|
||||
C_SRCS = main.c tty.c font.c memm.c memm_${ARCH}.c raw.c time.c syscall_${ARCH}.c interrupt_${ARCH}.c
|
||||
C_OBJS = ${C_SRCS:.c=.c.o}
|
||||
|
||||
################################
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
#[cfg(target_arch = "x86_64")]
|
||||
pub mod x86_64;
|
|
@ -11,7 +11,8 @@ init64:
|
|||
mov rsp, rax
|
||||
mov rdi, rbx
|
||||
|
||||
lidt [0x104010]
|
||||
; 加载idt
|
||||
lidt [0x104010] ; idt_ptr
|
||||
|
||||
; 加载系统调用相关寄存器
|
||||
; IA32_STAR = 0x0018_0008_0000_0000
|
||||
|
|
|
@ -21,17 +21,18 @@ init32:
|
|||
mov dword [edi], 0
|
||||
|
||||
; 设置PD0中的PDE
|
||||
mov ecx, 64
|
||||
; 以2MB页映射前64MB
|
||||
mov ecx, 32
|
||||
mov eax, 0
|
||||
mov edi, 0x103000 ; PD0
|
||||
init32_loop0:
|
||||
mov edx, eax
|
||||
add edx, 0x183
|
||||
mov dword [edi], edx
|
||||
add eax, 0x200000 ; 2MB
|
||||
add edi, 4
|
||||
mov dword [edi], 0
|
||||
add edi, 4
|
||||
add eax, 0x200000 ; 2MB
|
||||
loop init32_loop0
|
||||
|
||||
; 加载GDTR、段寄存器和TR寄存器
|
||||
|
|
|
@ -51,7 +51,10 @@
|
|||
add rsp, 4
|
||||
%endmacro
|
||||
|
||||
; 此处的cli在进入rust的中断处理函数后才会对应sti
|
||||
; 因为在保存栈帧前中断不可以被打断
|
||||
%macro interrupt_entry_enter 0
|
||||
cli
|
||||
push rbp
|
||||
lea rbp, [rsp]
|
||||
store_regs
|
||||
|
@ -62,6 +65,7 @@
|
|||
retrieve_section
|
||||
retrieve_regs
|
||||
leave
|
||||
sti
|
||||
%endmacro
|
||||
|
||||
; 用于带有错误码的中断,创建一个没有错误码的上下文拷贝
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
use crate::{kernel::tty::tty::Tty, message};
|
||||
|
||||
extern "C" {
|
||||
pub fn interrupt_open();
|
||||
pub fn interrupt_close();
|
||||
// 以下两个函数签名的返回值用于使编译器保留rax寄存器
|
||||
pub fn interrupt_rust_enter() -> usize;
|
||||
pub fn interrupt_rust_leave() -> usize;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn interrupt_req_UNSUPPORTED(rip: u64, rsp: u64, errcode: u64) -> ! {
|
||||
interrupt_rust_enter();
|
||||
let tty = Tty::from_id(0).unwrap();
|
||||
tty.enable();
|
||||
tty.print(message!(
|
||||
"{Panic}: Kernel hit an {Unsupported} interrupt on rip=0x{} and rsp=0x{}.\n",
|
||||
FmtMeta::Color(Color::RED),
|
||||
FmtMeta::Color(Color::YELLOW),
|
||||
FmtMeta::Pointer(rip as usize),
|
||||
FmtMeta::Pointer(rsp as usize)
|
||||
));
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn interrupt_req_DE(rip: u64, rsp: u64, errcode: u64) {
|
||||
interrupt_rust_enter();
|
||||
let tty = Tty::from_id(0).unwrap();
|
||||
tty.enable();
|
||||
tty.print(message!(
|
||||
"{Warning}: Kernel hit {Divid Error} on rip=0x{} and rsp=0x{}.\n",
|
||||
FmtMeta::Color(Color::PURPLE),
|
||||
FmtMeta::Color(Color::YELLOW),
|
||||
FmtMeta::Pointer(rip as usize),
|
||||
FmtMeta::Pointer(rsp as usize)
|
||||
));
|
||||
interrupt_rust_leave();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn interrupt_req_NMI(rip: u64, rsp: u64, errcode: u64) {}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn interrupt_req_BP(rip: u64, rsp: u64, errcode: u64) {}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn interrupt_req_OF(rip: u64, rsp: u64, errcode: u64) {}
|
|
@ -1,190 +0,0 @@
|
|||
#include <kernel/arch/x86_64/interrupt_procs.h>
|
||||
#include <kernel/arch/x86_64/memm.h>
|
||||
#include <kernel/arch/x86_64/proc.h>
|
||||
#include <kernel/kernel.h>
|
||||
#include <kernel/tty.h>
|
||||
#include <libk/string.h>
|
||||
|
||||
interrupt_req_gen(UNSUPPORTED)
|
||||
{
|
||||
tty **tty0_option = tty_get(0);
|
||||
if (tty0_option == nullptr)
|
||||
{
|
||||
KERNEL_TODO();
|
||||
}
|
||||
tty *tty0 = *tty0_option;
|
||||
tty_text_print(tty0, "Panic: Unsupported interrupt.", RED, BLACK);
|
||||
KERNEL_TODO();
|
||||
}
|
||||
|
||||
static void rip_not_cannonical(u64 rip, tty *tty0)
|
||||
{
|
||||
char num[17];
|
||||
memset(num, 0, sizeof(num));
|
||||
pointer_to_string(rip, num);
|
||||
tty_text_print(tty0, "Panic", RED, BLACK);
|
||||
tty_text_print(tty0, ": Unexpected non-cannonical %rip value ", WHITE, BLACK);
|
||||
tty_text_print(tty0, num, ORANGE, BLACK);
|
||||
tty_text_print(tty0, ".\n", WHITE, BLACK);
|
||||
KERNEL_TODO();
|
||||
}
|
||||
|
||||
interrupt_req_gen(DE)
|
||||
{
|
||||
tty **tty0_option = tty_get(0);
|
||||
if (tty0_option == nullptr)
|
||||
{
|
||||
KERNEL_TODO();
|
||||
}
|
||||
tty *tty0 = *tty0_option;
|
||||
if (!is_cannonical(rip))
|
||||
{
|
||||
rip_not_cannonical(rip, tty0);
|
||||
}
|
||||
if (!is_user_address(rip))
|
||||
{
|
||||
char nums[34];
|
||||
memset(nums, 0, sizeof(nums));
|
||||
pointer_to_string(rip, nums);
|
||||
pointer_to_string(rsp, nums + 17);
|
||||
tty_text_print(tty0, "Panic", RED, BLACK);
|
||||
tty_text_print(tty0, ": Divided by zero occurs in kernel,\n\t", WHITE, BLACK);
|
||||
tty_text_print(tty0, "with %rip=", WHITE, BLACK);
|
||||
tty_text_print(tty0, "0x", ORANGE, BLACK);
|
||||
tty_text_print(tty0, nums, ORANGE, BLACK);
|
||||
tty_text_print(tty0, ", %rsp=", WHITE, BLACK);
|
||||
tty_text_print(tty0, "0x", ORANGE, BLACK);
|
||||
tty_text_print(tty0, nums + 17, ORANGE, BLACK);
|
||||
tty_text_print(tty0, ".\n", WHITE, BLACK);
|
||||
KERNEL_TODO();
|
||||
}
|
||||
else
|
||||
{ // TODO 转储并结束进程
|
||||
KERNEL_TODO();
|
||||
}
|
||||
}
|
||||
|
||||
interrupt_req_gen(BP)
|
||||
{
|
||||
tty **tty0_option = tty_get(0);
|
||||
if (tty0_option == nullptr)
|
||||
{
|
||||
KERNEL_TODO();
|
||||
}
|
||||
tty *tty0 = *tty0_option;
|
||||
if (!is_cannonical(rip))
|
||||
{
|
||||
rip_not_cannonical(rip, tty0);
|
||||
}
|
||||
proc_texture_registers_t *texture = (void *)errcode;
|
||||
if (!is_user_address(rip))
|
||||
{
|
||||
char nums[34];
|
||||
memset(nums, 0, sizeof(nums));
|
||||
pointer_to_string(rip, nums);
|
||||
pointer_to_string(rsp, nums + 17);
|
||||
tty_text_print(tty0, "Debug", PURPLE, BLACK);
|
||||
tty_text_print(tty0, ": Kernel hit a breakpoint,\n\t", WHITE, BLACK);
|
||||
tty_text_print(tty0, "with %rip=", WHITE, BLACK);
|
||||
tty_text_print(tty0, "0x", ORANGE, BLACK);
|
||||
tty_text_print(tty0, nums, ORANGE, BLACK);
|
||||
tty_text_print(tty0, ", %rsp=", WHITE, BLACK);
|
||||
tty_text_print(tty0, "0x", ORANGE, BLACK);
|
||||
tty_text_print(tty0, nums + 17, ORANGE, BLACK);
|
||||
tty_text_print(tty0, ",\n\t", WHITE, BLACK);
|
||||
tty_text_print(tty0, "on texture: \n", WHITE, BLACK);
|
||||
pointer_to_string(texture->rax, nums);
|
||||
tty_text_print(tty0, "rax\t", WHITE, BLACK);
|
||||
tty_text_print(tty0, nums, BLUE, BLACK);
|
||||
tty_text_print(tty0, "\t", WHITE, BLACK);
|
||||
pointer_to_string(texture->rcx, nums);
|
||||
tty_text_print(tty0, "rcx\t", WHITE, BLACK);
|
||||
tty_text_print(tty0, nums, BLUE, BLACK);
|
||||
tty_text_print(tty0, "\n", WHITE, BLACK);
|
||||
pointer_to_string(texture->rbx, nums);
|
||||
tty_text_print(tty0, "rbx\t", WHITE, BLACK);
|
||||
tty_text_print(tty0, nums, BLUE, BLACK);
|
||||
tty_text_print(tty0, "\t", WHITE, BLACK);
|
||||
pointer_to_string(texture->rdx, nums);
|
||||
tty_text_print(tty0, "rdx\t", WHITE, BLACK);
|
||||
tty_text_print(tty0, nums, BLUE, BLACK);
|
||||
tty_text_print(tty0, "\n", WHITE, BLACK);
|
||||
pointer_to_string(texture->rsi, nums);
|
||||
tty_text_print(tty0, "rsi\t", WHITE, BLACK);
|
||||
tty_text_print(tty0, nums, BLUE, BLACK);
|
||||
tty_text_print(tty0, "\t", WHITE, BLACK);
|
||||
pointer_to_string(texture->rdi, nums);
|
||||
tty_text_print(tty0, "rdi\t", WHITE, BLACK);
|
||||
tty_text_print(tty0, nums, BLUE, BLACK);
|
||||
tty_text_print(tty0, "\n", WHITE, BLACK);
|
||||
pointer_to_string(texture->rbp, nums);
|
||||
tty_text_print(tty0, "rbp\t", WHITE, BLACK);
|
||||
tty_text_print(tty0, nums, BLUE, BLACK);
|
||||
tty_text_print(tty0, "\t", WHITE, BLACK);
|
||||
pointer_to_string(texture->rsp, nums);
|
||||
tty_text_print(tty0, "rsp\t", WHITE, BLACK);
|
||||
tty_text_print(tty0, nums, BLUE, BLACK);
|
||||
tty_text_print(tty0, "\n", WHITE, BLACK);
|
||||
pointer_to_string(texture->rip, nums);
|
||||
tty_text_print(tty0, "rip\t", WHITE, BLACK);
|
||||
tty_text_print(tty0, nums, BLUE, BLACK);
|
||||
tty_text_print(tty0, "\t", WHITE, BLACK);
|
||||
pointer_to_string(texture->rflags, nums);
|
||||
tty_text_print(tty0, "rflags\t", WHITE, BLACK);
|
||||
tty_text_print(tty0, nums, BLUE, BLACK);
|
||||
tty_text_print(tty0, "\n", WHITE, BLACK);
|
||||
pointer_to_string(texture->r8, nums);
|
||||
tty_text_print(tty0, "r8\t", WHITE, BLACK);
|
||||
tty_text_print(tty0, nums, BLUE, BLACK);
|
||||
tty_text_print(tty0, "\t", WHITE, BLACK);
|
||||
pointer_to_string(texture->r9, nums);
|
||||
tty_text_print(tty0, "r9\t", WHITE, BLACK);
|
||||
tty_text_print(tty0, nums, BLUE, BLACK);
|
||||
tty_text_print(tty0, "\n", WHITE, BLACK);
|
||||
pointer_to_string(texture->r10, nums);
|
||||
tty_text_print(tty0, "r10\t", WHITE, BLACK);
|
||||
tty_text_print(tty0, nums, BLUE, BLACK);
|
||||
tty_text_print(tty0, "\t", WHITE, BLACK);
|
||||
pointer_to_string(texture->r11, nums);
|
||||
tty_text_print(tty0, "r11\t", WHITE, BLACK);
|
||||
tty_text_print(tty0, nums, BLUE, BLACK);
|
||||
tty_text_print(tty0, "\n", WHITE, BLACK);
|
||||
pointer_to_string(texture->r12, nums);
|
||||
tty_text_print(tty0, "r12\t", WHITE, BLACK);
|
||||
tty_text_print(tty0, nums, BLUE, BLACK);
|
||||
tty_text_print(tty0, "\t", WHITE, BLACK);
|
||||
pointer_to_string(texture->r13, nums);
|
||||
tty_text_print(tty0, "r13\t", WHITE, BLACK);
|
||||
tty_text_print(tty0, nums, BLUE, BLACK);
|
||||
tty_text_print(tty0, "\n", WHITE, BLACK);
|
||||
pointer_to_string(texture->r14, nums);
|
||||
tty_text_print(tty0, "r14\t", WHITE, BLACK);
|
||||
tty_text_print(tty0, nums, BLUE, BLACK);
|
||||
tty_text_print(tty0, "\t", WHITE, BLACK);
|
||||
pointer_to_string(texture->r15, nums);
|
||||
tty_text_print(tty0, "r15\t", WHITE, BLACK);
|
||||
tty_text_print(tty0, nums, BLUE, BLACK);
|
||||
tty_text_print(tty0, "\n", WHITE, BLACK);
|
||||
pointer_to_string(texture->cs, nums);
|
||||
tty_text_print(tty0, "cs\t", WHITE, BLACK);
|
||||
tty_text_print(tty0, nums, BLUE, BLACK);
|
||||
tty_text_print(tty0, "\t", WHITE, BLACK);
|
||||
pointer_to_string(texture->ss, nums);
|
||||
tty_text_print(tty0, "ss\t", WHITE, BLACK);
|
||||
tty_text_print(tty0, nums, BLUE, BLACK);
|
||||
tty_text_print(tty0, "\n", WHITE, BLACK);
|
||||
pointer_to_string(texture->ds, nums);
|
||||
tty_text_print(tty0, "ds\t", WHITE, BLACK);
|
||||
tty_text_print(tty0, nums, BLUE, BLACK);
|
||||
tty_text_print(tty0, "\t", WHITE, BLACK);
|
||||
pointer_to_string(texture->es, nums);
|
||||
tty_text_print(tty0, "es\t", WHITE, BLACK);
|
||||
tty_text_print(tty0, nums, BLUE, BLACK);
|
||||
tty_text_print(tty0, "\n", WHITE, BLACK);
|
||||
KERNEL_TODO();
|
||||
}
|
||||
else
|
||||
{ // TODO 将当前进程的状态设置为暂停并通知当前进程的调试程序
|
||||
KERNEL_TODO();
|
||||
}
|
||||
}
|
|
@ -63,7 +63,7 @@ interrupt_entry_UNSUPPORTED:
|
|||
call interrupt_req_UNSUPPORTED
|
||||
|
||||
interrupt_entry_leave
|
||||
iret
|
||||
iretq
|
||||
|
||||
global interrupt_entry_DE
|
||||
extern interrupt_req_DE
|
||||
|
@ -75,12 +75,12 @@ interrupt_entry_DE:
|
|||
call interrupt_req_DE
|
||||
|
||||
interrupt_entry_leave
|
||||
iret
|
||||
iretq
|
||||
|
||||
global interrupt_entry_DE
|
||||
global interrupt_entry_NMI
|
||||
interrupt_entry_NMI:
|
||||
; TODO 暂时不需要为这个中断实现任何功能
|
||||
iret
|
||||
iretq
|
||||
|
||||
global interrupt_entry_BP
|
||||
extern interrupt_req_BP
|
||||
|
@ -94,4 +94,16 @@ interrupt_entry_BP:
|
|||
call interrupt_req_BP
|
||||
|
||||
interrupt_entry_leave
|
||||
iret
|
||||
iretq
|
||||
|
||||
global interrupt_entry_OF
|
||||
extern interrupt_req_OF
|
||||
interrupt_entry_OF:
|
||||
interrupt_entry_enter
|
||||
|
||||
mov rdi, [rsp + 128]
|
||||
mov rsi, [rsp + 152]
|
||||
call interrupt_req_OF
|
||||
|
||||
interrupt_entry_leave
|
||||
iretq
|
||||
|
|
|
@ -20,6 +20,8 @@ void interrupt_init()
|
|||
interrupt_register_gate(gate, 2);
|
||||
trap_gate_generate(gate, interrupt_entry_sym(BP));
|
||||
interrupt_register_gate(gate, 3);
|
||||
trap_gate_generate(gate, interrupt_entry_sym(OF));
|
||||
interrupt_register_gate(gate, 4);
|
||||
|
||||
interrupt_open();
|
||||
}
|
||||
|
|
|
@ -9,3 +9,30 @@ interrupt_open:
|
|||
interrupt_close:
|
||||
cli
|
||||
ret
|
||||
|
||||
global interrupt_rust_enter
|
||||
extern TSS
|
||||
; usize interrupt_rust_enter()
|
||||
; 返回值用于为寄存器rax占位
|
||||
interrupt_rust_enter:
|
||||
; *(rsp - 8) = *(TSS + 36)
|
||||
mov rax, [TSS + 36]
|
||||
mov qword [rsp - 8], rax
|
||||
; *(TSS + 36) = rsp - 8
|
||||
mov rax, TSS
|
||||
lea rax, [rax + 36]
|
||||
mov [rax], rsp
|
||||
sub qword [rax], 8
|
||||
sti
|
||||
ret
|
||||
|
||||
global interrupt_rust_leave
|
||||
extern TSS
|
||||
; usize interrupt_rust_leave()
|
||||
; 返回值用于为寄存器rax占位
|
||||
interrupt_rust_leave:
|
||||
cli
|
||||
; *(TSS + 36) = *(rsp - 8)
|
||||
mov rax, [rsp - 8]
|
||||
mov [TSS + 36], rax
|
||||
ret
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
pub mod interrupt;
|
||||
pub mod proc;
|
|
@ -0,0 +1,32 @@
|
|||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct RegisterTexture {
|
||||
es: u16,
|
||||
ds: u16,
|
||||
reserved: u32,
|
||||
r15: u64,
|
||||
r14: u64,
|
||||
r13: u64,
|
||||
r12: u64,
|
||||
r11: u64,
|
||||
r10: u64,
|
||||
r9: u64,
|
||||
r8: u64,
|
||||
rdi: u64,
|
||||
rsi: u64,
|
||||
rdx: u64,
|
||||
rbx: u64,
|
||||
rcx: u64,
|
||||
rax: u64,
|
||||
rbp: u64,
|
||||
rip: u64,
|
||||
cs: u64,
|
||||
rflags: u64,
|
||||
rsp: u64,
|
||||
ss: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ProcessTexture {
|
||||
register: RegisterTexture,
|
||||
}
|
|
@ -11,6 +11,7 @@ extern "C" {
|
|||
pub struct SystemTimeError(Duration);
|
||||
|
||||
#[derive(Clone, Copy, Hash)]
|
||||
#[derive(Default)]
|
||||
pub struct SystemTime {
|
||||
unix_time: usize,
|
||||
ns_time: usize,
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use alloc::vec;
|
||||
use alloc::vec::Vec;
|
||||
use crate::libk::alloc::vec::Vec;
|
||||
|
||||
use super::{
|
||||
clock::time::SystemTime,
|
||||
|
@ -28,12 +27,12 @@ pub struct KernelLogger {
|
|||
impl KernelLogger {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
fatal_queue: vec![],
|
||||
error_queue: vec![],
|
||||
warning_queue: vec![],
|
||||
info_queue: vec![],
|
||||
debug_queue: vec![],
|
||||
trace_queue: vec![],
|
||||
fatal_queue: Vec::new(),
|
||||
error_queue: Vec::new(),
|
||||
warning_queue: Vec::new(),
|
||||
info_queue: Vec::new(),
|
||||
debug_queue: Vec::new(),
|
||||
trace_queue: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,105 +90,18 @@ impl KernelLogger {
|
|||
self.trace_queue.push((SystemTime::now(), msg));
|
||||
}
|
||||
|
||||
pub fn iter(&self, level: LoggerLevel) -> LogIterator {
|
||||
let mut logs = vec![];
|
||||
match level {
|
||||
LoggerLevel::Fatal => {
|
||||
logs.push(&self.fatal_queue);
|
||||
}
|
||||
LoggerLevel::Error => {
|
||||
logs.push(&self.fatal_queue);
|
||||
logs.push(&self.error_queue);
|
||||
}
|
||||
LoggerLevel::Warning => {
|
||||
logs.push(&self.fatal_queue);
|
||||
logs.push(&self.error_queue);
|
||||
logs.push(&self.warning_queue);
|
||||
}
|
||||
LoggerLevel::Info => {
|
||||
logs.push(&self.fatal_queue);
|
||||
logs.push(&self.error_queue);
|
||||
logs.push(&self.warning_queue);
|
||||
logs.push(&self.info_queue);
|
||||
}
|
||||
LoggerLevel::Debug => {
|
||||
logs.push(&self.fatal_queue);
|
||||
logs.push(&self.error_queue);
|
||||
logs.push(&self.warning_queue);
|
||||
logs.push(&self.info_queue);
|
||||
logs.push(&self.debug_queue);
|
||||
}
|
||||
LoggerLevel::Trace => {
|
||||
logs.push(&self.fatal_queue);
|
||||
logs.push(&self.error_queue);
|
||||
logs.push(&self.warning_queue);
|
||||
logs.push(&self.info_queue);
|
||||
logs.push(&self.debug_queue);
|
||||
logs.push(&self.trace_queue);
|
||||
}
|
||||
}
|
||||
let mut res = vec![];
|
||||
let mut indeces = Vec::new();
|
||||
for _ in 0..logs.len() {
|
||||
indeces.push(0usize);
|
||||
}
|
||||
let all_end = |indeces: &Vec<usize>, logs: &Vec<&Vec<(SystemTime, Message)>>| {
|
||||
for i in 0..indeces.len() {
|
||||
if indeces[i] < logs.len() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
};
|
||||
while !all_end(&indeces, &logs) {
|
||||
let mut min_ind = None;
|
||||
let mut min = None;
|
||||
for i in 0..indeces.len() {
|
||||
if indeces[i] >= logs[i].len() {
|
||||
continue;
|
||||
}
|
||||
if let Some(minx) = min.as_mut() {
|
||||
if logs[i][indeces[i]].0 < *minx {
|
||||
*minx = logs[i][indeces[i]].0;
|
||||
min_ind = Some(i);
|
||||
}
|
||||
} else {
|
||||
min = Some(logs[i][indeces[i]].0);
|
||||
min_ind = Some(i);
|
||||
}
|
||||
}
|
||||
if let Some(mini) = min_ind {
|
||||
res.push(&logs[mini][indeces[mini]]);
|
||||
indeces[mini] += 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
LogIterator { logs: res }
|
||||
pub fn iter(&self, _level: LoggerLevel) -> LogIterator {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LogIterator<'a> {
|
||||
logs: Vec<&'a (SystemTime, Message)>,
|
||||
pub struct LogIterator {
|
||||
}
|
||||
|
||||
impl<'a> Iterator for LogIterator<'a> {
|
||||
impl Iterator for LogIterator {
|
||||
type Item = Message;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let res = if let Some((time, msg)) = self.logs.first() {
|
||||
Some(
|
||||
MessageBuilder::new()
|
||||
.message(time)
|
||||
.append(MessageBuilder::from_message(msg.clone()))
|
||||
.build(),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if let Some(_) = res {
|
||||
self.logs.remove(0);
|
||||
}
|
||||
res
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,6 +48,8 @@ void kmain(void *mb2_bootinfo)
|
|||
// 初始化中断管理
|
||||
interrupt_init();
|
||||
|
||||
int i = 1 / 0;
|
||||
|
||||
// 初始化系统调用
|
||||
syscall_init();
|
||||
|
||||
|
|
|
@ -1,22 +1,7 @@
|
|||
use crate::message;
|
||||
|
||||
use super::{
|
||||
klog::{KernelLogger, LoggerLevel},
|
||||
tty::tty::{BuilderFunctions::*, Color, Tty},
|
||||
};
|
||||
use crate::kernel::tty::tty::Tty;
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn kmain_rust() -> ! {
|
||||
let tty = Tty::from_id(0).unwrap();
|
||||
let mut logger = KernelLogger::new();
|
||||
logger.info(message!(
|
||||
Msg("Hello, "),
|
||||
Msg("Metaverse"),
|
||||
FgColor(Color::GREEN),
|
||||
Msg("!\n")
|
||||
));
|
||||
for msg in logger.iter(LoggerLevel::Info) {
|
||||
tty.print(msg);
|
||||
}
|
||||
loop {}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,6 @@ allocator_t *memm_allocator_new(void *start, usize length, usize type, usize pid
|
|||
allocator_t *allocator = start;
|
||||
allocator->magic = MEMM_ALLOCATOR_MAGIC;
|
||||
allocator->full = false;
|
||||
allocator->pid = 0;
|
||||
allocator->size = length;
|
||||
allocator->type = type;
|
||||
switch (type)
|
||||
|
@ -71,10 +70,6 @@ void memm_free(void *mem)
|
|||
allocator_t *allocator = memory_manager.kernel_base_allocator;
|
||||
if (allocator->magic != MEMM_ALLOCATOR_MAGIC)
|
||||
return;
|
||||
if (is_user_address((u64)mem))
|
||||
{
|
||||
mem = mem - allocator->userspace + (void *)allocator;
|
||||
}
|
||||
allocator->free(allocator->allocator_instance, mem);
|
||||
if (allocator->full)
|
||||
allocator->full = false;
|
||||
|
|
|
@ -6,9 +6,9 @@ use core::{
|
|||
};
|
||||
|
||||
extern "C" {
|
||||
pub fn memm_kernel_allocate(size: usize) -> *mut u8;
|
||||
fn memm_kernel_allocate(size: usize) -> *mut u8;
|
||||
// pub fn memm_user_allocate(size: usize, pid: usize);
|
||||
pub fn memm_free(mem: *mut u8);
|
||||
fn memm_free(mem: *mut u8);
|
||||
}
|
||||
|
||||
pub struct KernelAllocator {}
|
||||
|
@ -31,4 +31,4 @@ unsafe impl GlobalAlloc for KernelAllocator {
|
|||
}
|
||||
|
||||
#[global_allocator]
|
||||
static KERNEL_ALLOCATOR: KernelAllocator = KernelAllocator {};
|
||||
pub static KERNEL_ALLOCATOR: KernelAllocator = KernelAllocator {};
|
||||
|
|
|
@ -1 +1 @@
|
|||
mod memm;
|
||||
pub mod memm;
|
||||
|
|
|
@ -3,4 +3,4 @@ pub mod klog;
|
|||
pub mod main;
|
||||
pub mod memm;
|
||||
pub mod tty;
|
||||
pub mod sync;
|
||||
pub mod arch;
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
pub mod rwlock;
|
|
@ -1,129 +0,0 @@
|
|||
use core::{ops::{Deref, DerefMut}, ptr::null_mut};
|
||||
|
||||
use alloc::{vec, vec::Vec};
|
||||
|
||||
/// ## RwLock<T>
|
||||
/// 读写锁
|
||||
///
|
||||
/// * 对于写入操作:
|
||||
///
|
||||
/// 锁没有占用时,获取锁,并执行闭包。
|
||||
///
|
||||
/// 当锁已经被占用,将闭包悬挂。
|
||||
///
|
||||
/// 释放锁时,将所有悬挂的闭包都执行。
|
||||
///
|
||||
/// 正在释放锁时,`write`方法返回`Err(())`
|
||||
///
|
||||
/// ```
|
||||
/// let num = 6;
|
||||
/// let num = RwLock::new(num);
|
||||
/// if let Err(()) = num.write(
|
||||
/// |n| *n = 10
|
||||
/// ) {}
|
||||
/// let numstr = format!("{}", num.read());
|
||||
/// ````
|
||||
pub struct RwLock<'a, T> {
|
||||
obj: T,
|
||||
locked: bool,
|
||||
dealing_hanged: bool,
|
||||
ptr: *mut RwLockWriteGuard<'a, T>,
|
||||
hanging: Vec<&'a dyn Fn(&mut T)>,
|
||||
}
|
||||
|
||||
unsafe impl<T> Send for RwLock<'_, T> {}
|
||||
unsafe impl<T> Sync for RwLock<'_, T> {}
|
||||
|
||||
impl<'a, T> RwLock<'a, T> {
|
||||
pub fn new(obj: T) -> Self {
|
||||
Self {
|
||||
obj,
|
||||
locked: false,
|
||||
dealing_hanged: false,
|
||||
ptr: null_mut(),
|
||||
hanging: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read(&self) -> RwLockReadGuard<T> {
|
||||
RwLockReadGuard { obj: &self.obj }
|
||||
}
|
||||
|
||||
pub fn write(&'a mut self, f: &'a dyn Fn(&mut T)) -> Result<RwLockWriteGuard<T>, ()> {
|
||||
if self.dealing_hanged {
|
||||
Err(())
|
||||
} else if !self.locked {
|
||||
self.locked = true;
|
||||
f(&mut self.obj);
|
||||
let ptr = { self as *mut RwLock<'a, T> };
|
||||
let obj = &mut self.obj;
|
||||
let mut res = RwLockWriteGuard {
|
||||
obj,
|
||||
ptr,
|
||||
must_deal_hang: false,
|
||||
};
|
||||
self.ptr = &mut res as *mut RwLockWriteGuard<'_, T>;
|
||||
Ok(res)
|
||||
} else {
|
||||
self.hanging.push(f);
|
||||
let ptr = { self as *mut RwLock<'a, T> };
|
||||
let obj = &mut self.obj;
|
||||
Ok(RwLockWriteGuard {
|
||||
obj,
|
||||
ptr,
|
||||
must_deal_hang: false,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RwLockReadGuard<'a, T> {
|
||||
obj: &'a T,
|
||||
}
|
||||
|
||||
impl<'a, T> Deref for RwLockReadGuard<'a, T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.obj
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Drop for RwLockReadGuard<'a, T> {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
pub struct RwLockWriteGuard<'a, T> {
|
||||
obj: &'a mut T,
|
||||
ptr: *mut RwLock<'a, T>,
|
||||
must_deal_hang: bool,
|
||||
}
|
||||
|
||||
impl<'a, T> Deref for RwLockWriteGuard<'a, T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.obj
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> DerefMut for RwLockWriteGuard<'a, T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
self.obj
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Drop for RwLockWriteGuard<'a, T> {
|
||||
fn drop(&mut self) {
|
||||
if self.must_deal_hang {
|
||||
let p = unsafe { &mut *self.ptr };
|
||||
p.dealing_hanged = true;
|
||||
for f in p.hanging.iter() {
|
||||
f(self.obj);
|
||||
}
|
||||
p.hanging.clear();
|
||||
p.dealing_hanged = false;
|
||||
p.locked = false;
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,46 +1,28 @@
|
|||
pub mod tty;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! message_msg {
|
||||
() => {};
|
||||
( $builder : expr, $e : expr) => {
|
||||
$builder.message_mut($e);
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! message_fgc {
|
||||
() => {};
|
||||
( $builder : expr, $e : expr) => {
|
||||
$builder.foreground_color_mut($e);
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! message_bgc {
|
||||
() => {};
|
||||
( $builder : expr, $e : expr ) => {
|
||||
$builder.background_color_mut($e);
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! message {
|
||||
( $( $e : expr ),* ) => {{
|
||||
( $fmtter : expr ) => {{
|
||||
use crate::kernel::tty::tty::MessageBuilder;
|
||||
MessageBuilder::new()
|
||||
.message($fmtter)
|
||||
.build()
|
||||
}};
|
||||
( $fmtter : expr, $( $e : expr ),* ) => {{
|
||||
use crate::{
|
||||
kernel::tty::tty::{MessageBuilder, BuilderFunctions},
|
||||
message_msg, message_fgc, message_bgc
|
||||
kernel::tty::tty::{
|
||||
MessageBuilder,
|
||||
FmtMeta,
|
||||
Color,
|
||||
format_message
|
||||
},
|
||||
libk::alloc::vec::Vec,
|
||||
};
|
||||
let mut tmp_builder = MessageBuilder::new();
|
||||
let mut formatter = $fmtter.chars().collect::<Vec<char>>();
|
||||
let builder = MessageBuilder::new();
|
||||
$(
|
||||
if let BuilderFunctions::Msg(e) = $e {
|
||||
message_msg!(tmp_builder, e);
|
||||
} else if let BuilderFunctions::FgColor(c) = $e {
|
||||
message_fgc!(tmp_builder, c);
|
||||
} else if let BuilderFunctions::BgColor(c) = $e {
|
||||
message_bgc!(tmp_builder, c);
|
||||
}
|
||||
let builder = builder.append(format_message(&mut formatter, $e));
|
||||
)*
|
||||
tmp_builder.build()
|
||||
builder.build()
|
||||
}};
|
||||
}
|
||||
|
|
|
@ -77,6 +77,7 @@ inline static void scroll_buffer(
|
|||
usize dist)
|
||||
{
|
||||
memcpy(buffer, buffer + width * pixsize * dist, (height - dist) * width * pixsize);
|
||||
memset(buffer + (height - dist) * width * pixsize, 0, dist * width * pixsize);
|
||||
}
|
||||
|
||||
inline static void putchar(
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use core::ptr::null_mut;
|
||||
|
||||
use alloc::{
|
||||
use crate::libk::alloc::{
|
||||
boxed::Box,
|
||||
string::{String, ToString},
|
||||
vec,
|
||||
vec::Vec,
|
||||
};
|
||||
|
||||
|
@ -141,7 +141,7 @@ impl Tty {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub struct Color(pub u8, pub u8, pub u8);
|
||||
|
||||
impl Color {
|
||||
|
@ -169,7 +169,7 @@ pub struct Resolution {
|
|||
pub height: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Default)]
|
||||
pub struct MessageSection {
|
||||
msg: String,
|
||||
fgcolor: Color,
|
||||
|
@ -179,14 +179,14 @@ pub struct MessageSection {
|
|||
/// ## Message
|
||||
///
|
||||
/// 用`MessageBuilder`构造一个`Message`对象
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Default)]
|
||||
pub struct Message(Vec<MessageSection>);
|
||||
|
||||
impl ToString for Message {
|
||||
fn to_string(&self) -> String {
|
||||
let mut res = String::new();
|
||||
for MessageSection { msg, .. } in self.0.iter() {
|
||||
res += msg;
|
||||
res += msg.clone();
|
||||
}
|
||||
res
|
||||
}
|
||||
|
@ -212,7 +212,7 @@ impl ToString for Message {
|
|||
/// ```rust
|
||||
/// use crate::kernel::tty::tty::BuilderFunctions::*;
|
||||
///
|
||||
/// message!(
|
||||
/// message_raw!(
|
||||
/// Msg("Hello, "),
|
||||
/// Msg("Metaverse"),
|
||||
/// FgColor(Color::GREEN),
|
||||
|
@ -233,8 +233,8 @@ pub struct MessageBuilder {
|
|||
msg: Message,
|
||||
}
|
||||
|
||||
pub enum BuilderFunctions<'a> {
|
||||
Msg(&'a str),
|
||||
pub enum BuilderFunctions<T: ToString> {
|
||||
Msg(T),
|
||||
FgColor(Color),
|
||||
BgColor(Color),
|
||||
}
|
||||
|
@ -242,10 +242,14 @@ pub enum BuilderFunctions<'a> {
|
|||
impl MessageBuilder {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
msg: Message(vec![]),
|
||||
msg: Message(Vec::new()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.msg.0.is_empty()
|
||||
}
|
||||
|
||||
pub fn from_message(msg: Message) -> Self {
|
||||
Self { msg }
|
||||
}
|
||||
|
@ -302,3 +306,82 @@ impl MessageBuilder {
|
|||
self.msg
|
||||
}
|
||||
}
|
||||
|
||||
pub enum FmtMeta {
|
||||
Color(Color),
|
||||
String(String),
|
||||
ToStringable(Box<dyn ToString>),
|
||||
Hex(u8),
|
||||
Pointer(usize),
|
||||
}
|
||||
|
||||
pub fn format_message(fmt: &mut Vec<char>, meta: FmtMeta) -> MessageBuilder {
|
||||
let mut msgbuilder = MessageBuilder::new();
|
||||
let mut fmt_start = None;
|
||||
let mut fmt_end = None;
|
||||
for i in 0..fmt.len() {
|
||||
if fmt[i] == '{' {
|
||||
fmt_start = Some(i);
|
||||
}
|
||||
if fmt[i] == '}' {
|
||||
fmt_end = Some(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
let tohex = |n: u8| {
|
||||
if n < 10 {
|
||||
(b'0' + n) as char
|
||||
} else {
|
||||
(b'a' + n - 10) as char
|
||||
}
|
||||
};
|
||||
if fmt_start == None || fmt_end == None {
|
||||
msgbuilder.message_mut(&String::from_iter(fmt.iter()));
|
||||
} else {
|
||||
let fmt_start = fmt_start.unwrap();
|
||||
let fmt_end = fmt_end.unwrap();
|
||||
let mut formatter = Vec::new();
|
||||
for _ in fmt_start..=fmt_end {
|
||||
formatter.push(fmt.remove(fmt_start));
|
||||
}
|
||||
formatter.remove(formatter.len() - 1);
|
||||
formatter.remove(0);
|
||||
match meta {
|
||||
FmtMeta::Color(color) => {
|
||||
let first = fmt.split_at(fmt_start).0;
|
||||
msgbuilder.message_mut(&String::from_iter(first.iter()));
|
||||
for _ in 0..fmt_start {
|
||||
fmt.remove(0);
|
||||
}
|
||||
msgbuilder.message_mut(&String::from_iter(formatter.iter()));
|
||||
msgbuilder.foreground_color_mut(color);
|
||||
}
|
||||
FmtMeta::String(s) => {
|
||||
for c in s.chars().rev() {
|
||||
fmt.insert(fmt_start, *c);
|
||||
}
|
||||
}
|
||||
FmtMeta::ToStringable(s) => {
|
||||
for c in s.to_string().chars().rev() {
|
||||
fmt.insert(fmt_start, *c);
|
||||
}
|
||||
}
|
||||
FmtMeta::Hex(num) => {
|
||||
fmt.insert(fmt_start, tohex(num >> 4));
|
||||
fmt.insert(fmt_start, tohex(num & 0xf));
|
||||
}
|
||||
FmtMeta::Pointer(mut p) => {
|
||||
for _ in 0..16 {
|
||||
fmt.insert(fmt_start, tohex((p & 0xf) as u8));
|
||||
p >>= 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut rests = Vec::new();
|
||||
while !fmt.is_empty() && fmt[0] != '{' {
|
||||
rests.push(fmt.remove(0));
|
||||
}
|
||||
msgbuilder.message_mut(&String::from_iter(rests.iter()));
|
||||
msgbuilder
|
||||
}
|
||||
|
|
66
src/lib.rs
66
src/lib.rs
|
@ -1,69 +1,23 @@
|
|||
#![no_std]
|
||||
#![feature(strict_provenance)]
|
||||
#![feature(layout_for_ptr)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::{
|
||||
string::{String, ToString},
|
||||
vec::Vec,
|
||||
};
|
||||
use core::{panic::PanicInfo, ptr::null_mut};
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
use kernel::tty::tty::{self, tty_enable, tty_text_print, Color};
|
||||
use kernel::tty::tty::Tty;
|
||||
|
||||
pub mod kernel;
|
||||
pub mod libk;
|
||||
|
||||
#[panic_handler]
|
||||
unsafe fn kernel_panic_handler(info: &PanicInfo) -> ! {
|
||||
let line_in_file = if let Some(loca) = info.location() {
|
||||
loca.line().to_string()
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
let info = {
|
||||
let mut v = Vec::new();
|
||||
v.push(("Kernel Panic: ", (Color::RED, Color::BLACK)));
|
||||
v.push((
|
||||
if let Some(loca) = info.location() {
|
||||
loca.file()
|
||||
} else {
|
||||
"NoFile"
|
||||
},
|
||||
(Color::GREEN, Color::BLACK),
|
||||
unsafe fn kernel_panic_handler(_info: &PanicInfo) -> ! {
|
||||
let tty = Tty::from_id(0).unwrap();
|
||||
tty.enable();
|
||||
tty.print(message!(
|
||||
"Hit a {Rust} panic.",
|
||||
FmtMeta::Color(Color::ORANGE)
|
||||
));
|
||||
v.push((":", (Color::WHITE, Color::BLACK)));
|
||||
v.push((
|
||||
if let Some(_) = info.location() {
|
||||
line_in_file.as_str()
|
||||
} else {
|
||||
"NoLine"
|
||||
},
|
||||
(Color::WHITE, Color::BLACK),
|
||||
));
|
||||
v.push((": ", (Color::WHITE, Color::BLACK)));
|
||||
v.push((
|
||||
if let Some(&s) = info.payload().downcast_ref::<&str>() {
|
||||
s
|
||||
} else {
|
||||
"Unknown panic."
|
||||
},
|
||||
(Color::BLUE, Color::BLACK),
|
||||
));
|
||||
v.push(("\n", (Color::BLACK, Color::BLACK)));
|
||||
v
|
||||
};
|
||||
let tty = tty::tty_get(0);
|
||||
if tty != null_mut() {
|
||||
let tty = *tty;
|
||||
tty_enable(tty);
|
||||
for (msgo, (fgc, bgc)) in info.into_iter() {
|
||||
let msg = String::from(msgo).as_bytes_mut() as *mut [u8] as *mut u8;
|
||||
let p = msg.offset(msgo.len() as isize);
|
||||
let swp = *p;
|
||||
*p = 0;
|
||||
tty_text_print(tty, msg, u32::from(fgc), u32::from(bgc));
|
||||
*p = swp;
|
||||
}
|
||||
}
|
||||
loop {}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
use core::alloc::{GlobalAlloc, Layout};
|
||||
|
||||
use crate::kernel::memm::memm::KERNEL_ALLOCATOR;
|
||||
|
||||
pub unsafe fn alloc(layout: Layout) -> *mut u8 {
|
||||
KERNEL_ALLOCATOR.alloc(layout)
|
||||
}
|
||||
|
||||
pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
|
||||
KERNEL_ALLOCATOR.dealloc(ptr, layout);
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
use core::{
|
||||
alloc::Layout,
|
||||
mem::transmute,
|
||||
ops::{Deref, DerefMut},
|
||||
ptr::addr_of,
|
||||
};
|
||||
|
||||
use crate::libk::alloc::alloc::{alloc, dealloc};
|
||||
|
||||
pub struct Box<T: ?Sized> {
|
||||
inner: *mut T,
|
||||
}
|
||||
|
||||
impl<T> Box<T> {
|
||||
pub fn new(t: T) -> Self {
|
||||
unsafe {
|
||||
let inner = alloc(Layout::for_value(&t));
|
||||
inner.copy_from(addr_of!(t).cast(), 1);
|
||||
Self {
|
||||
inner: transmute(inner),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Deref for Box<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
unsafe { self.inner.as_ref().unwrap() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> DerefMut for Box<T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
unsafe { self.inner.as_mut().unwrap() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Drop for Box<T> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
dealloc(
|
||||
self.inner.cast(),
|
||||
Layout::for_value_raw(self.inner.cast_const()),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
pub mod alloc;
|
||||
pub mod boxed;
|
||||
pub mod string;
|
||||
pub mod vec;
|
|
@ -0,0 +1,386 @@
|
|||
use core::ops::{Add, AddAssign};
|
||||
|
||||
use super::vec::{Vec, VecIterator};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct String {
|
||||
data: Vec<char>,
|
||||
u8data: Vec<u8>,
|
||||
}
|
||||
|
||||
impl String {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
data: Vec::new(),
|
||||
u8data: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.data.len()
|
||||
}
|
||||
|
||||
pub fn chars(&self) -> VecIterator<char> {
|
||||
self.data.iter()
|
||||
}
|
||||
|
||||
pub fn as_bytes(&self) -> &[u8] {
|
||||
&self.u8data[..]
|
||||
}
|
||||
|
||||
pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] {
|
||||
&mut self.u8data[..]
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, index: usize, item: char) {
|
||||
self.data.insert(index, item);
|
||||
self.u8data.insert(index, item as u8);
|
||||
}
|
||||
}
|
||||
|
||||
impl FromIterator<char> for String {
|
||||
fn from_iter<T: IntoIterator<Item = char>>(iter: T) -> Self {
|
||||
let data = Vec::from_iter(iter);
|
||||
let u8data = Vec::from_iter(data.iter().map(|c| *c as u8));
|
||||
Self { data, u8data }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FromIterator<&'a char> for String {
|
||||
fn from_iter<T: IntoIterator<Item = &'a char>>(iter: T) -> Self {
|
||||
let data = Vec::from_iter(iter.into_iter().map(|c| *c));
|
||||
let u8data = Vec::from_iter(data.iter().map(|c| *c as u8));
|
||||
Self { data, u8data }
|
||||
}
|
||||
}
|
||||
|
||||
impl ToString for String {
|
||||
fn to_string(&self) -> String {
|
||||
self.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for String {
|
||||
type Output = Self;
|
||||
|
||||
fn add(mut self, rhs: Self) -> Self::Output {
|
||||
self.data.append(&mut rhs.chars().map(|c| *c).collect());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign for String {
|
||||
fn add_assign(&mut self, rhs: String) {
|
||||
*self = self.clone() + rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for String {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
data: self.data.clone(),
|
||||
u8data: self.u8data.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ToString {
|
||||
fn to_string(&self) -> String;
|
||||
fn to_octal_string(&self) -> String {
|
||||
String::new()
|
||||
}
|
||||
fn to_hex_string(&self) -> String {
|
||||
String::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToString for str {
|
||||
fn to_string(&self) -> String {
|
||||
String::from_iter(self.chars())
|
||||
}
|
||||
}
|
||||
|
||||
impl ToString for &'static str {
|
||||
fn to_string(&self) -> String {
|
||||
(*self).to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToString for u8 {
|
||||
fn to_string(&self) -> String {
|
||||
let mut num = *self;
|
||||
let mut res = String::new();
|
||||
while num != 0 {
|
||||
res.insert(0, ((num % 10) as u8 + b'0') as char);
|
||||
num /= 10;
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
fn to_octal_string(&self) -> String {
|
||||
let mut num = *self;
|
||||
let mut res = String::new();
|
||||
while num != 0 {
|
||||
res.insert(0, ((num % 8) as u8 + b'0') as char);
|
||||
num /= 8;
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
fn to_hex_string(&self) -> String {
|
||||
let tohex = |x| {
|
||||
if x < 10 {
|
||||
x as u8 + b'0'
|
||||
} else {
|
||||
x as u8 - 10 + b'a'
|
||||
}
|
||||
};
|
||||
let mut num = *self;
|
||||
let mut res = String::new();
|
||||
while num != 0 {
|
||||
res.insert(0, tohex(num % 16) as char);
|
||||
num /= 16;
|
||||
}
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl ToString for u16 {
|
||||
fn to_string(&self) -> String {
|
||||
let mut num = *self;
|
||||
let mut res = String::new();
|
||||
while num != 0 {
|
||||
res.insert(0, ((num % 10) as u8 + b'0') as char);
|
||||
num /= 10;
|
||||
}
|
||||
if res.len() == 0 {
|
||||
res.insert(0, '0');
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
fn to_octal_string(&self) -> String {
|
||||
let mut num = *self;
|
||||
let mut res = String::new();
|
||||
while num != 0 {
|
||||
res.insert(0, ((num % 8) as u8 + b'0') as char);
|
||||
num /= 8;
|
||||
}
|
||||
if res.len() == 0 {
|
||||
res.insert(0, '0');
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
fn to_hex_string(&self) -> String {
|
||||
let tohex = |x| {
|
||||
if x < 10 {
|
||||
x as u8 + b'0'
|
||||
} else {
|
||||
x as u8 - 10 + b'a'
|
||||
}
|
||||
};
|
||||
let mut num = *self;
|
||||
let mut res = String::new();
|
||||
while num != 0 {
|
||||
res.insert(0, tohex(num % 16) as char);
|
||||
num /= 16;
|
||||
}
|
||||
if res.len() == 0 {
|
||||
res.insert(0, '0');
|
||||
}
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl ToString for u32 {
|
||||
fn to_string(&self) -> String {
|
||||
let mut num = *self;
|
||||
let mut res = String::new();
|
||||
while num != 0 {
|
||||
res.insert(0, ((num % 10) as u8 + b'0') as char);
|
||||
num /= 10;
|
||||
}
|
||||
if res.len() == 0 {
|
||||
res.insert(0, '0');
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
fn to_octal_string(&self) -> String {
|
||||
let mut num = *self;
|
||||
let mut res = String::new();
|
||||
while num != 0 {
|
||||
res.insert(0, ((num % 8) as u8 + b'0') as char);
|
||||
num /= 8;
|
||||
}
|
||||
if res.len() == 0 {
|
||||
res.insert(0, '0');
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
fn to_hex_string(&self) -> String {
|
||||
let tohex = |x| {
|
||||
if x < 10 {
|
||||
x as u8 + b'0'
|
||||
} else {
|
||||
x as u8 - 10 + b'a'
|
||||
}
|
||||
};
|
||||
let mut num = *self;
|
||||
let mut res = String::new();
|
||||
while num != 0 {
|
||||
res.insert(0, tohex(num % 16) as char);
|
||||
num /= 16;
|
||||
}
|
||||
if res.len() == 0 {
|
||||
res.insert(0, '0');
|
||||
}
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl ToString for u64 {
|
||||
fn to_string(&self) -> String {
|
||||
let mut num = *self;
|
||||
let mut res = String::new();
|
||||
while num != 0 {
|
||||
res.insert(0, ((num % 10) as u8 + b'0') as char);
|
||||
num /= 10;
|
||||
}
|
||||
if res.len() == 0 {
|
||||
res.insert(0, '0');
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
fn to_octal_string(&self) -> String {
|
||||
let mut num = *self;
|
||||
let mut res = String::new();
|
||||
while num != 0 {
|
||||
res.insert(0, ((num % 8) as u8 + b'0') as char);
|
||||
num /= 8;
|
||||
}
|
||||
if res.len() == 0 {
|
||||
res.insert(0, '0');
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
fn to_hex_string(&self) -> String {
|
||||
let tohex = |x| {
|
||||
if x < 10 {
|
||||
x as u8 + b'0'
|
||||
} else {
|
||||
x as u8 - 10 + b'a'
|
||||
}
|
||||
};
|
||||
let mut num = *self;
|
||||
let mut res = String::new();
|
||||
while num != 0 {
|
||||
res.insert(0, tohex(num % 16) as char);
|
||||
num /= 16;
|
||||
}
|
||||
if res.len() == 0 {
|
||||
res.insert(0, '0');
|
||||
}
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl ToString for u128 {
|
||||
fn to_string(&self) -> String {
|
||||
let mut num = *self;
|
||||
let mut res = String::new();
|
||||
while num != 0 {
|
||||
res.insert(0, ((num % 10) as u8 + b'0') as char);
|
||||
num /= 10;
|
||||
}
|
||||
if res.len() == 0 {
|
||||
res.insert(0, '0');
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
fn to_octal_string(&self) -> String {
|
||||
let mut num = *self;
|
||||
let mut res = String::new();
|
||||
while num != 0 {
|
||||
res.insert(0, ((num % 8) as u8 + b'0') as char);
|
||||
num /= 8;
|
||||
}
|
||||
if res.len() == 0 {
|
||||
res.insert(0, '0');
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
fn to_hex_string(&self) -> String {
|
||||
let tohex = |x| {
|
||||
if x < 10 {
|
||||
x as u8 + b'0'
|
||||
} else {
|
||||
x as u8 - 10 + b'a'
|
||||
}
|
||||
};
|
||||
let mut num = *self;
|
||||
let mut res = String::new();
|
||||
while num != 0 {
|
||||
res.insert(0, tohex(num % 16) as char);
|
||||
num /= 16;
|
||||
}
|
||||
if res.len() == 0 {
|
||||
res.insert(0, '0');
|
||||
}
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl ToString for usize {
|
||||
fn to_string(&self) -> String {
|
||||
let mut num = *self;
|
||||
let mut res = String::new();
|
||||
while num != 0 {
|
||||
res.insert(0, ((num % 10) as u8 + b'0') as char);
|
||||
num /= 10;
|
||||
}
|
||||
if res.len() == 0 {
|
||||
res.insert(0, '0');
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
fn to_octal_string(&self) -> String {
|
||||
let mut num = *self;
|
||||
let mut res = String::new();
|
||||
while num != 0 {
|
||||
res.insert(0, ((num % 8) as u8 + b'0') as char);
|
||||
num /= 8;
|
||||
}
|
||||
if res.len() == 0 {
|
||||
res.insert(0, '0');
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
fn to_hex_string(&self) -> String {
|
||||
let tohex = |x| {
|
||||
if x < 10 {
|
||||
x as u8 + b'0'
|
||||
} else {
|
||||
x as u8 - 10 + b'a'
|
||||
}
|
||||
};
|
||||
let mut num = *self;
|
||||
let mut res = String::new();
|
||||
while num != 0 {
|
||||
res.insert(0, tohex(num % 16) as char);
|
||||
num /= 16;
|
||||
}
|
||||
if res.len() == 0 {
|
||||
res.insert(0, '0');
|
||||
}
|
||||
res
|
||||
}
|
||||
}
|
|
@ -0,0 +1,284 @@
|
|||
use core::{
|
||||
alloc::Layout,
|
||||
ops::{Index, IndexMut, Range, RangeFull},
|
||||
ptr::addr_of_mut,
|
||||
slice,
|
||||
};
|
||||
|
||||
use crate::libk::{
|
||||
alloc::alloc::{alloc, dealloc},
|
||||
core::ptr::PtrOptions,
|
||||
};
|
||||
|
||||
pub struct Vec<T> {
|
||||
pointer: *mut T,
|
||||
length: usize,
|
||||
capacity: usize,
|
||||
}
|
||||
|
||||
impl<T: Default> Vec<T> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
pointer: unsafe { alloc(Layout::array::<T>(4).unwrap()).cast() },
|
||||
length: 0,
|
||||
capacity: 4,
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn extend_capacity(&mut self) {
|
||||
let newp: *mut T = alloc(Layout::array::<T>(self.capacity * 2).unwrap()).cast();
|
||||
self.pointer.kcopy_to(newp, self.length);
|
||||
dealloc(
|
||||
self.pointer.cast(),
|
||||
Layout::array::<T>(self.capacity).unwrap(),
|
||||
);
|
||||
self.pointer = newp;
|
||||
self.capacity *= 2;
|
||||
}
|
||||
|
||||
pub fn push(&mut self, item: T) {
|
||||
if self.capacity == self.length {
|
||||
unsafe { self.extend_capacity() }
|
||||
}
|
||||
unsafe { self.pointer.offset(self.length as isize).write(item) };
|
||||
self.length += 1;
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, index: usize, item: T) {
|
||||
if self.capacity == self.length {
|
||||
unsafe { self.extend_capacity() }
|
||||
}
|
||||
let rearlen = self.length - index;
|
||||
unsafe {
|
||||
if rearlen != 0 {
|
||||
let tmp = alloc(Layout::array::<T>(rearlen).unwrap()).cast();
|
||||
self.pointer.offset(index as isize).kcopy_to(tmp, rearlen);
|
||||
self.pointer.offset(index as isize).write(item);
|
||||
self.pointer
|
||||
.offset(index as isize + 1)
|
||||
.kcopy_from(tmp, rearlen);
|
||||
} else {
|
||||
self.pointer.offset(self.length as isize).write(item);
|
||||
}
|
||||
}
|
||||
self.length += 1;
|
||||
}
|
||||
|
||||
pub fn append(&mut self, v: &mut Self) {
|
||||
while self.capacity < self.length + v.length {
|
||||
unsafe { self.extend_capacity() }
|
||||
}
|
||||
unsafe {
|
||||
self.pointer
|
||||
.offset(self.length as isize)
|
||||
.kcopy_from(v.pointer.cast_const(), v.length)
|
||||
};
|
||||
self.length += v.length;
|
||||
}
|
||||
|
||||
pub fn split_at(&self, index: usize) -> (&[T], &[T]) {
|
||||
if index >= self.length {
|
||||
panic!("Index out of bound.");
|
||||
}
|
||||
(&self[0..index], &self[index..self.length])
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.length
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.length == 0
|
||||
}
|
||||
|
||||
pub fn last_mut(&mut self) -> Option<&mut T> {
|
||||
unsafe { self.pointer.offset(self.length as isize - 1).as_mut() }
|
||||
}
|
||||
|
||||
pub fn last(&self) -> Option<&T> {
|
||||
unsafe { self.pointer.offset(self.length as isize - 1).as_ref() }
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, index: usize) -> T {
|
||||
if index >= self.length {
|
||||
panic!("Index out of bound.");
|
||||
}
|
||||
let mut t: T = T::default();
|
||||
let pt = addr_of_mut!(t);
|
||||
unsafe {
|
||||
pt.kcopy_from(self.pointer.offset(index as isize).cast_const(), 1);
|
||||
self.pointer.offset(index as isize).kcopy_from(
|
||||
self.pointer.offset(index as isize + 1),
|
||||
self.length - index - 1,
|
||||
);
|
||||
}
|
||||
self.length -= 1;
|
||||
t
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> VecIterator<T> {
|
||||
VecIterator {
|
||||
pointer: self.pointer,
|
||||
index: 0,
|
||||
length: self.length,
|
||||
_phantom: &(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Default> Default for Vec<T> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Default> Index<usize> for Vec<T> {
|
||||
type Output = T;
|
||||
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
unsafe { self.pointer.offset(index as isize).as_ref().unwrap() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Default> Index<Range<usize>> for Vec<T> {
|
||||
type Output = [T];
|
||||
|
||||
fn index(&self, index: Range<usize>) -> &Self::Output {
|
||||
unsafe { &slice::from_raw_parts_mut(self.pointer, self.length)[index] }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Default> Index<RangeFull> for Vec<T> {
|
||||
type Output = [T];
|
||||
|
||||
fn index(&self, _: RangeFull) -> &Self::Output {
|
||||
unsafe { slice::from_raw_parts(self.pointer.cast(), self.length) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Default> IndexMut<RangeFull> for Vec<T> {
|
||||
fn index_mut(&mut self, _: RangeFull) -> &mut Self::Output {
|
||||
unsafe { slice::from_raw_parts_mut(self.pointer.cast(), self.length) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Default> Clone for Vec<T> {
|
||||
fn clone(&self) -> Self {
|
||||
let res = Self {
|
||||
pointer: unsafe { alloc(Layout::array::<T>(self.capacity).unwrap()).cast() },
|
||||
length: self.length,
|
||||
capacity: self.capacity,
|
||||
};
|
||||
unsafe {
|
||||
res.pointer
|
||||
.kcopy_from(self.pointer.cast_const(), self.length)
|
||||
};
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Drop for Vec<T> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
dealloc(
|
||||
self.pointer.cast(),
|
||||
Layout::array::<T>(self.capacity).unwrap(),
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Default> FromIterator<T> for Vec<T> {
|
||||
fn from_iter<U: IntoIterator<Item = T>>(iter: U) -> Self {
|
||||
let mut res = Vec::new();
|
||||
for i in iter {
|
||||
res.push(i);
|
||||
}
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Default> IntoIterator for Vec<T> {
|
||||
type Item = T;
|
||||
|
||||
type IntoIter = VecIter<T>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
VecIter {
|
||||
pointer: self.pointer,
|
||||
index: 0,
|
||||
length: self.length,
|
||||
capacity: self.capacity,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct VecIterator<'a, T> {
|
||||
pointer: *mut T,
|
||||
index: usize,
|
||||
length: usize,
|
||||
_phantom: &'a (),
|
||||
}
|
||||
|
||||
impl<'a, T: 'a> Iterator for VecIterator<'a, T> {
|
||||
type Item = &'a T;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.index == self.length {
|
||||
None
|
||||
} else {
|
||||
let res = unsafe { Some(self.pointer.offset(self.index as isize).as_ref().unwrap()) };
|
||||
self.index += 1;
|
||||
res
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: 'a> DoubleEndedIterator for VecIterator<'a, T> {
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
if self.index == 0 {
|
||||
None
|
||||
} else {
|
||||
self.index -= 1;
|
||||
unsafe { Some(self.pointer.offset(self.index as isize).as_ref().unwrap()) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct VecIter<T> {
|
||||
pointer: *mut T,
|
||||
index: usize,
|
||||
length: usize,
|
||||
capacity: usize,
|
||||
}
|
||||
|
||||
impl<T: Default> Iterator for VecIter<T> {
|
||||
type Item = T;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.index == self.length {
|
||||
None
|
||||
} else {
|
||||
let mut t = T::default();
|
||||
let res = unsafe {
|
||||
self.pointer
|
||||
.offset(self.index as isize)
|
||||
.kcopy_to(addr_of_mut!(t), 1);
|
||||
Some(t)
|
||||
};
|
||||
self.index += 1;
|
||||
res
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Drop for VecIter<T> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
dealloc(
|
||||
self.pointer.cast(),
|
||||
Layout::array::<T>(self.capacity).unwrap(),
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
pub mod ptr;
|
|
@ -0,0 +1,30 @@
|
|||
use core::mem::{size_of, transmute};
|
||||
|
||||
extern "C" {
|
||||
pub fn memset(des: *const u8, src: u8, len: usize);
|
||||
pub fn memcpy(des: *const u8, src: *const u8, len: usize);
|
||||
pub fn strlen(des: *const u8) -> usize;
|
||||
}
|
||||
|
||||
pub trait PtrOptions<T> {
|
||||
unsafe fn kcopy_from(self, src: *const T, count: usize);
|
||||
unsafe fn kcopy_to(self, des: *const T, count: usize);
|
||||
}
|
||||
|
||||
impl<T> PtrOptions<T> for *mut T {
|
||||
unsafe fn kcopy_from(self, src: *const T, count: usize) {
|
||||
memcpy(
|
||||
transmute(self.cast_const()),
|
||||
transmute(src),
|
||||
count * size_of::<T>(),
|
||||
);
|
||||
}
|
||||
|
||||
unsafe fn kcopy_to(self, des: *const T, count: usize) {
|
||||
memcpy(
|
||||
transmute(des),
|
||||
transmute(self.cast_const()),
|
||||
count * size_of::<T>(),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1 +1,2 @@
|
|||
pub mod string;
|
||||
pub mod alloc;
|
||||
pub mod core;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Reference in New Issue