Skip to content

Commit

Permalink
sched: Make cond_resched_lock() RT aware
Browse files Browse the repository at this point in the history
[ This is an all-in-one commit reverting the commit
     sched: Do not account rcu_preempt_depth on RT in might_sleep()
  and introducing this commit.
]

The might_sleep() checks in the cond_resched_lock() variants use
PREEMPT_LOCK_OFFSET for preempt count offset checking.

On PREEMPT_RT enabled kernels spin/rw_lock held sections stay preemptible
which means PREEMPT_LOCK_OFFSET is 0, but that still triggers the
might_sleep() check because that takes RCU read side nesting into account.

On RT enabled kernels spin/read/write_lock() issue rcu_read_lock() to
resemble the !RT semantics, which means in cond_resched_lock() the might
sleep check will see preempt_count() == 0 and rcu_preempt_depth() == 1.

Introduce PREEMPT_LOCK_SCHED_OFFSET for those might sleep checks and map
them to PREEMPT_LOCK_OFFSET on !RT and to 1 (accounting for
rcu_preempt_depth()) on RT enabled kernels.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
  • Loading branch information
Thomas Gleixner authored and Sebastian Andrzej Siewior committed Sep 22, 2021
1 parent 279b703 commit c56c6f2
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 19 deletions.
12 changes: 10 additions & 2 deletions include/linux/preempt.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,17 @@
* The preempt_count offset after spin_lock()
*/
#if !defined(CONFIG_PREEMPT_RT)
#define PREEMPT_LOCK_OFFSET PREEMPT_DISABLE_OFFSET
#define PREEMPT_LOCK_OFFSET PREEMPT_DISABLE_OFFSET
#define PREEMPT_LOCK_RESCHED_OFFSET PREEMPT_LOCK_OFFSET
#else
#define PREEMPT_LOCK_OFFSET 0
/* Locks on RT do not disable preemption */
#define PREEMPT_LOCK_OFFSET 0
/*
* spin/rw_lock() on RT implies rcu_read_lock(). The might_sleep() check in
* cond_resched*lock() has to take that into account because it checks for
* preempt_count() + rcu_preempt_depth().
*/
#define PREEMPT_LOCK_RESCHED_OFFSET 1
#endif

/*
Expand Down
7 changes: 0 additions & 7 deletions include/linux/rcupdate.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,6 @@ void __rcu_read_unlock(void);
* types of kernel builds, the rcu_read_lock() nesting depth is unknowable.
*/
#define rcu_preempt_depth() READ_ONCE(current->rcu_read_lock_nesting)
#ifndef CONFIG_PREEMPT_RT
#define sched_rcu_preempt_depth() rcu_preempt_depth()
#else
static inline int sched_rcu_preempt_depth(void) { return 0; }
#endif

#else /* #ifdef CONFIG_PREEMPT_RCU */

Expand All @@ -84,8 +79,6 @@ static inline int rcu_preempt_depth(void)
return 0;
}

#define sched_rcu_preempt_depth() rcu_preempt_depth()

#endif /* #else #ifdef CONFIG_PREEMPT_RCU */

/* Internal to kernel */
Expand Down
18 changes: 9 additions & 9 deletions include/linux/sched.h
Original file line number Diff line number Diff line change
Expand Up @@ -2169,19 +2169,19 @@ extern int __cond_resched_lock(spinlock_t *lock);
extern int __cond_resched_rwlock_read(rwlock_t *lock);
extern int __cond_resched_rwlock_write(rwlock_t *lock);

#define cond_resched_lock(lock) ({ \
___might_sleep(__FILE__, __LINE__, PREEMPT_LOCK_OFFSET);\
__cond_resched_lock(lock); \
#define cond_resched_lock(lock) ({ \
__might_sleep(__FILE__, __LINE__, PREEMPT_LOCK_RESCHED_OFFSET); \
__cond_resched_lock(lock); \
})

#define cond_resched_rwlock_read(lock) ({ \
__might_sleep(__FILE__, __LINE__, PREEMPT_LOCK_OFFSET); \
__cond_resched_rwlock_read(lock); \
#define cond_resched_rwlock_read(lock) ({ \
__might_sleep(__FILE__, __LINE__, PREEMPT_LOCK_RESCHED_OFFSET); \
__cond_resched_rwlock_read(lock); \
})

#define cond_resched_rwlock_write(lock) ({ \
__might_sleep(__FILE__, __LINE__, PREEMPT_LOCK_OFFSET); \
__cond_resched_rwlock_write(lock); \
#define cond_resched_rwlock_write(lock) ( { \
__might_sleep(__FILE__, __LINE__, PREEMPT_LOCK_RESCHED_OFFSET); \
__cond_resched_rwlock_write(lock); \
})

static inline void cond_resched_rcu(void)
Expand Down
2 changes: 1 addition & 1 deletion kernel/sched/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -9547,7 +9547,7 @@ void __init sched_init(void)
#ifdef CONFIG_DEBUG_ATOMIC_SLEEP
static inline int preempt_count_equals(int preempt_offset)
{
int nested = preempt_count() + sched_rcu_preempt_depth();
int nested = preempt_count() + rcu_preempt_depth();

return (nested == preempt_offset);
}
Expand Down

0 comments on commit c56c6f2

Please sign in to comment.