Use xchg in publish content
[urcu.git] / urcu.h
diff --git a/urcu.h b/urcu.h
index 27695d495aeeb6388b121a099183949cbbdbac06..fb8cedf3e15beab5ba5355b153d0bb999fa1c7fc 100644 (file)
--- a/urcu.h
+++ b/urcu.h
@@ -33,6 +33,45 @@ static inline void atomic_inc(int *v)
                     : "+m" (*v));
 }
 
+#define xchg(ptr, v)                                                   \
+       ((__typeof__(*(ptr)))__xchg((unsigned long)(v), (ptr), sizeof(*(ptr))))
+
+struct __xchg_dummy {
+       unsigned long a[100];
+};
+#define __xg(x) ((struct __xchg_dummy *)(x))
+
+/*
+ * Note: no "lock" prefix even on SMP: xchg always implies lock anyway
+ * Note 2: xchg has side effect, so that attribute volatile is necessary,
+ *       but generally the primitive is invalid, *ptr is output argument. --ANK
+ */
+static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
+                                  int size)
+{
+       switch (size) {
+       case 1:
+               asm volatile("xchgb %b0,%1"
+                            : "=q" (x)
+                            : "m" (*__xg(ptr)), "0" (x)
+                            : "memory");
+               break;
+       case 2:
+               asm volatile("xchgw %w0,%1"
+                            : "=r" (x)
+                            : "m" (*__xg(ptr)), "0" (x)
+                            : "memory");
+               break;
+       case 4:
+               asm volatile("xchgl %0,%1"
+                            : "=r" (x)
+                            : "m" (*__xg(ptr)), "0" (x)
+                            : "memory");
+               break;
+       }
+       return x;
+}
+
 /* Nop everywhere except on alpha. */
 #define smp_read_barrier_depends()
 
@@ -190,9 +229,29 @@ static inline void rcu_read_unlock(void)
                (p) = (v); \
        })
 
-extern void *urcu_publish_content(void **ptr, void *new);
+#define rcu_xchg_pointer(p, v) \
+       ({ \
+               if (!__builtin_constant_p(v) || \
+                   ((v) != NULL)) \
+                       wmb(); \
+               xchg(p, v); \
+       })
+
 extern void synchronize_rcu(void);
 
+/*
+ * Exchanges the pointer and waits for quiescent state.
+ * The pointer returned can be freed.
+ */
+#define urcu_publish_content(p, v) \
+       ({ \
+               void *oldptr; \
+               debug_yield_write(); \
+               oldptr = rcu_xchg_pointer(p, v); \
+               synchronize_rcu(); \
+               oldptr; \
+       })
+
 /*
  * Reader thread registration.
  */
This page took 0.022854 seconds and 4 git commands to generate.