[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Chicken-users] remove enable/disable interrupt flag

From: Alan Post
Subject: Re: [Chicken-users] remove enable/disable interrupt flag
Date: Thu, 29 Sep 2011 10:23:54 -0601

On Thu, Sep 29, 2011 at 05:06:54PM +0100, Alaric Snell-Pym wrote:
> Hash: SHA1
> On 09/29/2011 04:47 PM, Alan Post wrote:
> > It seems that the thread-like nature of signal handling and the
> > thread-like nature of threading have been intermixed in the
> > scheduler, and this particular feature is at cross-purposes.
> So it seems... Signals should always end up being handled somewhere,
> unlessly explicitly set to be ignored; in that case, ignoring it IS
> handling it, but not otherwise.

I'll add too that signals have an API-level mechanism for ignoring
them, which we should probably use.  And yes.

> IIRC, signals are handled by setting a flag and poking the stack limit
> then returning. A GC is then invoked as soon as the interrupted thread
> tries to allocate memory, due to the poked stack limit, but the GC
> checks for the signal flag and goes off to do the signal if it has to.
> I presume that invoking the Chicken runtime inside the C-level signal
> handler is unsafe on account of Chicken wanting to call non-signal-safe
> C functions.

It would be something of a minor miracle were this not true.  I
think it is technically achievable, though I say that with zero
understanding of the actual effort involved.  It's more my ideal
case worth banging my head against a few times than something I
think we can do in practice.

> I presume that allocating memory in a Chicken-level signal handler is
> "risky" as you might have actually been at or near the stack limit when
> the signal happened.
> I have not looked at the mechanism in code - just heard hearsay about it
> - - so please take this suggestion with a pinch of salt:
> 1) Have a (signal-safe) data structure containing pending signals. This
> might just be a bitmask, or if we want to be flash, a queue of generic
> pending "software interrupts" if there's uses for it other than signals.
> 2) C-level signal handlers poke an entry into the structure indicating
> the need to invoke a Chicken signal handler, and poke the stack limit
> [all of the above is basically what I think we already have]
> 3) The GC, invoked due to the stack limit being breached, checks for
> pending signals. If there are any, it resets the stack limit to what it
> was originally, then modifies the currently active continuation to a
> newly-allocated one that invokes a system procedure which executes all
> pending signals, then continues to the previous continuation; and returns.
> The normal stack limit needs to be set so that there will always, in the
> worst case, be enough space to allocate that extra continuation frame.
> If the system WAS at the edge of the stack when the signal(s) came in,
> it would then still be able to allocate the special continuation;
> execution of it would then almost instantly trigger a perfectly ordinary
> GC, and execution would continue as usual, executing the pending signal
> handler(s) then continuing with user code as before.

The Minix source code is illustrative on this point.  I think a
program being near the stack limit when a signal arrives is the only
time in that operating system that a process will be killed without
the normal mechanims the kernel goes through--It just tosses the
thing out.

I've never looked at how this behaves on *BSD or Linux, but I
imagine there is a similar condition (or as you outline above,
a reserve available).  So this comes up even in C, which at least
on Minux is not a handleable condition.

We effectively can't handle it if our GC makes a syscall--I imagine
that we minimally call sbrk() (or whatever the kids call it these
days) in the event of a full, post-GC heap.  That may well be a
terminal case in this rabbit hole, mirroring the terminal case in the
C code.

> That would give you low latency, unless the GC really needed to happen,
> in which case... well... it needs to happen before the handler can run.
> It would run signal handlers in the context of the currently executing
> thread when they happened, so to all intents and purposes it would be
> normal Chicken code, and the current thread would just temporarily dart
> off into signal handlers when required; I'm not sure what dynamic
> environment (in the parameters/current-output-port) they should be in;
> neither do I know how they are implemented in Chicken! Perhaps they
> should encapsulate a copy of the dynamic environment in place when the
> signal handler was registered, as the most hygienic option...

I pretty much rely on my registered signal handler being in the
dynamic environment it was declared in.  The EINTR test case uses
this to get hold of a file descriptor created in the main thread. 

I'll add that we might of course get a signal while performing GC,
a case that needs to be accounted for.  And that we also *must* handle
deferred signals before making another syscall, whether that syscall
happened from user code or whether we're making a syscall in service
to the need of the runtime.

I think is a fantastic outline of what needs to happen.  I will work on
a patch, with no guarantee of how fast I will be.

.i ma'a lo bradi cu penmi gi'e du

reply via email to

[Prev in Thread] Current Thread [Next in Thread]