|
1 // Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of the License "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // e32test\personality\example\main.cpp |
|
15 // Test code for example RTOS personality. |
|
16 // |
|
17 // |
|
18 |
|
19 #include <kernel/kern_priv.h> |
|
20 #include <personality/example/personality.h> |
|
21 |
|
22 #ifdef __cplusplus |
|
23 extern "C" { |
|
24 #endif |
|
25 |
|
26 #define OC_TASK 0 |
|
27 #define L2_TASK 1 |
|
28 #define RR_TASK 2 |
|
29 #define NONEXISTENT_TASK 3 |
|
30 #define TM_TASK 4 |
|
31 #define TASK1 6 |
|
32 #define TASK2 7 |
|
33 #define TASK3 8 |
|
34 #define TASK4 9 |
|
35 #define L1_TASK 10 |
|
36 |
|
37 void oo_overall_control(void); |
|
38 void l1_task_entry(void); |
|
39 void l2_task_entry(void); |
|
40 void rr_task_entry(void); |
|
41 void tm_task_entry(void); |
|
42 void task1_entry(void); |
|
43 void task2_entry(void); |
|
44 void task3_entry(void); |
|
45 void task4_entry(void); |
|
46 |
|
47 typedef void (*isr_entry)(unsigned); |
|
48 |
|
49 extern int start_random_isr(isr_entry vector); |
|
50 extern void stop_random_isr(void); |
|
51 |
|
52 const taskinfo task_list[] = |
|
53 { |
|
54 |
|
55 /* entry_pt, priority, stack_size, task_id, auto_start */ |
|
56 |
|
57 { &oo_overall_control, 120, 1024, OC_TASK, 1 }, |
|
58 { &l2_task_entry, 236, 1024, L2_TASK, 0 }, |
|
59 { &rr_task_entry, 224, 1024, RR_TASK, 0 }, |
|
60 { &tm_task_entry, 240, 1024, TM_TASK, 0 }, |
|
61 { &task1_entry, 112, 1024, TASK1, 0 }, |
|
62 { &task2_entry, 112, 1024, TASK2, 0 }, |
|
63 { &task3_entry, 112, 1024, TASK3, 0 }, |
|
64 { &task4_entry, 112, 1024, TASK4, 0 }, |
|
65 { &l1_task_entry, 244, 1024, L1_TASK, 0 }, |
|
66 /* terminator */ |
|
67 { 0, 0, 0, 0, 0 } |
|
68 }; |
|
69 |
|
70 const poolinfo pool_list[] = |
|
71 { |
|
72 /* block size, block count */ |
|
73 { 32, 256 }, |
|
74 { 64, 256 }, |
|
75 { 128, 128 }, |
|
76 { 256, 64 }, |
|
77 { 512, 32 }, |
|
78 /* terminator */ |
|
79 { 0, 0 } |
|
80 }; |
|
81 |
|
82 const int timer_count = 8; |
|
83 const int semaphore_count = 2; |
|
84 |
|
85 #define TM_TIMER 0 |
|
86 |
|
87 #define TM_INIT_DELAY 1000 |
|
88 #define TM_PERIOD 2 |
|
89 |
|
90 volatile unsigned next_random_id = 0; |
|
91 volatile unsigned random_sem_signal_interval = 0; |
|
92 volatile unsigned random_sem_signal_count = 0; |
|
93 volatile unsigned random_send_interval = 0; |
|
94 volatile unsigned random_send_count = 0; |
|
95 volatile unsigned tmcount = 0; |
|
96 volatile int t1func = 0; |
|
97 volatile int t2func = 0; |
|
98 volatile int t3func = 0; |
|
99 volatile int t4func = 0; |
|
100 |
|
101 #define TEST_SEM 0 |
|
102 #define ISR_SEM 1 |
|
103 |
|
104 #define MSG_ID_INIT 1 |
|
105 #define MSG_ID_RUN 2 |
|
106 #define MSG_ID_RUN_P 3 |
|
107 #define MSG_ID_RND_ISR 4 |
|
108 #define MSG_ID_DONE 5 |
|
109 #define MSG_ID_DATA 6 |
|
110 #define MSG_ID_FLUSH 7 |
|
111 #define MSG_ID_SEM_RPT 8 |
|
112 #define MSG_ID_RCV_RPT 9 |
|
113 #define MSG_ID_TM_RPT 10 |
|
114 |
|
115 typedef struct _run_msg |
|
116 { |
|
117 msghdr header; |
|
118 int task_id; |
|
119 unsigned tmcount; |
|
120 int parameter; |
|
121 } run_msg; |
|
122 |
|
123 typedef struct _random_isr_msg |
|
124 { |
|
125 msghdr header; |
|
126 unsigned random_isr_number; |
|
127 unsigned extra; |
|
128 } random_isr_msg; |
|
129 |
|
130 typedef struct _data_msg |
|
131 { |
|
132 msghdr header; |
|
133 int length; |
|
134 unsigned char checksum; |
|
135 unsigned char data[1]; |
|
136 } data_msg; |
|
137 |
|
138 typedef struct _report_msg |
|
139 { |
|
140 msghdr header; |
|
141 int pad; |
|
142 unsigned count; |
|
143 unsigned ok_count; |
|
144 unsigned bad_count; |
|
145 } report_msg; |
|
146 |
|
147 void busy_wait(unsigned ticks) |
|
148 { |
|
149 unsigned t0 = tmcount; |
|
150 while ((tmcount - t0) < ticks) |
|
151 {} |
|
152 } |
|
153 |
|
154 void send_run_signal() |
|
155 { |
|
156 run_msg* m = (run_msg*)alloc_mem_block(sizeof(run_msg)); |
|
157 assert(m); |
|
158 m->header.msg_id = MSG_ID_RUN; |
|
159 m->task_id = current_task_id(); |
|
160 m->tmcount = tmcount; |
|
161 int r = send_msg(OC_TASK, &m->header); |
|
162 assert(r == OK); |
|
163 } |
|
164 |
|
165 void send_run_signal_p(int parameter) |
|
166 { |
|
167 run_msg* m = (run_msg*)alloc_mem_block(sizeof(run_msg)); |
|
168 assert(m); |
|
169 m->header.msg_id = MSG_ID_RUN_P; |
|
170 m->task_id = current_task_id(); |
|
171 m->tmcount = tmcount; |
|
172 m->parameter = parameter; |
|
173 int r = send_msg(OC_TASK, &m->header); |
|
174 assert(r == OK); |
|
175 } |
|
176 |
|
177 void tsend_run_signal_p(int task_id, int parameter) |
|
178 { |
|
179 run_msg* m = (run_msg*)alloc_mem_block(sizeof(run_msg)); |
|
180 assert(m); |
|
181 m->header.msg_id = MSG_ID_RUN_P; |
|
182 m->task_id = current_task_id(); |
|
183 m->tmcount = tmcount; |
|
184 m->parameter = parameter; |
|
185 int r = send_msg(task_id, &m->header); |
|
186 assert(r == OK); |
|
187 } |
|
188 |
|
189 void check_no_signal() |
|
190 { |
|
191 msghdr* m = NULL; |
|
192 int r = recv_msg(&m, NO_WAIT); |
|
193 assert(r == TIMED_OUT); |
|
194 } |
|
195 |
|
196 unsigned check_for_signal(int task_id) |
|
197 { |
|
198 msghdr* m = NULL; |
|
199 int r = recv_msg(&m, NO_WAIT); |
|
200 assert(r == OK); |
|
201 assert(m->msg_id == MSG_ID_RUN); |
|
202 run_msg* rm = (run_msg*)m; |
|
203 assert(rm->task_id == task_id); |
|
204 unsigned tmc = rm->tmcount; |
|
205 free_mem_block(m); |
|
206 return tmc; |
|
207 } |
|
208 |
|
209 int check_for_signal_p(int task_id, int task_id2, unsigned* pt) |
|
210 { |
|
211 msghdr* m = NULL; |
|
212 int r = recv_msg(&m, NO_WAIT); |
|
213 assert(r == OK); |
|
214 assert(m->msg_id == MSG_ID_RUN_P); |
|
215 run_msg* rm = (run_msg*)m; |
|
216 assert(rm->task_id == task_id); |
|
217 assert(m->sending_task_id == task_id2); |
|
218 r = rm->parameter; |
|
219 if (pt) |
|
220 *pt = rm->tmcount; |
|
221 free_mem_block(m); |
|
222 return r; |
|
223 } |
|
224 |
|
225 int wait_for_signal_p(int task_id, unsigned* pt) |
|
226 { |
|
227 msghdr* m = NULL; |
|
228 int r = recv_msg(&m, WAIT_FOREVER); |
|
229 assert(r == OK); |
|
230 assert(m->msg_id == MSG_ID_RUN_P); |
|
231 run_msg* rm = (run_msg*)m; |
|
232 assert(rm->task_id == task_id); |
|
233 r = rm->parameter; |
|
234 if (pt) |
|
235 *pt = rm->tmcount; |
|
236 free_mem_block(m); |
|
237 return r; |
|
238 } |
|
239 |
|
240 void resume_4(int t1, int t2, int t3, int t4) |
|
241 { |
|
242 if (t1>=0) |
|
243 assert(resume_task(t1)==OK); |
|
244 if (t2>=0) |
|
245 assert(resume_task(t2)==OK); |
|
246 if (t3>=0) |
|
247 assert(resume_task(t3)==OK); |
|
248 if (t4>=0) |
|
249 assert(resume_task(t4)==OK); |
|
250 } |
|
251 |
|
252 void check_signal_4(int t1, int t2, int t3, int t4) |
|
253 { |
|
254 if (t1>=0) |
|
255 check_for_signal(t1); |
|
256 else |
|
257 check_no_signal(); |
|
258 if (t2>=0) |
|
259 check_for_signal(t2); |
|
260 else |
|
261 check_no_signal(); |
|
262 if (t3>=0) |
|
263 check_for_signal(t3); |
|
264 else |
|
265 check_no_signal(); |
|
266 if (t4>=0) |
|
267 check_for_signal(t4); |
|
268 else |
|
269 check_no_signal(); |
|
270 } |
|
271 |
|
272 void check_for_multiple_signals(int task_id, int count) |
|
273 { |
|
274 unsigned t = check_for_signal(task_id); |
|
275 while (--count) |
|
276 { |
|
277 unsigned t2 = check_for_signal(task_id); |
|
278 assert(t2 - t >= 1); |
|
279 t = t2; |
|
280 } |
|
281 } |
|
282 |
|
283 int flush_signals(void) |
|
284 { |
|
285 int c = 0; |
|
286 for (;;) |
|
287 { |
|
288 msghdr* m = NULL; |
|
289 int r = recv_msg(&m, NO_WAIT); |
|
290 if (r == TIMED_OUT) |
|
291 break; |
|
292 assert(r == OK); |
|
293 assert(m->msg_id == MSG_ID_RUN); |
|
294 free_mem_block(m); |
|
295 ++c; |
|
296 } |
|
297 return c; |
|
298 } |
|
299 |
|
300 void test_mem_pool(size_t size, int count, void** chain) |
|
301 { |
|
302 int i, fill; |
|
303 void *b, *bb, *c; |
|
304 c = *chain; |
|
305 for (i=0; i<count; ++i) |
|
306 { |
|
307 b = alloc_mem_block(size); |
|
308 assert(b != NULL); |
|
309 fill = (int)(size>>5); |
|
310 fill += 29; |
|
311 fill *= fill; |
|
312 fill &= 0xff; |
|
313 memset(b, fill, size); |
|
314 *(void**)b = c; |
|
315 ((int*)b)[1] = (int)size; |
|
316 c = b; |
|
317 } |
|
318 bb = alloc_mem_block(size); |
|
319 assert(bb == NULL); |
|
320 *chain = c; |
|
321 } |
|
322 |
|
323 void check_blocks(void* chain) |
|
324 { |
|
325 void* p = chain; |
|
326 while (p) |
|
327 { |
|
328 unsigned char *q, *qq; |
|
329 int size, fill, x; |
|
330 size = ((int*)p)[1]; |
|
331 fill = (size>>5)+29; |
|
332 fill = (fill*fill)&0xff; |
|
333 q = (unsigned char*)p + sizeof(void*) + sizeof(int); |
|
334 qq = (unsigned char*)p + size; |
|
335 x = 0; |
|
336 while (q<qq) |
|
337 x |= (*q++ ^ fill); |
|
338 assert(x==0); |
|
339 p = *(void**)p; |
|
340 } |
|
341 } |
|
342 |
|
343 int free_blocks(void* chain) |
|
344 { |
|
345 void* p = chain; |
|
346 int c = 0; |
|
347 while (p) |
|
348 { |
|
349 void* n = *(void**)p; |
|
350 free_mem_block(p); |
|
351 p = n; |
|
352 ++c; |
|
353 } |
|
354 return c; |
|
355 } |
|
356 |
|
357 void test_mem_mgr(void) |
|
358 { |
|
359 void* chain = NULL; |
|
360 const poolinfo* pi = pool_list; |
|
361 int nblocks = 0; |
|
362 int nfreed = 0; |
|
363 for (; pi->block_size; ++pi) |
|
364 { |
|
365 nblocks += pi->block_count; |
|
366 test_mem_pool(pi->block_size, pi->block_count, &chain); |
|
367 } |
|
368 check_blocks(chain); |
|
369 nfreed = free_blocks(chain); |
|
370 assert(nfreed == nblocks); |
|
371 chain = NULL; |
|
372 for (--pi; pi >= pool_list; --pi) |
|
373 test_mem_pool(pi->block_size, pi->block_count, &chain); |
|
374 check_blocks(chain); |
|
375 nfreed = free_blocks(chain); |
|
376 assert(nfreed == nblocks); |
|
377 chain = NULL; |
|
378 kprintf("Memory Manager Test OK"); |
|
379 } |
|
380 |
|
381 void test_suspend_1(void) |
|
382 { |
|
383 unsigned t1, t2, t3; |
|
384 int r; |
|
385 t1 = tmcount; |
|
386 delay(5*TM_PERIOD); |
|
387 t2 = tmcount; |
|
388 assert( ((int)t2)-((int)t1) >= 5 ); |
|
389 r = suspend_task(TM_TASK); |
|
390 assert(r == OK); |
|
391 t1 = tmcount; |
|
392 delay(5*TM_PERIOD); |
|
393 t2 = tmcount; |
|
394 assert(t2==t1); |
|
395 r = resume_task(TM_TASK); |
|
396 assert(r == OK); |
|
397 t3 = tmcount; |
|
398 assert( ((int)t3)-((int)t2) >= 5 ); |
|
399 |
|
400 r = suspend_task(TM_TASK); |
|
401 assert(r == OK); |
|
402 r = suspend_task(TM_TASK); |
|
403 assert(r == OK); |
|
404 t1 = tmcount; |
|
405 delay(5*TM_PERIOD); |
|
406 t2 = tmcount; |
|
407 assert(t2==t1); |
|
408 r = resume_task(TM_TASK); |
|
409 assert(r == OK); |
|
410 t3 = tmcount; |
|
411 assert(t3==t2); |
|
412 r = resume_task(TM_TASK); |
|
413 assert(r == OK); |
|
414 t3 = tmcount; |
|
415 assert( ((int)t3)-((int)t2) >= 5 ); |
|
416 |
|
417 r = suspend_task(-1); |
|
418 assert(r == BAD_TASK_ID); |
|
419 r = suspend_task(300); |
|
420 assert(r == BAD_TASK_ID); |
|
421 r = suspend_task(NONEXISTENT_TASK); |
|
422 assert(r == BAD_TASK_ID); |
|
423 r = resume_task(-1); |
|
424 assert(r == BAD_TASK_ID); |
|
425 r = resume_task(300); |
|
426 assert(r == BAD_TASK_ID); |
|
427 r = resume_task(NONEXISTENT_TASK); |
|
428 assert(r == BAD_TASK_ID); |
|
429 |
|
430 kprintf("test_suspend_1 OK"); |
|
431 } |
|
432 |
|
433 void test_priority_scheduling(void) |
|
434 { |
|
435 int init_pri = get_task_priority(current_task_id()); |
|
436 resume_4(TASK1, TASK2, TASK3, TASK4); |
|
437 delay(80*TM_PERIOD); |
|
438 check_for_multiple_signals(TASK1, 50); // check no timeslicing |
|
439 assert(flush_signals()<=31); |
|
440 suspend_task(TASK1); |
|
441 delay(80*TM_PERIOD); |
|
442 check_for_multiple_signals(TASK2, 50); // check no timeslicing |
|
443 assert(flush_signals()<=31); |
|
444 suspend_task(TASK2); |
|
445 delay(80*TM_PERIOD); |
|
446 check_for_multiple_signals(TASK3, 50); // check no timeslicing |
|
447 assert(flush_signals()<=31); |
|
448 suspend_task(TASK3); |
|
449 delay(1); |
|
450 check_for_signal(TASK4); |
|
451 assert(flush_signals()<=1); |
|
452 |
|
453 t1func = 1; |
|
454 t2func = 1; |
|
455 t3func = 1; |
|
456 t4func = 1; |
|
457 |
|
458 resume_4(TASK1, TASK2, TASK3, TASK4); |
|
459 delay(10); |
|
460 flush_signals(); |
|
461 |
|
462 resume_4(TASK3, TASK2, TASK4, TASK1); |
|
463 delay(10); |
|
464 check_signal_4(TASK3, TASK2, TASK4, TASK1); |
|
465 check_no_signal(); |
|
466 resume_4(TASK1, TASK2, TASK3, TASK4); |
|
467 check_no_signal(); // all lower priority so don't run |
|
468 set_task_priority(TASK2, 255); // higher than current task so run immediately |
|
469 check_for_signal(TASK2); |
|
470 set_task_priority(TASK4, 116); |
|
471 check_no_signal(); // all lower priority so don't run |
|
472 delay(10); |
|
473 check_for_signal(TASK4); |
|
474 check_for_signal(TASK1); |
|
475 check_for_signal(TASK3); |
|
476 set_task_priority(TASK1, 116); |
|
477 set_task_priority(TASK2, 116); |
|
478 set_task_priority(TASK3, 116); |
|
479 set_task_priority(TASK4, 116); |
|
480 resume_4(TASK1, TASK2, TASK3, TASK4); |
|
481 set_task_priority(current_task_id(), 112); // drop current task priority |
|
482 assert(get_task_priority(current_task_id())==112); |
|
483 check_signal_4(TASK1, TASK2, TASK3, TASK4); |
|
484 set_task_priority(current_task_id(), init_pri); |
|
485 assert(get_task_priority(current_task_id())==init_pri); |
|
486 |
|
487 kprintf("test_priority_scheduling OK"); |
|
488 } |
|
489 |
|
490 unsigned sem_test(int task_id) |
|
491 { |
|
492 int r = semaphore_signal(TEST_SEM); |
|
493 assert(r==OK); |
|
494 return check_for_signal(task_id); |
|
495 } |
|
496 |
|
497 unsigned sem_test_p(int task_id, int parameter) |
|
498 { |
|
499 unsigned t; |
|
500 int r = semaphore_signal(TEST_SEM); |
|
501 assert(r==OK); |
|
502 r = check_for_signal_p(task_id, task_id, &t); |
|
503 assert(r == parameter); |
|
504 return t; |
|
505 } |
|
506 |
|
507 unsigned sem_test_pt(int task_id, int parameter) |
|
508 { |
|
509 unsigned t; |
|
510 int r = semaphore_signal(TEST_SEM); |
|
511 assert(r==OK); |
|
512 r = check_for_signal_p(task_id, task_id, &t); |
|
513 assert(r == parameter); |
|
514 return t; |
|
515 } |
|
516 |
|
517 void test_semaphore(void) |
|
518 { |
|
519 unsigned t1, t2, t3; |
|
520 int r; |
|
521 int init_pri = get_task_priority(current_task_id()); |
|
522 set_task_priority(TASK1, 128); |
|
523 set_task_priority(TASK2, 128); |
|
524 set_task_priority(TASK3, 128); |
|
525 set_task_priority(TASK4, 128); |
|
526 t1func = 2; |
|
527 t2func = 2; |
|
528 t3func = 2; |
|
529 t4func = 2; |
|
530 resume_4(TASK1, TASK2, TASK3, TASK4); |
|
531 delay(10); // let tasks wait on semaphore |
|
532 check_no_signal(); |
|
533 sem_test(TASK1); // test they are released in same order |
|
534 sem_test(TASK2); |
|
535 sem_test(TASK3); |
|
536 sem_test(TASK4); |
|
537 check_no_signal(); |
|
538 set_task_priority(TASK3, 132); // test highest priority is released first |
|
539 sem_test(TASK3); |
|
540 sem_test(TASK3); |
|
541 suspend_task(TASK3); // test suspended task doesn't contend for semaphore |
|
542 sem_test(TASK1); |
|
543 sem_test(TASK2); |
|
544 sem_test(TASK4); |
|
545 sem_test(TASK1); |
|
546 suspend_task(TASK2); |
|
547 sem_test(TASK4); |
|
548 sem_test(TASK1); |
|
549 sem_test(TASK4); |
|
550 set_task_priority(TASK2, 136); // change priority while suspended |
|
551 sem_test(TASK1); |
|
552 sem_test(TASK4); |
|
553 sem_test(TASK1); |
|
554 resume_task(TASK2); |
|
555 sem_test(TASK2); |
|
556 sem_test(TASK2); // test new highest priority task acquires semaphore first |
|
557 delay(100*TM_PERIOD); |
|
558 check_no_signal(); // check waits don't time out |
|
559 |
|
560 t2func = 3; // switch over to timed waits for task 2 |
|
561 t1 = sem_test(TASK2); // get one last message of previous type |
|
562 delay(5*TM_PERIOD); |
|
563 t2 = sem_test_p(TASK2, OK); // signal after half the timeout and check OK |
|
564 delay(11*TM_PERIOD); // wait for > timeout |
|
565 r = check_for_signal_p(TASK2, TASK2, &t3); |
|
566 assert(r == TIMED_OUT); |
|
567 kprintf("t2-t1=%d t3-t2=%d", t2-t1, t3-t2); |
|
568 assert(t2-t1 >= 5); |
|
569 assert(t3-t2 >= 10); |
|
570 sem_test_p(TASK2, OK); |
|
571 resume_task(TASK3); |
|
572 |
|
573 set_task_priority(current_task_id(), 176); // raise current task priority |
|
574 semaphore_signal(TEST_SEM); // signal semaphore 4 times - should release all 4 waiting threads |
|
575 semaphore_signal(TEST_SEM); |
|
576 semaphore_signal(TEST_SEM); |
|
577 semaphore_signal(TEST_SEM); |
|
578 set_task_priority(current_task_id(), init_pri); // let tasks run |
|
579 r = check_for_signal_p(TASK2, TASK2, NULL); |
|
580 assert(r == OK); |
|
581 check_for_signal(TASK3); |
|
582 check_for_signal(TASK4); |
|
583 check_for_signal(TASK1); |
|
584 set_task_priority(current_task_id(), 176); // raise current task priority |
|
585 busy_wait(11); // let semaphore wait time out |
|
586 t1func = 4; // switch all threads over |
|
587 t2func = 4; // |
|
588 t3func = 4; // |
|
589 t4func = 4; // |
|
590 semaphore_signal(TEST_SEM); // signal semaphore 3 times - should release other 3 waiting threads |
|
591 semaphore_signal(TEST_SEM); |
|
592 semaphore_signal(TEST_SEM); |
|
593 set_task_priority(current_task_id(), init_pri); // let tasks run |
|
594 r = check_for_signal_p(TASK2, TASK2, NULL); |
|
595 assert(r == TIMED_OUT); |
|
596 check_for_signal(TASK3); |
|
597 check_for_signal(TASK4); |
|
598 check_for_signal(TASK1); |
|
599 |
|
600 kprintf("test_semaphore OK"); |
|
601 } |
|
602 |
|
603 void test_message_queue(void) |
|
604 { |
|
605 unsigned t1, t2, t3, t4; |
|
606 int tid, p, r; |
|
607 int init_pri = get_task_priority(current_task_id()); |
|
608 p = 0; |
|
609 t1 = 0; |
|
610 for (tid = TASK1; tid <= TASK4; ++tid) |
|
611 { |
|
612 for (p = 1; p; p<<=1) |
|
613 { |
|
614 tsend_run_signal_p(tid, p); |
|
615 r = check_for_signal_p(OC_TASK, tid, NULL); |
|
616 assert(r == p); |
|
617 } |
|
618 } |
|
619 check_no_signal(); |
|
620 set_task_priority(current_task_id(), 176); // raise current task priority |
|
621 set_task_priority(TASK4, 144); // change task priorities while they are waiting |
|
622 set_task_priority(TASK3, 140); |
|
623 set_task_priority(TASK2, 136); |
|
624 set_task_priority(TASK1, 132); |
|
625 t1func = 5; // switch task 1 to timed waits |
|
626 for (tid = TASK1; tid <= TASK4; ++tid) |
|
627 { |
|
628 for (p = 0; p<0x40000000; p+=(0x413b9cb+tid)) |
|
629 { |
|
630 tsend_run_signal_p(tid, p); // let multiple messages accumulate on the queues |
|
631 } |
|
632 } |
|
633 check_no_signal(); |
|
634 set_task_priority(current_task_id(), init_pri); // let tasks run |
|
635 kprintf("init_pri=%d",init_pri); |
|
636 for (tid = TASK4; tid >= TASK1; --tid) |
|
637 { |
|
638 for (p = 0; p<0x40000000; p+=(0x413b9cb+tid)) |
|
639 { |
|
640 r = check_for_signal_p(OC_TASK, tid, &t1); |
|
641 assert(r == p); |
|
642 } |
|
643 } |
|
644 |
|
645 delay(5*TM_PERIOD); |
|
646 tsend_run_signal_p(TASK1, p); // send after half timeout |
|
647 r = check_for_signal_p(OC_TASK, TASK1, &t2); |
|
648 assert(r == p); |
|
649 delay(11*TM_PERIOD); // wait for > timeout |
|
650 tsend_run_signal_p(TASK1, ~p); // send after timeout |
|
651 r = check_for_signal_p(TASK1, TASK1, &t3); |
|
652 assert(r == TIMED_OUT); |
|
653 kprintf("t2-t1=%d t3-t2=%d", t2-t1, t3-t2); |
|
654 assert(t2-t1 >= 5); |
|
655 assert(t3-t2 >= 10); |
|
656 r = check_for_signal_p(OC_TASK, TASK1, &t4); |
|
657 assert(r == ~p); |
|
658 assert(t4-t3 <= 1); |
|
659 t1func = 6; // switch task 1 to timed semaphore wait |
|
660 t2func = 7; // switch task 2 to timed queue wait |
|
661 t3func = 8; // |
|
662 t4func = 8; // |
|
663 for (tid = TASK1; tid <= TASK4; ++tid) |
|
664 { |
|
665 tsend_run_signal_p(tid, 0); |
|
666 r = check_for_signal_p(OC_TASK, tid, NULL); |
|
667 assert(r == 0); |
|
668 } |
|
669 check_no_signal(); |
|
670 |
|
671 kprintf("test_message_queue OK"); |
|
672 } |
|
673 |
|
674 void random_isr(unsigned n) |
|
675 { |
|
676 random_isr_msg* m; |
|
677 unsigned extra = 1; |
|
678 unsigned count = 1; |
|
679 int r; |
|
680 if (!(n%11)) |
|
681 ++count; |
|
682 if (!(n%13)) |
|
683 ++count; |
|
684 while (count--) |
|
685 { |
|
686 m = (random_isr_msg*)alloc_mem_block(sizeof(random_isr_msg)); |
|
687 m->header.msg_id = MSG_ID_RND_ISR; |
|
688 m->random_isr_number = n; |
|
689 extra *= n; |
|
690 m->extra = extra; |
|
691 r = send_msg(L1_TASK, &m->header); |
|
692 } |
|
693 if (random_sem_signal_count && !--random_sem_signal_count) |
|
694 { |
|
695 random_sem_signal_count = random_sem_signal_interval; |
|
696 semaphore_signal(ISR_SEM); |
|
697 } |
|
698 } |
|
699 |
|
700 void flush_queue(msghdr** f, msghdr** l, msghdr* tm) |
|
701 { |
|
702 msghdr* m = *f; |
|
703 *f = NULL; |
|
704 *l = NULL; |
|
705 send_to_epoc(tm); |
|
706 while (m) |
|
707 { |
|
708 msghdr* n = m->next; |
|
709 send_to_epoc(m); |
|
710 m = n; |
|
711 } |
|
712 } |
|
713 |
|
714 void l1_task_entry(void) |
|
715 { |
|
716 msghdr* first = NULL; |
|
717 msghdr* last = NULL; |
|
718 unsigned state = 0; |
|
719 unsigned extra_count = 0; |
|
720 unsigned extra_value = 0; |
|
721 assert(current_task_id() == L1_TASK); |
|
722 kprintf("L1_TASK running"); |
|
723 for (;;) |
|
724 { |
|
725 msghdr* m = NULL; |
|
726 int r = recv_msg(&m, WAIT_FOREVER); |
|
727 assert(r == OK); |
|
728 switch (m->msg_id) |
|
729 { |
|
730 case MSG_ID_RND_ISR: |
|
731 { |
|
732 random_isr_msg* rm = (random_isr_msg*)m; |
|
733 assert(m->sending_task_id == TASK_ID_ISR); |
|
734 assert(rm->random_isr_number == next_random_id); |
|
735 if (state == 0) |
|
736 { |
|
737 extra_count = 0; |
|
738 if (!(next_random_id % 11)) |
|
739 ++extra_count; |
|
740 if (!(next_random_id % 13)) |
|
741 ++extra_count; |
|
742 extra_value = next_random_id; |
|
743 } |
|
744 else if (state > 0) |
|
745 { |
|
746 extra_value *= next_random_id; |
|
747 } |
|
748 assert(rm->extra == extra_value); |
|
749 if (++state > extra_count) |
|
750 state = 0; |
|
751 if (state == 0) |
|
752 ++next_random_id; |
|
753 if (rm->random_isr_number == 0) |
|
754 send_msg(OC_TASK, m), m=NULL; |
|
755 if (state == 1 && extra_count == 2 && m) |
|
756 { |
|
757 flush_queue(&first, &last, m); |
|
758 m = NULL; |
|
759 } |
|
760 if (random_send_count && !--random_send_count) |
|
761 { |
|
762 random_send_count = random_send_interval; |
|
763 if (m) |
|
764 send_msg(TASK2, m), m=NULL; |
|
765 } |
|
766 break; |
|
767 } |
|
768 case MSG_ID_DATA: |
|
769 m->next = NULL; |
|
770 if (last) |
|
771 last->next = m; |
|
772 else |
|
773 first = m; |
|
774 last = m; |
|
775 m = NULL; |
|
776 break; |
|
777 case MSG_ID_FLUSH: |
|
778 flush_queue(&first, &last, m); |
|
779 m = NULL; |
|
780 break; |
|
781 default: |
|
782 kprintf("L1<-%08x",m->msg_id); |
|
783 break; |
|
784 } |
|
785 if (m) |
|
786 free_mem_block(m); |
|
787 } |
|
788 } |
|
789 |
|
790 void l2_task_entry(void) |
|
791 { |
|
792 assert(current_task_id() == L2_TASK); |
|
793 kprintf("L2_TASK running"); |
|
794 for (;;) |
|
795 { |
|
796 msghdr* m = NULL; |
|
797 int r = recv_msg(&m, WAIT_FOREVER); |
|
798 assert(r == OK); |
|
799 switch (m->msg_id) |
|
800 { |
|
801 case MSG_ID_DATA: |
|
802 { |
|
803 data_msg* dm = (data_msg*)m; |
|
804 int i; |
|
805 unsigned char cs = 0; |
|
806 for (i=0; i<dm->length; ++i) |
|
807 cs = (unsigned char)(cs + dm->data[i]); |
|
808 dm->checksum = cs; |
|
809 send_msg(L1_TASK, m); |
|
810 m=NULL; |
|
811 break; |
|
812 } |
|
813 default: |
|
814 kprintf("L2<-%08x",m->msg_id); |
|
815 break; |
|
816 } |
|
817 if (m) |
|
818 free_mem_block(m); |
|
819 } |
|
820 } |
|
821 |
|
822 void rr_task_entry(void) |
|
823 { |
|
824 assert(current_task_id() == RR_TASK); |
|
825 kprintf("RR_TASK running"); |
|
826 for (;;) |
|
827 { |
|
828 msghdr* m = NULL; |
|
829 int r = recv_msg(&m, WAIT_FOREVER); |
|
830 assert(r == OK); |
|
831 switch (m->msg_id) |
|
832 { |
|
833 case MSG_ID_DATA: |
|
834 send_msg(L2_TASK, m); |
|
835 m=NULL; |
|
836 break; |
|
837 default: |
|
838 kprintf("RR<-%08x",m->msg_id); |
|
839 break; |
|
840 } |
|
841 if (m) |
|
842 free_mem_block(m); |
|
843 } |
|
844 } |
|
845 |
|
846 void tm_task_entry(void) |
|
847 { |
|
848 assert(current_task_id() == TM_TASK); |
|
849 kprintf("TM_TASK running"); |
|
850 for (;;) |
|
851 { |
|
852 msghdr* m = NULL; |
|
853 int r = recv_msg(&m, WAIT_FOREVER); |
|
854 assert(r == OK); |
|
855 switch (m->msg_id) |
|
856 { |
|
857 case MSG_ID_TIMEOUT: |
|
858 tmcount = ((timer_msg*)m)->count; |
|
859 assert(m->sending_task_id == TASK_ID_ISR); |
|
860 if (!(tmcount & 255)) |
|
861 { |
|
862 report_msg* rpt = (report_msg*)alloc_mem_block(sizeof(report_msg)); |
|
863 rpt->header.msg_id = MSG_ID_TM_RPT; |
|
864 rpt->count = tmcount; |
|
865 rpt->ok_count = 0; |
|
866 rpt->bad_count = 0; |
|
867 send_to_epoc(&rpt->header); |
|
868 } |
|
869 break; |
|
870 default: |
|
871 kprintf("TM<-%08x",m->msg_id); |
|
872 break; |
|
873 } |
|
874 free_mem_block(m); |
|
875 } |
|
876 } |
|
877 |
|
878 void generic_task(volatile int* f) |
|
879 { |
|
880 int r; |
|
881 msghdr* m; |
|
882 unsigned t1, t2; |
|
883 unsigned count = 0; |
|
884 unsigned ok_count = 0; |
|
885 unsigned bad_count = 0; |
|
886 while (*f==0) |
|
887 { |
|
888 send_run_signal(); |
|
889 busy_wait(1); |
|
890 } |
|
891 while (*f==1) |
|
892 { |
|
893 send_run_signal(); |
|
894 suspend_task(current_task_id()); |
|
895 } |
|
896 while (*f==2) |
|
897 { |
|
898 r = semaphore_wait(TEST_SEM, WAIT_FOREVER); |
|
899 assert(r == OK); |
|
900 send_run_signal(); |
|
901 } |
|
902 while (*f==3) |
|
903 { |
|
904 r = semaphore_wait(TEST_SEM, 10*TM_PERIOD); |
|
905 assert(r==OK || r==TIMED_OUT); |
|
906 send_run_signal_p(r); |
|
907 } |
|
908 while (*f==4) |
|
909 { |
|
910 r = recv_msg(&m, WAIT_FOREVER); |
|
911 assert(r==OK); |
|
912 assert(m->sending_task_id == OC_TASK); |
|
913 r = send_msg(OC_TASK, m); |
|
914 assert(r == OK); |
|
915 } |
|
916 while (*f==5) |
|
917 { |
|
918 r = recv_msg(&m, 10*TM_PERIOD); |
|
919 assert(r==OK || r==TIMED_OUT); |
|
920 if (r == OK) |
|
921 { |
|
922 assert(m->sending_task_id == OC_TASK); |
|
923 r = send_msg(OC_TASK, m); |
|
924 assert(r == OK); |
|
925 } |
|
926 else |
|
927 send_run_signal_p(r); |
|
928 } |
|
929 while (*f==6) |
|
930 { |
|
931 t1 = tick_count(); |
|
932 r = semaphore_wait(ISR_SEM, 5); |
|
933 t2 = tick_count() - t1; |
|
934 if (r == TIMED_OUT && t2<5) |
|
935 { |
|
936 kprintf("SEM timed out too soon: %d", t2); |
|
937 ++bad_count; |
|
938 } |
|
939 if (r == OK) |
|
940 ++ok_count; |
|
941 ++count; |
|
942 if (!(count & 0xff)) |
|
943 { |
|
944 report_msg* rpt = (report_msg*)alloc_mem_block(sizeof(report_msg)); |
|
945 rpt->header.msg_id = MSG_ID_SEM_RPT; |
|
946 rpt->count = count; |
|
947 rpt->ok_count = ok_count; |
|
948 rpt->bad_count = bad_count; |
|
949 send_to_epoc(&rpt->header); |
|
950 } |
|
951 } |
|
952 while (*f==7) |
|
953 { |
|
954 t1 = tick_count(); |
|
955 r = recv_msg(&m, 5); |
|
956 t2 = tick_count() - t1; |
|
957 if (r == TIMED_OUT && t2<5) |
|
958 { |
|
959 kprintf("RECV timed out too soon: %d", t2); |
|
960 ++bad_count; |
|
961 } |
|
962 if (r==OK) |
|
963 ++ok_count, free_mem_block(m); |
|
964 ++count; |
|
965 if (!(count & 0xff)) |
|
966 { |
|
967 report_msg* rpt = (report_msg*)alloc_mem_block(sizeof(report_msg)); |
|
968 rpt->header.msg_id = MSG_ID_RCV_RPT; |
|
969 rpt->count = count; |
|
970 rpt->ok_count = ok_count; |
|
971 rpt->bad_count = bad_count; |
|
972 send_to_epoc(&rpt->header); |
|
973 } |
|
974 } |
|
975 kprintf("Task %d finished", current_task_id()); |
|
976 for(;;) |
|
977 suspend_task(current_task_id()); |
|
978 } |
|
979 |
|
980 void task1_entry(void) |
|
981 { |
|
982 assert(current_task_id() == TASK1); |
|
983 generic_task(&t1func); |
|
984 } |
|
985 |
|
986 void task2_entry(void) |
|
987 { |
|
988 assert(current_task_id() == TASK2); |
|
989 generic_task(&t2func); |
|
990 } |
|
991 |
|
992 void task3_entry(void) |
|
993 { |
|
994 assert(current_task_id() == TASK3); |
|
995 generic_task(&t3func); |
|
996 } |
|
997 |
|
998 void task4_entry(void) |
|
999 { |
|
1000 assert(current_task_id() == TASK4); |
|
1001 generic_task(&t4func); |
|
1002 } |
|
1003 |
|
1004 |
|
1005 |
|
1006 void oo_overall_control(void) |
|
1007 { |
|
1008 int r; |
|
1009 msghdr* m; |
|
1010 random_isr_msg* rm; |
|
1011 unsigned t1, t2, rss_interval; |
|
1012 kprintf("OC_TASK running"); |
|
1013 assert(current_task_id() == OC_TASK); |
|
1014 resume_task(L2_TASK); |
|
1015 resume_task(RR_TASK); |
|
1016 resume_task(TM_TASK); |
|
1017 test_mem_mgr(); |
|
1018 |
|
1019 kprintf("Wait for init msg"); |
|
1020 r = recv_msg(&m, WAIT_FOREVER); |
|
1021 assert(r == OK); |
|
1022 assert(m->msg_id == MSG_ID_INIT); |
|
1023 assert(m->sending_task_id == TASK_ID_UNKNOWN); |
|
1024 free_mem_block(m); |
|
1025 kprintf("Received init msg"); |
|
1026 |
|
1027 r = start_periodic_timer(TM_TIMER, TM_TASK, TM_INIT_DELAY, TM_PERIOD, NULL); |
|
1028 assert(r == OK); |
|
1029 delay(TM_INIT_DELAY-10); |
|
1030 assert(tmcount == 0); |
|
1031 delay(10*TM_PERIOD+20); |
|
1032 assert(tmcount > 0); |
|
1033 test_suspend_1(); |
|
1034 test_priority_scheduling(); |
|
1035 test_semaphore(); |
|
1036 test_message_queue(); |
|
1037 |
|
1038 resume_task(L1_TASK); |
|
1039 r = start_random_isr(&random_isr); |
|
1040 if (r != OK) |
|
1041 goto no_random_isr; |
|
1042 |
|
1043 r = recv_msg(&m, WAIT_FOREVER); |
|
1044 assert(r == OK); |
|
1045 assert(m->msg_id == MSG_ID_RND_ISR); |
|
1046 assert(m->sending_task_id == L1_TASK); |
|
1047 rm = (random_isr_msg*)m; |
|
1048 assert(rm->random_isr_number == 0); |
|
1049 free_mem_block(m); |
|
1050 t1 = next_random_id; |
|
1051 delay(1024); |
|
1052 t2 = next_random_id; |
|
1053 kprintf("%d random ISRs in 1024 ticks", t2-t1); |
|
1054 rss_interval = (5*(t2-t1)+512)/1024; |
|
1055 set_task_priority(TASK1, 196); // needs to be higher than DfcThread1 |
|
1056 set_task_priority(TASK2, 196); |
|
1057 random_sem_signal_interval = rss_interval; |
|
1058 random_sem_signal_count = rss_interval; |
|
1059 random_send_interval = rss_interval; |
|
1060 random_send_count = rss_interval; |
|
1061 |
|
1062 no_random_isr: |
|
1063 m = (msghdr*)alloc_mem_block(sizeof(msghdr)); |
|
1064 m->msg_id = MSG_ID_DONE; |
|
1065 send_to_epoc(m); |
|
1066 kprintf("All tests completed OK"); |
|
1067 for (;;) |
|
1068 { |
|
1069 int r = recv_msg(&m, WAIT_FOREVER); |
|
1070 assert(r == OK); |
|
1071 switch (m->msg_id) |
|
1072 { |
|
1073 case MSG_ID_DATA: |
|
1074 send_msg(RR_TASK, m); |
|
1075 m=NULL; |
|
1076 break; |
|
1077 case MSG_ID_FLUSH: |
|
1078 send_msg(L1_TASK, m); |
|
1079 m=NULL; |
|
1080 break; |
|
1081 case MSG_ID_DONE: |
|
1082 stop_random_isr(); |
|
1083 stop_timer(TM_TIMER); |
|
1084 suspend_task(L1_TASK); |
|
1085 suspend_task(L2_TASK); |
|
1086 suspend_task(RR_TASK); |
|
1087 suspend_task(TM_TASK); |
|
1088 suspend_task(TASK1); |
|
1089 suspend_task(TASK2); |
|
1090 suspend_task(TASK3); |
|
1091 suspend_task(TASK4); |
|
1092 break; |
|
1093 default: |
|
1094 kprintf("OC<-%08x",m->msg_id); |
|
1095 break; |
|
1096 } |
|
1097 if (m) |
|
1098 free_mem_block(m); |
|
1099 } |
|
1100 } |
|
1101 |
|
1102 #ifdef __cplusplus |
|
1103 } |
|
1104 #endif |