Quality RTOS & Embedded Software

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




Loading

xSemaphoreTake macro with delay 0 cannot work

Posted by madyn999 on September 14, 2015

Support says that xsemaphoretake with a delay of zero will poll the semaphore and return status without taking the semaphore.

The macro expansion sets the "just peeking" to pdFALSE. It always does, without any sensitivity to the value of time (which is passed to generic routines).

While the generic routines pay attention to the value of "just peeking" properly, the macro ignores the value of the delay constant.

Calling the base routine (xgenericqueuereceive) with the proper parameters works, but the macro does not work as advertised.

Version 8.2.2, Atmel XMEGA (not relevant since this is not in the port code), Atmel Studio (ditto with not relevant).

A limit check on the value of the timeout would fix the problem, (= 0 also says peek only), or perhaps fixing the macro with a conditional (if at all possible).


xSemaphoreTake macro with delay 0 cannot work

Posted by heinbali01 on September 14, 2015

Hi Harvey,

About the flag xJustPeeking, have a look in queue.h, under the function xQueuePeek:

Receive an item from a queue without removing the item from the queue.

Note that the a call with xJustPeeking == pdTRUE can also block, in case xBlockTime is unequal to zero.

The comment under xSemaphoreTake() says:

A block time of zero can be used to poll the semaphore

It does not mention the word peeking but polling. xSemaphoreTake() with a time-out of zero will really Take the semaphore if that is possible, it will not just check it's status.

Got it?

Regards.


xSemaphoreTake macro with delay 0 cannot work

Posted by madyn999 on September 15, 2015

The mcro XSemaphoreTake always sets xJustPeeking pdFALSE. Therefore the comment under XSemaphoreTake() is false, period, unless the definition of poll says to "take it anyway and return the status". This is not what Windows does in a similar situation and removes the ability to poll (peek) the semaphore status without affecting the flag.

Now the question becomes linguistic, what is the difference between peeking and polling? If I receive an item from a queue without taking it, shouldn't the item and queue be completely unchanged? I seem to remember that the standard queue allows this without removing the item (or "taking" it).

The behavior of a semaphore in this example, and a queue are different, yet the semaphore is a one unit queue. Using xSemaphoreTake with a duration of 0 does affect the semaphore, and to me, it should not.

As I said, I can work around this by using xGeneric stuff, but it seems inconsistent. Using the xSemaphoreTake macro with a delay of zero does not allow polling of the semaphore. How would you suggest, after reading the definintion of the macro, and still using this macro, that a sample of the state of the semaphore be obtained without affecting the state of the semaphore itself?

I will maintain that xSemaphoreTake with a time of zero should not affect the semaphore, and should return the status of the semaphore. I will also suggest that since there is NO macro that does this instead of using xSemaphoreTake with a time of zero, that the macro in question is simply not addressing this situation and is wrong. It was intended to work differently, and does not.

Since the underlieing code works one way (if fed by the macro properly), then I would suggest that the functionality is supposed to be there, and is consistent with the use of a semaphore as a single unit queue. The macro, as written, does not support this.

Perhaps we can simply modify the macro so that if the value of wait time is zero, we set xJustPeeking to pdTRUE.

Harvey


xSemaphoreTake macro with delay 0 cannot work

Posted by heinbali01 on September 15, 2015

Hi Harvey,

Perhaps we can simply modify the macro so that if the value of wait time is zero, we set xJustPeeking to pdTRUE.

I'm afraid that is not possible: it would break too many lines of existing source code :-)

what is the difference between peeking and polling?

Although I'm not a native English speaker, I'd say that the existing documentation (written by a native speaker) is accurate.

  • Polling is often associated with a non-blocking way of programming, as opposed to an interrupt-driven approach.
  • Peeking is sneakingly looking (peeping) into something, getting information without changing anything to what is being observed

The macro xSemaphoreTake always sets xJustPeeking pdFALSE

That is indeed what is promised by its name: Take a semaphore (not peeking) I do not see the relation between a blocking-time of zero ( "I don't want to wait for it" ) and making the xJustPeeking flag non-zero ( "I don't want to take the semaphore if available" ).

What would you thing of this addition to semphr.h :

~~~~~ #define xSemaphoreCanTake( xSemaphore ) ( uxQueueMessagesWaiting( ( xSemaphore ) ) != 0u ) ~~~~~

If it returns true, that means that the very next xSemaphoreTake() on that semaphore will succeed.

Any suggestion here, Richard?

Regards.


xSemaphoreTake macro with delay 0 cannot work

Posted by rtel on September 15, 2015

The mcro XSemaphoreTake always sets xJustPeeking pdFALSE. Therefore the comment under XSemaphoreTake() is false, period, unless the definition of poll says to "take it anyway and return the status". This is not what Windows does in a similar situation and removes the ability to poll (peek) the semaphore status without affecting the flag.

Now the question becomes linguistic

As you say, I think this is a linguistic thing. Let me explain how it is intended to work, then if you don't think this is how it is working, please let me know and I will investigate.

If you peek a queue then you return the first item in the queue (assuming there is data in the queue) without modifying the queue. That is, the item remains in the queue. Remember semaphores are macros that use the queues, so like many other queue API functions, you can also call xQueuePeek() on a semaphore.

If you read from a queue then you actually remove the item from the queue. If you take a semaphore, then you make the semaphore unavailable to any other task. When you read a queue, or take a semaphore, you can specify a block time, and the block time can be 0. If the call specifies a non-zero block time then it is a blocking call - if the queue is empty, or the semaphore is not available, the calling task will wait in the Blocked state until it either times out or data becomes available. If the call specifies a zero block time then it is a pollilng call because the function will return immediately to the calling task. If you make a polling (zero block time) call to take a semaphore, and the semaphore is available, then you will obtain the semaphore - as you called a function that is intended to take the semaphore you just specified a block time of 0.

I think this terminology is in common use. For example, if I am waiting for a bit to become set in a register then I can poll the register by sitting in a loop continuously reading the register, until the bit is set - or I can make a blocking call in which case I wait for an interrupt to tell me the bit is set. If I poll a semaphore, then I can sit in a loop continuously trying to take the semaphore with a zero block time, until the semaphore becomes available.

The behavior of a semaphore in this example, and a queue are different, yet the semaphore is a one unit queue. Using xSemaphoreTake with a duration of 0 does affect the semaphore, and to me, it should not.

I don't understand this. If you read a queue with a block time of zero, and there is data in the queue, then you will modify the queue too.

I will maintain that xSemaphoreTake with a time of zero should not affect the semaphore,

Is it not legitimate for somebody to want to take a semaphore with a block time of 0? In your scheme, how would that work?

It was intended to work differently, and does not.

As I said, I think this is purely a linguistic issue. You want to be using the xQueuePeek() function, not the xSemaphoreTake() function.

Regards.


xSemaphoreTake macro with delay 0 cannot work

Posted by madyn999 on September 15, 2015

OK, in part it is linguistic, and also in a major part, it is the intent of the design.

The difficulty I had is in the interpretation and intent of the macro. I'd favor the addition of xSemaphoreCanTake.

The reason is that I have a semaphore protecting the use of a graphics display. I have a background process that I want to check to see if the display is available, but I do not want blocking, I want skipping if the display was not available. The major process will, in this case, have priority. The definition of xSemaphoreTake implied to me that with a value of zero, I could, and would get the status of the semaphore without taking it. As I see, this is not the case.

Since the functionality is still useful, then xSemaphoreCanTake is a good idea.

Thanks for the detailed reply.

Harvey


xSemaphoreTake macro with delay 0 cannot work

Posted by richard_damon on September 16, 2015

I would assume that your task checking is going to want to use the display if it is available, and thus will want to take the semaphore. In that case a Take with a delay of 0 is exactly what you want. If is fails, you skip, if it works you use.

The biggest problem with a Semaphore peek is just because the semaphore was available then, doesn't mean someone else doesn't take it right after you checked. The only case I can think where I might want to use something like a peek would be if I needed to take a number of semaphores, but only if all were available, and that was somewhat unlikely. Then a round of peeks might be done and if all were available, then to a round of takes, unwinding if one fails at that point.


xSemaphoreTake macro with delay 0 cannot work

Posted by madyn999 on September 16, 2015

ah, now here's the problem: The display routine has the semaphore and blocking test, where I really want it to block (so the calling task blocks) if not available.

The problem is with a heartbeat task, which should update the screen if it can, but if it can't just skips the update until the next time through. The polling of the semaphore would keep this from happening unless there's a context change between the semaphore getting polled and the duration of the call and testing of the semaphore.

The ideal fix would be to call the display two ways, one with a semaphore (everything else) and a call that bypasses the display semaphore when called from a routine that can be thought of as a lower priority routne.

The higher priority routines (everything but heartbeat) block on the semaphore in the display routine itself. The lower priority routines would use xSemaphoreGet with a delay of zero, which would bounce out without the semaphore (and skip the update), which is fine, and if the routine got the semaphore, then it could keep it and update the display.

I was hoping to avoid that, but given the places where context changes could happen, I can still see problems with the original solution, and none with the second one.

I do admit that somehow the second solution seems not very elegant.

Although it is the solution, unless there's something I've forgotten.

Harvey


xSemaphoreTake macro with delay 0 cannot work

Posted by richard_damon on September 16, 2015

The problem is that context switches generally can happen at any time. Presumably, the heartbeat task is a low priority task (that helps detect some task hoging the system), so that means that the fact that heartbeat is running says all those other tasks are blocked. Unless ALL those tasks are blocked for a fixed time, the interrupt that signals the thing they are waiting for can happen at any moment. You also dont know that you aren't at the very end of a time slot (unless you read the timer and check). Even if you are coming out of a delay, a higher priority task might also have come out at the same tick and used up most of the tick, leaving you at the end.

Taking and giving an uncontested semaphore isn't that heavy of an operation, and is the only really clear solution.

One thing to think about, would be if using a Mutex rather than a Semaphore might make more sense. The question being if the priority inheretance feature would be helpful to handle priority inversion conditions (where a mid level non-display using task can block a higher priority task by interrupting a lower priority task while it is using the display)


xSemaphoreTake macro with delay 0 cannot work

Posted by madyn999 on September 16, 2015

That's not the way it works. While the heartbeat task could do task diagnostics, and may in the future; it is intended as a non-blocking screen update task. If the screen can't be updated, then that is acceptable. It is of equal priority to the other tasks.

Since in this system design, tasks are not created and destroyed, but only created, different task priorities do not seem to work well, the higher priority task gets all the processor time. Sill working on that one, though.

In this system, the tasks are blocked for access to resources or are blocked because there is nothing for them to do. The issue of priority inversion does not seem to be an issue yet.

The solution I have adopted is to call the graphics routine with an argument specifying delay. If it is zero, then the xSemaphoreGet macro can be called with a delay of zero. If the semaphore is gotten, then the graphics routine is called, if not, then the routine returns without using the display.

For any other task needing the display, those tasks are allowed to be blocked.

Checking the semaphore before calling the routine could result in a block because a context change could happen between the check and the time it is really gotten (call to graphics routine).


xSemaphoreTake macro with delay 0 cannot work

Posted by richard_damon on September 17, 2015

If you have higher priority tasks hogging the system, it sounds like an unusual use of an RTOS. I almost never create/destroy tasks after startup, and put tasks at a number of priorities. The key is that tasks should do what they need and then block until they need to do it again. (Only a task at the Idle priority, like the Idle task, should be allowed to not block). If a task being made higher priority can lock out the other tasks, then it sounds like it isn't blocking. (And if all tasks are the same priority, you can't get priority inversion).


xSemaphoreTake macro with delay 0 cannot work

Posted by heinbali01 on September 17, 2015

Richard Damon wrote: > The biggest problem with a Semaphore peek is just because the semaphore > was available then, doesn't mean someone else doesn't take it right > after you checked

True, but in some cases there is only 1 possible taker of a semaphore (or receiver of a queue). For instance the IP-task in the +TCP stack: it may safely check the length of the queue to see if there is an API call. Nobody else will consume these messages.

Harvey wrote: > different task priorities do not seem to work well, > the higher priority task gets all the processor time

True: in a RTOS the highest-priority task(s) that are runnable get all CPU time. As soon as a task goes in a blocked state, lower-priority tasks get attention. That is a choice-by-design.

You can:

  • either give your tasks the same priority and make sure that configUSE_PREEMPTION is defined as '1' (time-slicing)
  • combine several jobs within a single task and decide yourself how much time should be spent to each of the jobs.

Regards.


xSemaphoreTake macro with delay 0 cannot work

Posted by madyn999 on September 17, 2015

SInce the highest priority task never goes away, that's what I see.

For semaphores, in my design, there are many tasks that may want the semaphore, but only one can give it back.

Thanks for the information about the configUSE_PREEMPTION. I'll give that a try and see what happens. The design choice here is that I have a number of tasks that have equal priority (display, I2C input, I2C error, heartbeat, and perhaps a touchscreen task). The higher priority tasks (when I tried them) ran constantly, and the lower levels did not, even if I used a task wait. (as I remember it), so that suggested that all the tasks needed to be equal priority.

If I did not do this, then I'd have the overhead of creating and destroying tasks, but I was worried about the amount of overhead.

Harvey


xSemaphoreTake macro with delay 0 cannot work

Posted by richard_damon on September 17, 2015

Actually, in my designs it is almost ALWAYS that there is a single taker of a semaphore or receiver of a queue, The one major exception is for something link an I2C controller that may be used by multiple tasks to talk to devices, in which case the semaphore/queue is protected by a mutex. (And I use mutexes to provide exclusive access). I can see uses for checking the number of items in a queue, but I still don't see a common use for peeking at a semaphore.

As to tasks blocking, the basic purpose of using something like a RTOS is to get a 'real time' responce to an external request. You get the best response if the task that will handle the request is sitting blocked waiting for the request, and when the request comes in, the task unblocks and runs.

With what it sounds like you are doing, having to wait for time slices to past so the right task runs, you will get a MUCH longer delay to handling the request. It may be that you application doesn't really have any true real time requirements, but that should be an unusual case.


xSemaphoreTake macro with delay 0 cannot work

Posted by madyn999 on September 18, 2015

In my designs as well, a single taker of a queue. That is used for inter-task communications. Since the semaphore is used to prevent (block) access to a shared resource, well, I can see that semaphore taken by many, given by one.

The real time nature of the programming is mostly to expedite the I2C (or remote) access to the display Most of the tasks are blocked, since there is a vTaskDelay in most tasks, which are event driven. Almost all the tasks are event driven, waiting for a queue to deliver something, and therefore blocked. The only periodic task is the local screen update (heartbeat) which updates system statistics on the screen.


xSemaphoreTake macro with delay 0 cannot work

Posted by heinbali01 on September 18, 2015

Hi Harvey,

since there is a vTaskDelay in most tasks, which are event driven

The functions vTaskDelay() and vTaskDelayUntil() are not interruptable. If you want an event to interrupt a blocking call, the cheapest way is probably to use the Notify fuctions mentioned in task.h :

~~~~~ /* Unblocking from a normal task: */ BaseTypet xTaskNotify( TaskHandlet xTaskToNotify, uint32_t ulValue, eNotifyAction eAction );

/* Unblocking when called from an interrupt: */ BaseTypet xTaskNotifyFromISR( TaskHandlet xTaskToNotify, uint32t ulValue, eNotifyAction eAction, BaseTypet *pxHigherPriorityTaskWoken );

/* Wait to be notified: */ BaseTypet xTaskNotifyWait( uint32t ulBitsToClearOnEntry, uint32t ulBitsToClearOnExit, uint32t *pulNotificationValue, TickType_t xTicksToWait ); ~~~~~

These functions can be used to replace a semaphore in case it has only 1 taker. Note that you'll have to store a copy of the task's TaskHandle_t, and pass that to the task which will call xTaskNotify().

Earlier you wrote: > the higher priority task gets all the processor time. Still working on that one, though.

I'm still wondering: isn't the workload just too high for your CPU? And is that work which must be done within a certain time?

If not, you could also assign a very low (or IDLE) priority: that task will receive all remaining CPU time not used by other tasks.

Example: for the FreeRTOS +FAT testing there are 6 tasks continuously accessing the same disk: create, write, seek, read, and close files. The only time when such a task will block is when waiting for disk access. Among the 6 tasks there is time-slicing, each one tends to get 16.7 % CPU time. The application is still responsive: a telnet session is running at a normal priority and it will respond immediatelyto every request.

Regards.


xSemaphoreTake macro with delay 0 cannot work

Posted by richard_damon on September 18, 2015

Harvey, I tend to use a mutex for mutual exclusion instead of a semaphore, which gets around that case, but yes, if you use semaphores for exclusion, that would be a major exception to the one taker per semaphore.

I am not sure what you mean by 'Event Driven' and blocking on vTaskDelay. An event driven task should be waiting for the event, be it a semaphore or a queue to have data, or waiting for a TaskNotify. A task blocked on vTaskDelay CAN'T respond to an event, but must wait for its time to pass and then maybe check on things. This is not really event based.

You then say they are waiting for data in a queue, if so, why are the blocking on vTaskDelay instead of blocking on data in the queue they are responsible for? The only 'reasonable' answer I know is that they are waiting on multiple queue, which is normally a sign of a bad design. FreeRTOS has also added some multi-wait capability which can often even handle this case.


xSemaphoreTake macro with delay 0 cannot work

Posted by madyn999 on September 18, 2015

OK, I misspoke a bit. I am using a wait for an item on a queue to trigger processing.

In short, the system may be externally commanded by an I2C message. The interrupt handler builds the message, then puts it on a queue. The slave command task blocks on the queue, so it can respond quickly. That is the design model for any task that is queue driven.

This is a smart graphics display, which can be commanded by I2C or RF packets, and in addition, has a local status update which can be remotely controlled (on or off). The processor should spend most of its time waiting for a commands, and periodically update the status part of the display.

The display itself is managed by a single semaphore, which for almost all tasks will block the task.

The only tasks where a wait is used exclusively are status monitoring tasks where the output is meant to be information, and not a real time response. When those tasks update the display, they will skip an update if the display is unavailable.

I did have a queue on the display itself, but the amount of data passed to the graphics routine to draw a frame or button is fairly large, and since this is on an XMEGA I have a limited amount of available RAM. The idea was to keep local tasks (display status update) from interfering with the remote commands over I2C.

I'll try different priorities for some of the tasks, I'll be able to get a better idea of what's going on since I have run-time statistics implemented now.


[ 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