Memory order of `mprotect`

From: Yichao Yu
Date: Sat Apr 22 2017 - 09:50:06 EST


Hi,

For the purpose of concurrent/parallel GC (in userspace obviously),
I'm interested in what memory order guarantee is provided by the
mprotect syscall. My questions are (assuming no compilier reordering
or with sufficient compiler barrier)

1. If thread 1 triggers a segfault on an address due to a mprotect on
thread 2, can I be sure that everything happens on thread 2 before the
syscall can be observed in thread 1 in the signal handler of the
segfault? What if a full memory barrier is placed in the signal
handler before performing load on thread1?

2. If thread 1 does an volatile load on an address that is set to
PROT_NONE by thread 2 and didn't trigger a segfault, is this enough of
a happens before relation between the two. Or in another word, if the
two threads do (`*ga` starts as `0`, `p` is a page aligned address)

// thread 1
*ga = 1;
*(volatile int*)p; // no segfault happens

// thread 2
mprotect(p, 4096, PROT_NONE);
a = *ga;

is there a guarantee that `a` on thread 2 will be `1`? (assuming no
segfault observed on thread 1 and no other code modifies `*ga`)

I'm mainly interested in x86(_64) and arm/aarch64, maybe ppc too. So
far my tests on x64 and aarch64 suggests no violations of these though
I'm not sure if my test is conclusive or if the behavior can be relied
on in the long term. Some searching suggests that `mprotect` may issue
a TLB shootdown on all threads with the address mapped when permission
is removed which might provide the guarantee stated here though it's
unclear to me if future optimization of the kernel code could break
this guarentee.

Thanks.

Yichao Yu