| arch.h | | arch.h | |
| | | | |
| skipping to change at line 35 | | skipping to change at line 35 | |
| #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 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/cmm_wmb to "strict" barriers that may be needed when | | * 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 | | * using SSE or working with I/O areas. cmm_smp_rmb/cmm_smp_wmb are | |
| * only compiler barriers, which is enough for general use. | | * only compiler barriers, which is enough for general use. | |
| */ | | */ | |
|
| #define cmm_rmb() asm volatile("lfence":::"memory") | | #define cmm_rmb() __asm__ __volatile__ ("lfence":::"memory") | |
| #define cmm_wmb() asm volatile("sfence"::: "memory") | | #define cmm_wmb() __asm__ __volatile__ ("sfence"::: "memory") | |
| #define cmm_smp_rmb() cmm_barrier() | | #define cmm_smp_rmb() cmm_barrier() | |
| #define cmm_smp_wmb() cmm_barrier() | | #define cmm_smp_wmb() cmm_barrier() | |
| #else | | #else | |
| /* | | /* | |
| * We leave smp_rmb/smp_wmb as full barriers for processors that do not hav
e | | * We leave smp_rmb/smp_wmb as full barriers for processors that do not hav
e | |
| * fence instructions. | | * fence instructions. | |
| * | | * | |
| * An empty cmm_smp_rmb() may not be enough on old PentiumPro multiprocesso
r | | * 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 | | * systems, due to an erratum. The Linux kernel says that "Even distro | |
| * kernels should think twice before enabling this", but for now let's | | * kernels should think twice before enabling this", but for now let's | |
| * be conservative and leave the full barrier on 32-bit processors. Also, | | * be conservative and leave the full barrier on 32-bit processors. Also, | |
| * IDT WinChip supports weak store ordering, and the kernel may enable it | | * 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. | | * 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)":::"memor | |
| #define cmm_rmb() asm volatile("lock; addl $0,0(%%esp)":::"memory") | | y") | |
| #define cmm_wmb() asm volatile("lock; addl $0,0(%%esp)"::: "memory") | | #define cmm_rmb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)":::"memor | |
| | | y") | |
| | | #define cmm_wmb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)"::: "memo | |
| | | ry") | |
| #endif | | #endif | |
| | | | |
|
| #define caa_cpu_relax() asm volatile("rep; nop" : : : "memory"); | | #define caa_cpu_relax() __asm__ __volatile__ ("rep; nop" : : : "memo
ry"); | |
| | | | |
| #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 caa_get_cycles(void) | | static inline cycles_t caa_get_cycles(void) | |
| { | | { | |
| cycles_t ret = 0; | | cycles_t ret = 0; | |
| | | | |
| | | | |
End of changes. 5 change blocks. |
| 8 lines changed or deleted | | 11 lines changed or added | |
|
| compiler.h | | compiler.h | |
| | | | |
| skipping to change at line 27 | | skipping to change at line 27 | |
| * | | * | |
| * The above copyright notice and this permission notice shall be included
in | | * The above copyright notice and this permission notice shall be included
in | |
| * all copies or substantial portions of the Software. | | * all copies or substantial portions of the Software. | |
| */ | | */ | |
| | | | |
| #include <stddef.h> /* for offsetof */ | | #include <stddef.h> /* for offsetof */ | |
| | | | |
| #define caa_likely(x) __builtin_expect(!!(x), 1) | | #define caa_likely(x) __builtin_expect(!!(x), 1) | |
| #define caa_unlikely(x) __builtin_expect(!!(x), 0) | | #define caa_unlikely(x) __builtin_expect(!!(x), 0) | |
| | | | |
|
| #define cmm_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 CMM_ACCESS_ONCE(), but only when the compiler is
aware of | | * successive instances of CMM_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 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 caa_max | | #ifndef caa_max | |
| #define caa_max(a,b) ((a)>(b)?(a):(b)) | | #define caa_max(a,b) ((a)>(b)?(a):(b)) | |
| #endif | | #endif | |
| | | | |
| #ifndef caa_min | | #ifndef caa_min | |
| #define caa_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__) | |
| | | | |
| skipping to change at line 68 | | skipping to change at line 68 | |
| | | | |
| /* | | /* | |
| * caa_container_of - Get the address of an object containing a field. | | * caa_container_of - Get the address of an object containing a field. | |
| * | | * | |
| * @ptr: pointer to the field. | | * @ptr: pointer to the field. | |
| * @type: type of the object. | | * @type: type of the object. | |
| * @member: name of the field within the object. | | * @member: name of the field within the object. | |
| */ | | */ | |
| #define caa_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)); \ | |
| }) | | }) | |
| | | | |
| #define CAA_BUILD_BUG_ON_ZERO(cond) (sizeof(struct { int:-!!(cond); })) | | #define CAA_BUILD_BUG_ON_ZERO(cond) (sizeof(struct { int:-!!(cond); })) | |
|
| #define CAA_BUILD_BUG_ON(cond) ((void)BUILD_BUG_ON_ZERO(cond)) | | #define CAA_BUILD_BUG_ON(cond) ((void)CAA_BUILD_BUG_ON_ZERO(cond)) | |
| | | | |
| /* | | /* | |
| * __rcu is an annotation that documents RCU pointer accesses that need | | * __rcu is an annotation that documents RCU pointer accesses that need | |
| * to be protected by a read-side critical section. Eventually, a static | | * to be protected by a read-side critical section. Eventually, a static | |
| * checker will be able to use this annotation to detect incorrect RCU | | * checker will be able to use this annotation to detect incorrect RCU | |
| * usage. | | * usage. | |
| */ | | */ | |
| #define __rcu | | #define __rcu | |
| | | | |
| #ifdef __cplusplus | | #ifdef __cplusplus | |
| | | | |
End of changes. 4 change blocks. |
| 4 lines changed or deleted | | 4 lines changed or added | |
|
| hlist.h | | hlist.h | |
| | | | |
| skipping to change at line 65 | | skipping to change at line 65 | |
| static inline void cds_hlist_del (struct cds_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 cds_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 = cds_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 = cds_hlist_entry(pos, typeof(*entry), member)) | | entry = cds_hlist_entry(pos, __typeof__(*entry), member
)) | |
| | | | |
| #define cds_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 = cds_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 = cds_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. 4 change blocks. |
| 4 lines changed or deleted | | 4 lines changed or added | |
|
| list.h | | list.h | |
| | | | |
| skipping to change at line 149 | | skipping to change at line 149 | |
| 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 cds_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 cds_list_for_each_entry(pos, head, member)
\ | | #define cds_list_for_each_entry(pos, head, member)
\ | |
|
| for (pos = cds_list_entry((head)->next, typeof(*pos), member); \ | | for (pos = cds_list_entry((head)->next, __typeof__(*pos), member); \ | |
| &pos->member != (head); \ | | &pos->member != (head); \ | |
|
| pos = cds_list_entry(pos->member.next, typeof(*pos), member)) | | pos = cds_list_entry(pos->member.next, __typeof__(*pos), member
)) | |
| | | | |
| #define cds_list_for_each_entry_reverse(pos, head, member)
\ | | #define cds_list_for_each_entry_reverse(pos, head, member)
\ | |
|
| for (pos = cds_list_entry((head)->prev, typeof(*pos), member); \ | | for (pos = cds_list_entry((head)->prev, __typeof__(*pos), member); \ | |
| &pos->member != (head); \ | | &pos->member != (head); \ | |
|
| pos = cds_list_entry(pos->member.prev, typeof(*pos), member)) | | pos = cds_list_entry(pos->member.prev, __typeof__(*pos), member
)) | |
| | | | |
| #define cds_list_for_each_entry_safe(pos, p, head, member)
\ | | #define cds_list_for_each_entry_safe(pos, p, head, member)
\ | |
|
| for (pos = cds_list_entry((head)->next, typeof(*pos), member), \ | | for (pos = cds_list_entry((head)->next, __typeof__(*pos), member), \ | |
| p = cds_list_entry(pos->member.next,typeof(*pos), membe | | p = cds_list_entry(pos->member.next, __typeof__(*pos), | |
| r); \ | | member); \ | |
| &pos->member != (head); \ | | &pos->member != (head); \ | |
|
| pos = p, p = cds_list_entry(pos->member.next, typeof(*pos), mem
ber)) | | pos = p, p = cds_list_entry(pos->member.next, __typeof__(*pos),
member)) | |
| | | | |
| static inline int cds_list_empty(struct cds_list_head *head) | | static inline int cds_list_empty(struct cds_list_head *head) | |
| { | | { | |
| return head == head->next; | | return head == head->next; | |
| } | | } | |
| | | | |
| static inline void cds_list_replace_init(struct cds_list_head *old, | | static inline void cds_list_replace_init(struct cds_list_head *old, | |
| struct cds_list_head *_new) | | struct cds_list_head *_new) | |
| { | | { | |
| struct cds_list_head *head = old->next; | | struct cds_list_head *head = old->next; | |
| | | | |
End of changes. 6 change blocks. |
| 8 lines changed or deleted | | 8 lines changed or added | |
|
| rcuhlist.h | | rcuhlist.h | |
| | | | |
| skipping to change at line 59 | | skipping to change at line 59 | |
| 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 cds_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 = cds_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 = cds_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. 2 change blocks. |
| 2 lines changed or deleted | | 2 lines changed or added | |
|
| rculfhash.h | | rculfhash.h | |
| | | | |
| skipping to change at line 178 | | skipping to change at line 178 | |
| /* | | /* | |
| * cds_lfht_destroy - destroy a hash table. | | * cds_lfht_destroy - destroy a hash table. | |
| * @ht: the hash table to destroy. | | * @ht: the hash table to destroy. | |
| * @attr: (output) resize worker thread attributes, as received by cds_lfht
_new. | | * @attr: (output) resize worker thread attributes, as received by cds_lfht
_new. | |
| * The caller will typically want to free this pointer if dynamicall
y | | * The caller will typically want to free this pointer if dynamicall
y | |
| * allocated. The attr point can be NULL if the caller does not | | * allocated. The attr point can be NULL if the caller does not | |
| * need to be informed of the value passed to cds_lfht_new(). | | * need to be informed of the value passed to cds_lfht_new(). | |
| * | | * | |
| * Return 0 on success, negative error value on error. | | * Return 0 on success, negative error value on error. | |
| * Threads calling this API need to be registered RCU read-side threads. | | * Threads calling this API need to be registered RCU read-side threads. | |
|
| | | * cds_lfht_destroy should *not* be called from a RCU read-side critical | |
| | | * section. | |
| */ | | */ | |
| int cds_lfht_destroy(struct cds_lfht *ht, pthread_attr_t **attr); | | int cds_lfht_destroy(struct cds_lfht *ht, pthread_attr_t **attr); | |
| | | | |
| /* | | /* | |
| * cds_lfht_count_nodes - count the number of nodes in the hash table. | | * cds_lfht_count_nodes - count the number of nodes in the hash table. | |
| * @ht: the hash table. | | * @ht: the hash table. | |
| * @split_count_before: sample the node count split-counter before traversa
l. | | * @split_count_before: sample the node count split-counter before traversa
l. | |
| * @count: traverse the hash table, count the number of nodes observed. | | * @count: traverse the hash table, count the number of nodes observed. | |
| * @split_count_after: sample the node count split-counter after traversal. | | * @split_count_after: sample the node count split-counter after traversal. | |
| * | | * | |
| | | | |
| skipping to change at line 453 | | skipping to change at line 455 | |
| #define cds_lfht_for_each_duplicate(ht, hash, match, key, iter, node) \ | | #define cds_lfht_for_each_duplicate(ht, hash, match, key, iter, node) \ | |
| for (cds_lfht_lookup(ht, hash, match, key, iter), \ | | for (cds_lfht_lookup(ht, hash, match, key, iter), \ | |
| node = cds_lfht_iter_get_node(iter); \ | | node = cds_lfht_iter_get_node(iter); \ | |
| node != NULL; \ | | node != NULL; \ | |
| cds_lfht_next_duplicate(ht, match, key, iter), \ | | cds_lfht_next_duplicate(ht, match, key, iter), \ | |
| node = cds_lfht_iter_get_node(iter)) | | node = cds_lfht_iter_get_node(iter)) | |
| | | | |
| #define cds_lfht_for_each_entry(ht, iter, pos, member) \ | | #define cds_lfht_for_each_entry(ht, iter, pos, member) \ | |
| for (cds_lfht_first(ht, iter), \ | | for (cds_lfht_first(ht, iter), \ | |
| pos = caa_container_of(cds_lfht_iter_get_node(iter),
\ | | pos = caa_container_of(cds_lfht_iter_get_node(iter),
\ | |
|
| typeof(*(pos)), member); \ | | __typeof__(*(pos)), member); \ | |
| &(pos)->member != NULL; \ | | &(pos)->member != NULL; \ | |
| cds_lfht_next(ht, iter), \ | | cds_lfht_next(ht, iter), \ | |
| pos = caa_container_of(cds_lfht_iter_get_node(iter),
\ | | pos = caa_container_of(cds_lfht_iter_get_node(iter),
\ | |
|
| typeof(*(pos)), member)) | | __typeof__(*(pos)), member)) | |
| | | | |
| #define cds_lfht_for_each_entry_duplicate(ht, hash, match, key,
\ | | #define cds_lfht_for_each_entry_duplicate(ht, hash, match, key,
\ | |
| iter, pos, member) \ | | iter, pos, member) \ | |
| for (cds_lfht_lookup(ht, hash, match, key, iter), \ | | for (cds_lfht_lookup(ht, hash, match, key, iter), \ | |
| pos = caa_container_of(cds_lfht_iter_get_node(iter),
\ | | pos = caa_container_of(cds_lfht_iter_get_node(iter),
\ | |
|
| typeof(*(pos)), member); \ | | __typeof__(*(pos)), member); \ | |
| &(pos)->member != NULL; \ | | &(pos)->member != NULL; \ | |
| cds_lfht_next_duplicate(ht, match, key, iter), \ | | cds_lfht_next_duplicate(ht, match, key, iter), \ | |
| pos = caa_container_of(cds_lfht_iter_get_node(iter),
\ | | pos = caa_container_of(cds_lfht_iter_get_node(iter),
\ | |
|
| typeof(*(pos)), member)) | | __typeof__(*(pos)), member)) | |
| | | | |
| #ifdef __cplusplus | | #ifdef __cplusplus | |
| } | | } | |
| #endif | | #endif | |
| | | | |
| #endif /* _URCU_RCULFHASH_H */ | | #endif /* _URCU_RCULFHASH_H */ | |
| | | | |
End of changes. 5 change blocks. |
| 4 lines changed or deleted | | 6 lines changed or added | |
|
| rculist.h | | rculist.h | |
| | | | |
| skipping to change at line 73 | | skipping to change at line 73 | |
| */ | | */ | |
| | | | |
| /* Iterate forward over the elements of the list. */ | | /* Iterate forward over the elements of the list. */ | |
| #define cds_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 cds_list_for_each_entry_rcu(pos, head, member)
\ | | #define cds_list_for_each_entry_rcu(pos, head, member)
\ | |
|
| for (pos = cds_list_entry(rcu_dereference((head)->next), typeof(*pos
), member); \ | | for (pos = cds_list_entry(rcu_dereference((head)->next), __typeof__(
*pos), member); \ | |
| &pos->member != (head); \ | | &pos->member != (head); \ | |
|
| pos = cds_list_entry(rcu_dereference(pos->member.next), typeof(
*pos), member)) | | pos = cds_list_entry(rcu_dereference(pos->member.next), __typeo
f__(*pos), member)) | |
| | | | |
| #endif /* _URCU_RCULIST_H */ | | #endif /* _URCU_RCULIST_H */ | |
| | | | |
End of changes. 2 change blocks. |
| 2 lines changed or deleted | | 2 lines changed or added | |
|
| tls-compat.h | | tls-compat.h | |
| | | | |
| skipping to change at line 37 | | skipping to change at line 37 | |
| #include <urcu/config.h> | | #include <urcu/config.h> | |
| #include <urcu/compiler.h> | | #include <urcu/compiler.h> | |
| #include <urcu/arch.h> | | #include <urcu/arch.h> | |
| | | | |
| #ifdef __cplusplus | | #ifdef __cplusplus | |
| extern "C" { | | extern "C" { | |
| #endif | | #endif | |
| | | | |
| #ifdef CONFIG_RCU_TLS /* Based on ax_tls.m4 */ | | #ifdef CONFIG_RCU_TLS /* Based on ax_tls.m4 */ | |
| | | | |
|
| | | /* | |
| | | * Hint: How to define/declare TLS variables of compound types | |
| | | * such as array or function pointers? | |
| | | * | |
| | | * Answer: Use typedef to assign a type_name to the compound type. | |
| | | * Example: Define a TLS variable which is an int array with len=4: | |
| | | * | |
| | | * typedef int my_int_array_type[4]; | |
| | | * DEFINE_URCU_TLS(my_int_array_type, var_name); | |
| | | * | |
| | | * Another exmaple: | |
| | | * typedef void (*call_rcu_flavor)(struct rcu_head *, XXXX); | |
| | | * DECLARE_URCU_TLS(call_rcu_flavor, p_call_rcu); | |
| | | */ | |
| | | | |
| # define DECLARE_URCU_TLS(type, name) \ | | # define DECLARE_URCU_TLS(type, name) \ | |
| CONFIG_RCU_TLS type name | | CONFIG_RCU_TLS type name | |
| | | | |
| # define DEFINE_URCU_TLS(type, name) \ | | # define DEFINE_URCU_TLS(type, name) \ | |
| CONFIG_RCU_TLS type name | | CONFIG_RCU_TLS type name | |
| | | | |
| # define URCU_TLS(name) (name) | | # define URCU_TLS(name) (name) | |
| | | | |
| #else /* #ifndef CONFIG_RCU_TLS */ | | #else /* #ifndef CONFIG_RCU_TLS */ | |
| | | | |
| | | | |
End of changes. 1 change blocks. |
| 0 lines changed or deleted | | 15 lines changed or added | |
|
| urcu-bp.h | | urcu-bp.h | |
| | | | |
| skipping to change at line 96 | | skipping to change at line 96 | |
| * library wrappers to be used by non-LGPL compatible source code. | | * library wrappers to be used by non-LGPL compatible source code. | |
| * See LGPL-only urcu/static/urcu-pointer.h for documentation. | | * See LGPL-only urcu/static/urcu-pointer.h for documentation. | |
| */ | | */ | |
| | | | |
| extern void rcu_read_lock(void); | | extern void rcu_read_lock(void); | |
| extern void rcu_read_unlock(void); | | extern void rcu_read_unlock(void); | |
| | | | |
| extern void *rcu_dereference_sym_bp(void *p); | | extern void *rcu_dereference_sym_bp(void *p); | |
| #define rcu_dereference_bp(p)
\ | | #define rcu_dereference_bp(p)
\ | |
| ({
\ | | ({
\ | |
|
| typeof(p) _________p1 = URCU_FORCE_CAST(typeof(p),
\ | | __typeof__(p) _________p1 = URCU_FORCE_CAST(__typeof__(p),
\ | |
| rcu_dereference_sym_bp(URCU_FORCE_CAST(void *, p)));
\ | | rcu_dereference_sym_bp(URCU_FORCE_CAST(void *, p)));
\ | |
| (_________p1);
\ | | (_________p1);
\ | |
| }) | | }) | |
| | | | |
| extern void *rcu_cmpxchg_pointer_sym_bp(void **p, void *old, void *_new); | | extern void *rcu_cmpxchg_pointer_sym_bp(void **p, void *old, void *_new); | |
| #define rcu_cmpxchg_pointer_bp(p, old, _new)
\ | | #define rcu_cmpxchg_pointer_bp(p, old, _new)
\ | |
| ({
\ | | ({
\ | |
|
| typeof(*(p)) _________pold = (old); | | __typeof__(*(p)) _________pold = (old); | |
| \ | | \ | |
| typeof(*(p)) _________pnew = (_new); | | __typeof__(*(p)) _________pnew = (_new); | |
| \ | | \ | |
| typeof(*(p)) _________p1 = URCU_FORCE_CAST(typeof(*(p)), | | __typeof__(*(p)) _________p1 = URCU_FORCE_CAST(__typeof__(*( | |
| \ | | p)), \ | |
| rcu_cmpxchg_pointer_sym_bp(URCU_FORCE_CAST(void **, | | rcu_cmpxchg_pointer_sym_bp(URCU_FORCE_CAST(void **, | |
| p),\ | | p), \ | |
| _________pold,
\ | | _________pold,
\ | |
| _________pnew));
\ | | _________pnew));
\ | |
| (_________p1);
\ | | (_________p1);
\ | |
| }) | | }) | |
| | | | |
| extern void *rcu_xchg_pointer_sym_bp(void **p, void *v); | | extern void *rcu_xchg_pointer_sym_bp(void **p, void *v); | |
| #define rcu_xchg_pointer_bp(p, v)
\ | | #define rcu_xchg_pointer_bp(p, v)
\ | |
| ({
\ | | ({
\ | |
|
| typeof(*(p)) _________pv = (v); | | __typeof__(*(p)) _________pv = (v); | |
| \ | | \ | |
| typeof(*(p)) _________p1 = URCU_FORCE_CAST(typeof(*(p)), | | __typeof__(*(p)) _________p1 = URCU_FORCE_CAST(__typeof__(*( | |
| \ | | p)),\ | |
| rcu_xchg_pointer_sym_bp(URCU_FORCE_CAST(void **, p),
\ | | rcu_xchg_pointer_sym_bp(URCU_FORCE_CAST(void **, p),
\ | |
| _________pv));
\ | | _________pv));
\ | |
| (_________p1);
\ | | (_________p1);
\ | |
| }) | | }) | |
| | | | |
| extern void *rcu_set_pointer_sym_bp(void **p, void *v); | | extern void *rcu_set_pointer_sym_bp(void **p, void *v); | |
| #define rcu_set_pointer_bp(p, v)
\ | | #define rcu_set_pointer_bp(p, v)
\ | |
| ({
\ | | ({
\ | |
|
| typeof(*(p)) _________pv = (v); | | __typeof__(*(p)) _________pv = (v); | |
| \ | | \ | |
| typeof(*(p)) _________p1 = URCU_FORCE_CAST(typeof(*(p)), | | __typeof__(*(p)) _________p1 = URCU_FORCE_CAST(__typeof__(*( | |
| \ | | p)), \ | |
| rcu_set_pointer_sym_bp(URCU_FORCE_CAST(void **, p),
\ | | rcu_set_pointer_sym_bp(URCU_FORCE_CAST(void **, p),
\ | |
| _________pv));
\ | | _________pv));
\ | |
| (_________p1);
\ | | (_________p1);
\ | |
| }) | | }) | |
| | | | |
| #endif /* !_LGPL_SOURCE */ | | #endif /* !_LGPL_SOURCE */ | |
| | | | |
| extern void synchronize_rcu(void); | | extern void synchronize_rcu(void); | |
| | | | |
| /* | | /* | |
| | | | |
End of changes. 4 change blocks. |
| 17 lines changed or deleted | | 17 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 = URCU_FORCE_CAST(typeof(p),
\ | | __typeof__(p) _________p1 = URCU_FORCE_CAST(__typeof__(p
), \ | |
| rcu_dereference_sym(URCU_FORCE_CAST(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 = URCU_FORCE_CAST(typeof(*(p)), | | __typeof__(*(p)) _________p1 = URCU_FORCE_CAST(__typeof__(*( | |
| \ | | p)), \ | |
| rcu_cmpxchg_pointer_sym(URCU_FORCE_CAST(void **, p), | | rcu_cmpxchg_pointer_sym(URCU_FORCE_CAST(void **, p), | |
| \ | | \ | |
| _________pold,
\ | | _________pold,
\ | |
| _________pnew));
\ | | _________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 = URCU_FORCE_CAST(typeof(*(p)), | | __typeof__(*(p)) _________p1 = URCU_FORCE_CAST(__typeof__(*( | |
| \ | | p)), \ | |
| rcu_xchg_pointer_sym(URCU_FORCE_CAST(void **, p),
\ | | rcu_xchg_pointer_sym(URCU_FORCE_CAST(void **, p),
\ | |
| _________pv));
\ | | _________pv));
\ | |
| (_________p1);
\ | | (_________p1);
\ | |
| }) | | }) | |
| | | | |
| /* | | /* | |
| * Note: rcu_set_pointer_sym returns @v because we don't want to break | | * Note: rcu_set_pointer_sym returns @v because we don't want to break | |
| * the ABI. At the API level, rcu_set_pointer() now returns void. Use of | | * the ABI. At the API level, rcu_set_pointer() now returns void. Use of | |
| * the return value is therefore deprecated, and will cause a build | | * the return value is therefore deprecated, and will cause a build | |
| * error. | | * error. | |
| */ | | */ | |
| 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)
\ | |
| do {
\ | | do {
\ | |
|
| typeof(*(p)) _________pv = (v);
\ | | __typeof__(*(p)) _________pv = (v);
\ | |
| (void) rcu_set_pointer_sym(URCU_FORCE_CAST(void **, p),
\ | | (void) rcu_set_pointer_sym(URCU_FORCE_CAST(void **, p),
\ | |
| _________pv);
\ | | _________pv);
\ | |
| } while (0) | | } while (0) | |
| | | | |
| #endif /* !_LGPL_SOURCE */ | | #endif /* !_LGPL_SOURCE */ | |
| | | | |
| /* | | /* | |
| * void rcu_assign_pointer(type *ptr, type *new) | | * void 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 | |
| | | | |
End of changes. 4 change blocks. |
| 14 lines changed or deleted | | 14 lines changed or added | |
|