public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Ingo Molnar <mingo@elte.hu>
To: linux-kernel@vger.kernel.org, Linus Torvalds <torvalds@osdl.org>,
	Andrew Morton <akpm@osdl.org>
Cc: Arjan van de Ven <arjanv@infradead.org>,
	Steven Rostedt <rostedt@goodmis.org>,
	Alan Cox <alan@lxorguk.ukuu.org.uk>,
	Christoph Hellwig <hch@infradead.org>, Andi Kleen <ak@suse.de>,
	David Howells <dhowells@redhat.com>,
	Alexander Viro <viro@ftp.linux.org.uk>,
	Oleg Nesterov <oleg@tv-sign.ru>, Paul Jackson <pj@sgi.com>
Subject: [patch 10/15] Generic Mutex Subsystem, mutex-migration-helper-core.patch
Date: Mon, 19 Dec 2005 02:38:37 +0100	[thread overview]
Message-ID: <20051219013837.GF28038@elte.hu> (raw)


introduce the mutex_debug type, and switch the semaphore APIs to it in a 
type-sensitive way. Plain semaphores will still use the proper 
arch-semaphore calls.

Signed-off-by: Ingo Molnar <mingo@elte.hu>

----

 include/linux/mutex.h     |  116 ++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/semaphore.h |   64 +++++++++++++++++++++++++
 kernel/mutex.c            |   73 ++++++++++++++++++++++++++++
 lib/Kconfig.debug         |   28 +++++++++++
 lib/semaphore-sleepers.c  |   16 ++++--
 5 files changed, 293 insertions(+), 4 deletions(-)

Index: linux/include/linux/mutex.h
===================================================================
--- linux.orig/include/linux/mutex.h
+++ linux/include/linux/mutex.h
@@ -99,4 +99,120 @@ extern int FASTCALL(mutex_trylock(struct
 extern void FASTCALL(mutex_unlock(struct mutex *lock));
 extern int FASTCALL(mutex_is_locked(struct mutex *lock));
 
+/*
+ * Debugging variant of mutexes. The only difference is that they accept
+ * the semaphore APIs too:
+ */
+struct mutex_debug {
+	struct mutex lock;
+};
+
+#define DEFINE_MUTEX_DEBUG(mutexname) \
+	struct mutex_debug mutexname = \
+		{ .lock = __MUTEX_INITIALIZER(mutexname.lock) }
+
+extern void FASTCALL(mutex_debug_down(struct mutex_debug *lock));
+extern int FASTCALL(mutex_debug_down_interruptible(struct mutex_debug *lock));
+extern int FASTCALL(mutex_debug_down_trylock(struct mutex_debug *lock));
+extern void FASTCALL(mutex_debug_up(struct mutex_debug *lock));
+extern int FASTCALL(mutex_debug_sem_is_locked(struct mutex_debug *lock));
+
+/*
+ * The down()/up() type-safe wrappers, for debug mutexes:
+ */
+
+extern int __bad_mutex_debug_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_mutex_debug_func_type();				\
+} while (0)
+
+#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_mutex_debug_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_mutex_debug_func_type();				\
+} while (0)
+
+#define sema_init(sem, val) \
+	PICK_FUNC_2ARG(struct arch_semaphore, struct mutex_debug, \
+		arch_sema_init, mutex_debug_sema_init, sem, val)
+
+#define init_MUTEX(sem) \
+	PICK_FUNC_1ARG(struct arch_semaphore, struct mutex_debug, \
+		arch_init_MUTEX, mutex_debug_init_MUTEX, sem)
+
+#define init_MUTEX_LOCKED(sem) \
+	PICK_FUNC_1ARG(struct arch_semaphore, struct mutex_debug, \
+		arch_init_MUTEX_LOCKED, mutex_debug_init_MUTEX_LOCKED, sem)
+
+#define down(sem) \
+	PICK_FUNC_1ARG(struct arch_semaphore, struct mutex_debug, \
+		arch_down, mutex_debug_down, sem)
+
+#define down_interruptible(sem) \
+	PICK_FUNC_1ARG_RET(struct arch_semaphore, struct mutex_debug, \
+		arch_down_interruptible, mutex_debug_down_interruptible, sem)
+
+#define down_trylock(sem) \
+	PICK_FUNC_1ARG_RET(struct arch_semaphore, struct mutex_debug, \
+		arch_down_trylock, mutex_debug_down_trylock, sem)
+
+#define up(sem) \
+	PICK_FUNC_1ARG(struct arch_semaphore, struct mutex_debug, \
+		arch_up, mutex_debug_up, sem)
+
+#define sem_is_locked(sem) \
+	PICK_FUNC_1ARG_RET(struct arch_semaphore, struct mutex_debug, \
+		arch_sem_is_locked, mutex_debug_sem_is_locked, sem)
+
+#define sema_count(sem) \
+	PICK_FUNC_1ARG_RET(struct arch_semaphore, struct mutex_debug, \
+		arch_sema_count, mutex_debug_sema_count, sem)
+
+#ifdef CONFIG_DEBUG_MUTEXESS
+  extern FASTCALL(void __mutex_debug_sema_init(struct mutex_debug *lock,
+		  int val, char *name, char *file, int line));
+# define mutex_debug_sema_init(sem, val) \
+		__mutex_debug_sema_init(sem, val, #sem, __FILE__, __LINE__)
+#else
+  extern FASTCALL(void __mutex_debug_sema_init(struct mutex_debug *lock, int val));
+# define mutex_debug_sema_init(sem, val) \
+		__mutex_debug_sema_init(sem, val)
+#endif
+
+#define mutex_debug_init_MUTEX(sem) mutex_debug_sema_init(sem, 1)
+
+/*
+ * No locked initialization for mutexes:
+ */
+extern void there_is_no_init_MUTEX_LOCKED_for_mutexes(void);
+
+#define mutex_debug_init_MUTEX_LOCKED(sem) \
+		there_is_no_init_MUTEX_LOCKED_for_mutexes()
+
 #endif
Index: linux/include/linux/semaphore.h
===================================================================
--- /dev/null
+++ linux/include/linux/semaphore.h
@@ -0,0 +1,64 @@
+#ifndef _LINUX_SEMAPHORE_H
+#define _LINUX_SEMAPHORE_H
+
+#include <linux/config.h>
+#include <linux/mutex.h>
+
+#ifdef CONFIG_DEBUG_MUTEX_FULL
+# define semaphore		mutex_debug
+# define DECLARE_MUTEX		DEFINE_MUTEX_DEBUG
+#else
+# define DECLARE_MUTEX		ARCH_DECLARE_MUTEX
+#endif
+
+# define DECLARE_MUTEX_LOCKED	ARCH_DECLARE_MUTEX_LOCKED
+
+#if 0
+#ifdef CONFIG_GENERIC_MUTEXES
+# include <linux/mutex.h>
+#else
+
+#define DECLARE_MUTEX		ARCH_DECLARE_MUTEX
+#define DECLARE_MUTEX_LOCKED	ARCH_DECLARE_MUTEX_LOCKED
+
+static inline void sema_init(struct arch_semaphore *sem, int val)
+{
+	arch_sema_init(sem, val);
+}
+static inline void init_MUTEX(struct arch_semaphore *sem)
+{
+	arch_init_MUTEX(sem);
+}
+static inline void init_MUTEX_LOCKED(struct arch_semaphore *sem)
+{
+	arch_init_MUTEX_LOCKED(sem);
+}
+static inline void down(struct arch_semaphore *sem)
+{
+	arch_down(sem);
+}
+static inline int down_interruptible(struct arch_semaphore *sem)
+{
+	return arch_down_interruptible(sem);
+}
+static inline int down_trylock(struct arch_semaphore *sem)
+{
+	return arch_down_trylock(sem);
+}
+static inline void up(struct arch_semaphore *sem)
+{
+	arch_up(sem);
+}
+static inline int sem_is_locked(struct arch_semaphore *sem)
+{
+	return arch_sem_is_locked(sem);
+}
+static inline int sema_count(struct arch_semaphore *sem)
+{
+	return arch_sema_count(sem);
+}
+
+#endif /* CONFIG_GENERIC_MUTEXES */
+#endif
+
+#endif /* _LINUX_SEMAPHORE_H */
Index: linux/kernel/mutex.c
===================================================================
--- linux.orig/kernel/mutex.c
+++ linux/kernel/mutex.c
@@ -562,3 +562,76 @@ void fastcall __mutex_init(struct mutex 
 
 }
 EXPORT_SYMBOL_GPL(__mutex_init);
+
+/*
+ * Semaphore-compatible API wrappers:
+ */
+
+#ifdef CONFIG_DEBUG_MUTEXESS
+void fastcall
+__mutex_debug_sema_init(struct mutex_debug *lock, int val, char *name,
+			char *file, int line)
+{
+	__mutex_init(&lock->lock, name, file, line);
+
+	DEBUG_WARN_ON(val != 0 && val != 1);
+	if (!val)
+		__mutex_lock(&lock->lock __CALLER_IP__);
+}
+#else
+void fastcall __mutex_debug_sema_init(struct mutex_debug *lock, int val)
+{
+	__mutex_init(&lock->lock);
+
+	DEBUG_WARN_ON(val != 0 && val != 1);
+	if (!val)
+		__mutex_lock(&lock->lock __CALLER_IP__);
+}
+#endif
+
+EXPORT_SYMBOL(__mutex_debug_sema_init);
+
+void fastcall mutex_debug_down(struct mutex_debug *lock)
+{
+	DEBUG_WARN_ON(in_interrupt());
+	__mutex_lock(&lock->lock __CALLER_IP__);
+}
+EXPORT_SYMBOL(mutex_debug_down);
+
+int fastcall mutex_debug_down_interruptible(struct mutex_debug *lock)
+{
+	DEBUG_WARN_ON(in_interrupt());
+	return __mutex_lock_interruptible(&lock->lock, 0 __CALLER_IP__);
+}
+EXPORT_SYMBOL(mutex_debug_down_interruptible);
+
+/*
+ * try to down the mutex, 0 on success and 1 on failure. (inverted)
+ */
+int fastcall mutex_debug_down_trylock(struct mutex_debug *lock)
+{
+	DEBUG_WARN_ON(in_interrupt());
+	/*
+	 * Trylock semantics of semaphores are inverted that of spinlocks
+	 * and mutexes:
+	 */
+	if (__mutex_trylock(&lock->lock __CALLER_IP__))
+		return 0;
+	return 1;
+}
+EXPORT_SYMBOL(mutex_debug_down_trylock);
+
+void fastcall mutex_debug_up(struct mutex_debug *lock)
+{
+	DEBUG_WARN_ON(in_interrupt());
+	__mutex_unlock(&lock->lock __CALLER_IP__);
+}
+EXPORT_SYMBOL(mutex_debug_up);
+
+int fastcall mutex_debug_sem_is_locked(struct mutex_debug *lock)
+{
+	DEBUG_WARN_ON(in_interrupt());
+	return mutex_is_locked(&lock->lock);
+}
+EXPORT_SYMBOL(mutex_debug_sem_is_locked);
+
Index: linux/lib/Kconfig.debug
===================================================================
--- linux.orig/lib/Kconfig.debug
+++ linux/lib/Kconfig.debug
@@ -95,6 +95,34 @@ config DEBUG_PREEMPT
 	  if kernel code uses it in a preemption-unsafe way. Also, the kernel
 	  will detect preemption count underflows.
 
+config GENERIC_MUTEXES
+	bool
+	depends on ARCH_SEMAPHORES
+	default y
+
+choice
+	prompt "Mutex Debugging Mode"
+	default DEBUG_NONE
+	depends on ARCH_SEMAPHORES
+
+config DEBUG_MUTEX_NONE
+	bool "Off"
+	help
+	  No runtime checking of semaphores. Fastest mode.
+
+config DEBUG_MUTEX_PARTIAL
+	bool "Partial"
+	help
+	  Check mutexes that have been marked as mutexes explicitly.
+
+config DEBUG_MUTEX_FULL
+	bool "Full"
+	help
+	  Check all mutexes and semaphores. (except the handful of
+	  semaphores that have been explicitly marked as non-debug)
+
+endchoice
+
 config DEBUG_MUTEXESS
         bool "Mutex debugging, deadlock detection"
         default y
Index: linux/lib/semaphore-sleepers.c
===================================================================
--- linux.orig/lib/semaphore-sleepers.c
+++ linux/lib/semaphore-sleepers.c
@@ -16,6 +16,7 @@
 #include <linux/sched.h>
 #include <linux/err.h>
 #include <linux/init.h>
+#include <linux/module.h>
 #include <asm/semaphore.h>
 
 /*
@@ -49,12 +50,12 @@
  *    we cannot lose wakeup events.
  */
 
-fastcall void __up(struct semaphore *sem)
+fastcall void __up(struct arch_semaphore *sem)
 {
 	wake_up(&sem->wait);
 }
 
-fastcall void __sched __down(struct semaphore * sem)
+fastcall void __sched __down(struct arch_semaphore * sem)
 {
 	struct task_struct *tsk = current;
 	DECLARE_WAITQUEUE(wait, tsk);
@@ -91,7 +92,7 @@ fastcall void __sched __down(struct sema
 	tsk->state = TASK_RUNNING;
 }
 
-fastcall int __sched __down_interruptible(struct semaphore * sem)
+fastcall int __sched __down_interruptible(struct arch_semaphore * sem)
 {
 	int retval = 0;
 	struct task_struct *tsk = current;
@@ -154,7 +155,7 @@ fastcall int __sched __down_interruptibl
  * single "cmpxchg" without failure cases,
  * but then it wouldn't work on a 386.
  */
-fastcall int __down_trylock(struct semaphore * sem)
+fastcall int __down_trylock(struct arch_semaphore * sem)
 {
 	int sleepers;
 	unsigned long flags;
@@ -175,3 +176,10 @@ fastcall int __down_trylock(struct semap
 	spin_unlock_irqrestore(&sem->wait.lock, flags);
 	return 1;
 }
+
+int fastcall arch_sem_is_locked(struct arch_semaphore *sem)
+{
+	return (int) atomic_read(&sem->count) < 0;
+}
+
+EXPORT_SYMBOL(arch_sem_is_locked);

             reply	other threads:[~2005-12-19  1:39 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-12-19  1:38 Ingo Molnar [this message]
2005-12-19 14:12 ` [patch 10/15] Generic Mutex Subsystem, mutex-migration-helper-core.patch Steven Rostedt
2005-12-19 16:38   ` Ingo Molnar
2005-12-19 14:16 ` Steven Rostedt
2005-12-19 16:39   ` Ingo Molnar
2005-12-19 14:25 ` Steven Rostedt
2005-12-19 16:41   ` Ingo Molnar
2005-12-19 15:00 ` Christoph Hellwig
2005-12-19 15:35   ` Steven Rostedt
2005-12-20  4:48   ` Ingo Molnar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20051219013837.GF28038@elte.hu \
    --to=mingo@elte.hu \
    --cc=ak@suse.de \
    --cc=akpm@osdl.org \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=arjanv@infradead.org \
    --cc=dhowells@redhat.com \
    --cc=hch@infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=oleg@tv-sign.ru \
    --cc=pj@sgi.com \
    --cc=rostedt@goodmis.org \
    --cc=torvalds@osdl.org \
    --cc=viro@ftp.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox