aboutsummaryrefslogtreecommitdiffstats
path: root/bin/mtdag.c
diff options
context:
space:
mode:
Diffstat (limited to 'bin/mtdag.c')
-rw-r--r--bin/mtdag.c291
1 files changed, 291 insertions, 0 deletions
diff --git a/bin/mtdag.c b/bin/mtdag.c
new file mode 100644
index 0000000..adf6d8d
--- /dev/null
+++ b/bin/mtdag.c
@@ -0,0 +1,291 @@
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#include <string.h>
15#include <limits.h>
16#include <sys/mman.h>
17#include <sys/stat.h>
18#include <fcntl.h>
19#include <unistd.h>
20/* Include gettid() */
21#include <sys/types.h>
22
23/* Include threading support. */
24#include <pthread.h>
25
26/* Include the LITMUS^RT API.*/
27#include "litmus.h"
28#include "color_shm.h"
29#include "asm/cycles.h"
30
31#define PERIOD 100
32#define RELATIVE_DEADLINE 100
33#define EXEC_COST 10
34
35/* Let's create 10 threads in the example,
36 * for a total utilization of 1.
37 */
38#define NUM_THREADS 2
39
40/* The information passed to each thread. Could be anything. */
41struct thread_context {
42 int id;
43 int cpu;
44 int job_no;
45 char* shm1;
46 char* shm2;
47 char* shm3;
48};
49
50/* The real-time thread program. Doesn't have to be the same for
51 * all threads. Here, we only have one that will invoke job().
52 */
53void* rt_thread(void *tcontext);
54
55/* Declare the periodically invoked job.
56 * Returns 1 -> task should exit.
57 * 0 -> task should continue.
58 */
59int job(struct thread_context *tcx);
60
61
62/* Catch errors.
63 */
64#define CALL( exp ) do { \
65 int ret; \
66 ret = exp; \
67 if (ret != 0) \
68 fprintf(stderr, "%s failed: %m\n", #exp);\
69 else \
70 fprintf(stderr, "%s ok.\n", #exp); \
71 } while (0)
72
73
74/* Basic setup is the same as in the single-threaded example. However,
75 * we do some thread initiliazation first before invoking the job.
76 */
77int main(int argc, char** argv)
78{
79 int i;
80 struct thread_context ctx[NUM_THREADS];
81 pthread_t task[NUM_THREADS];
82 char *shm1;
83 char *shm2;
84 char *shm3;
85 struct color_ioctl_cmd shm_info;
86 struct color_ioctl_offset shm_offset;
87 /* The task is in background mode upon startup. */
88
89
90 /*****
91 * 1) Command line paramter parsing would be done here.
92 */
93
94
95
96 /*****
97 * 2) Work environment (e.g., global data structures, file data, etc.) would
98 * be setup here.
99 */
100
101 shm_info.color = 0x00000001;
102 shm_info.bank = 0x00000020;
103 shm_offset.offset = 0;
104 shm_offset.lock = 1;
105
106 shm1 = (char*)color_mmap(1024, shm_info, shm_offset);
107 if (!shm1) {
108 printf("color mmap failed.\n");
109 exit(-1);
110 }
111 else {
112 printf("Mapped vaddr = %p\n", shm1);
113 }
114
115 shm_info.color = 0x00000003;
116 shm_offset.offset = 1024;
117 shm2 = (char*)color_mmap(4096, shm_info, shm_offset);
118 if (!shm2) {
119 printf("color mmap failed.\n");
120 exit(-1);
121 }
122 else {
123 printf("Mapped vaddr = %p\n", shm2);
124 }
125
126 mlockall(MCL_CURRENT | MCL_FUTURE);
127 /*****
128 * 3) Initialize LITMUS^RT.
129 * Task parameters will be specified per thread.
130 */
131 init_litmus();
132
133
134 /*****
135 * 4) Launch threads.
136 */
137 for (i = 0; i < NUM_THREADS; i++) {
138 ctx[i].id = i;
139 ctx[i].cpu = 0;
140 ctx[i].job_no = 0;
141 ctx[i].shm1 = shm1;
142 ctx[i].shm3 = shm2;
143 ctx[i].shm2 = shm3;
144 pthread_create(task + i, NULL, rt_thread, (void *) (ctx + i));
145 }
146
147
148 /*****
149 * 5) Wait for RT threads to terminate.
150 */
151 for (i = 0; i < NUM_THREADS; i++)
152 pthread_join(task[i], NULL);
153
154
155 /*****
156 * 6) Clean up, maybe print results and stats, and exit.
157 */
158 return 0;
159}
160
161
162
163/* A real-time thread is very similar to the main function of a single-threaded
164 * real-time app. Notice, that init_rt_thread() is called to initialized per-thread
165 * data structures of the LITMUS^RT user space libary.
166 */
167void* rt_thread(void *tcontext)
168{
169 int do_exit;
170 struct thread_context *ctx = (struct thread_context *) tcontext;
171 struct rt_task param;
172 int ret;
173 struct mc2_task mc2_param;
174 struct reservation_config res_config;
175
176 /* Set up task parameters */
177 init_rt_task_param(&param);
178 param.exec_cost = ms2ns(EXEC_COST);
179 param.period = ms2ns(PERIOD);
180 param.relative_deadline = ms2ns(RELATIVE_DEADLINE*(ctx->id+1));
181
182 /* What to do in the case of budget overruns? */
183 param.budget_policy = NO_ENFORCEMENT;
184
185 /* The task class parameter is ignored by most plugins. */
186 param.cls = RT_CLASS_SOFT;
187
188 /* The priority parameter is only used by fixed-priority plugins. */
189 param.priority = LITMUS_LOWEST_PRIORITY;
190
191 /* Make presence visible. */
192 printf("RT Thread %d active.\n", ctx->id);
193
194 /* reservation config */
195 res_config.id = gettid();
196 res_config.polling_params.budget = ms2ns(EXEC_COST+1);
197 res_config.polling_params.period = param.period;
198 res_config.polling_params.offset = 0;
199 res_config.polling_params.relative_deadline = 0;
200 res_config.priority = LITMUS_MAX_PRIORITY;
201 res_config.cpu = ctx->cpu;
202 mc2_param.crit = CRIT_LEVEL_A;
203 mc2_param.res_id = gettid();
204 /*****
205 * 1) Initialize real-time settings.
206 */
207 CALL( init_rt_thread() );
208
209 ret = reservation_create(PERIODIC_POLLING, &res_config);
210 if (ret < 0) {
211 printf("reservation failed.\n");
212 return NULL;
213 }
214
215 /* To specify a partition, do
216 *
217 * param.cpu = CPU;
218 * be_migrate_to(CPU);
219 *
220 * where CPU ranges from 0 to "Number of CPUs" - 1 before calling
221 * set_rt_task_param().
222 */
223 param.cpu = ctx->cpu;
224 ret = be_migrate_to_cpu(ctx->cpu);
225 if (ret < 0) {
226 printf("RT Thread %d fails to migrate to CPU%d\n", ctx->id, ctx->cpu);
227 return NULL;
228 }
229 CALL( set_rt_task_param(gettid(), &param) );
230
231 CALL( set_mc2_task_param(gettid(), &mc2_param) );
232 /*****
233 * 2) Transition to real-time mode.
234 */
235 CALL( task_mode(LITMUS_RT_TASK) );
236
237 /* The task is now executing as a real-time task if the call didn't fail.
238 */
239
240
241
242 /*****
243 * 3) Invoke real-time jobs.
244 */
245 do {
246 /* Wait until the next job is released. */
247 sleep_next_period();
248 /* Invoke job. */
249 do_exit = job(ctx);
250 } while (!do_exit);
251
252
253
254 /*****
255 * 4) Transition to background mode.
256 */
257 CALL( task_mode(BACKGROUND_TASK) );
258 reservation_destroy(gettid(), res_config.cpu);
259
260 return NULL;
261}
262
263
264
265int job(struct thread_context *tcx)
266{
267 int i;
268 char* buf1 = tcx->shm1;
269 char* buf2 = tcx->shm2;
270 char* buf3 = tcx->shm3;
271 char tmp = 0;
272 /* Do real-time calculation. */
273 printf("Task %d Job %d executinig\n", tcx->id, tcx->job_no);
274
275 if (tcx->id == 0) {
276 printf("READ\n");
277 for (i=0; i<600; i++) {
278 char t = buf1[i];
279 printf("%x ", t);
280 }
281 printf("\n");
282
283 ;
284 }
285 //test_call(0);
286 tcx->job_no++;
287 if (tcx->job_no == 10)
288 return 1;
289 /* Don't exit. */
290 return 0;
291}