1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165 |
- #ifndef __LINUX_RCUPDATE_H
- #define __LINUX_RCUPDATE_H
- #include <linux/types.h>
- #include <linux/cache.h>
- #include <linux/spinlock.h>
- #include <linux/threads.h>
- #include <linux/cpumask.h>
- #include <linux/seqlock.h>
- #include <linux/lockdep.h>
- #include <linux/completion.h>
- #include <linux/debugobjects.h>
- #include <linux/bug.h>
- #include <linux/compiler.h>
- #include <linux/ktime.h>
- #include <linux/irqflags.h>
- #include <asm/barrier.h>
- #ifndef CONFIG_TINY_RCU
- extern int rcu_expedited;
- extern int rcu_normal;
- #endif
- #ifdef CONFIG_TINY_RCU
- static inline bool rcu_gp_is_normal(void)
- {
- return true;
- }
- static inline bool rcu_gp_is_expedited(void)
- {
- return false;
- }
- static inline void rcu_expedite_gp(void)
- {
- }
- static inline void rcu_unexpedite_gp(void)
- {
- }
- #else
- bool rcu_gp_is_normal(void);
- bool rcu_gp_is_expedited(void);
- void rcu_expedite_gp(void);
- void rcu_unexpedite_gp(void);
- #endif
- enum rcutorture_type {
- RCU_FLAVOR,
- RCU_BH_FLAVOR,
- RCU_SCHED_FLAVOR,
- RCU_TASKS_FLAVOR,
- SRCU_FLAVOR,
- INVALID_RCU_FLAVOR
- };
- #if defined(CONFIG_TREE_RCU) || defined(CONFIG_PREEMPT_RCU)
- void rcutorture_get_gp_data(enum rcutorture_type test_type, int *flags,
- unsigned long *gpnum, unsigned long *completed);
- void rcutorture_record_test_transition(void);
- void rcutorture_record_progress(unsigned long vernum);
- void do_trace_rcu_torture_read(const char *rcutorturename,
- struct rcu_head *rhp,
- unsigned long secs,
- unsigned long c_old,
- unsigned long c);
- #else
- static inline void rcutorture_get_gp_data(enum rcutorture_type test_type,
- int *flags,
- unsigned long *gpnum,
- unsigned long *completed)
- {
- *flags = 0;
- *gpnum = 0;
- *completed = 0;
- }
- static inline void rcutorture_record_test_transition(void)
- {
- }
- static inline void rcutorture_record_progress(unsigned long vernum)
- {
- }
- #ifdef CONFIG_RCU_TRACE
- void do_trace_rcu_torture_read(const char *rcutorturename,
- struct rcu_head *rhp,
- unsigned long secs,
- unsigned long c_old,
- unsigned long c);
- #else
- #define do_trace_rcu_torture_read(rcutorturename, rhp, secs, c_old, c) \
- do { } while (0)
- #endif
- #endif
- #define UINT_CMP_GE(a, b) (UINT_MAX / 2 >= (a) - (b))
- #define UINT_CMP_LT(a, b) (UINT_MAX / 2 < (a) - (b))
- #define ULONG_CMP_GE(a, b) (ULONG_MAX / 2 >= (a) - (b))
- #define ULONG_CMP_LT(a, b) (ULONG_MAX / 2 < (a) - (b))
- #define ulong2long(a) (*(long *)(&(a)))
- #ifdef CONFIG_PREEMPT_RCU
- void call_rcu(struct rcu_head *head,
- rcu_callback_t func);
- #else
- #define call_rcu call_rcu_sched
- #endif
- void call_rcu_bh(struct rcu_head *head,
- rcu_callback_t func);
- void call_rcu_sched(struct rcu_head *head,
- rcu_callback_t func);
- void synchronize_sched(void);
- struct rcu_synchronize {
- struct rcu_head head;
- struct completion completion;
- };
- void wakeme_after_rcu(struct rcu_head *head);
- void __wait_rcu_gp(bool checktiny, int n, call_rcu_func_t *crcu_array,
- struct rcu_synchronize *rs_array);
- #define _wait_rcu_gp(checktiny, ...) \
- do { \
- call_rcu_func_t __crcu_array[] = { __VA_ARGS__ }; \
- struct rcu_synchronize __rs_array[ARRAY_SIZE(__crcu_array)]; \
- __wait_rcu_gp(checktiny, ARRAY_SIZE(__crcu_array), \
- __crcu_array, __rs_array); \
- } while (0)
- #define wait_rcu_gp(...) _wait_rcu_gp(false, __VA_ARGS__)
- #define synchronize_rcu_mult(...) \
- _wait_rcu_gp(IS_ENABLED(CONFIG_TINY_RCU), __VA_ARGS__)
- void call_rcu_tasks(struct rcu_head *head, rcu_callback_t func);
- void synchronize_rcu_tasks(void);
- void rcu_barrier_tasks(void);
- #ifdef CONFIG_PREEMPT_RCU
- void __rcu_read_lock(void);
- void __rcu_read_unlock(void);
- void rcu_read_unlock_special(struct task_struct *t);
- void synchronize_rcu(void);
- #define rcu_preempt_depth() (current->rcu_read_lock_nesting)
- #else
- static inline void __rcu_read_lock(void)
- {
- if (IS_ENABLED(CONFIG_PREEMPT_COUNT))
- preempt_disable();
- }
- static inline void __rcu_read_unlock(void)
- {
- if (IS_ENABLED(CONFIG_PREEMPT_COUNT))
- preempt_enable();
- }
- static inline void synchronize_rcu(void)
- {
- synchronize_sched();
- }
- static inline int rcu_preempt_depth(void)
- {
- return 0;
- }
- #endif
- void rcu_init(void);
- void rcu_sched_qs(void);
- void rcu_bh_qs(void);
- void rcu_check_callbacks(int user);
- void rcu_report_dead(unsigned int cpu);
- void rcu_cpu_starting(unsigned int cpu);
- #ifndef CONFIG_TINY_RCU
- void rcu_end_inkernel_boot(void);
- #else
- static inline void rcu_end_inkernel_boot(void) { }
- #endif
- #ifdef CONFIG_RCU_STALL_COMMON
- void rcu_sysrq_start(void);
- void rcu_sysrq_end(void);
- #else
- static inline void rcu_sysrq_start(void)
- {
- }
- static inline void rcu_sysrq_end(void)
- {
- }
- #endif
- #ifdef CONFIG_NO_HZ_FULL
- void rcu_user_enter(void);
- void rcu_user_exit(void);
- #else
- static inline void rcu_user_enter(void) { }
- static inline void rcu_user_exit(void) { }
- #endif
- #ifdef CONFIG_RCU_NOCB_CPU
- void rcu_init_nohz(void);
- #else
- static inline void rcu_init_nohz(void)
- {
- }
- #endif
- #define RCU_NONIDLE(a) \
- do { \
- rcu_irq_enter_irqson(); \
- do { a; } while (0); \
- rcu_irq_exit_irqson(); \
- } while (0)
- #ifdef CONFIG_TASKS_RCU
- #define TASKS_RCU(x) x
- extern struct srcu_struct tasks_rcu_exit_srcu;
- #define rcu_note_voluntary_context_switch(t) \
- do { \
- rcu_all_qs(); \
- if (READ_ONCE((t)->rcu_tasks_holdout)) \
- WRITE_ONCE((t)->rcu_tasks_holdout, false); \
- } while (0)
- #else
- #define TASKS_RCU(x) do { } while (0)
- #define rcu_note_voluntary_context_switch(t) rcu_all_qs()
- #endif
- #define cond_resched_rcu_qs() \
- do { \
- if (!cond_resched()) \
- rcu_note_voluntary_context_switch(current); \
- } while (0)
- #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) || defined(CONFIG_SMP)
- bool __rcu_is_watching(void);
- #endif
- #if defined(CONFIG_TREE_RCU) || defined(CONFIG_PREEMPT_RCU)
- #include <linux/rcutree.h>
- #elif defined(CONFIG_TINY_RCU)
- #include <linux/rcutiny.h>
- #else
- #error "Unknown RCU implementation specified to kernel configuration"
- #endif
- #define RCU_SCHEDULER_INACTIVE 0
- #define RCU_SCHEDULER_INIT 1
- #define RCU_SCHEDULER_RUNNING 2
- #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD
- void init_rcu_head(struct rcu_head *head);
- void destroy_rcu_head(struct rcu_head *head);
- void init_rcu_head_on_stack(struct rcu_head *head);
- void destroy_rcu_head_on_stack(struct rcu_head *head);
- #else
- static inline void init_rcu_head(struct rcu_head *head)
- {
- }
- static inline void destroy_rcu_head(struct rcu_head *head)
- {
- }
- static inline void init_rcu_head_on_stack(struct rcu_head *head)
- {
- }
- static inline void destroy_rcu_head_on_stack(struct rcu_head *head)
- {
- }
- #endif
- #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PROVE_RCU)
- bool rcu_lockdep_current_cpu_online(void);
- #else
- static inline bool rcu_lockdep_current_cpu_online(void)
- {
- return true;
- }
- #endif
- #ifdef CONFIG_DEBUG_LOCK_ALLOC
- static inline void rcu_lock_acquire(struct lockdep_map *map)
- {
- lock_acquire(map, 0, 0, 2, 0, NULL, _THIS_IP_);
- }
- static inline void rcu_lock_release(struct lockdep_map *map)
- {
- lock_release(map, 1, _THIS_IP_);
- }
- extern struct lockdep_map rcu_lock_map;
- extern struct lockdep_map rcu_bh_lock_map;
- extern struct lockdep_map rcu_sched_lock_map;
- extern struct lockdep_map rcu_callback_map;
- int debug_lockdep_rcu_enabled(void);
- int rcu_read_lock_held(void);
- int rcu_read_lock_bh_held(void);
- int rcu_read_lock_sched_held(void);
- #else
- # define rcu_lock_acquire(a) do { } while (0)
- # define rcu_lock_release(a) do { } while (0)
- static inline int rcu_read_lock_held(void)
- {
- return 1;
- }
- static inline int rcu_read_lock_bh_held(void)
- {
- return 1;
- }
- static inline int rcu_read_lock_sched_held(void)
- {
- return !preemptible();
- }
- #endif
- #ifdef CONFIG_PROVE_RCU
- #define RCU_LOCKDEP_WARN(c, s) \
- do { \
- static bool __section(.data.unlikely) __warned; \
- if (debug_lockdep_rcu_enabled() && !__warned && (c)) { \
- __warned = true; \
- lockdep_rcu_suspicious(__FILE__, __LINE__, s); \
- } \
- } while (0)
- #if defined(CONFIG_PROVE_RCU) && !defined(CONFIG_PREEMPT_RCU)
- static inline void rcu_preempt_sleep_check(void)
- {
- RCU_LOCKDEP_WARN(lock_is_held(&rcu_lock_map),
- "Illegal context switch in RCU read-side critical section");
- }
- #else
- static inline void rcu_preempt_sleep_check(void)
- {
- }
- #endif
- #define rcu_sleep_check() \
- do { \
- rcu_preempt_sleep_check(); \
- RCU_LOCKDEP_WARN(lock_is_held(&rcu_bh_lock_map), \
- "Illegal context switch in RCU-bh read-side critical section"); \
- RCU_LOCKDEP_WARN(lock_is_held(&rcu_sched_lock_map), \
- "Illegal context switch in RCU-sched read-side critical section"); \
- } while (0)
- #else
- #define RCU_LOCKDEP_WARN(c, s) do { } while (0)
- #define rcu_sleep_check() do { } while (0)
- #endif
- #ifdef __CHECKER__
- #define rcu_dereference_sparse(p, space) \
- ((void)(((typeof(*p) space *)p) == p))
- #else
- #define rcu_dereference_sparse(p, space)
- #endif
- #define __rcu_access_pointer(p, space) \
- ({ \
- typeof(*p) *_________p1 = (typeof(*p) *__force)READ_ONCE(p); \
- rcu_dereference_sparse(p, space); \
- ((typeof(*p) __force __kernel *)(_________p1)); \
- })
- #define __rcu_dereference_check(p, c, space) \
- ({ \
- \
- typeof(*p) *________p1 = (typeof(*p) *__force)lockless_dereference(p); \
- RCU_LOCKDEP_WARN(!(c), "suspicious rcu_dereference_check() usage"); \
- rcu_dereference_sparse(p, space); \
- ((typeof(*p) __force __kernel *)(________p1)); \
- })
- #define __rcu_dereference_protected(p, c, space) \
- ({ \
- RCU_LOCKDEP_WARN(!(c), "suspicious rcu_dereference_protected() usage"); \
- rcu_dereference_sparse(p, space); \
- ((typeof(*p) __force __kernel *)(p)); \
- })
- #define rcu_dereference_raw(p) \
- ({ \
- \
- typeof(p) ________p1 = lockless_dereference(p); \
- ((typeof(*p) __force __kernel *)(________p1)); \
- })
- #define RCU_INITIALIZER(v) (typeof(*(v)) __force __rcu *)(v)
- #define rcu_assign_pointer(p, v) \
- ({ \
- uintptr_t _r_a_p__v = (uintptr_t)(v); \
- \
- if (__builtin_constant_p(v) && (_r_a_p__v) == (uintptr_t)NULL) \
- WRITE_ONCE((p), (typeof(p))(_r_a_p__v)); \
- else \
- smp_store_release(&p, RCU_INITIALIZER((typeof(p))_r_a_p__v)); \
- _r_a_p__v; \
- })
- #define rcu_access_pointer(p) __rcu_access_pointer((p), __rcu)
- #define rcu_dereference_check(p, c) \
- __rcu_dereference_check((p), (c) || rcu_read_lock_held(), __rcu)
- #define rcu_dereference_bh_check(p, c) \
- __rcu_dereference_check((p), (c) || rcu_read_lock_bh_held(), __rcu)
- #define rcu_dereference_sched_check(p, c) \
- __rcu_dereference_check((p), (c) || rcu_read_lock_sched_held(), \
- __rcu)
- #define rcu_dereference_raw_notrace(p) __rcu_dereference_check((p), 1, __rcu)
- #define rcu_dereference_protected(p, c) \
- __rcu_dereference_protected((p), (c), __rcu)
- #define rcu_dereference(p) rcu_dereference_check(p, 0)
- #define rcu_dereference_bh(p) rcu_dereference_bh_check(p, 0)
- #define rcu_dereference_sched(p) rcu_dereference_sched_check(p, 0)
- #define rcu_pointer_handoff(p) (p)
- static inline void rcu_read_lock(void)
- {
- __rcu_read_lock();
- __acquire(RCU);
- rcu_lock_acquire(&rcu_lock_map);
- RCU_LOCKDEP_WARN(!rcu_is_watching(),
- "rcu_read_lock() used illegally while idle");
- }
- static inline void rcu_read_unlock(void)
- {
- RCU_LOCKDEP_WARN(!rcu_is_watching(),
- "rcu_read_unlock() used illegally while idle");
- __release(RCU);
- __rcu_read_unlock();
- rcu_lock_release(&rcu_lock_map);
- }
- static inline void rcu_read_lock_bh(void)
- {
- local_bh_disable();
- __acquire(RCU_BH);
- rcu_lock_acquire(&rcu_bh_lock_map);
- RCU_LOCKDEP_WARN(!rcu_is_watching(),
- "rcu_read_lock_bh() used illegally while idle");
- }
- static inline void rcu_read_unlock_bh(void)
- {
- RCU_LOCKDEP_WARN(!rcu_is_watching(),
- "rcu_read_unlock_bh() used illegally while idle");
- rcu_lock_release(&rcu_bh_lock_map);
- __release(RCU_BH);
- local_bh_enable();
- }
- static inline void rcu_read_lock_sched(void)
- {
- preempt_disable();
- __acquire(RCU_SCHED);
- rcu_lock_acquire(&rcu_sched_lock_map);
- RCU_LOCKDEP_WARN(!rcu_is_watching(),
- "rcu_read_lock_sched() used illegally while idle");
- }
- static inline notrace void rcu_read_lock_sched_notrace(void)
- {
- preempt_disable_notrace();
- __acquire(RCU_SCHED);
- }
- static inline void rcu_read_unlock_sched(void)
- {
- RCU_LOCKDEP_WARN(!rcu_is_watching(),
- "rcu_read_unlock_sched() used illegally while idle");
- rcu_lock_release(&rcu_sched_lock_map);
- __release(RCU_SCHED);
- preempt_enable();
- }
- static inline notrace void rcu_read_unlock_sched_notrace(void)
- {
- __release(RCU_SCHED);
- preempt_enable_notrace();
- }
- #define RCU_INIT_POINTER(p, v) \
- do { \
- rcu_dereference_sparse(p, __rcu); \
- WRITE_ONCE(p, RCU_INITIALIZER(v)); \
- } while (0)
- #define RCU_POINTER_INITIALIZER(p, v) \
- .p = RCU_INITIALIZER(v)
- #define __is_kfree_rcu_offset(offset) ((offset) < 4096)
- #define __kfree_rcu(head, offset) \
- do { \
- BUILD_BUG_ON(!__is_kfree_rcu_offset(offset)); \
- kfree_call_rcu(head, (rcu_callback_t)(unsigned long)(offset)); \
- } while (0)
- #define kfree_rcu(ptr, rcu_head) \
- __kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head))
- #ifdef CONFIG_TINY_RCU
- static inline int rcu_needs_cpu(u64 basemono, u64 *nextevt)
- {
- *nextevt = KTIME_MAX;
- return 0;
- }
- #endif
- #if defined(CONFIG_RCU_NOCB_CPU_ALL)
- static inline bool rcu_is_nocb_cpu(int cpu) { return true; }
- #elif defined(CONFIG_RCU_NOCB_CPU)
- bool rcu_is_nocb_cpu(int cpu);
- #else
- static inline bool rcu_is_nocb_cpu(int cpu) { return false; }
- #endif
- #ifdef CONFIG_NO_HZ_FULL_SYSIDLE
- bool rcu_sys_is_idle(void);
- void rcu_sysidle_force_exit(void);
- #else
- static inline bool rcu_sys_is_idle(void)
- {
- return false;
- }
- static inline void rcu_sysidle_force_exit(void)
- {
- }
- #endif
- #define rcu_ftrace_dump(oops_dump_mode) \
- do { \
- static atomic_t ___rfd_beenhere = ATOMIC_INIT(0); \
- \
- if (!atomic_read(&___rfd_beenhere) && \
- !atomic_xchg(&___rfd_beenhere, 1)) \
- ftrace_dump(oops_dump_mode); \
- } while (0)
- #endif
|