增加内核日志
This commit is contained in:
parent
7afa51d9ea
commit
bfd7530ae2
|
@ -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
|
||||
{
|
||||
invalid = 0,
|
||||
tty_type_invalid = 0,
|
||||
// 用于在内核刚刚被引导,只有bootloader提供的显示功能时使用
|
||||
tty_type_raw_framebuffer = 1,
|
||||
// 用于图形功能初始化后,直接连接图形接口
|
||||
|
@ -40,8 +40,9 @@ typedef struct __framebuffer framebuffer;
|
|||
// 文本模式中的字符由tty模块渲染
|
||||
typedef enum __tty_mode
|
||||
{
|
||||
tty_mode_text = 0,
|
||||
tty_mode_graphics = 1,
|
||||
tty_mode_invalid = 0,
|
||||
tty_mode_text = 1,
|
||||
tty_mode_graphics = 2,
|
||||
} tty_mode;
|
||||
|
||||
typedef struct __tty_text_state
|
||||
|
@ -55,6 +56,7 @@ typedef struct __tty_text_state
|
|||
typedef struct __tty
|
||||
{
|
||||
usize id;
|
||||
usize width, height;
|
||||
tty_type type;
|
||||
tty_typeinfo typeinfo;
|
||||
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))
|
||||
|
||||
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
|
||||
*
|
||||
|
@ -130,7 +140,6 @@ void tty_text_print(tty *ttyx, char *string, u32 color, u32 bgcolor);
|
|||
* 类型的tty占用
|
||||
*/
|
||||
bool tty_enable(tty *ttyx);
|
||||
|
||||
void tty_disable(tty *ttyx);
|
||||
|
||||
#define TTY_FONT_SCALE 2
|
||||
|
|
|
@ -11,7 +11,7 @@ ifdef release
|
|||
CCFLAGS := ${CCFLAGS} -O2
|
||||
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}
|
||||
|
||||
################################
|
||||
|
@ -38,7 +38,7 @@ STRIP_SECS = -R .note.GNU-stack
|
|||
OBJCOPY_FLAGS = ${STRIP_SECS}
|
||||
|
||||
# 子目录
|
||||
VPATH = memm/ memm/allocator tty/ klog/ arch/${ARCH}
|
||||
VPATH = memm/ memm/allocator tty/ klog/ arch/${ARCH} clock/
|
||||
|
||||
%.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"
|
||||
|
|
|
@ -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]
|
||||
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();
|
||||
tty.enable();
|
||||
let hello = MessageBuilder::new()
|
||||
.message("Hello, ".to_string())
|
||||
.message("Metaverse".to_string())
|
||||
.foreground_color(Color(0xa, 0xee, 0xa))
|
||||
.message("!\n".to_string())
|
||||
.build();
|
||||
tty.print(hello);
|
||||
for msg in logger.iter(LoggerLevel::Info) {
|
||||
tty.print(msg);
|
||||
}
|
||||
loop {}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use core::alloc::{GlobalAlloc, Layout};
|
|||
|
||||
extern "C" {
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
pub mod clock;
|
||||
pub mod klog;
|
||||
pub mod main;
|
||||
pub mod memm;
|
||||
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->mode = mode;
|
||||
res->enabled = false;
|
||||
res->width = 0;
|
||||
res->height = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -52,6 +54,8 @@ void tty_set_framebuffer(tty *ttyx, framebuffer *fb)
|
|||
if (ttyx->type != tty_type_raw_framebuffer)
|
||||
return;
|
||||
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)
|
||||
{
|
||||
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)
|
||||
return;
|
||||
// TODO 暂时只支持framebuffer
|
||||
if (ttyx->type != tty_type_raw_framebuffer)
|
||||
return;
|
||||
if (ttyx->mode != tty_mode_text)
|
||||
return;
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (tty_ctrler.enabled[ttyx->id])
|
||||
|
|
|
@ -1,11 +1,19 @@
|
|||
use std::ptr::null_mut;
|
||||
use std::{fmt::Debug, ptr::null_mut};
|
||||
|
||||
extern "C" {
|
||||
fn tty_new(tty_type: u8, mode: u8) -> *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_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_disable(tty: *mut u8);
|
||||
}
|
||||
|
@ -17,9 +25,31 @@ pub enum Type {
|
|||
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 {
|
||||
Text = 0,
|
||||
Graphics = 1,
|
||||
Invalid = 0,
|
||||
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 {
|
||||
|
@ -50,6 +80,29 @@ impl Tty {
|
|||
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) {
|
||||
unsafe { tty_enable(self.tty_pointer) };
|
||||
}
|
||||
|
@ -82,8 +135,45 @@ impl Tty {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
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 {
|
||||
fn from(value: Color) -> Self {
|
||||
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 {
|
||||
msg: String,
|
||||
fgcolor: Color,
|
||||
bgcolor: Color,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
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 {
|
||||
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 {
|
||||
self.msg.0.push(MessageSection {
|
||||
msg,
|
||||
|
@ -119,6 +278,14 @@ impl MessageBuilder {
|
|||
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 {
|
||||
if let Some(msg) = self.msg.0.last_mut() {
|
||||
msg.bgcolor = color;
|
||||
|
@ -126,6 +293,12 @@ impl MessageBuilder {
|
|||
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 {
|
||||
if let Some(msg) = self.msg.0.last_mut() {
|
||||
msg.fgcolor = color;
|
||||
|
@ -133,6 +306,17 @@ impl MessageBuilder {
|
|||
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 {
|
||||
self.msg
|
||||
}
|
||||
|
|
Reference in New Issue