os/kernelhwsrv/kerneltest/e32test/personality/example/main.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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