/* based_mt_task.c -- A basic multi-threaded real-time task skeleton.
*
* This (by itself useless) task demos how to setup a multi-threaded LITMUS^RT
* real-time task. Familiarity with the single threaded example (base_task.c)
* is assumed.
*
* Currently, liblitmus still lacks automated support for real-time
* tasks, but internaly it is thread-safe, and thus can be used together
* with pthreads.
*/
#include <stdio.h>
#include <stdlib.h>
/* Include gettid() */
#include <sys/types.h>
/* Include threading support. */
#include <pthread.h>
/* Include the LITMUS^RT API.*/
#include "litmus.h"
#define PERIOD 100
#define REL_DEADLINE 100
#define EXEC_COST 10
/* Let's create 10 threads in the example,
* for a total utilization of 1.
*/
#define NUM_THREADS 10
/* The information passed to each thread. Could be anything. */
struct thread_context {
int id;
};
/* The real-time thread program. Doesn't have to be the same for
* all threads. Here, we only have one that will invoke job().
*/
void* rt_thread(void *tcontext);
/* Declare the periodically invoked job.
* Returns 1 -> task should exit.
* 0 -> task should continue.
*/
int job(void);
/* 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)
/* Basic setup is the same as in the single-threaded example. However,
* we do some thread initiliazation first before invoking the job.
*/
int main(int argc, char** argv)
{
int i;
struct thread_context ctx[NUM_THREADS];
pthread_t task[NUM_THREADS];
/* 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) Initialize LITMUS^RT.
* Task parameters will be specified per thread.
*/
init_litmus();
/*****
* 4) Launch threads.
*/
for (i = 0; i < NUM_THREADS; i++) {
ctx[i].id = i;
pthread_create(task + i, NULL, rt_thread, (void *) (ctx + i));
}
/*****
* 5) Wait for RT threads to terminate.
*/
for (i = 0; i < NUM_THREADS; i++)
pthread_join(task[i], NULL);
/*****
* 6) Clean up, maybe print results and stats, and exit.
*/
return 0;
}
/* A real-time thread is very similar to the main function of a single-threaded
* real-time app. Notice, that init_rt_thread() is called to initialized per-thread
* data structures of the LITMUS^RT user space libary.
*/
void* rt_thread(void *tcontext)
{
int do_exit;
struct thread_context *ctx = (struct thread_context *) tcontext;
/* Make presence visible. */
printf("RT Thread %d active.\n", ctx->id);
/*****
* 1) Initialize real-time settings.
*/
CALL( init_rt_thread() );
CALL( sporadic_global(EXEC_COST, PERIOD, REL_DEADLINE) );
/*****
* 2) 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.
*/
/*****
* 3) Invoke real-time jobs.
*/
do {
/* Wait until the next job is released. */
sleep_next_period();
/* Invoke job. */
do_exit = job();
} while (!do_exit);
/*****
* 4) Transition to background mode.
*/
CALL( task_mode(BACKGROUND_TASK) );
return NULL;
}
int job(void)
{
/* Do real-time calculation. */
/* Don't exit. */
return 0;
}