Blocking on Multiple RTOS Objects

Regarding xQueueSelectFromSet, it is written:
NULL is returned if a call to xQueueSelectFromSet() times out. Otherwise xQueueSelectFromSet() returns the handle of the queue set member that is ready for reading, allowing the calling task to immediately call xQueueReceive() or xSemaphoreTake() (on a queue handle or semaphore handle respectively) with the guarantee that the operation will succeed
In the world of synchronization, there exists analogues to xQueueSelectFromSet on other OS’s. On Windows, it is WaitForMultipleObjects. On Linux , it is epoll. On FreeBSD/etc. , it is kqueue. There has been quite a bit of discussion regarding the theoretically-correct model for mutliple-object synchronization, and what is more pratically correct. IMHO, of all of the synchronization frameworks, the Windows people found the “sweet spot”. In the context of this discussion, they made it so that if WaitForMultipleObjects returns true, the side-effect(s) of having successfully waited against a waitable object occurs, automatically, before WaitForMultipleObjects returns. I would like to know how receptive the community would be toward tweaking xQueueSelectFromSet so that the semantics changed to be more inline with WaitForMultipleObjects. I was hoping not to get into a lengthy discussion regarding the merits of why the auto-side effect model is better before hearing what others thought. Regards, SM

Blocking on Multiple RTOS Objects

I’m open to the idea, but for backward compatibility reasons I suggest it be a different function rather than changing the semantics of the existing implementation. Also, this implementation is not that efficient, predominantly because it was created when code size was a big concerns so it is built on top of existing code without adding a lot of new code. My preference is to use a model where all communication is sent through a single queue with part of the data that is transmitted informing the receiver of the nature (what the data is, where it came from, etc.) of the information – in the same way that were there more than one queue the queue on which data was received would inform the receiver of the nature of the information.

Blocking on Multiple RTOS Objects

Richard, After thinking about your model, one concludes that, indeed, a “wait for multiple sychronization primitives” function must be different from xQueueSelectFromSet. I guess I should reveal, upfront, what I have in mind, to avoid design-creep. I would like a “full complement” of synchronization primitives. Of course, FreeRTOS already has a surprisingly rich model for synchronization. Here, I am talking more about the waiting functions. These are the enhancments that I would make: 1. Create a new function xWaitForOne that waits against a single synchronization object. This function would take a TickType_t to specify time-out. 2. Create a new function xWaitForAny that waits against a multiple synchronization objects. This function would be able to wait for up to a #define specified number objects simultaneously. Microsoft calls their #define for this maximum MAXIMUMWAITOBJECTS. This function would take a TickType_t to specify time-out. 3. Make timer, event, semaphore, mutex, all waitable using xWaitForOne and xWaitForAny , using handles to such objects as arguments. 4. My prefernce would have been to modify FreeRTOS’s existing timer primitive to make it possible to insert its handle into xWaitForOne and xWaitForAny, but I am not sure whether that is desirable or possible. There is also the issue of FreeRTOS’s timer’s callback function, but that pointer argument could be set to NULL under the new model. 5. Coincidentally, in this thread, Richard Damon mentions that he has a C++ wrapper for FreeRTOS’s thread framework. When one clicks to see his code on github, it is clearly evident that he is heading in the same direction, as least for primitives. 6. For my personal use, “full complement” would mean adding shared-memory, but I realize that this is probably asking too much.

Blocking on Multiple RTOS Objects

I did not respond to your preference for the model that you described above. I did see your UDP example. The xWaitForAny model seems to be fundamental, no? Don’t want to appear to be a Big OS bigot, but the ability to stash handles of Semaphore/etc. into some kind of array, and wait on just that (no data tagging), seems to be very useful.

Blocking on Multiple RTOS Objects

Stack Master, while working with FreeRTOS for 13+ years, I never felt any need for a unified call that waits for many objects. The UDP example is indeed very useful. Mind you that the UDP library is now extended with many more protocols, like TCP, and it is now called FreeRTOS+TCP. The principles are still the same: IP-task listens to a queue, and the messages (IPStackEvent_t) are simple and fixed-size. They are treated in a first-in first-out order. ~~~ /* Message type that is sent to the IP-task. */ struct { eIPEvent_t eEventType; void *pvData; } IPStackEvent_t; ~~~ The task that handles the network interface (EMAC), works with two interrupts (RX/TX), and it is called “the EMAC deferred interrupt handler task”. The ISR’s do a minimum: read and clear a status of the peripheral. The high-priority task will be woken up (vTaskNotifyGiveFromISR), and take care of receiving and sending Ethernet data. Recently, Richard wrote a good an interesting text about semaphores and task-notify here. Don’t miss that. When I have a complex task that works with many different objects ( queues, GPIO-status, TCP sockets, audio controllers, etc ), I will have it block in a simple call to ulTaskNotifyTake(). All other tasks and drivers know the task handle, and they can ask for it’s immediate attention by calling either xTaskNotifyGive() or vTaskNotifyGiveFromISR().

Blocking on Multiple RTOS Objects

Perhaps the wrong link in that post?

Blocking on Multiple RTOS Objects

Hein, Thanks for that link. Per Richard (Barry)’s reply, I noticed that the semaphore aspect was missing from the link. I think what the OP wanted in that discussion was perhaps a condition-variable. I’ve never used them myself, but I have seen others talking about them. Regarding xWaitForAny, what about on “Big OS”? Haven’t you ever saw the need to wait on multiple objects in those Big OS’s?

Blocking on Multiple RTOS Objects

I noticed that the semaphore aspect was missing from the link.
Oops, sorry, I sent the wrong URL, should be when can we not use task notificatin as binary semaphore
Regarding xWaitForAny, what about on “Big OS”?
Wasn’t FreeRTOS an RTOS?
Haven’t you ever seen the need to wait on multiple objects in those Big OS’s?
Yes of course. When I write an application on Linux or Windows, I will use primitives like select() and semaphores much in the same way. There are all sorts of ways to treat devices (cq sockets) in asynchronous ways. I find select() and poll() very powerful on big OS’s.

Blocking on Multiple RTOS Objects

As you know, many coders have wrapped epoll(), WaitForMultipleObjects() etc. in C or C++ such that they never see these functions in our day-to-day coding. This is true for mutiple Big OS’s in my case. My C++ application compiles to 1.8 MB on Linux/x86-32, and I use event loops in my source code very often, but I never use epoll() or kqueue() explicitly. For several years, I watched FreeRTOS from the sideline’s thinking: That’s a nice OS. Too bad my application will not fit into a $10US computer. But today that is no longer true. There are many sub-$10US computers that can hold 1.8MB executables, and while some of them run Linux, many of them run FreeRTOS. Last week, I decided to look at FreeRTOS in more detail, and it occurred to me that, with some functions added, for my own situation, there is very little distinction between it and Big OS’s. If my app needs 43 threads running simultaneosly on an MCU with 8MB of RAM, no problem, whereas several years ago, it would have been a problem, because there was not enough RAM. Because the memory is now available, and multi-threading has always been available, and most synchronization primitives are available; the lure of being able to do a simple re-compile against FreeRTOS without changing any of my “regular” C++ is code is very hard to ignore. My guess is that the same is true for other people who are thinking about porting large applications to “small” MCU’s running FreeRTOS.

Blocking on Multiple RTOS Objects

While there is much similarity betseen an RTOS (especially a micro kernal like FreeRTOS) and a ‘Big OS’, there are also significant fundamental differences. A programmer who ignores these tends to write bad, if not broken code. One big difference is that with a ‘Big OS’, the OS has control of the machine, and parcels out access to the user programs, and those only have as much access as the OS gives them, and one of the key features is the OS is in control and is trying to protect one program from another. With an RTOS like FreeRTOS this is reversed. The program is in complete control over the machine, it owns it and controls it. The program gives the kernal usage of a few parts of it to get the services it needs. There is no fundamental concept of protecting the machine from the program. One spot this distinction shows up is in the identities of the fundamental program units to each other. In FreeRTOS we have Tasks, that interact with each other through global variables and various syncronization primatives. For the ‘Big OS’, this is pretty much like the basic thread. But the Big OS adds to that Processes which are mostly isolated from each other, and these Processes are often grouped into Sessions, and these Sessions are well isolated from each other. People confusing these two sometimes ask how to kill a Task and clean up its resources, thinking of Processes, which FreeRTOS doesn’t have. A second big spot where we see a difference is in I/O, in the Big OS, all I/O is provided by the OS and all communication needs to be done through well defined channels, it needs to be this way to protect differnet Processes and Sessions from each other. The OS needs to be in control. With FreeRTOS, it provides NO I/O, all I/O is provided by the user program, perhaps through standard library proceedures, but it is outside the kernel. This means there doesn’t need to be as uniform of an I/O interface, and the I/O drivers can be more customizable to the program needs. If your larger application has built into it the concept that it is a unique Process from parts of the system, and that there are other parts running that are well isolated from it, then it may well NOT be suitable for conversion to something like FreeRTOS.

Blocking on Multiple RTOS Objects

Valid points. First, I imagined my main 1.8MB application running on FreeRTOS, useful in its own right in isolation on a 32-bit sub-$10US MCU. Then I imagined several companion applications, each on the order of 50KB, running alongside the main application. Bcause My Code Is Perfect And Never Ever Ever Crashes ® , I was planning to approach the “no-processes” issue by simply lumping all the applications together into one image. However, certainly I am not the first person to think about adding a mechanism for processes and dynamic loading. For an MCU with 8MB of flash and 4MB RAM, the idea of dynamic loading, both in the terms of reading into RAM on command a new process, as well as run-time binding of symbols, is very attractive. But that is certainly not necessary to get the benefit of multiple “programs” running simultaneously. This is what lead me to my original post. FreeRTOS already provides so much of what my apps use on Big OS, I asked what else would be needed to provide a pain-free port, and it was xWaitForAny and xWaitForOne. If I could get C++’s RTTI, exception handling, and static initialization, (shared memory would be nice, but easily faked); I would be able to make a no-change port of an application that currently runs happily on a 16-core Xeon onto sub-$10 MCU’s. This is the allure: to be able to compile the same C++ code base for a $5000 machine vs $5 machine with essentially no changes to source or configuration changes other than editing a 8 or 9 .INI files to inform the applications that they are now running in only 4MB of RAM. Or, if I use FreeRTOS to determine total available RAM at start-up, then the only porting issues, aside from the above, is use of certain hardware-acceleration primitives (AES) that are different on the MCU’s and would have been necessary anyway.

Blocking on Multiple RTOS Objects

This should get added to the FreeRTOS users guide… ~~ _/) ~~~~ _/) ~~~~ _/) ~~~~ _/) ~~ Tom Lafleur
On Jun 25, 2019, at 6:57 AM, Richard Damon richarddamon@users.sourceforge.net wrote: While there is much similarity betseen an RTOS (especially a micro kernal like FreeRTOS) and a ‘Big OS’, there are also significant fundamental differences. A programmer who ignores these tends to write bad, if not broken code. One big difference is that with a ‘Big OS’, the OS has control of the machine, and parcels out access to the user programs, and those only have as much access as the OS gives them, and one of the key features is the OS is in control and is trying to protect one program from another. With an RTOS like FreeRTOS this is reversed. The program is in complete control over the machine, it owns it and controls it. The program gives the kernal usage of a few parts of it to get the services it needs. There is no fundamental concept of protecting the machine from the program. One spot this distinction shows up is in the identities of the fundamental program units to each other. In FreeRTOS we have Tasks, that interact with each other through global variables and various syncronization primatives. For the ‘Big OS’, this is pretty much like the basic thread. But the Big OS adds to that Processes which are mostly isolated from each other, and these Processes are often grouped into Sessions, and these Sessions are well isolated from each other. People confusing these two sometimes ask how to kill a Task and clean up its resources, thinking of Processes, which FreeRTOS doesn’t have. A second big spot where we see a difference is in I/O, in the Big OS, all I/O is provided by the OS and all communication needs to be done through well defined channels, it needs to be this way to protect differnet Processes and Sessions from each other. The OS needs to be in control. With FreeRTOS, it provides NO I/O, all I/O is provided by the user program, perhaps through standard library proceedures, but it is outside the kernel. This means there doesn’t need to be as uniform of an I/O interface, and the I/O drivers can be more customizable to the program needs. If your larger application has built into it the concept that it is a unique Process from parts of the system, and that there are other parts running that are well isolated from it, then it may well NOT be suitable for conversion to something like FreeRTOS. Blocking on Multiple RTOS Objects Sent from sourceforge.net because you indicated interest in https://sourceforge.net/p/freertos/discussion/382005/ To unsubscribe from further messages, please visit https://sourceforge.net/auth/subscriptions/

Blocking on Multiple RTOS Objects

The big issue is it sounds like you somewhere are assuming the process model (even if not needing it for crash protection). FreeRTOS by its nature doesn’t really support the concept of independant processes, as fundamentally the whole application is built into a single process. I say this because I do get C++’s RTTI, exception handling and static initalization in my FreeRTOS apps. Now static initialization all occurs by the spec before the start of the application main (which is before FreeRTOS starts) and not at the begining of some Task (as a task is not a process). Tasks also need to keep track of the resources they use and release those that need to be before terminating, as they aren’t Processes (so you don’t get the automatic cleanup of a process). In FreeRTOS you terminate the ‘Process’ by rebooting or turning off the system. Shared memory doesn’t need to be ‘faked’ as ALL memory is shared, unless you specifically make you task a restricted task (and then you just need to map the shared memory into one of the accessable segments). This is in part because FreeRTOS only supports MPUs not MMU (or more accurately, treats processors with MMUs as if they just had an MPU).

Blocking on Multiple RTOS Objects

Oh no, not assuming anything at all. I do understand all of that. I was approaching my problem from a practical perspective. I was thinking about what steps would minimize a porting effort from Big OS to FreeRTOS onto these devices. Without xWaitForAny , my code would have to change. With a few more functions, my code would not have to change. I mentioned the process issue while thinking about other programmers. If one takes an 8MB/4BM Flash/RAM MCU, that is clearly permits a different operating model than 32KB/4KB MCU. While it would be inappropriate to insist on adding a process model to FreeRTOS, one cannot blame some programmers for making the observation that 8MB/4MB is enough to provide sophisticated “Big Os” features. Naturally, any features added would have to be done in such a way so as not to interfere with extant FreeRTOS model. Dynamic-linking, which I am not proposing, but someone else wanted, would suddenly make sense. One can imagine that “system” DLL’s have been partititioned into an orthogonal baiss set, so that synchro primitives might be in one DLL, security in another, strings in another, network I/O in another, whatever. Then, even though no MMU features would be active, because, as I said, We All Write Perfect Code ®, one would have a situation where it would be possible to publish compiled software to run on sub-$10US devices. And that would permit the ultimate laziness: I would compile my 10 or so Big OS apps for my MCU of choice with 8MB/4MB. Then I would drag and drop apps to and from my Windows 7 machine to my MCU, mixing and matching ad-hoc, over the Internet, without rebuilding the OS. And I would induce the MCU to run which ever app I specify. I would also receive published binary from third parties, servers of various sorts, like an SSH-like server, for example.

Blocking on Multiple RTOS Objects

First big comment, With FreeRTOS there is no ‘rebuilding the OS’, there is just loading your program, and that is where there seems to be the fundamental disconnect in the model. With a ‘Big OS’ system, the OS owns the system and pulls in programs and various processes. This is the nature of that sort of machine. With FreeRTOS, you load your program into the machine that uses FreeRTOS as a library as part of the program. FreeRTOS doesn’t run your program, your program runs FreeRTOS (your application starts first, and sets up FreeRTOS and lets FreeRTOS control aspects of the application) Your vision seems to be to have some sort of Master Control Program that builds up an app from pieces, that MCP is NOT FreeRTOS, but could perhaps be a FreeRTOS based app that is able to assemble/download an app from some source. I am not sure how you envision this ‘combining’ of your multiple apps into a single unified app, that share a run time library with FreeRTOS without a compiling step (or at least a linking step).

Blocking on Multiple RTOS Objects

No disconnect. I am aware of the current FreeRTOS model. You are speaking about what is. I am speaking about what could be. First, there are two distinct topics here. One is xWaitForAny/xWaitForOne, which, if existed, would go a long way to getting me, personally, what I want, with no other change at all. The other is that, for MCU’s with a sufficient amount of Flash/RAM, it is possible for FreeRTOS to more to have Big OS features. One could start with the smallest notion of what constitutes an OS, and start adding features to this smallest notion. One might ask if the OS is multitasking. One might ask if there is hardware-enforced memory protection. One might ask if there is demand-paging. One might asks there is a distinction between user-mode/kernel-mode, and if so, whether user-mode code can gain acess to i/O registers. One might ask if it provides real-time support, etc; As one adds features to the hypothetical OS, the size of the code will grow, naturally. No one tool fits all situations, and so, OS’s will sometimes have a particular purpose, and certain features will be excluded, and some included. FreeRTOS has obviously been a fanstastic OS over the years and has served its purpose well for its chosen feature-set. If, it is predicated that FreeRTOS is only to be run on low foot-print MCU’s, and that any change that causes it to grow in size and or complexity is not permitted, then, well, there would be nothing to discuss, because the predication would mean that no non-sanctioned feature would be allowed, no matter how much flash/RAM is available. But if one discovers, by coincidence, that FreeRTOS currently runs on MCU’s that have near-Big-OS Flash/RAM, it is natural to ask what would happpen if FreeRTOS were modified to become a Big-Little-OS on these devices. By “modified”, I do not mean to say that it is changed fundamentally. I mean modified in the same spirit of a la carte pick-and-choose that currently exists. Another way to look at it is to imagine starting a new project to write preemptive multitasking OS from scratch, specifically targeted at sub-$10 MCU’s that have at least 4MB of Flash and 4BM of RAM. One will go through the usual (arduous) decision-making process of deciding what features should be included, size/performance trade-offs, abstraction barriers for hardware, etc. When one is finished, one will have a hypothetical OS. IMO, FreeRTOS (Richard), has done such a good job of being a “Little OS”, that this little OS is not so far from a Big OS in features for system-level “user-mode” coding. So if one were to write a new hypothetical “Mid-Size” OS that is not big, but capable of running Big Programs under a model that Big OS’s have done for decades; would one rewrite the hypothetical OS from scratch? Of course not. When you have something that is already 95%+ of where you want to be, you don’t start from scratch. You use what’s there, or at least try. The question then becomes: How wide is the gap between what exists and what you want? FreeRTOS is 95%+ (at least) of what I would want if I needed a “Little OS” that was capable of runing my Big Apps on sub-$10 devices in a manner that is currently done on Big OS’s. No, my apps would not run on an 64K/4K machine, but I’m OK with that. There are quite a few people who would be quite intrigued by being able to plop a distinct, compiled binary onto a running FreeRTOS MCU and have it execute in a manner that is currently done on Big OS’s. It would be a sweet spot between less capable RTOS’s and Linux/Windows Embedded. I see opportunity here.

Blocking on Multiple RTOS Objects

I thin you miss the key property of a micro kernal, which is what FreeRTOS is. FreeRTOS is focused on being a small basic very portable tool for building applications. Many of the features you are asking about don’t belong in the micro kernal. Let us compare this to your Big OS type system, most of these have a kernal with in them, but they are bigger than the kernal. Let us take a Linux system, and suppose we have a machine with JUST the kernal (and a few minimal drivers) installed. It boots, loads itself, and then effectively dies, as the kernal itself isn’t very usable. The kernal needs to start up a shell of some sort for the user to interact with. In the same way, FreeRTOS needs an application to run to do anything useful, but it doesn’t come with one built in, because there is no one most likely model for what it should be. Much oof what you talk about desiring for FreeRTOS to grow with is the domain of such a shell, not the kernal. I suspect that if you tried to build such a shell around FreeRTOS, you would find that there are many different ways to structure it, each with different abilities and limitations, and that no one structure is clearly best for the broad range of uses. Also, to really use the shell concept, you want the concept of a Process, so when you finish one task the system cleans itself up, but that level of tracking isn’t built into FreeRTOS as it is too expensive and not needed for most of its applications. It could be added in the shell/executive though.

Blocking on Multiple RTOS Objects

Again, you are speaking about what is, and I am speaking about what could be. 🙂 You are 100% right that FreeRTOS is currently structured a certain way because of original intent. Yet, if I had more time, I would make specific, deliberate modifications to that structure to realize something that a lot of engineers would find useful. That would be possible because FreeRTOS (Richard) has done an excellent job of keeping features orthogonal. By contrast, if AIX could run 8MB/4MB MCU, I would not be interested, because, despite being a “Big OS” with purportedly every tool under the Sun, AIX is functionally deficient in the area of sychronization, and there is no hope of enhancing it the way the Linux and FreeBSD have done to their OS’s. FreeRTOS, with modifications, has the potential to fill a “hole” in the OS market that no OS that I know of has currently filled. Barebones QNX/Windows Embedded are too big. There are a bunch of “weird” OS’s like TinyOS that reveal their weirdness (insufficiency for generalized purposes) almost immediately upon reading documentation. uCOS appears to have done a reasonable job heading toward a “regular set” of synchro primitives, but like FreeRTOS, it stops short of being able to wait, simultaneously, on multiple types of objects which, again, is what I want, and what I believe is an essential ingredient in the regular model for systems programming. The Linux and Illumos (Solaris) people eventually provided a primitive in this spirit, (eventfd), for multiple-object waiting which is sorta/kinda/mostly correct, but these OS’s, again, are too big. The FreeBSD people swear by kqueue, but not only does it not allow named waitable timers, to my knowledge, there is no wizardry that can be done to circumvent this “deficiency”. If there is, I’d certainly like to know about it. So one goes back to FreeRTOS, and though, say xTimerCreate does not use its pcTimerName argument in the same way that CreateWaitableTimer uses its lpTimerName argument, the argument is still there, and being present at all is a great convenience if one is to move in a direction of fully-generalized sychronization primitives. Taking all this into consideration, one might conclude that FreeRTOS, a tiny OS, has a more correct sychronization-primitive model than AIX, an obviously much bigger OS. This is the appeal: If there be such a thing as a regular set of syncrhonization primitives, FreeRTOS is closer to that model than AIX, IMO. This presumes, of course, that one has good intuition about what constitutes a “fully-generalized” set of synchronization primitives, and that there is concensus on what that set is. I’m claiming that Microsoft figured out what that set was, and “closure” of that set in FreeRTOS would be realized by creating xWaitForOne and xWaitForAny. Primitives beyond this basic set (fast “user-mode” spinlocks) then fall in the nice-to-have category, IMO. These primitives are best implemented in the kernel, as you know. The process-model, dynamica loading, etc. features…those are answers to a questions that a question that an OS theorist might ask: What features might be added to FreeRTOS to make it a full-generalized OS without significantly increasing its size or complexity? What is a fully-generalized OS, anyway?

Blocking on Multiple RTOS Objects

You say it is what it could be, I would say it is more what you want it to be, but for me, most of these are things I hope never become part of the kernel. I would not want to see any of these features added that add essential cost for system that don’t need/want it. I will say to begin with that I have NEVER found a need for a FreeRTOS task to wait on multiple things at once, NEVER. I will admit that some people have seen a need for something like that, which is why QueueSets were created, even if they are less powerful than you WaitForAny operation, but it seems sufficient for them, and it was able to be implemented at no cost to the basic Queue operation (a key feature). My first impession is this might be hard to do for your general WaitForAny call, and still keep the current bounded execution time for a queue read/write irrespective on how many/who is waiting for the queue. The one case where I have used a WaitForAny was in a multiprocess environments as part of inter-process communications. When Process A sends a request to Process B, it might use one of several different message forms, and Process B will typically have a single thread listening for all those messages and when it gets one, often forwards it to an appropriate worker thread. Thus this message pump needs a WaitForAny. Process A couldn’t directly address the needed thread, because that is a detail abstracted out by the process boundry. With Tasks, we don’t have that process boundry, so the Task that is acting like Process A, doesn’t need to address a dispatch thread in Process B, but can (and should) directly address the task that is responsible for that operation, which likely will be waiting for a single queue, or possibly a QueueSet if it handles multiple different sorts of things. What use of WaitForAny that isn’t brought about by the limitations of a Multi-Process envronment do you have? Adding the equivalent of processes to FreeRTOS would be heavy weight, and inappropriate. Some of your features might work as part of FreeRTOS/Plus. Just as I am glad that a network stack is not build into FreeRTOS as that is weight I rarely need, but is available by adding the appropriate additional package that builds on top of FreeRTOS, so perhaps some of your additions could be worked into an addon package like that. For example, your comment about timers using the name so that you could look up a timer by name. I see no need for something like that, as I generally know the timer I want to use, as it has a given purpose. The need to look up a timer by name mostly comes, in my opinion, from wanting to share the timer between processes (where you can’t just access the handle as a global). If you really wanted to be able to look up a timer by name, just add a wrapper layer that keeps a dictionary of timers with their names, and lets you look up a timer register through it. That would add no overhead to applciations/timers that don’t need it.

Blocking on Multiple RTOS Objects

The one case where I have used a WaitForAny was in a multiprocess environments as part of inter-process communications. When Process A sends a request to Process B, it might use one of several different message forms, and Process B will typically have a single thread listening for all those messages and when it gets one, often forwards it to an appropriate worker thread. Thus this message pump needs a WaitForAny. Process A couldn’t directly address the needed thread, because that is a detail abstracted out by the process boundry.
What do you mean by that? [I want to make sure that we are on the same page before responding to other comments in your reply.]

Blocking on Multiple RTOS Objects

Sorry for the delay, this thread is very off topic and I don’t think of it as urgent. When I build an application in a FreeRTOS like environment, all of my tasks have a specific function to do, and tend to have a very specific thing to wait on to do that task, They have no need for a WaitForAny operation. Because the whole application is inside one ‘Process’, it knows about itself and knows how to talk to the right pieces. The only cases I can see for a WaitForAny would be in a different environment where the whole system was bigger and bigger and contained multiple applications that aren’t supposed to know about how each other works and are to be isolated from each other, In this envronment, a given application may need to wait for multiple different things, and thus perhaps there is a need for a WaitForAny. As an example, in my library of widgets I put together to build system is a task that gathers certain envronmental attributes and determines certain condtions and broadcasts this state. In a Big OS type environment, it would need some form of configuring system for the details of how it is to work, and create some from of signalling queue that others interested in its results would listen to. Under FreeRTOS it is much simpler, I add the source file for the widget to my project, that widget includes a header file that isn’t part of its library, but part of the application where I put the parameters that adjust how the widget works. When it gets a result, it calls a function that it declares but doesn’t define (or only weakly defines) with the result, and the part of the system that wants the result defines that function. If I need that result in two or more places, I define that function to just call multiple other functions to let all the places that are interested know of the result. Much simpler code, but wouldn’t be allowed in a multi-process model without a lot of overhead, as processes can’t easily get into the internals of other processes. There is a fundamental difference in system design. A Big OS system puts at the top of the food chain, the OS, and it assumes that there are multiple users of the system wanting to use it that don’t necesarily total trust each other so it tries to provide isolate between each other. In FreeRTOS, at the top is the systems programmer that puts together the application that will run, ONE piece of that is the FreeRTOS kernel which is one of many tools to get the job done. It is assumed that the programmer is compitent and allows him to establish efficient channels between the pieces of the application. As I said in the beginning, I have NEVER seen the need for a WaitForAny type operation in my FreeRTOS designs, and I suspect that your desire from it comes from a multi-process mind set, and if you did get your WaitForAny, you would suddenly find the lack of those other things suddenly being the blockers. There is a LOT of overhead to support a multi-process execution model, that overhead is inappropriate for most of the systems targeted by FreeRTOS. It might be possible to provide much of what you need in a layer above/beside FreeRTOS, just like TCP or FATFS are provided.

Blocking on Multiple RTOS Objects

Sorry for the delay, this thread is very off topic and I don’t think of it as urgent. No worries. As I said in the beginning, I have NEVER seen the need for a WaitForAny type operation in my FreeRTOS designs, and I suspect that your desire from it comes from a multi-process mind set, and if you did get your WaitForAny, you would suddenly find the lack of those other things suddenly being the blockers.
Actually, the application that I have in mind is a single-process application that is useful in its own right. I just ran it on Windows 7. It is probably 2MB compiled, with run-time “private bytes” at 58MB, and working-set at 65MB. There are no other programs in my suite of applications that need to be run to make this single app useful. This application currently shows 16 threads running, and will burst to maybe 50 or 60 threads for a few seconds (have not tried yet). It is compiled from roughly 235 .cpp/.hpp files. When I consider porting this app, I ask what exists on the target OS, what does not, whether any deficiencies in the target OS are actually deficiencies, or if the problem is actually my model, etc. If I conclude that the issue is with the target OS, and that I have no choice but to change the app, I ask whether the change would result in a true port, or a pseudo-port, after the application has been lobotomized so much that it becomes something distinct from its original incarnation. Taking a step back and looking at the application, indeed all of the applications, and being honest with myself about whether there is something fundamental mssing in the target OS, or whether the problem is with my software architectures, I have concluded, to the best of my objectivity, that the issue is a deficiency in the target OS. Of course, this claim can only be true if the primitives that are “missing” really are theoretically-fundamental, which is why I said earlier, that I believe that WaitFormultipleObjects=xWaitForAny and friends are not “nice to haves’, but fundamental to generalized multi-threaded applications. This is actually the crux of this thread. It’s not really my asking for these synchro functions (I am), it’s asking another question: Given that there now exist sub-$10US CPU’s with, say, 8MB Flash/4BM RAM, that are too small for OS’s like Linux/Windows – Embedded/etc. (more or less), but big enough to run sophisticated, highly-threaded applications that normally run on Big OS’s, does there exist an OS that is small enough so as not to consume too much of the Flash/RAM of the MCU, but feature-rich enough so that generalized, multi-threaded (single-process) applications can be ported to it without overhauling the apps (supposedly theoretically-regular) architecture? I believe that the answer, today, is “No”. But FreeRTOS is very close.

Blocking on Multiple RTOS Objects

Let me ask you what set of Multiple Syncronization objects does any of your Threads (to translate to Tasks) needs to wait on, that wouldn’t be amendable to useing a QueueSet. My comment is that there are usually fundamental assumptions in large applications on how the system works and the move from a Big OS environment to a small efficient environment like FreeRTOS (small might still have a lot of resources, more that the kernel doesn’t use much of them). You say you feel it is fundamental, in my mind I can’t think of a real use for it, any ‘need’ is actually just a mispartioning of responcibilites. Part of the issue is that at its core, FreeRTOS to achive its objective of being a good Real Time system has tight limitations on the amount of work that needs to be done to manipulate the syncronization primatives. An open ended action like a WaitForAny tends to introduce extra work that might need to be done, and might make it hard to continue to make the constraints for those parts of the system that still need the tight limits. Most Big OS systems are designed to not worry about these real time requirements, and maybe support a limited subset that is sort of real time. Perhaps if you made an effort to look at what it would cost to add something like a WhatForAny operation that still maintained the real-time restrictions on those primatives.

Blocking on Multiple RTOS Objects

Waitable Timers. A thread might do all of the following things simultaneously:
  • Wait on 4 Semaphores.
  • Wait on 1 Event.
  • Wait on 3 Timers.
That is a total of 8 things to wait on simultaneously in an event loop. Naturally, this begs the question: “Should a programmer even be doing that?” I claim that the answer is “yes”. The mental relief that an engineer experiences under an event-loop is greater than that under call-backs or whatever other mechanisms are employed, IMO. Once a programmer gets used to this model, it becomes easier than trying to get the the format specifiers right in printf(). I do not believe that xWaitForAny wold be some whimsical nice-to-have that makes my job as a lazy programmer easier. I believe that it is fundamentally essential in the regular model for generalized multi-threading applications, in the same way that mutexes, themselves, are fundamental. I am saying that there is a reason that Dave Cutler and crew at Micosoft spent so much time crafting such a relative small number of OS functions (with huge salaries). I’m saying that Esdger Dijkstra, original author of the mutex and pioneering thinker in the area of synchronization and distributed computing, in general, would probably bless xWaitForAny as not a nice-to-have, but “fundamentally regular”. Ironically, at the time Dijkstra proposed his mutex, he received considerable push-back from other leaders in computer science, because they felt that his concepts of multi-threading were ridiculous. It often happens in engineering that some engineers will start insisting that certain things are fundamental, fiddling with them before they become widely accepted, while other engineers remain skeptical, because the extant model has been “good enough”. While the debate is ongoing, there will be a kind of “creeping” toward the truth. Eventually, it will be discovered that, indeed, the primitive is fundamental. And then of course, 10 or 20 years later, we will all look back and think, “So..what were we debating again?” For synchronization, this is happening, but is taking too long, IMO. Assuming that it is true that event loops are fundamental primitives of generalized multi-threading engineering, which I admit is still under debate, one might ask, “Where is the creeping?” It is libevent. There is also libuv. One can see the stumbling that occurs while said creeping is ongoing. For example, there people who are agnry with the design of the Linux equivalent of xWaitForAny, epoll. Their entire consternation can be traced back to a single design “flaw” which, unfortunately, is present in xQueueSelectFromSet(): The “flaw” is a counter-model to the following: If it is true that waiting for multiple objects simultaneously using a single function is a fundamental primitive in the realm of generalized synchronization, then that function must force the side-effect of the successfully-triggered object to occur before the function returns. Of course, xQueueSelectFromSet(), did not do this because it cannot, because not all elements in the queue can have their “side-effects” effected. This is true for epoll as well: Not all types of things that can be waited-on in epoll are amenable to being “side-effected”. This simple articulation of design choice has all kinds of ramifications for engineers trying to get their sychronization models right, hence the raging debate. For example, on Linux and FreeBSD, the number of waitable objecst can be on the order of 1000’s. The number of threads (Tasks) waiting can also be on the order of 10’s or 100’s. Then, when a waitable object (Semaphore/etc.) triggers, you’ll get 10’s or 100’s of threads suddenly coming awake, even though only one of them would have work to do, the so-called thundering herd problem. Not good. You are right, however: one would need to be sensitive to the effect of grafting-on new primitives onto a kernel that many people are alredy happy with. There would be a minimal tolerance to the imposition of time and space of the new primitive on the kernel, and this cannot be taken lightly. This is why any attempt to add xWaitForAny / etc. would have to be done with a lot of discipline and understanding of context in which it would operate.

Blocking on Multiple RTOS Objects

Ahh, that is the fundamental flaw in your design. A central core event loop is NOT a core concept in a single process real time system, but comes from the mindset of a multi-process system where something outside the process is sending the process various notifcations of things to do, and the outside world want to think of the process as a monolith. To get into details, you have said very little about what those are. WHY are there 4 semaphores, an Event, and 3 timers all providing a single task instructions about what to do? What are those semaphore signallig? What is the Event? Why is a single Task handling things at 3 different time rates? My guess is if proper factored, there is likely a better partition where there is a seperate task for each of these syncronization source, each waiting for a single thing and doing what it is asking for. My guess is you are deeply ingrained in a big machine model, and think that it is simple to just move it into a smaller machine. My experiance is that generally there are fairly significant assumption built into the design that really do depend on some of the heavy machinery of the big machine, and it really is much hard to port to the small environment.

Blocking on Multiple RTOS Objects

But I do not regard FreeRTOS as necessarily being a “real-time” OS, despite the “R” and “T” in “FreeRTOS” staring me squarely in the face. The key word is “necessarily”. Given FreeRTOS’s architecture, it is no more “necessary” to regard it as a real-time OS than it is to regard, necessarily, a Ford F-350 Super Duty pick-up truck as a towing vehicle. Both, given their architectures, can be multi-purposed. The question then becomes one of reasonableness: Is it reasonable to take the wife and kids out on a date in a Ford F-350? Sure. No problem. Is that why Ford created the F-350? No. Is it reasonable to add side-steps to make it easier for the little ones to climb-up? Yes. Does that hurt the overall purpose of the vehicle if Ford were to add that side-steps to all F-350’s? No. I do not see the “much harder to port to a smaller environment”. One might write the following code, then ask if it is portable: int x = 0; The answer had better be “yes”. Then one might ask again for: ~~~ struct Foo { int x; int y; } ; ~~~ Again, the answer had better be yes. One can play this game for the entirety of a codebase, where we eyeball each line of code, and ask ourselves, objectively, “Is this code truly portable?” If the code had been written with portability in mind from the outset, the answer will continue to be “yes”. There will eventually come a point where the answer is not only “no”, but there is nothing that the programmer can do to make it portable, because the code under consideration is inherently non-portable. We then focus on those lines of code and ask: * How much of this non-portable code is there in the entire application? * What is its nature? I/O? Sychronization? IPC? Harware control? Machine identification? In my case, the answers are, respectively: * <5% * synchronization Sure, there are issues with C++ RTTI, exception handling, etc…but these are relatively trivial. xWaitForAny is not trivial, and cannot be circumvented in my model. This gets us back to the sub-$10 MCU. The question becomes: Is there a market for a multi-tasking OS that can run Big Apps on a sub-$10 MCU. I claim that the answer is “yes”. Is there a multi-tasking OS that can run these Big Apps under a fully generalized multi-threading model on such an MCU? I claim that the answer is “no”. In light of what OS’s are available, does it make sense to write one from scratch? No. Why? Because FreeRTOS is already very close to what would be needed.

Blocking on Multiple RTOS Objects

To work your analogy, adding steps probably doesn’t impact its usability as the pickup truck it was designed as. Removing the bed in the back and replacing it with more seats probably does, even if some people think, I don’t use the bed, I just use it to tow my boat. It might make sense for a one off customization, but not something Ford would do to the base design. I suspect that adding a fully general WaitForAny might approach that latter. YOU don’t think of FreeRTOS as a Real Time system, and likely don’t have much in the way of real Real Time requirements. I can’t see something being added to the basic FreeRTOS design that breaks the fundamental RT design requirements. At first glance, I suspect that a fully generic WaitForAny is apt to break the Strictly Fixed Maximum Time rule that the core primatives have. QueueSets have a number of fairly specific limitations just because they were needed to maintain those requireements, and EventGroups needed a slightly inefficient design to maintain those requirements, with some some requirements on the priority of the Timer/SysReq Task. You are of course free to fork off the basic design and create a FreeOS project that meets your goals (just make sure you observe the licence of the pieces you use),