Changeset 181a746 in mainline for kernel/generic/include/synch/rcu.h
- Timestamp:
- 2012-07-10T17:50:29Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 5b6c033
- Parents:
- 22b5924
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/include/synch/rcu.h
r22b5924 r181a746 36 36 #define KERN_RCU_H_ 37 37 38 #include <adt/list.h> 39 #include <synch/semaphore.h> 40 #include <compiler/barrier.h> 41 42 38 43 /* Fwd decl. */ 39 struct rcu_head; 40 41 /** RCU callback type. */ 42 typedef void (*rcu_cb_func_t)(struct rcu_head *head); 43 44 /** */ 45 struct rcu_head { 46 struct rcu_head *next; 47 rcu_cb_func_t func; 48 }; 49 50 51 52 void rcu_read_lock(void); 53 void rcu_read_unlock(void); 54 void rcu_synchronize(void); 55 void rcu_call(struct rcu_head *head, rcu_cb_func_t func); 56 57 44 struct thread; 45 struct rcu_item; 46 47 /** Grace period number typedef. */ 48 typedef uint64_t rcu_gp_t; 49 50 /** RCU callback type. The passed rcu_item_t maybe freed. */ 51 typedef void (*rcu_func_t)(struct rcu_item *rcu_item); 52 53 typedef struct rcu_item { 54 rcu_func_t func; 55 struct rcu_item *next; 56 } rcu_item_t; 57 58 59 /** RCU related per-cpu data. */ 60 typedef struct rcu_cpu_data { 61 /** The cpu recorded a quiescent state last time during this grace period */ 62 rcu_gp_t last_seen_gp; 63 64 /** Pointer to the currently used nesting count (THREAD's or CPU's). */ 65 size_t *pnesting_cnt; 66 /** Temporary nesting count if THREAD is NULL, eg in scheduler(). */ 67 size_t tmp_nesting_cnt; 68 69 /** Callbacks to invoke once the current grace period ends, ie cur_cbs_gp. 70 * Accessed by the local reclaimer only. 71 */ 72 rcu_item_t *cur_cbs; 73 /** Callbacks to invoke once the next grace period ends, ie next_cbs_gp. 74 * Accessed by the local reclaimer only. 75 */ 76 rcu_item_t *next_cbs; 77 /** New callbacks are place at the end of this list. */ 78 rcu_item_t *arriving_cbs; 79 /** Tail of arriving_cbs list. Disable interrupts to access. */ 80 rcu_item_t **parriving_cbs_tail; 81 /** Number of callbacks currently in arriving_cbs. 82 * Disable interrupts to access. 83 */ 84 size_t arriving_cbs_cnt; 85 86 /** At the end of this grace period callbacks in cur_cbs will be invoked.*/ 87 rcu_gp_t cur_cbs_gp; 88 /** At the end of this grace period callbacks in next_cbs will be invoked. 89 * 90 * Should be the next grace period but it allows the reclaimer to 91 * notice if it missed a grace period end announcement. In that 92 * case it can execute next_cbs without waiting for another GP. 93 * 94 * Invariant: next_cbs_gp >= cur_cbs_gp 95 */ 96 rcu_gp_t next_cbs_gp; 97 98 /** This cpu has not yet passed a quiescent state and it is delaying the 99 * detector. Once it reaches a QS it must sema_up(rcu.remaining_readers). 100 */ 101 bool is_delaying_gp; 102 103 /** Positive if there are callbacks pending in arriving_cbs. */ 104 semaphore_t arrived_flag; 105 106 /** The reclaimer should expedite GPs for cbs in arriving_cbs. */ 107 bool expedite_arriving; 108 109 /** Interruptable attached reclaimer thread. */ 110 struct thread *reclaimer_thr; 111 112 /* Some statistics. */ 113 size_t stat_max_cbs; 114 size_t stat_avg_cbs; 115 size_t stat_missed_gps; 116 } rcu_cpu_data_t; 117 118 119 /** RCU related per-thread data. */ 120 typedef struct rcu_thread_data { 121 /** The number of times an RCU reader section is nested. 122 * 123 * If positive, it is definitely executing reader code. If zero, 124 * the thread might already be executing reader code thanks to 125 * cpu instruction reordering. 126 */ 127 size_t nesting_cnt; 128 129 /** True if the thread was preempted in a reader section. 130 * 131 * The thread is place into rcu.cur_preempted or rcu.next_preempted 132 * and must remove itself in rcu_read_unlock(). 133 * 134 * Access with interrupts disabled. 135 */ 136 bool was_preempted; 137 /** Preempted threads link. Access with rcu.prempt_lock.*/ 138 link_t preempt_link; 139 } rcu_thread_data_t; 140 141 142 #ifndef member_to_inst 143 #define member_to_inst(ptr_member, type, member_identif) \ 144 ((type*) (((void*)(ptr_member)) - ((void*)&(((type*)0)->member_identif)))) 58 145 #endif 59 146 147 /** Use to assign a pointer to newly initialized data to a rcu reader 148 * accessible pointer. 149 * 150 * Example: 151 * @code 152 * typedef struct exam { 153 * struct exam *next; 154 * int grade; 155 * } exam_t; 156 * 157 * exam_t *exam_list; 158 * // .. 159 * 160 * // Insert at the beginning of the list. 161 * exam_t *my_exam = malloc(sizeof(exam_t), 0); 162 * my_exam->grade = 5; 163 * my_exam->next = exam_list; 164 * rcu_assign(exam_list, my_exam); 165 * 166 * // Changes properly propagate. Every reader either sees 167 * // the old version of exam_list or the new version with 168 * // the fully initialized my_exam. 169 * rcu_synchronize(); 170 * // Now we can be sure every reader sees my_exam. 171 * 172 * @endcode 173 */ 174 #define rcu_assign(ptr, value) \ 175 do { \ 176 memory_barrier(); \ 177 (ptr) = (value); \ 178 } while (0) 179 180 /** Use to access RCU protected data in a reader section. 181 * 182 * Example: 183 * @code 184 * exam_t *exam_list; 185 * // ... 186 * 187 * rcu_read_lock(); 188 * exam_t *first_exam = rcu_access(exam_list); 189 * // We can now safely use first_exam, it won't change 190 * // under us while we're using it. 191 * 192 * // .. 193 * rcu_read_unlock(); 194 * @endcode 195 */ 196 #define rcu_access(ptr) ACCESS_ONCE(ptr) 197 198 extern void rcu_read_lock(void); 199 extern void rcu_read_unlock(void); 200 extern void rcu_synchronize(void); 201 extern void rcu_call(rcu_item_t *rcu_item, rcu_func_t func); 202 203 extern void rcu_print_stat(void); 204 205 extern void rcu_init(void); 206 extern void rcu_stop(void); 207 extern void rcu_cpu_init(void); 208 extern void rcu_kinit_init(void); 209 extern void rcu_thread_init(struct thread*); 210 extern void rcu_thread_exiting(void); 211 extern void rcu_after_thread_ran(void); 212 extern void rcu_before_thread_runs(void); 213 214 /* Debugging/testing support. Not part of public API. Do not use! */ 215 extern uint64_t rcu_completed_gps(void); 216 extern void _rcu_call(bool expedite, rcu_item_t *rcu_item, rcu_func_t func); 217 218 #endif 219 60 220 /** @} 61 221 */ 62
Note:
See TracChangeset
for help on using the changeset viewer.