use alloc::vec;
use ax_errno::{AxError, AxResult};
use ax_memory_addr::{MemoryAddr, PAGE_SIZE_4K, VirtAddr};
use ax_runtime::hal::paging::MappingFlags;
use ax_task::current;
use starry_vm::vm_write_slice;
use crate::task::AsThread;
pub fn sys_mincore(addr: usize, length: usize, vec: *mut u8) -> AxResult<isize> {
let start_addr = VirtAddr::from(addr);
if !start_addr.is_aligned(PAGE_SIZE_4K) {
return Err(AxError::InvalidInput);
}
if vec.is_null() {
return Err(AxError::BadAddress);
}
debug!("sys_mincore <= addr: {addr:#x}, length: {length:#x}, vec: {vec:?}");
if length == 0 {
return Ok(0);
}
let page_count = length.div_ceil(PAGE_SIZE_4K);
let mut result = vec![0u8; page_count];
{
let curr = current();
let aspace_arc = curr.as_thread().proc_data.aspace();
let aspace = aspace_arc.lock();
let mut i = 0;
while i < page_count {
let addr = start_addr + i * PAGE_SIZE_4K;
let area = aspace.find_area(addr).ok_or(AxError::NoMemory)?;
if !area.flags().contains(MappingFlags::USER) {
return Err(AxError::NoMemory);
}
let (is_resident, size) = match aspace.page_table().query(addr) {
Ok((_, _, size)) => {
(true, size as _)
}
Err(_) => {
(false, PAGE_SIZE_4K)
}
};
let n = size / PAGE_SIZE_4K;
if is_resident {
let end = (i + n).min(page_count);
result[i..end].fill(1);
}
i += n;
}
}
vm_write_slice(vec, result.as_slice())?;
Ok(0)
}