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 31 #ifdef __cplusplus 32 extern "C" { 33 #endif 34 35 /* 36 * Important ! 37 * 38 * Each thread containing read-side critical sections must be registered 39 * with rcu_register_thread() before calling rcu_read_lock(). 40 * rcu_unregister_thread() should be called before the thread exits. 41 */ 42 43 #ifdef DEBUG_RCU 44 #define rcu_assert(args...) assert(args) 45 #else 46 #define rcu_assert(args...) 47 #endif 48 49 /* 50 * Global quiescent period counter with low-order bits unused. 51 * Using a int rather than a char to eliminate false register dependencies 52 * causing stalls on some architectures. 53 */ 54 extern unsigned long rcu_gp_ctr; 55 56 extern QemuEvent rcu_gp_event; 57 58 struct rcu_reader_data { 59 /* Data used by both reader and synchronize_rcu() */ 60 unsigned long ctr; 61 bool waiting; 62 63 /* Data used by reader only */ 64 unsigned depth; 65 66 /* Data used for registry, protected by rcu_registry_lock */ 67 QLIST_ENTRY(rcu_reader_data) node; 68 }; 69 70 extern __thread struct rcu_reader_data rcu_reader; 71 72 static inline void rcu_read_lock(void) 73 { 74 struct rcu_reader_data *p_rcu_reader = &rcu_reader; 75 unsigned ctr; 76 77 if (p_rcu_reader->depth++ > 0) { 78 return; 79 } 80 81 ctr = atomic_read(&rcu_gp_ctr); 82 atomic_xchg(&p_rcu_reader->ctr, ctr); 83 } 84 85 static inline void rcu_read_unlock(void) 86 { 87 struct rcu_reader_data *p_rcu_reader = &rcu_reader; 88 89 assert(p_rcu_reader->depth != 0); 90 if (--p_rcu_reader->depth > 0) { 91 return; 92 } 93 94 atomic_xchg(&p_rcu_reader->ctr, 0); 95 if (unlikely(atomic_read(&p_rcu_reader->waiting))) { 96 atomic_set(&p_rcu_reader->waiting, false); 97 qemu_event_set(&rcu_gp_event); 98 } 99 } 100 101 extern void synchronize_rcu(void); 102 103 /* 104 * Reader thread registration. 105 */ 106 extern void rcu_register_thread(void); 107 extern void rcu_unregister_thread(void); 108 109 /* 110 * Support for fork(). fork() support is enabled at startup. 111 */ 112 extern void rcu_enable_atfork(void); 113 extern void rcu_disable_atfork(void); 114 115 struct rcu_head; 116 typedef void RCUCBFunc(struct rcu_head *head); 117 118 struct rcu_head { 119 struct rcu_head *next; 120 RCUCBFunc *func; 121 }; 122 123 extern void call_rcu1(struct rcu_head *head, RCUCBFunc *func); 124 125 /* The operands of the minus operator must have the same type, 126 * which must be the one that we specify in the cast. 127 */ 128 #define call_rcu(head, func, field) \ 129 call_rcu1(({ \ 130 char __attribute__((unused)) \ 131 offset_must_be_zero[-offsetof(typeof(*(head)), field)], \ 132 func_type_invalid = (func) - (void (*)(typeof(head)))(func); \ 133 &(head)->field; \ 134 }), \ 135 (RCUCBFunc *)(func)) 136 137 #define g_free_rcu(obj, field) \ 138 call_rcu1(({ \ 139 char __attribute__((unused)) \ 140 offset_must_be_zero[-offsetof(typeof(*(obj)), field)]; \ 141 &(obj)->field; \ 142 }), \ 143 (RCUCBFunc *)g_free); 144 145 #ifdef __cplusplus 146 } 147 #endif 148 149 #endif /* QEMU_RCU_H */ 150