pub trait Process {
Show 60 methods
// Required methods
fn processid(&self) -> ProcessId;
fn short_app_id(&self) -> ShortId;
fn binary_version(&self) -> Option<BinaryVersion>;
fn get_credential(&self) -> Option<AcceptedCredential>;
fn get_restart_count(&self) -> usize;
fn get_process_name(&self) -> &'static str;
fn has_tasks(&self) -> bool;
fn pending_tasks(&self) -> usize;
fn enqueue_task(&self, task: Task) -> Result<(), ErrorCode>;
fn dequeue_task(&self) -> Option<Task>;
fn remove_upcall(&self, upcall_id: UpcallId) -> Option<Task>;
fn remove_pending_upcalls(&self, upcall_id: UpcallId) -> usize;
fn get_state(&self) -> State;
fn ready(&self) -> bool;
fn is_running(&self) -> bool;
fn set_yielded_state(&self);
fn set_yielded_for_state(&self, upcall_id: UpcallId);
fn stop(&self);
fn resume(&self);
fn set_fault_state(&self);
fn start(&self, cap: &dyn ProcessStartCapability);
fn try_restart(&self, completion_code: Option<u32>);
fn terminate(&self, completion_code: Option<u32>);
fn get_completion_code(&self) -> Option<Option<u32>>;
fn brk(&self, new_break: *const u8) -> Result<CapabilityPtr, Error>;
fn sbrk(&self, increment: isize) -> Result<CapabilityPtr, Error>;
fn number_writeable_flash_regions(&self) -> usize;
fn get_writeable_flash_region(&self, region_index: usize) -> (usize, usize);
fn update_stack_start_pointer(&self, stack_pointer: *const u8);
fn update_heap_start_pointer(&self, heap_pointer: *const u8);
fn build_readwrite_process_buffer(
&self,
buf_start_addr: *mut u8,
size: usize,
) -> Result<ReadWriteProcessBuffer, ErrorCode>;
fn build_readonly_process_buffer(
&self,
buf_start_addr: *const u8,
size: usize,
) -> Result<ReadOnlyProcessBuffer, ErrorCode>;
unsafe fn set_byte(&self, addr: *mut u8, value: u8) -> bool;
fn get_command_permissions(
&self,
driver_num: usize,
offset: usize,
) -> CommandPermissions;
fn get_storage_permissions(&self) -> StoragePermissions;
fn setup_mpu(&self);
fn add_mpu_region(
&self,
unallocated_memory_start: *const u8,
unallocated_memory_size: usize,
min_region_size: usize,
) -> Option<Region>;
fn remove_mpu_region(&self, region: Region) -> Result<(), ErrorCode>;
fn allocate_grant(
&self,
grant_num: usize,
driver_num: usize,
size: usize,
align: usize,
) -> Result<(), ()>;
fn grant_is_allocated(&self, grant_num: usize) -> Option<bool>;
fn allocate_custom_grant(
&self,
size: usize,
align: usize,
) -> Result<(ProcessCustomGrantIdentifier, NonNull<u8>), ()>;
fn enter_grant(&self, grant_num: usize) -> Result<NonNull<u8>, Error>;
fn enter_custom_grant(
&self,
identifier: ProcessCustomGrantIdentifier,
) -> Result<*mut u8, Error>;
unsafe fn leave_grant(&self, grant_num: usize);
fn grant_allocated_count(&self) -> Option<usize>;
fn lookup_grant_from_driver_num(
&self,
driver_num: usize,
) -> Result<usize, Error>;
fn is_valid_upcall_function_pointer(&self, upcall_fn: *const ()) -> bool;
fn set_syscall_return_value(&self, return_value: SyscallReturn);
fn set_process_function(&self, callback: FunctionCall);
fn switch_to(&self) -> Option<ContextSwitchReason>;
fn get_addresses(&self) -> ProcessAddresses;
fn get_sizes(&self) -> ProcessSizes;
fn get_stored_state(&self, out: &mut [u8]) -> Result<usize, ErrorCode>;
fn print_full_process(&self, writer: &mut dyn Write);
fn debug_syscall_count(&self) -> usize;
fn debug_dropped_upcall_count(&self) -> usize;
fn debug_timeslice_expiration_count(&self) -> usize;
fn debug_timeslice_expired(&self);
fn debug_syscall_called(&self, last_syscall: Syscall);
fn debug_syscall_last(&self) -> Option<Syscall>;
}
Expand description
This trait represents a generic process that the Tock scheduler can schedule.
Required Methods§
Sourcefn short_app_id(&self) -> ShortId
fn short_app_id(&self) -> ShortId
Returns the ShortId
generated by the application binary checker at
loading.
Sourcefn binary_version(&self) -> Option<BinaryVersion>
fn binary_version(&self) -> Option<BinaryVersion>
Returns the version number of the binary in this process, as specified
in a TBF Program Header. If the binary has no version assigned this
returns None
.
Sourcefn get_credential(&self) -> Option<AcceptedCredential>
fn get_credential(&self) -> Option<AcceptedCredential>
Return the credential which the credential checker approved if the
credential checker approved a credential. If the process was allowed to
run without credentials, return None
.
Sourcefn get_restart_count(&self) -> usize
fn get_restart_count(&self) -> usize
Returns how many times this process has been restarted.
Sourcefn get_process_name(&self) -> &'static str
fn get_process_name(&self) -> &'static str
Get the name of the process. Used for IPC.
Sourcefn has_tasks(&self) -> bool
fn has_tasks(&self) -> bool
Return if there are any Tasks (upcalls/IPC requests) enqueued for the process.
Sourcefn pending_tasks(&self) -> usize
fn pending_tasks(&self) -> usize
Returns the number of pending tasks. If 0 then dequeue_task()
will
return None
when called.
Sourcefn enqueue_task(&self, task: Task) -> Result<(), ErrorCode>
fn enqueue_task(&self, task: Task) -> Result<(), ErrorCode>
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
process should run, for example a upcall or an IPC call.
This function returns:
Ok(())
if theTask
was successfully enqueued.- [
Err(ErrorCode::NODEVICE)
] if the process is no longer alive. - [
Err(ErrorCode::NOMEM)
] if the task could not be enqueued because there is insufficient space in the internal task queue.
Other return values must be treated as kernel-internal errors.
Sourcefn dequeue_task(&self) -> Option<Task>
fn dequeue_task(&self) -> Option<Task>
Sourcefn remove_upcall(&self, upcall_id: UpcallId) -> Option<Task>
fn remove_upcall(&self, upcall_id: UpcallId) -> Option<Task>
Sourcefn remove_pending_upcalls(&self, upcall_id: UpcallId) -> usize
fn remove_pending_upcalls(&self, upcall_id: UpcallId) -> usize
Remove all scheduled upcalls with the given upcall_id
from the task
queue.
Returns the number of removed upcalls.
Sourcefn ready(&self) -> bool
fn ready(&self) -> bool
Returns whether this process is ready to execute.
A process is ready if it has work to do or if it was interrupted while executing and can continue to execute.
§Returns
true
if the process is ready and false
otherwise.
Sourcefn is_running(&self) -> bool
fn is_running(&self) -> bool
Returns whether the process is running or not.
A process is considered running if it is active and has active stack frames. A running process can be executed.
A process that is not running cannot be executed. The process may have faulted or it may have completed.
§Returns
true
if the process is running and false
otherwise.
Sourcefn set_yielded_state(&self)
fn set_yielded_state(&self)
Move this process from the running state to the yielded state.
This will fail (i.e. not do anything) if the process was not previously running.
Sourcefn set_yielded_for_state(&self, upcall_id: UpcallId)
fn set_yielded_for_state(&self, upcall_id: UpcallId)
Move this process from the running state to the yielded-for state.
This will fail (i.e. not do anything) if the process was not previously running.
Sourcefn stop(&self)
fn stop(&self)
Move this process from running or yielded state into the stopped state.
This will fail (i.e. not do anything) if the process was not either running or yielded.
Sourcefn resume(&self)
fn resume(&self)
Move this stopped process back into its original state.
This transitions a process from
Stopped
to Running
, Yielded
or
YieldedFor
.
This will fail (i.e. not do anything) if the process was not stopped.
Sourcefn set_fault_state(&self)
fn set_fault_state(&self)
Put this process in the fault state.
The kernel will use the process’s fault policy to decide what action to take in regards to the faulted process.
Sourcefn start(&self, cap: &dyn ProcessStartCapability)
fn start(&self, cap: &dyn ProcessStartCapability)
Start a terminated process. This function can only be called on a terminated process.
The caller MUST verify this process is unique before calling this function. This requires a capability to call to ensure that the caller have verified that this process is unique before trying to start it.
Sourcefn try_restart(&self, completion_code: Option<u32>)
fn try_restart(&self, completion_code: Option<u32>)
Terminates and attempts to restart the process. The process and current application always terminate. The kernel may, based on its own policy, restart the application using the same process, reuse the process for another application, or simply terminate the process and application.
This function can be called when the process is in any state except for
Terminated
. It attempts to reset all process
state and re-initialize it so that it can be reused.
Restarting an application can fail for three general reasons:
-
The process is already terminated. Use
Process::start()
instead. -
The kernel chooses not to restart the application, based on its policy.
-
The kernel decides to restart the application but fails to do so because some state can no long be configured for the process. For example, the syscall state for the process fails to initialize.
After try_restart()
runs, the process will either be queued to run the
same application’s _start
function, terminated, or queued to run a
different application’s _start
function.
As the process will be terminated before being restarted, this function
accepts an optional completion_code
. If the process provided a
completion code (e.g. via the exit syscall), then this should be called
with Some(u32)
. If the kernel is trying to restart the process and the
process did not provide a completion code, then this should be called
with None
.
Sourcefn terminate(&self, completion_code: Option<u32>)
fn terminate(&self, completion_code: Option<u32>)
Stop and clear a process’s state and put it into the
Terminated
state.
This will end the process, but does not reset it such that it could be restarted and run again. This function instead frees grants and any queued tasks for this process, but leaves the debug information about the process and other state intact.
When a process is terminated, an optional completion_code
should be
stored for the process. If the process provided the completion code
(e.g. via the exit syscall), then this function should be called with a
completion code of Some(u32)
. If the kernel is terminating the process
and therefore has no completion code from the process, it should provide
None
.
Sourcefn get_completion_code(&self) -> Option<Option<u32>>
fn get_completion_code(&self) -> Option<Option<u32>>
Get the completion code if the process has previously terminated.
§Returns
If the process has never terminated then there has been no opportunity
for a completion code to be set, and this will return None
.
If the process has previously terminated this will return Some()
. If
the last time the process terminated it did not provide a completion
code (e.g. the process faulted), then this will return Some(None)
. If
the last time the process terminated it did provide a completion code,
this will return Some(Some(completion_code))
.
Sourcefn brk(&self, new_break: *const u8) -> Result<CapabilityPtr, Error>
fn brk(&self, new_break: *const u8) -> Result<CapabilityPtr, Error>
Change the location of the program break to new_break
and reallocate
the MPU region covering program memory.
§Returns
On success, return the previous break address with authority that has RW permissions from the start of process RAM to the new break.
On error, return:
Error::InactiveApp
if the process is not running and adjusting the memory pointers is not valid.Error::OutOfMemory
if the requested break would overlap with the grant region or if the newly requested memory cannot be protected with the MPU.Error::AddressOutOfBounds
if the requested break is beyond the process’s memory region.Error::KernelError
if there was an internal kernel error. This is a bug.
Sourcefn sbrk(&self, increment: isize) -> Result<CapabilityPtr, Error>
fn sbrk(&self, increment: isize) -> Result<CapabilityPtr, Error>
Change the location of the program break by increment
bytes,
reallocate the MPU region covering program memory, and return the
previous break address.
§Returns
On success, return the previous break address with authority that has RW permissions from the start of process RAM to the new break.
On error, return:
Error::InactiveApp
if the process is not running and adjusting the sbrk is not valid.Error::OutOfMemory
if the requested break would overlap with the grant region or if the newly requested memory cannot be protected with the MPU.Error::AddressOutOfBounds
if the requested break is beyond the process’s memory region.Error::KernelError
if there was an internal kernel error. This is a bug.
Sourcefn number_writeable_flash_regions(&self) -> usize
fn number_writeable_flash_regions(&self) -> usize
How many writeable flash regions defined in the TBF header for this process.
§Returns
The number of writeable flash regions defined for this process.
Sourcefn get_writeable_flash_region(&self, region_index: usize) -> (usize, usize)
fn get_writeable_flash_region(&self, region_index: usize) -> (usize, usize)
Get the offset from the beginning of flash and the size of the defined writeable flash region.
§Returns
A tuple containing the a usize
of the offset from the beginning of the
process’s flash region where the writeable region starts and a usize
of
the size of the region in bytes.
Sourcefn update_stack_start_pointer(&self, stack_pointer: *const u8)
fn update_stack_start_pointer(&self, stack_pointer: *const u8)
Debug function to update the kernel on where the stack starts for this process. Processes are not required to call this through the memop system call, but it aids in debugging the process.
Sourcefn update_heap_start_pointer(&self, heap_pointer: *const u8)
fn update_heap_start_pointer(&self, heap_pointer: *const u8)
Debug function to update the kernel on where the process heap starts. Also optional.
Sourcefn build_readwrite_process_buffer(
&self,
buf_start_addr: *mut u8,
size: usize,
) -> Result<ReadWriteProcessBuffer, ErrorCode>
fn build_readwrite_process_buffer( &self, buf_start_addr: *mut u8, size: usize, ) -> Result<ReadWriteProcessBuffer, ErrorCode>
Creates a ReadWriteProcessBuffer
from the given offset and size in
process memory.
§Returns
In case of success, this method returns the created
ReadWriteProcessBuffer
.
In case of an error, an appropriate ErrorCode
is returned:
- If the memory is not contained in the process-accessible memory space
/
buf_start_addr
andsize
are not a valid read-write buffer (any byte in the range is not read/write accessible to the process):ErrorCode::INVAL
. - If the process is not active:
ErrorCode::FAIL
. - For all other errors:
ErrorCode::FAIL
.
Sourcefn build_readonly_process_buffer(
&self,
buf_start_addr: *const u8,
size: usize,
) -> Result<ReadOnlyProcessBuffer, ErrorCode>
fn build_readonly_process_buffer( &self, buf_start_addr: *const u8, size: usize, ) -> Result<ReadOnlyProcessBuffer, ErrorCode>
Creates a ReadOnlyProcessBuffer
from the given offset and size in
process memory.
§Returns
In case of success, this method returns the created
ReadOnlyProcessBuffer
.
In case of an error, an appropriate ErrorCode is returned:
- If the memory is not contained in the process-accessible memory space
/
buf_start_addr
andsize
are not a valid read-only buffer (any byte in the range is not read-accessible to the process):ErrorCode::INVAL
. - If the process is not active:
ErrorCode::FAIL
. - For all other errors:
ErrorCode::FAIL
.
Sourceunsafe fn set_byte(&self, addr: *mut u8, value: u8) -> bool
unsafe fn set_byte(&self, addr: *mut u8, value: u8) -> bool
Set a single byte within the process address space at addr
to value
.
Return true if addr
is within the RAM bounds currently exposed to the
process (thereby writable by the process itself) and the value was set,
false otherwise.
§Safety
This function verifies that the byte to be written is in the process’s accessible memory. However, to avoid undefined behavior the caller needs to ensure that no other references exist to the process’s memory before calling this function.
Sourcefn get_command_permissions(
&self,
driver_num: usize,
offset: usize,
) -> CommandPermissions
fn get_command_permissions( &self, driver_num: usize, offset: usize, ) -> CommandPermissions
Return the permissions for this process for a given driver_num
.
The returned CommandPermissions
will indicate if any permissions for
individual command numbers are specified. If there are permissions set
they are returned as a 64 bit bitmask for sequential command numbers.
The offset indicates the multiple of 64 command numbers to get
permissions for.
Sourcefn get_storage_permissions(&self) -> StoragePermissions
fn get_storage_permissions(&self) -> StoragePermissions
Get the storage permissions for the process.
Returns None
if the process has no storage permissions.
Sourcefn setup_mpu(&self)
fn setup_mpu(&self)
Configure the MPU to use the process’s allocated regions.
It is not valid to call this function when the process is inactive (i.e. the process will not run again).
Sourcefn add_mpu_region(
&self,
unallocated_memory_start: *const u8,
unallocated_memory_size: usize,
min_region_size: usize,
) -> Option<Region>
fn add_mpu_region( &self, unallocated_memory_start: *const u8, unallocated_memory_size: usize, min_region_size: usize, ) -> Option<Region>
Allocate a new MPU region for the process that is at least
min_region_size
bytes and lies within the specified stretch of
unallocated memory.
It is not valid to call this function when the process is inactive (i.e. the process will not run again).
Sourcefn remove_mpu_region(&self, region: Region) -> Result<(), ErrorCode>
fn remove_mpu_region(&self, region: Region) -> Result<(), ErrorCode>
Removes an MPU region from the process that has been previously added
with add_mpu_region
.
It is not valid to call this function when the process is inactive (i.e. the process will not run again).
Sourcefn allocate_grant(
&self,
grant_num: usize,
driver_num: usize,
size: usize,
align: usize,
) -> Result<(), ()>
fn allocate_grant( &self, grant_num: usize, driver_num: usize, size: usize, align: usize, ) -> Result<(), ()>
Allocate memory from the grant region and store the reference in the proper grant pointer index.
This function must check that doing the allocation does not cause the kernel memory break to go below the top of the process accessible memory region allowed by the MPU. Note, this can be different from the actual app_brk, as MPU alignment and size constraints may result in the MPU enforced region differing from the app_brk.
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
- The grant_num already has an allocated grant.
Sourcefn grant_is_allocated(&self, grant_num: usize) -> Option<bool>
fn grant_is_allocated(&self, grant_num: usize) -> Option<bool>
Check if a given grant for this process has been allocated.
Returns None
if the process is not active. Otherwise, returns true
if the grant has been allocated, false
otherwise.
Sourcefn allocate_custom_grant(
&self,
size: usize,
align: usize,
) -> Result<(ProcessCustomGrantIdentifier, NonNull<u8>), ()>
fn allocate_custom_grant( &self, size: usize, align: usize, ) -> Result<(ProcessCustomGrantIdentifier, NonNull<u8>), ()>
Allocate memory from the grant region that is size
bytes long and
aligned to align
bytes. This is used for creating custom grants which
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 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.
Sourcefn enter_grant(&self, grant_num: usize) -> Result<NonNull<u8>, Error>
fn enter_grant(&self, grant_num: usize) -> Result<NonNull<u8>, Error>
Enter the grant based on grant_num
for this process.
Entering a grant means getting access to the actual memory for the object stored as the grant.
This will return an Err
if the process is inactive of the grant_num
is invalid, if the grant has not been allocated, or if the grant is
already entered. If this returns Ok()
then the pointer points to the
previously allocated memory for this grant.
Sourcefn enter_custom_grant(
&self,
identifier: ProcessCustomGrantIdentifier,
) -> Result<*mut u8, Error>
fn enter_custom_grant( &self, identifier: ProcessCustomGrantIdentifier, ) -> Result<*mut u8, Error>
Enter a custom grant based on the identifier
.
This retrieves a pointer to the previously allocated custom grant based on the identifier returned when the custom grant was allocated.
This returns an error if the custom grant is no longer accessible, or if the process is inactive.
Sourceunsafe fn leave_grant(&self, grant_num: usize)
unsafe fn leave_grant(&self, grant_num: usize)
Opposite of enter_grant()
. Used to signal that the grant is no longer
entered.
If grant_num
is valid, this function cannot fail. If grant_num
is
invalid, this function will do nothing. If the process is inactive then
grants are invalid and are not entered or not entered, and this function
will do nothing.
§Safety
The caller must ensure that no references to the memory inside the grant
exist after calling leave_grant()
. Otherwise, it would be possible to
effectively enter the grant twice (once using the existing reference,
once with a new call to enter_grant()
) which breaks the memory safety
requirements of grants.
Sourcefn grant_allocated_count(&self) -> Option<usize>
fn grant_allocated_count(&self) -> Option<usize>
Return the count of the number of allocated grant pointers if the
process is active. This does not count custom grants. This is used to
determine if a new grant has been allocated after a call to
SyscallDriver::allocate_grant()
.
Useful for debugging/inspecting the system.
Sourcefn lookup_grant_from_driver_num(
&self,
driver_num: usize,
) -> Result<usize, Error>
fn lookup_grant_from_driver_num( &self, driver_num: usize, ) -> Result<usize, Error>
Get the grant number (grant_num) associated with a given driver number if there is a grant associated with that driver_num.
Sourcefn is_valid_upcall_function_pointer(&self, upcall_fn: *const ()) -> bool
fn is_valid_upcall_function_pointer(&self, upcall_fn: *const ()) -> bool
Verify that an upcall function pointer is within process-accessible memory.
Returns true
if the upcall function pointer is valid for this process,
and false
otherwise.
Sourcefn set_syscall_return_value(&self, return_value: SyscallReturn)
fn set_syscall_return_value(&self, return_value: SyscallReturn)
Set the return value the process should see when it begins executing again after the syscall.
It is not valid to call this function when the process is inactive (i.e. the process will not run again).
This can fail, if the UKB implementation cannot correctly set the return value. An example of how this might occur:
- The UKB implementation uses the process’s stack to transfer values between kernelspace and userspace.
- The process calls memop.brk and reduces its accessible memory region below its current stack.
- The UKB implementation can no longer set the return value on the stack since the process no longer has access to its stack.
If it fails, the process will be put into the faulted state.
Sourcefn set_process_function(&self, callback: FunctionCall)
fn set_process_function(&self, callback: FunctionCall)
Set the function that is to be executed when the process is resumed.
It is not valid to call this function when the process is inactive (i.e. the process will not run again).
Sourcefn switch_to(&self) -> Option<ContextSwitchReason>
fn switch_to(&self) -> Option<ContextSwitchReason>
Context switch to a specific process.
This will return None
if the process is inactive and cannot be
switched to.
Sourcefn get_addresses(&self) -> ProcessAddresses
fn get_addresses(&self) -> ProcessAddresses
Return process state information related to the location in memory of various process data structures.
Sourcefn get_sizes(&self) -> ProcessSizes
fn get_sizes(&self) -> ProcessSizes
Return process state information related to the size in memory of various process data structures.
Sourcefn get_stored_state(&self, out: &mut [u8]) -> Result<usize, ErrorCode>
fn get_stored_state(&self, out: &mut [u8]) -> Result<usize, ErrorCode>
Write stored state as a binary blob into the out
slice. Returns the
number of bytes written to out
on success.
Returns ErrorCode::SIZE
if out
is too short to hold the stored state
binary representation. Returns ErrorCode::FAIL
on an internal error.
Sourcefn print_full_process(&self, writer: &mut dyn Write)
fn print_full_process(&self, writer: &mut dyn Write)
Print out the full state of the process: its memory map, its context, and the state of the memory protection unit (MPU).
Sourcefn debug_syscall_count(&self) -> usize
fn debug_syscall_count(&self) -> usize
Returns how many syscalls this app has called.
Sourcefn debug_dropped_upcall_count(&self) -> usize
fn debug_dropped_upcall_count(&self) -> usize
Returns how many upcalls for this process have been dropped.
Sourcefn debug_timeslice_expiration_count(&self) -> usize
fn debug_timeslice_expiration_count(&self) -> usize
Returns how many times this process has exceeded its timeslice.
Sourcefn debug_timeslice_expired(&self)
fn debug_timeslice_expired(&self)
Increment the number of times the process has exceeded its timeslice.
Sourcefn debug_syscall_called(&self, last_syscall: Syscall)
fn debug_syscall_called(&self, last_syscall: Syscall)
Increment the number of times the process called a syscall and record the last syscall that was called.
Sourcefn debug_syscall_last(&self) -> Option<Syscall>
fn debug_syscall_last(&self) -> Option<Syscall>
Return the last syscall the process called. Returns None
if the
process has not called any syscalls or the information is unknown.