Quality RTOS & Embedded Software

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




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 ]    [ Sitemap ]    [ ]




Copyright (C) 2004-2010 Richard Barry. Copyright (C) 2010-2016 Real Time Engineers Ltd.
Any and all data, files, source code, html content and documentation included in the FreeRTOSTM distribution or available on this site are the exclusive property of Real Time Engineers Ltd.. See the files license.txt (included in the distribution) and this copyright notice for more information. FreeRTOSTM and FreeRTOS.orgTM are trade marks of Real Time Engineers Ltd.

Latest News:

FreeRTOS V9.0.0 is now available for download.


Free TCP/IP and file system demos for the RTOS


Sponsored Links

⇓ Now With No Code Size Limit! ⇓
⇑ Free Download Without Registering ⇑


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

Renesas Electronics Gold Alliance RTOS Partner.jpg

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

Atmel RTOS partner supporting ARM Cortex-M3 and AVR32 microcontrollers

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

Xilinx Microblaze and Zynq partner

Silicon Labs low power RTOS partner

Altera RTOS partner for Nios II and Cortex-A9 SoC

Freescale Alliance RTOS Member supporting ARM and ColdFire microcontrollers

Infineon ARM Cortex-M microcontrollers

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

Cypress RTOS partner supporting ARM Cortex-M3

Fujitsu RTOS partner supporting ARM Cortex-M3 and FM3

Microsemi (previously Actel) RTOS partner supporting ARM Cortex-M3

Atollic Partner

IAR Partner

Keil ARM Partner

Embedded Artists