I see code like __CPROVER_fence("RRfence", "RWfence");
being using in projects like the Linux RCU testing and pthread wrappers for CBMC analysis. I looked at the online documentation, but found no text on the strings sent to this CBMC function.
What are the available parameters to __CPROVER_fence
?
My take is that it is an annotation/function to denote barriers/fences performed by the real implementation. Ie, it is an analysis stub for the real functionality. Obviously the parameters denote types of barriers, but I have not found a reference to the actual parameters and corresponding barrier types. Ie, "RRFence" is a read fence, meaning reads before this point will complete before reads after this point (as a guess).
Use the source Luke.
All notation are 'fences' to say that some CPU barrier primitive has prevented the hazard type from occurring. So, it is all prior "read/write" will be committed
to cachebefore the subsequent "read/write". The 'function' can accept any combination/permutation of these values.'cumul' versions are documented in section 4.4.2 of Herding cats..., they are 'transitive' fences which show that all threads/cores will see the ordering.
Indeed as Hasturkun has pointed out, there are eight annotations accepted by
CPROVER_fence()
. See wikipedia hazards for details as well as other cited papers.The 'cumul' versions are similar to the normal 'fence' with the addition that order is preserved to all cores. For instance, on the ARM CPU, all fences are the 'cumul' type. The straight 'fence' is only for out-of-order issues, such as pipeline and/or write buffers for a single core.
All notation are 'fences' to say that some CPU barrier primitive has prevented the hazard type from occurring. So, it is all prior "read/write" will be committed before the subsequent "read/write". The 'function' can accept any permutation of these values.
Some things like a counter that are not dependent on other consistent values can be fine with only some fences. However, other values/tuples/structs are multi-address (non-atomic to load/store) and could require that multiple value are read/written in a consistent way. A taxonomy of interdependent accesses Table III. Glossary of litmus tests names of Herding cats....
The page, Software Verification for Weak Memory, at CProver is a Rosetta stone for this topic. It refers mainly to the tool 'musketeer', but further reading will show that many concepts are incorporated into the CBMC tool. Even the URL for the page contains 'wmm' which is also in the 'goto-instrument' directory as 'wmm' where this functionality is implemented.
The directory cbmc-concurrency and ansi-c have many examples of use of the
CPROVER_fence()
and other memory modelling primitives.Sample C prover code to implement
pthread_mutex_lock()
for analysis,My understanding is that it is checking for,
Interestingly,
man pthread_mutex_lock()
doesn't say anything about CPU synchronization or fences. We have priority inversion, dead lock, etc with mutex/lock programing, but also it has a price on pipeline performance. Indeed on ARM/Linux/glibc, kuser_cmpxchg32_fixup callsmp_dmb arm
to fulfill this requirement. A similar regression test shows failures ofpthread_create()
where a write buffer could leave a value in indeterminate state on the initial thread startup, unless a barrier is inserted aspthread_create()
doesn't have this synchronization.It seems this work is fairly recent (by some standards), with papers dated 2013 and Linux RCU commit in 2016. It is possible the authors wish to keep the API fluid. Probably they are more concentrated on the more enjoyable task of proving the provers and didn't have time to document this interface.
Note: Earlier versions of the answer assumed that cache synchronization with non-cached bus masters was covered by this API. That is not the case. System programmers trying to use
cbmc
need to use other mechanics, if this is of concern.