Skip to content

Commit a4f9548

Browse files
committed
samples: philosopher: Add Condvar based sync
Add an implementation of the fork synchronizer build around a single array of flags, protected by a mutex, and coordinated with a condition variable. Signed-off-by: David Brown <[email protected]>
1 parent 8455599 commit a4f9548

File tree

2 files changed

+78
-1
lines changed

2 files changed

+78
-1
lines changed

samples/philosophers/src/condsync.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright (c) 2024 Linaro LTD
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
//! # sync::Mutex/sync::Condvar implementation of ForkSync
5+
//!
6+
//! This implementation of the Fork synchronizer uses a single data object, protected by a
7+
//! `sync::Mutex`, and coordinated by a `sync::Condvar`.
8+
9+
use crate::{
10+
ForkSync,
11+
NUM_PHIL,
12+
};
13+
use zephyr::{
14+
kobj_define,
15+
};
16+
use zephyr::object::KobjInit;
17+
use zephyr::sync::Mutex;
18+
use zephyr::sync::Condvar;
19+
// use zephyr::time::Forever;
20+
21+
#[derive(Debug)]
22+
pub struct CondSync {
23+
/// The lock that holds the flag for each philosopher.
24+
lock: Mutex<[bool; NUM_PHIL]>,
25+
/// Condition variable to wake other threads.
26+
cond: Condvar,
27+
}
28+
29+
impl CondSync {
30+
pub fn new() -> CondSync {
31+
MUTEX.init();
32+
CONDVAR.init();
33+
let sys_mutex = MUTEX.get();
34+
let sys_condvar = CONDVAR.get();
35+
36+
let lock = Mutex::new_from([false; NUM_PHIL], sys_mutex);
37+
let cond = Condvar::new_from(sys_condvar);
38+
CondSync { lock, cond }
39+
}
40+
}
41+
42+
impl ForkSync for CondSync {
43+
fn take(&self, index: usize) {
44+
let mut lock = self.lock.lock().unwrap();
45+
while lock[index] {
46+
lock = self.cond.wait(lock).unwrap();
47+
}
48+
lock[index] = true;
49+
}
50+
51+
fn release(&self, index: usize) {
52+
let mut lock = self.lock.lock().unwrap();
53+
lock[index] = false;
54+
// No predictible waiter, so must wake everyone.
55+
self.cond.notify_all();
56+
}
57+
}
58+
59+
kobj_define! {
60+
static MUTEX: StaticMutex;
61+
static CONDVAR: StaticCondvar;
62+
}

samples/philosophers/src/lib.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@ use zephyr::{
1616
sync::{Arc, Mutex},
1717
};
1818

19+
use crate::condsync::CondSync;
1920
use crate::sysmutex::SysMutexSync;
2021

22+
mod condsync;
2123
mod sysmutex;
2224

2325
/// How many philosophers. There will be the same number of forks.
@@ -84,7 +86,8 @@ extern "C" fn rust_main() {
8486
}
8587
}
8688

87-
fn get_syncer() -> Vec<Arc<dyn ForkSync>> {
89+
#[allow(dead_code)]
90+
fn get_syncerb() -> Vec<Arc<dyn ForkSync>> {
8891
// Simple mutex version.
8992
let syncer = Box::new(SysMutexSync::new())
9093
as Box<dyn ForkSync>;
@@ -96,6 +99,18 @@ fn get_syncer() -> Vec<Arc<dyn ForkSync>> {
9699
result
97100
}
98101

102+
fn get_syncer() -> Vec<Arc<dyn ForkSync>> {
103+
// Condvar version
104+
let syncer = Box::new(CondSync::new())
105+
as Box<dyn ForkSync>;
106+
let syncer: Arc<dyn ForkSync> = Arc::from(syncer);
107+
let mut result = Vec::new();
108+
for _ in 0..NUM_PHIL {
109+
result.push(syncer.clone());
110+
}
111+
result
112+
}
113+
99114
fn phil_thread(n: usize, syncer: Arc<dyn ForkSync>, stats: Arc<Mutex<Stats>>) {
100115
printkln!("Child {} started: {:?}", n, syncer);
101116

0 commit comments

Comments
 (0)