Next Generation WASM Microkernel Operating System
at main 102 lines 3.7 kB view raw
1// Copyright 2025 Jonas Kruckenberg 2// 3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or 4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or 5// http://opensource.org/licenses/MIT>, at your option. This file may not be 6// copied, modified, or distributed except according to those terms. 7 8use alloc::sync::Arc; 9use core::sync::atomic::AtomicU64; 10 11use cranelift_codegen::settings::{Configurable, Flags}; 12use k23_spin::{Mutex, MutexGuard}; 13use rand::{Rng, SeedableRng}; 14use rand_chacha::ChaCha20Rng; 15 16use crate::arch; 17use crate::wasm::compile::Compiler; 18use crate::wasm::cranelift::CraneliftCompiler; 19use crate::wasm::type_registry::TypeRegistry; 20 21/// Global context for the runtime. 22/// 23/// An engine can be safely shared across threads and is a cheap cloneable 24/// handle to the actual engine. The engine itself will be deallocated once all 25/// references to it have gone away. 26#[derive(Debug, Clone)] 27pub struct Engine(Arc<EngineInner>); 28 29#[derive(Debug)] 30pub struct EngineInner { 31 compiler: CraneliftCompiler, 32 type_registry: TypeRegistry, 33 rng: Option<Mutex<ChaCha20Rng>>, 34 asid_alloc: Mutex<arch::AsidAllocator>, 35 epoch_counter: AtomicU64, 36} 37 38impl Default for Engine { 39 fn default() -> Self { 40 let isa_builder = cranelift_codegen::isa::lookup(target_lexicon::HOST).unwrap(); 41 let mut b = cranelift_codegen::settings::builder(); 42 b.set("opt_level", "speed_and_size").unwrap(); 43 b.set("libcall_call_conv", "isa_default").unwrap(); 44 b.set("preserve_frame_pointers", "true").unwrap(); 45 b.set("enable_probestack", "true").unwrap(); 46 b.set("probestack_strategy", "inline").unwrap(); 47 let target_isa = isa_builder.finish(Flags::new(b)).unwrap(); 48 49 Self(Arc::new(EngineInner { 50 compiler: CraneliftCompiler::new(target_isa), 51 type_registry: TypeRegistry::default(), 52 rng: None, 53 asid_alloc: Mutex::new(arch::AsidAllocator::new()), 54 epoch_counter: AtomicU64::new(0), 55 })) 56 } 57} 58 59impl Engine { 60 pub fn new(rng: &mut impl Rng) -> Self { 61 let isa_builder = cranelift_codegen::isa::lookup(target_lexicon::HOST).unwrap(); 62 let mut b = cranelift_codegen::settings::builder(); 63 b.set("opt_level", "speed_and_size").unwrap(); 64 b.set("libcall_call_conv", "isa_default").unwrap(); 65 b.set("preserve_frame_pointers", "true").unwrap(); 66 b.set("enable_probestack", "true").unwrap(); 67 b.set("probestack_strategy", "inline").unwrap(); 68 let target_isa = isa_builder.finish(Flags::new(b)).unwrap(); 69 70 Self(Arc::new(EngineInner { 71 compiler: CraneliftCompiler::new(target_isa), 72 type_registry: TypeRegistry::default(), 73 rng: Some(Mutex::new(ChaCha20Rng::from_rng(rng))), 74 asid_alloc: Mutex::new(arch::AsidAllocator::new()), 75 epoch_counter: AtomicU64::new(0), 76 })) 77 } 78 79 pub fn same(lhs: &Engine, rhs: &Engine) -> bool { 80 Arc::ptr_eq(&lhs.0, &rhs.0) 81 } 82 83 pub fn compiler(&self) -> &dyn Compiler { 84 &self.0.compiler 85 } 86 87 /// Returns the type registry of this engine, used to canonicalize types. 88 pub fn type_registry(&self) -> &TypeRegistry { 89 &self.0.type_registry 90 } 91 92 pub fn allocate_asid(&self) -> u16 { 93 let mut alloc = self.0.asid_alloc.lock(); 94 alloc.alloc().expect("out of address space identifiers") 95 } 96 pub fn rng(&self) -> Option<MutexGuard<'_, ChaCha20Rng>> { 97 Some(self.0.rng.as_ref()?.lock()) 98 } 99 pub fn epoch_counter(&self) -> &AtomicU64 { 100 &self.0.epoch_counter 101 } 102}