support ps

This commit is contained in:
PanQL 2020-04-28 17:23:34 +08:00 committed by Runji Wang
parent 4e65330817
commit ea69f7fee1
8 changed files with 219 additions and 8 deletions

View File

@ -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 {

View File

@ -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 {

View File

@ -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.

View File

@ -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 {

View File

@ -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.
}

View File

@ -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)]

View File

@ -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)

View File

@ -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! {