Interrupting repl in Slime

Alan Ruttenberg alanruttenberg at gmail.com
Fri Apr 8 01:26:46 UTC 2022


Some more: This is where the code for checking for interrupt is generated
(defun maybe-generate-interrupt-check ()
  (unless (> *speed* *safety*)
    (let ((label1 (gensym)))

* (emit-getstatic +lisp+ "interrupted" :boolean)      (emit 'ifeq label1)*
      (emit-invokestatic +lisp+ "handleInterrupt" nil nil)
      (label label1))))

I'm thinking, since interrupt-lisp isn't used anyways, modify it to take a
thread argument.
In interrupt-lisp, call setInterrupted with that thread.
In Lisp.java change the type of interrupted and change setInterrupted to
take a thread argument, setting Lisp.interrupted to it.

Then, in the maybe-generate-interrupt-check don't Lisp.interrupted check as
boolean, check if eq to current thread. The current thread can be made
accessible adding  (ensure-thread-var-initialized), which puts it into a
local at the beginning of the function. Access it with  (aload *thread*)
which puts it on the stack. I think this means that the lines underlined
above get replaced with.

  (ensure-thread-var-initialized)
  (emit-getstatic +lisp+ "interrupted" +lisp-thread+)
  (aload *thread*)
  (emit 'if_acmpne label1)

In Lisp.handleInterrupts it's setInterrupted(null) vs
setInterrrupted(false);

As stated, this mechanism is strictly to enable control-c.

However, maybe we could have it help thread-interrupt respond more
quickly.  in Lisp.handleInterrupts.
check thread.isInterrupted and call processThreadInterrupts (the thing that
is done now) otherwise break.
Have the implementation of thread-interrupt do what it does now and also
call interrupt-lisp to get it noticed.
---

I haven't tried this. Mostly I'm fumbling around trying to get enough
information to do this. I don't know java byte code except what I learned
researching this.
I don't know if there are pitfalls. I don't know why something like this
wouldn't have been done in the first place.

The only thing I can currently think of is that there could be a race
condition on setting Lisp.interrupted.
The consequence of that is that if there were two quick thread-interrupts,
only one of the threads would
do the quick response. The other would be processed in the way it currently
is.

Anyways, comments solicited.
Alan





On Thu, Apr 7, 2022 at 1:21 PM Alan Ruttenberg <alanruttenberg at gmail.com>
wrote:

> The functions that ABCL uses in Threads.java are thread.interrupt and
> thread.isInterrupted. It overrides interrupt and isInterrupted to implement
> interrupt-thread - by saving away the function the target thread is to be
> interrupted with.  Remember, interrupt-thread isn't executed by the thread
> to be interrupted, it's called from another thread. The receiving thread
> handles InterruptedException, which is only called on explicit check of
> interrupt state or from sleep or wait.
>
> Separately, in Lisp.Java there's setInterrupted and handleInterrupt that
> don't use the java mechanism. Rather setInterrupted sets a static volatile
> Lisp.interrupted, handleInterrupted clears the variable and calls break.
> setInterrupted, as I said, is only called from interrupt-lisp. Code
> generation inserts checks of Lisp.interrupted and calls handleInterrupted
> if it is set. I have a feeling that this part was done so that frequent
> interrupt checks could be made without taking the performance hit of a
> synchronized method call. Remember this check is done inside every loop
> iteration. The check for Lisp.interrupted is a volatile read, which in most
> cases is handled in the cache. A write to the volatile invalidates the
> cache forcing the new value to be read from memory. So much less expensive.
>
> It would be useful to know the history of how it came to be that there are
> two different interrupt mechanisms.
>
>
>
> On Thu, Apr 7, 2022 at 7:21 AM Alessio Stalla <alessiostalla at gmail.com>
> wrote:
>
>> No, I mean
>> https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#interrupted--
>>
>> The only deprecated methods are suspend, resume and stop. The interrupt
>> machinery is what developers are supposed to use (at least when not using
>> some higher-level framework). It's a form of cooperative multitasking,
>> since a thread can completely ignore the interrupt. However, given we have
>> control over Lisp threads, we can play nice with that convention, and maybe
>> offer a without-interrupts special form for performance-critical code where
>> the developer assumes the responsibility of checking for interrupts in
>> selected moments.
>>
>> On Thu, 7 Apr 2022 at 11:42, Mark Evenson <evenson at panix.com> wrote:
>>
>>>
>>>
>>> > On Apr 7, 2022, at 08:22, Alessio Stalla <alessiostalla at gmail.com>
>>> wrote:
>>> >
>>> > […] Java threads already natively have an interrupt flag.
>>>
>>> Presumably, the [Thread.State enumeration] is what you are referring to.
>>> I have checked that it is present in openjdk{8,11,17}, and not marked as
>>> deprecated.
>>>
>>> [1]:
>>> https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.State.html
>>>
>>> --
>>> "A screaming comes across the sky.  It has happened before but there is
>>> nothing
>>> to compare to it now."
>>>
>>>
>>>
>>>
>>>
>>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.common-lisp.net/pipermail/armedbear-devel/attachments/20220407/72579677/attachment.html>


More information about the armedbear-devel mailing list