1
0
mirror of https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git synced 2026-10-24 00:48:53 +03:00

bindings: rust: mark all owning types as Send

The thread-safety rules of libgpiod allow individual object instances to
be used from different threads. So far, this was not actually possible
with the Rust bindings. Not being `Send` disallowed the user to transfer
the ownership to different threads.

Rust also has a `Sync` marker. That one would even allow sending
references of objects to other threads. Since we wrap a lot of C
functions with `fn foo(&self)` signatures, that would not be safe.
libgpiod does not allow concurrent API calls to the same object instance
- which Rust would allow for read-only references. Thus, we do not
define that one.

Chip was already modeled correctly.

line::Info is not marked as Send since it may either be owning or non-
owning. That problem is fixed as part of a separate pull request [1].

[1] https://lore.kernel.org/r/20230927-rust-line-info-soundness-v1-0-990dce6f18ab@linaro.org

Link: https://lore.kernel.org/r/CVHO091CC80Y.3KUOSLSOBVL0T@ablu-work
Signed-off-by: Erik Schilling <erik.schilling@linaro.org>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
This commit is contained in:
Erik Schilling
2023-09-28 16:37:30 +02:00
committed by Bartosz Golaszewski
parent 626bdba0d7
commit 64aac85b59
7 changed files with 32 additions and 0 deletions

View File

@@ -24,6 +24,10 @@ use super::{
#[derive(Debug, Eq, PartialEq)]
pub struct Event(*mut gpiod::gpiod_edge_event);
// SAFETY: Event models a wrapper around an owned gpiod_edge_event and may
// be safely sent to other threads.
unsafe impl Send for Event {}
impl Event {
pub fn event_clone(event: &Event) -> Result<Event> {
// SAFETY: `gpiod_edge_event` is guaranteed to be valid here.

View File

@@ -68,6 +68,14 @@ pub struct Buffer {
events: Vec<*mut gpiod::gpiod_edge_event>,
}
// SAFETY: Buffer models an owned gpiod_edge_event_buffer. However, there may
// be events tied to it. Concurrent access from multiple threads to a buffer
// and its associated events is not allowed by the C lib.
// In Rust, those events will always be borrowed from a buffer instance. Thus,
// either Rust prevents the user to move the Buffer while there are still
// borrowed events, or we can safely send the the Buffer.
unsafe impl Send for Buffer {}
impl Buffer {
/// Create a new edge event buffer.
///

View File

@@ -25,6 +25,10 @@ pub struct Event {
pub(crate) event: *mut gpiod::gpiod_info_event,
}
// SAFETY: Event models a wrapper around an owned gpiod_info_event and may be
// safely sent to other threads.
unsafe impl Send for Event {}
impl Event {
/// Get a single chip's line's status change event.
pub(crate) fn new(event: *mut gpiod::gpiod_info_event) -> Self {

View File

@@ -28,6 +28,10 @@ pub struct Config {
pub(crate) config: *mut gpiod::gpiod_line_config,
}
// SAFETY: Config models a wrapper around an owned gpiod_line_config and may be
// safely sent to other threads.
unsafe impl Send for Config {}
impl Config {
/// Create a new line config object.
pub fn new() -> Result<Self> {

View File

@@ -20,6 +20,10 @@ pub struct Request {
pub(crate) request: *mut gpiod::gpiod_line_request,
}
// SAFETY: Request models a wrapper around an owned gpiod_line_request and may
// be safely sent to other threads.
unsafe impl Send for Request {}
impl Request {
/// Request a set of lines for exclusive usage.
pub(crate) fn new(request: *mut gpiod::gpiod_line_request) -> Result<Self> {

View File

@@ -25,6 +25,10 @@ pub struct Settings {
pub(crate) settings: *mut gpiod::gpiod_line_settings,
}
// SAFETY: Settings models a wrapper around an owned gpiod_line_settings and may
// be safely sent to other threads.
unsafe impl Send for Settings {}
impl Settings {
/// Create a new line settings object.
pub fn new() -> Result<Self> {

View File

@@ -20,6 +20,10 @@ pub struct Config {
pub(crate) config: *mut gpiod::gpiod_request_config,
}
// SAFETY: Config models a wrapper around an owned gpiod_request_config and may
// be safely sent to other threads.
unsafe impl Send for Config {}
impl Config {
/// Create a new request config object.
pub fn new() -> Result<Self> {