diff --git a/docs/development/current/main/phase-85-ring0-runtime/README.md b/docs/development/current/main/phase-85-ring0-runtime/README.md new file mode 100644 index 00000000..ab7456c4 --- /dev/null +++ b/docs/development/current/main/phase-85-ring0-runtime/README.md @@ -0,0 +1,75 @@ +# Phase 85: Ring0 Runtime System + +Ring0 is the OS API abstraction layer in Hakorune/Nyash, providing a clean interface to system resources without knowing about Boxes or Nyash-specific concepts. + +## Architecture + +Ring0Context bundles multiple API traits: +- **MemApi**: Memory allocation (malloc/free) +- **IoApi**: Stdin/Stdout/Stderr operations +- **TimeApi**: System time and monotonic clock +- **LogApi**: Structured logging +- **FsApi**: File system operations (Phase 90-A) +- **ThreadApi**: Thread operations (Phase 90-D) + +## Implementations + +### Phase 88: Initial std-based implementations +- NoopMem: Stub memory API (returns null) +- StdIo: std::io based I/O +- StdTime: std::time based time +- StdLog: eprintln!/println! based logging +- StdFs: std::fs based filesystem +- StdThread: std::thread based threading + +### Phase 102: MemApi Bridge Skeleton + +**Completed Tasks**: +- StdMem implementation (stdlib alloc/free based) +- default_ring0() unified to use StdMem instead of NoopMem +- Unit tests for StdMem allocation and statistics +- NoopMem retained for compatibility + +#### Implementation Status +- **StdMem**: Implemented (stdlib alloc/free based) +- **Statistics Management**: allocated/freed/current counters +- **Compatibility**: NoopMem retained for testing + +#### Design Notes +- The free() method counts freed operations but not freed bytes (no size info) +- Full statistics tracking will be added in Phase 102B (hakmem integration) + +#### Usage Example +```rust +let mem = StdMem::new(); +let ptr = mem.alloc(1024); +let stats = mem.stats(); +println!("allocated: {}, current: {}", stats.allocated, stats.current); +mem.free(ptr); +``` + +#### Next Steps +Phase 102B will add: +- Size-pairing dictionary (record alloc sizes) +- Accurate freed size statistics +- hakmem API bridge integration + +## Global Ring0Context + +Ring0 provides a global singleton via: +- `init_global_ring0(ctx)`: Initialize global context +- `get_global_ring0()`: Get global context + +## Testing + +All Ring0 components have comprehensive unit tests. Run with: +```bash +cargo test --release --lib ring0 +``` + +## Files + +- `src/runtime/ring0/mod.rs`: Main module and Ring0Context struct +- `src/runtime/ring0/traits.rs`: API trait definitions +- `src/runtime/ring0/std_impls.rs`: Standard library implementations +- `src/runtime/ring0/errors.rs`: Error types diff --git a/docs/development/current/main/ring0-inventory.md b/docs/development/current/main/ring0-inventory.md index 898b486b..98edfbaf 100644 --- a/docs/development/current/main/ring0-inventory.md +++ b/docs/development/current/main/ring0-inventory.md @@ -4,7 +4,7 @@ This document provides an inventory of Ring0.log infrastructure and categorizes the remaining println!/eprintln! call sites across the codebase. This inventory serves as the foundation for future migration planning. -**Status**: Design phase (Phase 99) - assessment and planning only, no code changes. +**Status**: Phase 101-B in progress — planning baseline plus partial internal/dev migration to Ring0.log (113 call sites converted across 5 batches). --- @@ -155,6 +155,35 @@ This document provides an inventory of Ring0.log infrastructure and categorizes --- +### Phase 101-B Update (2025-12-04) + +- internal/dev ログ 26 箇所を Ring0.log 化(stderr ノイズ削減)[第1バッチ] + - runtime: provider_lock.rs, type_meta.rs, deprecations.rs, leak_tracker.rs, plugin_loader_unified.rs + - plugin loader v2: loader/config.rs, loader/library.rs, loader/metadata.rs, instance_manager.rs, ffi_bridge.rs +- internal/dev ログ 21 箇所を追加で Ring0.log 化 [第2バッチ] + - runtime: provider_verify.rs, scheduler.rs, gc_controller.rs, box_registry.rs + - plugin loader v2: loader/specs.rs(TypeBox ABI/trace) + - runner: runner/trace.rs(cli_verbose トレース) + - mir: mir/verification.rs(NYASH_BREAKFINDER_SSA_TRACE / NYASH_DEBUG_VERIFIER) +- internal/dev ログ 20 箇所を追加で Ring0.log 化 [第3バッチ] + - mir core: basic_block.rs(insert-after-phis trace)、control_form.rs、hints.rs、effect.rs、printer.rs、optimizer.rs +- internal/dev ログ 26 箇所を追加で Ring0.log 化 [第4バッチ] + - mir builder/region: loop_builder/phi_ops.rs、builder/type_registry.rs、region/observer.rs + - plugin loader v2: enabled/extern_functions.rs(call/console trace)、enabled/types.rs(finalize trace) +- internal/dev ログ 20 箇所を追加で Ring0.log 化 [第5バッチ] + - mir loop_builder JoinIR 系: joinir_if_phi_selector.rs(dry-run trace)、control.rs(LoopForm debug) + - mir builder observe: observe/types.rs(NYASH_MIR_TYPE_TRACE)、observe/resolve.rs(NYASH_DEBUG_KPI_KNOWN) + - joinir VM bridge: join_ir_vm_bridge_dispatch/exec_routes.rs(run_generic_joinir_route trace) + - plugin loader v2: enabled/extern_functions.rs(NYASH_DEBUG_TRACE / runtime_checkpoint_trace / NYASH_BOX_INTROSPECT_TRACE) +- 役目: internal/diagnostic ログの責務を Ring0.log に寄せ、ConsoleService とテスト出力を分離 +- 残件概算: + - dev-debug: ~475–495 箇所(Phase 101-A の 34 箇所 + 5バッチ合計 113 箇所以外の残り) + - internal: ~699 箇所(812 から 113 箇所控除のラフ値) + - test: ~299 箇所(方針どおり維持) + - hack_check (.hako) は別フェーズで扱う(Rust 側とは切り離し) + +--- + ## Section 3: Ring0.log Expansion Plan (Sketch) ### Future Directions (Not Implemented) @@ -460,6 +489,24 @@ rg 'impl.*LogApi' --type rust --- +### Phase 102: MemApi Bridge Skeleton (COMPLETED) + +**Completed Tasks**: +- ✅ StdMem implementation (stdlib alloc/free) +- ✅ default_ring0() unified to use StdMem +- ✅ Unit tests for StdMem allocation and statistics +- ✅ NoopMem retained for compatibility + +**Status**: Skeleton ready for Phase 102B (hakmem bridge integration) + +**Files Modified**: +- src/runtime/ring0/std_impls.rs (added StdMem) +- src/runtime/ring0/mod.rs (updated default_ring0, exports) +- docs/development/current/main/phase-85-ring0-runtime/README.md (added Phase 102 section) +- docs/development/current/main/ring0-inventory.md (this file) + +--- + ## Summary Phase 99 establishes a **clear inventory** of logging infrastructure and println! call sites: @@ -469,4 +516,6 @@ Phase 99 establishes a **clear inventory** of logging infrastructure and println 3. **Migration strategy**: Phased approach starting with user-facing messages 4. **Success criteria**: Clear metrics for each phase +**Phase 102**: StdMem implementation complete, preparing for hakmem integration. + **Next Steps**: Phase 100+ will implement gradual migrations based on this inventory. diff --git a/src/runtime/ring0/mod.rs b/src/runtime/ring0/mod.rs index dd612276..8ec52269 100644 --- a/src/runtime/ring0/mod.rs +++ b/src/runtime/ring0/mod.rs @@ -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), + ) + }; + } } diff --git a/src/runtime/ring0/std_impls.rs b/src/runtime/ring0/std_impls.rs index f4b4c02c..212f961c 100644 --- a/src/runtime/ring0/std_impls.rs +++ b/src/runtime/ring0/std_impls.rs @@ -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>, +} + +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"); + } +}