Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion kernel/src/grant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1039,7 +1039,10 @@ impl<'a, T: Default, Upcalls: UpcallSize, AllowROs: AllowRoSize, AllowRWs: Allow
);

// Allocate grant, the memory is still uninitialized though.
if !process.allocate_grant(grant_num, driver_num, alloc_size, alloc_align) {
if process
.allocate_grant(grant_num, driver_num, alloc_size, alloc_align)
.is_err()
{
return Err(Error::OutOfMemory);
}

Expand Down
25 changes: 18 additions & 7 deletions kernel/src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use core::fmt;
use core::fmt::Write;
use core::num::NonZeroU32;
use core::ptr::NonNull;
use core::str;

Expand Down Expand Up @@ -272,6 +273,17 @@ pub enum StoppedExecutingReason {
KernelPreemption,
}

/// The version of a binary.
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
pub struct BinaryVersion(NonZeroU32);

impl BinaryVersion {
/// Creates a new binary version.
pub fn new(value: NonZeroU32) -> Self {
Self(value)
}
}

/// This trait represents a generic process that the Tock scheduler can
/// schedule.
pub trait Process {
Expand All @@ -283,9 +295,8 @@ pub trait Process {
fn short_app_id(&self) -> ShortID;

/// Returns the version number of the binary in this process, as specified
/// in a TBF Program Header; if the Userspace Binary only has a TBF Main
/// Header, returns 0.
fn binary_version(&self) -> u32;
/// in a TBF Program Header; if the binary has no version assigned, return [None]
fn binary_version(&self) -> Option<BinaryVersion>;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously, 0 marked the absence of the binary version. This approach works, but Option is the Rust way of doing this in my opinion.

Using a u32 for the binary version is too powerful: several operations defined on the integer type don't make sense, like addition or division. Or do they?

In the end, NonZeroU32 has been chosen as the underlying type of the new BinaryVersion type. This allows code generation optimizations. In my tests, the new version compiles exactly the same to the old code.


/// Queue a `Task` for the process. This will be added to a per-process
/// buffer and executed by the scheduler. `Task`s are some function the app
Expand Down Expand Up @@ -601,7 +612,7 @@ pub trait Process {
/// app_brk, as MPU alignment and size constraints may result in the MPU
/// enforced region differing from the app_brk.
///
/// This will return `false` and fail if:
/// This will return `Err(())` and fail if:
/// - The process is inactive, or
/// - There is not enough available memory to do the allocation, or
/// - The grant_num is invalid, or
Expand All @@ -612,7 +623,7 @@ pub trait Process {
driver_num: usize,
size: usize,
align: usize,
) -> bool;
) -> Result<(), ()>;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Result is the Rust way of signaling a function may fail. Additionally, Result triggers a warning when the return value is unused. From my little experiments, the new signature is compiled to the same code as the old one.


/// Check if a given grant for this process has been allocated.
///
Expand All @@ -625,14 +636,14 @@ pub trait Process {
/// are not recorded in the grant pointer array, but are useful for capsules
/// which need additional process-specific dynamically allocated memory.
///
/// If successful, return a Some() with an identifier that can be used with
/// If successful, return a Ok() with an identifier that can be used with
/// `enter_custom_grant()` to get access to the memory and the pointer to
/// the memory which must be used to initialize the memory.
fn allocate_custom_grant(
&self,
size: usize,
align: usize,
) -> Option<(ProcessCustomGrantIdentifier, NonNull<u8>)>;
) -> Result<(ProcessCustomGrantIdentifier, NonNull<u8>), ()>;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This follows the pattern of returning a Result as allocate_grant.


/// Enter the grant based on `grant_num` for this process.
///
Expand Down
39 changes: 24 additions & 15 deletions kernel/src/process_standard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use core::cell::Cell;
use core::cmp;
use core::fmt::Write;
use core::num::NonZeroU32;
use core::ptr::NonNull;
use core::{mem, ptr, slice, str};

Expand All @@ -22,6 +23,7 @@ use crate::errorcode::ErrorCode;
use crate::kernel::Kernel;
use crate::platform::chip::Chip;
use crate::platform::mpu::{self, MPU};
use crate::process::BinaryVersion;
use crate::process::{Error, FunctionCall, FunctionCallSource, Process, State, Task};
use crate::process::{FaultAction, ProcessCustomGrantIdentifier, ProcessId};
use crate::process::{ProcessAddresses, ProcessSizes, ShortID};
Expand Down Expand Up @@ -246,8 +248,15 @@ impl<C: Chip> Process for ProcessStandard<'_, C> {
self.app_id.get()
}

fn binary_version(&self) -> u32 {
self.header.get_binary_version()
fn binary_version(&self) -> Option<BinaryVersion> {
match self.header.get_binary_version() {
0 => None,
// Safety: because of the previous arm, version != 0, so the call to
// NonZeroU32::new_unchecked() is safe
version => Some(BinaryVersion::new(unsafe {
NonZeroU32::new_unchecked(version)
})),
}
}

fn enqueue_task(&self, task: Task) -> Result<(), ErrorCode> {
Expand Down Expand Up @@ -822,22 +831,22 @@ impl<C: Chip> Process for ProcessStandard<'_, C> {
driver_num: usize,
size: usize,
align: usize,
) -> bool {
) -> Result<(), ()> {
// Do not modify an inactive process.
if !self.is_running() {
return false;
return Err(());
}

// Verify the grant_num is valid.
if grant_num >= self.kernel.get_grant_count_and_finalize() {
return false;
return Err(());
}

// Verify that the grant is not already allocated. If the pointer is not
// null then the grant is already allocated.
if let Some(is_allocated) = self.grant_is_allocated(grant_num) {
if is_allocated {
return false;
return Err(());
}
}

Expand All @@ -854,41 +863,41 @@ impl<C: Chip> Process for ProcessStandard<'_, C> {
// If we find a match, then the `driver_num` must already be used and
// the grant allocation fails.
if exists {
return false;
return Err(());
}

// Use the shared grant allocator function to actually allocate memory.
// Returns `None` if the allocation cannot be created.
if let Some(grant_ptr) = self.allocate_in_grant_region_internal(size, align) {
// Update the grant pointer to the address of the new allocation.
self.grant_pointers.map_or(false, |grant_pointers| {
self.grant_pointers.map_or(Err(()), |grant_pointers| {
// Implement `grant_pointers[grant_num] = grant_ptr` without a
// chance of a panic.
grant_pointers
.get_mut(grant_num)
.map_or(false, |grant_entry| {
.map_or(Err(()), |grant_entry| {
// Actually set the driver num and grant pointer.
grant_entry.driver_num = driver_num;
grant_entry.grant_ptr = grant_ptr.as_ptr();

// If all of this worked, return true.
true
Ok(())
})
})
} else {
// Could not allocate the memory for the grant region.
false
Err(())
}
}

fn allocate_custom_grant(
&self,
size: usize,
align: usize,
) -> Option<(ProcessCustomGrantIdentifier, NonNull<u8>)> {
) -> Result<(ProcessCustomGrantIdentifier, NonNull<u8>), ()> {
// Do not modify an inactive process.
if !self.is_running() {
return None;
return Err(());
}

// Use the shared grant allocator function to actually allocate memory.
Expand All @@ -898,10 +907,10 @@ impl<C: Chip> Process for ProcessStandard<'_, C> {
// this custom grant in the future.
let identifier = self.create_custom_grant_identifier(ptr);

Some((identifier, ptr))
Ok((identifier, ptr))
} else {
// Could not allocate memory for the custom grant.
None
Err(())
}
}

Expand Down