arch.h   arch.h 
skipping to change at line 32 skipping to change at line 32
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include <urcu/compiler.h> #include <urcu/compiler.h>
#include <urcu/config.h> #include <urcu/config.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#define CACHE_LINE_SIZE 128 #define CAA_CACHE_LINE_SIZE 128
#ifdef CONFIG_RCU_HAVE_FENCE #ifdef CONFIG_RCU_HAVE_FENCE
#define mb() asm volatile("mfence":::"memory") #define cmm_mb() asm volatile("mfence":::"memory")
#define rmb() asm volatile("lfence":::"memory") #define cmm_rmb() asm volatile("lfence":::"memory")
#define wmb() asm volatile("sfence"::: "memory") #define cmm_wmb() asm volatile("sfence"::: "memory")
#else #else
/* /*
* Some non-Intel clones support out of order store. wmb() ceases to be a * Some non-Intel clones support out of order store. cmm_wmb() ceases to be a
* nop for these. * nop for these.
*/ */
#define mb() asm volatile("lock; addl $0,0(%%esp)":::"memory") #define cmm_mb() asm volatile("lock; addl $0,0(%%esp)":::"memory")
#define rmb() asm volatile("lock; addl $0,0(%%esp)":::"memory") #define cmm_rmb() asm volatile("lock; addl $0,0(%%esp)":::"memory")
#define wmb() asm volatile("lock; addl $0,0(%%esp)"::: "memory") #define cmm_wmb() asm volatile("lock; addl $0,0(%%esp)"::: "memory")
#endif #endif
#define cpu_relax() asm volatile("rep; nop" : : : "memory"); #define caa_cpu_relax() asm volatile("rep; nop" : : : "memory");
#define rdtscll(val) \ #define rdtscll(val) \
do { \ do { \
unsigned int __a, __d; \ unsigned int __a, __d; \
asm volatile("rdtsc" : "=a" (__a), "=d" (__d)); \ asm volatile("rdtsc" : "=a" (__a), "=d" (__d)); \
(val) = ((unsigned long long)__a) \ (val) = ((unsigned long long)__a) \
| (((unsigned long long)__d) << 32); \ | (((unsigned long long)__d) << 32); \
} while(0) } while(0)
typedef unsigned long long cycles_t; typedef unsigned long long cycles_t;
static inline cycles_t get_cycles(void) static inline cycles_t caa_get_cycles(void)
{ {
cycles_t ret = 0; cycles_t ret = 0;
rdtscll(ret); rdtscll(ret);
return ret; return ret;
} }
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
 End of changes. 6 change blocks. 
10 lines changed or deleted 10 lines changed or added


 arch_generic.h   arch_generic.h 
skipping to change at line 31 skipping to change at line 31
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include <urcu/compiler.h> #include <urcu/compiler.h>
#include <urcu/config.h> #include <urcu/config.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#ifndef CACHE_LINE_SIZE #ifndef CAA_CACHE_LINE_SIZE
#define CACHE_LINE_SIZE 64 #define CAA_CACHE_LINE_SIZE 64
#endif #endif
#if !defined(mc) && !defined(rmc) && !defined(wmc) #if !defined(cmm_mc) && !defined(cmm_rmc) && !defined(cmm_wmc)
#define CONFIG_HAVE_MEM_COHERENCY #define CONFIG_HAVE_MEM_COHERENCY
/* /*
* Architectures with cache coherency must _not_ define mc/rmc/wmc. * Architectures with cache coherency must _not_ define cmm_mc/cmm_rmc/cmm_ wmc.
* *
* For them, mc/rmc/wmc are implemented with a * simple compiler barrier; * For them, cmm_mc/cmm_rmc/cmm_wmc are implemented with a * simple compile
* in addition, we provide defaults for mb (using GCC builtins) as well as r barrier;
* rmb and wmb (defaulting to mb). * in addition, we provide defaults for cmm_mb (using GCC builtins) as well
as
* cmm_rmb and cmm_wmb (defaulting to cmm_mb).
*/ */
#ifndef mb #ifndef cmm_mb
#define mb() __sync_synchronize() #define cmm_mb() __sync_synchronize()
#endif #endif
#ifndef rmb #ifndef cmm_rmb
#define rmb() mb() #define cmm_rmb() cmm_mb()
#endif #endif
#ifndef wmb #ifndef cmm_wmb
#define wmb() mb() #define cmm_wmb() cmm_mb()
#endif #endif
#define mc() barrier() #define cmm_mc() cmm_barrier()
#define rmc() barrier() #define cmm_rmc() cmm_barrier()
#define wmc() barrier() #define cmm_wmc() cmm_barrier()
#else #else
/* /*
* Architectures without cache coherency need something like the following: * Architectures without cache coherency need something like the following:
* *
* #define mc() arch_cache_flush() * #define cmm_mc() arch_cache_flush()
* #define rmc() arch_cache_flush_read() * #define cmm_rmc() arch_cache_flush_read()
* #define wmc() arch_cache_flush_write() * #define cmm_wmc() arch_cache_flush_write()
* *
* Of these, only mc is mandatory. rmc and wmc default to mc. mb/rmb/wmb * Of these, only cmm_mc is mandatory. cmm_rmc and cmm_wmc default to cmm_
* use these definitions by default: mc.
* cmm_mb/cmm_rmb/cmm_wmb use these definitions by default:
* *
* #define mb() mc() * #define cmm_mb() cmm_mc()
* #define rmb() rmc() * #define cmm_rmb() cmm_rmc()
* #define wmb() wmc() * #define cmm_wmb() cmm_wmc()
*/ */
#ifndef mb #ifndef cmm_mb
#define mb() mc() #define cmm_mb() cmm_mc()
#endif #endif
#ifndef rmb #ifndef cmm_rmb
#define rmb() rmc() #define cmm_rmb() cmm_rmc()
#endif #endif
#ifndef wmb #ifndef cmm_wmb
#define wmb() wmc() #define cmm_wmb() cmm_wmc()
#endif #endif
#ifndef rmc #ifndef cmm_rmc
#define rmc() mc() #define cmm_rmc() cmm_mc()
#endif #endif
#ifndef wmc #ifndef cmm_wmc
#define wmc() mc() #define cmm_wmc() cmm_mc()
#endif #endif
#endif #endif
/* Nop everywhere except on alpha. */ /* Nop everywhere except on alpha. */
#ifndef read_barrier_depends #ifndef cmm_read_barrier_depends
#define read_barrier_depends() #define cmm_read_barrier_depends()
#endif #endif
#ifdef CONFIG_RCU_SMP #ifdef CONFIG_RCU_SMP
#define smp_mb() mb() #define cmm_smp_mb() cmm_mb()
#define smp_rmb() rmb() #define cmm_smp_rmb() cmm_rmb()
#define smp_wmb() wmb() #define cmm_smp_wmb() cmm_wmb()
#define smp_mc() mc() #define cmm_smp_mc() cmm_mc()
#define smp_rmc() rmc() #define cmm_smp_rmc() cmm_rmc()
#define smp_wmc() wmc() #define cmm_smp_wmc() cmm_wmc()
#define smp_read_barrier_depends() read_barrier_depends() #define cmm_smp_read_barrier_depends() cmm_read_barrier_depends()
#else #else
#define smp_mb() barrier() #define cmm_smp_mb() cmm_barrier()
#define smp_rmb() barrier() #define cmm_smp_rmb() cmm_barrier()
#define smp_wmb() barrier() #define cmm_smp_wmb() cmm_barrier()
#define smp_mc() barrier() #define cmm_smp_mc() cmm_barrier()
#define smp_rmc() barrier() #define cmm_smp_rmc() cmm_barrier()
#define smp_wmc() barrier() #define cmm_smp_wmc() cmm_barrier()
#define smp_read_barrier_depends() #define cmm_smp_read_barrier_depends()
#endif #endif
#ifndef cpu_relax #ifndef caa_cpu_relax
#define cpu_relax() barrier() #define caa_cpu_relax() cmm_barrier()
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* _URCU_ARCH_GENERIC_H */ #endif /* _URCU_ARCH_GENERIC_H */
 End of changes. 20 change blocks. 
52 lines changed or deleted 55 lines changed or added


 compiler.h   compiler.h 
skipping to change at line 26 skipping to change at line 26
* Permission to modify the code and to distribute modified code is granted , * Permission to modify the code and to distribute modified code is granted ,
* provided the above notices are retained, and a notice that the code was * provided the above notices are retained, and a notice that the code was
* modified is included with the above copyright notice. * modified is included with the above copyright notice.
*/ */
#include <stddef.h> /* for offsetof */ #include <stddef.h> /* for offsetof */
#define likely(x) __builtin_expect(!!(x), 1) #define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0) #define unlikely(x) __builtin_expect(!!(x), 0)
#define barrier() asm volatile("" : : : "memory") #define cmm_barrier() asm volatile("" : : : "memory")
/* /*
* Instruct the compiler to perform only a single access to a variable * Instruct the compiler to perform only a single access to a variable
* (prohibits merging and refetching). The compiler is also forbidden to re order * (prohibits merging and refetching). The compiler is also forbidden to re order
* successive instances of ACCESS_ONCE(), but only when the compiler is awa re of * successive instances of CAA_ACCESS_ONCE(), but only when the compiler is aware of
* particular ordering. Compiler ordering can be ensured, for example, by * particular ordering. Compiler ordering can be ensured, for example, by
* putting two ACCESS_ONCE() in separate C statements. * putting two CAA_ACCESS_ONCE() in separate C statements.
* *
* This macro does absolutely -nothing- to prevent the CPU from reordering, * This macro does absolutely -nothing- to prevent the CPU from reordering,
* merging, or refetching absolutely anything at any time. Its main intend ed * merging, or refetching absolutely anything at any time. Its main intend ed
* use is to mediate communication between process-level code and irq/NMI * use is to mediate communication between process-level code and irq/NMI
* handlers, all running on the same CPU. * handlers, all running on the same CPU.
*/ */
#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x)) #define CAA_ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
#ifndef max #ifndef max
#define max(a,b) ((a)>(b)?(a):(b)) #define max(a,b) ((a)>(b)?(a):(b))
#endif #endif
#ifndef min #ifndef min
#define min(a,b) ((a)<(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b))
#endif #endif
#if defined(__SIZEOF_LONG__) #if defined(__SIZEOF_LONG__)
#define BITS_PER_LONG (__SIZEOF_LONG__ * 8) #define CAA_BITS_PER_LONG (__SIZEOF_LONG__ * 8)
#elif defined(_LP64) #elif defined(_LP64)
#define BITS_PER_LONG 64 #define CAA_BITS_PER_LONG 64
#else #else
#define BITS_PER_LONG 32 #define CAA_BITS_PER_LONG 32
#endif #endif
#define container_of(ptr, type, member) \ #define caa_container_of(ptr, type, member) \
({ \ ({ \
const typeof(((type *)NULL)->member) * __ptr = (ptr); \ const typeof(((type *)NULL)->member) * __ptr = (ptr); \
(type *)((char *)__ptr - offsetof(type, member)); \ (type *)((char *)__ptr - offsetof(type, member)); \
}) })
#endif /* _URCU_COMPILER_H */ #endif /* _URCU_COMPILER_H */
 End of changes. 8 change blocks. 
8 lines changed or deleted 8 lines changed or added


 hlist.h   hlist.h 
skipping to change at line 19 skipping to change at line 19
* *
* Author: Jan Blunck <jblunck@suse.de> * Author: Jan Blunck <jblunck@suse.de>
* *
* Copyright (C) 2010 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> * Copyright (C) 2010 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 2.1 as * under the terms of the GNU Lesser General Public License version 2.1 as
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
struct hlist_head struct cds_hlist_head
{ {
struct hlist_node *next; struct cds_hlist_node *next;
}; };
struct hlist_node struct cds_hlist_node
{ {
struct hlist_node *next; struct cds_hlist_node *next;
struct hlist_node *prev; struct cds_hlist_node *prev;
}; };
/* Initialize a new list head. */ /* Initialize a new list head. */
static inline void INIT_HLIST_HEAD(struct hlist_head *ptr) static inline void CDS_INIT_HLIST_HEAD(struct cds_hlist_head *ptr)
{ {
ptr->next = NULL; ptr->next = NULL;
} }
/* Get typed element from list at a given position. */ /* Get typed element from list at a given position. */
#define hlist_entry(ptr, type, member) \ #define cds_hlist_entry(ptr, type, member) \
((type *) ((char *) (ptr) - (unsigned long) (&((type *) 0)->member)) ) ((type *) ((char *) (ptr) - (unsigned long) (&((type *) 0)->member)) )
/* Add new element at the head of the list. */ /* Add new element at the head of the list. */
static inline void hlist_add_head (struct hlist_node *newp, static inline void cds_hlist_add_head (struct cds_hlist_node *newp,
struct hlist_head *head) struct cds_hlist_head *head)
{ {
if (head->next) if (head->next)
head->next->prev = newp; head->next->prev = newp;
newp->next = head->next; newp->next = head->next;
newp->prev = (struct hlist_node *)head; newp->prev = (struct cds_hlist_node *)head;
head->next = newp; head->next = newp;
} }
/* Remove element from list. */ /* Remove element from list. */
static inline void hlist_del (struct hlist_node *elem) static inline void cds_hlist_del (struct cds_hlist_node *elem)
{ {
if (elem->next) if (elem->next)
elem->next->prev = elem->prev; elem->next->prev = elem->prev;
elem->prev->next = elem->next; elem->prev->next = elem->next;
} }
#define hlist_for_each_entry(entry, pos, head, member) \ #define cds_hlist_for_each_entry(entry, pos, head, member) \
for (pos = (head)->next, \ for (pos = (head)->next, \
entry = hlist_entry(pos, typeof(*entry), member); \ entry = cds_hlist_entry(pos, typeof(*entry), member); \
pos != NULL; \ pos != NULL; \
pos = pos->next, \ pos = pos->next, \
entry = hlist_entry(pos, typeof(*entry), member)) entry = cds_hlist_entry(pos, typeof(*entry), member))
#define hlist_for_each_entry_safe(entry, pos, p, head, member) \ #define cds_hlist_for_each_entry_safe(entry, pos, p, head, member) \
for (pos = (head)->next, \ for (pos = (head)->next, \
entry = hlist_entry(pos, typeof(*entry), member); \ entry = cds_hlist_entry(pos, typeof(*entry), member); \
(pos != NULL) && ({ p = pos->next; 1;}); \ (pos != NULL) && ({ p = pos->next; 1;}); \
pos = p, \ pos = p, \
entry = hlist_entry(pos, typeof(*entry), member)) entry = cds_hlist_entry(pos, typeof(*entry), member))
#endif /* _KCOMPAT_HLIST_H */ #endif /* _KCOMPAT_HLIST_H */
 End of changes. 15 change blocks. 
17 lines changed or deleted 17 lines changed or added


 list.h   list.h 
skipping to change at line 28 skipping to change at line 28
02111-1307 USA. */ 02111-1307 USA. */
#ifndef _LIST_H #ifndef _LIST_H
#define _LIST_H 1 #define _LIST_H 1
/* The definitions of this file are adopted from those which can be /* The definitions of this file are adopted from those which can be
found in the Linux kernel headers to enable people familiar with found in the Linux kernel headers to enable people familiar with
the latter find their way in these sources as well. */ the latter find their way in these sources as well. */
/* Basic type for the double-link list. */ /* Basic type for the double-link list. */
typedef struct list_head typedef struct cds_list_head
{ {
struct list_head *next; struct cds_list_head *next;
struct list_head *prev; struct cds_list_head *prev;
} list_t; } list_t;
/* Define a variable with the head and tail of the list. */ /* Define a variable with the head and tail of the list. */
#define LIST_HEAD(name) \ #define CDS_LIST_HEAD(name) \
list_t name = { &(name), &(name) } list_t name = { &(name), &(name) }
/* Initialize a new list head. */ /* Initialize a new list head. */
#define INIT_LIST_HEAD(ptr) \ #define CDS_INIT_LIST_HEAD(ptr) \
(ptr)->next = (ptr)->prev = (ptr) (ptr)->next = (ptr)->prev = (ptr)
#define LIST_HEAD_INIT(name) { .prev = &(name), .next = &(name) } #define CDS_LIST_HEAD_INIT(name) { .prev = &(name), .next = &(name) }
/* Add new element at the head of the list. */ /* Add new element at the head of the list. */
static inline void static inline void
list_add (list_t *newp, list_t *head) cds_list_add (list_t *newp, list_t *head)
{ {
head->next->prev = newp; head->next->prev = newp;
newp->next = head->next; newp->next = head->next;
newp->prev = head; newp->prev = head;
head->next = newp; head->next = newp;
} }
/* Add new element at the tail of the list. */ /* Add new element at the tail of the list. */
static inline void static inline void
list_add_tail (list_t *newp, list_t *head) cds_list_add_tail (list_t *newp, list_t *head)
{ {
head->prev->next = newp; head->prev->next = newp;
newp->next = head; newp->next = head;
newp->prev = head->prev; newp->prev = head->prev;
head->prev = newp; head->prev = newp;
} }
/* Remove element from list. */ /* Remove element from list. */
static inline void static inline void
__list_del (list_t *prev, list_t *next) __cds_list_del (list_t *prev, list_t *next)
{ {
next->prev = prev; next->prev = prev;
prev->next = next; prev->next = next;
} }
/* Remove element from list. */ /* Remove element from list. */
static inline void static inline void
list_del (list_t *elem) cds_list_del (list_t *elem)
{ {
__list_del (elem->prev, elem->next); __cds_list_del (elem->prev, elem->next);
} }
/* delete from list, add to another list as head */ /* delete from list, add to another list as head */
static inline void static inline void
list_move (list_t *elem, list_t *head) cds_list_move (list_t *elem, list_t *head)
{ {
__list_del (elem->prev, elem->next); __cds_list_del (elem->prev, elem->next);
list_add (elem, head); cds_list_add (elem, head);
} }
/* replace an old entry. /* replace an old entry.
*/ */
static inline void static inline void
list_replace(list_t *old, list_t *_new) cds_list_replace(list_t *old, list_t *_new)
{ {
_new->next = old->next; _new->next = old->next;
_new->prev = old->prev; _new->prev = old->prev;
_new->prev->next = _new; _new->prev->next = _new;
_new->next->prev = _new; _new->next->prev = _new;
} }
/* Join two lists. */ /* Join two lists. */
static inline void static inline void
list_splice (list_t *add, list_t *head) cds_list_splice (list_t *add, list_t *head)
{ {
/* Do nothing if the list which gets added is empty. */ /* Do nothing if the list which gets added is empty. */
if (add != add->next) if (add != add->next)
{ {
add->next->prev = head; add->next->prev = head;
add->prev->next = head->next; add->prev->next = head->next;
head->next->prev = add->prev; head->next->prev = add->prev;
head->next = add->next; head->next = add->next;
} }
} }
/* Get typed element from list at a given position. */ /* Get typed element from list at a given position. */
#define list_entry(ptr, type, member) \ #define cds_list_entry(ptr, type, member) \
((type *) ((char *) (ptr) - (unsigned long) (&((type *) 0)->member))) ((type *) ((char *) (ptr) - (unsigned long) (&((type *) 0)->member)))
/* Iterate forward over the elements of the list. */ /* Iterate forward over the elements of the list. */
#define list_for_each(pos, head) \ #define cds_list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next) for (pos = (head)->next; pos != (head); pos = pos->next)
/* Iterate forward over the elements of the list. */ /* Iterate forward over the elements of the list. */
#define list_for_each_prev(pos, head) \ #define cds_list_for_each_prev(pos, head) \
for (pos = (head)->prev; pos != (head); pos = pos->prev) for (pos = (head)->prev; pos != (head); pos = pos->prev)
/* Iterate backwards over the elements list. The list elements can be /* Iterate backwards over the elements list. The list elements can be
removed from the list while doing this. */ removed from the list while doing this. */
#define list_for_each_prev_safe(pos, p, head) \ #define cds_list_for_each_prev_safe(pos, p, head) \
for (pos = (head)->prev, p = pos->prev; \ for (pos = (head)->prev, p = pos->prev; \
pos != (head); \ pos != (head); \
pos = p, p = pos->prev) pos = p, p = pos->prev)
#define list_for_each_entry(pos, head, member) \ #define cds_list_for_each_entry(pos, head, member)
for (pos = list_entry((head)->next, typeof(*pos), member); \ \
for (pos = cds_list_entry((head)->next, typeof(*pos), member); \
&pos->member != (head); \ &pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member)) pos = cds_list_entry(pos->member.next, typeof(*pos), member))
#define list_for_each_entry_reverse(pos, head, member) \ #define cds_list_for_each_entry_reverse(pos, head, member)
for (pos = list_entry((head)->prev, typeof(*pos), member); \ \
for (pos = cds_list_entry((head)->prev, typeof(*pos), member); \
&pos->member != (head); \ &pos->member != (head); \
pos = list_entry(pos->member.prev, typeof(*pos), member)) pos = cds_list_entry(pos->member.prev, typeof(*pos), member))
#define list_for_each_entry_safe(pos, p, head, member) \ #define cds_list_for_each_entry_safe(pos, p, head, member)
for (pos = list_entry((head)->next, typeof(*pos), member), \ \
p = list_entry(pos->member.next,typeof(*pos), member); for (pos = cds_list_entry((head)->next, typeof(*pos), member), \
\ p = cds_list_entry(pos->member.next,typeof(*pos), membe
r); \
&pos->member != (head); \ &pos->member != (head); \
pos = p, p = list_entry(pos->member.next, typeof(*pos), member) ) pos = p, p = cds_list_entry(pos->member.next, typeof(*pos), mem ber))
static inline int list_empty(list_t *head) static inline int cds_list_empty(list_t *head)
{ {
return head == head->next; return head == head->next;
} }
static inline void list_replace_init(list_t *old, static inline void cds_list_replace_init(list_t *old,
list_t *_new) list_t *_new)
{ {
list_t *head = old->next; list_t *head = old->next;
list_del(old); cds_list_del(old);
list_add_tail(_new, head); cds_list_add_tail(_new, head);
INIT_LIST_HEAD(old); CDS_INIT_LIST_HEAD(old);
} }
#endif /* list.h */ #endif /* list.h */
 End of changes. 27 change blocks. 
36 lines changed or deleted 39 lines changed or added


 rcuhlist.h   rcuhlist.h 
skipping to change at line 33 skipping to change at line 33
#ifndef _URCU_RCUHLIST_H #ifndef _URCU_RCUHLIST_H
#define _URCU_RCUHLIST_H #define _URCU_RCUHLIST_H
#include <urcu/hlist.h> #include <urcu/hlist.h>
#include <urcu/arch.h> #include <urcu/arch.h>
#include <urcu-pointer.h> #include <urcu-pointer.h>
/* Add new element at the head of the list. /* Add new element at the head of the list.
*/ */
static inline void hlist_add_head_rcu(struct hlist_node *newp, static inline void cds_hlist_add_head_rcu(struct cds_hlist_node *newp,
struct hlist_head *head) struct cds_hlist_head *head)
{ {
newp->next = head->next; newp->next = head->next;
newp->prev = (struct hlist_node *)head; newp->prev = (struct cds_hlist_node *)head;
smp_wmb(); cmm_smp_wmb();
if (head->next) if (head->next)
head->next->prev = newp; head->next->prev = newp;
head->next = newp; head->next = newp;
} }
/* Remove element from list. */ /* Remove element from list. */
static inline void hlist_del_rcu(struct hlist_node *elem) static inline void cds_hlist_del_rcu(struct cds_hlist_node *elem)
{ {
if (elem->next) if (elem->next)
elem->next->prev = elem->prev; elem->next->prev = elem->prev;
elem->prev->next = elem->next; elem->prev->next = elem->next;
} }
/* Iterate through elements of the list. /* Iterate through elements of the list.
* This must be done while rcu_read_lock() is held. * This must be done while rcu_read_lock() is held.
*/ */
#define hlist_for_each_entry_rcu(entry, pos, head, member) \ #define cds_hlist_for_each_entry_rcu(entry, pos, head, member) \
for (pos = rcu_dereference((head)->next), \ for (pos = rcu_dereference((head)->next), \
entry = hlist_entry(pos, typeof(*entry), member); \ entry = cds_hlist_entry(pos, typeof(*entry), member); \
pos != NULL; \ pos != NULL; \
pos = rcu_dereference(pos->next), \ pos = rcu_dereference(pos->next), \
entry = hlist_entry(pos, typeof(*entry), member)) entry = cds_hlist_entry(pos, typeof(*entry), member))
#endif /* _URCU_RCUHLIST_H */ #endif /* _URCU_RCUHLIST_H */
 End of changes. 6 change blocks. 
8 lines changed or deleted 8 lines changed or added


 rculfqueue-static.h   rculfqueue-static.h 
skipping to change at line 50 skipping to change at line 50
* hold a RCU read lock to deal with cmpxchg ABA problem. This implementati on * hold a RCU read lock to deal with cmpxchg ABA problem. This implementati on
* keeps a dummy head node to ensure we can always update the queue lockles sly. * keeps a dummy head node to ensure we can always update the queue lockles sly.
* Given that this is a queue, the dummy head node must always advance as w e * Given that this is a queue, the dummy head node must always advance as w e
* dequeue entries. Therefore, we keep a reference count on each entry we a re * dequeue entries. Therefore, we keep a reference count on each entry we a re
* dequeueing, so they can be kept as dummy head node until the next dequeu e, at * dequeueing, so they can be kept as dummy head node until the next dequeu e, at
* which point their reference count will be decremented. * which point their reference count will be decremented.
*/ */
#define URCU_LFQ_PERMANENT_REF 128 #define URCU_LFQ_PERMANENT_REF 128
void _rcu_lfq_node_init(struct rcu_lfq_node *node) void _cds_lfq_node_init_rcu(struct cds_lfq_node_rcu *node)
{ {
node->next = NULL; node->next = NULL;
urcu_ref_init(&node->ref); urcu_ref_init(&node->ref);
} }
void _rcu_lfq_init(struct rcu_lfq_queue *q) void _cds_lfq_init_rcu(struct cds_lfq_queue_rcu *q)
{ {
_rcu_lfq_node_init(&q->init); _cds_lfq_node_init_rcu(&q->init);
/* Make sure the initial node is never freed. */ /* Make sure the initial node is never freed. */
urcu_ref_set(&q->init.ref, URCU_LFQ_PERMANENT_REF); urcu_ref_set(&q->init.ref, URCU_LFQ_PERMANENT_REF);
q->head = q->tail = &q->init; q->head = q->tail = &q->init;
} }
void _rcu_lfq_enqueue(struct rcu_lfq_queue *q, struct rcu_lfq_node *node) void _cds_lfq_enqueue_rcu(struct cds_lfq_queue_rcu *q, struct cds_lfq_node_ rcu *node)
{ {
urcu_ref_get(&node->ref); urcu_ref_get(&node->ref);
/* /*
* uatomic_cmpxchg() implicit memory barrier orders earlier stores t o * uatomic_cmpxchg() implicit memory barrier orders earlier stores t o
* node before publication. * node before publication.
*/ */
for (;;) { for (;;) {
struct rcu_lfq_node *tail, *next; struct cds_lfq_node_rcu *tail, *next;
rcu_read_lock(); rcu_read_lock();
tail = rcu_dereference(q->tail); tail = rcu_dereference(q->tail);
/* /*
* Typically expect tail->next to be NULL. * Typically expect tail->next to be NULL.
*/ */
next = uatomic_cmpxchg(&tail->next, NULL, node); next = uatomic_cmpxchg(&tail->next, NULL, node);
if (next == NULL) { if (next == NULL) {
/* /*
* Tail was at the end of queue, we successfully * Tail was at the end of queue, we successfully
skipping to change at line 108 skipping to change at line 108
rcu_read_unlock(); rcu_read_unlock();
continue; continue;
} }
} }
} }
/* /*
* The entry returned by dequeue must be taken care of by doing a urcu_ref_ put, * The entry returned by dequeue must be taken care of by doing a urcu_ref_ put,
* which calls the release primitive when the reference count drops to zero . A * which calls the release primitive when the reference count drops to zero . A
* grace period must be waited after execution of the release callback befo re * grace period must be waited after execution of the release callback befo re
* performing the actual memory reclamation or modifying the rcu_lfq_node * performing the actual memory reclamation or modifying the cds_lfq_node_r cu
* structure. * structure.
* In other words, the entry lfq node returned by dequeue must not be * In other words, the entry lfq node returned by dequeue must not be
* modified/re-used/freed until the reference count reaches zero and a grac e * modified/re-used/freed until the reference count reaches zero and a grac e
* period has elapsed (after the refcount reached 0). * period has elapsed (after the refcount reached 0).
*/ */
struct rcu_lfq_node * struct cds_lfq_node_rcu *
_rcu_lfq_dequeue(struct rcu_lfq_queue *q, void (*release)(struct urcu_ref * _cds_lfq_dequeue_rcu(struct cds_lfq_queue_rcu *q, void (*release)(struct ur
)) cu_ref *))
{ {
for (;;) { for (;;) {
struct rcu_lfq_node *head, *next; struct cds_lfq_node_rcu *head, *next;
rcu_read_lock(); rcu_read_lock();
head = rcu_dereference(q->head); head = rcu_dereference(q->head);
next = rcu_dereference(head->next); next = rcu_dereference(head->next);
if (next) { if (next) {
if (uatomic_cmpxchg(&q->head, head, next) == head) { if (uatomic_cmpxchg(&q->head, head, next) == head) {
rcu_read_unlock(); rcu_read_unlock();
urcu_ref_put(&head->ref, release); urcu_ref_put(&head->ref, release);
return next; return next;
} else { } else {
 End of changes. 8 change blocks. 
10 lines changed or deleted 10 lines changed or added


 rculfqueue.h   rculfqueue.h 
skipping to change at line 43 skipping to change at line 43
/* /*
* Lock-free RCU queue using reference counting. Enqueue and dequeue operat ions * Lock-free RCU queue using reference counting. Enqueue and dequeue operat ions
* hold a RCU read lock to deal with cmpxchg ABA problem. This implementati on * hold a RCU read lock to deal with cmpxchg ABA problem. This implementati on
* keeps a dummy head node to ensure we can always update the queue lockles sly. * keeps a dummy head node to ensure we can always update the queue lockles sly.
* Given that this is a queue, the dummy head node must always advance as w e * Given that this is a queue, the dummy head node must always advance as w e
* dequeue entries. Therefore, we keep a reference count on each entry we a re * dequeue entries. Therefore, we keep a reference count on each entry we a re
* dequeueing, so they can be kept as dummy head node until the next dequeu e, at * dequeueing, so they can be kept as dummy head node until the next dequeu e, at
* which point their reference count will be decremented. * which point their reference count will be decremented.
*/ */
struct rcu_lfq_node { struct cds_lfq_node_rcu {
struct rcu_lfq_node *next; struct cds_lfq_node_rcu *next;
struct urcu_ref ref; struct urcu_ref ref;
}; };
struct rcu_lfq_queue { struct cds_lfq_queue_rcu {
struct rcu_lfq_node *head, *tail; struct cds_lfq_node_rcu *head, *tail;
struct rcu_lfq_node init; /* Dummy initialization node */ struct cds_lfq_node_rcu init; /* Dummy initialization node */
}; };
#ifdef _LGPL_SOURCE #ifdef _LGPL_SOURCE
#include <urcu/rculfqueue-static.h> #include <urcu/rculfqueue-static.h>
#define rcu_lfq_node_init _rcu_lfq_node_init #define cds_lfq_node_init_rcu _cds_lfq_node_init_rcu
#define rcu_lfq_init _rcu_lfq_init #define cds_lfq_init_rcu _cds_lfq_init_rcu
#define rcu_lfq_enqueue _rcu_lfq_enqueue #define cds_lfq_enqueue_rcu _cds_lfq_enqueue_rcu
#define rcu_lfq_dequeue _rcu_lfq_dequeue #define cds_lfq_dequeue_rcu _cds_lfq_dequeue_rcu
#else /* !_LGPL_SOURCE */ #else /* !_LGPL_SOURCE */
extern void rcu_lfq_node_init(struct rcu_lfq_node *node); extern void cds_lfq_node_init_rcu(struct cds_lfq_node_rcu *node);
extern void rcu_lfq_init(struct rcu_lfq_queue *q); extern void cds_lfq_init_rcu(struct cds_lfq_queue_rcu *q);
extern void rcu_lfq_enqueue(struct rcu_lfq_queue *q, struct rcu_lfq_node *n extern void cds_lfq_enqueue_rcu(struct cds_lfq_queue_rcu *q, struct cds_lfq
ode); _node_rcu *node);
/* /*
* The entry returned by dequeue must be taken care of by doing a urcu_ref_ put, * The entry returned by dequeue must be taken care of by doing a urcu_ref_ put,
* which calls the release primitive when the reference count drops to zero . A * which calls the release primitive when the reference count drops to zero . A
* grace period must be waited after execution of the release callback befo re * grace period must be waited after execution of the release callback befo re
* performing the actual memory reclamation or modifying the rcu_lfq_node * performing the actual memory reclamation or modifying the cds_lfq_node_r cu
* structure. * structure.
* In other words, the entry lfq node returned by dequeue must not be * In other words, the entry lfq node returned by dequeue must not be
* modified/re-used/freed until the reference count reaches zero and a grac e * modified/re-used/freed until the reference count reaches zero and a grac e
* period has elapsed (after the refcount reached 0). * period has elapsed (after the refcount reached 0).
*/ */
extern struct rcu_lfq_node * extern struct cds_lfq_node_rcu *
rcu_lfq_dequeue(struct rcu_lfq_queue *q, void (*release)(struct urcu_ref *) cds_lfq_dequeue_rcu(struct cds_lfq_queue_rcu *q, void (*release)(struct urc
); u_ref *));
#endif /* !_LGPL_SOURCE */ #endif /* !_LGPL_SOURCE */
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* _URCU_RCULFQUEUE_H */ #endif /* _URCU_RCULFQUEUE_H */
 End of changes. 6 change blocks. 
17 lines changed or deleted 17 lines changed or added


 rculfstack-static.h   rculfstack-static.h 
skipping to change at line 36 skipping to change at line 36
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include <urcu/uatomic_arch.h> #include <urcu/uatomic_arch.h>
/* A urcu implementation header should be already included. */ /* A urcu implementation header should be already included. */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
void _rcu_lfs_node_init(struct rcu_lfs_node *node) void _cds_lfs_node_init_rcu(struct cds_lfs_node_rcu *node)
{ {
} }
void _rcu_lfs_init(struct rcu_lfs_stack *s) void _cds_lfs_init_rcu(struct cds_lfs_stack_rcu *s)
{ {
s->head = NULL; s->head = NULL;
} }
void _rcu_lfs_push(struct rcu_lfs_stack *s, struct rcu_lfs_node *node) void _cds_lfs_push_rcu(struct cds_lfs_stack_rcu *s, struct cds_lfs_node_rcu *node)
{ {
struct rcu_lfs_node *head = NULL; struct cds_lfs_node_rcu *head = NULL;
for (;;) { for (;;) {
struct rcu_lfs_node *old_head = head; struct cds_lfs_node_rcu *old_head = head;
node->next = head; node->next = head;
/* /*
* uatomic_cmpxchg() implicit memory barrier orders earlier * uatomic_cmpxchg() implicit memory barrier orders earlier
* stores to node before publication. * stores to node before publication.
*/ */
head = uatomic_cmpxchg(&s->head, old_head, node); head = uatomic_cmpxchg(&s->head, old_head, node);
if (old_head == head) if (old_head == head)
break; break;
} }
} }
/* /*
* The caller must wait for a grace period to pass before freeing the retur ned * The caller must wait for a grace period to pass before freeing the retur ned
* node or modifying the rcu_lfs_node structure. * node or modifying the cds_lfs_node_rcu structure.
* Returns NULL if stack is empty. * Returns NULL if stack is empty.
*/ */
struct rcu_lfs_node * struct cds_lfs_node_rcu *
_rcu_lfs_pop(struct rcu_lfs_stack *s) _cds_lfs_pop_rcu(struct cds_lfs_stack_rcu *s)
{ {
for (;;) { for (;;) {
struct rcu_lfs_node *head; struct cds_lfs_node_rcu *head;
rcu_read_lock(); rcu_read_lock();
head = rcu_dereference(s->head); head = rcu_dereference(s->head);
if (head) { if (head) {
struct rcu_lfs_node *next = rcu_dereference(head->ne xt); struct cds_lfs_node_rcu *next = rcu_dereference(head ->next);
if (uatomic_cmpxchg(&s->head, head, next) == head) { if (uatomic_cmpxchg(&s->head, head, next) == head) {
rcu_read_unlock(); rcu_read_unlock();
return head; return head;
} else { } else {
/* Concurrent modification. Retry. */ /* Concurrent modification. Retry. */
rcu_read_unlock(); rcu_read_unlock();
continue; continue;
} }
} else { } else {
 End of changes. 9 change blocks. 
10 lines changed or deleted 10 lines changed or added


 rculfstack.h   rculfstack.h 
skipping to change at line 30 skipping to change at line 30
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software * License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
struct rcu_lfs_node { struct cds_lfs_node_rcu {
struct rcu_lfs_node *next; struct cds_lfs_node_rcu *next;
}; };
struct rcu_lfs_stack { struct cds_lfs_stack_rcu {
struct rcu_lfs_node *head; struct cds_lfs_node_rcu *head;
}; };
#ifdef _LGPL_SOURCE #ifdef _LGPL_SOURCE
#include <urcu/rculfstack-static.h> #include <urcu/rculfstack-static.h>
#define rcu_lfs_node_init _rcu_lfs_node_init #define cds_lfs_node_init_rcu _cds_lfs_node_init_rcu
#define rcu_lfs_init _rcu_lfs_init #define cds_lfs_init_rcu _cds_lfs_init_rcu
#define rcu_lfs_push _rcu_lfs_push #define cds_lfs_push_rcu _cds_lfs_push_rcu
#define rcu_lfs_pop _rcu_lfs_pop #define cds_lfs_pop_rcu _cds_lfs_pop_rcu
#else /* !_LGPL_SOURCE */ #else /* !_LGPL_SOURCE */
extern void rcu_lfs_node_init(struct rcu_lfs_node *node); extern void cds_lfs_node_init_rcu(struct cds_lfs_node_rcu *node);
extern void rcu_lfs_init(struct rcu_lfs_stack *s); extern void cds_lfs_init_rcu(struct cds_lfs_stack_rcu *s);
extern void rcu_lfs_push(struct rcu_lfs_stack *s, struct rcu_lfs_node *node extern void cds_lfs_push_rcu(struct cds_lfs_stack_rcu *s, struct cds_lfs_no
); de_rcu *node);
/* /*
* The caller must wait for a grace period to pass before freeing the retur ned * The caller must wait for a grace period to pass before freeing the retur ned
* node or modifying the rcu_lfs_node structure. * node or modifying the cds_lfs_node_rcu structure.
* Returns NULL if stack is empty. * Returns NULL if stack is empty.
*/ */
extern struct rcu_lfs_node *rcu_lfs_pop(struct rcu_lfs_stack *s); extern struct cds_lfs_node_rcu *cds_lfs_pop_rcu(struct cds_lfs_stack_rcu *s );
#endif /* !_LGPL_SOURCE */ #endif /* !_LGPL_SOURCE */
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* _URCU_RCULFSTACK_H */ #endif /* _URCU_RCULFSTACK_H */
 End of changes. 6 change blocks. 
14 lines changed or deleted 14 lines changed or added


 rculist.h   rculist.h 
skipping to change at line 33 skipping to change at line 33
#ifndef _URCU_RCULIST_H #ifndef _URCU_RCULIST_H
#define _URCU_RCULIST_H #define _URCU_RCULIST_H
#include <urcu/list.h> #include <urcu/list.h>
#include <urcu/arch.h> #include <urcu/arch.h>
#include <urcu-pointer.h> #include <urcu-pointer.h>
/* Add new element at the head of the list. /* Add new element at the head of the list.
*/ */
static inline void list_add_rcu(list_t *newp, list_t *head) static inline void cds_list_add_rcu(list_t *newp, list_t *head)
{ {
newp->next = head->next; newp->next = head->next;
newp->prev = head; newp->prev = head;
smp_wmb(); cmm_smp_wmb();
head->next->prev = newp; head->next->prev = newp;
head->next = newp; head->next = newp;
} }
/* replace an old entry atomically. /* replace an old entry atomically.
*/ */
static inline void list_replace_rcu(list_t *old, list_t *_new) static inline void cds_list_replace_rcu(list_t *old, list_t *_new)
{ {
_new->next = old->next; _new->next = old->next;
_new->prev = old->prev; _new->prev = old->prev;
rcu_assign_pointer(_new->prev->next, _new); rcu_assign_pointer(_new->prev->next, _new);
_new->next->prev = _new; _new->next->prev = _new;
} }
/* Remove element from list. */ /* Remove element from list. */
static inline void list_del_rcu(list_t *elem) static inline void cds_list_del_rcu(list_t *elem)
{ {
elem->next->prev = elem->prev; elem->next->prev = elem->prev;
elem->prev->next = elem->next; elem->prev->next = elem->next;
} }
/* /*
* Iteration through all elements of the list must be done while rcu_read_l ock() * Iteration through all elements of the list must be done while rcu_read_l ock()
* is held. * is held.
*/ */
/* Iterate forward over the elements of the list. */ /* Iterate forward over the elements of the list. */
#define list_for_each_rcu(pos, head) \ #define cds_list_for_each_rcu(pos, head) \
for (pos = rcu_dereference((head)->next); pos != (head); \ for (pos = rcu_dereference((head)->next); pos != (head); \
pos = rcu_dereference(pos->next)) pos = rcu_dereference(pos->next))
/* Iterate through elements of the list. /* Iterate through elements of the list.
*/ */
#define list_for_each_entry_rcu(pos, head, member) #define cds_list_for_each_entry_rcu(pos, head, member)
\ \
for (pos = list_entry(rcu_dereference((head)->next), typeof(*pos), m for (pos = cds_list_entry(rcu_dereference((head)->next), typeof(*pos
ember); \ ), member); \
&pos->member != (head); \ &pos->member != (head); \
pos = list_entry(rcu_dereference(pos->member.next), typeof(*pos ), member)) pos = cds_list_entry(rcu_dereference(pos->member.next), typeof( *pos), member))
#endif /* _URCU_RCULIST_H */ #endif /* _URCU_RCULIST_H */
 End of changes. 7 change blocks. 
10 lines changed or deleted 10 lines changed or added


 system.h   system.h 
skipping to change at line 25 skipping to change at line 25
* for any purpose, provided the above notices are retained on all copies. * for any purpose, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is granted , * Permission to modify the code and to distribute modified code is granted ,
* provided the above notices are retained, and a notice that the code was * provided the above notices are retained, and a notice that the code was
* modified is included with the above copyright notice. * modified is included with the above copyright notice.
*/ */
#include <urcu/compiler.h> #include <urcu/compiler.h>
#include <urcu/arch.h> #include <urcu/arch.h>
/* /*
* Identify a shared load. A smp_rmc() or smp_mc() should come before the l oad. * Identify a shared load. A cmm_smp_rmc() or cmm_smp_mc() should come befo re the load.
*/ */
#define _LOAD_SHARED(p) ACCESS_ONCE(p) #define _CAA_LOAD_SHARED(p) CAA_ACCESS_ONCE(p)
/* /*
* Load a data from shared memory, doing a cache flush if required. * Load a data from shared memory, doing a cache flush if required.
*/ */
#define LOAD_SHARED(p) \ #define CAA_LOAD_SHARED(p) \
({ \ ({ \
smp_rmc(); \ cmm_smp_rmc(); \
_LOAD_SHARED(p); \ _CAA_LOAD_SHARED(p); \
}) })
/* /*
* Identify a shared store. A smp_wmc() or smp_mc() should follow the store . * Identify a shared store. A cmm_smp_wmc() or cmm_smp_mc() should follow t he store.
*/ */
#define _STORE_SHARED(x, v) ({ ACCESS_ONCE(x) = (v); }) #define _CAA_STORE_SHARED(x, v) ({ CAA_ACCESS_ONCE(x) = (v); })
/* /*
* Store v into x, where x is located in shared memory. Performs the requir ed * Store v into x, where x is located in shared memory. Performs the requir ed
* cache flush after writing. Returns v. * cache flush after writing. Returns v.
*/ */
#define STORE_SHARED(x, v) \ #define CAA_STORE_SHARED(x, v) \
({ \ ({ \
typeof(x) _v = _STORE_SHARED(x, v); \ typeof(x) _v = _CAA_STORE_SHARED(x, v); \
smp_wmc(); \ cmm_smp_wmc(); \
_v; \ _v; \
}) })
#endif /* _URCU_SYSTEM_H */ #endif /* _URCU_SYSTEM_H */
 End of changes. 8 change blocks. 
10 lines changed or deleted 10 lines changed or added


 uatomic_arch.h   uatomic_arch.h 
skipping to change at line 42 skipping to change at line 42
/* /*
* Derived from AO_compare_and_swap() and AO_test_and_set_full(). * Derived from AO_compare_and_swap() and AO_test_and_set_full().
*/ */
struct __uatomic_dummy { struct __uatomic_dummy {
unsigned long v[10]; unsigned long v[10];
}; };
#define __hp(x) ((struct __uatomic_dummy *)(x)) #define __hp(x) ((struct __uatomic_dummy *)(x))
#define _uatomic_set(addr, v) STORE_SHARED(*(addr), (v)) #define _uatomic_set(addr, v) CAA_STORE_SHARED(*(addr), (v))
/* cmpxchg */ /* cmpxchg */
static inline __attribute__((always_inline)) static inline __attribute__((always_inline))
unsigned long __uatomic_cmpxchg(void *addr, unsigned long old, unsigned long __uatomic_cmpxchg(void *addr, unsigned long old,
unsigned long _new, int len) unsigned long _new, int len)
{ {
switch (len) { switch (len) {
case 1: case 1:
{ {
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 uatomic_generic.h   uatomic_generic.h 
skipping to change at line 32 skipping to change at line 32
*/ */
#include <urcu/compiler.h> #include <urcu/compiler.h>
#include <urcu/system.h> #include <urcu/system.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#ifndef uatomic_set #ifndef uatomic_set
#define uatomic_set(addr, v) STORE_SHARED(*(addr), (v)) #define uatomic_set(addr, v) CAA_STORE_SHARED(*(addr), (v))
#endif #endif
#ifndef uatomic_read #ifndef uatomic_read
#define uatomic_read(addr) LOAD_SHARED(*(addr)) #define uatomic_read(addr) CAA_LOAD_SHARED(*(addr))
#endif #endif
#if !defined __OPTIMIZE__ || defined UATOMIC_NO_LINK_ERROR #if !defined __OPTIMIZE__ || defined UATOMIC_NO_LINK_ERROR
static inline __attribute__((always_inline)) static inline __attribute__((always_inline))
void _uatomic_link_error() void _uatomic_link_error()
{ {
#ifdef ILLEGAL_INSTR #ifdef ILLEGAL_INSTR
/* generate an illegal instruction. Cannot catch this with linker tr icks /* generate an illegal instruction. Cannot catch this with linker tr icks
* when optimizations are disabled. */ * when optimizations are disabled. */
__asm__ __volatile__(ILLEGAL_INSTR); __asm__ __volatile__(ILLEGAL_INSTR);
 End of changes. 2 change blocks. 
2 lines changed or deleted 2 lines changed or added


 urcu-bp-static.h   urcu-bp-static.h 
skipping to change at line 143 skipping to change at line 143
* Global quiescent period counter with low-order bits unused. * Global quiescent period counter with low-order bits unused.
* Using a int rather than a char to eliminate false register dependencies * Using a int rather than a char to eliminate false register dependencies
* causing stalls on some architectures. * causing stalls on some architectures.
*/ */
extern long rcu_gp_ctr; extern long rcu_gp_ctr;
struct rcu_reader { struct rcu_reader {
/* Data used by both reader and synchronize_rcu() */ /* Data used by both reader and synchronize_rcu() */
long ctr; long ctr;
/* Data used for registry */ /* Data used for registry */
struct list_head node __attribute__((aligned(CACHE_LINE_SIZE))); struct cds_list_head node __attribute__((aligned(CAA_CACHE_LINE_SIZE )));
pthread_t tid; pthread_t tid;
int alloc; /* registry entry allocated */ int alloc; /* registry entry allocated */
}; };
/* /*
* Bulletproof version keeps a pointer to a registry not part of the TLS. * Bulletproof version keeps a pointer to a registry not part of the TLS.
* Adds a pointer dereference on the read-side, but won't require to unregi ster * Adds a pointer dereference on the read-side, but won't require to unregi ster
* the reader thread. * the reader thread.
*/ */
extern struct rcu_reader __thread *rcu_reader; extern struct rcu_reader __thread *rcu_reader;
skipping to change at line 165 skipping to change at line 165
static inline int rcu_old_gp_ongoing(long *value) static inline int rcu_old_gp_ongoing(long *value)
{ {
long v; long v;
if (value == NULL) if (value == NULL)
return 0; return 0;
/* /*
* Make sure both tests below are done on the same version of *value * Make sure both tests below are done on the same version of *value
* to insure consistency. * to insure consistency.
*/ */
v = LOAD_SHARED(*value); v = CAA_LOAD_SHARED(*value);
return (v & RCU_GP_CTR_NEST_MASK) && return (v & RCU_GP_CTR_NEST_MASK) &&
((v ^ rcu_gp_ctr) & RCU_GP_CTR_PHASE); ((v ^ rcu_gp_ctr) & RCU_GP_CTR_PHASE);
} }
static inline void _rcu_read_lock(void) static inline void _rcu_read_lock(void)
{ {
long tmp; long tmp;
/* Check if registered */ /* Check if registered */
if (unlikely(!rcu_reader)) if (unlikely(!rcu_reader))
rcu_bp_register(); rcu_bp_register();
cmm_barrier(); /* Ensure the compiler does not reorder us with mute x */
tmp = rcu_reader->ctr; tmp = rcu_reader->ctr;
/* /*
* rcu_gp_ctr is * rcu_gp_ctr is
* RCU_GP_COUNT | (~RCU_GP_CTR_PHASE or RCU_GP_CTR_PHASE) * RCU_GP_COUNT | (~RCU_GP_CTR_PHASE or RCU_GP_CTR_PHASE)
*/ */
if (likely(!(tmp & RCU_GP_CTR_NEST_MASK))) { if (likely(!(tmp & RCU_GP_CTR_NEST_MASK))) {
_STORE_SHARED(rcu_reader->ctr, _LOAD_SHARED(rcu_gp_ctr)); _CAA_STORE_SHARED(rcu_reader->ctr, _CAA_LOAD_SHARED(rcu_gp_c tr));
/* /*
* Set active readers count for outermost nesting level befo re * Set active readers count for outermost nesting level befo re
* accessing the pointer. * accessing the pointer.
*/ */
smp_mb(); cmm_smp_mb();
} else { } else {
_STORE_SHARED(rcu_reader->ctr, tmp + RCU_GP_COUNT); _CAA_STORE_SHARED(rcu_reader->ctr, tmp + RCU_GP_COUNT);
} }
} }
static inline void _rcu_read_unlock(void) static inline void _rcu_read_unlock(void)
{ {
/* /*
* Finish using rcu before decrementing the pointer. * Finish using rcu before decrementing the pointer.
*/ */
smp_mb(); cmm_smp_mb();
_STORE_SHARED(rcu_reader->ctr, rcu_reader->ctr - RCU_GP_COUNT); _CAA_STORE_SHARED(rcu_reader->ctr, rcu_reader->ctr - RCU_GP_COUNT);
cmm_barrier(); /* Ensure the compiler does not reorder us with mute
x */
} }
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* _URCU_BP_STATIC_H */ #endif /* _URCU_BP_STATIC_H */
 End of changes. 7 change blocks. 
7 lines changed or deleted 10 lines changed or added


 urcu-defer-static.h   urcu-defer-static.h 
skipping to change at line 101 skipping to change at line 101
* - else current element contains data * - else current element contains data
*/ */
struct defer_queue { struct defer_queue {
unsigned long head; /* add element at head */ unsigned long head; /* add element at head */
void *last_fct_in; /* last fct pointer encoded */ void *last_fct_in; /* last fct pointer encoded */
unsigned long tail; /* next element to remove at tail */ unsigned long tail; /* next element to remove at tail */
void *last_fct_out; /* last fct pointer encoded */ void *last_fct_out; /* last fct pointer encoded */
void **q; void **q;
/* registry information */ /* registry information */
unsigned long last_head; unsigned long last_head;
struct list_head list; /* list of thread queues */ struct cds_list_head list; /* list of thread queues */
}; };
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* _URCU_DEFER_STATIC_H */ #endif /* _URCU_DEFER_STATIC_H */
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 urcu-pointer-static.h   urcu-pointer-static.h 
skipping to change at line 52 skipping to change at line 52
* _rcu_dereference - reads (copy) a RCU-protected pointer to a local varia ble * _rcu_dereference - reads (copy) a RCU-protected pointer to a local varia ble
* into a RCU read-side critical section. The pointer can later be safely * into a RCU read-side critical section. The pointer can later be safely
* dereferenced within the critical section. * dereferenced within the critical section.
* *
* This ensures that the pointer copy is invariant thorough the whole criti cal * This ensures that the pointer copy is invariant thorough the whole criti cal
* section. * section.
* *
* Inserts memory barriers on architectures that require them (currently on ly * Inserts memory barriers on architectures that require them (currently on ly
* Alpha) and documents which pointers are protected by RCU. * Alpha) and documents which pointers are protected by RCU.
* *
* The compiler memory barrier in LOAD_SHARED() ensures that value-speculat ive * The compiler memory barrier in CAA_LOAD_SHARED() ensures that value-spec ulative
* optimizations (e.g. VSS: Value Speculation Scheduling) does not perform the * optimizations (e.g. VSS: Value Speculation Scheduling) does not perform the
* data read before the pointer read by speculating the value of the pointe r. * data read before the pointer read by speculating the value of the pointe r.
* Correct ordering is ensured because the pointer is read as a volatile ac cess. * Correct ordering is ensured because the pointer is read as a volatile ac cess.
* This acts as a global side-effect operation, which forbids reordering of * This acts as a global side-effect operation, which forbids reordering of
* dependent memory operations. Note that such concern about dependency-bre aking * dependent memory operations. Note that such concern about dependency-bre aking
* optimizations will eventually be taken care of by the "memory_order_cons ume" * optimizations will eventually be taken care of by the "memory_order_cons ume"
* addition to forthcoming C++ standard. * addition to forthcoming C++ standard.
* *
* Should match rcu_assign_pointer() or rcu_xchg_pointer(). * Should match rcu_assign_pointer() or rcu_xchg_pointer().
*/ */
#define _rcu_dereference(p) ({ \ #define _rcu_dereference(p) ({ \
typeof(p) _________p1 = LOAD_SHARED(p); \ typeof(p) _________p1 = CAA_LOAD_SHARED(p);
smp_read_barrier_depends(); \ \
cmm_smp_read_barrier_depends(); \
(_________p1); \ (_________p1); \
}) })
/** /**
* _rcu_cmpxchg_pointer - same as rcu_assign_pointer, but tests if the poin ter * _rcu_cmpxchg_pointer - same as rcu_assign_pointer, but tests if the poin ter
* is as expected by "old". If succeeds, returns the previous pointer to th e * is as expected by "old". If succeeds, returns the previous pointer to th e
* data structure, which can be safely freed after waiting for a quiescent state * data structure, which can be safely freed after waiting for a quiescent state
* using synchronize_rcu(). If fails (unexpected value), returns old (which * using synchronize_rcu(). If fails (unexpected value), returns old (which
* should not be freed !). * should not be freed !).
*/ */
#define _rcu_cmpxchg_pointer(p, old, _new) \ #define _rcu_cmpxchg_pointer(p, old, _new) \
({ \ ({ \
typeof(*p) _________pold = (old); \ typeof(*p) _________pold = (old); \
typeof(*p) _________pnew = (_new); \ typeof(*p) _________pnew = (_new); \
if (!__builtin_constant_p(_new) || \ if (!__builtin_constant_p(_new) || \
((_new) != NULL)) \ ((_new) != NULL)) \
wmb(); \ cmm_wmb(); \
uatomic_cmpxchg(p, _________pold, _________pnew); \ uatomic_cmpxchg(p, _________pold, _________pnew); \
}) })
/** /**
* _rcu_xchg_pointer - same as rcu_assign_pointer, but returns the previous * _rcu_xchg_pointer - same as rcu_assign_pointer, but returns the previous
* pointer to the data structure, which can be safely freed after waiting f or a * pointer to the data structure, which can be safely freed after waiting f or a
* quiescent state using synchronize_rcu(). * quiescent state using synchronize_rcu().
*/ */
#define _rcu_xchg_pointer(p, v) \ #define _rcu_xchg_pointer(p, v) \
({ \ ({ \
typeof(*p) _________pv = (v); \ typeof(*p) _________pv = (v); \
if (!__builtin_constant_p(v) || \ if (!__builtin_constant_p(v) || \
((v) != NULL)) \ ((v) != NULL)) \
wmb(); \ cmm_wmb(); \
uatomic_xchg(p, _________pv); \ uatomic_xchg(p, _________pv); \
}) })
#define _rcu_set_pointer(p, v) \ #define _rcu_set_pointer(p, v) \
({ \ ({ \
typeof(*p) _________pv = (v); \ typeof(*p) _________pv = (v); \
if (!__builtin_constant_p(v) || \ if (!__builtin_constant_p(v) || \
((v) != NULL)) \ ((v) != NULL)) \
wmb(); \ cmm_wmb(); \
uatomic_set(p, _________pv); \ uatomic_set(p, _________pv); \
}) })
/** /**
* _rcu_assign_pointer - assign (publicize) a pointer to a new data structu re * _rcu_assign_pointer - assign (publicize) a pointer to a new data structu re
* meant to be read by RCU read-side critical sections. Returns the assigne d * meant to be read by RCU read-side critical sections. Returns the assigne d
* value. * value.
* *
* Documents which pointers will be dereferenced by RCU read-side critical * Documents which pointers will be dereferenced by RCU read-side critical
* sections and adds the required memory barriers on architectures requirin g * sections and adds the required memory barriers on architectures requirin g
 End of changes. 5 change blocks. 
6 lines changed or deleted 7 lines changed or added


 urcu-qsbr-static.h   urcu-qsbr-static.h 
skipping to change at line 138 skipping to change at line 138
* Global quiescent period counter with low-order bits unused. * Global quiescent period counter with low-order bits unused.
* Using a int rather than a char to eliminate false register dependencies * Using a int rather than a char to eliminate false register dependencies
* causing stalls on some architectures. * causing stalls on some architectures.
*/ */
extern unsigned long rcu_gp_ctr; extern unsigned long rcu_gp_ctr;
struct rcu_reader { struct rcu_reader {
/* Data used by both reader and synchronize_rcu() */ /* Data used by both reader and synchronize_rcu() */
unsigned long ctr; unsigned long ctr;
/* Data used for registry */ /* Data used for registry */
struct list_head node __attribute__((aligned(CACHE_LINE_SIZE))); struct cds_list_head node __attribute__((aligned(CAA_CACHE_LINE_SIZE )));
pthread_t tid; pthread_t tid;
}; };
extern struct rcu_reader __thread rcu_reader; extern struct rcu_reader __thread rcu_reader;
extern int gp_futex; extern int gp_futex;
/* /*
* Wake-up waiting synchronize_rcu(). Called from many concurrent threads. * Wake-up waiting synchronize_rcu(). Called from many concurrent threads.
*/ */
skipping to change at line 162 skipping to change at line 162
uatomic_set(&gp_futex, 0); uatomic_set(&gp_futex, 0);
futex_noasync(&gp_futex, FUTEX_WAKE, 1, futex_noasync(&gp_futex, FUTEX_WAKE, 1,
NULL, NULL, 0); NULL, NULL, 0);
} }
} }
static inline int rcu_gp_ongoing(unsigned long *ctr) static inline int rcu_gp_ongoing(unsigned long *ctr)
{ {
unsigned long v; unsigned long v;
v = LOAD_SHARED(*ctr); v = CAA_LOAD_SHARED(*ctr);
return v && (v != rcu_gp_ctr); return v && (v != rcu_gp_ctr);
} }
static inline void _rcu_read_lock(void) static inline void _rcu_read_lock(void)
{ {
rcu_assert(rcu_reader.ctr); rcu_assert(rcu_reader.ctr);
} }
static inline void _rcu_read_unlock(void) static inline void _rcu_read_unlock(void)
{ {
} }
static inline void _rcu_quiescent_state(void) static inline void _rcu_quiescent_state(void)
{ {
smp_mb(); cmm_smp_mb();
_STORE_SHARED(rcu_reader.ctr, _LOAD_SHARED(rcu_gp_ctr)); _CAA_STORE_SHARED(rcu_reader.ctr, _CAA_LOAD_SHARED(rcu_gp_ctr));
smp_mb(); /* write rcu_reader.ctr before read futex */ cmm_smp_mb(); /* write rcu_reader.ctr before read futex */
wake_up_gp(); wake_up_gp();
smp_mb(); cmm_smp_mb();
} }
static inline void _rcu_thread_offline(void) static inline void _rcu_thread_offline(void)
{ {
smp_mb(); cmm_smp_mb();
STORE_SHARED(rcu_reader.ctr, 0); CAA_STORE_SHARED(rcu_reader.ctr, 0);
smp_mb(); /* write rcu_reader.ctr before read futex */ cmm_smp_mb(); /* write rcu_reader.ctr before read futex */
wake_up_gp(); wake_up_gp();
cmm_barrier(); /* Ensure the compiler does not reorder us with mute x */
} }
static inline void _rcu_thread_online(void) static inline void _rcu_thread_online(void)
{ {
_STORE_SHARED(rcu_reader.ctr, LOAD_SHARED(rcu_gp_ctr)); cmm_barrier(); /* Ensure the compiler does not reorder us with mute
smp_mb(); x */
_CAA_STORE_SHARED(rcu_reader.ctr, CAA_LOAD_SHARED(rcu_gp_ctr));
cmm_smp_mb();
} }
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* _URCU_QSBR_STATIC_H */ #endif /* _URCU_QSBR_STATIC_H */
 End of changes. 7 change blocks. 
11 lines changed or deleted 14 lines changed or added


 urcu-static.h   urcu-static.h 
skipping to change at line 184 skipping to change at line 184
#define MB_GROUP_ALL 0 #define MB_GROUP_ALL 0
#define RCU_MB_GROUP MB_GROUP_ALL #define RCU_MB_GROUP MB_GROUP_ALL
#ifdef RCU_MEMBARRIER #ifdef RCU_MEMBARRIER
extern int has_sys_membarrier; extern int has_sys_membarrier;
static inline void smp_mb_slave(int group) static inline void smp_mb_slave(int group)
{ {
if (likely(has_sys_membarrier)) if (likely(has_sys_membarrier))
barrier(); cmm_barrier();
else else
smp_mb(); cmm_smp_mb();
} }
#endif #endif
#ifdef RCU_MB #ifdef RCU_MB
static inline void smp_mb_slave(int group) static inline void smp_mb_slave(int group)
{ {
smp_mb(); cmm_smp_mb();
} }
#endif #endif
#ifdef RCU_SIGNAL #ifdef RCU_SIGNAL
static inline void smp_mb_slave(int group) static inline void smp_mb_slave(int group)
{ {
barrier(); cmm_barrier();
} }
#endif #endif
/* /*
* The trick here is that RCU_GP_CTR_PHASE must be a multiple of 8 so we ca n use * The trick here is that RCU_GP_CTR_PHASE must be a multiple of 8 so we ca n use
* a full 8-bits, 16-bits or 32-bits bitmask for the lower order bits. * a full 8-bits, 16-bits or 32-bits bitmask for the lower order bits.
*/ */
#define RCU_GP_COUNT (1UL << 0) #define RCU_GP_COUNT (1UL << 0)
/* Use the amount of bits equal to half of the architecture long size */ /* Use the amount of bits equal to half of the architecture long size */
#define RCU_GP_CTR_PHASE (1UL << (sizeof(unsigned long) << 2)) #define RCU_GP_CTR_PHASE (1UL << (sizeof(unsigned long) << 2))
skipping to change at line 225 skipping to change at line 225
* Using a int rather than a char to eliminate false register dependencies * Using a int rather than a char to eliminate false register dependencies
* causing stalls on some architectures. * causing stalls on some architectures.
*/ */
extern unsigned long rcu_gp_ctr; extern unsigned long rcu_gp_ctr;
struct rcu_reader { struct rcu_reader {
/* Data used by both reader and synchronize_rcu() */ /* Data used by both reader and synchronize_rcu() */
unsigned long ctr; unsigned long ctr;
char need_mb; char need_mb;
/* Data used for registry */ /* Data used for registry */
struct list_head node __attribute__((aligned(CACHE_LINE_SIZE))); struct cds_list_head node __attribute__((aligned(CAA_CACHE_LINE_SIZE )));
pthread_t tid; pthread_t tid;
}; };
extern struct rcu_reader __thread rcu_reader; extern struct rcu_reader __thread rcu_reader;
extern int gp_futex; extern int gp_futex;
/* /*
* Wake-up waiting synchronize_rcu(). Called from many concurrent threads. * Wake-up waiting synchronize_rcu(). Called from many concurrent threads.
*/ */
skipping to change at line 253 skipping to change at line 253
} }
static inline int rcu_gp_ongoing(unsigned long *ctr) static inline int rcu_gp_ongoing(unsigned long *ctr)
{ {
unsigned long v; unsigned long v;
/* /*
* Make sure both tests below are done on the same version of *value * Make sure both tests below are done on the same version of *value
* to insure consistency. * to insure consistency.
*/ */
v = LOAD_SHARED(*ctr); v = CAA_LOAD_SHARED(*ctr);
return (v & RCU_GP_CTR_NEST_MASK) && return (v & RCU_GP_CTR_NEST_MASK) &&
((v ^ rcu_gp_ctr) & RCU_GP_CTR_PHASE); ((v ^ rcu_gp_ctr) & RCU_GP_CTR_PHASE);
} }
static inline void _rcu_read_lock(void) static inline void _rcu_read_lock(void)
{ {
unsigned long tmp; unsigned long tmp;
cmm_barrier(); /* Ensure the compiler does not reorder us with mute x */
tmp = rcu_reader.ctr; tmp = rcu_reader.ctr;
/* /*
* rcu_gp_ctr is * rcu_gp_ctr is
* RCU_GP_COUNT | (~RCU_GP_CTR_PHASE or RCU_GP_CTR_PHASE) * RCU_GP_COUNT | (~RCU_GP_CTR_PHASE or RCU_GP_CTR_PHASE)
*/ */
if (likely(!(tmp & RCU_GP_CTR_NEST_MASK))) { if (likely(!(tmp & RCU_GP_CTR_NEST_MASK))) {
_STORE_SHARED(rcu_reader.ctr, _LOAD_SHARED(rcu_gp_ctr)); _CAA_STORE_SHARED(rcu_reader.ctr, _CAA_LOAD_SHARED(rcu_gp_ct r));
/* /*
* Set active readers count for outermost nesting level befo re * Set active readers count for outermost nesting level befo re
* accessing the pointer. See smp_mb_master(). * accessing the pointer. See smp_mb_master().
*/ */
smp_mb_slave(RCU_MB_GROUP); smp_mb_slave(RCU_MB_GROUP);
} else { } else {
_STORE_SHARED(rcu_reader.ctr, tmp + RCU_GP_COUNT); _CAA_STORE_SHARED(rcu_reader.ctr, tmp + RCU_GP_COUNT);
} }
} }
static inline void _rcu_read_unlock(void) static inline void _rcu_read_unlock(void)
{ {
unsigned long tmp; unsigned long tmp;
tmp = rcu_reader.ctr; tmp = rcu_reader.ctr;
/* /*
* Finish using rcu before decrementing the pointer. * Finish using rcu before decrementing the pointer.
* See smp_mb_master(). * See smp_mb_master().
*/ */
if (likely((tmp & RCU_GP_CTR_NEST_MASK) == RCU_GP_COUNT)) { if (likely((tmp & RCU_GP_CTR_NEST_MASK) == RCU_GP_COUNT)) {
smp_mb_slave(RCU_MB_GROUP); smp_mb_slave(RCU_MB_GROUP);
_STORE_SHARED(rcu_reader.ctr, rcu_reader.ctr - RCU_GP_COUNT) ; _CAA_STORE_SHARED(rcu_reader.ctr, rcu_reader.ctr - RCU_GP_CO UNT);
/* write rcu_reader.ctr before read futex */ /* write rcu_reader.ctr before read futex */
smp_mb_slave(RCU_MB_GROUP); smp_mb_slave(RCU_MB_GROUP);
wake_up_gp(); wake_up_gp();
} else { } else {
_STORE_SHARED(rcu_reader.ctr, rcu_reader.ctr - RCU_GP_COUNT) ; _CAA_STORE_SHARED(rcu_reader.ctr, rcu_reader.ctr - RCU_GP_CO UNT);
} }
cmm_barrier(); /* Ensure the compiler does not reorder us with mute x */
} }
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* _URCU_STATIC_H */ #endif /* _URCU_STATIC_H */
 End of changes. 12 change blocks. 
10 lines changed or deleted 12 lines changed or added


 wfqueue-static.h   wfqueue-static.h 
skipping to change at line 50 skipping to change at line 50
* This implementation adds a dummy head node when the queue is empty to en sure * This implementation adds a dummy head node when the queue is empty to en sure
* we can always update the queue locklessly. * we can always update the queue locklessly.
* *
* Inspired from half-wait-free/half-blocking queue implementation done by * Inspired from half-wait-free/half-blocking queue implementation done by
* Paul E. McKenney. * Paul E. McKenney.
*/ */
#define WFQ_ADAPT_ATTEMPTS 10 /* Retry if being set */ #define WFQ_ADAPT_ATTEMPTS 10 /* Retry if being set */
#define WFQ_WAIT 10 /* Wait 10 ms if being set * / #define WFQ_WAIT 10 /* Wait 10 ms if being set * /
void _wfq_node_init(struct wfq_node *node) void _cds_wfq_node_init(struct cds_wfq_node *node)
{ {
node->next = NULL; node->next = NULL;
} }
void _wfq_init(struct wfq_queue *q) void _cds_wfq_init(struct cds_wfq_queue *q)
{ {
int ret; int ret;
_wfq_node_init(&q->dummy); _cds_wfq_node_init(&q->dummy);
/* Set queue head and tail */ /* Set queue head and tail */
q->head = &q->dummy; q->head = &q->dummy;
q->tail = &q->dummy.next; q->tail = &q->dummy.next;
ret = pthread_mutex_init(&q->lock, NULL); ret = pthread_mutex_init(&q->lock, NULL);
assert(!ret); assert(!ret);
} }
void _wfq_enqueue(struct wfq_queue *q, struct wfq_node *node) void _cds_wfq_enqueue(struct cds_wfq_queue *q, struct cds_wfq_node *node)
{ {
struct wfq_node **old_tail; struct cds_wfq_node **old_tail;
/* /*
* uatomic_xchg() implicit memory barrier orders earlier stores to d ata * uatomic_xchg() implicit memory barrier orders earlier stores to d ata
* structure containing node and setting node->next to NULL before * structure containing node and setting node->next to NULL before
* publication. * publication.
*/ */
old_tail = uatomic_xchg(&q->tail, node); old_tail = uatomic_xchg(&q->tail, node);
/* /*
* At this point, dequeuers see a NULL old_tail->next, which indicat es * At this point, dequeuers see a NULL old_tail->next, which indicat es
* that the queue is being appended to. The following store will app end * that the queue is being appended to. The following store will app end
* "node" to the queue from a dequeuer perspective. * "node" to the queue from a dequeuer perspective.
*/ */
STORE_SHARED(*old_tail, node); CAA_STORE_SHARED(*old_tail, node);
} }
/* /*
* It is valid to reuse and free a dequeued node immediately. * It is valid to reuse and free a dequeued node immediately.
* *
* No need to go on a waitqueue here, as there is no possible state in whic h the * No need to go on a waitqueue here, as there is no possible state in whic h the
* list could cause dequeue to busy-loop needlessly while waiting for anoth er * list could cause dequeue to busy-loop needlessly while waiting for anoth er
* thread to be scheduled. The queue appears empty until tail->next is set by * thread to be scheduled. The queue appears empty until tail->next is set by
* enqueue. * enqueue.
*/ */
struct wfq_node * struct cds_wfq_node *
___wfq_dequeue_blocking(struct wfq_queue *q) ___cds_wfq_dequeue_blocking(struct cds_wfq_queue *q)
{ {
struct wfq_node *node, *next; struct cds_wfq_node *node, *next;
int attempt = 0; int attempt = 0;
/* /*
* Queue is empty if it only contains the dummy node. * Queue is empty if it only contains the dummy node.
*/ */
if (q->head == &q->dummy && LOAD_SHARED(q->tail) == &q->dummy.next) if (q->head == &q->dummy && CAA_LOAD_SHARED(q->tail) == &q->dummy.ne xt)
return NULL; return NULL;
node = q->head; node = q->head;
/* /*
* Adaptative busy-looping waiting for enqueuer to complete enqueue. * Adaptative busy-looping waiting for enqueuer to complete enqueue.
*/ */
while ((next = LOAD_SHARED(node->next)) == NULL) { while ((next = CAA_LOAD_SHARED(node->next)) == NULL) {
if (++attempt >= WFQ_ADAPT_ATTEMPTS) { if (++attempt >= WFQ_ADAPT_ATTEMPTS) {
poll(NULL, 0, WFQ_WAIT); /* Wait for 10ms */ poll(NULL, 0, WFQ_WAIT); /* Wait for 10ms */
attempt = 0; attempt = 0;
} else } else
cpu_relax(); caa_cpu_relax();
} }
/* /*
* Move queue head forward. * Move queue head forward.
*/ */
q->head = next; q->head = next;
/* /*
* Requeue dummy node if we just dequeued it. * Requeue dummy node if we just dequeued it.
*/ */
if (node == &q->dummy) { if (node == &q->dummy) {
_wfq_node_init(node); _cds_wfq_node_init(node);
_wfq_enqueue(q, node); _cds_wfq_enqueue(q, node);
return ___wfq_dequeue_blocking(q); return ___cds_wfq_dequeue_blocking(q);
} }
return node; return node;
} }
struct wfq_node * struct cds_wfq_node *
_wfq_dequeue_blocking(struct wfq_queue *q) _cds_wfq_dequeue_blocking(struct cds_wfq_queue *q)
{ {
struct wfq_node *retnode; struct cds_wfq_node *retnode;
int ret; int ret;
ret = pthread_mutex_lock(&q->lock); ret = pthread_mutex_lock(&q->lock);
assert(!ret); assert(!ret);
retnode = ___wfq_dequeue_blocking(q); retnode = ___cds_wfq_dequeue_blocking(q);
ret = pthread_mutex_unlock(&q->lock); ret = pthread_mutex_unlock(&q->lock);
assert(!ret); assert(!ret);
return retnode; return retnode;
} }
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* _URCU_WFQUEUE_STATIC_H */ #endif /* _URCU_WFQUEUE_STATIC_H */
 End of changes. 15 change blocks. 
19 lines changed or deleted 19 lines changed or added


 wfqueue.h   wfqueue.h 
skipping to change at line 43 skipping to change at line 43
/* /*
* Queue with wait-free enqueue/blocking dequeue. * Queue with wait-free enqueue/blocking dequeue.
* This implementation adds a dummy head node when the queue is empty to en sure * This implementation adds a dummy head node when the queue is empty to en sure
* we can always update the queue locklessly. * we can always update the queue locklessly.
* *
* Inspired from half-wait-free/half-blocking queue implementation done by * Inspired from half-wait-free/half-blocking queue implementation done by
* Paul E. McKenney. * Paul E. McKenney.
*/ */
struct wfq_node { struct cds_wfq_node {
struct wfq_node *next; struct cds_wfq_node *next;
}; };
struct wfq_queue { struct cds_wfq_queue {
struct wfq_node *head, **tail; struct cds_wfq_node *head, **tail;
struct wfq_node dummy; /* Dummy node */ struct cds_wfq_node dummy; /* Dummy node */
pthread_mutex_t lock; pthread_mutex_t lock;
}; };
#ifdef _LGPL_SOURCE #ifdef _LGPL_SOURCE
#include <urcu/wfqueue-static.h> #include <urcu/wfqueue-static.h>
#define wfq_node_init _wfq_node_init #define cds_wfq_node_init _cds_wfq_node_init
#define wfq_init _wfq_init #define cds_wfq_init _cds_wfq_init
#define wfq_enqueue _wfq_enqueue #define cds_wfq_enqueue _cds_wfq_enqueue
#define __wfq_dequeue_blocking ___wfq_dequeue_blocking #define __cds_wfq_dequeue_blocking ___cds_wfq_dequeue_blocking
#define wfq_dequeue_blocking _wfq_dequeue_blocking #define cds_wfq_dequeue_blocking _cds_wfq_dequeue_blocking
#else /* !_LGPL_SOURCE */ #else /* !_LGPL_SOURCE */
extern void wfq_node_init(struct wfq_node *node); extern void cds_wfq_node_init(struct cds_wfq_node *node);
extern void wfq_init(struct wfq_queue *q); extern void cds_wfq_init(struct cds_wfq_queue *q);
extern void wfq_enqueue(struct wfq_queue *q, struct wfq_node *node); extern void cds_wfq_enqueue(struct cds_wfq_queue *q, struct cds_wfq_node *n
/* __wfq_dequeue_blocking: caller ensures mutual exclusion between dequeues ode);
*/ /* __cds_wfq_dequeue_blocking: caller ensures mutual exclusion between dequ
extern struct wfq_node *__wfq_dequeue_blocking(struct wfq_queue *q); eues */
extern struct wfq_node *wfq_dequeue_blocking(struct wfq_queue *q); extern struct cds_wfq_node *__cds_wfq_dequeue_blocking(struct cds_wfq_queue
*q);
extern struct cds_wfq_node *cds_wfq_dequeue_blocking(struct cds_wfq_queue *
q);
#endif /* !_LGPL_SOURCE */ #endif /* !_LGPL_SOURCE */
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* _URCU_WFQUEUE_H */ #endif /* _URCU_WFQUEUE_H */
 End of changes. 4 change blocks. 
17 lines changed or deleted 20 lines changed or added


 wfstack-static.h   wfstack-static.h 
skipping to change at line 38 skipping to change at line 38
#include <pthread.h> #include <pthread.h>
#include <assert.h> #include <assert.h>
#include <urcu/compiler.h> #include <urcu/compiler.h>
#include <urcu/uatomic_arch.h> #include <urcu/uatomic_arch.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#define WF_STACK_END ((void *)0x1UL) #define CDS_WF_STACK_END ((void *)0x1UL)
#define WFS_ADAPT_ATTEMPTS 10 /* Retry if being set */ #define CDS_WFS_ADAPT_ATTEMPTS 10 /* Retry if being set */
#define WFS_WAIT 10 /* Wait 10 ms if being set * #define CDS_WFS_WAIT 10 /* Wait 10 ms if being set *
/ /
void _wfs_node_init(struct wfs_node *node) void _cds_wfs_node_init(struct cds_wfs_node *node)
{ {
node->next = NULL; node->next = NULL;
} }
void _wfs_init(struct wfs_stack *s) void _cds_wfs_init(struct cds_wfs_stack *s)
{ {
int ret; int ret;
s->head = WF_STACK_END; s->head = CDS_WF_STACK_END;
ret = pthread_mutex_init(&s->lock, NULL); ret = pthread_mutex_init(&s->lock, NULL);
assert(!ret); assert(!ret);
} }
void _wfs_push(struct wfs_stack *s, struct wfs_node *node) void _cds_wfs_push(struct cds_wfs_stack *s, struct cds_wfs_node *node)
{ {
struct wfs_node *old_head; struct cds_wfs_node *old_head;
assert(node->next == NULL); assert(node->next == NULL);
/* /*
* uatomic_xchg() implicit memory barrier orders earlier stores to n ode * uatomic_xchg() implicit memory barrier orders earlier stores to n ode
* (setting it to NULL) before publication. * (setting it to NULL) before publication.
*/ */
old_head = uatomic_xchg(&s->head, node); old_head = uatomic_xchg(&s->head, node);
/* /*
* At this point, dequeuers see a NULL node->next, they should busy- wait * At this point, dequeuers see a NULL node->next, they should busy- wait
* until node->next is set to old_head. * until node->next is set to old_head.
*/ */
STORE_SHARED(node->next, old_head); CAA_STORE_SHARED(node->next, old_head);
} }
/* /*
* Returns NULL if stack is empty. * Returns NULL if stack is empty.
*/ */
struct wfs_node * struct cds_wfs_node *
___wfs_pop_blocking(struct wfs_stack *s) ___cds_wfs_pop_blocking(struct cds_wfs_stack *s)
{ {
struct wfs_node *head, *next; struct cds_wfs_node *head, *next;
int attempt = 0; int attempt = 0;
retry: retry:
head = LOAD_SHARED(s->head); head = CAA_LOAD_SHARED(s->head);
if (head == WF_STACK_END) if (head == CDS_WF_STACK_END)
return NULL; return NULL;
/* /*
* Adaptative busy-looping waiting for push to complete. * Adaptative busy-looping waiting for push to complete.
*/ */
while ((next = LOAD_SHARED(head->next)) == NULL) { while ((next = CAA_LOAD_SHARED(head->next)) == NULL) {
if (++attempt >= WFS_ADAPT_ATTEMPTS) { if (++attempt >= CDS_WFS_ADAPT_ATTEMPTS) {
poll(NULL, 0, WFS_WAIT); /* Wait for 10ms */ poll(NULL, 0, CDS_WFS_WAIT); /* Wait for 10ms */
attempt = 0; attempt = 0;
} else } else
cpu_relax(); caa_cpu_relax();
} }
if (uatomic_cmpxchg(&s->head, head, next) == head) if (uatomic_cmpxchg(&s->head, head, next) == head)
return head; return head;
else else
goto retry; /* Concurrent modification. Retry. * / goto retry; /* Concurrent modification. Retry. * /
} }
struct wfs_node * struct cds_wfs_node *
_wfs_pop_blocking(struct wfs_stack *s) _cds_wfs_pop_blocking(struct cds_wfs_stack *s)
{ {
struct wfs_node *retnode; struct cds_wfs_node *retnode;
int ret; int ret;
ret = pthread_mutex_lock(&s->lock); ret = pthread_mutex_lock(&s->lock);
assert(!ret); assert(!ret);
retnode = ___wfs_pop_blocking(s); retnode = ___cds_wfs_pop_blocking(s);
ret = pthread_mutex_unlock(&s->lock); ret = pthread_mutex_unlock(&s->lock);
assert(!ret); assert(!ret);
return retnode; return retnode;
} }
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* _URCU_WFSTACK_STATIC_H */ #endif /* _URCU_WFSTACK_STATIC_H */
 End of changes. 15 change blocks. 
23 lines changed or deleted 23 lines changed or added


 wfstack.h   wfstack.h 
skipping to change at line 34 skipping to change at line 34
*/ */
#include <pthread.h> #include <pthread.h>
#include <assert.h> #include <assert.h>
#include <urcu/compiler.h> #include <urcu/compiler.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
struct wfs_node { struct cds_wfs_node {
struct wfs_node *next; struct cds_wfs_node *next;
}; };
struct wfs_stack { struct cds_wfs_stack {
struct wfs_node *head; struct cds_wfs_node *head;
pthread_mutex_t lock; pthread_mutex_t lock;
}; };
#ifdef _LGPL_SOURCE #ifdef _LGPL_SOURCE
#include <urcu/wfstack-static.h> #include <urcu/wfstack-static.h>
#define wfs_node_init _wfs_node_init #define cds_wfs_node_init _cds_wfs_node_init
#define wfs_init _wfs_init #define cds_wfs_init _cds_wfs_init
#define wfs_push _wfs_push #define cds_wfs_push _cds_wfs_push
#define __wfs_pop_blocking ___wfs_pop_blocking #define __cds_wfs_pop_blocking ___cds_wfs_pop_blocking
#define wfs_pop_blocking _wfs_pop_blocking #define cds_wfs_pop_blocking _cds_wfs_pop_blocking
#else /* !_LGPL_SOURCE */ #else /* !_LGPL_SOURCE */
extern void wfs_node_init(struct wfs_node *node); extern void cds_wfs_node_init(struct cds_wfs_node *node);
extern void wfs_init(struct wfs_stack *s); extern void cds_wfs_init(struct cds_wfs_stack *s);
extern void wfs_push(struct wfs_stack *s, struct wfs_node *node); extern void cds_wfs_push(struct cds_wfs_stack *s, struct cds_wfs_node *node
/* __wfs_pop_blocking: caller ensures mutual exclusion between pops */ );
extern struct wfs_node *__wfs_pop_blocking(struct wfs_stack *s); /* __cds_wfs_pop_blocking: caller ensures mutual exclusion between pops */
extern struct wfs_node *wfs_pop_blocking(struct wfs_stack *s); extern struct cds_wfs_node *__cds_wfs_pop_blocking(struct cds_wfs_stack *s)
;
extern struct cds_wfs_node *cds_wfs_pop_blocking(struct cds_wfs_stack *s);
#endif /* !_LGPL_SOURCE */ #endif /* !_LGPL_SOURCE */
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* _URCU_WFSTACK_H */ #endif /* _URCU_WFSTACK_H */
 End of changes. 4 change blocks. 
15 lines changed or deleted 17 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/