starry-kernel 0.10.1

A Linux-compatible OS kernel built on ArceOS unikernel
Documentation
use axfs_ng_vfs::{VfsError, VfsResult};

use super::IdentityTraceBuffer;
use crate::{
    pseudofs::DirectRwFsFileOps,
    sync::Mutex,
    task::{current_user_task, future::block_on_user},
};

/// File representing the trace pipe.
///
/// TODO: Linux rejects concurrent `trace_pipe` readers at open time with
/// `EBUSY`, because this file consumes records from the shared trace buffer.
/// The current pseudofs/VFS path has no per-open hook or private file state, so
/// this node cannot faithfully reserve and release a reader slot yet. Keep the
/// limitation documented here until tracefs files can move their read state to
/// open-file private data.
pub struct TracePipeFile(Mutex<super::TextDrain>);

impl TracePipeFile {
    /// Creates a new `TracePipeFile` instance.
    pub const fn new() -> Self {
        Self(Mutex::new(super::TextDrain::new()))
    }

    fn readable(&self) -> bool {
        let trace_raw_pipe = super::TRACE_STATE.raw_pipe.lock();
        !trace_raw_pipe.is_empty()
    }
}

impl DirectRwFsFileOps for TracePipeFile {
    fn read_at(&self, buf: &mut [u8], _offset: u64) -> VfsResult<usize> {
        if buf.is_empty() {
            return Ok(0);
        }

        let read_len = loop {
            {
                let mut drain = self.0.lock();
                let mut trace_raw_pipe = super::TRACE_STATE.raw_pipe.lock();
                let read_len = super::common_trace_pipe_read(&mut *trace_raw_pipe, &mut drain, buf);
                if read_len != 0 {
                    break read_len;
                }
            }

            // wait for new data
            let task = current_user_task();
            let _result = block_on_user(
                &task,
                crate::task::wait_on_pollset(&super::TRACE_STATE.pipe_event, || {
                    self.readable().then_some(true)
                }),
            )
            .into_result()
            .map_err(|error| VfsError::from(crate::StarryError::from(error)))?;
        };
        Ok(read_len)
    }
}