1use crate::{arch::Trapframe, task::mytask};
10use alloc::{boxed::Box, string::{String, ToString}};
11use hashbrown::HashMap;
12use spin::Mutex;
13
14pub mod scarlet;
15
16pub const MAX_ABI_LENGTH: usize = 64;
17
18pub trait AbiModule: 'static {
25 fn name() -> &'static str
26 where
27 Self: Sized;
28
29 fn handle_syscall(&self, trapframe: &mut Trapframe) -> Result<usize, &'static str>;
30}
31
32
33pub struct AbiRegistry {
39 factories: HashMap<String, fn() -> Box<dyn AbiModule>>,
40}
41
42impl AbiRegistry {
43 fn new() -> Self {
44 Self {
45 factories: HashMap::new(),
46 }
47 }
48
49 #[allow(static_mut_refs)]
50 pub fn global() -> &'static Mutex<AbiRegistry> {
51 static mut INSTANCE: Option<Mutex<AbiRegistry>> = None;
53 static INIT: spin::Once = spin::Once::new();
54
55 unsafe {
56 INIT.call_once(|| {
57 INSTANCE = Some(Mutex::new(AbiRegistry::new()));
58 });
59
60 INSTANCE.as_ref().unwrap()
62 }
63 }
64
65 pub fn register<T>()
66 where
67 T: AbiModule + Default + 'static,
68 {
69 crate::early_println!("Registering ABI module: {}", T::name());
70 let mut registry = Self::global().lock();
71 registry
72 .factories
73 .insert(T::name().to_string(), || Box::new(T::default()));
74 }
75
76 pub fn instantiate(name: &str) -> Option<Box<dyn AbiModule>> {
77 let registry = Self::global().lock();
78 registry.factories.get(name).map(|f| f())
79 }
80}
81
82#[macro_export]
83macro_rules! register_abi {
84 ($ty:ty) => {
85 $crate::abi::AbiRegistry::register::<$ty>();
86 };
87}
88
89pub fn syscall_dispatcher(trapframe: &mut Trapframe) -> Result<usize, &'static str> {
90 let task = mytask().unwrap();
91 let abi = task.abi.as_deref_mut().expect("ABI not set");
92 abi.handle_syscall(trapframe)
93}