2007-08-28 21:40:53

by Daniel Walker

[permalink] [raw]
Subject: [PATCH -rt 1/8] introduce PICK_FUNCTION

PICK_FUNCTION() is similar to the other PICK_OP style macros, and was
created to replace them all. I used variable argument macros to handle
PICK_FUNC_2ARG/PICK_FUNC_1ARG. Otherwise the marcos are similar to the
original macros used for semaphores. The entire system is used to do a
compile time switch between two different locking APIs. For example,
real spinlocks (raw_spinlock_t) and mutexes (or sleeping spinlocks).

This new macro replaces all the duplication from lock type to lock type.
The result of this patch, and the next two, is a fairly nice simplification,
and consolidation. Although the seqlock changes are larger than the originals
I think over all the patchset is worth while.

Incorporated peterz's suggestion to not require TYPE_EQUAL() to only
use pointers.

Signed-off-by: Daniel Walker <[email protected]>

---
include/linux/pickop.h | 36 +++++++++++++
include/linux/rt_lock.h | 129 +++++++++++++++---------------------------------
2 files changed, 77 insertions(+), 88 deletions(-)

Index: linux-2.6.22/include/linux/pickop.h
===================================================================
--- /dev/null
+++ linux-2.6.22/include/linux/pickop.h
@@ -0,0 +1,36 @@
+#ifndef _LINUX_PICKOP_H
+#define _LINUX_PICKOP_H
+
+#undef TYPE_EQUAL
+#define TYPE_EQUAL(var, type) \
+ __builtin_types_compatible_p(typeof(var), type *)
+
+#undef PICK_TYPE_EQUAL
+#define PICK_TYPE_EQUAL(var, type) \
+ __builtin_types_compatible_p(typeof(var), type)
+
+extern int __bad_func_type(void);
+
+#define PICK_FUNCTION(type1, type2, func1, func2, arg0, ...) \
+do { \
+ if (PICK_TYPE_EQUAL((arg0), type1)) \
+ func1((type1)(arg0), ##__VA_ARGS__); \
+ else if (PICK_TYPE_EQUAL((arg0), type2)) \
+ func2((type2)(arg0), ##__VA_ARGS__); \
+ else __bad_func_type(); \
+} while (0)
+
+#define PICK_FUNCTION_RET(type1, type2, func1, func2, arg0, ...) \
+({ \
+ unsigned long __ret; \
+ \
+ if (PICK_TYPE_EQUAL((arg0), type1)) \
+ __ret = func1((type1)(arg0), ##__VA_ARGS__); \
+ else if (PICK_TYPE_EQUAL((arg0), type2)) \
+ __ret = func2((type2)(arg0), ##__VA_ARGS__); \
+ else __ret = __bad_func_type(); \
+ \
+ __ret; \
+})
+
+#endif /* _LINUX_PICKOP_H */
Index: linux-2.6.22/include/linux/rt_lock.h
===================================================================
--- linux-2.6.22.orig/include/linux/rt_lock.h
+++ linux-2.6.22/include/linux/rt_lock.h
@@ -156,76 +156,40 @@ extern void fastcall rt_up(struct semaph

extern int __bad_func_type(void);

-#undef TYPE_EQUAL
-#define TYPE_EQUAL(var, type) \
- __builtin_types_compatible_p(typeof(var), type *)
-
-#define PICK_FUNC_1ARG(type1, type2, func1, func2, arg) \
-do { \
- if (TYPE_EQUAL((arg), type1)) \
- func1((type1 *)(arg)); \
- else if (TYPE_EQUAL((arg), type2)) \
- func2((type2 *)(arg)); \
- else __bad_func_type(); \
-} while (0)
+#include <linux/pickop.h>

-#define PICK_FUNC_1ARG_RET(type1, type2, func1, func2, arg) \
-({ \
- unsigned long __ret; \
- \
- if (TYPE_EQUAL((arg), type1)) \
- __ret = func1((type1 *)(arg)); \
- else if (TYPE_EQUAL((arg), type2)) \
- __ret = func2((type2 *)(arg)); \
- else __ret = __bad_func_type(); \
- \
- __ret; \
-})
-
-#define PICK_FUNC_2ARG(type1, type2, func1, func2, arg0, arg1) \
-do { \
- if (TYPE_EQUAL((arg0), type1)) \
- func1((type1 *)(arg0), arg1); \
- else if (TYPE_EQUAL((arg0), type2)) \
- func2((type2 *)(arg0), arg1); \
- else __bad_func_type(); \
-} while (0)
+/*
+ * PICK_SEM_OP() is a small redirector to allow less typing of the lock
+ * types struct compat_semaphore, struct semaphore, at the front of the
+ * PICK_FUNCTION macro.
+ */
+#define PICK_SEM_OP(...) PICK_FUNCTION(struct compat_semaphore *, \
+ struct semaphore *, ##__VA_ARGS__)
+#define PICK_SEM_OP_RET(...) PICK_FUNCTION_RET(struct compat_semaphore *,\
+ struct semaphore *, ##__VA_ARGS__)

#define sema_init(sem, val) \
- PICK_FUNC_2ARG(struct compat_semaphore, struct semaphore, \
- compat_sema_init, rt_sema_init, sem, val)
+ PICK_SEM_OP(compat_sema_init, rt_sema_init, sem, val)

-#define init_MUTEX(sem) \
- PICK_FUNC_1ARG(struct compat_semaphore, struct semaphore, \
- compat_init_MUTEX, rt_init_MUTEX, sem)
+#define init_MUTEX(sem) PICK_SEM_OP(compat_init_MUTEX, rt_init_MUTEX, sem)

#define init_MUTEX_LOCKED(sem) \
- PICK_FUNC_1ARG(struct compat_semaphore, struct semaphore, \
- compat_init_MUTEX_LOCKED, rt_init_MUTEX_LOCKED, sem)
+ PICK_SEM_OP(compat_init_MUTEX_LOCKED, rt_init_MUTEX_LOCKED, sem)

-#define down(sem) \
- PICK_FUNC_1ARG(struct compat_semaphore, struct semaphore, \
- compat_down, rt_down, sem)
+#define down(sem) PICK_SEM_OP(compat_down, rt_down, sem)

#define down_interruptible(sem) \
- PICK_FUNC_1ARG_RET(struct compat_semaphore, struct semaphore, \
- compat_down_interruptible, rt_down_interruptible, sem)
+ PICK_SEM_OP_RET(compat_down_interruptible, rt_down_interruptible, sem)

#define down_trylock(sem) \
- PICK_FUNC_1ARG_RET(struct compat_semaphore, struct semaphore, \
- compat_down_trylock, rt_down_trylock, sem)
+ PICK_SEM_OP_RET(compat_down_trylock, rt_down_trylock, sem)

-#define up(sem) \
- PICK_FUNC_1ARG(struct compat_semaphore, struct semaphore, \
- compat_up, rt_up, sem)
+#define up(sem) PICK_SEM_OP(compat_up, rt_up, sem)

#define sem_is_locked(sem) \
- PICK_FUNC_1ARG_RET(struct compat_semaphore, struct semaphore, \
- compat_sem_is_locked, rt_sem_is_locked, sem)
+ PICK_SEM_OP_RET(compat_sem_is_locked, rt_sem_is_locked, sem)

-#define sema_count(sem) \
- PICK_FUNC_1ARG_RET(struct compat_semaphore, struct semaphore, \
- compat_sema_count, rt_sema_count, sem)
+#define sema_count(sem) PICK_SEM_OP_RET(compat_sema_count, rt_sema_count, sem)

/*
* rwsems:
@@ -272,58 +236,47 @@ extern void fastcall rt_downgrade_write(

# define rt_rwsem_is_locked(rws) (rt_mutex_is_locked(&(rws)->lock))

-#define init_rwsem(rwsem) \
- PICK_FUNC_1ARG(struct compat_rw_semaphore, struct rw_semaphore, \
- compat_init_rwsem, rt_init_rwsem, rwsem)
-
-#define down_read(rwsem) \
- PICK_FUNC_1ARG(struct compat_rw_semaphore, struct rw_semaphore, \
- compat_down_read, rt_down_read, rwsem)
+#define PICK_RWSEM_OP(...) PICK_FUNCTION(struct compat_rw_semaphore *, \
+ struct rw_semaphore *, ##__VA_ARGS__)
+#define PICK_RWSEM_OP_RET(...) PICK_FUNCTION_RET(struct compat_rw_semaphore *,\
+ struct rw_semaphore *, ##__VA_ARGS__)
+
+#define init_rwsem(rwsem) PICK_RWSEM_OP(compat_init_rwsem, rt_init_rwsem, rwsem)
+
+#define down_read(rwsem) PICK_RWSEM_OP(compat_down_read, rt_down_read, rwsem)

#define down_read_non_owner(rwsem) \
- PICK_FUNC_1ARG(struct compat_rw_semaphore, struct rw_semaphore, \
- compat_down_read_non_owner, rt_down_read_non_owner, rwsem)
+ PICK_RWSEM_OP(compat_down_read_non_owner, rt_down_read_non_owner, rwsem)

#define down_read_trylock(rwsem) \
- PICK_FUNC_1ARG_RET(struct compat_rw_semaphore, struct rw_semaphore, \
- compat_down_read_trylock, rt_down_read_trylock, rwsem)
+ PICK_RWSEM_OP_RET(compat_down_read_trylock, rt_down_read_trylock, rwsem)

-#define down_write(rwsem) \
- PICK_FUNC_1ARG(struct compat_rw_semaphore, struct rw_semaphore, \
- compat_down_write, rt_down_write, rwsem)
+#define down_write(rwsem) PICK_RWSEM_OP(compat_down_write, rt_down_write, rwsem)

#define down_read_nested(rwsem, subclass) \
- PICK_FUNC_2ARG(struct compat_rw_semaphore, struct rw_semaphore, \
- compat_down_read_nested, rt_down_read_nested, rwsem, subclass)
-
+ PICK_RWSEM_OP(compat_down_read_nested, rt_down_read_nested, \
+ rwsem, subclass)

#define down_write_nested(rwsem, subclass) \
- PICK_FUNC_2ARG(struct compat_rw_semaphore, struct rw_semaphore, \
- compat_down_write_nested, rt_down_write_nested, rwsem, subclass)
+ PICK_RWSEM_OP(compat_down_write_nested, rt_down_write_nested, \
+ rwsem, subclass)

#define down_write_trylock(rwsem) \
- PICK_FUNC_1ARG_RET(struct compat_rw_semaphore, struct rw_semaphore, \
- compat_down_write_trylock, rt_down_write_trylock, rwsem)
+ PICK_RWSEM_OP_RET(compat_down_write_trylock, rt_down_write_trylock,\
+ rwsem)

-#define up_read(rwsem) \
- PICK_FUNC_1ARG(struct compat_rw_semaphore, struct rw_semaphore, \
- compat_up_read, rt_up_read, rwsem)
+#define up_read(rwsem) PICK_RWSEM_OP(compat_up_read, rt_up_read, rwsem)

#define up_read_non_owner(rwsem) \
- PICK_FUNC_1ARG(struct compat_rw_semaphore, struct rw_semaphore, \
- compat_up_read_non_owner, rt_up_read_non_owner, rwsem)
+ PICK_RWSEM_OP(compat_up_read_non_owner, rt_up_read_non_owner, rwsem)

-#define up_write(rwsem) \
- PICK_FUNC_1ARG(struct compat_rw_semaphore, struct rw_semaphore, \
- compat_up_write, rt_up_write, rwsem)
+#define up_write(rwsem) PICK_RWSEM_OP(compat_up_write, rt_up_write, rwsem)

#define downgrade_write(rwsem) \
- PICK_FUNC_1ARG(struct compat_rw_semaphore, struct rw_semaphore, \
- compat_downgrade_write, rt_downgrade_write, rwsem)
+ PICK_RWSEM_OP(compat_downgrade_write, rt_downgrade_write, rwsem)

#define rwsem_is_locked(rwsem) \
- PICK_FUNC_1ARG_RET(struct compat_rw_semaphore, struct rw_semaphore, \
- compat_rwsem_is_locked, rt_rwsem_is_locked, rwsem)
+ PICK_RWSEM_OP_RET(compat_rwsem_is_locked, rt_rwsem_is_locked, rwsem)

#endif /* CONFIG_PREEMPT_RT */


--


2007-08-28 23:44:51

by Nick Piggin

[permalink] [raw]
Subject: Re: [PATCH -rt 1/8] introduce PICK_FUNCTION

Daniel Walker wrote:
> PICK_FUNCTION() is similar to the other PICK_OP style macros, and was
> created to replace them all. I used variable argument macros to handle
> PICK_FUNC_2ARG/PICK_FUNC_1ARG. Otherwise the marcos are similar to the
> original macros used for semaphores. The entire system is used to do a
> compile time switch between two different locking APIs. For example,
> real spinlocks (raw_spinlock_t) and mutexes (or sleeping spinlocks).
>
> This new macro replaces all the duplication from lock type to lock type.
> The result of this patch, and the next two, is a fairly nice simplification,
> and consolidation. Although the seqlock changes are larger than the originals
> I think over all the patchset is worth while.
>
> Incorporated peterz's suggestion to not require TYPE_EQUAL() to only
> use pointers.

How come this is cc'ed to lkml? Is it something that is relevant to
the mainline kernel... or?

--
SUSE Labs, Novell Inc.

2007-08-29 00:03:17

by Daniel Walker

[permalink] [raw]
Subject: Re: [PATCH -rt 1/8] introduce PICK_FUNCTION

On Wed, 2007-08-29 at 09:44 +1000, Nick Piggin wrote:
> Daniel Walker wrote:
> > PICK_FUNCTION() is similar to the other PICK_OP style macros, and was
> > created to replace them all. I used variable argument macros to handle
> > PICK_FUNC_2ARG/PICK_FUNC_1ARG. Otherwise the marcos are similar to the
> > original macros used for semaphores. The entire system is used to do a
> > compile time switch between two different locking APIs. For example,
> > real spinlocks (raw_spinlock_t) and mutexes (or sleeping spinlocks).
> >
> > This new macro replaces all the duplication from lock type to lock type.
> > The result of this patch, and the next two, is a fairly nice simplification,
> > and consolidation. Although the seqlock changes are larger than the originals
> > I think over all the patchset is worth while.
> >
> > Incorporated peterz's suggestion to not require TYPE_EQUAL() to only
> > use pointers.
>
> How come this is cc'ed to lkml? Is it something that is relevant to
> the mainline kernel... or?

The real time changes are usually developed on lkml , that's how it's
been in the past. I personally like CC'ing lkml since real time can
sometimes touch lots of different subsystems .. So it good to have a
diverse set of people reviewing ..

Daniel