Recent additions/changes (see personal repo) Marc Nieper-Wißkirchen (11 Nov 2022 17:19 UTC)
Re: Recent additions/changes (see personal repo) Shiro Kawai (14 Nov 2022 19:05 UTC)
Re: Recent additions/changes (see personal repo) Marc Nieper-Wißkirchen (14 Nov 2022 19:11 UTC)
Re: Recent additions/changes (see personal repo) Shiro Kawai (15 Nov 2022 08:31 UTC)
Re: Recent additions/changes (see personal repo) Marc Feeley (17 Nov 2022 13:22 UTC)
Re: Recent additions/changes (see personal repo) Marc Nieper-Wißkirchen (17 Nov 2022 13:51 UTC)
Re: Recent additions/changes (see personal repo) Marc Feeley (17 Nov 2022 14:24 UTC)
Re: Recent additions/changes (see personal repo) Marc Nieper-Wißkirchen (17 Nov 2022 14:44 UTC)
Re: Recent additions/changes (see personal repo) Marc Feeley (17 Nov 2022 15:38 UTC)
Re: Recent additions/changes (see personal repo) Marc Nieper-Wißkirchen (17 Nov 2022 16:26 UTC)
Re: Recent additions/changes (see personal repo) Shiro Kawai (17 Nov 2022 20:12 UTC)
Re: Recent additions/changes (see personal repo) Marc Nieper-Wißkirchen (17 Nov 2022 20:32 UTC)
Re: Recent additions/changes (see personal repo) Shiro Kawai (17 Nov 2022 23:02 UTC)
Re: Recent additions/changes (see personal repo) Shiro Kawai (17 Nov 2022 23:13 UTC)
Re: Recent additions/changes (see personal repo) Marc Feeley (17 Nov 2022 20:43 UTC)

Re: Recent additions/changes (see personal repo) Marc Nieper-Wißkirchen 17 Nov 2022 16:25 UTC

I understand your problem, and I agree that the first example (with
the recursive call outside a critical section) should be
interruptable.

The problem is that the interrupting thread and the interrupted thread
won't be synchronized.  We can only say that the interrupted thread
must eventually observe the interrupt.  But this is probably enough,
so we should add something along the following lines:

The interrupt must be handled eventually as long as the union of
intervals in which the interrupted thread has interrupts enabled is
unbounded.  (This is some kind of a rewrite of your "bounded"
condition.)

Am Do., 17. Nov. 2022 um 16:38 Uhr schrieb Marc Feeley
<xxxxxx@iro.umontreal.ca>:
>
>
> > On Nov 17, 2022, at 9:44 AM, Marc Nieper-Wißkirchen <xxxxxx@gmail.com> wrote:
> >
> > Am Do., 17. Nov. 2022 um 15:24 Uhr schrieb Marc Feeley
> > <xxxxxx@iro.umontreal.ca>:
> >>
> >>
> >> Marc
> >>
> >>
> >>
> >>> On Nov 17, 2022, at 8:51 AM, Marc Nieper-Wißkirchen <xxxxxx@gmail.com> wrote:
> >>>
> >>> Am Do., 17. Nov. 2022 um 14:22 Uhr schrieb Marc Feeley
> >>> <xxxxxx@iro.umontreal.ca>:
> >>>>
> >>>>
> >>>>> On Nov 11, 2022, at 12:19 PM, Marc Nieper-Wißkirchen <xxxxxx@gmail.com> wrote:
> >>>>>
> >>>>> I have documented thread-interrupt! in 5.14.6.
> >>>>>
> >>>>> Thread-exit! is now renamed to thread-stop!.
> >>>>>
> >>>>> I hope that only editorial changes remain before we finalize this.
> >>>>>
> >>>>
> >>>> I have problems understanding the spec for thread-interrupt!:
> >>>>
> >>>> (thread-interrupt! thread thunk)      procedure
> >>>>
> >>>> Schedules an interrupt for thread for when the current-interrupt-level of thread is zero. The current continuation of thread is then replaced by a continuation that records the values it receives, invokes thunk with no arguments, discards its values, and then yields the recorded values to the original continuation.
> >>>>
> >>>> Note: An interrupt can occur while a thread is blocked waiting on a condition variable.
> >>>>
> >>>>
> >>>> It mentions “replacing” the current continuation of the target thread by a new one.  I don’t understand that model which seems to assume that the computation moves from continuation to continuation (i.e. that calling a continuation marks the beginning of a computational step).  I think it also assumes that every point where a continuation is called is a “safe point” where the Scheme VM is in a consistent state.  But when a program is written in continuation passing style the implicit continuations are never called because the computation is strictly a sequence of tail calls with no returns.  Also the simple infinite loop (let loop () (loop)) never calls a continuation… so does that mean it can’t be interrupted?
> >>>
> >>> A continuation is not called; a piece of code is evaluated in a
> >>> continuation.  After each evaluation step (the spec is silent on how
> >>> fine-grained this is), there will again be a continuation (possibly
> >>> the same) waiting for the result of some evaluation step.  In essence,
> >>> I mean the same as your syntactic replacement of <expr> by (begin
> >>> (poll-interrupts!) <expr>).  To make it precise, we would really have
> >>> to amend the formal semantics of Scheme.
> >>>
> >>
> >> I understand.  In that case it would be good to add a reminder of this stepping model.
> >
> > Okay, will do!
> >
> >>
> >>>> I think a better way to explain it is that every expression <expr> in the program is conceptually treated as (begin (poll-interrupts!) <expr>) and then give a definition of (poll-interrupts!) that checks the current-interrupt-level and calls any pending interrupt thunks.  Also, the spec must explain that (for performance reasons) the implementation may postpone the polling, but only for a bounded time.  An interrupt check must also be performed when the interrupt-level is set to 0, either due to a call (enable-interrupts!) or (current-interrupt-level 0) or on the way out of a binding done with (parameterize ((current-interrupt-level …)) …) or on the way in of a binding done with (parameterize ((current-interrupt-level 0)) …).
> >>>
> >>> The latter is, in general, too strict; as the body of parameterize is
> >>> in tail context when parameterize is in tail context, every return
> >>> from a call can effectively set the interrupt level to 0, meaning that
> >>> interrupts would have to be polled at every return.
> >>
> >> Not every return, just a return that returns to a continuation marked with a “parameterize”.  This is the (usual?) trick to avoid administrative overheads when returning to a special continuation (such as a continuation that is no longer on the stack).
> >
> > You are right; but what is the reason you want an interruption to be
> > performed immediately?  And without any synchronization between the
> > interrupting and the interrupted thread, "immediately" is not even
> > clear to me.
> >
>
> The important point is not that the interrupt check is done immediately.  But there must be a garantee that as soon as a thread allows interrupts, i.e. the level reaches 0, the thread can’t delay handling the interrupt for more than a bounded time.  The situation that is problematic is:
>
>   (begin
>     (parameterize ((current-interrupt-level 1)) A)
>     …
>     (parameterize ((current-interrupt-level 1)) B)
>     …)
>
> Assume an interrupt happens during the evaluation of expression A, and that both A and B have a long execution time.  We want the interrupt to be handled after the first parameterize and before the second parameterize.  An easy way to do that is to force a check when the current-interrupt-level reaches 0.  Another way would be when the level is being changed to >= 1 and it is currently 0.  If that’s not garanteed then I think it would be legitimate to handle these two expressions equivalently:
>
>   (let loop ()
>     (parameterize ((current-interrupt-level 1)) A)
>     (loop))
>
>   (parameterize ((current-interrupt-level 1))
>     (let loop ()
>       A
>       (loop)))
>
> and this would be unusable.
>
> Marc
>
>