Hi, with GCC 4.1 and GCC 4.4 (RHEL 5.9) the example below prints a value of 1 for netwait (on x86_64 and s390x). The problem is that the assignment at /* 2 */ is moved to /* 1 */ during instruction scheduling.
The quick fix is to make "netwait" volatile. But according to the C standard (7.13.2.1) this should only be necessary if the value is modified between setjmp and longjmp. http://gcc.gnu.org/onlinedocs/gcc/Incompatibilities.html#Incompatibilities shows an example which also modifies the variable between setjmp/longjmp. However, a sentence in the same section is more general and suggests to always use volatile: "When you use setjmp and longjmp, the only automatic variables guaranteed to remain valid are those declared volatile." I'm wondering whether the behaviour in the example below is accepted and is supposed to be covered by the paragraph on the "incompatibilies" page or whether we should try to fix this? In the end it is still a standard violation so I think we should?! A possible fix might be to consider all function calls in the function scope of setjmp to be full scheduling barriers. I was not able to reproduce the problem with head GCC. But I couldn't find anything which addresses the problem either. So I assume that a different situation before the scheduling pass hides the problem. Bye, -Andreas- #include <setjmp.h> #include <stdio.h> jmp_buf jmpbuf; void __attribute__((noinline)) calls_longjmp() { longjmp(jmpbuf, 2); } int __attribute__((noinline)) foo () { return 42; } void __attribute__((noinline)) bar (int netwait, int cnt) { int i; int err; while (netwait) { netwait = 0; for (i = cnt; --i >= 0;) { if (setjmp(jmpbuf) == 0) { err = foo (); /* 1 */ if (err != 2344) calls_longjmp(); netwait = 1; /* 2 */ } else { printf ("netwait: %d\n", netwait); netwait = 0; } } } } int main () { bar (1, 1); }