Skip to content

Use virtual memory tricks to make interrupt checks smaller and faster #1749

@fitzgen

Description

@fitzgen

Right now, to check if for interrupts:

  • we load the interrupts pointer from the vmctx
  • we dereference it to get the maybe-interrupted value
  • we compare that against the interrupt-has-been-requested value
  • and finally we conditionally trap when the comparison returned true.

There is no fast/slow path split here. Interrupts happen rarely, but we always perform those four steps.

By using virtual memory tricks, we can create a fast path for the common case when no interrupts are requested. We reserve a page of memory as the "interrupt page" and point to it from the vmctx. This replaces the current interrupt pointer on the vmctx. When interrupts are not requested, this page is readable. When an interrupt is requested, remove the readable bit via mprotect, and wait.

Now, all that our loop headers do is:

  • load the pointer to the interrupts page from the vmctx
  • (attempt to) read the first byte from the interrupts page

When the interrupts page is readable and an interrupt is not requested, we just have those two loads as our fast path.

When the interrupts page is not readable because an interrupt is requested, a signal is generated, so our signal handler needs to recognize+handle this case.

IIRC, essentially this same trick is used in some JVMs for synchronizing at safepoints for stop-the-world GC phases (e.g. root marking).

The one open question is how to detect stack overflows with this setup, since our interrupt handling and stack overflow code is very intertwined. Not totally sure here.

+cc @alexcrichton

Metadata

Metadata

Assignees

Labels

enhancementwasmtimeIssues about wasmtime that don't fall into another label

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions