Skip to content

Commit

Permalink
samples: philosophers: Add statistics
Browse files Browse the repository at this point in the history
Using the newly provided `sync::Mutex`, implement support for printing
statistics about the philosophers habits.  Remove the verbose message
showing each meal, and replace with a period print of the statics.

Change the sample.yml file with a regexp to make sure that all of the
philosphers are able to eat at least a bit.

Signed-off-by: David Brown <[email protected]>
  • Loading branch information
d3zd3z committed Sep 23, 2024
1 parent d38b55f commit 675e29b
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 10 deletions.
4 changes: 3 additions & 1 deletion samples/philosophers/sample.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ common:
harness_config:
type: one_line
regex:
- "Child 5 thinking"
# Match the statistics, and make sure that each philosopher has at least 10 (two digits)
# meals.
- "^\\[\\d{2,}, \\d{2,}, \\d{2,}, \\d{2,}, \\d{2,}, \\d{2,}\\]"
tags: rust
filter: CONFIG_RUST_SUPPORTED
tests:
Expand Down
63 changes: 54 additions & 9 deletions samples/philosophers/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ extern crate alloc;

use alloc::boxed::Box;
use alloc::vec::Vec;
use zephyr::object::KobjInit;
use zephyr::time::{Duration, sleep, Tick};
use zephyr::{
printkln,
kobj_define,
sys::uptime_get,
sync::Arc,
sync::{Arc, Mutex},
};

use crate::sysmutex::SysMutexSync;
Expand Down Expand Up @@ -51,6 +52,9 @@ extern "C" fn rust_main() {
zephyr::kconfig::CONFIG_BOARD);
printkln!("Time tick: {}", zephyr::time::SYS_FREQUENCY);

STAT_MUTEX.init();
let stats = Arc::new(Mutex::new_from(Stats::default(), STAT_MUTEX.get()));

let syncers = get_syncer();

printkln!("Pre fork");
Expand All @@ -65,9 +69,9 @@ extern "C" fn rust_main() {
let child_syncer = ChannelSync::new(cq_send.clone(), reply_queues[i].clone());
let child_syncer = Arc::new(child_syncer);
*/
// let child_stat = stats.clone();
let child_stat = stats.clone();
let thread = PHIL_THREAD[i].spawn(PHIL_STACK[i].token(), move || {
phil_thread(i, syncer /*, child_stat*/);
phil_thread(i, syncer, child_stat);
});
thread.start();
}
Expand All @@ -76,7 +80,7 @@ extern "C" fn rust_main() {
loop {
// Periodically, printout the stats.
zephyr::time::sleep(delay);
// stats.lock().unwrap().show();
stats.lock().unwrap().show();
}
}

Expand All @@ -92,7 +96,7 @@ fn get_syncer() -> Vec<Arc<dyn ForkSync>> {
result
}

fn phil_thread(n: usize, syncer: Arc<dyn ForkSync> /*, stats: Arc<Mutex<Stats>>*/) {
fn phil_thread(n: usize, syncer: Arc<dyn ForkSync>, stats: Arc<Mutex<Stats>>) {
printkln!("Child {} started: {:?}", n, syncer);

// Determine our two forks.
Expand All @@ -112,20 +116,58 @@ fn phil_thread(n: usize, syncer: Arc<dyn ForkSync> /*, stats: Arc<Mutex<Stats>>*
syncer.take(forks.1);

let delay = get_random_delay(n, 25);
printkln!("Child {} eating ({} ms)", n, delay);
// printkln!("Child {} eating ({} ms)", n, delay);
sleep(delay);
// stats.lock().unwrap().record_eat(n, delay);
stats.lock().unwrap().record_eat(n, delay);

// Release the forks.
// printkln!("Child {} giving up forks", n);
syncer.release(forks.1);
syncer.release(forks.0);

let delay = get_random_delay(n, 25);
printkln!("Child {} thinking ({} ms)", n, delay);
// printkln!("Child {} thinking ({} ms)", n, delay);
sleep(delay);
// stats.lock().unwrap().record_think(n, delay);
stats.lock().unwrap().record_think(n, delay);
}
}
}

/// Instead of just printing out so much information that the data just scrolls by, gather statistics.
#[derive(Default)]
struct Stats {
/// How many times each philospher has gone through the loop.
count: [u64; NUM_PHIL],
/// How much time each philosopher has spent eating.
eating: [u64; NUM_PHIL],
/// How much time each pilosopher has spent thinking.
thinking: [u64; NUM_PHIL],
}

impl Stats {
fn record_eat(&mut self, index: usize, time: Duration) {
self.eating[index] += time.to_millis();
}

fn record_think(&mut self, index: usize, time: Duration) {
self.thinking[index] += time.to_millis();
self.count[index] += 1;
}

fn show(&self) {
printkln!("{:?}, e:{:?}, t:{:?}", self.count, self.eating, self.thinking);

/*
// Invoke the thread analyzer report.
{
extern "C" {
fn thread_analyzer_print(cpu: usize);
}
unsafe {
thread_analyzer_print(0);
}
}
*/
}
}

Expand All @@ -141,4 +183,7 @@ fn get_random_delay(id: usize, period: usize) -> Duration {
kobj_define! {
static PHIL_THREAD: [StaticThread; NUM_PHIL];
static PHIL_STACK: [ThreadStack<PHIL_STACK_SIZE>; NUM_PHIL];

// A mutex to hold statistics data.
static STAT_MUTEX: StaticMutex;
}

0 comments on commit 675e29b

Please sign in to comment.