Question regarding the design decision of xEventGroupSetBitsFromISR

I have been quite excited about the new event group feature. There have been quite a few occasions where I found that I had a task that needed to block on multiple signals and the event groups look to be the answer for this. However I have a question regarding the design decision of xEventGroupSetBitsFromISR (and xEventGroupClearBitsFromISR?). The documentation states:
Setting bits in an event group is not a deterministic operation because there are an unknown number of tasks that may be waiting for the bit or bits being set. FreeRTOS does not allow non-deterministic operations to be performed in interrupts or from critical sections. Therefore xEventGroupSetBitFromISR() sends a message to the RTOS daemon task to have the set operation performed in the context of the daemon task – where a scheduler lock is used in place of a critical section.
I was wondering if this is a technical issue or more of a design philosophy issue. If it is the former, then perhaps a more detailed explanation might be helpful, however if it is the latter then I have trouble accepting this for the following reasons:
  1. The event groups are essentially like a group of semaphores and so the same reasoning could be applied to semaphores (there are an unknown number of tasks that may be waiting for the semaphore to be given). Why are semaphores treated differently in the context of an interrupt when their use is so similar?
* The implementation requires the use of an additional task and related overhead, which is otherwise unnecessary (well in my case it isn’t necessary). * xEventGroupSetBitsFromISR can fail to register the request which in my opinion makes it not deterministic and therefore defeating the purpose of the chosen design. Unlike a semaphore, it is unsuitable for use in an interrupt service routine because it cannot be relied upon to always be able to set the bit(s) and potentially unblock any task that is waiting for the bit(s). I wanted to use the event group mechanism for monitoring some “data request” inputs from several mp3 decoder ICs. Basically the idea was to have a single interrupt service routine and a single event group and just set or clear the bits depending on the state of the data request pins. Separate tasks for each mp3 decoder would then wait for their appropriate bit to be set before proceeding and also stop sending data to its decoder when the appropriate bit was cleared. However because of issue (3) above, I decided that the mechanism was unreliable and would lead to errors. I was also unimpressed by the additional overhead and decided that it wasn’t worthwhile.

Question regarding the design decision of xEventGroupSetBitsFromISR

The event groups are essentially like a group of semaphores and so the same reasoning could be applied to semaphores (there are an unknown number of tasks that may be waiting for the semaphore to be given). Why are semaphores treated differently in the context of an interrupt when their use is so similar?
With a semaphore it makes no difference how many tasks are actually blocked on a semaphore when it is given – only one task will be unblocked. The task that is unblocked is the highest priority task that is waiting on the semaphore (note this is unlike some systems which just unblock the task that has been waiting the longest – no matter the relative priority of the waiting tasks). The list implementation in FreeRTOS makes this a deterministic operation. You can there therefore calculate a known worst case – which is the case when a task is unblocked, as opposed to the best case when a task is not unblocked (because nothing was waiting for the semaphore). This is fundamentally different to the case where you use an event group because, unlike with a semaphore, setting an event bit can unblock between 0 and ‘n’ tasks at once, and the value of ‘n’ is not known so as far as the RTOS is concerned there is no calculable worst case – and the worst case may in fact (or is likely in fact) to be too long to be an acceptable operation to do from an interrupt. Again, other systems will do this, but FreeRTOS will not.
The implementation requires the use of an additional task and related overhead, which is otherwise unnecessary (well in my case it isn’t necessary).
It actually uses the same task as software timers. So if you are using software timers then no additional task is necessary. In your opinion, for your particular application, you suggest the additional task is not necessary. However, in the general case, I would suggest it was necessary for the reasons stated in reply to your first point. If I were to change the code to do everything from the interrupt then more people would be upset than were pleased.
xEventGroupSetBitsFromISR can fail to register the request which in my opinion makes it not deterministic
You mean the event queue might be full when the bit is set? If so it will probably trigger an assert() – giving you the opportunity to increase the size of the event queue so it doesn’t fail – or in fact handle the failure to post in any way you wish to recover gracefully. There is of course a physical limit to the processing power any particular chip can cope with, so there will be a physical limit to how quickly you can drain the event queue, but that is not unique to that particular queue – the same would be the case for any task processing. Regards.

Question regarding the design decision of xEventGroupSetBitsFromISR

Thank you for the detailed answer. A few questions/comments remain, however.
With a semaphore it makes no difference how many tasks are actually blocked on a semaphore when it is given – only one task will be unblocked. The task that is unblocked is the highest priority task that is waiting on the semaphore…
Is this not the case with the event groups? I was not aware of this one important difference. I guess I can understand this if the tasks are merely waiting for a particular bit to be set but what happens when the xClearOnExit parameter of xEventGroupWaitBits is true? Will all the tasks be unblocked or just one? Perhaps this difference between event groups and semaphores/mutexes needs to be specifically mentioned in the description of xEventGroupWaitBits. Could there perhaps be an option for xEventGroupSetBitsFromISR (and xEventGroupSetBits), perhaps as an option in the FreeRTOSConfig.h file? The option would select between the current behaviour where multiple tasks can be unblocked (and the daemon task must be used) or where only the highest priority task is unblocked (done directly in the interrupt without the daemon task). If only one task is ever waiting for a particular bit to be set then the argument that there are too many tasks for an interrupt to unblock becomes moot and a more optimised approach can be used.
It actually uses the same task as software timers. So if you are using software timers then no additional task is necessary.
I’m not using the software timers which is why I view this as additional overhead.
You mean the event queue might be full when the bit is set? If so it will probably trigger an assert() – giving you the opportunity to increase the size of the event queue so it doesn’t fail – or in fact handle the failure to post in any way you wish to recover gracefully.
Yes, the event queue might be full so the interrupt will not wind up setting the bit(s) in the event group. Increasing the event queue size from the interrupt is not an option when xEventGroupSetBitsFromISR fails and if a backup mechanism is required then this generally indicates to me that an alternative design is needed.

Question regarding the design decision of xEventGroupSetBitsFromISR

I think your questions are coming from your misunderstanding of what event groups are and how they are used, especially as you mention the ‘clear on exit’ option, which is not relevant to how many tasks get unblocked. When a semaphore is used only one task can ‘obtain’ the semaphore, as there is (conceptually) only one semaphore to take (assuming its not a counting semaphore). Hence only one task is unblocked when the semaphore is given. With an event group there might be lots of tasks waiting for any combination of bits in the event group – when those bits are set they are set, there is nothing that the tasks are ‘taking’ or ‘obtaining’, and any task waiting for that combination of bits is unblocked if that combination of bits are set. http://www.freertos.org/Inter-Task-Communication.html http://www.freertos.org/FreeRTOS-Event-Groups.html Regards.

Question regarding the design decision of xEventGroupSetBitsFromISR

Even ignoring the case of multiple tasks being unblocked, if tasks are using xWaitForAllBits set to true, then in constant time, it’s not even really practical to find out which task should be woken up! It would take an extraordinarily complicated data structure to be able to, in constant time, locate precisely the task that is waiting for not just the exact bits you are setting, but in fact any subset thereof.