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> {
|
pub fn get_exceptionate(&self) -> Arc<Exceptionate> {
|
||||||
self.exceptionate.clone()
|
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 {
|
impl JobInner {
|
||||||
|
|
|
@ -310,6 +310,14 @@ impl Process {
|
||||||
Ok(handle.object)
|
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`
|
/// Get the kernel object corresponding to this `handle_value`
|
||||||
pub fn get_object<T: KernelObject>(&self, handle_value: HandleValue) -> ZxResult<Arc<T>> {
|
pub fn get_object<T: KernelObject>(&self, handle_value: HandleValue) -> ZxResult<Arc<T>> {
|
||||||
let handle = self.get_handle(handle_value)?;
|
let handle = self.get_handle(handle_value)?;
|
||||||
|
@ -402,6 +410,14 @@ impl Process {
|
||||||
pub fn get_exceptionate(&self) -> Arc<Exceptionate> {
|
pub fn get_exceptionate(&self) -> Arc<Exceptionate> {
|
||||||
self.exceptionate.clone()
|
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 {
|
impl ProcessInner {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use core::sync::atomic::*;
|
use core::sync::atomic::*;
|
||||||
use {
|
use {
|
||||||
super::*, crate::object::*, alloc::sync::Arc, alloc::vec::Vec, bitflags::bitflags,
|
super::*, crate::object::*, alloc::collections::VecDeque, alloc::sync::Arc, alloc::vec::Vec,
|
||||||
kernel_hal::PageTable, spin::Mutex,
|
bitflags::bitflags, kernel_hal::PageTable, spin::Mutex,
|
||||||
};
|
};
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
|
@ -449,6 +449,31 @@ impl VmAddressRegion {
|
||||||
Err(ZxError::NOT_FOUND)
|
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)]
|
#[cfg(test)]
|
||||||
fn count(&self) -> usize {
|
fn count(&self) -> usize {
|
||||||
let mut guard = self.inner.lock();
|
let mut guard = self.inner.lock();
|
||||||
|
@ -487,6 +512,15 @@ struct VmMappingInner {
|
||||||
vmo_offset: usize,
|
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 {
|
impl core::fmt::Debug for VmMapping {
|
||||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
let inner = self.inner.lock();
|
let inner = self.inner.lock();
|
||||||
|
@ -548,6 +582,21 @@ impl VmMapping {
|
||||||
.unmap_from(&mut page_table, inner.addr, inner.vmo_offset, inner.size);
|
.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)`.
|
/// Cut and unmap regions in `[begin, end)`.
|
||||||
///
|
///
|
||||||
/// If it will be split, return another one.
|
/// If it will be split, return another one.
|
||||||
|
|
|
@ -67,6 +67,10 @@ pub trait VMObjectTrait: Sync + Send {
|
||||||
fn get_cache_policy(&self) -> CachePolicy;
|
fn get_cache_policy(&self) -> CachePolicy;
|
||||||
|
|
||||||
fn set_cache_policy(&self, policy: CachePolicy) -> ZxResult;
|
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 {
|
pub struct VmObject {
|
||||||
|
|
|
@ -316,6 +316,16 @@ impl VMObjectTrait for VMObjectPaged {
|
||||||
// fn is_contiguous(&self) -> bool {
|
// fn is_contiguous(&self) -> bool {
|
||||||
// false
|
// 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 {
|
enum CommitResult {
|
||||||
|
@ -522,9 +532,21 @@ impl VMObjectPagedInner {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Count committed pages of the VMO.
|
/// 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;
|
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) {
|
if self.frames.contains_key(&i) {
|
||||||
count += 1;
|
count += 1;
|
||||||
continue;
|
continue;
|
||||||
|
@ -658,7 +680,8 @@ impl VMObjectPagedInner {
|
||||||
info.num_children = if self.type_.is_hidden() { 2 } else { 0 };
|
info.num_children = if self.type_.is_hidden() { 2 } else { 0 };
|
||||||
info.num_mappings = self.mappings.len() as u64; // FIXME remove weak ptr
|
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.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.
|
// TODO cache_policy should be set up.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -120,6 +120,14 @@ impl VMObjectTrait for VMObjectPhysical {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn share_count(&self) -> usize {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn committed_pages_in_range(&self, _start_idx: usize, _end_idx: usize) -> usize {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -236,6 +236,9 @@ impl Syscall<'_> {
|
||||||
let _ = self.sys_handle_close(a3 as _);
|
let _ = self.sys_handle_close(a3 as _);
|
||||||
self.sys_thread_exit()
|
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);
|
error!("syscall unimplemented: {:?}", sys_type);
|
||||||
Err(ZxError::NOT_SUPPORTED)
|
Err(ZxError::NOT_SUPPORTED)
|
||||||
|
|
|
@ -168,14 +168,15 @@ impl Syscall<'_> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unsafe_code)]
|
||||||
pub fn sys_object_get_info(
|
pub fn sys_object_get_info(
|
||||||
&self,
|
&self,
|
||||||
handle: HandleValue,
|
handle: HandleValue,
|
||||||
topic: u32,
|
topic: u32,
|
||||||
buffer: usize,
|
buffer: usize,
|
||||||
buffer_size: usize,
|
buffer_size: usize,
|
||||||
_actual: UserOutPtr<usize>,
|
mut actual: UserOutPtr<usize>,
|
||||||
_avail: UserOutPtr<usize>,
|
mut avail: UserOutPtr<usize>,
|
||||||
) -> ZxResult {
|
) -> ZxResult {
|
||||||
let topic = Topic::try_from(topic).map_err(|_| ZxError::INVALID_ARGS)?;
|
let topic = Topic::try_from(topic).map_err(|_| ZxError::INVALID_ARGS)?;
|
||||||
info!(
|
info!(
|
||||||
|
@ -225,8 +226,71 @@ impl Syscall<'_> {
|
||||||
kmem.vmo_bytes = vmo_page_bytes() as u64;
|
kmem.vmo_bytes = vmo_page_bytes() as u64;
|
||||||
UserOutPtr::<ZxInfoKmem>::from(buffer).write(kmem)?;
|
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);
|
return Err(ZxError::NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -324,6 +388,34 @@ impl Syscall<'_> {
|
||||||
user_items.write_array(&items)?;
|
user_items.write_array(&items)?;
|
||||||
Ok(())
|
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! {
|
numeric_enum! {
|
||||||
|
|
Loading…
Reference in New Issue