vTaskDelay and task starvation

nndpkz wrote on Tuesday, June 05, 2018:

Hi,

I have rather simple question which is probably due to my misunderstanding of basic RTOS scheduling. If 2 tasks like this:

void task1()
{
	while(1) {
		xil_printf("1");
		vTaskDelay( pdMS_TO_TICKS( 1000UL ) );
	}
}

void task2()
{
	while(1) {
		xil_printf("2");
	}
}

are run with same priorites, I’ve noticed that task1 will never be executed due to delay. Once I remove delay, the processing time between tasks is divided as expected.

Can anyone explain me this?

Best regards,
Nenad

dcrocker wrote on Tuesday, June 05, 2018:

Richard will probably provide a detailed explanation of what is going on. However, it looks to me that you are relying solely on the tick interrupt to share CPU time between the two tasks. This is rarely a good idea. If the printf function includes a mutex to prevent the output getting garbled, then most times the tick interrupt occurs, task2 will own that mutex so task1 can’t be scheduled.

I would try one or both of the following to resolve the problem:

  1. Increase the priority of task 1. It spends most of its time delaying, so you can do this without starving task 2 of CPU time.
  2. Add a taskYIELD call at the bottom of the task2 loop, so that you are not relying solely on the tick interrupt to schedule CPU time between it and other tasks of equal priority.

rtel wrote on Tuesday, June 05, 2018:

As per David’s reply - a lot will depend on how the xil_printf() is
implemented. Is it thread safe? If so, how is it made thread safe (see
David’s reply). If it’s not thread safe, then what you are doing is
dangerous as any state inside xil_printf() (like its access to whichever
console you are writing to) could get corrupted - even if no data gets
corrupted you could get strings interleaved at the output as you are
printing from two tasks simultaneously. Does xil_printf() block (not
return until all data has been output)? If so, then your application
will be running extremely slowly. Etc. A good proportion of support
requests that have a call to printf() in them are caused by the printf()
call itself. You can serialise print output by having a logging task -
when a task wants to print something it writes the message it wants to
print to a queue and the logging task reads the data from the queue and
writes it to the output port at a very low task priority.

nndpkz wrote on Wednesday, June 06, 2018:

Hi guys,

thank you for your help. It seems indeed that this was the problem with xil_printf() after all. I made another quick test such as:

void task1()
{
	while(1) {
		xil_printf("1");
		vTaskDelay( pdMS_TO_TICKS( 1000UL ) );
	}
}

void task2()
{
	int i = 0;
	while(1) {
		i++;
	}
}

and both tasks were executing expected (I checked task2 in debug mode). Also, if there isn’t any call to xil_printf in task1 neither, than it also executes as expected.

Best regards,
Nenad