X-Git-Url: https://git.liburcu.org/?a=blobdiff_plain;f=urcu.h;h=bc86d435845d6da33255a63d7d5d2fbdecb4aa76;hb=9b171f4656b61d023c327af3d0b4de22eee37353;hp=27695d495aeeb6388b121a099183949cbbdbac06;hpb=e462817ecdce42b00f0cb0825e2425b08943105b;p=urcu.git diff --git a/urcu.h b/urcu.h index 27695d4..bc86d43 100644 --- a/urcu.h +++ b/urcu.h @@ -17,6 +17,7 @@ * Distributed under GPLv2 */ +#define __USE_GNU #include /* The "volatile" is due to gcc bugs */ @@ -33,6 +34,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() @@ -70,6 +110,8 @@ static inline void atomic_inc(int *v) #ifdef DEBUG_YIELD #include +#include +#include #define YIELD_READ (1 << 0) #define YIELD_WRITE (1 << 1) @@ -190,9 +232,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. */