[LITMUS^RT] [PATCH 2/2] Add a task skeleton that uses the new modules functionality

Manohar Vanga mvanga at mpi-sws.org
Tue Feb 4 03:20:27 CET 2014


This patch adds a sample task skeleton that can be used as the
basis for developing LITMUS^RT tasks in independent folders.
The Makefile assumes that the path to liblitmus is available in
the $DIR_LIBLITMUS environment variable.

Signed-off-by: Manohar Vanga <mvanga at mpi-sws.org>
---
 task-skeleton/Makefile |   11 ++++
 task-skeleton/task.c   |  162 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 173 insertions(+)
 create mode 100644 task-skeleton/Makefile
 create mode 100644 task-skeleton/task.c

diff --git a/task-skeleton/Makefile b/task-skeleton/Makefile
new file mode 100644
index 0000000..91a3519
--- /dev/null
+++ b/task-skeleton/Makefile
@@ -0,0 +1,11 @@
+obj-m += mod_task
+obj-mod_task += task.o
+
+export obj-m
+export obj-mod_task
+
+all:
+	make -C $(DIR_LIBLITMUS) M=$(PWD) modules
+
+clean:
+	rm $(obj-m) $(foreach obj, $(obj-m), $(obj-$(obj)))
diff --git a/task-skeleton/task.c b/task-skeleton/task.c
new file mode 100644
index 0000000..58f22c7
--- /dev/null
+++ b/task-skeleton/task.c
@@ -0,0 +1,162 @@
+/* Based on liblitmus/bin/base_task.c -- A basic real-time task skeleton. 
+ *
+ * This (by itself useless) task demos how to setup a 
+ * single-threaded LITMUS^RT real-time task.
+ */
+
+/* First, we include standard headers.
+ * Generally speaking, a LITMUS^RT real-time task can perform any
+ * system call, etc., but no real-time guarantees can be made if a
+ * system call blocks. To be on the safe side, only use I/O for debugging
+ * purposes and from non-real-time sections.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Second, we include the LITMUS^RT user space library header.
+ * This header, part of liblitmus, provides the user space API of
+ * LITMUS^RT.
+ */
+#include "litmus.h"
+
+/* Next, we define period and execution cost to be constant. 
+ * These are only constants for convenience in this example, they can be
+ * determined at run time, e.g., from command line parameters.
+ *
+ * These are in milliseconds.
+ */
+#define PERIOD            100
+#define RELATIVE_DEADLINE 100
+#define EXEC_COST         10
+
+/* Catch errors.
+ */
+#define CALL( exp ) do { \
+		int ret; \
+		ret = exp; \
+		if (ret != 0) \
+			fprintf(stderr, "%s failed: %m\n", #exp);\
+		else \
+			fprintf(stderr, "%s ok.\n", #exp); \
+	} while (0)
+
+
+/* Declare the periodically invoked job. 
+ * Returns 1 -> task should exit.
+ *         0 -> task should continue.
+ */
+int job(void);
+
+/* typically, main() does a couple of things: 
+ * 	1) parse command line parameters, etc.
+ *	2) Setup work environment.
+ *	3) Setup real-time parameters.
+ *	4) Transition to real-time mode.
+ *	5) Invoke periodic or sporadic jobs.
+ *	6) Transition to background mode.
+ *	7) Clean up and exit.
+ *
+ * The following main() function provides the basic skeleton of a single-threaded
+ * LITMUS^RT real-time task. In a real program, all the return values should be 
+ * checked for errors.
+ */
+int main(int argc, char** argv)
+{
+	int do_exit;
+	struct rt_task param;
+
+	/* Setup task parameters */
+	init_rt_task_param(&param);
+	param.exec_cost = ms2ns(EXEC_COST);
+	param.period = ms2ns(PERIOD);
+	param.relative_deadline = ms2ns(RELATIVE_DEADLINE);
+
+	/* What to do in the case of budget overruns? */
+	param.budget_policy = NO_ENFORCEMENT;
+
+	/* The task class parameter is ignored by most plugins. */
+	param.cls = RT_CLASS_SOFT;
+
+	/* The priority parameter is only used by fixed-priority plugins. */
+	param.priority = LITMUS_LOWEST_PRIORITY;
+
+	/* The task is in background mode upon startup. */
+
+
+	/*****
+	 * 1) Command line paramter parsing would be done here.
+	 */
+
+
+
+	/*****
+	 * 2) Work environment (e.g., global data structures, file data, etc.) would
+	 *    be setup here.
+	 */
+
+
+
+	/*****
+	 * 3) Setup real-time parameters. 
+	 *    In this example, we create a sporadic task that does not specify a 
+	 *    target partition (and thus is intended to run under global scheduling). 
+	 *    If this were to execute under a partitioned scheduler, it would be assigned
+	 *    to the first partition (since partitioning is performed offline).
+	 */
+	CALL( init_litmus() );
+
+	/* To specify a partition, do
+	 *
+	 * param.cpu = CPU;
+	 * be_migrate_to(CPU);
+	 *
+	 * where CPU ranges from 0 to "Number of CPUs" - 1 before calling
+	 * set_rt_task_param().
+	 */
+	CALL( set_rt_task_param(gettid(), &param) );
+
+
+	/*****
+	 * 4) Transition to real-time mode.
+	 */
+	CALL( task_mode(LITMUS_RT_TASK) );
+
+	/* The task is now executing as a real-time task if the call didn't fail. 
+	 */
+
+
+
+	/*****
+	 * 5) Invoke real-time jobs.
+	 */
+	do {
+		/* Wait until the next job is released. */
+		sleep_next_period();
+		/* Invoke job. */
+		do_exit = job();		
+	} while (!do_exit);
+
+
+	
+	/*****
+	 * 6) Transition to background mode.
+	 */
+	CALL( task_mode(BACKGROUND_TASK) );
+
+
+
+	/***** 
+	 * 7) Clean up, maybe print results and stats, and exit.
+	 */
+	return 0;
+}
+
+
+int job(void) 
+{
+	/* Do real-time calculation. */
+
+	/* Don't exit. */
+	return 0;
+}
-- 
1.7.9.5





More information about the litmus-dev mailing list