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 Feeley 17 Nov 2022 15:38 UTC

> 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