Skip to content

Commit

Permalink
capsules: add process_info capsule
Browse files Browse the repository at this point in the history
This allows userspace to list which processes are active.
  • Loading branch information
bradjc committed Feb 27, 2025
1 parent 22ab469 commit d9e74d0
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 0 deletions.
21 changes: 21 additions & 0 deletions boards/tutorials/nrf52840dk-thread-tutorial/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,18 @@ const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
type Ieee802154RawDriver =
components::ieee802154::Ieee802154RawComponentType<nrf52840::ieee802154_radio::Radio<'static>>;

/// Needed for process info capsule.
pub struct PMCapability;
unsafe impl capabilities::ProcessManagementCapability for PMCapability {}

struct Platform {
base: nrf52840dk_lib::Platform,
ieee802154: &'static Ieee802154RawDriver,
eui64: &'static nrf52840dk_lib::Eui64Driver,
screen: &'static ScreenDriver,
nonvolatile_storage:
&'static capsules_extra::nonvolatile_storage_driver::NonvolatileStorage<'static>,
process_info: &'static capsules_extra::process_info_driver::ProcessInfo<PMCapability>,
}

impl SyscallDriverLookup for Platform {
Expand All @@ -47,6 +52,7 @@ impl SyscallDriverLookup for Platform {
capsules_extra::eui64::DRIVER_NUM => f(Some(self.eui64)),
capsules_extra::ieee802154::DRIVER_NUM => f(Some(self.ieee802154)),
capsules_extra::screen::DRIVER_NUM => f(Some(self.screen)),
capsules_extra::process_info_driver::DRIVER_NUM => f(Some(self.process_info)),
capsules_extra::nonvolatile_storage_driver::DRIVER_NUM => {
f(Some(self.nonvolatile_storage))
}
Expand Down Expand Up @@ -179,6 +185,20 @@ pub unsafe fn main() {
nrf52840::nvmc::Nvmc
));

//--------------------------------------------------------------------------
// PROCESS INFO FOR USERSPACE
//--------------------------------------------------------------------------

let grant_cap = create_capability!(capabilities::MemoryAllocationCapability);
let process_info = kernel::static_init!(
capsules_extra::process_info_driver::ProcessInfo<PMCapability>,
capsules_extra::process_info_driver::ProcessInfo::new(
board_kernel,
board_kernel.create_grant(capsules_extra::process_info_driver::DRIVER_NUM, &grant_cap),
PMCapability
)
);

//--------------------------------------------------------------------------
// PLATFORM SETUP, SCHEDULER, AND START KERNEL LOOP
//--------------------------------------------------------------------------
Expand All @@ -189,6 +209,7 @@ pub unsafe fn main() {
ieee802154,
screen,
nonvolatile_storage,
process_info,
};

// These symbols are defined in the linker script.
Expand Down
1 change: 1 addition & 0 deletions capsules/core/src/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pub enum NUM {

// Kernel
Ipc = 0x10000,
ProcessInfo = 0x10002,

// HW Buses
Spi = 0x20001,
Expand Down
1 change: 1 addition & 0 deletions capsules/extra/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ pub mod nrf51822_serialization;
pub mod panic_button;
pub mod pca9544a;
pub mod pressure;
pub mod process_info_driver;
pub mod proximity;
pub mod public_key_crypto;
pub mod pwm;
Expand Down
138 changes: 138 additions & 0 deletions capsules/extra/src/process_info_driver.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
// Licensed under the Apache License, Version 2.0 or the MIT License.
// SPDX-License-Identifier: Apache-2.0 OR MIT
// Copyright Tock Contributors 2025.

//! Allow userspace to inspect the list of processes on the board.
use kernel::capabilities::ProcessManagementCapability;
use kernel::grant::{AllowRoCount, AllowRwCount, Grant, UpcallCount};
use kernel::processbuffer::WriteableProcessBuffer;
use kernel::syscall::{CommandReturn, SyscallDriver};
use kernel::Kernel;
use kernel::{ErrorCode, ProcessId};

/// Syscall driver number.
use capsules_core::driver;
pub const DRIVER_NUM: usize = driver::NUM::ProcessInfo as usize;

mod rw_allow {
pub const INFO: usize = 0;
/// The number of allow buffers the kernel stores for this grant
pub const COUNT: u8 = 1;
}

pub struct ProcessInfo<C: ProcessManagementCapability> {
apps: Grant<(), UpcallCount<0>, AllowRoCount<0>, AllowRwCount<{ rw_allow::COUNT }>>,

/// Reference to the kernel object so we can access process state.
kernel: &'static Kernel,

capability: C,
}

impl<C: ProcessManagementCapability> ProcessInfo<C> {
pub fn new(
kernel: &'static Kernel,
grant: Grant<(), UpcallCount<0>, AllowRoCount<0>, AllowRwCount<{ rw_allow::COUNT }>>,
capability: C,
) -> Self {
Self {
kernel,
apps: grant,
capability,
}
}

fn iterate_u32<F>(&self, process_id: ProcessId, func: F) -> u32
where
F: Fn(&dyn kernel::process::Process) -> u32,
{
let mut count = 0;
let _ = self.apps.enter(process_id, |_app, kernel_data| {
let _ = kernel_data
.get_readwrite_processbuffer(rw_allow::INFO)
.and_then(|shared| {
shared.mut_enter(|s| {
let mut chunks = s.chunks(size_of::<u32>());

self.kernel
.process_each_capability(&self.capability, |process| {
// Get the next chunk to write the next
// PID into.
if let Some(chunk) = chunks.nth(0) {
let _ =
chunk.copy_from_slice_or_err(&func(process).to_le_bytes());
}
count += 1;
});
})
});
});
count as u32
}
}

impl<C: ProcessManagementCapability> SyscallDriver for ProcessInfo<C> {
fn command(
&self,
command_num: usize,
data1: usize,
_data2: usize,
process_id: ProcessId,
) -> CommandReturn {
match command_num {
// Driver existence check
0 => CommandReturn::success(),

1 => {
let mut count = 0;

self.kernel
.process_each_capability(&self.capability, |_process| {
count += 1;
});

CommandReturn::success_u32(count)
}

2 => {
let count = self.iterate_u32(process_id, |process| process.processid().id() as u32);
CommandReturn::success_u32(count)
}

3 => {
let count = self.iterate_u32(process_id, |process| match process.short_app_id() {
kernel::process::ShortId::LocallyUnique => 0,
kernel::process::ShortId::Fixed(id) => id.into(),
});
CommandReturn::success_u32(count)
}

4 => {
let _ = self.apps.enter(process_id, |_app, kernel_data| {
let _ = kernel_data
.get_readwrite_processbuffer(rw_allow::INFO)
.and_then(|shared| {
shared.mut_enter(|s| {
self.kernel
.process_each_capability(&self.capability, |process| {
if process.processid().id() == data1 {
let n = process.get_process_name().as_bytes();
let _ = s[0..n.len()].copy_from_slice_or_err(n);
s[n.len()].set(0);
}
});
})
});
});
CommandReturn::success()
}

_ => CommandReturn::failure(ErrorCode::NOSUPPORT),
}
}

fn allocate_grant(&self, processid: ProcessId) -> Result<(), kernel::process::Error> {
self.apps.enter(processid, |_, _| {})
}
}

0 comments on commit d9e74d0

Please sign in to comment.