mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-24 05:29:04 -04:00
Merge branch 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull RCU changes from Ingo Molnar:
"The main changes in this cycle were:
- Improvements to expedited grace periods (Paul E McKenney)
- Performance improvements to and locktorture tests for percpu-rwsem
(Oleg Nesterov, Paul E McKenney)
- Torture-test changes (Paul E McKenney, Davidlohr Bueso)
- Documentation updates (Paul E McKenney)
- Miscellaneous fixes (Paul E McKenney, Boqun Feng, Oleg Nesterov,
Patrick Marlier)"
* 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (54 commits)
fs/writeback, rcu: Don't use list_entry_rcu() for pointer offsetting in bdi_split_work_to_wbs()
rcu: Better hotplug handling for synchronize_sched_expedited()
rcu: Enable stall warnings for synchronize_rcu_expedited()
rcu: Add tasks to expedited stall-warning messages
rcu: Add online/offline info to expedited stall warning message
rcu: Consolidate expedited CPU selection
rcu: Prepare for consolidating expedited CPU selection
cpu: Remove try_get_online_cpus()
rcu: Stop excluding CPU hotplug in synchronize_sched_expedited()
rcu: Stop silencing lockdep false positive for expedited grace periods
rcu: Switch synchronize_sched_expedited() to IPI
locktorture: Fix module unwind when bad torture_type specified
torture: Forgive non-plural arguments
rcutorture: Fix unused-function warning for torturing_tasks()
rcutorture: Fix module unwind when bad torture_type specified
rcu_sync: Cleanup the CONFIG_PROVE_RCU checks
locking/percpu-rwsem: Clean up the lockdep annotations in percpu_down_read()
locking/percpu-rwsem: Fix the comments outdated by rcu_sync
locking/percpu-rwsem: Make use of the rcu_sync infrastructure
locking/percpu-rwsem: Make percpu_free_rwsem() after kzalloc() safe
...
This commit is contained in:
commit
2814228699
42 changed files with 1333 additions and 545 deletions
|
|
@ -228,7 +228,6 @@ extern struct bus_type cpu_subsys;
|
|||
extern void cpu_hotplug_begin(void);
|
||||
extern void cpu_hotplug_done(void);
|
||||
extern void get_online_cpus(void);
|
||||
extern bool try_get_online_cpus(void);
|
||||
extern void put_online_cpus(void);
|
||||
extern void cpu_hotplug_disable(void);
|
||||
extern void cpu_hotplug_enable(void);
|
||||
|
|
@ -246,7 +245,6 @@ int cpu_down(unsigned int cpu);
|
|||
static inline void cpu_hotplug_begin(void) {}
|
||||
static inline void cpu_hotplug_done(void) {}
|
||||
#define get_online_cpus() do { } while (0)
|
||||
#define try_get_online_cpus() true
|
||||
#define put_online_cpus() do { } while (0)
|
||||
#define cpu_hotplug_disable() do { } while (0)
|
||||
#define cpu_hotplug_enable() do { } while (0)
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ static inline void list_add_tail(struct list_head *new, struct list_head *head)
|
|||
static inline void __list_del(struct list_head * prev, struct list_head * next)
|
||||
{
|
||||
next->prev = prev;
|
||||
prev->next = next;
|
||||
WRITE_ONCE(prev->next, next);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -615,7 +615,8 @@ static inline void __hlist_del(struct hlist_node *n)
|
|||
{
|
||||
struct hlist_node *next = n->next;
|
||||
struct hlist_node **pprev = n->pprev;
|
||||
*pprev = next;
|
||||
|
||||
WRITE_ONCE(*pprev, next);
|
||||
if (next)
|
||||
next->pprev = pprev;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,9 +93,10 @@ static inline void __hlist_bl_del(struct hlist_bl_node *n)
|
|||
LIST_BL_BUG_ON((unsigned long)n & LIST_BL_LOCKMASK);
|
||||
|
||||
/* pprev may be `first`, so be careful not to lose the lock bit */
|
||||
*pprev = (struct hlist_bl_node *)
|
||||
WRITE_ONCE(*pprev,
|
||||
(struct hlist_bl_node *)
|
||||
((unsigned long)next |
|
||||
((unsigned long)*pprev & LIST_BL_LOCKMASK));
|
||||
((unsigned long)*pprev & LIST_BL_LOCKMASK)));
|
||||
if (next)
|
||||
next->pprev = pprev;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,7 +76,8 @@ static inline void __hlist_nulls_del(struct hlist_nulls_node *n)
|
|||
{
|
||||
struct hlist_nulls_node *next = n->next;
|
||||
struct hlist_nulls_node **pprev = n->pprev;
|
||||
*pprev = next;
|
||||
|
||||
WRITE_ONCE(*pprev, next);
|
||||
if (!is_a_nulls(next))
|
||||
next->pprev = pprev;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,11 +5,12 @@
|
|||
#include <linux/rwsem.h>
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/rcu_sync.h>
|
||||
#include <linux/lockdep.h>
|
||||
|
||||
struct percpu_rw_semaphore {
|
||||
struct rcu_sync rss;
|
||||
unsigned int __percpu *fast_read_ctr;
|
||||
atomic_t write_ctr;
|
||||
struct rw_semaphore rw_sem;
|
||||
atomic_t slow_read_ctr;
|
||||
wait_queue_head_t write_waitq;
|
||||
|
|
|
|||
86
include/linux/rcu_sync.h
Normal file
86
include/linux/rcu_sync.h
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* RCU-based infrastructure for lightweight reader-writer locking
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you can access it online at
|
||||
* http://www.gnu.org/licenses/gpl-2.0.html.
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat, Inc.
|
||||
*
|
||||
* Author: Oleg Nesterov <oleg@redhat.com>
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_RCU_SYNC_H_
|
||||
#define _LINUX_RCU_SYNC_H_
|
||||
|
||||
#include <linux/wait.h>
|
||||
#include <linux/rcupdate.h>
|
||||
|
||||
enum rcu_sync_type { RCU_SYNC, RCU_SCHED_SYNC, RCU_BH_SYNC };
|
||||
|
||||
/* Structure to mediate between updaters and fastpath-using readers. */
|
||||
struct rcu_sync {
|
||||
int gp_state;
|
||||
int gp_count;
|
||||
wait_queue_head_t gp_wait;
|
||||
|
||||
int cb_state;
|
||||
struct rcu_head cb_head;
|
||||
|
||||
enum rcu_sync_type gp_type;
|
||||
};
|
||||
|
||||
extern void rcu_sync_lockdep_assert(struct rcu_sync *);
|
||||
|
||||
/**
|
||||
* rcu_sync_is_idle() - Are readers permitted to use their fastpaths?
|
||||
* @rsp: Pointer to rcu_sync structure to use for synchronization
|
||||
*
|
||||
* Returns true if readers are permitted to use their fastpaths.
|
||||
* Must be invoked within an RCU read-side critical section whose
|
||||
* flavor matches that of the rcu_sync struture.
|
||||
*/
|
||||
static inline bool rcu_sync_is_idle(struct rcu_sync *rsp)
|
||||
{
|
||||
#ifdef CONFIG_PROVE_RCU
|
||||
rcu_sync_lockdep_assert(rsp);
|
||||
#endif
|
||||
return !rsp->gp_state; /* GP_IDLE */
|
||||
}
|
||||
|
||||
extern void rcu_sync_init(struct rcu_sync *, enum rcu_sync_type);
|
||||
extern void rcu_sync_enter(struct rcu_sync *);
|
||||
extern void rcu_sync_exit(struct rcu_sync *);
|
||||
extern void rcu_sync_dtor(struct rcu_sync *);
|
||||
|
||||
#define __RCU_SYNC_INITIALIZER(name, type) { \
|
||||
.gp_state = 0, \
|
||||
.gp_count = 0, \
|
||||
.gp_wait = __WAIT_QUEUE_HEAD_INITIALIZER(name.gp_wait), \
|
||||
.cb_state = 0, \
|
||||
.gp_type = type, \
|
||||
}
|
||||
|
||||
#define __DEFINE_RCU_SYNC(name, type) \
|
||||
struct rcu_sync_struct name = __RCU_SYNC_INITIALIZER(name, type)
|
||||
|
||||
#define DEFINE_RCU_SYNC(name) \
|
||||
__DEFINE_RCU_SYNC(name, RCU_SYNC)
|
||||
|
||||
#define DEFINE_RCU_SCHED_SYNC(name) \
|
||||
__DEFINE_RCU_SYNC(name, RCU_SCHED_SYNC)
|
||||
|
||||
#define DEFINE_RCU_BH_SYNC(name) \
|
||||
__DEFINE_RCU_SYNC(name, RCU_BH_SYNC)
|
||||
|
||||
#endif /* _LINUX_RCU_SYNC_H_ */
|
||||
|
|
@ -247,10 +247,7 @@ static inline void list_splice_init_rcu(struct list_head *list,
|
|||
* primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock().
|
||||
*/
|
||||
#define list_entry_rcu(ptr, type, member) \
|
||||
({ \
|
||||
typeof(*ptr) __rcu *__ptr = (typeof(*ptr) __rcu __force *)ptr; \
|
||||
container_of((typeof(ptr))rcu_dereference_raw(__ptr), type, member); \
|
||||
})
|
||||
container_of(lockless_dereference(ptr), type, member)
|
||||
|
||||
/**
|
||||
* Where are list_empty_rcu() and list_first_entry_rcu()?
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ void do_trace_rcu_torture_read(const char *rcutorturename,
|
|||
* more than one CPU).
|
||||
*/
|
||||
void call_rcu(struct rcu_head *head,
|
||||
void (*func)(struct rcu_head *head));
|
||||
rcu_callback_t func);
|
||||
|
||||
#else /* #ifdef CONFIG_PREEMPT_RCU */
|
||||
|
||||
|
|
@ -191,7 +191,7 @@ void call_rcu(struct rcu_head *head,
|
|||
* memory ordering guarantees.
|
||||
*/
|
||||
void call_rcu_bh(struct rcu_head *head,
|
||||
void (*func)(struct rcu_head *head));
|
||||
rcu_callback_t func);
|
||||
|
||||
/**
|
||||
* call_rcu_sched() - Queue an RCU for invocation after sched grace period.
|
||||
|
|
@ -213,7 +213,7 @@ void call_rcu_bh(struct rcu_head *head,
|
|||
* memory ordering guarantees.
|
||||
*/
|
||||
void call_rcu_sched(struct rcu_head *head,
|
||||
void (*func)(struct rcu_head *rcu));
|
||||
rcu_callback_t func);
|
||||
|
||||
void synchronize_sched(void);
|
||||
|
||||
|
|
@ -274,7 +274,7 @@ do { \
|
|||
* See the description of call_rcu() for more detailed information on
|
||||
* memory ordering guarantees.
|
||||
*/
|
||||
void call_rcu_tasks(struct rcu_head *head, void (*func)(struct rcu_head *head));
|
||||
void call_rcu_tasks(struct rcu_head *head, rcu_callback_t func);
|
||||
void synchronize_rcu_tasks(void);
|
||||
void rcu_barrier_tasks(void);
|
||||
|
||||
|
|
@ -297,12 +297,14 @@ void synchronize_rcu(void);
|
|||
|
||||
static inline void __rcu_read_lock(void)
|
||||
{
|
||||
preempt_disable();
|
||||
if (IS_ENABLED(CONFIG_PREEMPT_COUNT))
|
||||
preempt_disable();
|
||||
}
|
||||
|
||||
static inline void __rcu_read_unlock(void)
|
||||
{
|
||||
preempt_enable();
|
||||
if (IS_ENABLED(CONFIG_PREEMPT_COUNT))
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
static inline void synchronize_rcu(void)
|
||||
|
|
@ -535,28 +537,8 @@ static inline int rcu_read_lock_sched_held(void)
|
|||
|
||||
#endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */
|
||||
|
||||
/* Deprecate rcu_lockdep_assert(): Use RCU_LOCKDEP_WARN() instead. */
|
||||
static inline void __attribute((deprecated)) deprecate_rcu_lockdep_assert(void)
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PROVE_RCU
|
||||
|
||||
/**
|
||||
* rcu_lockdep_assert - emit lockdep splat if specified condition not met
|
||||
* @c: condition to check
|
||||
* @s: informative message
|
||||
*/
|
||||
#define rcu_lockdep_assert(c, s) \
|
||||
do { \
|
||||
static bool __section(.data.unlikely) __warned; \
|
||||
deprecate_rcu_lockdep_assert(); \
|
||||
if (debug_lockdep_rcu_enabled() && !__warned && !(c)) { \
|
||||
__warned = true; \
|
||||
lockdep_rcu_suspicious(__FILE__, __LINE__, s); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* RCU_LOCKDEP_WARN - emit lockdep splat if specified condition is met
|
||||
* @c: condition to check
|
||||
|
|
@ -594,7 +576,6 @@ static inline void rcu_preempt_sleep_check(void)
|
|||
|
||||
#else /* #ifdef CONFIG_PROVE_RCU */
|
||||
|
||||
#define rcu_lockdep_assert(c, s) deprecate_rcu_lockdep_assert()
|
||||
#define RCU_LOCKDEP_WARN(c, s) do { } while (0)
|
||||
#define rcu_sleep_check() do { } while (0)
|
||||
|
||||
|
|
@ -810,6 +791,28 @@ static inline void rcu_preempt_sleep_check(void)
|
|||
*/
|
||||
#define rcu_dereference_sched(p) rcu_dereference_sched_check(p, 0)
|
||||
|
||||
/**
|
||||
* rcu_pointer_handoff() - Hand off a pointer from RCU to other mechanism
|
||||
* @p: The pointer to hand off
|
||||
*
|
||||
* This is simply an identity function, but it documents where a pointer
|
||||
* is handed off from RCU to some other synchronization mechanism, for
|
||||
* example, reference counting or locking. In C11, it would map to
|
||||
* kill_dependency(). It could be used as follows:
|
||||
*
|
||||
* rcu_read_lock();
|
||||
* p = rcu_dereference(gp);
|
||||
* long_lived = is_long_lived(p);
|
||||
* if (long_lived) {
|
||||
* if (!atomic_inc_not_zero(p->refcnt))
|
||||
* long_lived = false;
|
||||
* else
|
||||
* p = rcu_pointer_handoff(p);
|
||||
* }
|
||||
* rcu_read_unlock();
|
||||
*/
|
||||
#define rcu_pointer_handoff(p) (p)
|
||||
|
||||
/**
|
||||
* rcu_read_lock() - mark the beginning of an RCU read-side critical section
|
||||
*
|
||||
|
|
@ -1065,7 +1068,7 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
|
|||
#define __kfree_rcu(head, offset) \
|
||||
do { \
|
||||
BUILD_BUG_ON(!__is_kfree_rcu_offset(offset)); \
|
||||
kfree_call_rcu(head, (void (*)(struct rcu_head *))(unsigned long)(offset)); \
|
||||
kfree_call_rcu(head, (rcu_callback_t)(unsigned long)(offset)); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ static inline void synchronize_sched_expedited(void)
|
|||
}
|
||||
|
||||
static inline void kfree_call_rcu(struct rcu_head *head,
|
||||
void (*func)(struct rcu_head *rcu))
|
||||
rcu_callback_t func)
|
||||
{
|
||||
call_rcu(head, func);
|
||||
}
|
||||
|
|
@ -216,6 +216,7 @@ static inline bool rcu_is_watching(void)
|
|||
|
||||
static inline void rcu_all_qs(void)
|
||||
{
|
||||
barrier(); /* Avoid RCU read-side critical sections leaking across. */
|
||||
}
|
||||
|
||||
#endif /* __LINUX_RCUTINY_H */
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ void synchronize_rcu_bh(void);
|
|||
void synchronize_sched_expedited(void);
|
||||
void synchronize_rcu_expedited(void);
|
||||
|
||||
void kfree_call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu));
|
||||
void kfree_call_rcu(struct rcu_head *head, rcu_callback_t func);
|
||||
|
||||
/**
|
||||
* synchronize_rcu_bh_expedited - Brute-force RCU-bh grace period
|
||||
|
|
|
|||
|
|
@ -1345,10 +1345,12 @@ struct sched_dl_entity {
|
|||
|
||||
union rcu_special {
|
||||
struct {
|
||||
bool blocked;
|
||||
bool need_qs;
|
||||
} b;
|
||||
short s;
|
||||
u8 blocked;
|
||||
u8 need_qs;
|
||||
u8 exp_need_qs;
|
||||
u8 pad; /* Otherwise the compiler can store garbage here. */
|
||||
} b; /* Bits. */
|
||||
u32 s; /* Set of bits. */
|
||||
};
|
||||
struct rcu_node;
|
||||
|
||||
|
|
|
|||
|
|
@ -215,8 +215,11 @@ static inline int srcu_read_lock_held(struct srcu_struct *sp)
|
|||
*/
|
||||
static inline int srcu_read_lock(struct srcu_struct *sp) __acquires(sp)
|
||||
{
|
||||
int retval = __srcu_read_lock(sp);
|
||||
int retval;
|
||||
|
||||
preempt_disable();
|
||||
retval = __srcu_read_lock(sp);
|
||||
preempt_enable();
|
||||
rcu_lock_acquire(&(sp)->dep_map);
|
||||
return retval;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue