Skip to content

Commit

Permalink
Initialize documentation for cap
Browse files Browse the repository at this point in the history
  • Loading branch information
sorpaas committed Jan 6, 2017
1 parent fa09d3b commit 303a081
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 0 deletions.
3 changes: 3 additions & 0 deletions abi/src/lib.rs
Expand Up @@ -2,7 +2,9 @@
#![feature(asm)]
#![no_std]

/// A trait that allows setting a struct back to its default value.
pub trait SetDefault {
/// Set this struct back to its default value.
fn set_default(&mut self);
}

Expand Down Expand Up @@ -59,6 +61,7 @@ pub enum SystemCall {
},
}

/// Represents a task buffer used for system calls.
#[derive(Debug)]
pub struct TaskBuffer {
pub call: Option<SystemCall>
Expand Down
10 changes: 10 additions & 0 deletions kernel/src/cap/channel.rs
Expand Up @@ -5,14 +5,21 @@ use util::managed_arc::{ManagedArc, ManagedArcAny, ManagedWeakPool3Arc};

use super::{UntypedDescriptor};

/// Channel descriptor.
#[derive(Debug)]
pub struct ChannelDescriptor {
value: Option<u64>,
next: Option<ManagedArcAny>,
}
/// Channel capability. Reference-counted smart pointer to channel
/// descriptor.
///
/// Channels are used for inter-process communication of different
/// tasks.
pub type ChannelCap = ManagedArc<RwLock<ChannelDescriptor>>;

impl ChannelCap {
/// Create a channel capability from an untyped capability.
pub fn retype_from(untyped: &mut UntypedDescriptor) -> Self {
let mut arc: Option<Self> = None;

Expand All @@ -32,10 +39,13 @@ impl ChannelCap {
}

impl ChannelDescriptor {
/// Put a value to the channel.
pub fn put(&mut self, value: u64) {
self.value = Some(value);
}

/// Take a value from the channel. If there's no value in the
/// channel, `None` is returned.
pub fn take(&mut self) -> Option<u64> {
self.value.take()
}
Expand Down
18 changes: 18 additions & 0 deletions kernel/src/cap/cpool.rs
Expand Up @@ -6,39 +6,57 @@ use util::managed_arc::{ManagedArc, ManagedArcAny, ManagedWeakPool256Arc};

use super::{UntypedDescriptor};

/// Capability pool descriptor.
#[derive(Debug)]
pub struct CPoolDescriptor {
weak_pool: ManagedWeakPool256Arc,
next: Option<ManagedArcAny>,
}
/// Capability pool capability. Reference-counted smart pointer to
/// capability pool descriptor. Capability pool itself is a
/// `ManagedWeakPool` with 256 entries.
///
/// Capability pool capability is used to hold multiple capabilities
/// together so as to be addressable in user-space programs.
pub type CPoolCap = ManagedArc<RwLock<CPoolDescriptor>>;

impl CPoolDescriptor {
/// Create a new pointer to a capability descriptor using the
/// index. If nothing is in the entry, `None` is returned.
pub fn upgrade_any(&self, index: usize) -> Option<ManagedArcAny> {
unsafe { self.weak_pool.read().upgrade_any(index, |ptr, type_id| { super::upgrade_any(ptr, type_id) }) }
}

/// Like `upgrade_any`, but returns a value with the specified
/// type.
pub fn upgrade<T: Any>(&self, index: usize) -> Option<ManagedArc<T>>
where ManagedArc<T>: Any {
self.weak_pool.read().upgrade(index)
}

/// Downgrade a capability into the capability pool (weak pool) at
/// a specified index.
pub fn downgrade_at<T: Any>(&self, arc: &ManagedArc<T>, index: usize)
where ManagedArc<T>: Any {
self.weak_pool.read().downgrade_at(arc, index)
}

/// Downgrade a capability into the capability pool (weak pool) at
/// a free index.
pub fn downgrade_free<T: Any>(&self, arc: &ManagedArc<T>) -> Option<usize>
where ManagedArc<T>: Any {
self.weak_pool.read().downgrade_free(arc)
}

/// Size of the capability pool.
pub fn size(&self) -> usize {
256
}
}

impl CPoolCap {
/// Create a capability pool capability from an untyped
/// capability.
pub fn retype_from(untyped: &mut UntypedDescriptor) -> Self {
let mut arc: Option<Self> = None;

Expand Down
20 changes: 20 additions & 0 deletions kernel/src/cap/mod.rs
@@ -1,6 +1,10 @@
/// Untyped capability implementation.
mod untyped;
/// Capability pool capability implementation.
mod cpool;
/// Task capability implementation.
mod task;
/// Channel capability implementation.
mod channel;

pub use self::untyped::{UntypedDescriptor, UntypedCap};
Expand All @@ -15,8 +19,11 @@ use core::any::{TypeId};
use util::managed_arc::{ManagedWeakPool256Arc, ManagedArcAny, ManagedArc};

pub use abi::{SetDefault, TaskBuffer};
/// Raw page struct representing a whole page.
pub struct RawPage(pub [u8; PAGE_LENGTH]);
/// Raw page capability. Represents a page with no other information.
pub type RawPageCap = PageCap<RawPage>;
/// Task buffer page capability. Represents a page of task buffer.
pub type TaskBufferPageCap = PageCap<TaskBuffer>;

impl SetDefault for RawPage {
Expand All @@ -27,6 +34,16 @@ impl SetDefault for RawPage {
}
}

/// Create a managed Arc (capability) from an address of an kernel
/// object (architecture-specific or general). The `type_id` should be
/// a [TypeId](https://doc.rust-lang.org/std/any/struct.TypeId.html)
/// of a capability. If the `type_id` is not recognized, `None` is
/// returned.
///
/// # Safety
///
/// `ptr` must be a physical address pointing to a valid kernel object
/// of type `type_id`.
pub unsafe fn upgrade_any(ptr: PAddr, type_id: TypeId) -> Option<ManagedArcAny> {
if type_id == TypeId::of::<CPoolCap>() {
Some(unsafe { ManagedArc::from_ptr(ptr): CPoolCap }.into())
Expand All @@ -45,6 +62,9 @@ pub unsafe fn upgrade_any(ptr: PAddr, type_id: TypeId) -> Option<ManagedArcAny>
}
}

/// Drop an architecture-specific `any` capability. `ManagedArcAny` is
/// not itself droppable. It must be converted to its real type before
/// dropping.
pub fn drop_any(any: ManagedArcAny) {
if any.is::<CPoolCap>() {
any.into(): CPoolCap;
Expand Down
28 changes: 28 additions & 0 deletions kernel/src/cap/task.rs
Expand Up @@ -7,6 +7,9 @@ use arch::{TaskRuntime, Exception};

use super::{UntypedDescriptor, TopPageTableCap, CPoolCap, TaskBufferPageCap, ChannelCap};

/// Switch to an idle task that runs in kernel-mode. This is used when
/// no other tasks is runnable. Like normal context switching, this
/// returns only when exceptions (interrupts) happen.
pub fn idle() -> Exception {
#[naked]
unsafe fn idle_task() -> ! {
Expand All @@ -22,13 +25,15 @@ pub fn idle() -> Exception {
}
}

/// Represent a task status.
#[derive(Debug, Clone)]
pub enum TaskStatus {
Active,
ChannelWait(ChannelCap),
Inactive,
}

/// Task descriptor.
#[derive(Debug)]
pub struct TaskDescriptor {
weak_pool: ManagedWeakPool3Arc,
Expand All @@ -37,9 +42,14 @@ pub struct TaskDescriptor {
next_task: Option<TaskCap>,
status: TaskStatus
}
/// Task capability. Reference-counted smart pointer to task
/// descriptor.
///
/// Tasks represents isolated processes running.
pub type TaskCap = ManagedArc<RwLock<TaskDescriptor>>;

impl TaskCap {
/// Create a task capability from an untyped capability.
pub fn retype_from(untyped: &mut UntypedDescriptor) -> Self {
let mut arc: Option<Self> = None;

Expand Down Expand Up @@ -68,46 +78,58 @@ impl TaskCap {
}

impl TaskDescriptor {
/// Set the task's instruction pointer.
pub fn set_instruction_pointer(&mut self, instruction_pointer: VAddr) {
self.runtime.set_instruction_pointer(instruction_pointer)
}

/// Set the task's stack pointer.
pub fn set_stack_pointer(&mut self, stack_pointer: VAddr) {
self.runtime.set_stack_pointer(stack_pointer)
}

/// Set the task's root capability pool.
pub fn downgrade_cpool(&self, cpool: &CPoolCap) {
self.weak_pool.read().downgrade_at(cpool, 0)
}

/// Read from the task's root capability pool.
pub fn upgrade_cpool(&self) -> Option<CPoolCap> {
self.weak_pool.read().upgrade(0)
}

/// Set the task's top page table.
pub fn downgrade_top_page_table(&self, pml4: &TopPageTableCap) {
self.weak_pool.read().downgrade_at(pml4, 1)
}

/// Read from the task's top page table.
pub fn upgrade_top_page_table(&self) -> Option<TopPageTableCap> {
self.weak_pool.read().upgrade(1)
}

/// Set the task's buffer.
pub fn downgrade_buffer(&self, buffer: &TaskBufferPageCap) {
self.weak_pool.read().downgrade_at(buffer, 2)
}

/// Read from the task's buffer.
pub fn upgrade_buffer(&self) -> Option<TaskBufferPageCap> {
self.weak_pool.read().upgrade(2)
}

/// Current task status.
pub fn status(&self) -> TaskStatus {
self.status.clone()
}

/// Set the current task status.
pub fn set_status(&mut self, status: TaskStatus) {
self.status = status;
}

/// Switch to the task. The function is returned when exception
/// happens.
pub fn switch_to(&mut self) -> Exception {
if let Some(pml4) = self.upgrade_top_page_table() {
pml4.write().switch_to();
Expand All @@ -116,8 +138,12 @@ impl TaskDescriptor {
}
}

/// The first task initialized by the kernel.
static FIRST_TASK: Mutex<Option<TaskCap>> = Mutex::new(None);

/// Register a new task. Using `FIRST_TASK` static, this forms a
/// linked-list that allows an iterator to iterate over all created
/// tasks.
fn register_task(cap: TaskCap) {
let mut first_task = FIRST_TASK.lock();
if first_task.is_none() {
Expand All @@ -132,6 +158,7 @@ fn register_task(cap: TaskCap) {
}
}

/// A task iterator.
pub struct TaskIterator {
next: Option<TaskCap>,
}
Expand All @@ -152,6 +179,7 @@ impl Iterator for TaskIterator {
}
}

/// Return a task iterator using `FIRST_TASK`.
pub fn task_iter() -> TaskIterator {
TaskIterator {
next: FIRST_TASK.lock().clone(),
Expand Down
19 changes: 19 additions & 0 deletions kernel/src/cap/untyped.rs
Expand Up @@ -2,16 +2,28 @@ use common::*;
use util::{RwLock, align_up};
use util::managed_arc::{ManagedArc, ManagedArcAny};

/// Untyped descriptor.
#[derive(Debug)]
pub struct UntypedDescriptor {
start_paddr: PAddr,
length: usize,
watermark: PAddr,
first_child: Option<ManagedArcAny>
}
/// Untyped capability. Reference-counted smart pointer to untyped
/// descriptor.
///
/// Untyped capability represents free memory that can be retyped to
/// different useful capabilities.
pub type UntypedCap = ManagedArc<RwLock<UntypedDescriptor>>;

impl UntypedCap {
/// Bootstrap an untyped capability using a memory region information.
///
/// # Safety
///
/// Can only be used for free memory regions returned from
/// `InitInfo`.
pub unsafe fn bootstrap(start_paddr: PAddr, length: usize) -> Self {
let des_paddr = align_up(start_paddr, UntypedCap::inner_alignment());
assert!(des_paddr + UntypedCap::inner_length() <= start_paddr + length);
Expand All @@ -28,14 +40,19 @@ impl UntypedCap {
}

impl UntypedDescriptor {
/// Length of the untyped region.
pub fn length(&self) -> usize {
self.length
}

/// Start physical address of the untyped region.
pub fn start_paddr(&self) -> PAddr {
self.start_paddr
}

/// Allocate a memory region using the given length and
/// alignment. Shift the watermark of the current descriptor
/// passing over the allocated region.
pub unsafe fn allocate(&mut self, length: usize, alignment: usize) -> PAddr {
let paddr = align_up(self.watermark, alignment);
assert!(paddr + length <= self.start_paddr + self.length);
Expand All @@ -44,6 +61,8 @@ impl UntypedDescriptor {
paddr
}

/// Derive and allocate a memory region to a capability that
/// requires memory region.
pub unsafe fn derive<F>(&mut self, length: usize, alignment: usize, f: F) where F: FnOnce(PAddr, Option<ManagedArcAny>) -> ManagedArcAny {
let paddr = self.allocate(length, alignment);
self.first_child = Some(f(paddr, self.first_child.take()));
Expand Down

0 comments on commit 303a081

Please sign in to comment.