rcu.h (5559B)
1#ifndef QEMU_RCU_H 2#define QEMU_RCU_H 3 4/* 5 * urcu-mb.h 6 * 7 * Userspace RCU header with explicit memory barrier. 8 * 9 * This library is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU Lesser General Public 11 * License as published by the Free Software Foundation; either 12 * version 2.1 of the License, or (at your option) any later version. 13 * 14 * This library is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * Lesser General Public License for more details. 18 * 19 * You should have received a copy of the GNU Lesser General Public 20 * License along with this library; if not, write to the Free Software 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 22 * 23 * IBM's contributions to this file may be relicensed under LGPLv2 or later. 24 */ 25 26 27#include "qemu/thread.h" 28#include "qemu/queue.h" 29#include "qemu/atomic.h" 30#include "qemu/sys_membarrier.h" 31 32#ifdef __cplusplus 33extern "C" { 34#endif 35 36/* 37 * Important ! 38 * 39 * Each thread containing read-side critical sections must be registered 40 * with rcu_register_thread() before calling rcu_read_lock(). 41 * rcu_unregister_thread() should be called before the thread exits. 42 */ 43 44#ifdef DEBUG_RCU 45#define rcu_assert(args...) assert(args) 46#else 47#define rcu_assert(args...) 48#endif 49 50/* 51 * Global quiescent period counter with low-order bits unused. 52 * Using a int rather than a char to eliminate false register dependencies 53 * causing stalls on some architectures. 54 */ 55extern unsigned long rcu_gp_ctr; 56 57extern QemuEvent rcu_gp_event; 58 59struct rcu_reader_data { 60 /* Data used by both reader and synchronize_rcu() */ 61 unsigned long ctr; 62 bool waiting; 63 64 /* Data used by reader only */ 65 unsigned depth; 66 67 /* Data used for registry, protected by rcu_registry_lock */ 68 QLIST_ENTRY(rcu_reader_data) node; 69}; 70 71extern __thread struct rcu_reader_data rcu_reader; 72 73static inline void rcu_read_lock(void) 74{ 75 struct rcu_reader_data *p_rcu_reader = &rcu_reader; 76 unsigned ctr; 77 78 if (p_rcu_reader->depth++ > 0) { 79 return; 80 } 81 82 ctr = qatomic_read(&rcu_gp_ctr); 83 qatomic_set(&p_rcu_reader->ctr, ctr); 84 85 /* Write p_rcu_reader->ctr before reading RCU-protected pointers. */ 86 smp_mb_placeholder(); 87} 88 89static inline void rcu_read_unlock(void) 90{ 91 struct rcu_reader_data *p_rcu_reader = &rcu_reader; 92 93 assert(p_rcu_reader->depth != 0); 94 if (--p_rcu_reader->depth > 0) { 95 return; 96 } 97 98 /* Ensure that the critical section is seen to precede the 99 * store to p_rcu_reader->ctr. Together with the following 100 * smp_mb_placeholder(), this ensures writes to p_rcu_reader->ctr 101 * are sequentially consistent. 102 */ 103 qatomic_store_release(&p_rcu_reader->ctr, 0); 104 105 /* Write p_rcu_reader->ctr before reading p_rcu_reader->waiting. */ 106 smp_mb_placeholder(); 107 if (unlikely(qatomic_read(&p_rcu_reader->waiting))) { 108 qatomic_set(&p_rcu_reader->waiting, false); 109 qemu_event_set(&rcu_gp_event); 110 } 111} 112 113extern void synchronize_rcu(void); 114 115/* 116 * Reader thread registration. 117 */ 118extern void rcu_register_thread(void); 119extern void rcu_unregister_thread(void); 120 121/* 122 * Support for fork(). fork() support is enabled at startup. 123 */ 124extern void rcu_enable_atfork(void); 125extern void rcu_disable_atfork(void); 126 127struct rcu_head; 128typedef void RCUCBFunc(struct rcu_head *head); 129 130struct rcu_head { 131 struct rcu_head *next; 132 RCUCBFunc *func; 133}; 134 135extern void call_rcu1(struct rcu_head *head, RCUCBFunc *func); 136extern void drain_call_rcu(void); 137 138/* The operands of the minus operator must have the same type, 139 * which must be the one that we specify in the cast. 140 */ 141#define call_rcu(head, func, field) \ 142 call_rcu1(({ \ 143 char __attribute__((unused)) \ 144 offset_must_be_zero[-offsetof(typeof(*(head)), field)], \ 145 func_type_invalid = (func) - (void (*)(typeof(head)))(func); \ 146 &(head)->field; \ 147 }), \ 148 (RCUCBFunc *)(func)) 149 150#define g_free_rcu(obj, field) \ 151 call_rcu1(({ \ 152 char __attribute__((unused)) \ 153 offset_must_be_zero[-offsetof(typeof(*(obj)), field)]; \ 154 &(obj)->field; \ 155 }), \ 156 (RCUCBFunc *)g_free); 157 158typedef void RCUReadAuto; 159static inline RCUReadAuto *rcu_read_auto_lock(void) 160{ 161 rcu_read_lock(); 162 /* Anything non-NULL causes the cleanup function to be called */ 163 return (void *)(uintptr_t)0x1; 164} 165 166static inline void rcu_read_auto_unlock(RCUReadAuto *r) 167{ 168 rcu_read_unlock(); 169} 170 171G_DEFINE_AUTOPTR_CLEANUP_FUNC(RCUReadAuto, rcu_read_auto_unlock) 172 173#define WITH_RCU_READ_LOCK_GUARD() \ 174 WITH_RCU_READ_LOCK_GUARD_(glue(_rcu_read_auto, __COUNTER__)) 175 176#define WITH_RCU_READ_LOCK_GUARD_(var) \ 177 for (g_autoptr(RCUReadAuto) var = rcu_read_auto_lock(); \ 178 (var); rcu_read_auto_unlock(var), (var) = NULL) 179 180#define RCU_READ_LOCK_GUARD() \ 181 g_autoptr(RCUReadAuto) _rcu_read_auto __attribute__((unused)) = rcu_read_auto_lock() 182 183#ifdef __cplusplus 184} 185#endif 186 187#endif /* QEMU_RCU_H */