mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-30 16:07:39 +00:00
943f0edb75
On PREEMPT_RT, rw_semaphores and rwlocks are substituted with an rtmutex and a reader count. The implementation is writer unfair, as it is not feasible to do priority inheritance on multiple readers, but experience has shown that real-time workloads are not the typical workloads which are sensitive to writer starvation. The inner workings of rw_semaphores and rwlocks on RT are almost identical except for the task state and signal handling. rw_semaphores are not state preserving over a contention, they are expected to enter and leave with state == TASK_RUNNING. rwlocks have a mechanism to preserve the state of the task at entry and restore it after unblocking taking potential non-lock related wakeups into account. rw_semaphores can also be subject to signal handling interrupting a blocked state, while rwlocks ignore signals. To avoid code duplication, provide a shared implementation which takes the small difference vs. state and signals into account. The code is included into the relevant rw_semaphore/rwlock base code and compiled for each use case separately. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Signed-off-by: Ingo Molnar <mingo@kernel.org> Link: https://lore.kernel.org/r/20210815211302.957920571@linutronix.de
39 lines
876 B
C
39 lines
876 B
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
#ifndef _LINUX_RWBASE_RT_H
|
|
#define _LINUX_RWBASE_RT_H
|
|
|
|
#include <linux/rtmutex.h>
|
|
#include <linux/atomic.h>
|
|
|
|
#define READER_BIAS (1U << 31)
|
|
#define WRITER_BIAS (1U << 30)
|
|
|
|
struct rwbase_rt {
|
|
atomic_t readers;
|
|
struct rt_mutex_base rtmutex;
|
|
};
|
|
|
|
#define __RWBASE_INITIALIZER(name) \
|
|
{ \
|
|
.readers = ATOMIC_INIT(READER_BIAS), \
|
|
.rtmutex = __RT_MUTEX_BASE_INITIALIZER(name.rtmutex), \
|
|
}
|
|
|
|
#define init_rwbase_rt(rwbase) \
|
|
do { \
|
|
rt_mutex_base_init(&(rwbase)->rtmutex); \
|
|
atomic_set(&(rwbase)->readers, READER_BIAS); \
|
|
} while (0)
|
|
|
|
|
|
static __always_inline bool rw_base_is_locked(struct rwbase_rt *rwb)
|
|
{
|
|
return atomic_read(&rwb->readers) != READER_BIAS;
|
|
}
|
|
|
|
static __always_inline bool rw_base_is_contended(struct rwbase_rt *rwb)
|
|
{
|
|
return atomic_read(&rwb->readers) > 0;
|
|
}
|
|
|
|
#endif /* _LINUX_RWBASE_RT_H */
|