is fork() supported?
Andrew Haley
aph@redhat.com
Wed Aug 25 21:17:24 GMT 2021
On 8/25/21 5:59 PM, Kaz Kylheku (libffi) wrote:
> On 2021-08-25 02:27, Andrew Haley via Libffi-discuss wrote:
>> Note that this is *per thread*. other threads will simply continue to
>> execute code in the JITted region. The JIT can generate code, but can
>> not execute any JITted code until it calls
>> pthread_jit_write_protect_np(true). Of course this requires threads to
>> have differently-mapped regions. It would be very nice to have in
>> Linux. It is the right way to do it.
>
> It's *a* way to do it, but tweaking the address space so that it looks
> different in different threads seems extremely wrong and repugnant.
It works a treat.
> The threads of a process should live in exactly the same address space,
> in every detail: every page, every protection bit.
>
> There should be no TLB switching/flushing when we task switch from
> one thread to another in the same process.
>
> Of course, this is just another requirement, and no requirement
> is absolutely non-negotiable otherwise otherwise we have religion
> and not engineering.
I tend to treat sentences with a "should" but no "because" as ill-formed.
Only the pope gets to talk like that! ;-)
Why do you care anyway? It's not as if such things will be at all common.
It'll only happen if a thread's time slice expires while generating code.
> However, this is a pretty firm, fundamental thing, I would think!
>
> If it was done without actually making different memory maps per
> thread that would be great.
>
> For instance, suppose the mapping that is opened up for writing for
> one thread is actually write protected to all threads. What happens
> is this:
>
> 1. The "blessed" thread which owns the JIT mapping performs a write.
> 2. This traps into the kernel.
> 3. The kernel sees, aha, this is the blessed thread which is allowed
> to write.
> 4. The kernel emulates the write.
> 5. The thread's instruction pointer and other machine state is fixed
> up to look like it had done the write.
> 6. The thread is restarted.
>From userspace's point of view, that looks exactly the same, but much
slower. Seems to me that it's going to be more costly than an occasional
TLB flush; and if you have more processes than processors you're doing
that anyway.
> If the thread is not the blessed one, a fatal signal is generated,
> as usual.
>
> One the JITted code is installed, the blessedness goes away; all
> threads bomb if they write access it.
>
> Prior art for this, is obviously, things like simulating misaligned
> memory accesses on machines that trap on misalignment.
>
> The downside is that it's slow for writing a large amount of JIT
> material. Though installation of JIT material is amortized over the
> cost of compiling it in the first place, that may still be
> unacceptable overhead. (Also, it's not always amortized. Some
> ahead-of-time compiling situations would also use this mechanism;
> JIT is just a convenient acronym. Not all code loading is done by
> mapping directly into memory. In some languages, an code object
> might be read containing the executable code as a blob literal,
> which is then installed as if it came from JIT).
>
> Really, you need a dedicated write-like syscall for this, which the
> blessed thread can use to specify the bytes to be written to the
> JIT memory. That is similar to the solution involving writes to
> a file, except there is no file.
>
> In Linux, a possible place to dump this this might be oh, let's see,
> prctl?
>
> prctl(PR_WRITE_JIT, (long) dst, (long) src, (long) size);
>
> [dst, dst + size) must be a MAP_JIT mapping indicating the
> calling thread as being blessed, otherwise it fails.
Hmm, that might work, but would be a pain. In Java we
copy code around and then fix up the relocs at the destination
site.
--
Andrew Haley (he/him)
Java Platform Lead Engineer
Red Hat UK Ltd. <https://www.redhat.com>
https://keybase.io/andrewhaley
EAC8 43EB D3EF DB98 CC77 2FAD A5CD 6035 332F A671
More information about the Libffi-discuss
mailing list