Hi Rik,
I came up with a completely different approach:
The patch
a) fixes a lockup due to a missing restart.
b) makes the code again FIFO.
Changes:
- the wait-for-zero operations are moved into seperate lists. Thus they can
be checked seperately, without rescanning the whole queue.
- If a complex operating arrives, then all pending change operations are
moved into the global queue. This allows to keep everything FIFO.
Advantage:
- Fewer restarts in update_queue(), because pending wait-for-zero do not
force a restart anymore.
- Efficient handling of wait-for-zero semops, both simple and complex.
- FIFO. Dropping FIFO is a user visible change, and I'm a coward.
- simpler check_restart logic.
Disadvantage:
When one complex operation arrives, then the semaphore array goes into a
complex_present mode that always acquires the global lock. Even when the
complex operations have completed, pending simple decrease operations
prevent the array from switching back. The switch happens when
there are only simple wait-for-zero semops (or no semops at all).
But: Let's wait if this really exists: An application that does rarely
complex operations (and that doesn't prefer FIFO semantics).