On 17/10/17 12:04, Segher Boessenkool wrote: > On Tue, Oct 17, 2017 at 11:13:36AM +0200, David Brown wrote: >> My solution to this >> particular ordering problem is: >> >> uint32_t status; >> asm volatile ("mrs %0, PRIMASK" : "=r" (status) :: ); >> asm volatile ("cpsid i" :: "" (status) :); >> >> foo(); >> >> asm volatile ("msr PRIMASK, %0" :: "r" (status) : ); > > And that only works for you because you have foo() separately compiled. > If it was inlined (say with LTO) its instructions could move anywhere. > That is without changing a character in your source code; your program > simply does not mean what you think it means. > Yes, I am aware of that. I am not fond of "this seems to work in all my testing" solutions - but they are better than "I know for sure that this sometimes does /not/ work" code! If I knew for sure that the no-output assembly statement did not move (with respect to volatiles), then the code here is as good as if /no/ volatile asm statements moved (with respect to volatiles). In either case, with LTO or if foo() is in the same file, some or all of foo could move around - everything except volatile accesses and code that depends on them. That is always a potential problem, but there are ways around that - making sure you have dependencies (possibly artificial ones), using volatile, or the nuclear option of a memory clobber. Typically, when writing macros for "enter_critical/exit_critical" you include memory clobbers for safety and ease-of-use despite a possible additional cost, but here I am trying to establish minimum requirements.