27 #include <linux/export.h>
32 #include <linux/sched.h>
40 static inline void rcu_batch_init(
struct rcu_batch *
b)
52 b->
tail = &head->next;
58 static inline bool rcu_batch_empty(
struct rcu_batch *
b)
71 if (rcu_batch_empty(b))
76 if (b->
tail == &head->next)
88 if (!rcu_batch_empty(from)) {
112 #ifdef CONFIG_DEBUG_LOCK_ALLOC
120 return init_srcu_struct_fields(sp);
136 return init_srcu_struct_fields(sp);
146 static unsigned long srcu_readers_seq_idx(
struct srcu_struct *sp,
int idx)
149 unsigned long sum = 0;
163 static unsigned long srcu_readers_active_idx(
struct srcu_struct *sp,
int idx)
166 unsigned long sum = 0;
185 static bool srcu_readers_active_idx_check(
struct srcu_struct *sp,
int idx)
189 seq = srcu_readers_seq_idx(sp, idx);
222 if (srcu_readers_active_idx(sp, idx) != 0)
250 return srcu_readers_seq_idx(sp, idx) == seq;
261 static int srcu_readers_active(
struct srcu_struct *sp)
264 unsigned long sum = 0;
284 sum = srcu_readers_active(sp);
304 rcu_read_lock_sched_held()) & 0x1;
336 #define SRCU_RETRY_CHECK_DELAY 5
337 #define SYNCHRONIZE_SRCU_TRYCOUNT 2
338 #define SYNCHRONIZE_SRCU_EXP_TRYCOUNT 12
346 static bool try_check_zero(
struct srcu_struct *sp,
int idx,
int trycount)
349 if (srcu_readers_active_idx_check(sp, idx))
384 spin_unlock_irqrestore(&sp->
queue_lock, flags);
397 static void wakeme_after_rcu(
struct rcu_head *head)
405 static void srcu_advance_batches(
struct srcu_struct *sp,
int trycount);
406 static void srcu_reschedule(
struct srcu_struct *sp);
411 static void __synchronize_srcu(
struct srcu_struct *sp,
int trycount)
421 "Illegal synchronize_srcu() in same-type SRCU (or RCU) read-side critical section");
423 init_completion(&rcu.completion);
426 head->func = wakeme_after_rcu;
434 srcu_advance_batches(sp, trycount);
514 #define SRCU_CALLBACK_BATCH 10
515 #define SRCU_INTERVAL 1
521 static void srcu_collect_new(
struct srcu_struct *sp)
534 static void srcu_advance_batches(
struct srcu_struct *sp,
int trycount)
550 if (!try_check_zero(sp, idx, trycount))
578 trycount = trycount < 2 ? 2 : trycount;
579 if (!try_check_zero(sp, idx^1, trycount))
595 static void srcu_invoke_callbacks(
struct srcu_struct *sp)
614 static void srcu_reschedule(
struct srcu_struct *sp)
646 srcu_collect_new(sp);
647 srcu_advance_batches(sp, 1);
648 srcu_invoke_callbacks(sp);