Signal-based io questions
ambrus at math.bme.hu
Fri Sep 11 14:42:47 CEST 2009
Dear libev list,
Let me ask four theoretic question about what libev could do. These
questions are purely academic, as I am not actually planning to write
code using anything like these.
Unices have an interface where they can send a signal to the process
when a filehandle becomes readable or writable. This interface is
edge-triggered, so you don't get repeated signals if you do not
consume the input or fill the output buffer. The actual calls for
this on linux and bsd are fcntl function F_SETOWN. There are
essentially three ways this can help a program.
Firstly, the program can use a regular select loop, but as an
optimization it can rely on signal handling to interrupt a long
sequence of computations early instead of having to call a
non-blocking select every so often. Secondly, a program could rely on
blocking on signals only (with sigsuspend) instead of having to using
select to wait for any of io activity or signals, and then it can try
to read or write each file descriptor with non-blocking io. Thirdly,
a program can not only block on signals but use sigaction and
real-time signals to discover exactly what events happen.
My first question is whether this third method could be the base of a
backend in libev? There are some difficulties of course: the
implementation would be difficult, it might be hard to make it work
reliably, and it might not be more efficent than the best current
Secondly a seemingly unrelated topic. Some interpreters, most
importantly ruby 1.8 use a system where they use signals to implement
switching between threads on time slices. This works by setting up a
periodic timer signal that sets a flag, and checking this flag quite
often but only when it is safe to change to another thread, and if the
flag is set they call a scheduler to decide which threads are runnable
and which to switch to. There are other programs that use a similar
system as well, namely I think ruby 1.9, safe signals in perl 5.8 and
later, mz-scheme and the ghc runtime library, but I might not be
entirely correct here. The details like when the flag is checked and
how threads are switched differ of course.
My second question is whether libev could be used in the scheduler of
a system like this, to determine which threads to run? Perl Coro can
use libev to decide which coro to switch to, but it does not interrupt
threads on a timer before they would block. My guess is that libev
could work fine in a program like ruby 1.8 but there might be some
difficulty I'm not aware of.
My third question is whether you could improve some of these threading
systems by interrupting a running thread not only when its time slice
runs out, but also when an external event (io or timer or anything
else) makes another thread runnable? This could be implemented by
using the above mentioned F_SETOWN feature to request signals to be
delivered on an io event (and similarly setting up alarm signals for
the next timer event), and making these signals set that flag as well.
This could, I think, decrease latency. Of course, some care should
be taken not to let a thread starve others by arranging external
events to switch back to it, but this is not unsolvable. Note that
something similar is already done in such systems for internal events:
a function can yield its time to another thread it has just made
runnable as an optimization.
My fourth question applies only if the answer to the previous two is
yes, namely whether in this case libev itself could arrange for the io
and alarm signals to be sent on events the program is watching? This
way the program would have to register the event a thread is blocking
on, and then libev would use this both to determine which thread can
be ran next and to set the thread interrupt flag early.
Thanks in advance for any insights,
More information about the libev