diff --git a/samples/philosophers/Kconfig b/samples/philosophers/Kconfig index 97dfe318..fdc76b2f 100644 --- a/samples/philosophers/Kconfig +++ b/samples/philosophers/Kconfig @@ -7,14 +7,20 @@ source "Kconfig.zephyr" choice prompt "Select Synchronization implementation" - default SYNC_CHANNEL + default SYNC_SYS_DYNAMIC_SEMAPHORE config SYNC_SYS_SEMAPHORE bool "Use sys::Semaphore to synchronize forks" help - Use to have the dining philosophers sample use sys::Mutex, with one per fork, to + Use to have the dining philosophers sample use sys::Semaphore, with one per fork, to synchronize. + config SYNC_SYS_DYNAMIC_SEMAPHORE + bool "Use a dynamic sys::Semaphore to synchronize forks" + help + Use to have the dining philosophers sample use sys::Semaphore, with one per fork, to + synchronize. The Semaphores will be dynamically allocated. + config SYNC_SYS_MUTEX bool "Use sys::Semaphore to synchronize forks" help diff --git a/samples/philosophers/sample.yaml b/samples/philosophers/sample.yaml index b59af7b1..8e938bd2 100644 --- a/samples/philosophers/sample.yaml +++ b/samples/philosophers/sample.yaml @@ -17,6 +17,11 @@ tests: min_ram: 32 extra_configs: - CONFIG_SYNC_SYS_SEMAPHORE=y + sample.rust.philosopher.dynsemaphore: + tags: introduction + min_ram: 32 + extra_configs: + - CONFIG_SYNC_SYS_DYNAMIC_SEMAPHORE=y sample.rust.philosopher.sysmutex: tags: introduction min_ram: 32 diff --git a/samples/philosophers/src/dynsemsync.rs b/samples/philosophers/src/dynsemsync.rs new file mode 100644 index 00000000..8015ffe9 --- /dev/null +++ b/samples/philosophers/src/dynsemsync.rs @@ -0,0 +1,51 @@ +// Copyright (c) 2023 Linaro LTD +// SPDX-License-Identifier: Apache-2.0 + +//! Semaphore based sync. +//! +//! This is the simplest type of sync, which uses a single semaphore per fork. + +extern crate alloc; + +use alloc::vec::Vec; +use alloc::boxed::Box; + +use zephyr::{ + sync::Arc, sys::sync::Semaphore, time::Forever +}; + +use crate::{ForkSync, NUM_PHIL}; + +#[derive(Debug)] +pub struct SemSync { + /// The forks for this philosopher. This is a big excessive, as we really don't need all of + /// them, but the ForSync code uses the index here. + forks: [Arc; NUM_PHIL], +} + +impl ForkSync for SemSync { + fn take(&self, index: usize) { + self.forks[index].take(Forever).unwrap(); + } + + fn release(&self, index: usize) { + self.forks[index].give(); + } +} + +#[allow(dead_code)] +pub fn dyn_semaphore_sync() -> Vec> { + let forks = [(); NUM_PHIL].each_ref().map(|()| { + Arc::new(Semaphore::new(1, 1).unwrap()) + }); + + let syncers = (0..NUM_PHIL).map(|_| { + let syncer = SemSync { + forks: forks.clone(), + }; + let item = Box::new(syncer) as Box; + Arc::from(item) + }).collect(); + + syncers +} diff --git a/samples/philosophers/src/lib.rs b/samples/philosophers/src/lib.rs index ed6a093e..35be8f25 100644 --- a/samples/philosophers/src/lib.rs +++ b/samples/philosophers/src/lib.rs @@ -30,9 +30,12 @@ use crate::sysmutex::SysMutexSync; use crate::channel::get_channel_syncer; #[allow(unused_imports)] use crate::semsync::semaphore_sync; +#[allow(unused_imports)] +use crate::dynsemsync::dyn_semaphore_sync; mod channel; mod condsync; +mod dynsemsync; mod sysmutex; mod semsync; @@ -95,6 +98,11 @@ fn get_syncer() -> Vec> { semaphore_sync() } +#[cfg(CONFIG_SYNC_SYS_DYNAMIC_SEMAPHORE)] +fn get_syncer() -> Vec> { + dyn_semaphore_sync() +} + #[cfg(CONFIG_SYNC_SYS_MUTEX)] fn get_syncer() -> Vec> { let syncer = Box::new(SysMutexSync::new())