Author: hselasky
Date: Sun Feb 18 17:37:23 2018
New Revision: 329523
URL: https://svnweb.freebsd.org/changeset/base/329523

Log:
  Fix implementation of xchg() function macro in the LinuxKPI.
  The exchange operation must be atomic.
  
  MFC after:    1 week
  Sponsored by: Mellanox Technologies

Modified:
  head/sys/compat/linuxkpi/common/include/asm/atomic.h

Modified: head/sys/compat/linuxkpi/common/include/asm/atomic.h
==============================================================================
--- head/sys/compat/linuxkpi/common/include/asm/atomic.h        Sun Feb 18 
16:41:34 2018        (r329522)
+++ head/sys/compat/linuxkpi/common/include/asm/atomic.h        Sun Feb 18 
17:37:23 2018        (r329523)
@@ -198,12 +198,41 @@ atomic_cmpxchg(atomic_t *v, int old, int new)
 
 #define        cmpxchg_relaxed(...)    cmpxchg(__VA_ARGS__)
 
-#define        xchg(ptr, v) ({                                         \
-       __typeof(*(ptr)) __ret;                                 \
-                                                               \
-       __ret = *(ptr);                                         \
-       *(ptr) = v;                                             \
-       __ret;                                                  \
+#define        xchg(ptr, new) ({                                               
\
+       union {                                                         \
+               __typeof(*(ptr)) val;                                   \
+               u8 u8[0];                                               \
+               u16 u16[0];                                             \
+               u32 u32[0];                                             \
+               u64 u64[0];                                             \
+       } __ret = { .val = READ_ONCE(*ptr) }, __new = { .val = (new) }; \
+                                                                       \
+       CTASSERT(sizeof(__ret.val) == 1 || sizeof(__ret.val) == 2 ||    \
+           sizeof(__ret.val) == 4 || sizeof(__ret.val) == 8);          \
+                                                                       \
+       switch (sizeof(__ret.val)) {                                    \
+       case 1:                                                         \
+               while (!atomic_fcmpset_8((volatile u8 *)(ptr),          \
+                   __ret.u8, __new.u8[0]))                             \
+                       ;                                               \
+               break;                                                  \
+       case 2:                                                         \
+               while (!atomic_fcmpset_16((volatile u16 *)(ptr),        \
+                   __ret.u16, __new.u16[0]))                           \
+                       ;                                               \
+               break;                                                  \
+       case 4:                                                         \
+               while (!atomic_fcmpset_32((volatile u32 *)(ptr),        \
+                   __ret.u32, __new.u32[0]))                           \
+                       ;                                               \
+               break;                                                  \
+       case 8:                                                         \
+               while (!atomic_fcmpset_64((volatile u64 *)(ptr),        \
+                   __ret.u64, __new.u64[0]))                           \
+                       ;                                               \
+               break;                                                  \
+       }                                                               \
+       __ret.val;                                                      \
 })
 
 #define        LINUX_ATOMIC_OP(op, c_op)                               \
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to