Eeek! A nasty bug has been lurking in waitQSemN, which as far as I
can make out has been there for ever. Presumably no-one uses this
abstraction...
The bug is that waitQSemN would discard any other blocked threads
(presumably waiting for a larger chunk of the semaphore) if it
succeeds.
It still looks to me like the quantity semaphores in here can suffer
from starvation: if one thread requests a large chunk, while lots of
other threads are requesting smaller chunks, then the thread
requesting the large chunk might never get to run. I'm sure this must
be a well-known problem.
MERGE TO STABLE
if (avail - sz) >= 0 then
-- discharging 'sz' still leaves the semaphore
-- in an 'unblocked' state.
- putMVar sem (avail-sz,[])
+ putMVar sem (avail-sz,blocked)
else do
block <- newEmptyMVar
putMVar sem (avail, blocked++[(sz,block)])