Changeset a2f42e5 in mainline for uspace/lib/urcu/rcu.c
- Timestamp:
- 2012-11-23T19:57:38Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 29b8138
- Parents:
- 99022de
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/urcu/rcu.c
r99022de ra2f42e5 72 72 #include <compiler/barrier.h> 73 73 #include <libarch/barrier.h> 74 #include <adt/list.h>75 74 #include <futex.h> 76 75 #include <macros.h> 77 76 #include <async.h> 77 #include <adt/list.h> 78 78 #include <smp_memory_barrier.h> 79 79 #include <assert.h> 80 81 82 /** RCU sleeps for RCU_SLEEP_MS before polling an active RCU reader again. */ 80 83 #define RCU_SLEEP_MS 10 81 84 … … 87 90 88 91 89 typedef struct rcu_fibril_data { 92 /** Fibril local RCU data. */ 93 typedef struct fibril_rcu_data { 90 94 size_t nesting_cnt; 91 95 link_t link; 92 } rcu_fibril_data_t; 93 96 bool registered; 97 } fibril_rcu_data_t; 98 99 /** Process global RCU data. */ 94 100 typedef struct rcu_data { 95 101 fibril_mutex_t mtx; … … 101 107 102 108 103 static fibril_local rcu_fibril_data_t rcu_fibril = { 104 .nesting_cnt = 0 109 /** Fibril local RCU data. */ 110 static fibril_local fibril_rcu_data_t fibril_rcu = { 111 .nesting_cnt = 0, 112 .link = { 113 .next = NULL, 114 .prev = NULL 115 }, 116 .registered = false 105 117 }; 106 118 119 /** Process global RCU data. */ 107 120 static rcu_data_t rcu = { 108 121 .mtx = FIBRIL_MUTEX_INITIALIZER(rcu.mtx), … … 116 129 static void wait_for_readers(size_t reader_group); 117 130 static void force_mb_in_all_threads(void); 118 static bool is_preexisting_reader(const rcu_fibril_data_t *fib, size_t group);131 static bool is_preexisting_reader(const fibril_rcu_data_t *fib, size_t group); 119 132 120 133 static bool is_in_group(size_t nesting_cnt, size_t group); … … 130 143 void rcu_register_fibril(void) 131 144 { 145 assert(!fibril_rcu.registered); 146 132 147 futex_down(&rcu.list_futex); 133 list_append(& rcu_fibril.link, &rcu.fibrils_list);148 list_append(&fibril_rcu.link, &rcu.fibrils_list); 134 149 futex_up(&rcu.list_futex); 150 151 fibril_rcu.registered = true; 135 152 } 136 153 … … 142 159 void rcu_deregister_fibril(void) 143 160 { 161 assert(fibril_rcu.registered); 162 144 163 /* 145 164 * Forcefully unlock any reader sections. The fibril is exiting … … 149 168 */ 150 169 memory_barrier(); 151 rcu_fibril.nesting_cnt = 0;170 fibril_rcu.nesting_cnt = 0; 152 171 153 172 futex_down(&rcu.list_futex); 154 list_remove(& rcu_fibril.link);173 list_remove(&fibril_rcu.link); 155 174 futex_up(&rcu.list_futex); 175 176 fibril_rcu.registered = false; 156 177 } 157 178 … … 162 183 void rcu_read_lock(void) 163 184 { 164 size_t nesting_cnt = ACCESS_ONCE(rcu_fibril.nesting_cnt); 185 assert(fibril_rcu.registered); 186 187 size_t nesting_cnt = ACCESS_ONCE(fibril_rcu.nesting_cnt); 165 188 166 189 if (0 == (nesting_cnt >> RCU_NESTING_SHIFT)) { 167 ACCESS_ONCE( rcu_fibril.nesting_cnt) = ACCESS_ONCE(rcu.reader_group);190 ACCESS_ONCE(fibril_rcu.nesting_cnt) = ACCESS_ONCE(rcu.reader_group); 168 191 /* Required by MB_FORCE_L */ 169 192 compiler_barrier(); /* CC_BAR_L */ 170 193 } else { 171 ACCESS_ONCE( rcu_fibril.nesting_cnt) = nesting_cnt + RCU_NESTING_INC;194 ACCESS_ONCE(fibril_rcu.nesting_cnt) = nesting_cnt + RCU_NESTING_INC; 172 195 } 173 196 } … … 176 199 void rcu_read_unlock(void) 177 200 { 201 assert(fibril_rcu.registered); 202 178 203 /* Required by MB_FORCE_U */ 179 204 compiler_barrier(); /* CC_BAR_U */ 180 205 /* todo: ACCESS_ONCE(nesting_cnt) ? */ 181 rcu_fibril.nesting_cnt -= RCU_NESTING_INC; 206 fibril_rcu.nesting_cnt -= RCU_NESTING_INC; 207 } 208 209 /** Returns true if the current fibril is in an RCU reader section. */ 210 bool rcu_read_locked(void) 211 { 212 return 0 != (fibril_rcu.nesting_cnt >> RCU_NESTING_SHIFT); 182 213 } 183 214 … … 185 216 void rcu_synchronize(void) 186 217 { 218 assert(!rcu_read_locked()); 219 187 220 /* Contain load of rcu.cur_gp. */ 188 221 memory_barrier(); … … 201 234 * after that, gp_in_progress + 2, already started. 202 235 */ 203 if (rcu.cur_gp + 2 >= gp_in_progress) { 236 /* rcu.cur_gp >= gp_in_progress + 2, but tolerates overflows. */ 237 if (rcu.cur_gp != gp_in_progress && rcu.cur_gp + 1 != gp_in_progress) { 204 238 fibril_mutex_unlock(&rcu.mtx); 205 239 return; … … 280 314 while (!list_empty(&rcu.fibrils_list)) { 281 315 list_foreach_safe(rcu.fibrils_list, fibril_it, next_fibril) { 282 rcu_fibril_data_t *fib = member_to_inst(fibril_it,283 rcu_fibril_data_t, link);316 fibril_rcu_data_t *fib = member_to_inst(fibril_it, 317 fibril_rcu_data_t, link); 284 318 285 319 if (is_preexisting_reader(fib, reader_group)) { … … 299 333 } 300 334 301 static bool is_preexisting_reader(const rcu_fibril_data_t *fib, size_t group)335 static bool is_preexisting_reader(const fibril_rcu_data_t *fib, size_t group) 302 336 { 303 337 size_t nesting_cnt = ACCESS_ONCE(fib->nesting_cnt);
Note:
See TracChangeset
for help on using the changeset viewer.