Skip to content

Commit b9570ca

Browse files
committed
samples: philosophers: Add statistics
Rather than just printing a bunch of information out as the various philosopher threads dine, use some data protected within a Mutex to collect statistics, and print those out periodically. Signed-off-by: David Brown <[email protected]>
1 parent 3cff3c8 commit b9570ca

File tree

2 files changed

+45
-15
lines changed

2 files changed

+45
-15
lines changed

samples/philosophers/sample.yaml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,7 @@ common:
88
regex:
99
# Match the statistics, and make sure that each philosopher has at least 10 (two digits)
1010
# meals.
11-
# - "^\\[\\d{2,}, \\d{2,}, \\d{2,}, \\d{2,}, \\d{2,}, \\d{2,}\\]"
12-
#
13-
# Until the stastics have been implemented, just match on one of the children thinking
14-
- "^Child 5 thinking \\(\\d+ ticks.*"
11+
- "^\\[\\d{2,}, \\d{2,}, \\d{2,}, \\d{2,}, \\d{2,}, \\d{2,}\\]"
1512
tags: rust
1613
filter: CONFIG_RUST_SUPPORTED
1714
tests:

samples/philosophers/src/lib.rs

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use zephyr::{
1818
printkln,
1919
kobj_define,
2020
sys::uptime_get,
21-
sync::Arc,
21+
sync::{Arc, Mutex},
2222
};
2323

2424
// These are optional, based on Kconfig, so allow them to be unused.
@@ -68,21 +68,25 @@ extern "C" fn rust_main() {
6868
zephyr::kconfig::CONFIG_BOARD);
6969
printkln!("Time tick: {}", zephyr::time::SYS_FREQUENCY);
7070

71+
let stats = Arc::new(Mutex::new_from(Stats::default(), STAT_MUTEX.init_once(()).unwrap()));
72+
7173
let syncers = get_syncer();
7274

7375
printkln!("Pre fork");
7476

7577
for (i, syncer) in (0..NUM_PHIL).zip(syncers.into_iter()) {
78+
let child_stat = stats.clone();
7679
let thread = PHIL_THREADS[i].init_once(PHIL_STACKS[i].init_once(()).unwrap()).unwrap();
7780
thread.spawn(move || {
78-
phil_thread(i, syncer);
81+
phil_thread(i, syncer, child_stat);
7982
});
8083
}
8184

8285
let delay = Duration::secs_at_least(10);
8386
loop {
8487
// Periodically, printout the stats.
8588
zephyr::time::sleep(delay);
89+
stats.lock().unwrap().show();
8690
}
8791
}
8892

@@ -121,7 +125,7 @@ fn get_syncer() -> Vec<Arc<dyn ForkSync>> {
121125
get_channel_syncer()
122126
}
123127

124-
fn phil_thread(n: usize, syncer: Arc<dyn ForkSync>) {
128+
fn phil_thread(n: usize, syncer: Arc<dyn ForkSync>, stats: Arc<Mutex<Stats>>) {
125129
printkln!("Child {} started: {:?}", n, syncer);
126130

127131
// Determine our two forks.
@@ -134,26 +138,26 @@ fn phil_thread(n: usize, syncer: Arc<dyn ForkSync>) {
134138

135139
loop {
136140
{
137-
printkln!("Child {} hungry", n);
138-
printkln!("Child {} take left fork", n);
141+
// printkln!("Child {} hungry", n);
142+
// printkln!("Child {} take left fork", n);
139143
syncer.take(forks.0);
140-
printkln!("Child {} take right fork", n);
144+
// printkln!("Child {} take right fork", n);
141145
syncer.take(forks.1);
142146

143147
let delay = get_random_delay(n, 25);
144-
printkln!("Child {} eating ({} ms)", n, delay);
148+
// printkln!("Child {} eating ({} ms)", n, delay);
145149
sleep(delay);
146-
// stats.lock().unwrap().record_eat(n, delay);
150+
stats.lock().unwrap().record_eat(n, delay);
147151

148152
// Release the forks.
149-
printkln!("Child {} giving up forks", n);
153+
// printkln!("Child {} giving up forks", n);
150154
syncer.release(forks.1);
151155
syncer.release(forks.0);
152156

153157
let delay = get_random_delay(n, 25);
154-
printkln!("Child {} thinking ({} ms)", n, delay);
158+
// printkln!("Child {} thinking ({} ms)", n, delay);
155159
sleep(delay);
156-
// stats.lock().unwrap().record_think(n, delay);
160+
stats.lock().unwrap().record_think(n, delay);
157161
}
158162
}
159163
}
@@ -167,7 +171,36 @@ fn get_random_delay(id: usize, period: usize) -> Duration {
167171
Duration::millis_at_least(((delay + 1) * period) as Tick)
168172
}
169173

174+
/// Instead of just printint out so much information that the data just scolls by, gather
175+
/// statistics.
176+
#[derive(Default)]
177+
struct Stats {
178+
/// How many times each philosopher has gone through the loop.
179+
count: [u64; NUM_PHIL],
180+
/// How much time each philosopher has spent eating.
181+
eating: [u64; NUM_PHIL],
182+
/// How much time each philosopher has spent thinking.
183+
thinking: [u64; NUM_PHIL],
184+
}
185+
186+
impl Stats {
187+
fn record_eat(&mut self, index: usize, time: Duration) {
188+
self.eating[index] += time.to_millis();
189+
}
190+
191+
fn record_think(&mut self, index: usize, time: Duration) {
192+
self.thinking[index] += time.to_millis();
193+
self.count[index] += 1;
194+
}
195+
196+
fn show(&self) {
197+
printkln!("{:?}, e:{:?}, t:{:?}", self.count, self.eating, self.thinking);
198+
}
199+
}
200+
170201
kobj_define! {
171202
static PHIL_THREADS: [StaticThread; NUM_PHIL];
172203
static PHIL_STACKS: [ThreadStack<PHIL_STACK_SIZE>; NUM_PHIL];
204+
205+
static STAT_MUTEX: StaticMutex;
173206
}

0 commit comments

Comments
 (0)