123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501 |
- #include <linux/cache.h>
- #include <linux/spinlock.h>
- #include <linux/rtmutex.h>
- #include <linux/threads.h>
- #include <linux/cpumask.h>
- #include <linux/seqlock.h>
- #include <linux/swait.h>
- #include <linux/stop_machine.h>
- #include <linux/rcu_node_tree.h>
- #include "rcu_segcblist.h"
- struct rcu_dynticks {
- long dynticks_nesting;
- long dynticks_nmi_nesting;
- atomic_t dynticks;
- bool rcu_need_heavy_qs;
- unsigned long rcu_qs_ctr;
- bool rcu_urgent_qs;
- #ifdef CONFIG_RCU_FAST_NO_HZ
- bool all_lazy;
- unsigned long nonlazy_posted;
-
- unsigned long nonlazy_posted_snap;
-
- unsigned long last_accelerate;
-
- unsigned long last_advance_all;
-
- int tick_nohz_enabled_snap;
- #endif
- };
- struct rcu_exp_work {
- smp_call_func_t rew_func;
- struct rcu_state *rew_rsp;
- unsigned long rew_s;
- struct work_struct rew_work;
- };
- #define RCU_KTHREAD_STOPPED 0
- #define RCU_KTHREAD_RUNNING 1
- #define RCU_KTHREAD_WAITING 2
- #define RCU_KTHREAD_OFFCPU 3
- #define RCU_KTHREAD_YIELDING 4
- #define RCU_KTHREAD_MAX 4
- struct rcu_node {
- raw_spinlock_t __private lock;
-
-
- unsigned long gp_seq;
- unsigned long gp_seq_needed;
- unsigned long completedqs;
- unsigned long qsmask;
-
-
-
-
-
- unsigned long rcu_gp_init_mask;
- unsigned long qsmaskinit;
-
-
-
- unsigned long qsmaskinitnext;
-
- unsigned long expmask;
-
-
- unsigned long expmaskinit;
-
-
-
- unsigned long expmaskinitnext;
-
-
-
- unsigned long ffmask;
- unsigned long grpmask;
-
- int grplo;
- int grphi;
- u8 grpnum;
- u8 level;
- bool wait_blkd_tasks;
-
-
-
- struct rcu_node *parent;
- struct list_head blkd_tasks;
-
-
-
- struct list_head *gp_tasks;
-
-
-
- struct list_head *exp_tasks;
-
-
-
-
-
- struct list_head *boost_tasks;
-
-
-
-
-
-
-
- struct rt_mutex boost_mtx;
-
-
- unsigned long boost_time;
-
- struct task_struct *boost_kthread_task;
-
-
- unsigned int boost_kthread_status;
-
- #ifdef CONFIG_RCU_NOCB_CPU
- struct swait_queue_head nocb_gp_wq[2];
-
- #endif
- raw_spinlock_t fqslock ____cacheline_internodealigned_in_smp;
- spinlock_t exp_lock ____cacheline_internodealigned_in_smp;
- unsigned long exp_seq_rq;
- wait_queue_head_t exp_wq[4];
- struct rcu_exp_work rew;
- bool exp_need_flush;
- } ____cacheline_internodealigned_in_smp;
- #define leaf_node_cpu_bit(rnp, cpu) (1UL << ((cpu) - (rnp)->grplo))
- union rcu_noqs {
- struct {
- u8 norm;
- u8 exp;
- } b;
- u16 s;
- };
- struct rcu_data {
-
- unsigned long gp_seq;
- unsigned long gp_seq_needed;
- unsigned long rcu_qs_ctr_snap;
-
- union rcu_noqs cpu_no_qs;
- bool core_needs_qs;
- bool beenonline;
- bool gpwrap;
- struct rcu_node *mynode;
- unsigned long grpmask;
- unsigned long ticks_this_gp;
-
-
-
-
- struct rcu_segcblist cblist;
-
-
- long qlen_last_fqs_check;
-
- unsigned long n_force_qs_snap;
-
- long blimit;
-
- struct rcu_dynticks *dynticks;
- int dynticks_snap;
-
- unsigned long dynticks_fqs;
- unsigned long cond_resched_completed;
-
-
-
- struct rcu_head barrier_head;
- #ifdef CONFIG_RCU_FAST_NO_HZ
- struct rcu_head oom_head;
- #endif
- int exp_dynticks_snap;
-
- #ifdef CONFIG_RCU_NOCB_CPU
- struct rcu_head *nocb_head;
- struct rcu_head **nocb_tail;
- atomic_long_t nocb_q_count;
- atomic_long_t nocb_q_count_lazy;
- struct rcu_head *nocb_follower_head;
- struct rcu_head **nocb_follower_tail;
- struct swait_queue_head nocb_wq;
- struct task_struct *nocb_kthread;
- raw_spinlock_t nocb_lock;
- int nocb_defer_wakeup;
- struct timer_list nocb_timer;
-
- struct rcu_head *nocb_gp_head ____cacheline_internodealigned_in_smp;
-
- struct rcu_head **nocb_gp_tail;
- bool nocb_leader_sleep;
- struct rcu_data *nocb_next_follower;
-
-
- struct rcu_data *nocb_leader ____cacheline_internodealigned_in_smp;
-
- #endif
-
- unsigned int softirq_snap;
-
- struct irq_work rcu_iw;
- bool rcu_iw_pending;
- unsigned long rcu_iw_gp_seq;
- unsigned long rcu_ofl_gp_seq;
- short rcu_ofl_gp_flags;
- unsigned long rcu_onl_gp_seq;
- short rcu_onl_gp_flags;
- int cpu;
- struct rcu_state *rsp;
- };
- #define RCU_NOCB_WAKE_NOT 0
- #define RCU_NOCB_WAKE 1
- #define RCU_NOCB_WAKE_FORCE 2
- #define RCU_JIFFIES_TILL_FORCE_QS (1 + (HZ > 250) + (HZ > 500))
-
-
- #define RCU_JIFFIES_FQS_DIV 256
-
-
- #define RCU_STALL_RAT_DELAY 2
-
-
- #define rcu_wait(cond) \
- do { \
- for (;;) { \
- set_current_state(TASK_INTERRUPTIBLE); \
- if (cond) \
- break; \
- schedule(); \
- } \
- __set_current_state(TASK_RUNNING); \
- } while (0)
- struct rcu_state {
- struct rcu_node node[NUM_RCU_NODES];
- struct rcu_node *level[RCU_NUM_LVLS + 1];
-
-
- struct rcu_data __percpu *rda;
- call_rcu_func_t call;
- int ncpus;
-
- u8 boost ____cacheline_internodealigned_in_smp;
-
- unsigned long gp_seq;
- struct task_struct *gp_kthread;
- struct swait_queue_head gp_wq;
- short gp_flags;
- short gp_state;
-
- struct mutex barrier_mutex;
- atomic_t barrier_cpu_count;
- struct completion barrier_completion;
- unsigned long barrier_sequence;
-
-
- struct mutex exp_mutex;
- struct mutex exp_wake_mutex;
- unsigned long expedited_sequence;
- atomic_t expedited_need_qs;
- struct swait_queue_head expedited_wq;
- int ncpus_snap;
- unsigned long jiffies_force_qs;
-
- unsigned long jiffies_kick_kthreads;
-
- unsigned long n_force_qs;
-
- unsigned long gp_start;
-
- unsigned long gp_activity;
-
- unsigned long gp_req_activity;
-
- unsigned long jiffies_stall;
-
- unsigned long jiffies_resched;
-
- unsigned long n_force_qs_gpstart;
-
- unsigned long gp_max;
-
- const char *name;
- char abbr;
- struct list_head flavors;
- spinlock_t ofl_lock ____cacheline_internodealigned_in_smp;
-
-
- };
- #define RCU_GP_FLAG_INIT 0x1
- #define RCU_GP_FLAG_FQS 0x2
- #define RCU_GP_IDLE 0
- #define RCU_GP_WAIT_GPS 1
- #define RCU_GP_DONE_GPS 2
- #define RCU_GP_ONOFF 3
- #define RCU_GP_INIT 4
- #define RCU_GP_WAIT_FQS 5
- #define RCU_GP_DOING_FQS 6
- #define RCU_GP_CLEANUP 7
- #define RCU_GP_CLEANED 8
- #ifndef RCU_TREE_NONCORE
- static const char * const gp_state_names[] = {
- "RCU_GP_IDLE",
- "RCU_GP_WAIT_GPS",
- "RCU_GP_DONE_GPS",
- "RCU_GP_ONOFF",
- "RCU_GP_INIT",
- "RCU_GP_WAIT_FQS",
- "RCU_GP_DOING_FQS",
- "RCU_GP_CLEANUP",
- "RCU_GP_CLEANED",
- };
- #endif
- extern struct list_head rcu_struct_flavors;
- #define for_each_rcu_flavor(rsp) \
- list_for_each_entry((rsp), &rcu_struct_flavors, flavors)
- extern struct rcu_state rcu_sched_state;
- extern struct rcu_state rcu_bh_state;
- #ifdef CONFIG_PREEMPT_RCU
- extern struct rcu_state rcu_preempt_state;
- #endif
- int rcu_dynticks_snap(struct rcu_dynticks *rdtp);
- #ifdef CONFIG_RCU_BOOST
- DECLARE_PER_CPU(unsigned int, rcu_cpu_kthread_status);
- DECLARE_PER_CPU(int, rcu_cpu_kthread_cpu);
- DECLARE_PER_CPU(unsigned int, rcu_cpu_kthread_loops);
- DECLARE_PER_CPU(char, rcu_cpu_has_work);
- #endif
- #ifndef RCU_TREE_NONCORE
- static void rcu_bootup_announce(void);
- static void rcu_preempt_note_context_switch(bool preempt);
- static int rcu_preempt_blocked_readers_cgp(struct rcu_node *rnp);
- #ifdef CONFIG_HOTPLUG_CPU
- static bool rcu_preempt_has_tasks(struct rcu_node *rnp);
- #endif
- static void rcu_print_detail_task_stall(struct rcu_state *rsp);
- static int rcu_print_task_stall(struct rcu_node *rnp);
- static int rcu_print_task_exp_stall(struct rcu_node *rnp);
- static void rcu_preempt_check_blocked_tasks(struct rcu_state *rsp,
- struct rcu_node *rnp);
- static void rcu_preempt_check_callbacks(void);
- void call_rcu(struct rcu_head *head, rcu_callback_t func);
- static void __init __rcu_init_preempt(void);
- static void dump_blkd_tasks(struct rcu_state *rsp, struct rcu_node *rnp,
- int ncheck);
- static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags);
- static void rcu_preempt_boost_start_gp(struct rcu_node *rnp);
- static void invoke_rcu_callbacks_kthread(void);
- static bool rcu_is_callbacks_kthread(void);
- #ifdef CONFIG_RCU_BOOST
- static int rcu_spawn_one_boost_kthread(struct rcu_state *rsp,
- struct rcu_node *rnp);
- #endif
- static void __init rcu_spawn_boost_kthreads(void);
- static void rcu_prepare_kthreads(int cpu);
- static void rcu_cleanup_after_idle(void);
- static void rcu_prepare_for_idle(void);
- static void rcu_idle_count_callbacks_posted(void);
- static bool rcu_preempt_has_tasks(struct rcu_node *rnp);
- static void print_cpu_stall_info_begin(void);
- static void print_cpu_stall_info(struct rcu_state *rsp, int cpu);
- static void print_cpu_stall_info_end(void);
- static void zero_cpu_stall_ticks(struct rcu_data *rdp);
- static void increment_cpu_stall_ticks(void);
- static bool rcu_nocb_cpu_needs_barrier(struct rcu_state *rsp, int cpu);
- static struct swait_queue_head *rcu_nocb_gp_get(struct rcu_node *rnp);
- static void rcu_nocb_gp_cleanup(struct swait_queue_head *sq);
- static void rcu_init_one_nocb(struct rcu_node *rnp);
- static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp,
- bool lazy, unsigned long flags);
- static bool rcu_nocb_adopt_orphan_cbs(struct rcu_data *my_rdp,
- struct rcu_data *rdp,
- unsigned long flags);
- static int rcu_nocb_need_deferred_wakeup(struct rcu_data *rdp);
- static void do_nocb_deferred_wakeup(struct rcu_data *rdp);
- static void rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp);
- static void rcu_spawn_all_nocb_kthreads(int cpu);
- static void __init rcu_spawn_nocb_kthreads(void);
- #ifdef CONFIG_RCU_NOCB_CPU
- static void __init rcu_organize_nocb_kthreads(struct rcu_state *rsp);
- #endif
- static bool init_nocb_callback_list(struct rcu_data *rdp);
- static void rcu_bind_gp_kthread(void);
- static bool rcu_nohz_full_cpu(struct rcu_state *rsp);
- static void rcu_dynticks_task_enter(void);
- static void rcu_dynticks_task_exit(void);
- #ifdef CONFIG_SRCU
- void srcu_online_cpu(unsigned int cpu);
- void srcu_offline_cpu(unsigned int cpu);
- #else
- void srcu_online_cpu(unsigned int cpu) { }
- void srcu_offline_cpu(unsigned int cpu) { }
- #endif
- #endif
|