[bootlin/training-materials updates] master: preempt-rt: Add lab data (bc7b8139)
Maxime Chevallier
maxime.chevallier at bootlin.com
Thu Jan 5 11:17:14 CET 2023
Repository : https://github.com/bootlin/training-materials
On branch : master
Link : https://github.com/bootlin/training-materials/commit/bc7b8139b2c6c09558f89c63795cd61eadf93749
>---------------------------------------------------------------
commit bc7b8139b2c6c09558f89c63795cd61eadf93749
Author: Maxime Chevallier <maxime.chevallier at bootlin.com>
Date: Thu Jan 5 11:16:48 2023 +0100
preempt-rt: Add lab data
Signed-off-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
>---------------------------------------------------------------
bc7b8139b2c6c09558f89c63795cd61eadf93749
lab-data/preempt-rt/lab3/Makefile | 13 +++
lab-data/preempt-rt/lab3/gpiotest.c | 164 +++++++++++++++++++++++++++++++
lab-data/preempt-rt/lab3/pgflt.c | 188 ++++++++++++++++++++++++++++++++++++
3 files changed, 365 insertions(+)
diff --git a/lab-data/preempt-rt/lab3/Makefile b/lab-data/preempt-rt/lab3/Makefile
new file mode 100644
index 00000000..d1fd59c3
--- /dev/null
+++ b/lab-data/preempt-rt/lab3/Makefile
@@ -0,0 +1,13 @@
+all: pgflt gpiotest
+
+pgflt: pgflt.c
+ $(CROSS_COMPILE)gcc -O0 -o$@ $^ -lrt
+
+gpiotest: gpiotest.c
+ $(CROSS_COMPILE)gcc -O0 -o$@ $^ -lrt -lgpiod
+
+clean:
+ rm -f pgflt
+ rm -f gpiotest
+
+.PHONY: clean
diff --git a/lab-data/preempt-rt/lab3/gpiotest.c b/lab-data/preempt-rt/lab3/gpiotest.c
new file mode 100644
index 00000000..d5ee3376
--- /dev/null
+++ b/lab-data/preempt-rt/lab3/gpiotest.c
@@ -0,0 +1,164 @@
+#include <gpiod.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <malloc.h>
+#include <sys/mman.h>
+#include <time.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#ifndef CONSUMER
+#define CONSUMER "Consumer"
+#endif
+
+static void usage() {
+ printf("gpiotest <gpiochip_in> <gpio_in> <gpiochip_out> <gpio_out> [h] [p]\n");
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ struct timespec ts = { 1, 0 };
+ struct gpiod_line_event event;
+ struct gpiod_chip *input_chip, *output_chip;
+ struct gpiod_line *input_line, *output_line;
+ int i, ret;
+
+ char *input_chip_name;
+ char *output_chip_name;
+ unsigned int input_line_num;
+ unsigned int output_line_num;
+ bool save = false;
+ bool heap_save = false;
+ bool prefault = false;
+
+ struct timespec stack_ts_buffer[4096];
+ struct timespec *heap_ts_buffer;
+
+ if (argc < 5)
+ usage();
+
+ input_chip_name = argv[1];
+ input_line_num = atoi(argv[2]);
+
+ output_chip_name = argv[3];
+ output_line_num = atoi(argv[4]);
+
+ if (argc > 5) {
+ if (!strcmp(argv[5], "h"))
+ heap_save = true;
+ save = true;
+ }
+
+ if (argc > 6) {
+ if (!strcmp(argv[6], "p"))
+ prefault = true;
+ }
+
+ input_chip = gpiod_chip_open_by_name(input_chip_name);
+ if (!input_chip) {
+ perror("Open input chip failed\n");
+ ret = -1;
+ goto end;
+ }
+
+ output_chip = gpiod_chip_open_by_name(output_chip_name);
+ if (!output_chip) {
+ perror("Open output chip failed\n");
+ ret = -1;
+ goto end;
+ }
+
+ input_line = gpiod_chip_get_line(input_chip, input_line_num);
+ if (!input_line) {
+ perror("Get input line failed\n");
+ ret = -1;
+ goto close_chip;
+ }
+
+ output_line = gpiod_chip_get_line(output_chip, output_line_num);
+ if (!output_line) {
+ perror("Get input line failed\n");
+ ret = -1;
+ goto close_chip;
+ }
+
+ ret = gpiod_line_request_both_edges_events(input_line, CONSUMER);
+ if (ret < 0) {
+ perror("Request event notification failed\n");
+ ret = -1;
+ goto release_line;
+ }
+
+ ret = gpiod_line_request_output(output_line, CONSUMER, 0);
+ if (ret < 0) {
+ perror("Request event notification failed\n");
+ ret = -1;
+ goto release_line;
+ }
+
+ if (heap_save) {
+ heap_ts_buffer = malloc(4096 * sizeof(struct timespec));
+ if (!heap_ts_buffer)
+ return -1;
+ }
+
+ if (prefault) {
+ mlockall(MCL_CURRENT | MCL_FUTURE);
+ mallopt(M_TRIM_THRESHOLD, -1);
+ mallopt(M_MMAP_MAX, 0);
+
+ if (heap_save)
+ memset(heap_ts_buffer, 0, 4096 * sizeof(struct timespec));
+ else
+ memset(stack_ts_buffer, 0, sizeof(stack_ts_buffer));
+
+ }
+
+ i = 0;
+ while (true) {
+ ret = gpiod_line_event_wait(input_line, &ts);
+ if (ret < 0) {
+ perror("Wait event notification failed\n");
+ ret = -1;
+ goto release_line;
+ } else if (ret == 0) {
+ continue;
+ }
+
+ ret = gpiod_line_event_read(input_line, &event);
+ if (ret < 0) {
+ perror("Read last event notification failed\n");
+ ret = -1;
+ goto release_line;
+ }
+
+ if (save) {
+
+ if (heap_save)
+ heap_ts_buffer[i] = event.ts;
+ else
+ stack_ts_buffer[i] = event.ts;
+
+ i++;
+ if (i >= 4096)
+ i = 0;
+ }
+
+ gpiod_line_set_value(output_line,
+ event.event_type == GPIOD_LINE_EVENT_RISING_EDGE ? 1 : 0);
+
+ }
+
+ ret = 0;
+
+release_line:
+ gpiod_line_release(input_line);
+ gpiod_line_release(output_line);
+close_chip:
+ gpiod_chip_close(input_chip);
+ gpiod_chip_close(output_chip);
+end:
+ return ret;
+}
diff --git a/lab-data/preempt-rt/lab3/pgflt.c b/lab-data/preempt-rt/lab3/pgflt.c
new file mode 100644
index 00000000..3c0b58bc
--- /dev/null
+++ b/lab-data/preempt-rt/lab3/pgflt.c
@@ -0,0 +1,188 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <malloc.h>
+#include <sys/mman.h>
+#include <string.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+void timestamp(const char *msg, int val)
+{
+ static struct timespec tsl;
+ static long minfltl;
+
+ struct timespec ts;
+ unsigned long diff;
+ struct rusage r;
+ long rdiff;
+
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ getrusage(RUSAGE_SELF, &r);
+
+ if (tsl.tv_sec != 0) {
+ diff = (ts.tv_sec - tsl.tv_sec) * 1000000000;
+ diff += ts.tv_nsec - tsl.tv_nsec;
+
+ rdiff = r.ru_minflt - minfltl;
+
+ printf("% 10d ns % 5ld faults : %s", diff, rdiff, msg);
+ if (val >= 0)
+ printf(" (%d)", val);
+ printf("\n");
+ }
+
+ tsl = ts;
+ minfltl = r.ru_minflt;
+}
+
+/* 10 MiB */
+#define SIZE (10 * 1024 * 1024)
+
+void testfunc_malloc(void)
+{
+ char *p;
+
+ p = malloc(SIZE);
+ if (!p) {
+ fprintf(stderr, "MALLOC FAILED: %s:%d\n", __FILE__, __LINE__);
+ return;
+ }
+
+ memset(p, 42, SIZE);
+
+ if (p[SIZE - 1] != 42)
+ fprintf(stderr, "MEMSET FAILED: %s:%d\n", __FILE__, __LINE__);
+
+ free(p);
+}
+
+void recursive_stack(int i)
+{
+ char buf[1024];
+ if (i > 0)
+ recursive_stack(i - 1);
+}
+
+void testfunc_deepstack(void)
+{
+ char buf[1024];
+ recursive_stack(7 * 1024);
+}
+
+void prefault_stack(void)
+{
+#define STACK_SIZE (7680 * 1024) /* 7.5 MiB */
+ char buf[STACK_SIZE];
+ long pagesize;
+ int i;
+
+ pagesize = sysconf(_SC_PAGESIZE);
+
+ for (i = 0; i < STACK_SIZE; i += pagesize)
+ buf[i] = 0;
+}
+
+void prefault_heap(void)
+{
+#define HEAP_SIZE (20 * 1024 * 1024) /* 20 MiB */
+ long pagesize;
+ char *buf;
+ int i;
+
+ pagesize = sysconf(_SC_PAGESIZE);
+
+ buf = malloc(HEAP_SIZE);
+ if (!buf) {
+ fprintf(stderr, "MALLOC FAILED: %s:%d\n", __FILE__, __LINE__);
+ return;
+ }
+
+ for (i = 0; i < HEAP_SIZE; i += pagesize)
+ buf[i] = 0;
+
+ free(buf);
+}
+
+void setup_rt(unsigned int opts)
+{
+ if (opts & 0x1) {
+ if (mallopt(M_TRIM_THRESHOLD, -1) == 0) {
+ fprintf(stderr, "MALLOPT FAILED: %s:%d\n",
+ __FILE__, __LINE__);
+ }
+
+ if (mallopt(M_MMAP_MAX, 0) == 0) {
+ fprintf(stderr, "MALLOPT FAILED: %s:%d\n",
+ __FILE__, __LINE__);
+ }
+ }
+
+ if (opts & 0x2) {
+ if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
+ fprintf(stderr, "MLOCKALL FAILED: %s:%d\n",
+ __FILE__, __LINE__);
+ }
+ }
+
+ if (opts & 0x4)
+ prefault_stack();
+
+ if (opts & 0x8)
+ prefault_heap();
+}
+
+
+static void usage(const char *cmd)
+{
+ printf("usage: %s [opts-bitmask]\n", cmd);
+ printf(" opts-bits:\n");
+ printf(" 0x01 = mallopt\n");
+ printf(" 0x02 = mlockall\n");
+ printf(" 0x04 = prefault-stack\n");
+ printf(" 0x08 = prefault-heap\n");
+ printf(" 0x10 = run tests\n");
+ printf("\n");
+ printf(" 0x10 = no rt tweaks + tests\n");
+ printf(" 0x1f = full rt tweaks + tests\n");
+ printf("\n");
+}
+
+int main(int argc, char *argv[])
+{
+ unsigned int i;
+
+ if (argc != 2) {
+ usage(argv[0]);
+ return 1;
+ }
+
+ if (sscanf(argv[1], "%x", &i) != 1) {
+ usage(argv[0]);
+ return 1;
+ }
+
+ printf("options: 0x%x\n", i);
+
+ timestamp("init", -1);
+
+ setup_rt(i);
+
+ timestamp("main setup", -1);
+
+ if (i & 0x10) {
+ for (i = 0; i < 4; i++) {
+ testfunc_malloc();
+ timestamp("testfunc_malloc", i);
+ }
+
+ for (i = 0; i < 4; i++) {
+ testfunc_deepstack();
+ timestamp("testfunc_deepstack", i);
+ }
+ }
+
+ return 0;
+}
More information about the training-materials-updates
mailing list