| Subject: rwsem-add-rt-variant.patch |
| From: Thomas Gleixner <tglx@linutronix.de> |
| Date: Wed, 29 Jun 2011 21:02:53 +0200 |
| |
| Signed-off-by: Thomas Gleixner <tglx@linutronix.de> |
| --- |
| include/linux/rwsem.h | 6 ++ |
| include/linux/rwsem_rt.h | 128 +++++++++++++++++++++++++++++++++++++++++++++++ |
| lib/Makefile | 3 + |
| 3 files changed, 137 insertions(+) |
| |
| --- a/include/linux/rwsem.h |
| +++ b/include/linux/rwsem.h |
| @@ -16,6 +16,10 @@ |
| |
| #include <linux/atomic.h> |
| |
| +#ifdef CONFIG_PREEMPT_RT_FULL |
| +#include <linux/rwsem_rt.h> |
| +#else /* PREEMPT_RT_FULL */ |
| + |
| struct rw_semaphore; |
| |
| #ifdef CONFIG_RWSEM_GENERIC_SPINLOCK |
| @@ -139,4 +143,6 @@ do { \ |
| # define down_write_nested(sem, subclass) down_write(sem) |
| #endif |
| |
| +#endif /* !PREEMPT_RT_FULL */ |
| + |
| #endif /* _LINUX_RWSEM_H */ |
| --- /dev/null |
| +++ b/include/linux/rwsem_rt.h |
| @@ -0,0 +1,128 @@ |
| +#ifndef _LINUX_RWSEM_RT_H |
| +#define _LINUX_RWSEM_RT_H |
| + |
| +#ifndef _LINUX_RWSEM_H |
| +#error "Include rwsem.h" |
| +#endif |
| + |
| +/* |
| + * RW-semaphores are a spinlock plus a reader-depth count. |
| + * |
| + * Note that the semantics are different from the usual |
| + * Linux rw-sems, in PREEMPT_RT mode we do not allow |
| + * multiple readers to hold the lock at once, we only allow |
| + * a read-lock owner to read-lock recursively. This is |
| + * better for latency, makes the implementation inherently |
| + * fair and makes it simpler as well. |
| + */ |
| + |
| +#include <linux/rtmutex.h> |
| + |
| +struct rw_semaphore { |
| + struct rt_mutex lock; |
| + int read_depth; |
| +#ifdef CONFIG_DEBUG_LOCK_ALLOC |
| + struct lockdep_map dep_map; |
| +#endif |
| +}; |
| + |
| +#define __RWSEM_INITIALIZER(name) \ |
| + { .lock = __RT_MUTEX_INITIALIZER(name.lock), \ |
| + RW_DEP_MAP_INIT(name) } |
| + |
| +#define DECLARE_RWSEM(lockname) \ |
| + struct rw_semaphore lockname = __RWSEM_INITIALIZER(lockname) |
| + |
| +extern void __rt_rwsem_init(struct rw_semaphore *rwsem, const char *name, |
| + struct lock_class_key *key); |
| + |
| +#define __rt_init_rwsem(sem, name, key) \ |
| + do { \ |
| + rt_mutex_init(&(sem)->lock); \ |
| + __rt_rwsem_init((sem), (name), (key));\ |
| + } while (0) |
| + |
| +#define __init_rwsem(sem, name, key) __rt_init_rwsem(sem, name, key) |
| + |
| +# define rt_init_rwsem(sem) \ |
| +do { \ |
| + static struct lock_class_key __key; \ |
| + \ |
| + __rt_init_rwsem((sem), #sem, &__key); \ |
| +} while (0) |
| + |
| +extern void rt_down_write(struct rw_semaphore *rwsem); |
| +extern void rt_down_read_nested(struct rw_semaphore *rwsem, int subclass); |
| +extern void rt_down_write_nested(struct rw_semaphore *rwsem, int subclass); |
| +extern void rt_down_write_nested_lock(struct rw_semaphore *rwsem, |
| + struct lockdep_map *nest); |
| +extern void rt_down_read(struct rw_semaphore *rwsem); |
| +extern int rt_down_write_trylock(struct rw_semaphore *rwsem); |
| +extern int rt_down_read_trylock(struct rw_semaphore *rwsem); |
| +extern void rt_up_read(struct rw_semaphore *rwsem); |
| +extern void rt_up_write(struct rw_semaphore *rwsem); |
| +extern void rt_downgrade_write(struct rw_semaphore *rwsem); |
| + |
| +#define init_rwsem(sem) rt_init_rwsem(sem) |
| +#define rwsem_is_locked(s) rt_mutex_is_locked(&(s)->lock) |
| + |
| +static inline void down_read(struct rw_semaphore *sem) |
| +{ |
| + rt_down_read(sem); |
| +} |
| + |
| +static inline int down_read_trylock(struct rw_semaphore *sem) |
| +{ |
| + return rt_down_read_trylock(sem); |
| +} |
| + |
| +static inline void down_write(struct rw_semaphore *sem) |
| +{ |
| + rt_down_write(sem); |
| +} |
| + |
| +static inline int down_write_trylock(struct rw_semaphore *sem) |
| +{ |
| + return rt_down_write_trylock(sem); |
| +} |
| + |
| +static inline void up_read(struct rw_semaphore *sem) |
| +{ |
| + rt_up_read(sem); |
| +} |
| + |
| +static inline void up_write(struct rw_semaphore *sem) |
| +{ |
| + rt_up_write(sem); |
| +} |
| + |
| +static inline void downgrade_write(struct rw_semaphore *sem) |
| +{ |
| + rt_downgrade_write(sem); |
| +} |
| + |
| +static inline void down_read_nested(struct rw_semaphore *sem, int subclass) |
| +{ |
| + return rt_down_read_nested(sem, subclass); |
| +} |
| + |
| +static inline void down_write_nested(struct rw_semaphore *sem, int subclass) |
| +{ |
| + rt_down_write_nested(sem, subclass); |
| +} |
| +#ifdef CONFIG_DEBUG_LOCK_ALLOC |
| +static inline void down_write_nest_lock(struct rw_semaphore *sem, |
| + struct rw_semaphore *nest_lock) |
| +{ |
| + rt_down_write_nested_lock(sem, &nest_lock->dep_map); |
| +} |
| + |
| +#else |
| + |
| +static inline void down_write_nest_lock(struct rw_semaphore *sem, |
| + struct rw_semaphore *nest_lock) |
| +{ |
| + rt_down_write_nested_lock(sem, NULL); |
| +} |
| +#endif |
| +#endif |
| --- a/lib/Makefile |
| +++ b/lib/Makefile |
| @@ -38,8 +38,11 @@ obj-$(CONFIG_HAS_IOMEM) += iomap_copy.o |
| obj-$(CONFIG_CHECK_SIGNATURE) += check_signature.o |
| obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) += locking-selftest.o |
| obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o |
| + |
| +ifneq ($(CONFIG_PREEMPT_RT_FULL),y) |
| lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o |
| lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o |
| +endif |
| lib-$(CONFIG_PERCPU_RWSEM) += percpu-rwsem.o |
| |
| CFLAGS_hweight.o = $(subst $(quote),,$(CONFIG_ARCH_HWEIGHT_CFLAGS)) |