fs: simple kernel log buffer
This commit is contained in:
parent
dbbddaa4f5
commit
0dc2cfa159
55
src/debug.rs
55
src/debug.rs
@ -2,14 +2,30 @@
|
|||||||
use core::fmt::{self, Arguments};
|
use core::fmt::{self, Arguments};
|
||||||
|
|
||||||
use abi::error::Error;
|
use abi::error::Error;
|
||||||
use kernel_util::util::StaticVector;
|
use alloc::sync::Arc;
|
||||||
|
use futures_util::Future;
|
||||||
|
use kernel_util::util::{OneTimeInit, StaticVector};
|
||||||
|
|
||||||
use crate::{sync::IrqSafeSpinlock, task::process::Process};
|
use crate::{
|
||||||
|
sync::IrqSafeSpinlock,
|
||||||
|
task::{process::Process, runtime::QueueWaker},
|
||||||
|
util::ring::RingBuffer,
|
||||||
|
};
|
||||||
|
|
||||||
const MAX_DEBUG_SINKS: usize = 4;
|
const MAX_DEBUG_SINKS: usize = 4;
|
||||||
|
const RING_LOGGER_CAPACITY: usize = 65536;
|
||||||
|
|
||||||
struct SimpleLogger;
|
struct SimpleLogger;
|
||||||
|
|
||||||
|
struct RingLoggerInner {
|
||||||
|
data: RingBuffer<u8, RING_LOGGER_CAPACITY>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct RingLoggerSink {
|
||||||
|
inner: IrqSafeSpinlock<RingLoggerInner>,
|
||||||
|
waker: QueueWaker,
|
||||||
|
}
|
||||||
|
|
||||||
/// Defines the severity of the message
|
/// Defines the severity of the message
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub enum LogLevel {
|
pub enum LogLevel {
|
||||||
@ -151,11 +167,44 @@ impl fmt::Write for DebugSinkWrapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl RingLoggerSink {
|
||||||
|
pub const fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
inner: IrqSafeSpinlock::new(RingLoggerInner {
|
||||||
|
data: RingBuffer::new(0),
|
||||||
|
}),
|
||||||
|
waker: QueueWaker::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read(&self, pos: usize, buffer: &mut [u8]) -> usize {
|
||||||
|
unsafe { self.inner.lock().data.read_all_static(pos, buffer) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_fmt(&self, args: fmt::Arguments<'_>) -> fmt::Result {
|
||||||
|
use fmt::Write;
|
||||||
|
self.inner.lock().write_fmt(args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Write for RingLoggerInner {
|
||||||
|
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||||
|
for ch in s.bytes() {
|
||||||
|
unsafe {
|
||||||
|
self.data.write_unchecked(ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static LOGGER: SimpleLogger = SimpleLogger;
|
static LOGGER: SimpleLogger = SimpleLogger;
|
||||||
|
|
||||||
static DEBUG_SINKS: IrqSafeSpinlock<StaticVector<DebugSinkWrapper, MAX_DEBUG_SINKS>> =
|
static DEBUG_SINKS: IrqSafeSpinlock<StaticVector<DebugSinkWrapper, MAX_DEBUG_SINKS>> =
|
||||||
IrqSafeSpinlock::new(StaticVector::new());
|
IrqSafeSpinlock::new(StaticVector::new());
|
||||||
|
|
||||||
|
pub static RING_LOGGER_SINK: RingLoggerSink = RingLoggerSink::new();
|
||||||
|
|
||||||
/// Prints a hex-dump of a slice, appending a virtual address offset to the output
|
/// Prints a hex-dump of a slice, appending a virtual address offset to the output
|
||||||
pub fn hex_dump(level: LogLevel, addr_offset: usize, data: &[u8]) {
|
pub fn hex_dump(level: LogLevel, addr_offset: usize, data: &[u8]) {
|
||||||
for (i, b) in data.iter().enumerate() {
|
for (i, b) in data.iter().enumerate() {
|
||||||
@ -208,6 +257,8 @@ pub fn init() {
|
|||||||
pub fn debug_internal(args: Arguments, level: LogLevel) {
|
pub fn debug_internal(args: Arguments, level: LogLevel) {
|
||||||
use fmt::Write;
|
use fmt::Write;
|
||||||
|
|
||||||
|
RING_LOGGER_SINK.write_fmt(args).ok();
|
||||||
|
|
||||||
for sink in DEBUG_SINKS.lock().iter_mut() {
|
for sink in DEBUG_SINKS.lock().iter_mut() {
|
||||||
if level < sink.level {
|
if level < sink.level {
|
||||||
continue;
|
continue;
|
||||||
|
@ -192,7 +192,7 @@ impl Device for Pl011 {
|
|||||||
|
|
||||||
self.inner.init(IrqSafeSpinlock::new(inner));
|
self.inner.init(IrqSafeSpinlock::new(inner));
|
||||||
|
|
||||||
debug::add_sink(self, LogLevel::Debug);
|
// debug::add_sink(self, LogLevel::Debug);
|
||||||
devfs::add_char_device(self, CharDeviceType::TtySerial)?;
|
devfs::add_char_device(self, CharDeviceType::TtySerial)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -12,7 +12,7 @@ use git_version::git_version;
|
|||||||
use kernel_util::util::OneTimeInit;
|
use kernel_util::util::OneTimeInit;
|
||||||
use vfs::{Vnode, VnodeImpl, VnodeKind, VnodeRef, DIR_POSITION_FROM_CACHE};
|
use vfs::{Vnode, VnodeImpl, VnodeKind, VnodeRef, DIR_POSITION_FROM_CACHE};
|
||||||
|
|
||||||
use crate::util;
|
use crate::{debug, util};
|
||||||
|
|
||||||
trait GetterFn<T: ToString> = Fn() -> Result<T, Error>;
|
trait GetterFn<T: ToString> = Fn() -> Result<T, Error>;
|
||||||
trait ReaderFn = Fn(u64, &mut [u8]) -> Result<usize, Error>;
|
trait ReaderFn = Fn(u64, &mut [u8]) -> Result<usize, Error>;
|
||||||
@ -169,8 +169,7 @@ pub fn root() -> &'static VnodeRef {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn read_kernel_log(pos: u64, buffer: &mut [u8]) -> Result<usize, Error> {
|
fn read_kernel_log(pos: u64, buffer: &mut [u8]) -> Result<usize, Error> {
|
||||||
// TODO actual kernel log buffer
|
Ok(debug::RING_LOGGER_SINK.read(pos as usize, buffer))
|
||||||
todo!()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init() {
|
pub fn init() {
|
||||||
|
@ -9,24 +9,36 @@ use futures_util::Future;
|
|||||||
|
|
||||||
use crate::{sync::IrqSafeSpinlock, task::runtime::QueueWaker};
|
use crate::{sync::IrqSafeSpinlock, task::runtime::QueueWaker};
|
||||||
|
|
||||||
struct Inner<T, const N: usize> {
|
pub struct RingBuffer<T, const N: usize> {
|
||||||
rd: usize,
|
rd: usize,
|
||||||
wr: usize,
|
wr: usize,
|
||||||
data: [T; N],
|
data: [T; N],
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AsyncRing<T, const N: usize> {
|
pub struct AsyncRing<T, const N: usize> {
|
||||||
inner: Arc<IrqSafeSpinlock<Inner<T, N>>>,
|
inner: Arc<IrqSafeSpinlock<RingBuffer<T, N>>>,
|
||||||
read_waker: Arc<QueueWaker>,
|
read_waker: Arc<QueueWaker>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Copy, const N: usize> Inner<T, N> {
|
impl<T: Copy, const N: usize> RingBuffer<T, N> {
|
||||||
|
pub const fn new(value: T) -> Self {
|
||||||
|
Self {
|
||||||
|
rd: 0,
|
||||||
|
wr: 0,
|
||||||
|
data: [value; N],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
const fn is_readable(&self) -> bool {
|
const fn is_readable(&self) -> bool {
|
||||||
if self.rd <= self.wr {
|
self.is_readable_at(self.rd)
|
||||||
(self.wr - self.rd) > 0
|
}
|
||||||
|
|
||||||
|
const fn is_readable_at(&self, at: usize) -> bool {
|
||||||
|
if at <= self.wr {
|
||||||
|
(self.wr - at) > 0
|
||||||
} else {
|
} else {
|
||||||
(self.wr + (N - self.rd)) > 0
|
(self.wr + (N - at)) > 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,8 +49,19 @@ impl<T: Copy, const N: usize> Inner<T, N> {
|
|||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub unsafe fn read_all_static(&mut self, pos: usize, buffer: &mut [T]) -> usize {
|
||||||
|
let mut pos = (self.rd + pos) % N;
|
||||||
|
let mut off = 0;
|
||||||
|
while off < buffer.len() && self.is_readable_at(pos) {
|
||||||
|
buffer[off] = self.data[pos];
|
||||||
|
pos += 1;
|
||||||
|
off += 1;
|
||||||
|
}
|
||||||
|
off
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn write_unchecked(&mut self, ch: T) {
|
pub unsafe fn write_unchecked(&mut self, ch: T) {
|
||||||
self.data[self.wr] = ch;
|
self.data[self.wr] = ch;
|
||||||
self.wr = (self.wr + 1) % N;
|
self.wr = (self.wr + 1) % N;
|
||||||
}
|
}
|
||||||
@ -47,11 +70,7 @@ impl<T: Copy, const N: usize> Inner<T, N> {
|
|||||||
impl<T: Copy, const N: usize> AsyncRing<T, N> {
|
impl<T: Copy, const N: usize> AsyncRing<T, N> {
|
||||||
pub fn new(value: T) -> Self {
|
pub fn new(value: T) -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner: Arc::new(IrqSafeSpinlock::new(Inner {
|
inner: Arc::new(IrqSafeSpinlock::new(RingBuffer::new(value))),
|
||||||
rd: 0,
|
|
||||||
wr: 0,
|
|
||||||
data: [value; N],
|
|
||||||
})),
|
|
||||||
read_waker: Arc::new(QueueWaker::new()),
|
read_waker: Arc::new(QueueWaker::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -69,7 +88,7 @@ impl<T: Copy, const N: usize> AsyncRing<T, N> {
|
|||||||
|
|
||||||
pub fn read(&self) -> impl Future<Output = T> {
|
pub fn read(&self) -> impl Future<Output = T> {
|
||||||
struct ReadFuture<T: Copy, const N: usize> {
|
struct ReadFuture<T: Copy, const N: usize> {
|
||||||
inner: Arc<IrqSafeSpinlock<Inner<T, N>>>,
|
inner: Arc<IrqSafeSpinlock<RingBuffer<T, N>>>,
|
||||||
read_waker: Arc<QueueWaker>,
|
read_waker: Arc<QueueWaker>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user