aboutsummaryrefslogtreecommitdiffstats
path: root/bin/mtdag.c
diff options
context:
space:
mode:
Diffstat (limited to 'bin/mtdag.c')
-rw-r--r--bin/mtdag.c333
1 files changed, 333 insertions, 0 deletions
diff --git a/bin/mtdag.c b/bin/mtdag.c
new file mode 100644
index 0000000..4c6cf9a
--- /dev/null
+++ b/bin/mtdag.c
@@ -0,0 +1,333 @@
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
119 if (!shm2) {
120 printf("color mmap failed.\n");
121 exit(-1);
122 }
123 else {
124 printf("Mapped vaddr = %p\n", shm2);
125 }
126
127 shm_info.color = 0x00000002;
128 shm_offset.offset = 1024;
129 shm3 = (char*)color_mmap(3072, shm_info, shm_offset);
130 if (!shm3) {
131 printf("color mmap failed.\n");
132 exit(-1);
133 }
134 else {
135 printf("Mapped vaddr = %p\n", shm3);
136 }
137
138 mlockall(MCL_CURRENT | MCL_FUTURE);
139 /*****
140 * 3) Initialize LITMUS^RT.
141 * Task parameters will be specified per thread.
142 */
143 init_litmus();
144
145
146 /*****
147 * 4) Launch threads.
148 */
149 for (i = 0; i < NUM_THREADS; i++) {
150 ctx[i].id = i;
151 ctx[i].cpu = 0;
152 ctx[i].job_no = 0;
153 ctx[i].shm1 = shm1;
154 ctx[i].shm3 = shm2;
155 ctx[i].shm2 = shm3;
156 pthread_create(task + i, NULL, rt_thread, (void *) (ctx + i));
157 }
158
159
160 /*****
161 * 5) Wait for RT threads to terminate.
162 */
163 for (i = 0; i < NUM_THREADS; i++)
164 pthread_join(task[i], NULL);
165
166
167 /*****
168 * 6) Clean up, maybe print results and stats, and exit.
169 */
170 return 0;
171}
172
173
174
175/* A real-time thread is very similar to the main function of a single-threaded
176 * real-time app. Notice, that init_rt_thread() is called to initialized per-thread
177 * data structures of the LITMUS^RT user space libary.
178 */
179void* rt_thread(void *tcontext)
180{
181 int do_exit;
182 struct thread_context *ctx = (struct thread_context *) tcontext;
183 struct rt_task param;
184 int ret;
185 struct mc2_task mc2_param;
186 struct reservation_config res_config;
187
188 /* Set up task parameters */
189 init_rt_task_param(&param);
190 param.exec_cost = ms2ns(EXEC_COST);
191 param.period = ms2ns(PERIOD);
192 param.relative_deadline = ms2ns(RELATIVE_DEADLINE*(ctx->id+1));
193
194 /* What to do in the case of budget overruns? */
195 param.budget_policy = NO_ENFORCEMENT;
196
197 /* The task class parameter is ignored by most plugins. */
198 param.cls = RT_CLASS_SOFT;
199
200 /* The priority parameter is only used by fixed-priority plugins. */
201 param.priority = LITMUS_LOWEST_PRIORITY;
202
203 /* Make presence visible. */
204 printf("RT Thread %d active.\n", ctx->id);
205
206 /* reservation config */
207 res_config.id = gettid();
208 res_config.polling_params.budget = ms2ns(EXEC_COST+1);
209 res_config.polling_params.period = param.period;
210 res_config.polling_params.offset = 0;
211 res_config.polling_params.relative_deadline = 0;
212 res_config.priority = LITMUS_MAX_PRIORITY;
213 res_config.cpu = ctx->cpu;
214 mc2_param.crit = CRIT_LEVEL_A;
215 mc2_param.res_id = gettid();
216 /*****
217 * 1) Initialize real-time settings.
218 */
219 CALL( init_rt_thread() );
220
221 ret = reservation_create(PERIODIC_POLLING, &res_config);
222 if (ret < 0) {
223 printf("reservation failed.\n");
224 return NULL;
225 }
226
227 /* To specify a partition, do
228 *
229 * param.cpu = CPU;
230 * be_migrate_to(CPU);
231 *
232 * where CPU ranges from 0 to "Number of CPUs" - 1 before calling
233 * set_rt_task_param().
234 */
235 param.cpu = ctx->cpu;
236 ret = be_migrate_to_cpu(ctx->cpu);
237 if (ret < 0) {
238 printf("RT Thread %d fails to migrate to CPU%d\n", ctx->id, ctx->cpu);
239 return NULL;
240 }
241 CALL( set_rt_task_param(gettid(), &param) );
242
243 CALL( set_mc2_task_param(gettid(), &mc2_param) );
244 /*****
245 * 2) Transition to real-time mode.
246 */
247 CALL( task_mode(LITMUS_RT_TASK) );
248
249 /* The task is now executing as a real-time task if the call didn't fail.
250 */
251
252
253
254 /*****
255 * 3) Invoke real-time jobs.
256 */
257 do {
258 /* Wait until the next job is released. */
259 sleep_next_period();
260 /* Invoke job. */
261 do_exit = job(ctx);
262 } while (!do_exit);
263
264
265
266 /*****
267 * 4) Transition to background mode.
268 */
269 CALL( task_mode(BACKGROUND_TASK) );
270 reservation_destroy(gettid(), res_config.cpu);
271
272 return NULL;
273}
274
275
276
277int job(struct thread_context *tcx)
278{
279 int i;
280 char* buf1 = tcx->shm1;
281 char* buf2 = tcx->shm2;
282 char* buf3 = tcx->shm3;
283 char tmp = 0;
284 /* Do real-time calculation. */
285 printf("Task %d Job %d executinig\n", tcx->id, tcx->job_no);
286
287 if (tcx->id == 0) {
288 cycles_t t1, t2;
289 t1 = get_cycles();
290 for (i = 0; i < 1024; i+=32) {
291 tmp += buf1[i];
292 }
293 t2 = get_cycles();
294 printf("%lu\n", t2 = t2 - t1);
295
296 t1 = get_cycles();
297 for (i = 0; i < 4096; i+=32) {
298 tmp += buf2[i];
299 }
300 t2 = get_cycles();
301 printf("%lu\n", t2 = t2 - t1);
302
303 t1 = get_cycles();
304 for (i = 0; i < 3072; i+=32) {
305 tmp += buf3[i];
306 }
307 t2 = get_cycles();
308 printf("%lu\n", t2 = t2 - t1);
309
310/* printf("WRITE\n");
311 for (i=0; i<600; i++) {
312 buf1[i] = rand()%255;
313 printf("%x ",buf[i]);
314 }
315*/
316// printf("\n");
317 } else if (tcx->id == 1) {
318/* printf("READ\n");
319 for (i=0; i<600; i++) {
320 char t = buf[i];
321 printf("%x ", t);
322 }
323 printf("\n");
324*/
325 ;
326 }
327 //test_call(0);
328 tcx->job_no++;
329 if (tcx->job_no == 10)
330 return 1;
331 /* Don't exit. */
332 return 0;
333}