Quality RTOS & Embedded Software

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


Loading

Semaphore monopolization

Posted by Andrew on February 23, 2010
FreeRTOS V6.0.2 and V5.0.2.

It is possible to make taking semaphore impossible. It happens when tasks running on equal priorities try to take semaphore. First one (see task1 below) takes semaphore rarely for short time, the second one (see task2 below) takes semaphore for longer time but gives it back for a very short time. Takin semaphore in task1 never succeeds. Explicit taksYIELD() would walk around this problem, but it has significant impact on performance.

Simply giving semaphore doesn't switch context to waiting task.
I think it is a BUG but I can't make a bug request. Can anyone help?



xSemaphoreHandle sem ;

void task1(void *pvParam)
{
while(1) {
if (xSemaphoreTake(sem, 100)) {
// BUG! We should be able to go into here, but it never happens
xSemaphoreGive(sem) ;

vTaskDelay(100) ;
}
}
}


void task2(void *pvParam)
{
while (1) {
if (xSemaphoreTake(sem, 50)) {
// Let's do something time consuming with semaphore taken
vTaskDelay(100) ;
xSemaphoreGive(sem) ;
}
}
}

int main( void )
{
prvSetupHardware();

xTaskHandle thDummy ;
sem = xSemaphoreCreateMutex();
xTaskCreate(task1, (signed portCHAR*)"1", configMINIMAL_STACK_SIZE, NULL, 1, &thDummy) ;
xTaskCreate(task2, (signed portCHAR*)"2", configMINIMAL_STACK_SIZE, NULL, 1, &thDummy) ;

vTaskStartScheduler();
}

RE: Semaphore monopolization

Posted by Dave on February 23, 2010
xSemaphoreGive() calls xQueueGenericSend(). Then within xQueueGenericSend() (on line 474 of V6.0.2) there is a call to xTaskRemoveFromEventList() which will return true if the queue send caused a task of EQUAL OR HIGHER priority to unblock (despite what the comment says). xTaskRemoveFromEventList() returning true will cause a yield, which is what you say should happen but isn't. It looks ok to me.

It is possible that in your example the timing is such that one task always yields to the other just at the end of the time slice, meaning that a yield is performed back again almost immediately. This would be legitimate behavior.

RE: Semaphore monopolization

Posted by Andrew on February 23, 2010
I is not about timing. Code below still shows the problem


xSemaphoreHandle sem ;
void task1(void *pvParam)
{
while(1) {
if (xSemaphoreTake(sem, portMAX_DELAY)) {
// BUG! We should be able to go into here, but it never happens
xSemaphoreGive(sem) ;
vTaskDelay(1000) ;
}
}
}

void task2(void *pvParam)
{
while (1) {
if (xSemaphoreTake(sem, 50)) {
// Let's do something time consuming with semaphore taken
vTaskDelay(100) ;
xSemaphoreGive(sem) ;
}
}
}

RE: Semaphore monopolization

Posted by Andrew on February 23, 2010
What is interesting, taskYIELD is called within xSemaphoreGive, but it looks like double context switch happens. Unblocked task was transferred to ready list, byt then taskYIELD cause context switch to the next one.

RE: Semaphore monopolization

Posted by Andras Brozso on February 24, 2010
Akuros, I think your code works as designed, too.

As I understand, in your example task2 will poll the system constantly and it excludes task1 processing with the semaphore. So task1 will - most likely - never got available time-slice to run (but it could happen, if the scheduler break task2 execution after sem.give and before the sem.take, but this is very unlikely), because they are on same priority level, and task2's sem.give will not force a context switch.

However, I'm not telling that there isn't bug in the scheduler, but I think this is not that scenario, where the scheduling fails.

RE: Semaphore monopolization

Posted by Andrew on February 24, 2010
Probably the code works as designed, but not as intended. task1 and task2 are on the same priority to keep priorities count as low as possible, to lower memory usage for semaphore and speedup scheduling mechanism. As I suspect a semaphore (as a queue) contains priority list of tasks waiting for the semaphore to unblock them on xSemaphoreGive. If it doesn't work as in example, semaphore could be built on simple volatile portBASE_TYPE, and could have significant lower memory usage.

However, I think it is still a bug, because in xQueueGenericSend there is an intended taskYIELD when we are giving back a semaphore which other task (on priority >= current) is waiting on.

RE: Semaphore monopolization

Posted by Richard on February 24, 2010
I'm not really following this.

It would appear to me that when a task gives a semaphore back then a context switch will be performed if there is a task of equal or higher priority that was blocked waiting for the semaphore. I think this is the expected and wanted behaviour.

If two tasks of equal priority then attempt to take the semaphore either could get it - there are no guarantees there.

Have I missed something?

Regards.

RE: Semaphore monopolization

Posted by Andrew on February 24, 2010
“If two tasks of equal priority then attempt to take the semaphore either could get it - there are no guarantees there.”


But when a task is already blocked on semaphore, and semaphore holder gives it back the context switch should be performed to the next waiting for this semaphore. In the example context switch is performed, but context remains in task giving semaphore. So the otther task has no chance to take it.

On xSemaphoreGive expected and wanted behaviour is that the context is switched to the next task waiting on the semaphore. And this task should be able to take it, because it is waiting for it. If there was such guarantee here, it would be really useful.

Regards.


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


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

Latest News

NXP tweet showing LPC5500 (ARMv8-M Cortex-M33) running FreeRTOS.

Meet Richard Barry and learn about running FreeRTOS on RISC-V at FOSDEM 2019

Version 10.1.1 of the FreeRTOS kernel is available for immediate download. MIT licensed.

View a recording of the "OTA Update Security and Reliability" webinar, presented by TI and AWS.


Careers

FreeRTOS and other embedded software careers at AWS.



FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

Espressif ESP32

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

Renesas

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

Xilinx Microblaze and Zynq partner