| arch.h | | arch.h | |
| | | | |
| skipping to change at line 36 | | skipping to change at line 36 | |
| #include <urcu/config.h> | | #include <urcu/config.h> | |
| | | | |
| #ifdef __cplusplus | | #ifdef __cplusplus | |
| extern "C" { | | extern "C" { | |
| #endif | | #endif | |
| | | | |
| #define CAA_CACHE_LINE_SIZE 128 | | #define CAA_CACHE_LINE_SIZE 128 | |
| | | | |
| #ifdef CONFIG_RCU_HAVE_FENCE | | #ifdef CONFIG_RCU_HAVE_FENCE | |
| #define cmm_mb() asm volatile("mfence":::"memory") | | #define cmm_mb() asm volatile("mfence":::"memory") | |
|
| #define cmm_rmb() asm volatile("lfence":::"memory") | | | |
| #define cmm_wmb() asm volatile("sfence"::: "memory") | | /* | |
| | | * Define cmm_rmb/cmm_wmb to "strict" barriers that may be needed when | |
| | | * using SSE or working with I/O areas. cmm_smp_rmb/cmm_smp_wmb are | |
| | | * only compiler barriers, which is enough for general use. | |
| | | */ | |
| | | #define cmm_rmb() asm volatile("lfence":::"memory") | |
| | | #define cmm_wmb() asm volatile("sfence"::: "memory") | |
| | | #define cmm_smp_rmb() cmm_barrier() | |
| | | #define cmm_smp_wmb() cmm_barrier() | |
| #else | | #else | |
| /* | | /* | |
|
| * Some non-Intel clones support out of order store. cmm_wmb() ceases to be | | * We leave smp_rmb/smp_wmb as full barriers for processors that do not hav | |
| a | | e | |
| * nop for these. | | * fence instructions. | |
| | | * | |
| | | * An empty cmm_smp_rmb() may not be enough on old PentiumPro multiprocesso | |
| | | r | |
| | | * systems, due to an erratum. The Linux kernel says that "Even distro | |
| | | * kernels should think twice before enabling this", but for now let's | |
| | | * be conservative and leave the full barrier on 32-bit processors. Also, | |
| | | * IDT WinChip supports weak store ordering, and the kernel may enable it | |
| | | * under our feet; cmm_smp_wmb() ceases to be a nop for these processors. | |
| */ | | */ | |
| #define cmm_mb() asm volatile("lock; addl $0,0(%%esp)":::"memory") | | #define cmm_mb() asm volatile("lock; addl $0,0(%%esp)":::"memory") | |
| #define cmm_rmb() asm volatile("lock; addl $0,0(%%esp)":::"memory") | | #define cmm_rmb() asm volatile("lock; addl $0,0(%%esp)":::"memory") | |
| #define cmm_wmb() asm volatile("lock; addl $0,0(%%esp)"::: "memory") | | #define cmm_wmb() asm volatile("lock; addl $0,0(%%esp)"::: "memory") | |
| #endif | | #endif | |
| | | | |
| #define caa_cpu_relax() asm volatile("rep; nop" : : : "memory"); | | #define caa_cpu_relax() asm volatile("rep; nop" : : : "memory"); | |
| | | | |
| #define rdtscll(val) \ | | #define rdtscll(val) \ | |
| do { \ | | do { \ | |
| | | | |
End of changes. 2 change blocks. |
| 5 lines changed or deleted | | 21 lines changed or added | |
|
| compiler.h | | compiler.h | |
| | | | |
| skipping to change at line 42 | | skipping to change at line 42 | |
| * particular ordering. Compiler ordering can be ensured, for example, by | | * particular ordering. Compiler ordering can be ensured, for example, by | |
| * putting two CMM_ACCESS_ONCE() in separate C statements. | | * putting two CMM_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 CMM_ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x)) | | #define CMM_ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x)) | |
| | | | |
|
| #ifndef max | | #ifndef caa_max | |
| #define max(a,b) ((a)>(b)?(a):(b)) | | #define caa_max(a,b) ((a)>(b)?(a):(b)) | |
| #endif | | #endif | |
| | | | |
|
| #ifndef min | | #ifndef caa_min | |
| #define min(a,b) ((a)<(b)?(a):(b)) | | #define caa_min(a,b) ((a)<(b)?(a):(b)) | |
| #endif | | #endif | |
| | | | |
| #if defined(__SIZEOF_LONG__) | | #if defined(__SIZEOF_LONG__) | |
| #define CAA_BITS_PER_LONG (__SIZEOF_LONG__ * 8) | | #define CAA_BITS_PER_LONG (__SIZEOF_LONG__ * 8) | |
| #elif defined(_LP64) | | #elif defined(_LP64) | |
| #define CAA_BITS_PER_LONG 64 | | #define CAA_BITS_PER_LONG 64 | |
| #else | | #else | |
| #define CAA_BITS_PER_LONG 32 | | #define CAA_BITS_PER_LONG 32 | |
| #endif | | #endif | |
| | | | |
|
| #define caa_container_of(ptr, type, member) | | /* | |
| \ | | * caa_container_of - Get the address of an object containing a field. | |
| | | * | |
| | | * @ptr: pointer to the field. | |
| | | * @type: type of the object. | |
| | | * @member: name of the field within the object. | |
| | | */ | |
| | | #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)); \ | |
| }) | | }) | |
| | | | |
|
| | | #define CAA_BUILD_BUG_ON_ZERO(cond) (sizeof(struct { int:-!!(cond); })) | |
| | | #define CAA_BUILD_BUG_ON(cond) ((void)BUILD_BUG_ON_ZERO(cond)) | |
| | | | |
| | | /* | |
| | | * __rcu is an annotation that documents RCU pointer accesses that need | |
| | | * to be protected by a read-side critical section. Eventually, a static | |
| | | * checker will be able to use this annotation to detect incorrect RCU | |
| | | * usage. | |
| | | */ | |
| | | #define __rcu | |
| | | | |
| | | #ifdef __cplusplus | |
| | | #define URCU_FORCE_CAST(type, arg) (reinterpret_cast<type>(arg)) | |
| | | #else | |
| | | #define URCU_FORCE_CAST(type, arg) ((type) (arg)) | |
| | | #endif | |
| | | | |
| #endif /* _URCU_COMPILER_H */ | | #endif /* _URCU_COMPILER_H */ | |
| | | | |
End of changes. 5 change blocks. |
| 7 lines changed or deleted | | 30 lines changed or added | |
|
| generic.h | | generic.h | |
| | | | |
| skipping to change at line 103 | | skipping to change at line 103 | |
| #define cmm_wmc() cmm_mc() | | #define cmm_wmc() cmm_mc() | |
| #endif | | #endif | |
| #endif | | #endif | |
| | | | |
| /* Nop everywhere except on alpha. */ | | /* Nop everywhere except on alpha. */ | |
| #ifndef cmm_read_barrier_depends | | #ifndef cmm_read_barrier_depends | |
| #define cmm_read_barrier_depends() | | #define cmm_read_barrier_depends() | |
| #endif | | #endif | |
| | | | |
| #ifdef CONFIG_RCU_SMP | | #ifdef CONFIG_RCU_SMP | |
|
| | | #ifndef cmm_smp_mb | |
| #define cmm_smp_mb() cmm_mb() | | #define cmm_smp_mb() cmm_mb() | |
|
| | | #endif | |
| | | #ifndef cmm_smp_rmb | |
| #define cmm_smp_rmb() cmm_rmb() | | #define cmm_smp_rmb() cmm_rmb() | |
|
| | | #endif | |
| | | #ifndef cmm_smp_wmb | |
| #define cmm_smp_wmb() cmm_wmb() | | #define cmm_smp_wmb() cmm_wmb() | |
|
| | | #endif | |
| | | #ifndef cmm_smp_mc | |
| #define cmm_smp_mc() cmm_mc() | | #define cmm_smp_mc() cmm_mc() | |
|
| | | #endif | |
| | | #ifndef cmm_smp_rmc | |
| #define cmm_smp_rmc() cmm_rmc() | | #define cmm_smp_rmc() cmm_rmc() | |
|
| | | #endif | |
| | | #ifndef cmm_smp_wmc | |
| #define cmm_smp_wmc() cmm_wmc() | | #define cmm_smp_wmc() cmm_wmc() | |
|
| | | #endif | |
| | | #ifndef cmm_smp_read_barrier_depends | |
| #define cmm_smp_read_barrier_depends() cmm_read_barrier_depends() | | #define cmm_smp_read_barrier_depends() cmm_read_barrier_depends() | |
|
| | | #endif | |
| #else | | #else | |
|
| | | #ifndef cmm_smp_mb | |
| #define cmm_smp_mb() cmm_barrier() | | #define cmm_smp_mb() cmm_barrier() | |
|
| | | #endif | |
| | | #ifndef cmm_smp_rmb | |
| #define cmm_smp_rmb() cmm_barrier() | | #define cmm_smp_rmb() cmm_barrier() | |
|
| | | #endif | |
| | | #ifndef cmm_smp_wmb | |
| #define cmm_smp_wmb() cmm_barrier() | | #define cmm_smp_wmb() cmm_barrier() | |
|
| | | #endif | |
| | | #ifndef cmm_smp_mc | |
| #define cmm_smp_mc() cmm_barrier() | | #define cmm_smp_mc() cmm_barrier() | |
|
| | | #endif | |
| | | #ifndef cmm_smp_rmc | |
| #define cmm_smp_rmc() cmm_barrier() | | #define cmm_smp_rmc() cmm_barrier() | |
|
| | | #endif | |
| | | #ifndef cmm_smp_wmc | |
| #define cmm_smp_wmc() cmm_barrier() | | #define cmm_smp_wmc() cmm_barrier() | |
|
| | | #endif | |
| | | #ifndef cmm_smp_read_barrier_depends | |
| #define cmm_smp_read_barrier_depends() | | #define cmm_smp_read_barrier_depends() | |
| #endif | | #endif | |
|
| | | #endif | |
| | | | |
| #ifndef caa_cpu_relax | | #ifndef caa_cpu_relax | |
| #define caa_cpu_relax() cmm_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. 16 change blocks. |
| 0 lines changed or deleted | | 28 lines changed or added | |
|
| list.h | | list.h | |
|
| /* Copyright (C) 2002 Free Software Foundation, Inc. | | /* | |
| This file is part of the GNU C Library. | | * Copyright (C) 2002 Free Software Foundation, Inc. | |
| Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. | | * (originally part of the GNU C Library) | |
| | | * Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. | |
| The GNU C Library is free software; you can redistribute it and/or | | * | |
| modify it under the terms of the GNU Lesser General Public | | * Copyright (C) 2009 Pierre-Marc Fournier | |
| License as published by the Free Software Foundation; either | | * Conversion to RCU list. | |
| version 2.1 of the License, or (at your option) any later version. | | * Copyright (C) 2010 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> | |
| | | * | |
| The GNU C Library is distributed in the hope that it will be useful, | | * This library is free software; you can redistribute it and/or | |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | * modify it under the terms of the GNU Lesser General Public | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | | * License as published by the Free Software Foundation; either | |
| Lesser General Public License for more details. | | * version 2.1 of the License, or (at your option) any later version. | |
| | | * | |
| You should have received a copy of the GNU Lesser General Public | | * This library is distributed in the hope that it will be useful, | |
| License along with the GNU C Library; if not, write to the Free | | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 02111-1307 USA. */ | | * Lesser General Public License for more details. | |
| | | * | |
| | | * You should have received a copy of the GNU Lesser General Public | |
| | | * License along with this library; if not, write to the Free Software | |
| | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 | |
| | | USA | |
| | | */ | |
| | | | |
| #ifndef _CDS_LIST_H | | #ifndef _CDS_LIST_H | |
| #define _CDS_LIST_H 1 | | #define _CDS_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. */ | |
| struct cds_list_head | | struct cds_list_head | |
| | | | |
| skipping to change at line 124 | | skipping to change at line 129 | |
| 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 cds_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))) | |
| | | | |
|
| | | /* Get first entry from a list. */ | |
| | | #define cds_list_first_entry(ptr, type, member) \ | |
| | | cds_list_entry((ptr)->next, type, member) | |
| | | | |
| /* Iterate forward over the elements of the list. */ | | /* Iterate forward over the elements of the list. */ | |
| #define cds_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 cds_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. */ | |
| | | | |
End of changes. 2 change blocks. |
| 18 lines changed or deleted | | 28 lines changed or added | |
|
| rcuhlist.h | | rcuhlist.h | |
|
| /* Copyright (C) 2002 Free Software Foundation, Inc. | | /* | |
| This file is part of the GNU C Library. | | * Copyright (C) 2002 Free Software Foundation, Inc. | |
| Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. | | * (originally part of the GNU C Library) | |
| | | * Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. | |
| Copyright (C) 2009 Pierre-Marc Fournier | | * | |
| Conversion to RCU list. | | * Copyright (C) 2009 Pierre-Marc Fournier | |
| Copyright (C) 2010 Mathieu Desnoyers | | * Conversion to RCU list. | |
| | | * Copyright (C) 2010 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> | |
| The GNU C Library is free software; you can redistribute it and/or | | * | |
| modify it under the terms of the GNU Lesser General Public | | * This library is free software; you can redistribute it and/or | |
| License as published by the Free Software Foundation; either | | * modify it under the terms of the GNU Lesser General Public | |
| version 2.1 of the License, or (at your option) any later version. | | * License as published by the Free Software Foundation; either | |
| | | * version 2.1 of the License, or (at your option) any later version. | |
| The GNU C Library is distributed in the hope that it will be useful, | | * | |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | * This library is distributed in the hope that it will be useful, | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| Lesser General Public License for more details. | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| | | * Lesser General Public License for more details. | |
| You should have received a copy of the GNU Lesser General Public | | * | |
| License along with the GNU C Library; if not, write to the Free | | * You should have received a copy of the GNU Lesser General Public | |
| Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | | * License along with this library; if not, write to the Free Software | |
| 02111-1307 USA. */ | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 | |
| | | USA | |
| | | */ | |
| | | | |
| #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. | |
| */ | | */ | |
| | | | |
End of changes. 1 change blocks. |
| 22 lines changed or deleted | | 24 lines changed or added | |
|
| rculfqueue.h | | rculfqueue.h | |
| | | | |
| skipping to change at line 26 | | skipping to change at line 26 | |
| * This library is distributed in the hope that it will be useful, | | * This library is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| * Lesser General Public License for more details. | | * Lesser General Public License for more details. | |
| * | | * | |
| * 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 | |
| */ | | */ | |
| | | | |
|
| #include <urcu/ref.h> | | | |
| #include <assert.h> | | #include <assert.h> | |
|
| | | #include <urcu-call-rcu.h> | |
| | | | |
| #ifdef __cplusplus | | #ifdef __cplusplus | |
| extern "C" { | | extern "C" { | |
| #endif | | #endif | |
| | | | |
|
| /* | | | |
| * 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 | | | |
| * 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 | | | |
| * 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 | | | |
| * which point their reference count will be decremented. | | | |
| */ | | | |
| | | | |
| struct cds_lfq_queue_rcu; | | struct cds_lfq_queue_rcu; | |
| | | | |
| struct cds_lfq_node_rcu { | | struct cds_lfq_node_rcu { | |
| struct cds_lfq_node_rcu *next; | | struct cds_lfq_node_rcu *next; | |
|
| struct urcu_ref ref; | | int dummy; | |
| struct cds_lfq_queue_rcu *queue; | | | |
| struct rcu_head rcu_head; | | | |
| }; | | }; | |
| | | | |
| struct cds_lfq_queue_rcu { | | struct cds_lfq_queue_rcu { | |
| struct cds_lfq_node_rcu *head, *tail; | | struct cds_lfq_node_rcu *head, *tail; | |
|
| struct cds_lfq_node_rcu init; /* Dummy initialization node */ | | void (*queue_call_rcu)(struct rcu_head *head, | |
| void (*release)(struct urcu_ref *ref); | | void (*func)(struct rcu_head *head)); | |
| }; | | }; | |
| | | | |
| #ifdef _LGPL_SOURCE | | #ifdef _LGPL_SOURCE | |
| | | | |
| #include <urcu/static/rculfqueue.h> | | #include <urcu/static/rculfqueue.h> | |
| | | | |
| #define cds_lfq_node_init_rcu _cds_lfq_node_init_rcu | | #define cds_lfq_node_init_rcu _cds_lfq_node_init_rcu | |
| #define cds_lfq_init_rcu _cds_lfq_init_rcu | | #define cds_lfq_init_rcu _cds_lfq_init_rcu | |
|
| | | #define cds_lfq_destroy_rcu _cds_lfq_destroy_rcu | |
| #define cds_lfq_enqueue_rcu _cds_lfq_enqueue_rcu | | #define cds_lfq_enqueue_rcu _cds_lfq_enqueue_rcu | |
| #define cds_lfq_dequeue_rcu _cds_lfq_dequeue_rcu | | #define cds_lfq_dequeue_rcu _cds_lfq_dequeue_rcu | |
| | | | |
| #else /* !_LGPL_SOURCE */ | | #else /* !_LGPL_SOURCE */ | |
| | | | |
| extern void cds_lfq_node_init_rcu(struct cds_lfq_node_rcu *node); | | extern void cds_lfq_node_init_rcu(struct cds_lfq_node_rcu *node); | |
| extern void cds_lfq_init_rcu(struct cds_lfq_queue_rcu *q, | | extern void cds_lfq_init_rcu(struct cds_lfq_queue_rcu *q, | |
|
| void (*release)(struct urcu_ref *ref)); | | void queue_call_rcu(struct rcu_head *head, | |
| | | void (*func)(struct rcu_head *head)) | |
| | | ); | |
| | | /* | |
| | | * The queue should be emptied before calling destroy. | |
| | | * | |
| | | * Return 0 on success, -EPERM if queue is not empty. | |
| | | */ | |
| | | extern int cds_lfq_destroy_rcu(struct cds_lfq_queue_rcu *q); | |
| | | | |
| /* | | /* | |
| * Should be called under rcu read lock critical section. | | * Should be called under rcu read lock critical section. | |
| */ | | */ | |
| extern void cds_lfq_enqueue_rcu(struct cds_lfq_queue_rcu *q, | | extern void cds_lfq_enqueue_rcu(struct cds_lfq_queue_rcu *q, | |
| struct cds_lfq_node_rcu *node); | | struct cds_lfq_node_rcu *node); | |
| | | | |
| /* | | /* | |
| * Should be called under rcu read lock critical section. | | * Should be called under rcu read lock critical section. | |
| * | | * | |
|
| * The entry returned by dequeue must be taken care of by doing a | | * The caller must wait for a grace period to pass before freeing the retur | |
| * sequence of urcu_ref_put which release handler should do a call_rcu. | | ned | |
| * | | * node or modifying the cds_lfq_node_rcu structure. | |
| * In other words, the entry lfq node returned by dequeue must not be | | * Returns NULL if queue is empty. | |
| * modified/re-used/freed until the reference count reaches zero and a grac | | | |
| e | | | |
| * period has elapsed (after the refcount reached 0). | | | |
| */ | | */ | |
| extern | | extern | |
| struct cds_lfq_node_rcu *cds_lfq_dequeue_rcu(struct cds_lfq_queue_rcu *q); | | struct cds_lfq_node_rcu *cds_lfq_dequeue_rcu(struct cds_lfq_queue_rcu *q); | |
| | | | |
| #endif /* !_LGPL_SOURCE */ | | #endif /* !_LGPL_SOURCE */ | |
| | | | |
| #ifdef __cplusplus | | #ifdef __cplusplus | |
| } | | } | |
| #endif | | #endif | |
| | | | |
| | | | |
End of changes. 8 change blocks. |
| 30 lines changed or deleted | | 18 lines changed or added | |
|
| rculfstack.h | | rculfstack.h | |
| | | | |
| skipping to change at line 42 | | skipping to change at line 42 | |
| }; | | }; | |
| | | | |
| struct cds_lfs_stack_rcu { | | struct cds_lfs_stack_rcu { | |
| struct cds_lfs_node_rcu *head; | | struct cds_lfs_node_rcu *head; | |
| }; | | }; | |
| | | | |
| #ifdef _LGPL_SOURCE | | #ifdef _LGPL_SOURCE | |
| | | | |
| #include <urcu/static/rculfstack.h> | | #include <urcu/static/rculfstack.h> | |
| | | | |
|
| #define cds_lfs_node_init_rcu _cds_lfs_node_init_rcu | | #define cds_lfs_node_init_rcu _cds_lfs_node_init_rcu | |
| #define cds_lfs_init_rcu _cds_lfs_init_rcu | | #define cds_lfs_init_rcu _cds_lfs_init_rcu | |
| #define cds_lfs_push_rcu _cds_lfs_push_rcu | | #define cds_lfs_push_rcu _cds_lfs_push_rcu | |
| #define cds_lfs_pop_rcu _cds_lfs_pop_rcu | | #define cds_lfs_pop_rcu _cds_lfs_pop_rcu | |
| | | | |
| #else /* !_LGPL_SOURCE */ | | #else /* !_LGPL_SOURCE */ | |
| | | | |
| extern void cds_lfs_node_init_rcu(struct cds_lfs_node_rcu *node); | | extern void cds_lfs_node_init_rcu(struct cds_lfs_node_rcu *node); | |
| extern void cds_lfs_init_rcu(struct cds_lfs_stack_rcu *s); | | extern void cds_lfs_init_rcu(struct cds_lfs_stack_rcu *s); | |
|
| extern void cds_lfs_push_rcu(struct cds_lfs_stack_rcu *s, struct cds_lfs_no | | extern int cds_lfs_push_rcu(struct cds_lfs_stack_rcu *s, | |
| de_rcu *node); | | struct cds_lfs_node_rcu *node); | |
| | | | |
| /* | | /* | |
| * Should be called under rcu read lock critical section. | | * Should be called under rcu read lock critical section. | |
| * | | * | |
| * 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 cds_lfs_node_rcu structure. | | * node or modifying the cds_lfs_node_rcu structure. | |
| * Returns NULL if stack is empty. | | * Returns NULL if stack is empty. | |
| */ | | */ | |
| extern struct cds_lfs_node_rcu *cds_lfs_pop_rcu(struct cds_lfs_stack_rcu *s
); | | extern struct cds_lfs_node_rcu *cds_lfs_pop_rcu(struct cds_lfs_stack_rcu *s
); | |
| | | | |
| | | | |
End of changes. 2 change blocks. |
| 6 lines changed or deleted | | 6 lines changed or added | |
|
| rculist.h | | rculist.h | |
|
| /* Copyright (C) 2002 Free Software Foundation, Inc. | | /* | |
| This file is part of the GNU C Library. | | * Copyright (C) 2002 Free Software Foundation, Inc. | |
| Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. | | * (originally part of the GNU C Library) | |
| | | * Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. | |
| Copyright (C) 2009 Pierre-Marc Fournier | | * | |
| Conversion to RCU list. | | * Copyright (C) 2009 Pierre-Marc Fournier | |
| Copyright (C) 2010 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> | | * Conversion to RCU list. | |
| | | * Copyright (C) 2010 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> | |
| The GNU C Library is free software; you can redistribute it and/or | | * | |
| modify it under the terms of the GNU Lesser General Public | | * This library is free software; you can redistribute it and/or | |
| License as published by the Free Software Foundation; either | | * modify it under the terms of the GNU Lesser General Public | |
| version 2.1 of the License, or (at your option) any later version. | | * License as published by the Free Software Foundation; either | |
| | | * version 2.1 of the License, or (at your option) any later version. | |
| The GNU C Library is distributed in the hope that it will be useful, | | * | |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | | * This library is distributed in the hope that it will be useful, | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| Lesser General Public License for more details. | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| | | * Lesser General Public License for more details. | |
| You should have received a copy of the GNU Lesser General Public | | * | |
| License along with the GNU C Library; if not, write to the Free | | * You should have received a copy of the GNU Lesser General Public | |
| Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | | * License along with this library; if not, write to the Free Software | |
| 02111-1307 USA. */ | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 | |
| | | USA | |
| | | */ | |
| | | | |
| #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. | |
| */ | | */ | |
| | | | |
End of changes. 1 change blocks. |
| 22 lines changed or deleted | | 24 lines changed or added | |
|
| urcu-call-rcu.h | | urcu-call-rcu.h | |
| | | | |
| skipping to change at line 65 | | skipping to change at line 65 | |
| */ | | */ | |
| | | | |
| struct rcu_head { | | struct rcu_head { | |
| struct cds_wfq_node next; | | struct cds_wfq_node next; | |
| void (*func)(struct rcu_head *head); | | void (*func)(struct rcu_head *head); | |
| }; | | }; | |
| | | | |
| /* | | /* | |
| * Exported functions | | * Exported functions | |
| */ | | */ | |
|
| | | | |
| | | /* | |
| | | * get_cpu_call_rcu_data should be called with RCU read-side lock held. | |
| | | * Callers should be registered RCU read-side threads. | |
| | | */ | |
| struct call_rcu_data *get_cpu_call_rcu_data(int cpu); | | struct call_rcu_data *get_cpu_call_rcu_data(int cpu); | |
| pthread_t get_call_rcu_thread(struct call_rcu_data *crdp); | | pthread_t get_call_rcu_thread(struct call_rcu_data *crdp); | |
| struct call_rcu_data *create_call_rcu_data(unsigned long flags, | | struct call_rcu_data *create_call_rcu_data(unsigned long flags, | |
| int cpu_affinity); | | int cpu_affinity); | |
| int set_cpu_call_rcu_data(int cpu, struct call_rcu_data *crdp); | | int set_cpu_call_rcu_data(int cpu, struct call_rcu_data *crdp); | |
| struct call_rcu_data *get_default_call_rcu_data(void); | | struct call_rcu_data *get_default_call_rcu_data(void); | |
|
| | | /* | |
| | | * get_call_rcu_data should be called from registered RCU read-side | |
| | | * threads. For the QSBR flavor, the caller should be online. | |
| | | */ | |
| struct call_rcu_data *get_call_rcu_data(void); | | struct call_rcu_data *get_call_rcu_data(void); | |
| struct call_rcu_data *get_thread_call_rcu_data(void); | | struct call_rcu_data *get_thread_call_rcu_data(void); | |
| void set_thread_call_rcu_data(struct call_rcu_data *crdp); | | void set_thread_call_rcu_data(struct call_rcu_data *crdp); | |
| int create_all_cpu_call_rcu_data(unsigned long flags); | | int create_all_cpu_call_rcu_data(unsigned long flags); | |
|
| | | /* | |
| | | * call_rcu should be called from registered RCU read-side threads. | |
| | | * For the QSBR flavor, the caller should be online. | |
| | | */ | |
| void call_rcu(struct rcu_head *head, | | void call_rcu(struct rcu_head *head, | |
| void (*func)(struct rcu_head *head)); | | void (*func)(struct rcu_head *head)); | |
| void call_rcu_data_free(struct call_rcu_data *crdp); | | void call_rcu_data_free(struct call_rcu_data *crdp); | |
| void free_all_cpu_call_rcu_data(void); | | void free_all_cpu_call_rcu_data(void); | |
| void call_rcu_after_fork_child(void); | | void call_rcu_after_fork_child(void); | |
| | | | |
| #ifdef __cplusplus | | #ifdef __cplusplus | |
| } | | } | |
| #endif | | #endif | |
| | | | |
| | | | |
End of changes. 3 change blocks. |
| 0 lines changed or deleted | | 13 lines changed or added | |
|
| urcu-pointer.h | | urcu-pointer.h | |
| | | | |
| skipping to change at line 70 | | skipping to change at line 70 | |
| */ | | */ | |
| #define rcu_cmpxchg_pointer _rcu_cmpxchg_pointer | | #define rcu_cmpxchg_pointer _rcu_cmpxchg_pointer | |
| #define rcu_xchg_pointer _rcu_xchg_pointer | | #define rcu_xchg_pointer _rcu_xchg_pointer | |
| #define rcu_set_pointer _rcu_set_pointer | | #define rcu_set_pointer _rcu_set_pointer | |
| | | | |
| #else /* !_LGPL_SOURCE */ | | #else /* !_LGPL_SOURCE */ | |
| | | | |
| extern void *rcu_dereference_sym(void *p); | | extern void *rcu_dereference_sym(void *p); | |
| #define rcu_dereference(p)
\ | | #define rcu_dereference(p)
\ | |
| ({
\ | | ({
\ | |
|
| typeof(p) _________p1 = | | typeof(p) _________p1 = URCU_FORCE_CAST(typeof(p), | |
| \ | | \ | |
| rcu_dereference_sym((void *)(p)); | | rcu_dereference_sym(URCU_FORCE_CAST(void *, p))); | |
| \ | | \ | |
| (_________p1);
\ | | (_________p1);
\ | |
| }) | | }) | |
| | | | |
| extern void *rcu_cmpxchg_pointer_sym(void **p, void *old, void *_new); | | extern void *rcu_cmpxchg_pointer_sym(void **p, void *old, void *_new); | |
| #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); | |
| \ | | \ | |
| typeof(*p) _________p1 = | | typeof(*(p)) _________p1 = URCU_FORCE_CAST(typeof(*(p)), | |
| \ | | \ | |
| rcu_cmpxchg_pointer_sym((void **)(p), _________pold, | | rcu_cmpxchg_pointer_sym(URCU_FORCE_CAST(void **, p), | |
| \ | | \ | |
| _________pnew); | | _________pold, | |
| \ | | \ | |
| | | _________pnew)); | |
| | | \ | |
| (_________p1);
\ | | (_________p1);
\ | |
| }) | | }) | |
| | | | |
| extern void *rcu_xchg_pointer_sym(void **p, void *v); | | extern void *rcu_xchg_pointer_sym(void **p, void *v); | |
| #define rcu_xchg_pointer(p, v)
\ | | #define rcu_xchg_pointer(p, v)
\ | |
| ({
\ | | ({
\ | |
|
| typeof(*p) _________pv = (v); | | typeof(*(p)) _________pv = (v); | |
| \ | | \ | |
| typeof(*p) _________p1 = | | typeof(*(p)) _________p1 = URCU_FORCE_CAST(typeof(*(p)), | |
| \ | | \ | |
| rcu_xchg_pointer_sym((void **)(p), _________pv); | | rcu_xchg_pointer_sym(URCU_FORCE_CAST(void **, p), | |
| \ | | \ | |
| | | _________pv)); | |
| | | \ | |
| (_________p1);
\ | | (_________p1);
\ | |
| }) | | }) | |
| | | | |
| extern void *rcu_set_pointer_sym(void **p, void *v); | | extern void *rcu_set_pointer_sym(void **p, void *v); | |
| #define rcu_set_pointer(p, v)
\ | | #define rcu_set_pointer(p, v)
\ | |
| ({
\ | | ({
\ | |
|
| typeof(*p) _________pv = (v); | | typeof(*(p)) _________pv = (v); | |
| \ | | \ | |
| typeof(*p) _________p1 = | | typeof(*(p)) _________p1 = URCU_FORCE_CAST(typeof(*(p)), | |
| \ | | \ | |
| rcu_set_pointer_sym((void **)(p), _________pv); | | rcu_set_pointer_sym(URCU_FORCE_CAST(void **, p), | |
| \ | | \ | |
| | | _________pv)); | |
| | | \ | |
| }) | | }) | |
| | | | |
| #endif /* !_LGPL_SOURCE */ | | #endif /* !_LGPL_SOURCE */ | |
| | | | |
| /* | | /* | |
| * rcu_assign_pointer(type *ptr, type *new) | | * rcu_assign_pointer(type *ptr, type *new) | |
| * | | * | |
| * Same as rcu_set_pointer, but takes the pointer to assign to rather than
its | | * Same as rcu_set_pointer, but takes the pointer to assign to rather than
its | |
| * address as first parameter. Provided for compatibility with the Linux ke
rnel | | * address as first parameter. Provided for compatibility with the Linux ke
rnel | |
| * RCU semantic. | | * RCU semantic. | |
| | | | |
End of changes. 4 change blocks. |
| 26 lines changed or deleted | | 32 lines changed or added | |
|
| wfstack.h | | wfstack.h | |
| | | | |
| skipping to change at line 57 | | skipping to change at line 57 | |
| #define cds_wfs_node_init _cds_wfs_node_init | | #define cds_wfs_node_init _cds_wfs_node_init | |
| #define cds_wfs_init _cds_wfs_init | | #define cds_wfs_init _cds_wfs_init | |
| #define cds_wfs_push _cds_wfs_push | | #define cds_wfs_push _cds_wfs_push | |
| #define __cds_wfs_pop_blocking ___cds_wfs_pop_blocking | | #define __cds_wfs_pop_blocking ___cds_wfs_pop_blocking | |
| #define cds_wfs_pop_blocking _cds_wfs_pop_blocking | | #define cds_wfs_pop_blocking _cds_wfs_pop_blocking | |
| | | | |
| #else /* !_LGPL_SOURCE */ | | #else /* !_LGPL_SOURCE */ | |
| | | | |
| extern void cds_wfs_node_init(struct cds_wfs_node *node); | | extern void cds_wfs_node_init(struct cds_wfs_node *node); | |
| extern void cds_wfs_init(struct cds_wfs_stack *s); | | extern void cds_wfs_init(struct cds_wfs_stack *s); | |
|
| extern void cds_wfs_push(struct cds_wfs_stack *s, struct cds_wfs_node *node
); | | extern int cds_wfs_push(struct cds_wfs_stack *s, struct cds_wfs_node *node)
; | |
| /* __cds_wfs_pop_blocking: caller ensures mutual exclusion between pops */ | | /* __cds_wfs_pop_blocking: caller ensures mutual exclusion between pops */ | |
| 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)
; | |
| 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 | |
| | | | |
| | | | |
End of changes. 1 change blocks. |
| 1 lines changed or deleted | | 1 lines changed or added | |
|