Definition and use of Semas in FreeRtos

spreetsingh wrote on Monday, May 04, 2009:

This is a generic question on the use of Semas.
RTOS documentation states:
A binary semaphore need not be given back once obtained, so task synchronisation can be implemented by one task/interrupt continuously ‘giving’ the semaphore while another continuously ‘takes’ the semaphore. This is demonstrated by the sample code on the xSemaphoreGiveFromISR() documentation page.

Questions -
Who owns the sema as it is created? Is it the task that created it?
I have seen uses of this in the code, where the creating task explicitily takes the sema right after creation by calling the xSemaphoreTake and at other places, it just creates the sema.
Is there a rule to this?

Now the real question -
Let us say that a sema is shared between interrupt and a task.
Task creates the sema and waits on the sema for new data to arrive that is signaled by the ISR routine using the giveFromIsr call.

Before the ISR signals the availability of data with the givefromISR, who owns the sema? If the task owns the sema, it will always be looking at the data which is not there and so it constantly keeps looking for data (as it owns the sema) instead of waiting for data using the sema. If this is correct then it defeats the purpose of sema.

Is this correcty understanding?

Now a real example from the demo code:

I am looking at the web server code using uiP stack for the ARM7_LPC2368_Eclipse port FreeRtos release ver 5.2

Looking at the ARM_LPC2368_Eclipse code for uIP Stack in uip_task.c

xEMACSemaphore semaphore - is declared in emac.c and it is declared as external in uIP_task.c

1.  This semaphore is created twice by calling vSemaphoreCreateBinary( xEMACSemaphore ), once in uIP_task.c and once in emac.c
Is it OK to create it twice?

2. Once it is created, uip_task waits on this for new data to arrive with the following call in forever loop:
    xSemaphoreTake( xEMACSemaphore, configTICK_RATE_HZ / 2 );
3. This semaphore is given in an ISR routine with the:
     xSemaphoreGiveFromISR( xEMACSemaphore, &xHigherPriorityTaskWoken );

4. This sema is not given back by the uip_task anywhere.

when the uip_task goes into wait by  xSemaphoreTake(…), it will always be available even if the interrupt routine has not indicated arrival of new data with the givefromISR call.
Does this mean that the system is always polling for the data as opposed to waiting for the sema and then looking for the data?
3. No where in the code I see the sema being released by the uip_task.


edwards3 wrote on Monday, May 04, 2009:

I don’t know what you mean by “owns” a semaphore.

If a task tries to take a semaphore that is empty and specifies a block time it will enter the blocked state and not run again until the interrupt gives the semaphore or the block time expires. It does not poll the semaphore.

richard_damon wrote on Monday, May 04, 2009:

Semaphores are not “owned”, but are merely flags to indicate the availability of something. When FreeRTOS creates a semaphore, it creates it in the “ready” state so the next Take operation will immediately  succeed. If it shouldn’t, then after creating the semaphore, the creator should do a take to lower the semaphore.

The producer of the resource covered by the semaphore raises the semaphore (of "gives" it) and the consumer lowers (or "takes" it). This all assumes a binary semaphore. If you have a counting semaphore, then multiple gives can be queued up, to allow multiple takes afterwards. It is sort of like a queue without storing the data (which is actually how FreeRTOS operates them).

A Mutex on the other hand is owned. When a task wants access to a  shared resource it acquires the mutex, uses the resource and when it is done, releases the resource. If someone else wants the resource, the mutex locks them out until it is free. A Mutex is said to be owned by the task that has acquired it.

Note that a semaphore tends to be used for something that gets used up, so that when the consumer takes the semaphore, they are not expected to be returning it, while a mutex tends to be used on a shared resource to limit it to be only used by one task at a time, and when it is done it returns the resource to be able to be used by someone else.

spreetsingh wrote on Monday, May 04, 2009:

Thanks for quick response.

Let us say that a task creates a semaphore and tries to take it. Since it is empty, it will wait on it.
Now interrupt comes and does giveFRomISR - so, now the task that is waiting on it will be woken  and does its job and goes back to wait on this sema again. At this point, if the ISR does NOT do the giveFRomISR, what is the state of the sema? Is it empty?

How does it get set to empty?

spreetsingh wrote on Monday, May 04, 2009:

Richard - Thanks.
My understanding is that:
Underlying mechanism for this is the queue - which is either full or empty.
On creation, it is empty.
When a Give operation is performed, it becomes full.(kernel does this job)
When Take operation is performed, it becomes empty.(again kernel does this job)
And if it is already empty and a take operation is performed, it will wait on it till it becomes full.

richard_damon wrote on Monday, May 04, 2009:

When the task does a take,(ie when the take actually happens), the semaphore is set to empty, so when the interrupt did the give, it set the semaphore full, which then woke up the task, and finished the take and the semaphore goes back empty. When the task does the next take, the semaphore is still empty so the task blocks, until the take times out or something (like the interrupt) does a give.