kerneltest/e32test/personality/example/main.cpp
changeset 0 a41df078684a
child 43 c1f20ce4abcf
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     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