ch02-02, basic code

master
DeathWish5 5 years ago
parent 9424010ff8
commit fe4ee39b03

@ -3,4 +3,5 @@ members = [
"ch01-01",
"ch01-02",
"ch01-03",
"ch02-02",
]

@ -10,4 +10,3 @@ edition = "2018"
spin = "0.7"
downcast-rs = { version = "1.2.0", default-features = false }
bitflags = "1.2"
buddy_system_allocator = "0.7"

@ -1,5 +1,5 @@
[package]
name = "ch01-03"
name = "ch02-02"
version = "0.1.0"
authors = ["Runji Wang <wangrunji0408@163.com>"]
edition = "2018"
@ -10,4 +10,4 @@ edition = "2018"
spin = "0.7"
downcast-rs = { version = "1.2.0", default-features = false }
bitflags = "1.2"
buddy_system_allocator = "0.7"
hashbrown = "0.9"

@ -5,7 +5,6 @@ use {
alloc::collections::VecDeque,
alloc::sync::{Arc, Weak},
alloc::vec::Vec,
core::convert::TryInto,
core::sync::atomic::{AtomicU32, Ordering},
spin::Mutex,
};
@ -56,7 +55,7 @@ impl Channel {
/// Read a packet from the channel if check is ok, otherwise the msg will keep.
pub fn read(&self) -> ZxResult<T> {
let mut recv_queue = self.recv_queue.lock();
if let Some(msg) = recv_queue.front() {
if let Some(_) = recv_queue.front() {
let msg = recv_queue.pop_front().unwrap();
return Ok(msg);
}
@ -106,9 +105,6 @@ pub struct MessagePacket {
#[cfg(test)]
mod tests {
use super::*;
use alloc::boxed::Box;
use core::sync::atomic::*;
use core::time::Duration;
#[test]
fn test_basics() {

@ -1,9 +1,18 @@
#![no_std]
#![deny(unused_imports)]
#![allow(dead_code)]
#![feature(get_mut_unchecked)]
extern crate alloc;
#[cfg(test)]
#[macro_use]
extern crate std;
mod error;
mod ipc;
mod object;
mod task;
mod vm;
pub use self::error::*;

@ -2,6 +2,8 @@
use super::{KernelObject, Rights};
use alloc::sync::Arc;
pub type HandleValue = u32;
/// 内核对象句柄
#[derive(Clone)]
pub struct Handle {

@ -1,4 +1,3 @@
use crate::error::*;
use alloc::string::String;
use alloc::sync::Arc;
use core::fmt::Debug;
@ -6,13 +5,12 @@ use core::sync::atomic::*;
use downcast_rs::{impl_downcast, DowncastSync};
use spin::Mutex;
// ANCHOR: mod
mod handle;
mod rights;
pub use self::handle::*;
pub use self::rights::*;
// ANCHOR_END: mod
pub use super::*;
/// 内核对象公共接口
pub trait KernelObject: DowncastSync + Debug {
@ -79,6 +77,11 @@ impl Default for KObjectBase {
}
impl KObjectBase {
/// Create a new kernel object base.
pub fn new() -> Self {
Self::default()
}
/// 生成一个唯一的 ID
fn new_koid() -> KoID {
static NEXT_KOID: AtomicU64 = AtomicU64::new(1024);
@ -92,6 +95,16 @@ impl KObjectBase {
pub fn set_name(&self, name: &str) {
self.inner.lock().name = String::from(name);
}
/// Create a kernel object base with `name`.
pub fn with_name(name: &str) -> Self {
KObjectBase {
id: Self::new_koid(),
inner: Mutex::new(KObjectBaseInner {
name: String::from(name),
}),
}
}
}
/// 为内核对象 struct 自动实现 `KernelObject` trait 的宏。

@ -29,7 +29,29 @@ bitflags! {
const BASIC = Self::TRANSFER.bits | Self::DUPLICATE.bits | Self::WAIT.bits | Self::INSPECT.bits;
const IO = Self::READ.bits | Self::WRITE.bits;
/// GET_PROPERTY SET_PROPERTY
const PROPERTY = Self::GET_PROPERTY.bits | Self::SET_PROPERTY.bits;
/// GET_POLICY SET_POLICY
const POLICY = Self::GET_POLICY.bits | Self::SET_POLICY.bits;
/// BASIC & !Self::DUPLICATE | IO | SIGNAL | SIGNAL_PEER
const DEFAULT_CHANNEL = Self::BASIC.bits & !Self::DUPLICATE.bits | Self::IO.bits | Self::SIGNAL.bits | Self::SIGNAL_PEER.bits;
/// BASIC | IO | PROPERTY | ENUMERATE | DESTROY | SIGNAL | MANAGE_PROCESS | MANAGE_THREAD
const DEFAULT_PROCESS = Self::BASIC.bits | Self::IO.bits | Self::PROPERTY.bits | Self::ENUMERATE.bits | Self::DESTROY.bits
| Self::SIGNAL.bits | Self::MANAGE_PROCESS.bits | Self::MANAGE_THREAD.bits;
/// BASIC | IO | PROPERTY | DESTROY | SIGNAL | MANAGE_THREAD
const DEFAULT_THREAD = Self::BASIC.bits | Self::IO.bits | Self::PROPERTY.bits | Self::DESTROY.bits | Self::SIGNAL.bits | Self::MANAGE_THREAD.bits;
/// BASIC | WAIT
const DEFAULT_VMAR = Self::BASIC.bits & !Self::WAIT.bits;
/// BASIC | IO | PROPERTY | POLICY | ENUMERATE | DESTROY | SIGNAL | MANAGE_JOB | MANAGE_PROCESS | MANAGE_THREAD
const DEFAULT_JOB = Self::BASIC.bits | Self::IO.bits | Self::PROPERTY.bits | Self::POLICY.bits | Self::ENUMERATE.bits
| Self::DESTROY.bits | Self::SIGNAL.bits | Self::MANAGE_JOB.bits | Self::MANAGE_PROCESS.bits | Self::MANAGE_THREAD.bits;
}
}
// ANCHOR_END: rights

@ -1,6 +1,8 @@
use {
super::job_policy::*,
super::process::Process,
super::*,
crate::error::*,
crate::object::*,
crate::task::Task,
alloc::sync::{Arc, Weak},
@ -122,17 +124,6 @@ impl Job {
Ok(())
}
/// Sets timer slack policy to an empty job.
pub fn set_policy_timer_slack(&self, policy: TimerSlackPolicy) -> ZxResult {
let mut inner = self.inner.lock();
if !inner.is_empty() {
return Err(ZxError::BAD_STATE);
}
check_timer_policy(&policy)?;
inner.timer_policy = inner.timer_policy.generate_new(policy);
Ok(())
}
/// Add a process to the job.
pub(super) fn add_process(&self, process: Arc<Process>) -> ZxResult {
let mut inner = self.inner.lock();
@ -241,7 +232,7 @@ impl Drop for Job {
#[cfg(test)]
mod tests {
use super::*;
use crate::task::{CurrentThread, Status, Thread, ThreadState, TASK_RETCODE_SYSCALL_KILL};
use crate::task::TASK_RETCODE_SYSCALL_KILL;
#[test]
fn create() {
@ -387,35 +378,23 @@ mod tests {
let job = Job::create_child(&root_job).expect("failed to create job");
let proc = Process::create(&root_job, "proc").expect("failed to create process");
let thread = Thread::create(&proc, "thread").expect("failed to create thread");
let current_thread = CurrentThread(thread.clone());
root_job.kill();
assert!(root_job.inner.lock().killed);
assert!(job.inner.lock().killed);
assert_eq!(proc.status(), Status::Exited(TASK_RETCODE_SYSCALL_KILL));
assert_eq!(thread.state(), ThreadState::Dying);
// killed but not terminated, since `CurrentThread` not dropped.
assert!(!root_job.signal().contains(Signal::JOB_TERMINATED));
assert!(job.signal().contains(Signal::JOB_TERMINATED)); // but the lonely job is terminated
assert!(!proc.signal().contains(Signal::PROCESS_TERMINATED));
assert!(!thread.signal().contains(Signal::THREAD_TERMINATED));
std::mem::drop(current_thread);
// assert_eq!(thread.state(), ThreadState::Dying);
std::mem::drop(thread);
assert!(root_job.inner.lock().killed);
assert!(job.inner.lock().killed);
assert_eq!(proc.status(), Status::Exited(TASK_RETCODE_SYSCALL_KILL));
assert_eq!(thread.state(), ThreadState::Dead);
// all terminated now
assert!(root_job.signal().contains(Signal::JOB_TERMINATED));
assert!(job.signal().contains(Signal::JOB_TERMINATED));
assert!(proc.signal().contains(Signal::PROCESS_TERMINATED));
assert!(thread.signal().contains(Signal::THREAD_TERMINATED));
// assert_eq!(thread.state(), ThreadState::Dead);
// The job has no children.
let root_job = Job::root();
root_job.kill();
assert!(root_job.inner.lock().killed);
assert!(root_job.signal().contains(Signal::JOB_TERMINATED));
// The job's process have no threads.
let root_job = Job::root();
@ -425,31 +404,5 @@ mod tests {
assert!(root_job.inner.lock().killed);
assert!(job.inner.lock().killed);
assert_eq!(proc.status(), Status::Exited(TASK_RETCODE_SYSCALL_KILL));
assert!(root_job.signal().contains(Signal::JOB_TERMINATED));
assert!(job.signal().contains(Signal::JOB_TERMINATED));
assert!(proc.signal().contains(Signal::PROCESS_TERMINATED));
}
#[test]
fn critical_process() {
let root_job = Job::root();
let job = root_job.create_child().unwrap();
let job1 = root_job.create_child().unwrap();
let proc = Process::create(&job, "proc").expect("failed to create process");
assert_eq!(
proc.set_critical_at_job(&job1, true).err(),
Some(ZxError::INVALID_ARGS)
);
proc.set_critical_at_job(&root_job, true).unwrap();
assert_eq!(
proc.set_critical_at_job(&job, true).err(),
Some(ZxError::ALREADY_BOUND)
);
proc.exit(666);
assert!(root_job.inner.lock().killed);
assert!(root_job.signal().contains(Signal::JOB_TERMINATED));
}
}

@ -1,5 +1,3 @@
use crate::error::*;
/// Security and resource policies of a job.
#[derive(Default, Copy, Clone)]
pub struct JobPolicy {
@ -108,45 +106,3 @@ pub enum PolicyAction {
/// Terminate the process.
Kill = 4,
}
/// Timer slack policy.
///
/// See [timer slack](../../signal/timer/enum.Slack.html) for more information.
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct TimerSlackPolicy {
min_slack: i64,
default_mode: Slack,
}
/// Check whether the policy is valid.
pub fn check_timer_policy(policy: &TimerSlackPolicy) -> ZxResult {
if policy.min_slack.is_negative() {
return Err(ZxError::INVALID_ARGS);
}
Ok(())
}
#[repr(C)]
pub(super) struct TimerSlack {
amount: i64,
mode: Slack,
}
impl TimerSlack {
pub(super) fn generate_new(&self, policy: TimerSlackPolicy) -> TimerSlack {
TimerSlack {
amount: self.amount.max(policy.min_slack),
mode: policy.default_mode,
}
}
}
impl Default for TimerSlack {
fn default() -> Self {
TimerSlack {
amount: 0,
mode: Slack::Center,
}
}
}

@ -3,6 +3,9 @@ use super::*;
mod job;
mod job_policy;
mod process;
mod thread;
pub use {self::job::*, self::job_policy::*, self::process::*, self::thread::*};
/// Task (Thread, Process, or Job)
pub trait Task: Sync + Send {
@ -15,12 +18,6 @@ pub trait Task: Sync + Send {
/// Resume the task
fn resume(&self);
/// Get the exceptionate.
fn exceptionate(&self) -> Arc<Exceptionate>;
/// Get the debug exceptionate.
fn debug_exceptionate(&self) -> Arc<Exceptionate>;
}
/// The return code set when a task is killed via zx_task_kill().

@ -1,68 +1,116 @@
use super::*;
use crate::error::*;
use crate::object::*;
use alloc::collections::BTreeMap;
use alloc::sync::Arc;
use spin::Mutex;
// ANCHOR: process
/// 进程对象
use {
super::{job::Job, job_policy::*, thread::*, *},
crate::{error::*, object::*, vm::*},
alloc::{sync::Arc, vec::Vec},
hashbrown::HashMap,
spin::Mutex,
};
pub struct Process {
base: KObjectBase,
job: Arc<Job>,
policy: JobPolicy,
vmar: Arc<VmAddressRegion>,
inner: Mutex<ProcessInner>,
}
impl_kobject!(Process);
impl_kobject!(Process
fn get_child(&self, id: KoID) -> ZxResult<Arc<dyn KernelObject>> {
let inner = self.inner.lock();
let thread = inner.threads.iter().find(|o| o.id() == id).ok_or(ZxError::NOT_FOUND)?;
Ok(thread.clone())
}
fn related_koid(&self) -> KoID {
self.job.id()
}
);
#[derive(Default)]
struct ProcessInner {
handles: BTreeMap<HandleValue, Handle>,
max_handle_id: u32,
status: Status,
handles: HashMap<HandleValue, Handle>,
threads: Vec<Arc<Thread>>,
}
/// Status of a process.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum Status {
/// Initial state, no thread present in process.
Init,
/// First thread has started and is running.
Running,
/// Process has exited with the code.
Exited(i64),
}
pub type HandleValue = u32;
impl Default for Status {
fn default() -> Self {
Status::Init
}
}
impl Process {
/// 创建一个新的进程对象
pub fn new() -> Arc<Self> {
Arc::new(Process {
base: KObjectBase::default(),
inner: Mutex::new(ProcessInner {
handles: BTreeMap::default(),
}),
})
}
// ANCHOR_END: process
// ANCHOR: add_remove_handle
/// Create a new process in the `job`.
pub fn create(job: &Arc<Job>, name: &str) -> ZxResult<Arc<Self>> {
let proc = Arc::new(Process {
base: KObjectBase::with_name(name),
job: job.clone(),
policy: job.policy(),
vmar: VmAddressRegion::new_root(),
inner: Mutex::new(ProcessInner::default()),
});
job.add_process(proc.clone())?;
Ok(proc)
}
/// Get a handle from the process
fn get_handle(&self, handle_value: HandleValue) -> ZxResult<Handle> {
self.inner.lock().get_handle(handle_value)
}
/// 添加一个新的对象句柄
pub fn add_handle(&self, handle: Handle) -> HandleValue {
let mut inner = self.inner.lock();
let value = (0 as HandleValue..)
.find(|idx| !inner.handles.contains_key(idx))
.unwrap();
inner.handles.insert(value, handle);
value
self.inner.lock().add_handle(handle)
}
/// 删除一个对象句柄
pub fn remove_handle(&self, handle_value: HandleValue) {
self.inner.lock().handles.remove(&handle_value);
pub fn remove_handle(&self, handle_value: HandleValue) -> ZxResult<Handle> {
self.inner.lock().remove_handle(handle_value)
}
/// Add all handles to the process
pub fn add_handles(&self, handles: Vec<Handle>) -> Vec<HandleValue> {
let mut inner = self.inner.lock();
handles.into_iter().map(|h| inner.add_handle(h)).collect()
}
/// Remove all handles from the process.
pub fn remove_handles(&self, handle_values: &[HandleValue]) -> ZxResult<Vec<Handle>> {
let mut inner = self.inner.lock();
handle_values
.iter()
.map(|h| inner.remove_handle(*h))
.collect()
}
/// 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)?;
let object = handle
.object
.downcast_arc::<T>()
.map_err(|_| ZxError::WRONG_TYPE)?;
Ok(object)
}
// ANCHOR_END: add_remove_handle
// ANCHOR: get_object_with_rights
/// 根据句柄值查找内核对象,并检查权限
pub fn get_object_with_rights<T: KernelObject>(
&self,
handle_value: HandleValue,
desired_rights: Rights,
) -> ZxResult<Arc<T>> {
let handle = self
.inner
.lock()
.handles
.get(&handle_value)
.ok_or(ZxError::BAD_HANDLE)?
.clone();
let handle = self.get_handle(handle_value)?;
// check type before rights
let object = handle
.object
@ -73,5 +121,329 @@ impl Process {
}
Ok(object)
}
// ANCHOR_END: get_object_with_rights
/// Get the kernel object corresponding to this `handle_value` and this handle's rights.
pub fn get_object_and_rights<T: KernelObject>(
&self,
handle_value: HandleValue,
) -> ZxResult<(Arc<T>, Rights)> {
let handle = self.get_handle(handle_value)?;
let object = handle
.object
.downcast_arc::<T>()
.map_err(|_| ZxError::WRONG_TYPE)?;
Ok((object, handle.rights))
}
/// Remove a handle referring to a kernel object of the given type from the process.
pub fn remove_object<T: KernelObject>(&self, handle_value: HandleValue) -> ZxResult<Arc<T>> {
let handle = self.remove_handle(handle_value)?;
let object = handle
.object
.downcast_arc::<T>()
.map_err(|_| ZxError::WRONG_TYPE)?;
Ok(object)
}
pub fn start(&self) -> () {
// unimplemented!()
}
/// Exit current process with `retcode`.
/// The process do not terminate immediately when exited.
/// It will terminate after all its child threads are terminated.
pub fn exit(&self, retcode: i64) {
let mut inner = self.inner.lock();
if let Status::Exited(_) = inner.status {
return;
}
inner.status = Status::Exited(retcode);
inner.handles.clear();
}
/// The process finally terminates.
fn terminate(&self) {
// unimplemented!()
}
/// Check whether `condition` is allowed in the parent job's policy.
pub fn check_policy(&self, condition: PolicyCondition) -> ZxResult {
match self
.policy
.get_action(condition)
.unwrap_or(PolicyAction::Allow)
{
PolicyAction::Allow => Ok(()),
PolicyAction::Deny => Err(ZxError::ACCESS_DENIED),
_ => unimplemented!(),
}
}
/// Get process status.
pub fn status(&self) -> Status {
self.inner.lock().status
}
/// Get the `VmAddressRegion` of the process.
pub fn vmar(&self) -> Arc<VmAddressRegion> {
self.vmar.clone()
}
/// Get the job of the process.
pub fn job(&self) -> Arc<Job> {
self.job.clone()
}
/// Add a thread to the process.
pub(super) fn add_thread(&self, thread: Arc<Thread>) -> ZxResult {
let mut inner = self.inner.lock();
if let Status::Exited(_) = inner.status {
return Err(ZxError::BAD_STATE);
}
inner.threads.push(thread);
Ok(())
}
/// Remove a thread from the process.
///
/// If no more threads left, exit the process.
pub(super) fn remove_thread(&self, tid: KoID) {
let mut inner = self.inner.lock();
inner.threads.retain(|t| t.id() != tid);
if inner.threads.is_empty() {
drop(inner);
self.terminate();
}
}
/// Get KoIDs of Threads.
pub fn thread_ids(&self) -> Vec<KoID> {
self.inner.lock().threads.iter().map(|t| t.id()).collect()
}
/// Get information of this process.
pub fn get_info(&self) -> ProcessInfo {
let mut info = ProcessInfo {
..Default::default()
};
match self.inner.lock().status {
Status::Init => {
info.started = false;
info.has_exited = false;
}
Status::Running => {
info.started = true;
info.has_exited = false;
}
Status::Exited(ret) => {
info.return_code = ret;
info.has_exited = true;
info.started = true;
}
}
info
}
}
/// Information of a process.
#[allow(missing_docs)]
#[repr(C)]
#[derive(Default)]
pub struct ProcessInfo {
pub return_code: i64,
pub started: bool,
pub has_exited: bool,
}
impl Task for Process {
fn kill(&self) {
self.exit(TASK_RETCODE_SYSCALL_KILL);
}
fn suspend(&self) {
// unimplemented!()
}
fn resume(&self) {
// unimplemented!()
}
}
impl ProcessInner {
/// Add a handle to the process
fn add_handle(&mut self, handle: Handle) -> HandleValue {
let key = (self.max_handle_id << 2) | 0x3u32;
self.max_handle_id += 1;
self.handles.insert(key, handle);
key
}
fn remove_handle(&mut self, handle_value: HandleValue) -> ZxResult<Handle> {
let handle = self
.handles
.remove(&handle_value)
.ok_or(ZxError::BAD_HANDLE)?;
Ok(handle)
}
fn get_handle(&mut self, handle_value: HandleValue) -> ZxResult<Handle> {
let handle = self.handles.get(&handle_value).ok_or(ZxError::BAD_HANDLE)?;
Ok(handle.clone())
}
/// Whether `thread` is in this process.
fn contains_thread(&self, thread: &Arc<Thread>) -> bool {
self.threads.iter().any(|t| Arc::ptr_eq(t, thread))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn create() {
let root_job = Job::root();
let proc = Process::create(&root_job, "proc").expect("failed to create process");
assert_eq!(proc.related_koid(), root_job.id());
assert!(Arc::ptr_eq(&root_job, &proc.job()));
}
#[test]
fn handle() {
let root_job = Job::root();
let proc = Process::create(&root_job, "proc").expect("failed to create process");
let handle = Handle::new(proc.clone(), Rights::DEFAULT_PROCESS);
let handle_value = proc.add_handle(handle);
// getting object should success
let object: Arc<Process> = proc
.get_object_with_rights(handle_value, Rights::DEFAULT_PROCESS)
.expect("failed to get object");
assert!(Arc::ptr_eq(&object, &proc));
let (object, rights) = proc
.get_object_and_rights::<Process>(handle_value)
.expect("failed to get object");
assert!(Arc::ptr_eq(&object, &proc));
assert_eq!(rights, Rights::DEFAULT_PROCESS);
// getting object with an extra rights should fail.
assert_eq!(
proc.get_object_with_rights::<Process>(handle_value, Rights::MANAGE_JOB)
.err(),
Some(ZxError::ACCESS_DENIED)
);
// getting object with invalid type should fail.
assert_eq!(
proc.get_object_with_rights::<Job>(handle_value, Rights::DEFAULT_PROCESS)
.err(),
Some(ZxError::WRONG_TYPE)
);
proc.remove_handle(handle_value).unwrap();
// getting object with invalid handle should fail.
assert_eq!(
proc.get_object_with_rights::<Process>(handle_value, Rights::DEFAULT_PROCESS)
.err(),
Some(ZxError::BAD_HANDLE)
);
let handle1 = Handle::new(proc.clone(), Rights::DEFAULT_PROCESS);
let handle2 = Handle::new(proc.clone(), Rights::DEFAULT_PROCESS);
let handle_values = proc.add_handles(vec![handle1, handle2]);
let object1: Arc<Process> = proc
.get_object_with_rights(handle_values[0], Rights::DEFAULT_PROCESS)
.expect("failed to get object");
assert!(Arc::ptr_eq(&object1, &proc));
proc.remove_handles(&handle_values).unwrap();
assert_eq!(
proc.get_object_with_rights::<Process>(handle_values[0], Rights::DEFAULT_PROCESS)
.err(),
Some(ZxError::BAD_HANDLE)
);
}
#[test]
fn get_child() {
let root_job = Job::root();
let proc = Process::create(&root_job, "proc").expect("failed to create process");
let thread = Thread::create(&proc, "thread").expect("failed to create thread");
assert_eq!(proc.get_child(thread.id()).unwrap().id(), thread.id());
assert_eq!(proc.get_child(proc.id()).err(), Some(ZxError::NOT_FOUND));
let thread1 = Thread::create(&proc, "thread1").expect("failed to create thread");
assert_eq!(proc.thread_ids(), vec![thread.id(), thread1.id()]);
}
#[test]
fn contains_thread() {
let root_job = Job::root();
let proc = Process::create(&root_job, "proc").expect("failed to create process");
let thread = Thread::create(&proc, "thread").expect("failed to create thread");
let proc1 = Process::create(&root_job, "proc1").expect("failed to create process");
let thread1 = Thread::create(&proc1, "thread1").expect("failed to create thread");
let inner = proc.inner.lock();
assert!(inner.contains_thread(&thread) && !inner.contains_thread(&thread1));
}
#[test]
fn check_policy() {
let root_job = Job::root();
let policy1 = BasicPolicy {
condition: PolicyCondition::BadHandle,
action: PolicyAction::Allow,
};
let policy2 = BasicPolicy {
condition: PolicyCondition::NewChannel,
action: PolicyAction::Deny,
};
assert!(root_job
.set_policy_basic(SetPolicyOptions::Absolute, &[policy1, policy2])
.is_ok());
let proc = Process::create(&root_job, "proc").expect("failed to create process");
assert!(proc.check_policy(PolicyCondition::BadHandle).is_ok());
assert!(proc.check_policy(PolicyCondition::NewProcess).is_ok());
assert_eq!(
proc.check_policy(PolicyCondition::NewChannel).err(),
Some(ZxError::ACCESS_DENIED)
);
let _job = root_job.create_child().unwrap();
assert_eq!(
root_job
.set_policy_basic(SetPolicyOptions::Absolute, &[policy1, policy2])
.err(),
Some(ZxError::BAD_STATE)
);
}
#[test]
fn exit() {
let root_job = Job::root();
let proc = Process::create(&root_job, "proc").expect("failed to create process");
let info = proc.get_info();
assert!(!info.has_exited && !info.started && info.return_code == 0);
proc.exit(666);
let info = proc.get_info();
assert!(info.has_exited && info.started && info.return_code == 666);
assert_eq!(
Thread::create(&proc, "thread1").err(),
Some(ZxError::BAD_STATE)
);
}
}

@ -0,0 +1,24 @@
use {super::process::Process, super::*, crate::object::*, alloc::sync::Arc};
pub struct Thread {
base: KObjectBase,
proc: Arc<Process>,
}
impl_kobject!(Thread
fn related_koid(&self) -> KoID {
self.proc.id()
}
);
impl Thread {
/// Create a new thread.
pub fn create(proc: &Arc<Process>, name: &str) -> ZxResult<Arc<Self>> {
let thread = Arc::new(Thread {
base: KObjectBase::with_name(name),
proc: proc.clone(),
});
proc.add_thread(thread.clone())?;
Ok(thread)
}
}

@ -0,0 +1,6 @@
//! Objects for Virtual Memory Management.
use super::*;
mod vmar;
pub use self::vmar::*;

@ -0,0 +1,17 @@
use {super::*, crate::object::*, alloc::sync::Arc};
/// Virtual Memory Address Regions
pub struct VmAddressRegion {
base: KObjectBase,
}
impl_kobject!(VmAddressRegion);
impl VmAddressRegion {
/// Create a new root VMAR.
pub fn new_root() -> Arc<Self> {
Arc::new(VmAddressRegion {
base: KObjectBase::new(),
})
}
}
Loading…
Cancel
Save