strat9_kernel/async_io/
syscall.rs1use alloc::sync::Arc;
7use strat9_abi::data::AsyncRingLayout;
8
9use crate::{memory::UserSliceWrite, syscall::error::SyscallError};
10
11use super::{complete, dispatch, ring::RingError};
12
13#[derive(Debug, Clone, Copy)]
14pub struct AsyncRingMapping {
15 pub sq_base: u64,
16 pub cq_base: u64,
17 pub sq_size: u64,
18 pub cq_size: u64,
19 pub entries: u32,
20}
21
22fn require_owned_ring_by_id(ring_id: u64) -> Result<Arc<super::ring::Ring>, SyscallError> {
23 let task = crate::process::current_task_clone().ok_or(SyscallError::PermissionDenied)?;
24 let ring = super::ring::find_ring(ring_id).ok_or(SyscallError::BadHandle)?;
25
26 if ring.owner_pid != task.pid {
27 return Err(SyscallError::PermissionDenied);
28 }
29
30 Ok(ring)
31}
32
33pub fn sys_async_setup(entries: u64, _flags: u64) -> Result<u64, SyscallError> {
35 let Some(task) = crate::process::current_task_clone() else {
36 return Err(SyscallError::PermissionDenied);
37 };
38 let pid = task.pid;
39 let entries = entries as u32;
40
41 super::ring::Ring::create(pid, entries).map_err(|e| match e {
42 RingError::Alloc => SyscallError::OutOfMemory,
43 RingError::NotFound => SyscallError::BadHandle,
44 RingError::TooManyRings => SyscallError::OutOfMemory,
45 })
46}
47
48pub fn sys_async_map(ring_id: u64, out_ptr: u64) -> Result<u64, SyscallError> {
50 if out_ptr == 0 {
51 return Err(SyscallError::Fault);
52 }
53
54 let task = crate::process::current_task_clone().ok_or(SyscallError::PermissionDenied)?;
55 let ring = require_owned_ring_by_id(ring_id)?;
56
57 let mapping = ring
58 .map_into_process(&task.process.address_space_arc())
59 .map_err(|_| SyscallError::OutOfMemory)?;
60
61 let abi = AsyncRingLayout {
62 sq_base: mapping.sq_base,
63 cq_base: mapping.cq_base,
64 sq_size: mapping.sq_size,
65 cq_size: mapping.cq_size,
66 entries: mapping.entries,
67 _reserved: 0,
68 };
69
70 let out = UserSliceWrite::new(out_ptr, core::mem::size_of::<AsyncRingLayout>())?;
71 let bytes = unsafe {
72 core::slice::from_raw_parts(
73 &abi as *const AsyncRingLayout as *const u8,
74 core::mem::size_of::<AsyncRingLayout>(),
75 )
76 };
77 out.copy_from(bytes);
78
79 Ok(mapping.sq_size.saturating_add(mapping.cq_size))
80}
81
82pub fn sys_async_enter(
84 ring_id: u64,
85 to_submit: u64,
86 min_complete: u64,
87 _flags: u64,
88) -> Result<u64, SyscallError> {
89 let ring = require_owned_ring_by_id(ring_id)?;
90
91 let to_submit = to_submit as u32;
92 let min_complete = min_complete as u32;
93
94 if to_submit > 0 {
96 dispatch::drain_submissions(ring_id, to_submit);
97 }
98
99 crate::hardware::storage::ahci::flush_deferred_async_read_completions(ring_id);
100
101 let mut completed = complete::drain_completions(ring_id, min_complete);
105
106 if completed == 0 && min_complete > 0 {
108 completed = ring.wq.wait_until(|| {
109 if ring.destroyed.load(core::sync::atomic::Ordering::Acquire) != 0 {
110 return Some(0);
111 }
112
113 crate::hardware::storage::ahci::flush_deferred_async_read_completions(ring_id);
114
115 let ready = complete::drain_completions(ring_id, min_complete);
116 if ready > 0 {
117 Some(ready)
118 } else {
119 None
120 }
121 });
122 }
123
124 Ok(completed as u64)
125}
126
127pub fn sys_async_cancel(ring_id: u64, _user_data: u64, _flags: u64) -> Result<u64, SyscallError> {
129 let _ = require_owned_ring_by_id(ring_id)?;
130
131 Err(SyscallError::NotImplemented)
132}
133
134pub fn sys_async_destroy(ring_id: u64, _flags: u64) -> Result<u64, SyscallError> {
136 let _ = require_owned_ring_by_id(ring_id)?;
137
138 super::ring::destroy_ring(ring_id).map_err(|e| match e {
139 RingError::Alloc => SyscallError::OutOfMemory,
140 RingError::NotFound => SyscallError::BadHandle,
141 RingError::TooManyRings => SyscallError::InvalidArgument,
142 })?;
143
144 Ok(0)
145}