diff options
| author | Bjoern B. Brandenburg <bbb@cs.unc.edu> | 2008-01-24 15:53:56 -0500 |
|---|---|---|
| committer | Bjoern B. Brandenburg <bbb@cs.unc.edu> | 2008-01-24 15:53:56 -0500 |
| commit | ea71ba9e1275495edf9b03b7109fe290d959a47a (patch) | |
| tree | fe5679ebeee00ce270c3335deb1e326a6dc6f3d2 | |
| parent | a155ee1ccb51cf8b6746bcd44ab34f258c9802e0 (diff) | |
add multi-threaded example
| -rw-r--r-- | Makefile | 5 | ||||
| -rw-r--r-- | bin/base_mt_task.c | 159 | ||||
| -rw-r--r-- | bin/base_task.c | 9 |
3 files changed, 166 insertions, 7 deletions
| @@ -6,7 +6,7 @@ LIBS= ./liblitmus.a | |||
| 6 | LIB_OBJ= litmus.o syscalls.o sched_trace.o adaptive.o edf-hsb.o task.o kernel_iface.o | 6 | LIB_OBJ= litmus.o syscalls.o sched_trace.o adaptive.o edf-hsb.o task.o kernel_iface.o |
| 7 | 7 | ||
| 8 | TARGETS = showsched iotest set_rt_mode run timeout rt_launch edfhsb liblitmus.a \ | 8 | TARGETS = showsched iotest set_rt_mode run timeout rt_launch edfhsb liblitmus.a \ |
| 9 | wait_test np_test stdump mode_test base_task | 9 | wait_test np_test stdump mode_test base_task base_mt_task |
| 10 | 10 | ||
| 11 | vpath %.h include/ | 11 | vpath %.h include/ |
| 12 | vpath %.c src/ bin/ | 12 | vpath %.c src/ bin/ |
| @@ -15,6 +15,9 @@ all: ${TARGETS} | |||
| 15 | clean: | 15 | clean: |
| 16 | rm -f *.o *~ ${TARGETS} | 16 | rm -f *.o *~ ${TARGETS} |
| 17 | 17 | ||
| 18 | base_mt_task: base_mt_task.o liblitmus.a | ||
| 19 | cc -static -pthread -o base_mt_task base_mt_task.o ${LIBS} | ||
| 20 | |||
| 18 | base_task: base_task.o liblitmus.a | 21 | base_task: base_task.o liblitmus.a |
| 19 | cc -static -o base_task base_task.o ${LIBS} | 22 | cc -static -o base_task base_task.o ${LIBS} |
| 20 | 23 | ||
diff --git a/bin/base_mt_task.c b/bin/base_mt_task.c new file mode 100644 index 0000000..096b124 --- /dev/null +++ b/bin/base_mt_task.c | |||
| @@ -0,0 +1,159 @@ | |||
| 1 | /* based_mt_task.c -- A basic multi-threaded real-time task skeleton. | ||
| 2 | * | ||
| 3 | * This (by itself useless) task demos how to setup a multi-threaded LITMUS^RT | ||
| 4 | * real-time task. Familiarity with the single threaded example (base_task.c) | ||
| 5 | * is assumed. | ||
| 6 | * | ||
| 7 | * Currently, liblitmus still lacks automated support for real-time | ||
| 8 | * tasks, but internaly it is thread-safe, and thus can be used together | ||
| 9 | * with pthreads. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <stdio.h> | ||
| 13 | #include <stdlib.h> | ||
| 14 | |||
| 15 | /* Include threading support. */ | ||
| 16 | #include <pthread.h> | ||
| 17 | |||
| 18 | /* Include the LITMUS^RT API.*/ | ||
| 19 | #include "litmus.h" | ||
| 20 | |||
| 21 | #define PERIOD 100 | ||
| 22 | #define EXEC_COST 10 | ||
| 23 | |||
| 24 | /* Let's create 10 threads in the example, | ||
| 25 | * for a total utilization of 1. | ||
| 26 | */ | ||
| 27 | #define NUM_THREADS 10 | ||
| 28 | |||
| 29 | /* The information passed to each thread. Could be anything. */ | ||
| 30 | struct thread_context { | ||
| 31 | int id; | ||
| 32 | }; | ||
| 33 | |||
| 34 | /* The real-time thread program. Doesn't have to be the same for | ||
| 35 | * all threads. Here, we only have one that will invoke job(). | ||
| 36 | */ | ||
| 37 | void* rt_thread(struct thread_context* ctx); | ||
| 38 | |||
| 39 | /* Declare the periodically invoked job. | ||
| 40 | * Returns 1 -> task should exit. | ||
| 41 | * 0 -> task should continue. | ||
| 42 | */ | ||
| 43 | int job(void); | ||
| 44 | |||
| 45 | /* Basic setup is the same as in the single-threaded example. However, | ||
| 46 | * we do some thread initiliazation first before invoking the job. | ||
| 47 | */ | ||
| 48 | int main(int argc, char** argv) | ||
| 49 | { | ||
| 50 | int i; | ||
| 51 | struct thread_context ctx[NUM_THREADS]; | ||
| 52 | pthread_t task[NUM_THREADS]; | ||
| 53 | |||
| 54 | /* The task is in background mode upon startup. */ | ||
| 55 | |||
| 56 | |||
| 57 | /***** | ||
| 58 | * 1) Command line paramter parsing would be done here. | ||
| 59 | */ | ||
| 60 | |||
| 61 | |||
| 62 | |||
| 63 | /***** | ||
| 64 | * 2) Work environment (e.g., global data structures, file data, etc.) would | ||
| 65 | * be setup here. | ||
| 66 | */ | ||
| 67 | |||
| 68 | |||
| 69 | |||
| 70 | /***** | ||
| 71 | * 3) Initialize LITMUS^RT. | ||
| 72 | * Task parameters will be specified per thread. | ||
| 73 | */ | ||
| 74 | init_litmus(); | ||
| 75 | |||
| 76 | |||
| 77 | /***** | ||
| 78 | * 4) Launch threads. | ||
| 79 | */ | ||
| 80 | for (i = 0; i < NUM_THREADS; i++) { | ||
| 81 | ctx[i].id = i; | ||
| 82 | pthread_create(task + i, NULL, rt_thread, ctx + i); | ||
| 83 | } | ||
| 84 | |||
| 85 | |||
| 86 | /***** | ||
| 87 | * 5) Wait for RT threads to terminate. | ||
| 88 | */ | ||
| 89 | for (i = 0; i < NUM_THREADS; i++) | ||
| 90 | pthread_join(task[i], NULL); | ||
| 91 | |||
| 92 | |||
| 93 | /***** | ||
| 94 | * 6) Clean up, maybe print results and stats, and exit. | ||
| 95 | */ | ||
| 96 | return 0; | ||
| 97 | } | ||
| 98 | |||
| 99 | |||
| 100 | |||
| 101 | /* A real-time thread is very similar to the main function of a single-threaded | ||
| 102 | * real-time app. Notice, that init_rt_thread() is called to initialized per-thread | ||
| 103 | * data structures of the LITMUS^RT user space libary. | ||
| 104 | */ | ||
| 105 | void* rt_thread(struct thread_context* ctx) | ||
| 106 | { | ||
| 107 | int do_exit; | ||
| 108 | |||
| 109 | /* Make presence visible. */ | ||
| 110 | printf("RT Thread %d active.\n", ctx->id); | ||
| 111 | |||
| 112 | /***** | ||
| 113 | * 1) Initialize real-time settings. | ||
| 114 | */ | ||
| 115 | init_rt_thread(); | ||
| 116 | sporadic_global(EXEC_COST, PERIOD); | ||
| 117 | |||
| 118 | |||
| 119 | |||
| 120 | /***** | ||
| 121 | * 2) Transition to real-time mode. | ||
| 122 | */ | ||
| 123 | task_mode(LITMUS_RT_TASK); | ||
| 124 | |||
| 125 | /* The task is now executing as a real-time task if the call didn't fail. | ||
| 126 | */ | ||
| 127 | |||
| 128 | |||
| 129 | |||
| 130 | /***** | ||
| 131 | * 3) Invoke real-time jobs. | ||
| 132 | */ | ||
| 133 | do { | ||
| 134 | /* Wait until the next job is released. */ | ||
| 135 | sleep_next_period(); | ||
| 136 | /* Invoke job. */ | ||
| 137 | do_exit = job(); | ||
| 138 | } while (!do_exit); | ||
| 139 | |||
| 140 | |||
| 141 | |||
| 142 | /***** | ||
| 143 | * 4) Transition to background mode. | ||
| 144 | */ | ||
| 145 | task_mode(BACKGROUND_TASK); | ||
| 146 | |||
| 147 | |||
| 148 | return NULL; | ||
| 149 | } | ||
| 150 | |||
| 151 | |||
| 152 | |||
| 153 | int job(void) | ||
| 154 | { | ||
| 155 | /* Do real-time calculation. */ | ||
| 156 | |||
| 157 | /* Don't exit. */ | ||
| 158 | return 0; | ||
| 159 | } | ||
diff --git a/bin/base_task.c b/bin/base_task.c index e5f50b1..067c088 100644 --- a/bin/base_task.c +++ b/bin/base_task.c | |||
| @@ -1,12 +1,9 @@ | |||
| 1 | /* based_task.c -- A basic real-time task skeleton. | 1 | /* based_task.c -- A basic real-time task skeleton. |
| 2 | * | 2 | * |
| 3 | * This (by itself useless) task demos how to setup LITMUS^RT real-time task. | 3 | * This (by itself useless) task demos how to setup a |
| 4 | * | 4 | * single-threaded LITMUS^RT real-time task. |
| 5 | * Compile: | ||
| 6 | * | ||
| 7 | */ | 5 | */ |
| 8 | 6 | ||
| 9 | |||
| 10 | /* First, we include standard headers. | 7 | /* First, we include standard headers. |
| 11 | * Generally speaking, a LITMUS^RT real-time task can perform any | 8 | * Generally speaking, a LITMUS^RT real-time task can perform any |
| 12 | * system call, etc., but no real-time guarantees can be made if a | 9 | * system call, etc., but no real-time guarantees can be made if a |
| @@ -118,7 +115,7 @@ int main(int argc, char** argv) | |||
| 118 | 115 | ||
| 119 | 116 | ||
| 120 | /***** | 117 | /***** |
| 121 | * 7) Clean up and exit. | 118 | * 7) Clean up, maybe print results and stats, and exit. |
| 122 | */ | 119 | */ |
| 123 | return 0; | 120 | return 0; |
| 124 | } | 121 | } |
