/* 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 #include /* Include gettid() */ #include /* Include threading support. */ #include /* Include the LITMUS^RT API.*/ #include "litmus.h" #define PERIOD 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) ); /***** * 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; }