Are the standard library channels wait free? They are documented to be non-blocking (at least for
send for an unbounded channel and
try_send for a bounded channel).
That is not the same as wait free however, for example you might still get a deadlock in case of a priority inversion on a hard real-time system. I'm interested in if that can happen, specially in the context of real time threads.
I also looked around the rest of the ecosystem.
In summary: I would like a mpsc (or mpmc) which has a safe to use try_send. Safe to use from hard real-time threads that is.
From what I see in the implementation the channel has no starvation protection. If my limited understanding is correct you need additional memory
O(#threads) to implement this which is probably the reason why its not in std.
Good catch! Another issue I see there is the
backoff.spin_light call. I'm not sure if we can ever end up calling it in a spsc use, so the std channel might be safe to use in such a context.
But overall I will definitely stay away from these channels in any real time code, especially since the behaviour is undocumented and can thus presumably change in the future.
That's correct. If there's something you think should be guaranteed but isn't documented as such, you have to convince the libs team they don't need the flexibility to change it and get the guarantee documented.
I'm fine with having to use another solution, but that first requires knowing what things might be hidden problems. And that requires documenting such issues. It is always possible to lift such restrictions later as it makes more code accepted/possible. The other way around is indeed not possible.
The rust standard library has many things that are unsuitable for hard real-time (I would say it is outright real time hostile). I would rather that it was documented this was the case (what can lock, what can block, etc).
Some things are obvious:
- Mutex lacks support for priority inheritance (which is supported both via pthreads and directly via futex on Linux). Fortunately there is a crate for that. Unfortunately it requires that all your dependencies also use that crate, making it very limited. Sure, you can make sure to not use any such dependency in your real time threads, but since priority inversion is transitive, it can be an issue across the entire system.
- Channel is more insidious: it uses words like non-blocking that might make you think it should be fine, but it actually isn't.
- Are there other things that might be problematic? For example something using a mutable cache under the hood? I know the regex does this, not that you would ever use that in a real time thread. But maybe there is something doing a similar pattern in std, undocumented?
(Some things I consider obvious as a real time developer and have skipped above, such as never doing file IO or allocations in real time threads, and if you must allocate use some sort of memory pool of preallocated memory.)
In conclusion: I would like better documentation that things aren't real time safe. Because knowing is at least half the battle.