Task Blocking on various Types of Primitives

FreeRTOS appears to contain a wide variety of primitives that a Task can block on; however, they don’t seem unified.

For instance, let’s say that I wanted a Task to block on two queues and a bitmap of Task Notifications. It doesn’t look like I can. I saw ‘Queue Sets’, which explicitly seems to glue together Queues and Semaphores, but this looked specific and disjointed.

Am I missing a lower level of ‘block this Task until’ functionality that all of the primitives can be folded into at the same time?

Thanks,

Greg

1 Like

No there is not any ‘select’ kind of behaviour outside of the TCP stack. You could do something in the application though. For example, if you want the task to be unblocked by either a message being posted to a queue or a task notification then you could instead have the task blocked on an event group - then when something posts to the queue it would also have to set a bit in the event group that unblocks the task and tells it (because of the bit that was set) that it needs to read something from the queue. Like wise when something sends a notification it would then have to set a bit in the event group to unblock the task and tell it to check its notification status or value.

QueueSets lets you block an a combination of Queues and Semaphores (as these use the same structures under the hood). But the other are all distinct.

I actually find I never need this sort of thing, To me it tends to say something isn’t partitioned right. For REAL-TIME applications, a given task tends to be doing mostly one thing, so it really only needs to block on that thing. If you really need to wait for multiple things, have every thing that sense to it, after sending over the channel you want, then send a direct to task notification. The task then waits for that, and when it get it, polls the rest with 0 block time till they are all empty, then goes back to block on the notification.

Hi there Greg,

you are looking for something similar to Windows’ WaitForMultipleObjects(). One can say about Microsoft whatever they think and feel, but it must be acknowledged that NT’s asynchronous I/O system is one of the most thought-out and versatile architectures ever made (no surprise, it was Dave Cutler’s masterpiece).

In a nutshell, any OS object is designed to be synchronizable through the same mechanism. For example, a thread can be suspended to wait on (either AND or OR combinations) File I/O, semaphores, network events etc. There are tons of use cases for that, one of the most powerful being I/O completion ports. I have implementing a form of these for FreeRTOS on my list of retirement projects.

Thanks to all for the replies. They’re appreciated!

@RAc,

I suppose that WaitForMultipleObjects() would fit the bill. Another quite-visible example would be the way the Amiga OS handled blocking; a single primitive called ‘Signals’ (bitwise, much like Task Notification) was the root of most of the higher level blocking primitives.

If I wanted to wait on a socket, a Message Port (think Message Queue), and a bitmap of Signals, I’d get the signal # for the socket, get the signal # for the Message Port, OR it with the bitmap of the Signals I already wanted, and wait on the set. When woke, I could determine which ones woke the thread and could process them. Credit to a fellow named Carl Sassenrath for that.

Simply, there’s a shared primitive. I was hoping for anything like the NT model (which isn’t RT friendly, but it’s also open-ended), or the Signal model above (which actually is RT friendly).

Thanks again to all for the replies; I’ll go see if I can either push Message Queues on top of Task Notifications (shared primitive path) or see if I can just use Semaphores instead of Task Notifications (path of least resistance).

Greg

The key is if you WANT to wait for multiple things, make those multiple things be Queue and/or Semaphores. Or, in a restricted case, you could make them all be Events (as you can wait for one of a multitude of events in a given EventGroup). This still has the limitation that a given thing can only be in a single ‘group’ and is always accessed on the receiving side as the group.

The other primitives have advantages in some speed, but that speed comes from NOT needing to deal with the complexity of multi-waiting.