[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