forked from rcore-os/zCore
support ps
This commit is contained in:
parent
4e65330817
commit
ea69f7fee1
|
@ -184,6 +184,22 @@ impl Job {
|
|||
pub fn get_exceptionate(&self) -> Arc<Exceptionate> {
|
||||
self.exceptionate.clone()
|
||||
}
|
||||
|
||||
pub fn enumerate_process(&self, mut f: impl FnMut(KoID) -> bool) {
|
||||
self.inner
|
||||
.lock()
|
||||
.processes
|
||||
.iter()
|
||||
.find(|child| !f(child.id()));
|
||||
}
|
||||
|
||||
pub fn enumerate_children(&self, mut f: impl FnMut(KoID) -> bool) {
|
||||
self.inner
|
||||
.lock()
|
||||
.children
|
||||
.iter()
|
||||
.find(|child| !f(child.id()));
|
||||
}
|
||||
}
|
||||
|
||||
impl JobInner {
|
||||
|
|
|
@ -310,6 +310,14 @@ impl Process {
|
|||
Ok(handle.object)
|
||||
}
|
||||
|
||||
pub fn get_dyn_object_and_rights(
|
||||
&self,
|
||||
handle_value: HandleValue,
|
||||
) -> ZxResult<(Arc<dyn KernelObject>, Rights)> {
|
||||
let handle = self.get_handle(handle_value)?;
|
||||
Ok((handle.object, handle.rights))
|
||||
}
|
||||
|
||||
/// Get the kernel object corresponding to this `handle_value`
|
||||
pub fn get_object<T: KernelObject>(&self, handle_value: HandleValue) -> ZxResult<Arc<T>> {
|
||||
let handle = self.get_handle(handle_value)?;
|
||||
|
@ -402,6 +410,14 @@ impl Process {
|
|||
pub fn get_exceptionate(&self) -> Arc<Exceptionate> {
|
||||
self.exceptionate.clone()
|
||||
}
|
||||
|
||||
pub fn enumerate_thread(&self, mut f: impl FnMut(KoID) -> bool) {
|
||||
self.inner
|
||||
.lock()
|
||||
.threads
|
||||
.iter()
|
||||
.find(|child| !f(child.id()));
|
||||
}
|
||||
}
|
||||
|
||||
impl ProcessInner {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use core::sync::atomic::*;
|
||||
use {
|
||||
super::*, crate::object::*, alloc::sync::Arc, alloc::vec::Vec, bitflags::bitflags,
|
||||
kernel_hal::PageTable, spin::Mutex,
|
||||
super::*, crate::object::*, alloc::collections::VecDeque, alloc::sync::Arc, alloc::vec::Vec,
|
||||
bitflags::bitflags, kernel_hal::PageTable, spin::Mutex,
|
||||
};
|
||||
|
||||
bitflags! {
|
||||
|
@ -449,6 +449,31 @@ impl VmAddressRegion {
|
|||
Err(ZxError::NOT_FOUND)
|
||||
}
|
||||
|
||||
pub fn get_task_stats(&self) -> ZxInfoTaskStats {
|
||||
let mut task_stats = ZxInfoTaskStats::default();
|
||||
let mut list = VecDeque::new();
|
||||
self.inner
|
||||
.lock()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.children
|
||||
.iter()
|
||||
.for_each(|child| {
|
||||
list.push_back(child.clone());
|
||||
});
|
||||
while let Some(vmar) = list.pop_front() {
|
||||
let vmar_inner = vmar.inner.lock();
|
||||
let inner = vmar_inner.as_ref().unwrap();
|
||||
inner.children.iter().for_each(|child| {
|
||||
list.push_back(child.clone());
|
||||
});
|
||||
inner.mappings.iter().for_each(|map| {
|
||||
map.fill_in_task_status(&mut task_stats);
|
||||
});
|
||||
}
|
||||
task_stats
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn count(&self) -> usize {
|
||||
let mut guard = self.inner.lock();
|
||||
|
@ -487,6 +512,15 @@ struct VmMappingInner {
|
|||
vmo_offset: usize,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Default)]
|
||||
pub struct ZxInfoTaskStats {
|
||||
mapped_bytes: u64,
|
||||
private_bytes: u64,
|
||||
shared_bytes: u64,
|
||||
scaled_shared_bytes: u64,
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for VmMapping {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
let inner = self.inner.lock();
|
||||
|
@ -548,6 +582,21 @@ impl VmMapping {
|
|||
.unmap_from(&mut page_table, inner.addr, inner.vmo_offset, inner.size);
|
||||
}
|
||||
|
||||
fn fill_in_task_status(&self, task_stats: &mut ZxInfoTaskStats) {
|
||||
let inner = self.inner.lock();
|
||||
let start_idx = inner.vmo_offset / PAGE_SIZE;
|
||||
let end_idx = start_idx + inner.size / PAGE_SIZE;
|
||||
task_stats.mapped_bytes += self.vmo.len() as u64;
|
||||
let committed_pages = self.vmo.committed_pages_in_range(start_idx, end_idx);
|
||||
let share_count = self.vmo.share_count();
|
||||
if share_count == 1 {
|
||||
task_stats.private_bytes += (committed_pages * PAGE_SIZE) as u64;
|
||||
} else {
|
||||
task_stats.shared_bytes += (committed_pages * PAGE_SIZE) as u64;
|
||||
task_stats.scaled_shared_bytes += (committed_pages * PAGE_SIZE / share_count) as u64;
|
||||
}
|
||||
}
|
||||
|
||||
/// Cut and unmap regions in `[begin, end)`.
|
||||
///
|
||||
/// If it will be split, return another one.
|
||||
|
|
|
@ -67,6 +67,10 @@ pub trait VMObjectTrait: Sync + Send {
|
|||
fn get_cache_policy(&self) -> CachePolicy;
|
||||
|
||||
fn set_cache_policy(&self, policy: CachePolicy) -> ZxResult;
|
||||
|
||||
fn share_count(&self) -> usize;
|
||||
|
||||
fn committed_pages_in_range(&self, start_idx: usize, end_idx: usize) -> usize;
|
||||
}
|
||||
|
||||
pub struct VmObject {
|
||||
|
|
|
@ -316,6 +316,16 @@ impl VMObjectTrait for VMObjectPaged {
|
|||
// fn is_contiguous(&self) -> bool {
|
||||
// false
|
||||
// }
|
||||
|
||||
fn committed_pages_in_range(&self, start_idx: usize, end_idx: usize) -> usize {
|
||||
self.inner
|
||||
.lock()
|
||||
.committed_pages_in_range(start_idx, end_idx)
|
||||
}
|
||||
|
||||
fn share_count(&self) -> usize {
|
||||
self.inner.lock().mappings.len()
|
||||
}
|
||||
}
|
||||
|
||||
enum CommitResult {
|
||||
|
@ -522,9 +532,21 @@ impl VMObjectPagedInner {
|
|||
}
|
||||
|
||||
/// Count committed pages of the VMO.
|
||||
fn committed_pages(&self) -> usize {
|
||||
fn committed_pages_in_range(&self, start_idx: usize, end_idx: usize) -> usize {
|
||||
assert!(
|
||||
start_idx < self.size / PAGE_SIZE,
|
||||
"start_idx {:#x}, self.size {:#x}",
|
||||
start_idx,
|
||||
self.size
|
||||
);
|
||||
assert!(
|
||||
end_idx <= self.size / PAGE_SIZE,
|
||||
"end_idx {:#x}, self.size {:#x}",
|
||||
end_idx,
|
||||
self.size
|
||||
);
|
||||
let mut count = 0;
|
||||
for i in 0..self.size / PAGE_SIZE {
|
||||
for i in start_idx..end_idx {
|
||||
if self.frames.contains_key(&i) {
|
||||
count += 1;
|
||||
continue;
|
||||
|
@ -658,7 +680,8 @@ impl VMObjectPagedInner {
|
|||
info.num_children = if self.type_.is_hidden() { 2 } else { 0 };
|
||||
info.num_mappings = self.mappings.len() as u64; // FIXME remove weak ptr
|
||||
info.share_count = self.mappings.len() as u64; // FIXME share_count should be the count of unique aspace
|
||||
info.committed_bytes = (self.committed_pages() * PAGE_SIZE) as u64;
|
||||
info.committed_bytes =
|
||||
(self.committed_pages_in_range(0, self.size / PAGE_SIZE) * PAGE_SIZE) as u64;
|
||||
// TODO cache_policy should be set up.
|
||||
}
|
||||
|
||||
|
|
|
@ -120,6 +120,14 @@ impl VMObjectTrait for VMObjectPhysical {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn share_count(&self) -> usize {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn committed_pages_in_range(&self, _start_idx: usize, _end_idx: usize) -> usize {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -236,6 +236,9 @@ impl Syscall<'_> {
|
|||
let _ = self.sys_handle_close(a3 as _);
|
||||
self.sys_thread_exit()
|
||||
}),
|
||||
Sys::OBJECT_GET_CHILD => {
|
||||
self.sys_object_get_child(a0 as _, a1 as _, a2 as _, a3.into())
|
||||
}
|
||||
_ => {
|
||||
error!("syscall unimplemented: {:?}", sys_type);
|
||||
Err(ZxError::NOT_SUPPORTED)
|
||||
|
|
|
@ -168,14 +168,15 @@ impl Syscall<'_> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
pub fn sys_object_get_info(
|
||||
&self,
|
||||
handle: HandleValue,
|
||||
topic: u32,
|
||||
buffer: usize,
|
||||
buffer_size: usize,
|
||||
_actual: UserOutPtr<usize>,
|
||||
_avail: UserOutPtr<usize>,
|
||||
mut actual: UserOutPtr<usize>,
|
||||
mut avail: UserOutPtr<usize>,
|
||||
) -> ZxResult {
|
||||
let topic = Topic::try_from(topic).map_err(|_| ZxError::INVALID_ARGS)?;
|
||||
info!(
|
||||
|
@ -225,8 +226,71 @@ impl Syscall<'_> {
|
|||
kmem.vmo_bytes = vmo_page_bytes() as u64;
|
||||
UserOutPtr::<ZxInfoKmem>::from(buffer).write(kmem)?;
|
||||
}
|
||||
Topic::JobProcess => {
|
||||
let job = proc.get_object_with_rights::<Job>(handle, Rights::ENUMERATE)?;
|
||||
let (mut count, mut avail_count) = (0usize, 0usize);
|
||||
let ptr = UserOutPtr::<KoID>::from(buffer).as_ptr();
|
||||
let item_size = core::mem::size_of::<KoID>();
|
||||
job.enumerate_process(|id| {
|
||||
if count < buffer_size / item_size {
|
||||
unsafe {
|
||||
ptr.add(count).write(id);
|
||||
}
|
||||
count += 1;
|
||||
}
|
||||
avail_count += 1;
|
||||
true
|
||||
});
|
||||
actual.write(count)?;
|
||||
avail.write(avail_count)?;
|
||||
}
|
||||
Topic::TaskStats => {
|
||||
assert_eq!(core::mem::size_of::<ZxInfoTaskStats>(), buffer_size);
|
||||
let vmar = proc
|
||||
.get_object_with_rights::<Process>(handle, Rights::INSPECT)?
|
||||
.vmar();
|
||||
//let mut task_stats = ZxInfoTaskStats::default();
|
||||
let task_stats = vmar.get_task_stats();
|
||||
UserOutPtr::<ZxInfoTaskStats>::from(buffer).write(task_stats)?;
|
||||
}
|
||||
Topic::ProcessThreads => {
|
||||
let (mut count, mut avail_count) = (0usize, 0usize);
|
||||
let ptr = UserOutPtr::<KoID>::from(buffer).as_ptr();
|
||||
let item_size = core::mem::size_of::<KoID>();
|
||||
proc.get_object_with_rights::<Process>(handle, Rights::ENUMERATE)?
|
||||
.enumerate_thread(|id| {
|
||||
if count < buffer_size / item_size {
|
||||
unsafe {
|
||||
ptr.add(count).write(id);
|
||||
}
|
||||
count += 1;
|
||||
}
|
||||
avail_count += 1;
|
||||
true
|
||||
});
|
||||
actual.write(count)?;
|
||||
avail.write(avail_count)?;
|
||||
}
|
||||
Topic::JobChildren => {
|
||||
let (mut count, mut avail_count) = (0usize, 0usize);
|
||||
let ptr = UserOutPtr::<KoID>::from(buffer).as_ptr();
|
||||
let item_size = core::mem::size_of::<KoID>();
|
||||
proc.get_object_with_rights::<Job>(handle, Rights::ENUMERATE)?
|
||||
.enumerate_children(|id| {
|
||||
if count < buffer_size / item_size {
|
||||
unsafe {
|
||||
ptr.add(count).write(id);
|
||||
}
|
||||
count += 1;
|
||||
}
|
||||
avail_count += 1;
|
||||
true
|
||||
});
|
||||
actual.write(count)?;
|
||||
avail.write(avail_count)?;
|
||||
}
|
||||
_ => {
|
||||
warn!("not supported info topic: {:?}", topic);
|
||||
error!("not supported info topic: {:?}", topic);
|
||||
return Err(ZxError::NOT_SUPPORTED);
|
||||
}
|
||||
}
|
||||
|
@ -324,6 +388,34 @@ impl Syscall<'_> {
|
|||
user_items.write_array(&items)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn sys_object_get_child(
|
||||
&self,
|
||||
handle: HandleValue,
|
||||
koid: KoID,
|
||||
rights: u32,
|
||||
mut out: UserOutPtr<HandleValue>,
|
||||
) -> ZxResult {
|
||||
info!(
|
||||
"object.get_child: handle={:#x}, koid={:#x}, rights={:#x}",
|
||||
handle, koid, rights
|
||||
);
|
||||
let mut rights = Rights::from_bits(rights).ok_or(ZxError::INVALID_ARGS)?;
|
||||
let proc = self.thread.proc();
|
||||
let (task, parent_rights) = proc.get_dyn_object_and_rights(handle)?;
|
||||
if !parent_rights.contains(Rights::ENUMERATE) {
|
||||
return Err(ZxError::ACCESS_DENIED);
|
||||
}
|
||||
if rights == Rights::SAME_RIGHTS {
|
||||
rights = parent_rights;
|
||||
} else if (rights & parent_rights) != rights {
|
||||
return Err(ZxError::ACCESS_DENIED);
|
||||
}
|
||||
let child = task.get_child(koid)?;
|
||||
let child_handle = proc.add_handle(Handle::new(child, rights));
|
||||
out.write(child_handle)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
numeric_enum! {
|
||||
|
|
Loading…
Reference in New Issue