On 2000-Jul-19 19:31:12 -0700, John Polstra <[EMAIL PROTECTED]> wrote:
>In article <[EMAIL PROTECTED]>,
>Hellmuth Michaelis <[EMAIL PROTECTED]> wrote:
>> 
>> In the process of tracing down the problem of the kernel panic when booting
>> a kernel with pcvt enabled, i tried to compile a kernel without the -O
>> option to gcc and got this compile failure (sources from 18.7.2000 9:00 MET):
>> 
>> cc -c -pipe -Wall -Wredundant-decls -Wnested-externs -Wstrict-prototypes 
>>   -Wmissing-prototypes -Wpointer-arith -Winline -Wcast-qual  
>>   -fformat-extensions -ansi  -nostdinc -I- -I. -I../.. -I../../../include
>>   -D_KERNEL -include opt_global.h -elf  -mpreferred-stack-boundary=2
>>   -fomit-frame-pointer ../../i386/i386/atomic.c
>> In file included from ../../i386/i386/atomic.c:47:
>> machine/atomic.h: In function `atomic_set_char':
>> machine/atomic.h:106: inconsistent operand constraints in an `asm'
>> machine/atomic.h: In function `atomic_clear_char':
>> machine/atomic.h:107: inconsistent operand constraints in an `asm'
>[...]
>
>I have seen that same problem recently in a slightly different
>context.  After staring at the code for a very long time, I could
>only conclude that the problem was a bug in gcc.

Last year I did some testing of atomic.h with a variety of gcc
versions (and, following a prod from bde, at a variety of optimisation
levels).  At the time, I had great difficulty finding a set of
constraints that would work with both gcc 2.7.2 and egcs, with and
without optimisation.

Attached is a patch to /sys/i386/include/atomic.h,v 1.11 that I
believe solves the problem.  This is an adaption of what I did last
year, to include some of Bruce's comments.  At this stage, I've only
checked it against gcc version 2.95.2 19991024 (release) - at it
appears in 4.0 and the latest -current, with -O0, -O1 and -O2.  An
earlier version[1] worked with 2.7.2, 2.8.1 and ecgs 1.?.  I hope to
be able to check it on gcc 2.7.2 and maybe gcc 2.8.1 tonight.

Note that in theory, gcc 2.7.2 needs a second read-only argument with
a "0" constraint.  In practice, this doesn't seem to be necessary
since the write-only argument is volatile memory and therefore the
compiler can't optimize out any preceeding read.  This shouldn't be
required for later compiler versions since the first argument is
explicitly read-write.

[1] This was sent to Bruce early last October.  The changes since
    then are:
   - Correct `char' case to specify "q" constraint
   - Cast result of not (~) to ensure correct operand type.
   - Specify `w' in `short' case to correctly print the 16-bit register.

Peter
--- /3.0/cvs/src/sys/i386/include/atomic.h      Thu May 11 01:27:24 2000
+++ atomic.h    Mon Jul 24 08:02:16 2000
@@ -62,7 +62,7 @@
  * This allows kernel modules to be portable between UP and SMP systems.
  */
 #if defined(KLD_MODULE)
-#define ATOMIC_ASM(NAME, TYPE, OP, V)                  \
+#define ATOMIC_ASM(NAME, TYPE, OP, V, CLASS)                   \
        extern void atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v);
 
 #else /* !KLD_MODULE */
@@ -75,77 +75,61 @@
 /*
  * The assembly is volatilized to demark potential before-and-after side
  * effects if an interrupt or SMP collision were to occur.
+ *
+ * GCC 2.8 and later (including EGCS) support read/write operands
+ * using '+' as a constraint modifier.
+ *
+ * Earlier versions of gcc don't allow the '+' and recommend the use
+ * of separate, matching read-only and write-only operands.
+ * Unfortunately, this doesn't appear to work in all cases.  On
+ * the assumption that the memory operand is always volatile, it
+ * seems safe to tell gcc that it is write-only.  The `volatile'
+ * attribute on the memory operand prohibits any optimization
+ * away of the reference.
+ *
+ * The constraint class for the read operand is passed as a parameter
+ * to the macro because it needs to be different in the char case.
+ * (In theory, it should also be different in the short case, but
+ * gcc doesn't have any constraint classes to specify 16-bit registers).
+ *
+ * Note that gcc doesn't support string glueing for the constraint
+ * expressions, so the common "m" or "i" bits cannot be pulled out.
  */
-#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 9)
-/* egcs 1.1.2+ version */
-#define ATOMIC_ASM(NAME, TYPE, OP, V)                  \
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8)
+#define ATOMIC_ASM(NAME, TYPE, OP, V, CLASS)           \
 static __inline void                                   \
 atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\
 {                                                      \
-       __asm __volatile(MPLOCKED OP                    \
-                        : "=m" (*p)                    \
-                        :  "0" (*p), "ir" (V));        \
+       __asm __volatile(MPLOCKED OP : "+m" (*p) :  CLASS (V) : "cc"); \
 }
-
-#else
-/* gcc <= 2.8 version */
-#define ATOMIC_ASM(NAME, TYPE, OP, V)                  \
+#else          /* gcc < 2.8 version */
+#define ATOMIC_ASM(NAME, TYPE, OP, V, CLASS)           \
 static __inline void                                   \
 atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\
 {                                                      \
-       __asm __volatile(MPLOCKED OP                    \
-                        : "=m" (*p)                    \
-                        : "ir" (V));                   \
+       __asm __volatile(MPLOCKED OP : "=m" (*p) :  CLASS (V) : "cc"); \
 }
 #endif
 #endif /* KLD_MODULE */
 
-#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 9)
-
-/* egcs 1.1.2+ version */
-ATOMIC_ASM(set,             char,  "orb %b2,%0",   v)
-ATOMIC_ASM(clear,    char,  "andb %b2,%0", ~v)
-ATOMIC_ASM(add,             char,  "addb %b2,%0",  v)
-ATOMIC_ASM(subtract, char,  "subb %b2,%0",  v)
-
-ATOMIC_ASM(set,             short, "orw %w2,%0",   v)
-ATOMIC_ASM(clear,    short, "andw %w2,%0", ~v)
-ATOMIC_ASM(add,             short, "addw %w2,%0",  v)
-ATOMIC_ASM(subtract, short, "subw %w2,%0",  v)
-
-ATOMIC_ASM(set,             int,   "orl %2,%0",   v)
-ATOMIC_ASM(clear,    int,   "andl %2,%0", ~v)
-ATOMIC_ASM(add,             int,   "addl %2,%0",  v)
-ATOMIC_ASM(subtract, int,   "subl %2,%0",  v)
-
-ATOMIC_ASM(set,             long,  "orl %2,%0",   v)
-ATOMIC_ASM(clear,    long,  "andl %2,%0", ~v)
-ATOMIC_ASM(add,             long,  "addl %2,%0",  v)
-ATOMIC_ASM(subtract, long,  "subl %2,%0",  v)
-
-#else
-
-/* gcc <= 2.8 version */
-ATOMIC_ASM(set,             char,  "orb %1,%0",   v)
-ATOMIC_ASM(clear,    char,  "andb %1,%0", ~v)
-ATOMIC_ASM(add,             char,  "addb %1,%0",  v)
-ATOMIC_ASM(subtract, char,  "subb %1,%0",  v)
-
-ATOMIC_ASM(set,             short, "orw %1,%0",   v)
-ATOMIC_ASM(clear,    short, "andw %1,%0", ~v)
-ATOMIC_ASM(add,             short, "addw %1,%0",  v)
-ATOMIC_ASM(subtract, short, "subw %1,%0",  v)
-
-ATOMIC_ASM(set,             int,   "orl %1,%0",   v)
-ATOMIC_ASM(clear,    int,   "andl %1,%0", ~v)
-ATOMIC_ASM(add,             int,   "addl %1,%0",  v)
-ATOMIC_ASM(subtract, int,   "subl %1,%0",  v)
-
-ATOMIC_ASM(set,             long,  "orl %1,%0",   v)
-ATOMIC_ASM(clear,    long,  "andl %1,%0", ~v)
-ATOMIC_ASM(add,             long,  "addl %1,%0",  v)
-ATOMIC_ASM(subtract, long,  "subl %1,%0",  v)
-
-#endif
+ATOMIC_ASM(set,             char,  "orb %1,%0",   v, "iq")
+ATOMIC_ASM(clear,    char,  "andb %1,%0", (char)~v, "iq")
+ATOMIC_ASM(add,             char,  "addb %1,%0",  v, "iq")
+ATOMIC_ASM(subtract, char,  "subb %1,%0",  v, "iq")
+
+ATOMIC_ASM(set,             short, "orw %w1,%0",   v, "ir")
+ATOMIC_ASM(clear,    short, "andw %w1,%0", (short)~v, "ir")
+ATOMIC_ASM(add,             short, "addw %w1,%0",  v, "ir")
+ATOMIC_ASM(subtract, short, "subw %w1,%0",  v, "ir")
+
+ATOMIC_ASM(set,             int,   "orl %1,%0",   v, "ir")
+ATOMIC_ASM(clear,    int,   "andl %1,%0", ~v, "ir")
+ATOMIC_ASM(add,             int,   "addl %1,%0",  v, "ir")
+ATOMIC_ASM(subtract, int,   "subl %1,%0",  v, "ir")
+
+ATOMIC_ASM(set,             long,  "orl %1,%0",   v, "ir")
+ATOMIC_ASM(clear,    long,  "andl %1,%0", ~v, "ir")
+ATOMIC_ASM(add,             long,  "addl %1,%0",  v, "ir")
+ATOMIC_ASM(subtract, long,  "subl %1,%0",  v, "ir")
 
 #endif /* ! _MACHINE_ATOMIC_H_ */

Reply via email to