In general, there are a couple of hard expectations related to mprotect that I believe are safe to assume (as in "would be surprising for an OS to not meet):
1. A call to mprotect() is fully ordered with respect to loads and stores that happen before and after the call. This tends to be trivially achieved at the CPU and OS level because mprotect is a system call, which involves a trap, which in turn involves full ordering. [In strange no-ring-transition-implementations (e.g. in-kernel execution, etc.) the protect call would be presumably responsible for emulating this ordering assumption]. 2. A call to mprotect will not return before the protection request semantically takes hold everywhere within the process. If the mprotect() call sets a protection that would cause a fault, any operation on any thread that happens after this mprotect() call is required to fault. Similarly, if the mprotect() call sets a protection that would prevent a fault, any operation on any thread that happens after this mprotect() call is required to NOT fault. On Tuesday, May 2, 2017 at 9:43:49 AM UTC-7, Yichao Yu wrote: > > Hi, > > IIUC, multiple JVM GC implementations use page protections for various > thread synchronizations. Obviously this will rely on the behavior of > mprotect in multiple thread WRT when the other thread can observe it when > one thread removed certain access on a page, especially relative to other > memory operations on either threads. > > However, I was not able to find any good/explicit document on what the > expected behavior is. What I do find (googling and on this list) is that > the OS will issue a TLB shootdown if the page is cached on another thread > and I suppose this is done in order to provide some ordering guarantee > (otherwise it can probably just not do this and give a "relaxed" ording > where different thread will observe this change in a random order after an > arbitrary length of time) though I cannot find a good description of what > the guarantee is. > > Maybe it'll be clearer with examples so let's suppose thread 1 changes a > page p from PROT_READ to PROT_NONE and thread 2 has a load from this page. > > 1. If thread 2 fault, is it guaranteed that this happens after mprotect on > thread 1? (Or in another word that sounds less weird, can it observer all > load/stores on thread 1 happens before any operations on thread 2 after the > fault?) > I think this is a "yes". If thread 2 faults *DUE TO* a protection that is first set by an mprotect() done by thread1 (note emphasis on the due to part), the expectation is that all stores done by thread1 prior to the mprotect() call will be visible to any thread2 operations that execute after the fault is triggered, and that all loads done by thread 1 before the mprotect() call will NOT observe any stores done by thread2 after the fault is triggered. > > 2. The other way around, if thread 2 didn't fault, is it guaranteed that > the load happens before mprotect on thread 1? In another word, is it > guaranteed that thread 1 will be able to oberve all memory operation thread > 2 has done before the load, right after mprotect returns? > I don't think that is provided, simply because there is no ordering implied or described between the two in the description above. You did not describe how Thread1 knows whether or not thread2 has done the (potentially faulting) load yet, and whether or not that load had faulted... If you include the fact that thread1 receives some indication about whether or not thread2 has done the load operation and about whether or not that load had faulted, you will have something to hang some ordering assumptions on. E.g. if you changed the above to say: "if thread 2 *performed a load that* didn't fault*, and thread 1 has received an indication that this thread 2 load was completed without faulting*, is it guaranteed that the load happens before mprotect on thread 1? In another word, is it guaranteed that, *after both the mprotect() call and establishing that the thread 2 load operation did not fault,* thread 1 will be able to oberve all memory operations thread 2 has done before the load?" Then the answer would be "yes". > 3. Does transitivity work? i.e. if therer's a thread 3 that's also loading > from p, and if thread 2 faults on the load while thread 3 doesn't, can we > say that thread 2 faults after the mprotect on thread 1 which is after the > load on thread 3 and therefore the load (and fault) on thread 2 happens > after the load on thread 3? > Same as (2) above. You'd need to describe how threads 1 and 2 observe whether or not thread 3's load has happened, and whether or not it has faulted. Then, depending on how that information is communicated, you would be able to establish some ordering. > Also link to my question on stackoverflow[1] > > Thanks, > > Yichao Yu > > > [1] > http://stackoverflow.com/questions/43722456/behavior-of-mprotect-with-multiple-threads > > -- You received this message because you are subscribed to the Google Groups "mechanical-sympathy" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
