Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem TCP & FAT




Loading

Mutex runs not correct ?

Posted by Thang.Le on June 28, 2011
Hi all

i have a simply code using Mutex as following:
/-----------in main funtion ---------------------------/

xMutexLed = xSemaphoreCreateMutex();

xTaskCreate( vLED1FlashTask, ( signed char * ) "tLED1",
LED1_STACK_SIZE, NULL, tLED1_TASK_PRIORITY, ( xTaskHandle * ) NULL );

/* *********** tLED2 *********** */
xTaskCreate( vLED2FlashTask, ( signed char * ) "tLED2",
LED2_STACK_SIZE, NULL, tLED2_TASK_PRIORITY, ( xTaskHandle * ) NULL );


----------------2 tasks ----------------------

portTASK_FUNCTION( vLED1FlashTask, pvParameters )
{
while(1){
xSemaphoreTake(xMutexLed,portMAX_DELAY);
printf("----- change status LED 1");
xSemaphoreGive( xMutexLed );
}
}
//
//=================
portTASK_FUNCTION( vLED2FlashTask, pvParameters )
{
while(1){
xSemaphoreTake(xMutexLed,portMAX_DELAY);
printf("----- change status LED 2");
xSemaphoreGive( xMutexLed );
}
}
-----------------------------------------------

expected result will be:

----- change status LED 1
----- change status LED 2
----- change status LED 1
----- change status LED 2
----- change status LED 1
----- change status LED 2
..........

it mean that task vLED1FlashTask and task vLED2FlashTask will run in consecutively. However, actual result is vLED1FlashTask and task vLED2FlashTask will not run in consecutively. as:

----- change status LED 1
----- change status LED 1
----- change status LED 1
----- change status LED 1
----- change status LED 2
----- change status LED 1
----- change status LED 2
----- change status LED 2
....................

There is any bug in FreeRTOS ?

Thanks,
Thang Le

RE: Mutex runs not correct ?

Posted by Dave on June 28, 2011
“There is any bug in FreeRTOS”


Not that I know of or have ever found myself.

“expected result will be:

----- change status LED 1
----- change status LED 2
----- change status LED 1
----- change status LED 2
----- change status LED 1
----- change status LED 2”


Why?

RE: Mutex runs not correct ?

Posted by Thang.Le on June 28, 2011
add more: priority of tLED1_TASK_PRIORITY and tLED2_TASK_PRIORITY is same.
tLED1_TASK_PRIORITY = tLED2_TASK_PRIORITY .

configUSE_PREEMPTION = 1

Thanks,
Thang Le

RE: Mutex runs not correct ?

Posted by Thang.Le on June 28, 2011
hi davedoors

my program is only 2 tasks and we have same a priority. actual of vLED2FlashTask is:

//=================
portTASK_FUNCTION( vLED1FlashTask, pvParameters )
{
while(1){
xSemaphoreTake(xMutexLed,portMAX_DELAY);

printf("----- change status LED 1");
for(int i=0;i<1000;i++);

xSemaphoreGive( xMutexLed );
}
}
//
//=================
portTASK_FUNCTION( vLED2FlashTask, pvParameters )
{
while(1){
xSemaphoreTake(xMutexLed,portMAX_DELAY);

printf("----- change status LED 2");
for(int i=0;i<1000;i++);

xSemaphoreGive( xMutexLed );
}
}

and portTICK_RATE_MS = 3 second .

So, i think above expect result is OK ?

Thanks
Thang Le

RE: Mutex runs not correct ?

Posted by Dave on June 28, 2011
If the priorities are the same then a switch between the tasks will happen when a tick interrupt happens. I cannot tell from your code how long printf() will take to execute, maybe a tick interrupt happens once every 50 calls to printf(), maybe 50 interrupts happen during one printf() call, who knows. Also, does printf() stop the processor executing when it is called. Sometimes that is the case when if printf() is directed out a debug port.

Have you checked xMutexLed was actually created correctly and is not NULL?

As the tasks are the same priority and make a blocking call, then there is a chance that the pattern you expected would happen during execution, as when one task gives the mutex back the other one will unblock and start executing. That is not guaranteed though as it depends on the timing of the execution relative to the tick interrupts firing.

RE: Mutex runs not correct ?

Posted by Richard Damon on June 28, 2011
The issue is that giving a semaphore that another task is waiting on, does not automatically give them them the semaphore, but unblocks them so when they next get time, they will try and take it. Since each task after giving immediately takes it back, on the next tick when the other task gets time, it finds that the semaphore isn't available and blocks again.

What you should do is add a taskYield after the give, thus giving the other task a chance to grab the semaphore before it tries to take it back.

RE: Mutex runs not correct ?

Posted by Thang.Le on June 29, 2011
thanks all,

in my view, i always think that whenever we call a System call ( RTOS API) then a scheduling operation will happen. So, whenever i call xSemaphoreTake or xSemaphoreGive , then context switching must occur. This is to guarantee for real time attribute of a RTOS.

@ richard_damon: Thanks for your suggestion

Thanks,
Thang Le

RE: Mutex runs not correct ?

Posted by Richard on June 29, 2011
In fact, if sending a semaphore unblocks a task of greater than or equal priority to the sending semaphore, then a task a yield will automatically be performed within the API function itself - so putting a yield after the xSemaphoreGive() should not, in theory, make a difference. It was a logical suggestion though.

There is not really enough information in your post to provide a definitive answer, for example, what is printf() doing? Have you tried flushing stdout after calling printf(). Which port are you using? etc.

There are two plausible theories, that I could not verify without actually having your code to debug in front of me. The first is less plausible than the second, because the timing would have to be very critical:

1) Task A takes the semaphore.
2) Task B blocks on the semaphore.
3) Task A prints out is message, that takes 98/100ths of a tick period.
4) Task A then yields, that takes 1/100th of a tick period. There is now only 1/100th of a tick period left.
5) Task A yields as it gives the semaphore back.
6) Task B runs, but only has 1/100th of a tick period left to execute so does not do much.
7) A tick interrupt occurs and re-selects task A to run before task B has done anything.
8) Task A takes the semaphore and continues on its merry way. When task B runs again, the semaphore is still not available (task A has it again) so blocks once more.

or

1) Task A takes the semaphore.
2) Task A prints out its message, that does not take very long at all, say 5/100ths of a tick period.
3) Task A gives the semaphore back.
4) Task B has not run since Task A originally took the semaphore because Task A's operation only took a fraction of a tick period, so task B is not Blocked on the semaphore when task A gives it back, and therefore no automatic context switch occurs and Task A just continues on and takes the semaphore again.

The third scenario would be that printf() is doing something dramatic to the debug interface, which is halting the CPU or messing with interrupts, and so nothing can be guaranteed about how the application will execute.

You could use the trace macros to find out the actual execution pattern, then you would have an absolute answer, but that would take probably twenty minutes to set up and require a mechanism of obtaining the trace output.

Regards.

RE: Mutex runs not correct ?

Posted by Thang.Le on June 29, 2011
Thanks richardbarry,

re-check in first scenario:

1) Task A takes the semaphore.
2) Task B blocks on the semaphore.
3) Task A prints out is message, that takes 98/100ths of a tick period.
4) Task A then yields, that takes 1/100th of a tick period. There is now only 1/100th of a tick period left.
5) Task A yields as it gives the semaphore back.
6) Task B runs, but only has 1/100th of a tick period left to execute so does not do much.
7) A tick interrupt occurs and re-selects task A to run before task B has done anything.

Because at last time, Task A ran and Task A priority = Task B priority. next task is selected should be Taks B ? I think that will be suitable more.

In second senario:

....
3) Task A gives the semaphore back.

in my idea, Even though a interrupt tick has not ocurred yet, but the context switching should ocurr and Taks B will be selected to run. when the interrupt tick ocurrs, then context switching will ocurr again, and Task A will be selected, Task A takes the semaphore and go to Block state (because Task B is holding the semaphore) , context switching repeats again, and so on...

BTW, which i need is a thing similar as event flag for synchronizing tasks. Because can not use Mutex, Binary semaphore. So, i used the Queue and program ran as expected: :))

----- change status LED 1
----- change status LED 2
----- change status LED 1
----- change status LED 2
...

This is my code:

portTASK_FUNCTION( vLED1FlashTask, pvParameters )
{
char cValueToSend = 0;

while(1){

xQueueSend( xQueue_1, &cValueToSend, portMAX_DELAY);

for(int i=0;i<50;i++)
printf("----- change status LED 1");
}
}
// ==============================
portTASK_FUNCTION( vLED2FlashTask, pvParameters )
{
char cReceivedValue;

while(1){
xQueueReceive( xQueue_1, &cReceivedValue, portMAX_DELAY );

for(int i=0;i<50;i++)
printf("----- change status LED 2");
}
}

I am using IAR, port: AT91SAM7S256.
printf is only put characters to DBGU.

detail here: http://letrungthang.blogspot.com/2009/11/arm.html

More again, thanks all
Thang Le

RE: Mutex runs not correct ?

Posted by Thang.Le on June 29, 2011
oh my god, i guess that the program with Queue, may be result as:
----- change status LED 1
----- change status LED 2
----- change status LED 1
----- change status LED 2
----- change status LED 1
----- change status LED 2
----- change status LED 1
----- change status LED 2
----- change status LED 2
----- change status LED 1
----- change status LED 1
----- change status LED 2

do you agree me :-))

Thang Le


[ Back to the top ]    [ About FreeRTOS ]    [ Sitemap ]    [ ]




Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.

Latest News

FreeRTOS kernel V10 is available for immediate download. Now MIT licensed.


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

OpenRTOS and SafeRTOS