Date: Sun, 11 Jul 1999 23:58:52 -0700 (PDT) From: Matthew Dillon <dillon@apollo.backplane.com> To: Peter Jeremy <jeremyp@gsmx07.alcatel.com.au> Cc: mike@ducky.net, freebsd-current@FreeBSD.ORG Subject: Re: "objtrm" problem probably found (was Re: Stuck in "objtrm") Message-ID: <199907120658.XAA66214@apollo.backplane.com> References: <99Jul12.085624est.40350@border.alcanet.com.au>
next in thread | previous in thread | raw e-mail | index | archive | help
: :That said, it should be fairly simple to change Matt's new in-line :assembler versions to insert LOCK prefixes when building an SMP :kernel. (Although I don't know that this is necessary yet, given :the `Big Giant Lock'). : :There remains the problem of locating all the operations in the kernel :that _should_ be atomic but aren't marked as such. Doug Rabson and :the rest of the Alpha porting crew will have found a lot of these, but :locating race conditions by waiting for them to occur is not the best :solution. : :Peter Here's the patch. Alan should be committing it (or something close to it) soon. I did add the lock prefix, because I expect the SMP stuff will eventually depend on the atomic macros actually being SMP-atomic. It took a few iterations to get the __asm statement right :-) This patch appears to fix the objtrm problem and may also fix other potential VM races. -Matt Index: i386/include/atomic.h =================================================================== RCS file: /home/ncvs/src/sys/i386/include/atomic.h,v retrieving revision 1.1 diff -u -r1.1 atomic.h --- atomic.h 1998/08/24 08:39:36 1.1 +++ atomic.h 1999/07/11 08:03:50 @@ -30,29 +30,131 @@ /* * Various simple arithmetic on memory which is atomic in the presence - * of interrupts. + * of interrupts. This code is now SMP safe as well. * - * Note: these versions are not SMP safe. + * The assembly is volatilized to demark potential before-and-after side + * effects if an interrupt or SMP collision were to occurs. */ -#define atomic_set_char(P, V) (*(u_char*)(P) |= (V)) -#define atomic_clear_char(P, V) (*(u_char*)(P) &= ~(V)) -#define atomic_add_char(P, V) (*(u_char*)(P) += (V)) -#define atomic_subtract_char(P, V) (*(u_char*)(P) -= (V)) - -#define atomic_set_short(P, V) (*(u_short*)(P) |= (V)) -#define atomic_clear_short(P, V) (*(u_short*)(P) &= ~(V)) -#define atomic_add_short(P, V) (*(u_short*)(P) += (V)) -#define atomic_subtract_short(P, V) (*(u_short*)(P) -= (V)) - -#define atomic_set_int(P, V) (*(u_int*)(P) |= (V)) -#define atomic_clear_int(P, V) (*(u_int*)(P) &= ~(V)) -#define atomic_add_int(P, V) (*(u_int*)(P) += (V)) -#define atomic_subtract_int(P, V) (*(u_int*)(P) -= (V)) - -#define atomic_set_long(P, V) (*(u_long*)(P) |= (V)) -#define atomic_clear_long(P, V) (*(u_long*)(P) &= ~(V)) -#define atomic_add_long(P, V) (*(u_long*)(P) += (V)) -#define atomic_subtract_long(P, V) (*(u_long*)(P) -= (V)) +#define ATOMIC_ASM(type,op) \ + __asm __volatile ("lock; " op : "=m" (*(type *)p) : "ir" (v), "0" (*(type *)p)) + +static __inline void +atomic_set_char(void *p, u_char v) +{ + ATOMIC_ASM(u_char, "orb %1,%0"); +} + +static __inline void +atomic_clear_char(void *p, u_char v) +{ + v = ~v; + ATOMIC_ASM(u_char, "andb %1,%0"); +} + +static __inline void +atomic_add_char(void *p, u_char v) +{ + ATOMIC_ASM(u_char, "addb %1,%0"); +} + +static __inline void +atomic_subtract_char(void *p, u_char v) +{ + ATOMIC_ASM(u_char, "subb %1,%0"); +} + +static __inline void +atomic_set_short(void *p, u_short v) +{ + ATOMIC_ASM(u_short, "orw %1,%0"); +} + +static __inline void +atomic_clear_short(void *p, u_short v) +{ + v = ~v; + ATOMIC_ASM(u_short, "andw %1,%0"); +} + +static __inline void +atomic_add_short(void *p, u_short v) +{ + ATOMIC_ASM(u_short, "addw %1,%0"); +} + +static __inline void +atomic_subtract_short(void *p, u_short v) +{ + ATOMIC_ASM(u_short, "subw %1,%0"); +} + + +static __inline void +atomic_set_int(void *p, u_int v) +{ + ATOMIC_ASM(u_int, "orl %1,%0"); +} + +static __inline void +atomic_clear_int(void *p, u_int v) +{ + v = ~v; + ATOMIC_ASM(u_int, "andl %1,%0"); +} + +static __inline void +atomic_add_int(void *p, u_int v) +{ + ATOMIC_ASM(u_int, "addl %1,%0"); +} + +static __inline void +atomic_subtract_int(void *p, u_int v) +{ + ATOMIC_ASM(u_int, "subl %1,%0"); +} + + +static __inline void +atomic_set_long(void *p, u_long v) +{ + ATOMIC_ASM(u_long, "orl %1,%0"); +} + +static __inline void +atomic_clear_long(void *p, u_long v) +{ + v = ~v; + ATOMIC_ASM(u_long, "andl %1,%0"); +} + +static __inline void +atomic_add_long(void *p, u_long v) +{ + ATOMIC_ASM(u_long, "addl %1,%0"); +} + +static __inline void +atomic_subtract_long(void *p, u_long v) +{ + ATOMIC_ASM(u_long, "subl %1,%0"); +} + +#undef ATOMIC_ASM + +#ifndef I386_CPU + +static __inline int +atomic_cmpex(volatile int *pint, int oldv, int newv) +{ + __asm __volatile ("/* %0 %1 */; lock; cmpxchgl %2,(%3)" + : "=a" (oldv) + : "a" (oldv), "r" (newv), "r" (pint) + ); + return(oldv); +} + +#endif #endif /* ! _MACHINE_ATOMIC_H_ */ To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199907120658.XAA66214>