增加内核日志功能 #3
|
@ -0,0 +1,15 @@
|
||||||
|
#ifndef TIME_H
|
||||||
|
#define TIME_H
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
// 使用UNIX时间戳
|
||||||
|
usize system_time_get();
|
||||||
|
|
||||||
|
// 如果硬件支持更高的计时精度,
|
||||||
|
// 此函数提供从系统unix时间开始到现在的纳秒为单位的时间
|
||||||
|
usize system_time_ns_get();
|
||||||
|
|
||||||
|
void system_time_increase();
|
||||||
|
|
||||||
|
#endif
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
typedef enum __tty_type
|
typedef enum __tty_type
|
||||||
{
|
{
|
||||||
invalid = 0,
|
tty_type_invalid = 0,
|
||||||
// 用于在内核刚刚被引导,只有bootloader提供的显示功能时使用
|
// 用于在内核刚刚被引导,只有bootloader提供的显示功能时使用
|
||||||
tty_type_raw_framebuffer = 1,
|
tty_type_raw_framebuffer = 1,
|
||||||
// 用于图形功能初始化后,直接连接图形接口
|
// 用于图形功能初始化后,直接连接图形接口
|
||||||
|
@ -40,8 +40,9 @@ typedef struct __framebuffer framebuffer;
|
||||||
// 文本模式中的字符由tty模块渲染
|
// 文本模式中的字符由tty模块渲染
|
||||||
typedef enum __tty_mode
|
typedef enum __tty_mode
|
||||||
{
|
{
|
||||||
tty_mode_text = 0,
|
tty_mode_invalid = 0,
|
||||||
tty_mode_graphics = 1,
|
tty_mode_text = 1,
|
||||||
|
tty_mode_graphics = 2,
|
||||||
} tty_mode;
|
} tty_mode;
|
||||||
|
|
||||||
typedef struct __tty_text_state
|
typedef struct __tty_text_state
|
||||||
|
@ -55,6 +56,7 @@ typedef struct __tty_text_state
|
||||||
typedef struct __tty
|
typedef struct __tty
|
||||||
{
|
{
|
||||||
usize id;
|
usize id;
|
||||||
|
usize width, height;
|
||||||
tty_type type;
|
tty_type type;
|
||||||
tty_typeinfo typeinfo;
|
tty_typeinfo typeinfo;
|
||||||
tty_mode mode;
|
tty_mode mode;
|
||||||
|
@ -120,6 +122,14 @@ void tty_text_print(tty *ttyx, char *string, u32 color, u32 bgcolor);
|
||||||
|
|
||||||
#define gen_color(r, g, b) (((r) << 16) | ((g) << 8) | (b))
|
#define gen_color(r, g, b) (((r) << 16) | ((g) << 8) | (b))
|
||||||
|
|
||||||
|
usize tty_get_width(tty *ttyx);
|
||||||
|
usize tty_get_height(tty *ttyx);
|
||||||
|
|
||||||
|
tty_type tty_get_type(tty *ttyx);
|
||||||
|
tty_mode tty_get_mode(tty *ttyx);
|
||||||
|
|
||||||
|
bool tty_is_enabled(tty *ttyx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 打开某个tty
|
* @brief 打开某个tty
|
||||||
*
|
*
|
||||||
|
@ -130,7 +140,6 @@ void tty_text_print(tty *ttyx, char *string, u32 color, u32 bgcolor);
|
||||||
* 类型的tty占用
|
* 类型的tty占用
|
||||||
*/
|
*/
|
||||||
bool tty_enable(tty *ttyx);
|
bool tty_enable(tty *ttyx);
|
||||||
|
|
||||||
void tty_disable(tty *ttyx);
|
void tty_disable(tty *ttyx);
|
||||||
|
|
||||||
#define TTY_FONT_SCALE 2
|
#define TTY_FONT_SCALE 2
|
||||||
|
|
|
@ -11,7 +11,7 @@ ifdef release
|
||||||
CCFLAGS := ${CCFLAGS} -O2
|
CCFLAGS := ${CCFLAGS} -O2
|
||||||
endif
|
endif
|
||||||
|
|
||||||
C_SRCS = main.c tty.c font.c memm.c memm_${ARCH}.c raw.c
|
C_SRCS = main.c tty.c font.c memm.c memm_${ARCH}.c raw.c time.c
|
||||||
C_OBJS = ${C_SRCS:.c=.c.o}
|
C_OBJS = ${C_SRCS:.c=.c.o}
|
||||||
|
|
||||||
################################
|
################################
|
||||||
|
@ -38,7 +38,7 @@ STRIP_SECS = -R .note.GNU-stack
|
||||||
OBJCOPY_FLAGS = ${STRIP_SECS}
|
OBJCOPY_FLAGS = ${STRIP_SECS}
|
||||||
|
|
||||||
# 子目录
|
# 子目录
|
||||||
VPATH = memm/ memm/allocator tty/ klog/ arch/${ARCH}
|
VPATH = memm/ memm/allocator tty/ klog/ arch/${ARCH} clock/
|
||||||
|
|
||||||
%.c.o: %.c
|
%.c.o: %.c
|
||||||
@echo -e "\e[1m\e[33m${CC}\e[0m \e[32m$<\e[0m \e[34m-->\e[0m \e[1m\e[32m$@\e[0m"
|
@echo -e "\e[1m\e[33m${CC}\e[0m \e[32m$<\e[0m \e[34m-->\e[0m \e[1m\e[32m$@\e[0m"
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
pub mod time;
|
|
@ -0,0 +1,20 @@
|
||||||
|
#include <kernel/clock/time.h>
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
usize system_time;
|
||||||
|
usize system_time_ns;
|
||||||
|
|
||||||
|
usize system_time_get()
|
||||||
|
{
|
||||||
|
return system_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
usize system_time_ns_get()
|
||||||
|
{
|
||||||
|
return system_time_ns;
|
||||||
|
}
|
||||||
|
|
||||||
|
void system_time_increase()
|
||||||
|
{
|
||||||
|
system_time++;
|
||||||
|
}
|
|
@ -0,0 +1,165 @@
|
||||||
|
use std::{cmp::Ordering, fmt::Debug, ops::Sub, time::Duration};
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
fn system_time_get() -> usize;
|
||||||
|
fn system_time_ns_get() -> usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct SystemTimeError(Duration);
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Hash)]
|
||||||
|
pub struct SystemTime {
|
||||||
|
unix_time: usize,
|
||||||
|
ns_time: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for SystemTime {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let second_dur = 1000usize;
|
||||||
|
let minute_dur = second_dur * 60;
|
||||||
|
let hour_dur = minute_dur * 60;
|
||||||
|
let day_dur = hour_dur * 24;
|
||||||
|
let year_dur = day_dur * 365;
|
||||||
|
let four_year_dur = day_dur * (365 * 4 + 1);
|
||||||
|
|
||||||
|
let year = 1970
|
||||||
|
+ self.unix_time / four_year_dur * 4
|
||||||
|
+ if self.unix_time % four_year_dur < day_dur * 59 {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
(self.unix_time % four_year_dur - day_dur) / year_dur
|
||||||
|
};
|
||||||
|
let rest = self.unix_time % four_year_dur;
|
||||||
|
let mut leap = false;
|
||||||
|
let rest = if rest < day_dur * 59 {
|
||||||
|
rest
|
||||||
|
} else {
|
||||||
|
if rest < 60 {
|
||||||
|
leap = true;
|
||||||
|
}
|
||||||
|
rest - day_dur
|
||||||
|
};
|
||||||
|
let month = rest % year_dur;
|
||||||
|
let mut day = 0;
|
||||||
|
let month = if month < 31 * day_dur {
|
||||||
|
day = month;
|
||||||
|
1
|
||||||
|
} else if month < (31 + 28) * day_dur {
|
||||||
|
day = month - 31 * day_dur;
|
||||||
|
2
|
||||||
|
} else if month < (31 + 28 + 31) * day_dur {
|
||||||
|
day = month - (31 + 28) * day_dur;
|
||||||
|
3
|
||||||
|
} else if month < (31 + 28 + 31 + 30) * day_dur {
|
||||||
|
day = month - (31 + 28 + 31) * day_dur;
|
||||||
|
4
|
||||||
|
} else if month < (31 + 28 + 31 + 30 + 31) * day_dur {
|
||||||
|
day = month - (31 + 28 + 31 + 30) * day_dur;
|
||||||
|
5
|
||||||
|
} else if month < (31 + 28 + 31 + 30 + 31 + 30) * day_dur {
|
||||||
|
day = month - (31 + 28 + 31 + 30 + 31) * day_dur;
|
||||||
|
6
|
||||||
|
} else if month < (31 + 28 + 31 + 30 + 31 + 30 + 31) * day_dur {
|
||||||
|
day = month - (31 + 28 + 31 + 30 + 31 + 30) * day_dur;
|
||||||
|
7
|
||||||
|
} else if month < (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31) * day_dur {
|
||||||
|
day = month - (31 + 28 + 31 + 30 + 31 + 30 + 31) * day_dur;
|
||||||
|
8
|
||||||
|
} else if month < (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30) * day_dur {
|
||||||
|
day = month - (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31) * day_dur;
|
||||||
|
9
|
||||||
|
} else if month < (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31) * day_dur {
|
||||||
|
day = month - (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30) * day_dur;
|
||||||
|
10
|
||||||
|
} else if month < (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30) * day_dur {
|
||||||
|
day = month - (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31) * day_dur;
|
||||||
|
11
|
||||||
|
} else if month < (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31) * day_dur {
|
||||||
|
day = month - (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30) * day_dur;
|
||||||
|
12
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
let mut hour = day % day_dur;
|
||||||
|
day /= day_dur;
|
||||||
|
day += 1;
|
||||||
|
if leap {
|
||||||
|
day += 1;
|
||||||
|
}
|
||||||
|
let mut minute = hour % hour_dur;
|
||||||
|
hour /= hour_dur;
|
||||||
|
let mut second = minute % minute_dur;
|
||||||
|
minute /= minute_dur;
|
||||||
|
let milisec = second % second_dur;
|
||||||
|
second /= second_dur;
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"[{:02}-{:02}-{:02} {:02}:{:02}:{:02}.{:03}]",
|
||||||
|
year, month, day, hour, minute, second, milisec
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for SystemTime {}
|
||||||
|
impl PartialEq for SystemTime {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.unix_time == other.unix_time && self.ns_time == other.ns_time
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for SystemTime {
|
||||||
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
|
match self.unix_time.cmp(&other.unix_time) {
|
||||||
|
Ordering::Equal => self.ns_time.cmp(&other.ns_time),
|
||||||
|
ord => ord,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for SystemTime {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||||
|
match self.unix_time.partial_cmp(&other.unix_time) {
|
||||||
|
Some(Ordering::Equal) => self.ns_time.partial_cmp(&other.ns_time),
|
||||||
|
ord => ord,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sub<SystemTime> for SystemTime {
|
||||||
|
type Output = Result<Duration, SystemTimeError>;
|
||||||
|
|
||||||
|
fn sub(self, rhs: SystemTime) -> Self::Output {
|
||||||
|
if self < rhs {
|
||||||
|
let earl = (rhs - self).unwrap();
|
||||||
|
Err(SystemTimeError(earl))
|
||||||
|
} else {
|
||||||
|
let usdiff = self.ns_time as isize - self.ns_time as isize;
|
||||||
|
let usdiff = if usdiff >= 0 {
|
||||||
|
Duration::from_nanos(usdiff as usize as u64)
|
||||||
|
} else {
|
||||||
|
Duration::from_nanos(0) - Duration::from_nanos((-usdiff) as usize as u64)
|
||||||
|
};
|
||||||
|
Ok(Duration::from_millis((self.unix_time - rhs.unix_time) as u64) + usdiff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SystemTime {
|
||||||
|
pub fn now() -> Self {
|
||||||
|
unsafe {
|
||||||
|
Self {
|
||||||
|
unix_time: system_time_get(),
|
||||||
|
ns_time: system_time_ns_get(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn duration_since(&self, earlier: &SystemTime) -> Result<Duration, SystemTimeError> {
|
||||||
|
*self - *earlier
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn elapsed(&self) -> Result<Duration, SystemTimeError> {
|
||||||
|
SystemTime::now() - *self
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,160 @@
|
||||||
|
use super::{
|
||||||
|
clock::time::SystemTime,
|
||||||
|
tty::tty::{Color, Message, MessageBuilder},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
pub enum LoggerLevel {
|
||||||
|
Fatal,
|
||||||
|
Error,
|
||||||
|
Warning,
|
||||||
|
Info,
|
||||||
|
Debug,
|
||||||
|
Trace,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct KernelLogger {
|
||||||
|
fatal_queue: Vec<(SystemTime, Message)>,
|
||||||
|
error_queue: Vec<(SystemTime, Message)>,
|
||||||
|
warning_queue: Vec<(SystemTime, Message)>,
|
||||||
|
info_queue: Vec<(SystemTime, Message)>,
|
||||||
|
debug_queue: Vec<(SystemTime, Message)>,
|
||||||
|
trace_queue: Vec<(SystemTime, Message)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fatal(&mut self, msg: Message) {
|
||||||
|
let msg = MessageBuilder::new()
|
||||||
|
.message("Fatal: ".to_string())
|
||||||
|
.foreground_color(Color(0xee, 0xa, 0xa))
|
||||||
|
.append(MessageBuilder::from_message(&msg))
|
||||||
|
.build();
|
||||||
|
self.fatal_queue.push((SystemTime::now(), msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn error(&mut self, msg: Message) {
|
||||||
|
let msg = MessageBuilder::new()
|
||||||
|
.message("Error: ".to_string())
|
||||||
|
.foreground_color(Color(0xaa, 0x22, 0x22))
|
||||||
|
.append(MessageBuilder::from_message(&msg))
|
||||||
|
.build();
|
||||||
|
self.error_queue.push((SystemTime::now(), msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn warning(&mut self, msg: Message) {
|
||||||
|
let msg = MessageBuilder::new()
|
||||||
|
.message("Warning: ".to_string())
|
||||||
|
.foreground_color(Color(0xaa, 0xa, 0xaa))
|
||||||
|
.append(MessageBuilder::from_message(&msg))
|
||||||
|
.build();
|
||||||
|
self.warning_queue.push((SystemTime::now(), msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn info(&mut self, msg: Message) {
|
||||||
|
let msg = MessageBuilder::new()
|
||||||
|
.message("Info: ".to_string())
|
||||||
|
.foreground_color(Color(0xa, 0xee, 0xa))
|
||||||
|
.append(MessageBuilder::from_message(&msg))
|
||||||
|
.build();
|
||||||
|
self.info_queue.push((SystemTime::now(), msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn debug(&mut self, msg: Message) {
|
||||||
|
let msg = MessageBuilder::new()
|
||||||
|
.message("Debug: ".to_string())
|
||||||
|
.foreground_color(Color(0xee, 0xee, 0xee))
|
||||||
|
.append(MessageBuilder::from_message(&msg))
|
||||||
|
.build();
|
||||||
|
self.debug_queue.push((SystemTime::now(), msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn trace(&mut self, msg: Message) {
|
||||||
|
let msg = MessageBuilder::new()
|
||||||
|
.message("Trace: ".to_string())
|
||||||
|
.foreground_color(Color(0xee, 0xee, 0xee))
|
||||||
|
.append(MessageBuilder::from_message(&msg))
|
||||||
|
.build();
|
||||||
|
self.trace_queue.push((SystemTime::now(), msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter(&self, level: LoggerLevel) -> LogIterator {
|
||||||
|
let mut logs = vec![];
|
||||||
|
if level == LoggerLevel::Fatal {
|
||||||
|
logs.push(&self.fatal_queue);
|
||||||
|
}
|
||||||
|
if level == LoggerLevel::Fatal || level == LoggerLevel::Error {
|
||||||
|
logs.push(&self.error_queue);
|
||||||
|
}
|
||||||
|
if level == LoggerLevel::Fatal
|
||||||
|
|| level == LoggerLevel::Error
|
||||||
|
|| level == LoggerLevel::Warning
|
||||||
|
{
|
||||||
|
logs.push(&self.warning_queue);
|
||||||
|
}
|
||||||
|
if level == LoggerLevel::Fatal
|
||||||
|
|| level == LoggerLevel::Error
|
||||||
|
|| level == LoggerLevel::Warning
|
||||||
|
|| level == LoggerLevel::Info
|
||||||
|
{
|
||||||
|
logs.push(&self.info_queue);
|
||||||
|
}
|
||||||
|
if level == LoggerLevel::Fatal
|
||||||
|
|| level == LoggerLevel::Error
|
||||||
|
|| level == LoggerLevel::Warning
|
||||||
|
|| level == LoggerLevel::Info
|
||||||
|
|| level == LoggerLevel::Debug
|
||||||
|
{
|
||||||
|
logs.push(&self.debug_queue);
|
||||||
|
}
|
||||||
|
if level == LoggerLevel::Fatal
|
||||||
|
|| level == LoggerLevel::Error
|
||||||
|
|| level == LoggerLevel::Warning
|
||||||
|
|| level == LoggerLevel::Info
|
||||||
|
|| level == LoggerLevel::Debug
|
||||||
|
|| level == LoggerLevel::Trace
|
||||||
|
{
|
||||||
|
logs.push(&self.trace_queue);
|
||||||
|
}
|
||||||
|
let mut res = vec![];
|
||||||
|
while let Some(msg) = {
|
||||||
|
logs.iter_mut()
|
||||||
|
.filter_map(|&mut l| l.first().cloned())
|
||||||
|
.min_by_key(|&(syst, _)| syst)
|
||||||
|
} {
|
||||||
|
res.push(msg);
|
||||||
|
}
|
||||||
|
LogIterator { logs: res }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct LogIterator {
|
||||||
|
logs: Vec<(SystemTime, Message)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for LogIterator {
|
||||||
|
type Item = Message;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
if let Some((time, msg)) = self.logs.first() {
|
||||||
|
Some(
|
||||||
|
MessageBuilder::new()
|
||||||
|
.message(format!("{:?}", time))
|
||||||
|
.append(MessageBuilder::from_message(msg))
|
||||||
|
.build(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,15 +1,19 @@
|
||||||
use crate::kernel::tty::tty::{Color, MessageBuilder, Tty};
|
use super::{
|
||||||
|
klog::{KernelLogger, LoggerLevel},
|
||||||
|
tty::tty::{Color, ColorPair, Message, Tty},
|
||||||
|
};
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
extern "C" fn kmain_rust() {
|
extern "C" fn kmain_rust() {
|
||||||
|
let mut logger = KernelLogger::new();
|
||||||
|
logger.info(Message::from(format!(
|
||||||
|
"Hello, {:?}Metaverse{:?}!",
|
||||||
|
ColorPair::color(Color(0xa, 0xee, 0xa), Color(0, 0, 0)),
|
||||||
|
ColorPair::Reset
|
||||||
|
)));
|
||||||
let tty = Tty::from_id(0).unwrap();
|
let tty = Tty::from_id(0).unwrap();
|
||||||
tty.enable();
|
for msg in logger.iter(LoggerLevel::Info) {
|
||||||
let hello = MessageBuilder::new()
|
tty.print(msg);
|
||||||
.message("Hello, ".to_string())
|
}
|
||||||
.message("Metaverse".to_string())
|
|
||||||
.foreground_color(Color(0xa, 0xee, 0xa))
|
|
||||||
.message("!\n".to_string())
|
|
||||||
.build();
|
|
||||||
tty.print(hello);
|
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ use core::alloc::{GlobalAlloc, Layout};
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn memm_kernel_allocate(size: usize) -> *mut u8;
|
pub fn memm_kernel_allocate(size: usize) -> *mut u8;
|
||||||
pub fn memm_user_allocate(size: usize, pid: usize);
|
// pub fn memm_user_allocate(size: usize, pid: usize);
|
||||||
pub fn memm_free(mem: *mut u8);
|
pub fn memm_free(mem: *mut u8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
pub mod clock;
|
||||||
|
pub mod klog;
|
||||||
|
pub mod main;
|
||||||
pub mod memm;
|
pub mod memm;
|
||||||
pub mod tty;
|
pub mod tty;
|
||||||
pub mod main;
|
pub mod sync;
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
pub mod rwlock;
|
|
@ -0,0 +1,130 @@
|
||||||
|
use std::{
|
||||||
|
ops::{Deref, DerefMut},
|
||||||
|
ptr::null_mut,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// ## 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,6 +32,8 @@ tty *tty_new(tty_type type, tty_mode mode)
|
||||||
res->type = type;
|
res->type = type;
|
||||||
res->mode = mode;
|
res->mode = mode;
|
||||||
res->enabled = false;
|
res->enabled = false;
|
||||||
|
res->width = 0;
|
||||||
|
res->height = 0;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,6 +54,8 @@ void tty_set_framebuffer(tty *ttyx, framebuffer *fb)
|
||||||
if (ttyx->type != tty_type_raw_framebuffer)
|
if (ttyx->type != tty_type_raw_framebuffer)
|
||||||
return;
|
return;
|
||||||
memcpy(&ttyx->typeinfo.raw_framebuffer, fb, sizeof(framebuffer));
|
memcpy(&ttyx->typeinfo.raw_framebuffer, fb, sizeof(framebuffer));
|
||||||
|
ttyx->width = ttyx->typeinfo.raw_framebuffer.width;
|
||||||
|
ttyx->height = ttyx->typeinfo.raw_framebuffer.height;
|
||||||
if (ttyx->mode == tty_mode_text)
|
if (ttyx->mode == tty_mode_text)
|
||||||
{
|
{
|
||||||
ttyx->text.width = fb->width / tty_get_font()->char_width;
|
ttyx->text.width = fb->width / tty_get_font()->char_width;
|
||||||
|
@ -140,6 +144,9 @@ void tty_text_print(tty *ttyx, char *string, u32 color, u32 bgcolor)
|
||||||
{
|
{
|
||||||
if (ttyx->enabled == false)
|
if (ttyx->enabled == false)
|
||||||
return;
|
return;
|
||||||
|
// TODO 暂时只支持framebuffer
|
||||||
|
if (ttyx->type != tty_type_raw_framebuffer)
|
||||||
|
return;
|
||||||
if (ttyx->mode != tty_mode_text)
|
if (ttyx->mode != tty_mode_text)
|
||||||
return;
|
return;
|
||||||
if (ttyx->typeinfo.raw_framebuffer.pixtype == bgr)
|
if (ttyx->typeinfo.raw_framebuffer.pixtype == bgr)
|
||||||
|
@ -224,6 +231,35 @@ void tty_text_print(tty *ttyx, char *string, u32 color, u32 bgcolor)
|
||||||
simple_lock_unlock(ttyx->text.lock);
|
simple_lock_unlock(ttyx->text.lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
usize tty_get_width(tty *ttyx)
|
||||||
|
{
|
||||||
|
if (ttyx->mode == tty_mode_text)
|
||||||
|
return ttyx->text.width;
|
||||||
|
return ttyx->width;
|
||||||
|
}
|
||||||
|
|
||||||
|
usize tty_get_height(tty *ttyx)
|
||||||
|
{
|
||||||
|
if (ttyx->mode == tty_mode_text)
|
||||||
|
return ttyx->text.height;
|
||||||
|
return ttyx->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
tty_type tty_get_type(tty *ttyx)
|
||||||
|
{
|
||||||
|
return ttyx->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
tty_mode tty_get_mode(tty *ttyx)
|
||||||
|
{
|
||||||
|
return ttyx->mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool tty_is_enabled(tty *ttyx)
|
||||||
|
{
|
||||||
|
return ttyx->enabled;
|
||||||
|
}
|
||||||
|
|
||||||
bool tty_enable(tty *ttyx)
|
bool tty_enable(tty *ttyx)
|
||||||
{
|
{
|
||||||
if (tty_ctrler.enabled[ttyx->id])
|
if (tty_ctrler.enabled[ttyx->id])
|
||||||
|
|
|
@ -1,11 +1,19 @@
|
||||||
use std::ptr::null_mut;
|
use std::{fmt::Debug, ptr::null_mut};
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn tty_new(tty_type: u8, mode: u8) -> *mut u8;
|
fn tty_new(tty_type: u8, mode: u8) -> *mut u8;
|
||||||
fn tty_get(id: usize) -> *mut *mut u8;
|
fn tty_get(id: usize) -> *mut *mut u8;
|
||||||
pub fn tty_text_print(ttyx: *mut u8, string: *mut u8, color: u32, bgcolor: u32);
|
fn tty_text_print(ttyx: *mut u8, string: *mut u8, color: u32, bgcolor: u32);
|
||||||
fn tty_get_id(tty: *mut u8) -> usize;
|
fn tty_get_id(tty: *mut u8) -> usize;
|
||||||
|
|
||||||
|
fn tty_get_width(tty: *mut u8) -> usize;
|
||||||
|
fn tty_get_height(tty: *mut u8) -> usize;
|
||||||
|
|
||||||
|
fn tty_get_type(tty: *mut u8) -> u8;
|
||||||
|
fn tty_get_mode(tty: *mut u8) -> u8;
|
||||||
|
|
||||||
|
fn tty_is_enabled(tty: *mut u8) -> bool;
|
||||||
|
|
||||||
fn tty_enable(tty: *mut u8) -> bool;
|
fn tty_enable(tty: *mut u8) -> bool;
|
||||||
fn tty_disable(tty: *mut u8);
|
fn tty_disable(tty: *mut u8);
|
||||||
}
|
}
|
||||||
|
@ -17,9 +25,31 @@ pub enum Type {
|
||||||
VirtualTerm = 3,
|
VirtualTerm = 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<u8> for Type {
|
||||||
|
fn from(value: u8) -> Self {
|
||||||
|
match value {
|
||||||
|
1 => Type::RawFramebuffer,
|
||||||
|
2 => Type::Display,
|
||||||
|
3 => Type::VirtualTerm,
|
||||||
|
_ => Type::Invalid,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub enum Mode {
|
pub enum Mode {
|
||||||
Text = 0,
|
Invalid = 0,
|
||||||
Graphics = 1,
|
Text = 1,
|
||||||
|
Graphics = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u8> for Mode {
|
||||||
|
fn from(value: u8) -> Self {
|
||||||
|
match value {
|
||||||
|
1 => Mode::Text,
|
||||||
|
2 => Mode::Graphics,
|
||||||
|
_ => Mode::Invalid,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Tty {
|
pub struct Tty {
|
||||||
|
@ -50,6 +80,29 @@ impl Tty {
|
||||||
unsafe { tty_get_id(self.tty_pointer) }
|
unsafe { tty_get_id(self.tty_pointer) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn size(&self) -> Resolution {
|
||||||
|
unsafe {
|
||||||
|
Resolution {
|
||||||
|
width: tty_get_width(self.tty_pointer),
|
||||||
|
height: tty_get_height(self.tty_pointer),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_type(&self) -> Type {
|
||||||
|
let tp = unsafe { tty_get_type(self.tty_pointer) };
|
||||||
|
Type::from(tp)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mode(&self) -> Mode {
|
||||||
|
let mode = unsafe { tty_get_mode(self.tty_pointer) };
|
||||||
|
Mode::from(mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_enabled(&self) -> bool {
|
||||||
|
unsafe { tty_is_enabled(self.tty_pointer) }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn enable(&self) {
|
pub fn enable(&self) {
|
||||||
unsafe { tty_enable(self.tty_pointer) };
|
unsafe { tty_enable(self.tty_pointer) };
|
||||||
}
|
}
|
||||||
|
@ -82,8 +135,45 @@ impl Tty {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
pub struct Color(pub u8, pub u8, pub u8);
|
pub struct Color(pub u8, pub u8, pub u8);
|
||||||
|
|
||||||
|
impl ToString for Color {
|
||||||
|
fn to_string(&self) -> String {
|
||||||
|
format!("Color({:02x}, {:02x}, {:02x})", self.0, self.1, self.2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for Color {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{:02x}{:02x}{:02x}", self.0, self.1, self.2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum ColorPair {
|
||||||
|
Reset,
|
||||||
|
Color { fore: Color, back: Color },
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ColorPair {
|
||||||
|
pub fn reset() -> Self {
|
||||||
|
ColorPair::Reset
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn color(fore: Color, back: Color) -> Self {
|
||||||
|
ColorPair::Color { fore, back }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for ColorPair {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
ColorPair::Reset => write!(f, "\x1b{{}}"),
|
||||||
|
ColorPair::Color { fore, back } => write!(f, "\x1b{{{:?}{:?}}}", fore, back),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<Color> for u32 {
|
impl From<Color> for u32 {
|
||||||
fn from(value: Color) -> Self {
|
fn from(value: Color) -> Self {
|
||||||
let res = (value.0 as u32) << 16 | (value.1 as u32) << 8 | (value.2 as u32);
|
let res = (value.0 as u32) << 16 | (value.1 as u32) << 8 | (value.2 as u32);
|
||||||
|
@ -91,14 +181,79 @@ impl From<Color> for u32 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Resolution {
|
||||||
|
pub width: usize,
|
||||||
|
pub height: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct MessageSection {
|
pub struct MessageSection {
|
||||||
msg: String,
|
msg: String,
|
||||||
fgcolor: Color,
|
fgcolor: Color,
|
||||||
bgcolor: Color,
|
bgcolor: Color,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Message(Vec<MessageSection>);
|
pub struct Message(Vec<MessageSection>);
|
||||||
|
|
||||||
|
impl From<String> for Message {
|
||||||
|
fn from(value: String) -> Self {
|
||||||
|
let mut res = MessageBuilder::new();
|
||||||
|
let mut msg = String::new();
|
||||||
|
let mut color = ColorPair::Reset;
|
||||||
|
let mut coloring = false;
|
||||||
|
|
||||||
|
let mut colorp_str = String::new();
|
||||||
|
|
||||||
|
for c in value.as_bytes() {
|
||||||
|
if *c as char == '\x1b' {
|
||||||
|
coloring = true;
|
||||||
|
res.message_mut(msg.clone());
|
||||||
|
msg.clear();
|
||||||
|
if let ColorPair::Color { fore, back } = color {
|
||||||
|
res.foreground_color_mut(fore);
|
||||||
|
res.background_color_mut(back);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if coloring {
|
||||||
|
if *c as char == '{' {
|
||||||
|
colorp_str.clear();
|
||||||
|
} else if *c as char == '}' {
|
||||||
|
if colorp_str.is_empty() {
|
||||||
|
color = ColorPair::Reset;
|
||||||
|
} else {
|
||||||
|
let bts = colorp_str.as_bytes();
|
||||||
|
let r = bts[0] << 4 + bts[1];
|
||||||
|
let g = bts[2] << 4 + bts[3];
|
||||||
|
let b = bts[4] << 4 + bts[5];
|
||||||
|
let fore = Color(r, g, b);
|
||||||
|
let r = bts[6] << 4 + bts[7];
|
||||||
|
let g = bts[8] << 4 + bts[9];
|
||||||
|
let b = bts[10] << 4 + bts[11];
|
||||||
|
let back = Color(r, g, b);
|
||||||
|
color = ColorPair::Color { fore, back };
|
||||||
|
}
|
||||||
|
coloring = false;
|
||||||
|
} else {
|
||||||
|
colorp_str.push(*c as char);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
msg.push(*c as char);
|
||||||
|
}
|
||||||
|
if !msg.is_empty() {
|
||||||
|
res.message_mut(msg.clone());
|
||||||
|
msg.clear();
|
||||||
|
if let ColorPair::Color { fore, back } = color {
|
||||||
|
res.foreground_color_mut(fore);
|
||||||
|
res.background_color_mut(back);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct MessageBuilder {
|
pub struct MessageBuilder {
|
||||||
msg: Message,
|
msg: Message,
|
||||||
}
|
}
|
||||||
|
@ -110,6 +265,10 @@ impl MessageBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_message(msg: &Message) -> Self {
|
||||||
|
Self { msg: msg.clone() }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn message(mut self, msg: String) -> Self {
|
pub fn message(mut self, msg: String) -> Self {
|
||||||
self.msg.0.push(MessageSection {
|
self.msg.0.push(MessageSection {
|
||||||
msg,
|
msg,
|
||||||
|
@ -119,6 +278,14 @@ impl MessageBuilder {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn message_mut(&mut self, msg: String) {
|
||||||
|
self.msg.0.push(MessageSection {
|
||||||
|
msg,
|
||||||
|
fgcolor: Color(0xee, 0xee, 0xee),
|
||||||
|
bgcolor: Color(0, 0, 0),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
pub fn background_color(mut self, color: Color) -> Self {
|
pub fn background_color(mut self, color: Color) -> Self {
|
||||||
if let Some(msg) = self.msg.0.last_mut() {
|
if let Some(msg) = self.msg.0.last_mut() {
|
||||||
msg.bgcolor = color;
|
msg.bgcolor = color;
|
||||||
|
@ -126,6 +293,12 @@ impl MessageBuilder {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn background_color_mut(&mut self, color: Color) {
|
||||||
|
if let Some(msg) = self.msg.0.last_mut() {
|
||||||
|
msg.bgcolor = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn foreground_color(mut self, color: Color) -> Self {
|
pub fn foreground_color(mut self, color: Color) -> Self {
|
||||||
if let Some(msg) = self.msg.0.last_mut() {
|
if let Some(msg) = self.msg.0.last_mut() {
|
||||||
msg.fgcolor = color;
|
msg.fgcolor = color;
|
||||||
|
@ -133,6 +306,17 @@ impl MessageBuilder {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn foreground_color_mut(&mut self, color: Color) {
|
||||||
|
if let Some(msg) = self.msg.0.last_mut() {
|
||||||
|
msg.fgcolor = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn append(mut self, mut builder: Self) -> Self {
|
||||||
|
self.msg.0.append(&mut builder.msg.0);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn build(self) -> Message {
|
pub fn build(self) -> Message {
|
||||||
self.msg
|
self.msg
|
||||||
}
|
}
|
||||||
|
|
Reference in New Issue