diff --git a/.gitignore b/.gitignore index f805e81..958a081 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,6 @@ # Debug files *.dSYM/ *.su + +# Rust +target/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..9ff9204 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,26 @@ +image: scorpil/rust:stable + +stages: + - test + +cargo:test: + stage: test + script: + - ci/run-cargo-test.sh + +rustfmt: + stage: test + script: + - ci/run-rustfmt.sh + +shellcheck: + stage: test + image: ubuntu:yakkety + before_script: + - apt-get update && apt-get install -y shellcheck + - locale-gen en_US.UTF-8 + - export LANG=en_US.UTF-8 + - export LANGUAGE=en_US:en + - export LC_ALL=en_US.UTF-8 + script: + - ci/run-shellcheck.sh diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..3d9c78c --- /dev/null +++ b/.travis.yml @@ -0,0 +1,5 @@ +language: rust +rust: + - nightly +script: + - true diff --git a/README.md b/README.md index 9c0557d..7a1964c 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ -# resy-ss17-template +# resy-ss17-grp1 Template for grp repositories diff --git a/V1/led.sh b/V1/led.sh new file mode 100755 index 0000000..a0033e7 --- /dev/null +++ b/V1/led.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash +# usage: led.sh +set -o xtrace + +# config default +GPIO_PORT="${1:-18}" + +function export_port() { + port="${1}" + echo "${port}" > /sys/class/gpio/export +} +function unexport_port() { + port="${1}" + echo "${port}" > /sys/class/gpio/unexport +} + +function set_direction() { + port="${1}" + value="${2}" + echo "${value}" > "/sys/class/gpio/gpio${port}/direction" +} + +function set_value() { + port="${1}" + value="${2}" + echo "${value}" > "/sys/class/gpio/gpio${port}/value" +} + +function on() { + port="${1}" + set_value "${port}" "0" +} +function off() { + port="${1}" + set_value "${port}" "1" +} + +# set exit trap +trap 'unexport_port "${GPIO_PORT}"' EXIT + +# init GPIO port +export_port "${GPIO_PORT}" +set_direction "${GPIO_PORT}" "out" + +# loop led on/off +while true; do + on "${GPIO_PORT}" + sleep 1 + off "${GPIO_PORT}" + sleep 1 +done diff --git a/V1/led5/Cargo.lock b/V1/led5/Cargo.lock new file mode 100644 index 0000000..152edd2 --- /dev/null +++ b/V1/led5/Cargo.lock @@ -0,0 +1,66 @@ +[root] +name = "led5" +version = "0.1.0" +dependencies = [ + "chan 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "chan-signal 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bit-set" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bit-vec" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "chan" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "chan-signal" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "chan 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lazy_static" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rand" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[metadata] +"checksum bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9bf6104718e80d7b26a68fdbacff3481cfc05df670821affc7e9cbc1884400c" +"checksum bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5b97c2c8e8bbb4251754f559df8af22fb264853c7d009084a576cdf12565089d" +"checksum chan 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "f93bfe971116428a9066c1c3c69a09ae3ef69432f8418be28ab50f96783e6a50" +"checksum chan-signal 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0f3bb6c3bc387004ad914f0c5b7f33ace8bf7604bbec35f228b1a017f52cd3a0" +"checksum lazy_static 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4732c563b9a21a406565c4747daa7b46742f082911ae4753f390dc9ec7ee1a97" +"checksum libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "88ee81885f9f04bff991e306fea7c1c60a5f0f9e409e99f6b40e3311a3363135" +"checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d" diff --git a/V1/led5/Cargo.toml b/V1/led5/Cargo.toml new file mode 100644 index 0000000..345cf6b --- /dev/null +++ b/V1/led5/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "led5" +version = "0.1.0" +authors = ["Simon Wörner "] + +[dependencies] +chan = ">=0.1.19" +chan-signal = ">=0.2.0" diff --git a/V1/led5/src/main.rs b/V1/led5/src/main.rs new file mode 100644 index 0000000..df47b06 --- /dev/null +++ b/V1/led5/src/main.rs @@ -0,0 +1,150 @@ +#[macro_use] +extern crate chan; +extern crate chan_signal; + +use std::io::prelude::*; +use std::fs::File; +use std::thread; +use std::thread::JoinHandle; +use std::path::Path; +use std::time::Duration; + +use chan_signal::Signal; + +static GPIO_PORT_BTN: &'static str = "17"; +static GPIO_PORT_LED: &'static str = "18"; + +static GPIO_DIRECTION_IN: &'static str = "in"; +static GPIO_DIRECTION_OUT: &'static str = "out"; + +static GPIO_BTN_ON: &'static str = "0"; +//static GPIO_BTN_OFF: &'static str = "1"; + +static GPIO_LED_ON: &'static str = "0"; +static GPIO_LED_OFF: &'static str = "1"; + +fn write(path: &str, value: &str) { + let mut file = File::create(Path::new(path)) + .expect(format!("Open file '{}' failed", path).as_str()); + + file.write_all(value.as_bytes()) + .expect(format!("Write value '{}' to '{}' file failed", value, path).as_str()); + + #[cfg(debug_assertions)] + println!("Wrote value '{}' to '{}'.", value, path); +} +fn read(path: &str) -> String { + let mut file = File::open(Path::new(path)) + .expect(format!("Open file '{}' failed", path).as_str()); + let mut contents = String::new(); + + file.read_to_string(&mut contents) + .expect(format!("Read from '{}' file failed", path).as_str()); + + #[cfg(debug_assertions)] + println!("Read value '{}' from '{}'.", contents, path); + + contents +} + +fn export(port: &str) { + write("/sys/class/gpio/export", port) +} +fn unexport(port: &str) { + write("/sys/class/gpio/unexport", port) +} + +fn set_direction(port: &str, direction: &str) { + write(format!("/sys/class/gpio/gpio{}/direction", port).as_str(), direction); +} + +fn set_value(port: &str, value: &str) { + write(format!("/sys/class/gpio/gpio{}/value", port).as_str(), value); +} +fn get_value(port: &str) -> String { + String::from(read(format!("/sys/class/gpio/gpio{}/value", port).as_str()).trim()) +} + +fn main() { + let signal = chan_signal::notify(&[Signal::INT, Signal::TERM]); + let (sdone, rdone) = chan::sync(0); + let (spanic, rpanic) = chan::sync(0); + let worker = thread::Builder::new() + .name("worker".to_string()) + .spawn(move || run(rdone)) + .expect("Create worker thread failed"); + let watchdog = thread::Builder::new() + .name("watchdog".to_string()) + .spawn(move || watchdog(worker, spanic)) + .expect("Create watchdog thread failed"); + + chan_select! { + rpanic.recv() => { }, + signal.recv() -> signal => { + println!("received signal: {:?}", signal); + sdone.send(()); + } + } + + watchdog.join().expect("Watchdog thread paniced"); +} + +fn watchdog(thread: JoinHandle<()>, _spanic: chan::Sender<()>) { + thread.join().expect("Thread paniced"); +} + +fn run(rdone: chan::Receiver<()>) { + // init + export(GPIO_PORT_BTN); + export(GPIO_PORT_LED); + set_direction(GPIO_PORT_BTN, GPIO_DIRECTION_IN); + set_direction(GPIO_PORT_LED, GPIO_DIRECTION_OUT); + + let btn_tick = chan::tick(Duration::from_millis(50)); + let led_tick = chan::tick(Duration::from_millis(1000 / 5)); + let mut btn_last = false; + let mut led_on = false; + let mut enabled = true; + + loop { + chan_select! { + btn_tick.recv() => { + //#[cfg(debug_assertions)] + //println!("btn_tick"); + + // switch enabled if button state changed + let btn = get_value(GPIO_PORT_BTN) == GPIO_BTN_ON; + if btn && btn != btn_last { + enabled = !enabled; + } + + btn_last = btn; + }, + led_tick.recv() => { + #[cfg(debug_assertions)] + println!("led_tick"); + + // blink led if enabled + if enabled { + led_on = !led_on; + } else { + led_on = false; + } + + // set led state + if led_on { + set_value(GPIO_PORT_LED, GPIO_LED_ON); + } + else { + set_value(GPIO_PORT_LED, GPIO_LED_OFF); + } + }, + rdone.recv() => { + // unexport + unexport(GPIO_PORT_BTN); + unexport(GPIO_PORT_LED); + return; + }, + } + } +} diff --git a/V1/switch.c b/V1/switch.c new file mode 100644 index 0000000..9fc565f --- /dev/null +++ b/V1/switch.c @@ -0,0 +1,102 @@ +#include +#include +#include +#include +#include + +#define BASEPATH "/sys/class/gpio/" +#define GPIO_FOLDER "gpio%s/" + +#define PIN_BUTTON "17" +#define PIN_LED "18" + +#define LED_ON 0 +#define LED_OFF 1 + +#define BUTTON_PRESSED 0 +#define BUTTON_RELEASED 1 + +void writeFile(char *filename, char *buffer, size_t count) +{ + int fd = open(filename, O_WRONLY); + write(fd, buffer, count); + close(fd); +} + +void registerPin(char *pin) +{ + writeFile(BASEPATH "export", pin, strlen(pin)); +} + +void freePin(char *pin) +{ + writeFile(BASEPATH "unexport", pin, strlen(pin)); +} + +void setDirection(char *pin, char *direction, int dirlen) +{ + char path[50]; + sprintf(path, BASEPATH GPIO_FOLDER "direction", pin); + writeFile(path, direction, dirlen); +} + +void registerInput(char *pin) +{ + registerPin(pin); + setDirection(pin, "in", 2); +} + +void registerOutput(char *pin) +{ + registerPin(pin); + setDirection(pin, "out", 3); +} + +int readInput(char *pin) +{ + char path[50]; + int state; + sprintf(path, BASEPATH GPIO_FOLDER "value", pin); + FILE *fd = fopen(path, "r"); + fscanf(fd, "%i", &state); + fclose(fd); + return state; +} + +void writeOutput(char *pin, int state) +{ + char path[50]; + sprintf(path, BASEPATH GPIO_FOLDER "value", pin); + FILE *fd = fopen(path, "w"); + fprintf(fd, "%i", state); + fclose(fd); +} + +int main() +{ + struct timespec sleeptime, sleepremain; + int oldstate = BUTTON_PRESSED; + int state; + int count = 0; + registerInput(PIN_BUTTON); + registerOutput(PIN_LED); + sleeptime.tv_sec = 0; + sleeptime.tv_nsec = 1000000; + while (1) + { + nanosleep(&sleeptime, &sleepremain); + state = readInput(PIN_BUTTON); + if (state == BUTTON_PRESSED && oldstate == BUTTON_RELEASED) + { + count++; + printf("Number of button pushes: %i\n", count); + } + + if (state == BUTTON_PRESSED) + writeOutput(PIN_LED, LED_ON); + else + writeOutput(PIN_LED, LED_OFF); + + oldstate = state; + } +} diff --git a/V2/delay/.gitignore b/V2/delay/.gitignore new file mode 100644 index 0000000..f7b5423 --- /dev/null +++ b/V2/delay/.gitignore @@ -0,0 +1 @@ +*.eps diff --git a/V2/delay/Auswerung.md b/V2/delay/Auswerung.md new file mode 100644 index 0000000..03f3910 --- /dev/null +++ b/V2/delay/Auswerung.md @@ -0,0 +1,41 @@ +# Auswertung + + + +## No Load + + + +### No Realtime + +Läuft der Prozess ohne Load und Realtime so liegt das Delay im Mean bei etwa **100µs**. +Der Ausreiser bei *11.000µs* Sleep Periode lässt sich durch eine kurze zeitigte Last durch einen Hintergrundprozess erklären, da bei jeder Messung (100 Durchläufe) immer der Worst Case betrachtet wird. + +![delay_idle](delay_idle.png) + +### Realtime + +Im Vergleich dazu sinkt bei aktiver Realtime Priorität das Mean Delay auf etwa **25µs**. + +Hier gibt es dafür mehr Ausreiser welche aber nicht über **190µs** hinaus gehen, auch hier lassen sich diese durch eine kurze zeitigte Last von einen Hintergrundprozess erklären. + +![delay_idle_rt](delay_idle_rt.png) + + + +## Load + +### No Realtime + +Bei Load ohne Realtime gibt es zu Begin einen großen Ausreiser mit über **10.000 µs**. + +![delay_load](delay_load.png) + +### Realtime + +Durch die Realtime Priorität können solche Ausreiser vermieden werden, hier liegt der Mean etwas über dem ohne Last (etwa **27,5µs**) und die Ausreiser gehen bis knapp **55µs**. + +Dies liegt immer weit unter den Werten ohne Load ohne Realtime Priorität. + +![delay_load_rt](delay_load_rt.png) + diff --git a/V2/delay/delay_idle.png b/V2/delay/delay_idle.png new file mode 100644 index 0000000..54a6554 Binary files /dev/null and b/V2/delay/delay_idle.png differ diff --git a/V2/delay/delay_idle.txt b/V2/delay/delay_idle.txt new file mode 100644 index 0000000..d35eb49 --- /dev/null +++ b/V2/delay/delay_idle.txt @@ -0,0 +1,100 @@ + 1000000 74885 + 2000000 70188 + 3000000 100960 + 4000000 96993 + 5000000 97920 + 6000000 95671 + 7000000 95193 + 8000000 96590 + 9000000 93091 + 10000000 99800 + 11000000 97447 + 12000000 604203 + 13000000 104094 + 14000000 95803 + 15000000 95638 + 16000000 102138 + 17000000 102025 + 18000000 91546 + 19000000 96641 + 20000000 99028 + 21000000 120893 + 22000000 100362 + 23000000 96186 + 24000000 97427 + 25000000 136011 + 26000000 97303 + 27000000 106304 + 28000000 101138 + 29000000 107326 + 30000000 98307 + 31000000 102672 + 32000000 126308 + 33000000 96300 + 34000000 98373 + 35000000 95499 + 36000000 96948 + 37000000 100012 + 38000000 145522 + 39000000 103847 + 40000000 99775 + 41000000 97942 + 42000000 100953 + 43000000 145006 + 44000000 100518 + 45000000 97123 + 46000000 97738 + 47000000 163093 + 48000000 96574 + 49000000 99272 + 50000000 102283 + 51000000 141284 + 52000000 110285 + 53000000 98504 + 54000000 99068 + 55000000 105413 + 56000000 116444 + 57000000 94664 + 58000000 106010 + 59000000 96990 + 60000000 116771 + 61000000 105616 + 62000000 101075 + 63000000 108201 + 64000000 100692 + 65000000 97401 + 66000000 96037 + 67000000 156027 + 68000000 101695 + 69000000 100123 + 70000000 96780 + 71000000 97292 + 72000000 98376 + 73000000 101387 + 74000000 95961 + 75000000 98504 + 76000000 100942 + 77000000 97391 + 78000000 100610 + 79000000 95913 + 80000000 96685 + 81000000 96468 + 82000000 162291 + 83000000 138063 + 84000000 97220 + 85000000 96690 + 86000000 103070 + 87000000 96431 + 88000000 102827 + 89000000 132035 + 90000000 97650 + 91000000 101599 + 92000000 96850 + 93000000 105641 + 94000000 100006 + 95000000 96558 + 96000000 96290 + 97000000 99299 + 98000000 97207 + 99000000 96728 +100000000 99478 diff --git a/V2/delay/delay_idle_rt.png b/V2/delay/delay_idle_rt.png new file mode 100644 index 0000000..66b6206 Binary files /dev/null and b/V2/delay/delay_idle_rt.png differ diff --git a/V2/delay/delay_idle_rt.txt b/V2/delay/delay_idle_rt.txt new file mode 100644 index 0000000..c1fcc6d --- /dev/null +++ b/V2/delay/delay_idle_rt.txt @@ -0,0 +1,100 @@ + 1000000 16656 + 2000000 25916 + 3000000 21532 + 4000000 21365 + 5000000 28073 + 6000000 61812 + 7000000 25969 + 8000000 22677 + 9000000 28709 + 10000000 44480 + 11000000 47542 + 12000000 44199 + 13000000 26011 + 14000000 50844 + 15000000 24220 + 16000000 47490 + 17000000 30084 + 18000000 22418 + 19000000 24543 + 20000000 130157 + 21000000 87386 + 22000000 28783 + 23000000 41480 + 24000000 34803 + 25000000 51356 + 26000000 115667 + 27000000 57116 + 28000000 25699 + 29000000 27147 + 30000000 25419 + 31000000 25408 + 32000000 25971 + 33000000 25752 + 34000000 27513 + 35000000 22138 + 36000000 25356 + 37000000 24461 + 38000000 24919 + 39000000 26107 + 40000000 27034 + 41000000 27025 + 42000000 48784 + 43000000 188304 + 44000000 65535 + 45000000 72815 + 46000000 81399 + 47000000 89305 + 48000000 72733 + 49000000 27411 + 50000000 27557 + 51000000 101504 + 52000000 26026 + 53000000 25078 + 54000000 25693 + 55000000 22349 + 56000000 26401 + 57000000 27381 + 58000000 27996 + 59000000 23610 + 60000000 28079 + 61000000 22913 + 62000000 23371 + 63000000 28777 + 64000000 26476 + 65000000 27091 + 66000000 24528 + 67000000 23684 + 68000000 23675 + 69000000 22883 + 70000000 24904 + 71000000 26925 + 72000000 22332 + 73000000 24405 + 74000000 26530 + 75000000 23811 + 76000000 26094 + 77000000 22854 + 78000000 24511 + 79000000 22833 + 80000000 31417 + 81000000 21719 + 82000000 23324 + 83000000 26803 + 84000000 26585 + 85000000 26437 + 86000000 29864 + 87000000 26000 + 88000000 28438 + 89000000 28689 + 90000000 22794 + 91000000 23148 + 92000000 22096 + 93000000 26096 + 94000000 27233 + 95000000 25661 + 96000000 24244 + 97000000 25797 + 98000000 22609 + 99000000 25673 +100000000 26861 diff --git a/V2/delay/delay_load.png b/V2/delay/delay_load.png new file mode 100644 index 0000000..ab20456 Binary files /dev/null and b/V2/delay/delay_load.png differ diff --git a/V2/delay/delay_load.txt b/V2/delay/delay_load.txt new file mode 100644 index 0000000..3e35aaf --- /dev/null +++ b/V2/delay/delay_load.txt @@ -0,0 +1,100 @@ + 1000000 10251030 + 2000000 81073 + 3000000 75124 + 4000000 74646 + 5000000 63594 + 6000000 74833 + 7000000 72323 + 8000000 75230 + 9000000 75063 + 10000000 73386 + 11000000 78688 + 12000000 76335 + 13000000 74814 + 14000000 76106 + 15000000 79221 + 16000000 72074 + 17000000 77377 + 18000000 113772 + 19000000 86679 + 20000000 81460 + 21000000 78170 + 22000000 85867 + 23000000 78670 + 24000000 78711 + 25000000 73493 + 26000000 73848 + 27000000 85347 + 28000000 77889 + 29000000 83868 + 30000000 71202 + 31000000 79993 + 32000000 72849 + 33000000 84765 + 34000000 95432 + 35000000 86151 + 36000000 82703 + 37000000 85662 + 38000000 82266 + 39000000 87048 + 40000000 76569 + 41000000 137860 + 42000000 74517 + 43000000 75653 + 44000000 77154 + 45000000 80841 + 46000000 74633 + 47000000 85665 + 48000000 297163 + 49000000 78457 + 50000000 86051 + 51000000 68436 + 52000000 75406 + 53000000 387268 + 54000000 84187 + 55000000 83396 + 56000000 76563 + 57000000 82334 + 58000000 83886 + 59000000 283875 + 60000000 73294 + 61000000 76200 + 62000000 78482 + 63000000 88784 + 64000000 77055 + 65000000 79389 + 66000000 115212 + 67000000 87911 + 68000000 79776 + 69000000 83620 + 70000000 91839 + 71000000 84277 + 72000000 74006 + 73000000 78058 + 74000000 81886 + 75000000 85627 + 76000000 79419 + 77000000 87691 + 78000000 85806 + 79000000 78192 + 80000000 74693 + 81000000 79631 + 82000000 94621 + 83000000 76486 + 84000000 72257 + 85000000 78811 + 86000000 88280 + 87000000 78009 + 88000000 104926 + 89000000 78459 + 90000000 83397 + 91000000 78648 + 92000000 67649 + 93000000 79722 + 94000000 78514 + 95000000 79025 + 96000000 67974 + 97000000 78225 + 98000000 78944 + 99000000 78830 +100000000 67622 diff --git a/V2/delay/delay_load_rt.png b/V2/delay/delay_load_rt.png new file mode 100644 index 0000000..607a0d8 Binary files /dev/null and b/V2/delay/delay_load_rt.png differ diff --git a/V2/delay/delay_load_rt.txt b/V2/delay/delay_load_rt.txt new file mode 100644 index 0000000..aee26aa --- /dev/null +++ b/V2/delay/delay_load_rt.txt @@ -0,0 +1,100 @@ + 1000000 22281 + 2000000 15345 + 3000000 14709 + 4000000 13867 + 5000000 14377 + 6000000 28221 + 7000000 37482 + 8000000 12732 + 9000000 21993 + 10000000 15681 + 11000000 27859 + 12000000 23578 + 13000000 23828 + 14000000 23871 + 15000000 22037 + 16000000 20413 + 17000000 23163 + 18000000 18153 + 19000000 23404 + 20000000 18447 + 21000000 24166 + 22000000 22385 + 23000000 28885 + 24000000 23510 + 25000000 21313 + 26000000 27656 + 27000000 18063 + 28000000 26386 + 29000000 18044 + 30000000 19023 + 31000000 19222 + 32000000 18534 + 33000000 23941 + 34000000 35909 + 35000000 18869 + 36000000 18025 + 37000000 36505 + 38000000 23891 + 39000000 19246 + 40000000 18246 + 41000000 24433 + 42000000 17966 + 43000000 27591 + 44000000 18935 + 45000000 20436 + 46000000 22770 + 47000000 19061 + 48000000 19833 + 49000000 24197 + 50000000 23719 + 51000000 19751 + 52000000 24636 + 53000000 19470 + 54000000 24147 + 55000000 27940 + 56000000 27722 + 57000000 18962 + 58000000 24368 + 59000000 19932 + 60000000 20911 + 61000000 19859 + 62000000 19745 + 63000000 24214 + 64000000 19048 + 65000000 25497 + 66000000 18716 + 67000000 27456 + 68000000 20415 + 69000000 23582 + 70000000 26332 + 71000000 20177 + 72000000 25270 + 73000000 19532 + 74000000 25042 + 75000000 24668 + 76000000 25543 + 77000000 33971 + 78000000 35887 + 79000000 46503 + 80000000 45504 + 81000000 52368 + 82000000 23348 + 83000000 36568 + 84000000 16037 + 85000000 16548 + 86000000 16017 + 87000000 37882 + 88000000 14955 + 89000000 22341 + 90000000 23477 + 91000000 14197 + 92000000 15749 + 93000000 22822 + 94000000 15521 + 95000000 45511 + 96000000 34095 + 97000000 49033 + 98000000 53501 + 99000000 36409 +100000000 37909 diff --git a/V2/delay/render.sh b/V2/delay/render.sh new file mode 100755 index 0000000..91142a6 --- /dev/null +++ b/V2/delay/render.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +set -o xtrace + +SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) + +cd "${SCRIPT_DIR}" && gnuplot -c sleep_delay.gp + +while IFS= read -r -d '' f; do + output=$(echo "$f" | sed -E 's/\.eps$/.png/') + convert -density 300 "eps2:${f}" "$output" +done < <(find "${SCRIPT_DIR}" -name '*.eps' -print0) diff --git a/V2/delay/sleep_delay.gp b/V2/delay/sleep_delay.gp new file mode 100644 index 0000000..a5bd96f --- /dev/null +++ b/V2/delay/sleep_delay.gp @@ -0,0 +1,20 @@ +set title "{/=20 nanosleep delays}" +set terminal postscript eps enhanced +set xlabel "{/=20Period to sleep [nanoseconds]}" +set ylabel "{/=20Measured delay [nanoseconds]}" +set grid +set autoscale +set style data lines +show style data + +set output 'delay_idle.eps' +plot 'delay_idle.txt' using ($1):($2) title "{/=17 Load: no, RT: no}" lw 6 + +set output 'delay_load.eps' +plot 'delay_load.txt' using ($1):($2) title "{/=17 Load: yes, RT: no}" lw 6 + +set output 'delay_idle_rt.eps' +plot 'delay_idle_rt.txt' using ($1):($2) title "{/=17 Load: no, RT: yes}" lw 6 + +set output 'delay_load_rt.eps' +plot 'delay_load_rt.txt' using ($1):($2) title "{/=17 Load: yes, RT: yes}" lw 6 diff --git a/V2/sleep/Cargo.lock b/V2/sleep/Cargo.lock new file mode 100644 index 0000000..d352971 --- /dev/null +++ b/V2/sleep/Cargo.lock @@ -0,0 +1,62 @@ +[root] +name = "sleep" +version = "0.1.0" +dependencies = [ + "argparse 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "argparse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libc" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "redox_syscall" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "time" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum argparse 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37bb99f5e39ee8b23b6e227f5b8f024207e8616f44aa4b8c76ecd828011667ef" +"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +"checksum libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "88ee81885f9f04bff991e306fea7c1c60a5f0f9e409e99f6b40e3311a3363135" +"checksum redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "29dbdfd4b9df8ab31dec47c6087b7b13cbf4a776f335e4de8efba8288dda075b" +"checksum time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "211b63c112206356ef1ff9b19355f43740fc3f85960c598a93d3a3d3ba7beade" +"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" +"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/V2/sleep/Cargo.toml b/V2/sleep/Cargo.toml new file mode 100644 index 0000000..48785e9 --- /dev/null +++ b/V2/sleep/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "sleep" +version = "0.1.0" +authors = ["Simon Wörner "] + +[dependencies] +argparse = ">=0.2.1" +libc = ">=0.2" +time = ">=0.1.36" diff --git a/V2/sleep/src/lib.rs b/V2/sleep/src/lib.rs new file mode 100644 index 0000000..143e7a5 --- /dev/null +++ b/V2/sleep/src/lib.rs @@ -0,0 +1,80 @@ +extern crate libc; + +use std::time::Duration; + +#[cfg(target_os = "linux")] +fn clock_nanosleep(clk_id: libc::clockid_t, + flags: libc::c_int, + rqtp: *const libc::timespec, + rmtp: *mut libc::timespec) + -> libc::c_int { + unsafe { libc::clock_nanosleep(clk_id, flags, rqtp as *const _, rmtp as *mut _) } +} + +#[cfg(target_os = "macos")] +fn nanosleep(rqtp: *const libc::timespec, rmtp: *mut libc::timespec) -> libc::c_int { + unsafe { libc::nanosleep(rqtp as *const _, rmtp as *mut _) } +} + +/// Sleeps for the given duration. +/// +/// Uses `clock_nanosleep` on linux and `nanosleep` on darwin. +pub fn sleep(duration: Duration) -> Result { + let ts = duration_to_timespec(duration); + let mut remain = libc::timespec { + tv_sec: 0, + tv_nsec: 0, + }; + + #[cfg(target_os = "linux")] + let ret = clock_nanosleep(libc::CLOCK_MONOTONIC, 0, &ts, &mut remain); + + #[cfg(target_os = "macos")] + let ret = nanosleep(&ts, &mut remain); + + if ret == 0 { + Ok(timespec_to_duration(remain)) + } else { + Err(ret) + } +} + +fn duration_to_timespec(duration: Duration) -> libc::timespec { + libc::timespec { + tv_sec: duration.as_secs() as libc::time_t, + tv_nsec: duration.subsec_nanos() as libc::c_long, + } +} + +fn timespec_to_duration(timespec: libc::timespec) -> Duration { + Duration::new(timespec.tv_sec as u64, timespec.tv_nsec as u32) +} + +/// Set scheduler policy and priority for process with given pid. +/// +/// If `pid` equals zero, the policy of the calling process will be set. +/// +/// # Examples +/// +/// ```rust +/// // set *round-robin* policy (default) and priority 99 (realtime) for own process +/// set_scheduler(0, libc::SCHED_RR, 99); +/// ``` +#[cfg(target_os = "linux")] +pub fn set_scheduler(pid: libc::pid_t, policy: libc::c_int, priority: libc::c_int) -> libc::c_int { + let param = libc::sched_param { sched_priority: priority }; + unsafe { libc::sched_setscheduler(pid, policy, ¶m) } +} + +/// Set scheduler *round-robin* policy (default) and priority for own process. +/// +/// # Examples +/// +/// ```rust +/// // set *round-robin* policy (default) and priority 99 (realtime) +/// set_priority(99); +/// ``` +#[cfg(target_os = "linux")] +pub fn set_priority(priority: i32) -> libc::c_int { + set_scheduler(0, libc::SCHED_RR, priority) +} diff --git a/V2/sleep/src/main.rs b/V2/sleep/src/main.rs new file mode 100644 index 0000000..7ed1183 --- /dev/null +++ b/V2/sleep/src/main.rs @@ -0,0 +1,152 @@ +#![feature(step_by)] +extern crate argparse; +extern crate sleep; +extern crate time; + +use std::io::prelude::*; +use std::fs::File; +use std::path::Path; +use std::time::Duration; + +use argparse::{ArgumentParser, Print, Store}; +use sleep::sleep; +use time::precise_time_ns; + +#[cfg(target_os = "linux")] +use argparse::StoreTrue; + +#[cfg(target_os = "linux")] +use sleep::set_priority; + +fn duration_from_ns(duration_ns: u64) -> Duration { + Duration::new(duration_ns / 1_000_000_000, + (duration_ns % 1_000_000_000) as u32) +} +fn duration_to_ns(duration: Duration) -> u64 { + duration.as_secs() * 1_000_000_000u64 + duration.subsec_nanos() as u64 +} + +fn measure_duration(sleep_duration: Duration) -> Duration { + let start = precise_time_ns(); + let _remain = sleep(sleep_duration); + let end = precise_time_ns(); + + #[cfg(debug_assertions)] + println!("remain = {:?}", _remain); + + let duration = end - start; + let duration = duration_from_ns(duration); + + #[cfg(debug_assertions)] + println!("duration = {:?}", duration); + + duration +} + +fn measure_delay(sleep_duration: Duration) -> (Duration, Duration) { + let duration = measure_duration(sleep_duration); + let delay = duration - sleep_duration; + + #[cfg(debug_assertions)] + println!("delay = {:?}", delay); + + (duration, delay) +} + +fn measure_delay_loop(sleep_duration: Duration, count: u64) -> Vec<(Duration, Duration)> { + println!("Starting measurment with period {}s {}ns for {} loops", + sleep_duration.as_secs(), + sleep_duration.subsec_nanos(), + count); + let mut data: Vec<(Duration, Duration)> = Vec::with_capacity(count as usize); + + for _ in 0..count { + let (duration, delay) = measure_delay(sleep_duration); + data.push((duration, delay)); + + #[cfg(debug_assertions)] + print_delay(duration, delay); + } + + data +} + +fn print_delay(duration: Duration, delay: Duration) { + println!("value: {} s {} ns\tdelay: {} s {} ns\trelativ delay = {:.2}%\traw_data: {:?}", + duration.as_secs(), + duration.subsec_nanos(), + delay.as_secs(), + delay.subsec_nanos(), + (duration_to_ns(delay) * 100) as f64 / duration_to_ns(duration) as f64, + delay); +} + +fn main() { + let mut min: u64 = 1_000_000; + let mut max: u64 = 100_000_000; + let mut step: u64 = 1_000_000; + let mut count: u64 = 100; + let mut output: String = "".to_string(); + let mut file: Option = None; + + #[cfg(target_os = "linux")] + let mut realtime: bool = false; + + #[cfg(target_os = "macos")] + let realtime: bool = false; + + { + let mut ap = ArgumentParser::new(); + ap.set_description(env!("CARGO_PKG_DESCRIPTION")); + ap.refer(&mut min).add_option(&["--min"], Store, "Sleep period start"); + ap.refer(&mut max).add_option(&["--max"], Store, "Sleep period end"); + ap.refer(&mut step).add_option(&["--step"], Store, "Sleep period step size"); + ap.refer(&mut count).add_option(&["--loop"], Store, "Count of measurements per period"); + #[cfg(target_os = "linux")] + ap.refer(&mut realtime).add_option(&["--rt"], StoreTrue, "Set realtime priority"); + ap.refer(&mut output).add_option(&["-o", "--out"], Store, "Output file"); + ap.add_option(&["-V", "--version"], + Print(env!("CARGO_PKG_VERSION").to_string()), + "Show version"); + ap.parse_args_or_exit(); + } + + if realtime { + #[cfg(target_os = "linux")] + let ret = set_priority(99); + + #[cfg(target_os = "macos")] + let ret = 0; + + if ret != 0 { + panic!("Set realtime priority failed."); + } + } + + if output != "" { + file = Some(File::create(Path::new(output.as_str())).expect(format!("Open file '{}' failed", + output) + .as_str())); + } + + for duration in (min..max + 1).step_by(step) { + let data = measure_delay_loop(duration_from_ns(duration), count); + let max_delay = data.iter().max().expect("Max delay not found"); + + #[cfg(debug_assertions)] + println!("max_delay = {:?}", max_delay); + + print_delay(max_delay.0, max_delay.1); + + match file.as_ref() { + Some(mut f) => { + let value = format!("{: >9} {}\n", duration, duration_to_ns(max_delay.1)); + f.write_all(value.as_bytes()).expect(format!("Write value '{}' to '{}' file failed", + value, + output) + .as_str()); + } + None => {} + } + } +} diff --git a/ci/run-cargo-test.sh b/ci/run-cargo-test.sh new file mode 100755 index 0000000..d5d7d00 --- /dev/null +++ b/ci/run-cargo-test.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +ERROR=0 + +while IFS= read -r -d '' f; do + echo "run 'cargo test' with ${f}" + cargo test --manifest-path="${f}" + + if [[ $? -ne 0 ]]; then + ERROR=1 + fi +done < <(find . -type f -name 'Cargo.toml' -print0) + +exit ${ERROR} diff --git a/ci/run-rustfmt.sh b/ci/run-rustfmt.sh new file mode 100755 index 0000000..37403d1 --- /dev/null +++ b/ci/run-rustfmt.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +ERROR=0 + +while IFS= read -r -d '' f; do + echo "${f}" + + if [ "$(rustfmt --write-mode=diff "$f")" != $'' ] ; then + ERROR=1 + fi +done < <(find . -type f -name '*.rs' -print0) + +exit ${ERROR} diff --git a/ci/run-shellcheck.sh b/ci/run-shellcheck.sh new file mode 100755 index 0000000..4a2de49 --- /dev/null +++ b/ci/run-shellcheck.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +find . -type f -name '*.sh' -print0 | xargs -n 1 -0 shellcheck --color