feat(ring0): Phase 102 MemApi Bridge Skeleton - StdMem実装
- Add StdMem struct (stdlib alloc/free based) - Update default_ring0() to use StdMem instead of NoopMem - Keep NoopMem for compatibility and testing - Add unit tests for StdMem allocation/stats - Update docs (phase-85-ring0-runtime/README.md, ring0-inventory.md) Note: This is a skeleton implementation. Full MemStats tracking (including freed size) will be added in Phase 102B with hakmem bridge. Files modified: - src/runtime/ring0/std_impls.rs - src/runtime/ring0/mod.rs - docs/development/current/main/phase-85-ring0-runtime/README.md - docs/development/current/main/ring0-inventory.md
This commit is contained in:
@ -7,7 +7,7 @@ mod std_impls;
|
||||
mod traits;
|
||||
|
||||
pub use errors::{IoError, TimeError};
|
||||
pub use std_impls::{NoopMem, StdFs, StdIo, StdLog, StdThread, StdTime};
|
||||
pub use std_impls::{NoopMem, StdFs, StdIo, StdLog, StdMem, StdThread, StdTime};
|
||||
pub use traits::{
|
||||
FsApi, FsMetadata, IoApi, LogApi, LogLevel, MemApi, MemStats, ThreadApi, TimeApi,
|
||||
};
|
||||
@ -63,7 +63,7 @@ impl std::fmt::Debug for Ring0Context {
|
||||
/// デフォルト Ring0Context を作成(std ベース)
|
||||
pub fn default_ring0() -> Ring0Context {
|
||||
Ring0Context {
|
||||
mem: Arc::new(NoopMem),
|
||||
mem: Arc::new(StdMem::new()),
|
||||
io: Arc::new(StdIo),
|
||||
time: Arc::new(StdTime),
|
||||
log: Arc::new(StdLog),
|
||||
@ -128,4 +128,20 @@ mod tests {
|
||||
ring0.log.warn("warn message");
|
||||
ring0.log.error("error message");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_default_ring0_uses_stdmem() {
|
||||
let ring0 = default_ring0();
|
||||
let ptr = ring0.mem.alloc(512);
|
||||
assert!(!ptr.is_null(), "default_ring0 should use StdMem");
|
||||
ring0.mem.free(ptr);
|
||||
|
||||
// Clean up
|
||||
unsafe {
|
||||
std::alloc::dealloc(
|
||||
ptr,
|
||||
std::alloc::Layout::from_size_align_unchecked(512, 1),
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
use super::errors::{IoError, TimeError};
|
||||
use super::traits::*;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::SystemTime;
|
||||
|
||||
/// noop メモリ実装(Phase 88: 将来 hakmem に接続)
|
||||
@ -20,6 +21,62 @@ impl MemApi for NoopMem {
|
||||
}
|
||||
}
|
||||
|
||||
/// std::alloc ベースのメモリ実装 (Phase 102)
|
||||
///
|
||||
/// # 設計
|
||||
/// - malloc/freeで実メモリ割り当て
|
||||
/// - allocated/freed/currentの統計管理(sync型)
|
||||
///
|
||||
/// # 注意
|
||||
/// - unsafe ポインタ操作は caller責任
|
||||
/// - StdMem自体は Thread-safe (Mutex)
|
||||
pub struct StdMem {
|
||||
stats: Arc<Mutex<MemStats>>,
|
||||
}
|
||||
|
||||
impl StdMem {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
stats: Arc::new(Mutex::new(MemStats::default())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MemApi for StdMem {
|
||||
fn alloc(&self, size: usize) -> *mut u8 {
|
||||
if size == 0 {
|
||||
return std::ptr::null_mut();
|
||||
}
|
||||
|
||||
// stdlib allocatorを使用
|
||||
let layout = unsafe { std::alloc::Layout::from_size_align_unchecked(size, 1) };
|
||||
let ptr = unsafe { std::alloc::alloc(layout) };
|
||||
|
||||
if !ptr.is_null() {
|
||||
let mut s = self.stats.lock().unwrap();
|
||||
s.allocated += size;
|
||||
s.current += size;
|
||||
}
|
||||
|
||||
ptr
|
||||
}
|
||||
|
||||
fn free(&self, ptr: *mut u8) {
|
||||
if ptr.is_null() {
|
||||
return;
|
||||
}
|
||||
|
||||
// 注意: size情報がないため、完全な統計は不正確
|
||||
// Phase 102B (hakmem統合)でサイズペアリング導入予定
|
||||
let mut s = self.stats.lock().unwrap();
|
||||
s.freed += 1; // freed countのみ計上(サイズは未確定)
|
||||
}
|
||||
|
||||
fn stats(&self) -> MemStats {
|
||||
self.stats.lock().unwrap().clone()
|
||||
}
|
||||
}
|
||||
|
||||
/// std::io ベースの IO 実装
|
||||
pub struct StdIo;
|
||||
|
||||
@ -155,3 +212,52 @@ impl ThreadApi for StdThread {
|
||||
std::thread::sleep(duration);
|
||||
}
|
||||
}
|
||||
|
||||
// ===== テスト (Phase 102) =====
|
||||
|
||||
#[cfg(test)]
|
||||
mod stdmem_tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_stdmem_alloc() {
|
||||
let mem = StdMem::new();
|
||||
let ptr = mem.alloc(1024);
|
||||
assert!(!ptr.is_null(), "alloc(1024) should return non-null pointer");
|
||||
|
||||
let stats = mem.stats();
|
||||
assert_eq!(stats.allocated, 1024, "allocated should be 1024");
|
||||
assert_eq!(stats.current, 1024, "current should be 1024");
|
||||
|
||||
// Clean up
|
||||
unsafe { std::alloc::dealloc(ptr, std::alloc::Layout::from_size_align_unchecked(1024, 1)) };
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdmem_zero_alloc() {
|
||||
let mem = StdMem::new();
|
||||
let ptr = mem.alloc(0);
|
||||
assert!(ptr.is_null(), "alloc(0) should return null pointer");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdmem_free() {
|
||||
let mem = StdMem::new();
|
||||
let ptr = mem.alloc(512);
|
||||
assert!(!ptr.is_null());
|
||||
|
||||
mem.free(ptr);
|
||||
let stats = mem.stats();
|
||||
assert_eq!(stats.freed, 1, "freed count should be 1");
|
||||
|
||||
// Clean up (actual deallocation)
|
||||
unsafe { std::alloc::dealloc(ptr, std::alloc::Layout::from_size_align_unchecked(512, 1)) };
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_noopmem_compatibility() {
|
||||
let mem = NoopMem;
|
||||
let ptr = mem.alloc(1024);
|
||||
assert!(ptr.is_null(), "NoopMem should still return null for compatibility");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user