Expand description
Mechanisms for handling and defining system calls.
§System Call Overview
Tock supports six system calls. The allow_readonly
, allow_readwrite
,
subscribe
, yield
, and memop
system calls are handled by the core
kernel, while command
is implemented by drivers. The main system calls:
subscribe
passes a upcall to the driver which it can invoke on the process later, when an event has occurred or data of interest is available.command
tells the driver to do something immediately.allow_readwrite
provides the driver read-write access to an application buffer.allow_userspace_readable
provides the driver read-write access to an application buffer that is still shared with the app.allow_readonly
provides the driver read-only access to an application buffer.
§Mapping system-calls to drivers
Each of these three system calls takes at least two parameters. The first is
a driver identifier and tells the scheduler which driver to forward the
system call to. The second parameters is a _syscall number and is used by
the driver to differentiate instances of the call with different
driver-specific meanings (e.g. subscribe
for “data received” vs
subscribe
for “send completed”). The mapping between driver identifiers
and drivers is determined by a particular platform, while the syscall
number is driver-specific.
One convention in Tock is that driver minor number 0 for the command
syscall can always be used to determine if the driver is supported by the
running kernel by checking the return code. If the return value is greater
than or equal to zero then the driver is present. Typically this is
implemented by a null command that only returns 0, but in some cases the
command can also return more information, like the number of supported
devices (useful for things like the number of LEDs).
§The yield
system call class
While drivers do not handle yield
system calls, it is important to
understand them and how they interact with subscribe
, which registers
upcall functions with the kernel. When a process calls a yield
system
call, the kernel checks if there are any pending upcalls for the process. If
there are pending upcalls, it pushes one upcall onto the process stack. If
there are no pending upcalls, yield-wait
will cause the process to sleep
until a upcall is triggered, while yield-no-wait
returns immediately.
§Method result types
Each driver method has a limited set of valid return types. Every method has
a single return type corresponding to success and a single return type
corresponding to failure. For the subscribe
and allow
system calls,
these return types are the same for every instance of those calls. Each
instance of the command
system call, however, has its own specified return
types. A command that requests a timestamp, for example, might return a
32-bit number on success and an error code on failure, while a command that
requests time of day in microsecond granularity might return a 64-bit number
and a 32-bit timezone encoding on success, and an error code on failure.
These result types are represented as safe Rust types. The core kernel (the scheduler and syscall dispatcher) is responsible for encoding these types into the Tock system call ABI specification.
Structs§
- Possible return values of a
command
driver method, as specified in TRD104.
Enums§
ContextSwitchReason
specifies why the process stopped executing and execution returned to the kernel.- Decoded system calls as defined in TRD104.
- Enumeration of the system call classes based on the identifiers specified in the Tock ABI.
- Enumeration of the possible system call return variants.
- Enumeration of the yield system calls based on the Yield identifier values specified in the Tock ABI.
Traits§
- Trait for capsules implementing peripheral driver system calls specified in TRD104. The kernel translates the values passed from userspace into Rust types and includes which process is making the call. All of these system calls perform very little synchronous work; long running computations or I/O should be split-phase, with an upcall indicating their completion.
- The
UserspaceKernelBoundary
trait is implemented by the architectural component of the chip implementation of Tock. This trait allows the kernel to switch to and from processes in an architecture-independent manner.