linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/19] MUTEX: Introduce simple mutex implementation
@ 2005-12-12 23:45 David Howells
  2005-12-12 23:45 ` [PATCH 2/19] MUTEX: i386 arch mutex David Howells
                   ` (32 more replies)
  0 siblings, 33 replies; 249+ messages in thread
From: David Howells @ 2005-12-12 23:45 UTC (permalink / raw)
  To: torvalds, akpm, hch, arjan, matthew; +Cc: linux-kernel, linux-arch

The attached patch introduces a simple mutex implementation as an alternative
to the usual semaphore implementation where simple mutex functionality is all
that is required.

This is useful in two ways:

 (1) A number of archs only provide very simple atomic instructions (such as
     XCHG on i386, TAS on M68K, SWAP on FRV) which aren't sufficient to
     implement full semaphore support directly. Instead spinlocks must be
     employed to implement fuller functionality.

 (2) This makes it obvious in what way the semaphore is being used: whether
     it's being used as a mutex or being used as a counter.

This patch set does the following:

 (1) Provides a simple xchg() based semaphore as a default for all
     architectures that don't wish to override it and provide their own.

     Overriding is possible by setting CONFIG_ARCH_IMPLEMENTS_MUTEX and
     supplying asm/mutex.h

     Partial overriding is possible by #defining mutex_grab(), mutex_release()
     and is_mutex_locked() to perform the appropriate optimised functions.

 (2) Provides linux/mutex.h as a common include for gaining access to mutex
     semaphores.

 (3) Provides linux/semaphore.h as a common include for gaining access to all
     the different types of semaphore that may be used from within the kernel.

 (4) Renames down*() to down_sem*() and up() to up_sem() for the traditional
     semaphores, and removes init_MUTEX*() and DECLARE_MUTEX*() from
     asm/semaphore.h

 (5) Redirects the following to apply to the new mutexes rather than the
     traditional semaphores:

	down()
	down_trylock()
	down_interruptible()
	up()
	init_MUTEX()
     	init_MUTEX_LOCKED()
	DECLARE_MUTEX()
	DECLARE_MUTEX_LOCKED()

     On the basis that most usages of semaphores are as mutexes, this makes
     sense for in most cases it's just then a matter of changing the type from
     struct semaphore to struct mutex. In some cases, sema_init() has to be
     changed to init_MUTEX*() also.

 (6) Generally include linux/semaphore.h in place of asm/semaphore.h.

 (7) Provides a debugging config option CONFIG_DEBUG_MUTEX_OWNER by which the
     mutex owner can be tracked and by which over-upping can be detected.

Signed-Off-By: David Howells <dhowells@redhat.com>
---
warthog>diffstat -p1 mutex-simple-2615rc5.diff
 include/linux/mutex-simple.h |  194 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/mutex.h        |   32 +++++++
 include/linux/semaphore.h    |   30 ++++++
 lib/Kconfig.debug            |    8 +
 lib/Makefile                 |    4 
 lib/mutex-simple.c           |  178 +++++++++++++++++++++++++++++++++++++++
 lib/semaphore-sleepers.c     |    8 -
 7 files changed, 450 insertions(+), 4 deletions(-)

diff -uNrp /warthog/kernels/linux-2.6.15-rc5/include/linux/semaphore.h linux-2.6.15-rc5-mutex/include/linux/semaphore.h
--- /warthog/kernels/linux-2.6.15-rc5/include/linux/semaphore.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.15-rc5-mutex/include/linux/semaphore.h	2005-12-12 22:03:53.000000000 +0000
@@ -0,0 +1,30 @@
+/* semaphore.h: include the various types of semaphore in one package
+ *
+ * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _LINUX_SEMAPHORE_H
+#define _LINUX_SEMAPHORE_H
+
+/*
+ * simple mutex semaphores
+ */
+#include <linux/mutex.h>
+
+/*
+ * multiple-count semaphores
+ */
+#include <asm/semaphore.h>
+
+/*
+ * read/write semaphores
+ */
+#include <linux/rwsem.h>
+
+#endif /* _LINUX_SEMAPHORE_H */
diff -uNrp /warthog/kernels/linux-2.6.15-rc5/include/linux/mutex.h linux-2.6.15-rc5-mutex/include/linux/mutex.h
--- /warthog/kernels/linux-2.6.15-rc5/include/linux/mutex.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.15-rc5-mutex/include/linux/mutex.h	2005-12-12 22:13:30.000000000 +0000
@@ -0,0 +1,32 @@
+/* mutex.h: mutex semaphore implementation base
+ *
+ * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _LINUX_MUTEX_H
+#define _LINUX_MUTEX_H
+
+#include <linux/config.h>
+
+#ifdef CONFIG_ARCH_IMPLEMENTS_MUTEX
+
+/*
+ * the arch wants to implement the whole mutex itself
+ */
+#include <asm/mutex.h>
+#else
+
+/*
+ * simple exchange-based mutex
+ * - the arch may override mutex_grab(), mutex_release() and is_mutex_locked()
+ *   to use something other than xchg() by #defining mutex_grab
+ */
+#include <linux/mutex-simple.h>
+#endif
+
+#endif /* _LINUX_MUTEX_H */
diff -uNrp /warthog/kernels/linux-2.6.15-rc5/include/linux/mutex-simple.h linux-2.6.15-rc5-mutex/include/linux/mutex-simple.h
--- /warthog/kernels/linux-2.6.15-rc5/include/linux/mutex-simple.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.15-rc5-mutex/include/linux/mutex-simple.h	2005-12-12 22:26:11.000000000 +0000
@@ -0,0 +1,194 @@
+/* mutex-simple.h: simple exchange-based mutexes
+ *
+ * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ *
+ * This doesn't require the arch to do anything for straightforward xchg()
+ * based mutexes
+ *
+ * If the sets CONFIG_ARCH_IMPLEMENTS_MUTEX then this implementation will not
+ * be used, and the arch should supply asm/mutex.h.
+ *
+ * If the arch defines mutex_grab(), mutex_release() and is_mutex_locked() for
+ * itself, then those will be used to provide the appropriate functionality
+ *
+ * See lib/mutex-simple.c for the slow-path implementation.
+ */
+#ifndef _LINUX_MUTEX_SIMPLE_H
+#define _LINUX_MUTEX_SIMPLE_H
+
+#ifndef _LINUX_MUTEX_H
+#error linux/mutex-xchg.h should not be included directly; use linux/mutex.h instead
+#endif
+
+#ifndef __ASSEMBLY__
+
+#include <linux/linkage.h>
+#include <linux/wait.h>
+#include <linux/spinlock.h>
+#include <asm/system.h>
+
+/*
+ * the mutex semaphore definition
+ * - if state is 0, then the mutex is available
+ * - if state is non-zero, then the mutex is busy
+ * - if wait_list is not empty, then there are processes waiting for the mutex
+ */
+struct mutex {
+	int			state;
+	spinlock_t		wait_lock;
+	struct list_head	wait_list;
+#ifdef CONFIG_DEBUG_MUTEX_OWNER
+	struct task_struct	*__owner;
+#endif
+};
+
+#ifndef mutex_grab
+/*
+ * mutex_grab() attempts to grab the mutex and returns true if successful
+ */
+#define mutex_grab(mutex)	(xchg(&(mutex)->state, 1) == 0)
+
+/*
+ * mutex_release() releases the mutex
+ */
+#define mutex_release(mutex)	do { (mutex)->state = 0; } while(0)
+
+/*
+ * is_mutex_locked() returns non-zero if the mutex is locked
+ */
+#define is_mutex_locked(mutex)	((mutex)->state)
+#endif
+
+#ifdef CONFIG_DEBUG_MUTEX_OWNER
+# define __MUTEX_OWNER_INIT(owner) , .__owner = (owner)
+#else
+# define __MUTEX_OWNER_INIT(owner)
+#endif
+
+#define __MUTEX_INITIALISER(name,_state,owner)			\
+{								\
+	.state		= (_state),				\
+	.wait_lock	= SPIN_LOCK_UNLOCKED,			\
+	.wait_list	= LIST_HEAD_INIT((name).wait_list)	\
+	__MUTEX_OWNER_INIT(owner)				\
+}
+
+#define __DECLARE_MUTEX_GENERIC(name, owner, state)			\
+	struct mutex name = __MUTEX_INITIALISER(name, owner, state)
+
+#define DECLARE_MUTEX(name) \
+	__DECLARE_MUTEX_GENERIC(name, 0, NULL)
+
+#define DECLARE_MUTEX_LOCKED(name, owner) \
+	__DECLARE_MUTEX_GENERIC(name, 1, (owner))
+
+static inline void mutex_init(struct mutex *mutex,
+			      unsigned state,
+			      struct task_struct *owner)
+{
+	mutex->state = state;
+	spin_lock_init(&mutex->wait_lock);
+	INIT_LIST_HEAD(&mutex->wait_list);
+#ifdef CONFIG_DEBUG_MUTEX_OWNER
+	mutex->__owner = owner;
+#endif
+}
+
+static inline void init_MUTEX(struct mutex *mutex)
+{
+	mutex_init(mutex, 0, NULL);
+}
+
+static inline void init_MUTEX_LOCKED (struct mutex *mutex)
+{
+	mutex_init(mutex, 1, current);
+}
+
+extern void __down(struct mutex *mutex);
+extern int  __down_interruptible(struct mutex *mutex);
+extern void __up(struct mutex *mutex);
+
+#ifdef CONFIG_DEBUG_MUTEX_OWNER
+extern void __up_bad(struct mutex *mutex);
+#endif
+
+/*
+ * sleep until we get the mutex
+ */
+static inline void down(struct mutex *mutex)
+{
+	if (mutex_grab(mutex)) {
+#ifdef CONFIG_DEBUG_MUTEX_OWNER
+		mutex->__owner = current;
+#endif
+	}
+	else {
+		__down(mutex);
+	}
+}
+
+/*
+ * sleep interruptibly until we get the mutex
+ * - return 0 if successful, -EINTR if interrupted
+ */
+static inline int down_interruptible(struct mutex *mutex)
+{
+	if (mutex_grab(mutex)) {
+#ifdef CONFIG_DEBUG_MUTEX_OWNER
+		mutex->__owner = current;
+#endif
+		return 0;
+	}
+
+	return __down_interruptible(mutex);
+}
+
+/*
+ * attempt to grab the mutex without waiting for it to become available
+ * - returns zero if we acquired it
+ */
+static inline int down_trylock(struct mutex *mutex)
+{
+	if (mutex_grab(mutex)) {
+		/* success */
+#ifdef CONFIG_DEBUG_MUTEX_OWNER
+		mutex->__owner = current;
+#endif
+		return 0;
+	}
+
+	/* failure */
+	return 1;
+}
+
+/*
+ * release the mutex
+ */
+static inline void up(struct mutex *mutex)
+{
+	unsigned long flags;
+
+#ifdef CONFIG_DEBUG_MUTEX_OWNER
+	if (mutex->__owner != current)
+		__up_bad(mutex);
+	mutex->__owner = NULL;
+#endif
+
+	/* must prevent a race */
+	spin_lock_irqsave(&mutex->wait_lock, flags);
+	if (!list_empty(&mutex->wait_list))
+		__up(mutex);
+	else
+		mutex_release(mutex);
+	spin_unlock_irqrestore(&mutex->wait_lock, flags);
+}
+
+#endif /* __ASSEMBLY__ */
+#endif /* _LINUX_MUTEX_SIMPLE_H */
diff -uNrp /warthog/kernels/linux-2.6.15-rc5/lib/Kconfig.debug linux-2.6.15-rc5-mutex/lib/Kconfig.debug
--- /warthog/kernels/linux-2.6.15-rc5/lib/Kconfig.debug	2005-12-08 16:23:56.000000000 +0000
+++ linux-2.6.15-rc5-mutex/lib/Kconfig.debug	2005-12-12 16:59:35.000000000 +0000
@@ -111,6 +111,14 @@ config DEBUG_SPINLOCK_SLEEP
 	  If you say Y here, various routines which may sleep will become very
 	  noisy if they are called with a spinlock held.
 
+config DEBUG_MUTEX_OWNER
+	bool "Mutex owner tracking and checking"
+	depends on DEBUG_KERNEL
+	help
+	  If you say Y here, the process currently owning a mutex will be
+	  remembered, and a warning will be issued if anyone other than that
+	  process releases it.
+
 config DEBUG_KOBJECT
 	bool "kobject debugging"
 	depends on DEBUG_KERNEL
diff -uNrp /warthog/kernels/linux-2.6.15-rc5/lib/Makefile linux-2.6.15-rc5-mutex/lib/Makefile
--- /warthog/kernels/linux-2.6.15-rc5/lib/Makefile	2005-12-08 16:23:56.000000000 +0000
+++ linux-2.6.15-rc5-mutex/lib/Makefile	2005-12-12 18:59:21.000000000 +0000
@@ -28,6 +28,10 @@ ifneq ($(CONFIG_HAVE_DEC_LOCK),y)
   lib-y += dec_and_lock.o
 endif
 
+ifneq ($(CONFIG_ARCH_IMPLEMENTS_MUTEX),y)
+  lib-y += mutex-simple.o
+endif
+
 obj-$(CONFIG_CRC_CCITT)	+= crc-ccitt.o
 obj-$(CONFIG_CRC16)	+= crc16.o
 obj-$(CONFIG_CRC32)	+= crc32.o
diff -uNrp /warthog/kernels/linux-2.6.15-rc5/lib/mutex-simple.c linux-2.6.15-rc5-mutex/lib/mutex-simple.c
--- /warthog/kernels/linux-2.6.15-rc5/lib/mutex-simple.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.15-rc5-mutex/lib/mutex-simple.c	2005-12-12 22:27:00.000000000 +0000
@@ -0,0 +1,178 @@
+/* mutex-simple.c: simple mutex slow paths
+ *
+ * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+
+struct mutex_waiter {
+	struct list_head	list;
+	struct task_struct	*task;
+};
+
+/*
+ * wait for a token to be granted from a mutex
+ */
+void __down(struct mutex *mutex)
+{
+	struct mutex_waiter waiter;
+	struct task_struct *tsk = current;
+	unsigned long flags;
+
+	/* set up my own style of waitqueue */
+	waiter.task = tsk;
+
+	spin_lock_irqsave(&mutex->wait_lock, flags);
+
+	if (mutex_grab(mutex)) {
+		/* we got the mutex anyway */
+		spin_unlock_irqrestore(&mutex->wait_lock, flags);
+		return;
+	}
+
+	/* need to sleep */
+	get_task_struct(tsk);
+	list_add_tail(&waiter.list, &mutex->wait_list);
+
+	/* we don't need to touch the mutex struct anymore */
+	spin_unlock_irqrestore(&mutex->wait_lock, flags);
+
+	/* wait to be given the mutex */
+	set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+
+	for (;;) {
+		if (list_empty(&waiter.list))
+			break;
+		schedule();
+		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+	}
+
+	tsk->state = TASK_RUNNING;
+}
+
+EXPORT_SYMBOL(__down);
+
+/*
+ * interruptibly wait for a token to be granted from a mutex
+ */
+int __down_interruptible(struct mutex *mutex)
+{
+	struct mutex_waiter waiter;
+	struct task_struct *tsk = current;
+	unsigned long flags;
+	int ret;
+
+	/* set up my own style of waitqueue */
+	waiter.task = tsk;
+
+	spin_lock_irqsave(&mutex->wait_lock, flags);
+
+	if (mutex_grab(mutex)) {
+		/* we got the mutex anyway */
+		spin_unlock_irqrestore(&mutex->wait_lock, flags);
+		return 0;
+	}
+
+	/* need to sleep */
+	get_task_struct(tsk);
+	list_add_tail(&waiter.list, &mutex->wait_list);
+
+	/* we don't need to touch the mutex struct anymore */
+	set_task_state(tsk, TASK_INTERRUPTIBLE);
+
+	spin_unlock_irqrestore(&mutex->wait_lock, flags);
+
+	/* wait to be given the mutex */
+	for (;;) {
+		if (list_empty(&waiter.list))
+			break;
+		if (unlikely(signal_pending(current)))
+			goto interrupted;
+		schedule();
+		set_task_state(tsk, TASK_INTERRUPTIBLE);
+	}
+
+	tsk->state = TASK_RUNNING;
+	return 0;
+
+interrupted:
+	spin_lock_irqsave(&mutex->wait_lock, flags);
+
+	/* we may still have been given the mutex */
+	ret = 0;
+	if (!list_empty(&waiter.list)) {
+		list_del(&waiter.list);
+		ret = -EINTR;
+	}
+
+	spin_unlock_irqrestore(&mutex->wait_lock, flags);
+	if (ret == -EINTR)
+		put_task_struct(current);
+	return ret;
+}
+
+EXPORT_SYMBOL(__down_interruptible);
+
+/*
+ * release a single token back to a mutex
+ * - entered with lock held and interrupts disabled
+ * - the queue will not be empty
+ */
+void __up(struct mutex *mutex)
+{
+	struct mutex_waiter *waiter;
+	struct task_struct *tsk;
+
+	/* grant the token to the process at the front of the queue */
+	waiter = list_entry(mutex->wait_list.next, struct mutex_waiter, list);
+
+	/* we must be careful not to touch 'waiter' after we set ->task = NULL.
+	 * - it is an allocated on the waiter's stack and may become invalid at
+	 *   any time after that point (due to a wakeup from another source).
+	 */
+	list_del_init(&waiter->list);
+	tsk = waiter->task;
+#ifdef CONFIG_DEBUG_MUTEX_OWNER
+	mutex->__owner = tsk;
+#endif
+	mb();
+	waiter->task = NULL;
+	wake_up_process(tsk);
+	put_task_struct(tsk);
+}
+
+EXPORT_SYMBOL(__up);
+
+/*
+ * report an up() that doesn't match a down()
+ */
+#ifdef CONFIG_DEBUG_MUTEX_OWNER
+void __up_bad(struct mutex *mutex)
+{
+	if (!mutex->__owner) {
+		printk(KERN_ERR
+		       "BUG: process %d [%s] releasing unowned mutex\n",
+		       current->pid,
+		       current->comm);
+	}
+	else {
+		printk(KERN_ERR
+		       "BUG: process %d [%s] releasing mutex owned by %d [%s]\n",
+		       current->pid,
+		       current->comm,
+		       mutex->__owner->pid,
+		       mutex->__owner->comm);
+	}
+}
+
+EXPORT_SYMBOL(__up_bad);
+#endif
diff -uNrp /warthog/kernels/linux-2.6.15-rc5/lib/semaphore-sleepers.c linux-2.6.15-rc5-mutex/lib/semaphore-sleepers.c
--- /warthog/kernels/linux-2.6.15-rc5/lib/semaphore-sleepers.c	2005-11-01 13:19:22.000000000 +0000
+++ linux-2.6.15-rc5-mutex/lib/semaphore-sleepers.c	2005-12-12 17:58:35.000000000 +0000
@@ -49,12 +49,12 @@
  *    we cannot lose wakeup events.
  */
 
-fastcall void __up(struct semaphore *sem)
+fastcall void __up_sem(struct semaphore *sem)
 {
 	wake_up(&sem->wait);
 }
 
-fastcall void __sched __down(struct semaphore * sem)
+fastcall void __sched __down_sem(struct semaphore * sem)
 {
 	struct task_struct *tsk = current;
 	DECLARE_WAITQUEUE(wait, tsk);
@@ -91,7 +91,7 @@ fastcall void __sched __down(struct sema
 	tsk->state = TASK_RUNNING;
 }
 
-fastcall int __sched __down_interruptible(struct semaphore * sem)
+fastcall int __sched __down_sem_interruptible(struct semaphore * sem)
 {
 	int retval = 0;
 	struct task_struct *tsk = current;
@@ -154,7 +154,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_sem_trylock(struct semaphore * sem)
 {
 	int sleepers;
 	unsigned long flags;

^ permalink raw reply	[flat|nested] 249+ messages in thread
* Re: [PATCH 1/19] MUTEX: Introduce simple mutex implementation
@ 2005-12-15 13:58 linux
  2005-12-15 16:15 ` Linus Torvalds
  0 siblings, 1 reply; 249+ messages in thread
From: linux @ 2005-12-15 13:58 UTC (permalink / raw)
  To: torvalds; +Cc: linux-kernel

Our Fearless Leader, in a fit of madness, intoned:
> A real semaphore is counting. 
> 
> Dammit, unless the pure mutex has a _huge_ performance advantage on major 
> architectures, we're not changing it. There's absolutely zero point. A 
> counting semaphore is a perfectly fine mutex - the fact that it can _also_ 
> be used to allow more than 1 user into a critical region and generally do 
> other things is totally immaterial.

You're being thick today.  Pay attention to the arguments.

A counting semaphore is NOT a perfectly fine mutex, and it SHOULD be changed.

People are indeed unhappy with the naming, and whether patching 95%
of the callers of up() and down() is a good idea is a valid and active
subject of debate.  (For an out-of-tree -rt patch, is was certaintly
an extremely practical solution.)

But regardless of the eventual naming convention, mutexes are a good idea.
A mutex is *safer* than a counting semaphore.  That's the main benefit.
Indeed, unless there's a performance advantage to a counting semaphore,
you should use a mutex!

It documents in the source what you're doing.  Using a counting semaphore
for a mutex is as silly as using a float for a loop index.  Even if
there isn't much speed penalty on modern processors.

Or perhaps I should compare it to using void * everywhere.  That's a
perfectly fine pointer; why type-check it?

A separate mutex type allows extra error-checking.  You can keep track
of the current holder (since there can be only one) and check that the
same person released it and didn't try to double-acquire it.

You can do priority inheritance, which is the main motivation for doing
this work in the -rt patches.

This isn't about speed, it's about bug-free code.  And having a mutex
abstraction distinct from a general counting semaphore is damn useful
error-checking, even if it is simply a thin wrapper over a counting
semaphore.  The only reason the code is full of counting semaphores
right now is that that's all people had.

Better to give them the right tool.

^ permalink raw reply	[flat|nested] 249+ messages in thread
* RE: [PATCH 1/19] MUTEX: Introduce simple mutex implementation
@ 2005-12-15 17:45 Luck, Tony
  2005-12-15 18:00 ` David Howells
                   ` (2 more replies)
  0 siblings, 3 replies; 249+ messages in thread
From: Luck, Tony @ 2005-12-15 17:45 UTC (permalink / raw)
  To: dhowells, Andrew Morton
  Cc: Mark Lord, tglx, alan, pj, mingo, hch, torvalds, arjan, matthew,
	linux-kernel, linux-arch

     Okay, spinlocks are null ops when CONFIG_SMP and CONFIG_DEBUG_SPINLOCK
     are both disabled, but you still have to disable interrupts, and that
     slows things down, sometimes quite appreciably. It is, for example,
     something I really want to avoid doing on FRV as it takes a *lot* of
     cycles.

There was a USENIX paper a couple of decades ago that described how
to do a fast s/w disable of interrupts on machines where really disabling
interrupts was expensive.  The rough gist was that the spl[1-7]()
functions would just set a flag in memory to hold the desired interrupt
mask.  If an interrupt actually occurred when it was s/w blocked, the
handler would set a pending flag, and just rfi with interrupts disabled.
Then the splx() code checked to see whether there was a pending interrupt
and dealt with it if there was.

-Tony

 

^ permalink raw reply	[flat|nested] 249+ messages in thread
* Re: [PATCH 1/19] MUTEX: Introduce simple mutex implementation
@ 2005-12-16 12:49 linux
  2005-12-16 15:24 ` David Howells
  0 siblings, 1 reply; 249+ messages in thread
From: linux @ 2005-12-16 12:49 UTC (permalink / raw)
  To: dhowells; +Cc: linux, linux-kernel

> Now my point about using LL/SC is that:
> 
> 	1,C,A	cmpxchg(0,1) [failed]
> 	1,C,A	cmpxchg(1,3) [success]
> 	3,C,A	...
> 
> Can be turned into:
> 
> 	1,C,A	x = LL()
> 	1,C,A	x |= 2;
> 	1,C,A	SC(3) [success]
> 	3,C,A	...

... which can be turned back into

 	1,C,A	x = load()
 	1,C,A	x' = x | 2;
 	1,C,A	cmpxchg(x,x') [success]
 	3,C,A	...

which will fail and retry in exactly the same contention cases as the
LL/SC.  The only thing that LL gives you that's nice is a hint that
an SC is due very soon and so resisting a cache eviction for a couple
of cycles might be a good idea.

The reason that we tend to do the former is optimism that the lock
won't be held.  If that's a bad assumption, make it more pessimistic.

LL/SC can detect double changes during the critical section, but it's
very similar in expressive power to load + CMPXCHG.

^ permalink raw reply	[flat|nested] 249+ messages in thread

end of thread, other threads:[~2005-12-22 12:48 UTC | newest]

Thread overview: 249+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-12-12 23:45 [PATCH 1/19] MUTEX: Introduce simple mutex implementation David Howells
2005-12-12 23:45 ` [PATCH 2/19] MUTEX: i386 arch mutex David Howells
2005-12-12 23:45 ` [PATCH 8/19] MUTEX: Drivers I-K changes David Howells
2005-12-12 23:45 ` [PATCH 7/19] MUTEX: Drivers F-H changes David Howells
2005-12-12 23:45 ` [PATCH 6/19] MUTEX: Drivers A-E changes David Howells
2005-12-12 23:45 ` [PATCH 3/19] MUTEX: x86_64 arch mutex David Howells
2005-12-12 23:45 ` [PATCH 5/19] MUTEX: Core kernel changes David Howells
2005-12-12 23:45 ` [PATCH 4/19] MUTEX: FRV arch mutex David Howells
2005-12-12 23:45 ` [PATCH 15/19] MUTEX: Second set of include changes David Howells
2005-12-12 23:45 ` [PATCH 10/19] MUTEX: Drivers N-P changes David Howells
2005-12-12 23:45 ` [PATCH 9/19] MUTEX: Drivers L-M changes David Howells
2005-12-12 23:45 ` [PATCH 13/19] MUTEX: Filesystem changes David Howells
2005-12-12 23:45 ` [PATCH 14/19] MUTEX: First set of include changes David Howells
2005-12-12 23:45 ` [PATCH 12/19] MUTEX: Drivers T-Z changes David Howells
2005-12-12 23:45 ` [PATCH 11/19] MUTEX: Drivers Q-S changes David Howells
2005-12-12 23:45 ` [PATCH 18/19] MUTEX: Security changes David Howells
2005-12-12 23:45 ` [PATCH 17/19] MUTEX: Networking changes David Howells
2005-12-12 23:45 ` [PATCH 16/19] MUTEX: IPC changes David Howells
2005-12-12 23:45 ` [PATCH 19/19] MUTEX: Sound changes David Howells
2005-12-13  0:13 ` [PATCH 1/19] MUTEX: Introduce simple mutex implementation Nick Piggin
2005-12-13  0:19 ` Nick Piggin
2005-12-13  0:19 ` Andrew Morton
2005-12-13  7:54   ` Ingo Molnar
2005-12-13  7:58     ` Andi Kleen
2005-12-13  8:42       ` Andrew Morton
2005-12-13  8:49         ` Andi Kleen
2005-12-13  9:01           ` Andrew Morton
2005-12-13  9:02             ` Andrew Morton
2005-12-13 10:07               ` Jakub Jelinek
2005-12-13 10:11                 ` Andi Kleen
2005-12-13 10:15                   ` Jakub Jelinek
2005-12-13 10:25                   ` Andrew Morton
2005-12-14 10:46               ` Russell King
2005-12-13  9:05             ` Andi Kleen
2005-12-13  9:15               ` Andrew Morton
2005-12-13  9:24                 ` Andi Kleen
2005-12-13  9:44                   ` Andrew Morton
2005-12-13  9:49                     ` Andi Kleen
2005-12-13 10:28                   ` Andreas Schwab
2005-12-13 10:30                     ` Andi Kleen
2005-12-13 12:33                   ` Matthew Wilcox
2005-12-13 22:18               ` Adrian Bunk
2005-12-13 22:25                 ` Andi Kleen
2005-12-13 22:32                   ` Adrian Bunk
2005-12-13  9:11             ` Ingo Molnar
2005-12-13  9:04           ` Christoph Hellwig
2005-12-13  9:13             ` Ingo Molnar
2005-12-13 10:11             ` Jakub Jelinek
2005-12-13 10:19               ` Christoph Hellwig
2005-12-13 10:27                 ` Ingo Molnar
2005-12-15  4:53                 ` Miles Bader
2005-12-15  5:05                   ` Nick Piggin
2005-12-13  9:09           ` Ingo Molnar
2005-12-13  9:21             ` Andi Kleen
2005-12-13 16:16           ` Linus Torvalds
2005-12-13 21:56             ` Using C99 in the kernel was " Andi Kleen
2005-12-13 23:05               ` Al Viro
2005-12-13 23:41                 ` Andi Kleen
2005-12-13  9:03         ` Christoph Hellwig
2005-12-13  9:14           ` Andrew Morton
2005-12-13  9:21             ` Christoph Hellwig
2005-12-13 10:31             ` drivers/scsi/sd.c gcc-2.95.3 Alexey Dobriyan
2005-12-13  8:00     ` [PATCH 1/19] MUTEX: Introduce simple mutex implementation Arjan van de Ven
2005-12-13  9:03       ` Ingo Molnar
2005-12-13  9:09         ` Andi Kleen
2005-12-13  9:34           ` Ingo Molnar
2005-12-13 14:33             ` Mark Lord
2005-12-13 14:45               ` Arjan van de Ven
2005-12-13  9:37           ` Ingo Molnar
2005-12-13  9:19         ` Arjan van de Ven
2005-12-13  9:02     ` Christoph Hellwig
2005-12-13  9:39       ` Ingo Molnar
2005-12-13 10:00         ` Ingo Molnar
2005-12-13 17:40           ` Paul Jackson
2005-12-13 18:34           ` David Howells
2005-12-13 22:31             ` Paul Jackson
2005-12-14 11:02             ` David Howells
2005-12-14 11:12             ` David Howells
2005-12-14 11:18               ` Alan Cox
2005-12-14 12:35               ` David Howells
2005-12-14 13:58                 ` Thomas Gleixner
2005-12-14 23:40                   ` Mark Lord
2005-12-14 23:54                     ` Andrew Morton
2005-12-15 13:41                       ` Nikita Danilov
2005-12-15 14:56                         ` Alan Cox
2005-12-15 15:52                           ` Nikita Danilov
2005-12-15 16:50                             ` Christopher Friesen
2005-12-15 20:53                               ` Steven Rostedt
2005-12-15 15:55                           ` David Howells
2005-12-15 16:22                             ` linux-os (Dick Johnson)
2005-12-15 16:28                             ` Linus Torvalds
2005-12-15 17:04                               ` Thomas Gleixner
2005-12-15 17:09                               ` Paul Jackson
2005-12-15 17:17                               ` David Howells
2005-12-15 16:51                             ` David Howells
2005-12-15 16:56                             ` Paul Jackson
2005-12-15 17:28                             ` David Howells
2005-12-15 17:48                               ` Linus Torvalds
2005-12-15 18:20                                 ` Nikita Danilov
2005-12-15 20:58                                   ` Steven Rostedt
2005-12-15 19:21                                 ` Andrew Morton
2005-12-15 19:38                                   ` Linus Torvalds
2005-12-15 20:28                                   ` Steven Rostedt
2005-12-15 20:32                                     ` Geert Uytterhoeven
2005-12-16 21:41                                       ` Thomas Gleixner
2005-12-16 21:41                                         ` Linus Torvalds
2005-12-16 22:06                                           ` Thomas Gleixner
2005-12-16 22:19                                             ` Linus Torvalds
2005-12-16 22:32                                               ` Steven Rostedt
2005-12-16 22:42                                               ` Thomas Gleixner
2005-12-16 22:41                                                 ` Linus Torvalds
2005-12-16 22:49                                                   ` Steven Rostedt
2005-12-16 23:29                                                   ` Thomas Gleixner
2005-12-17  0:29                                                   ` Joe Korty
2005-12-17  1:00                                                     ` Linus Torvalds
2005-12-17  3:13                                                       ` Steven Rostedt
2005-12-17  7:34                                                         ` Linus Torvalds
2005-12-17 23:43                                                           ` Matthew Wilcox
2005-12-18  0:05                                                             ` Lee Revell
2005-12-18  0:21                                                               ` Matthew Wilcox
2005-12-18  1:25                                                                 ` Lee Revell
2005-12-22 12:27                                                             ` Bill Huey
2005-12-19 16:08                                                           ` Ingo Molnar
2005-12-22 12:40                                                           ` Bill Huey
2005-12-22 12:45                                                             ` Bill Huey
2005-12-19 23:46                                                       ` Keith Owens
2005-12-15 14:41                       ` Steven Rostedt
2005-12-14 23:57                     ` Thomas Gleixner
2005-12-14 23:57                       ` Mark Lord
2005-12-15  0:10                         ` Thomas Gleixner
2005-12-15  2:46                           ` Linus Torvalds
2005-12-15 15:53                           ` David Howells
2005-12-15 15:37                     ` David Howells
2005-12-15 19:28                       ` Andrew Morton
2005-12-15 20:18                         ` Andrew Morton
2005-12-15 21:28                           ` Steven Rostedt
2005-12-16 22:02                           ` Thomas Gleixner
2005-12-16 10:45                         ` David Howells
2005-12-13  9:55     ` Ingo Molnar
2005-12-13  0:30 ` Arnd Bergmann
2005-12-13  0:57 ` Daniel Walker
2005-12-13  3:23   ` Steven Rostedt
2005-12-13  2:57 ` Mark Lord
2005-12-13  3:17   ` Steven Rostedt
2005-12-13  9:06   ` Christoph Hellwig
2005-12-13  9:54 ` David Howells
2005-12-13 10:13   ` Ingo Molnar
2005-12-13 10:34     ` Ingo Molnar
2005-12-13 10:37       ` Ingo Molnar
2005-12-13 12:47       ` Oliver Neukum
2005-12-13 13:09         ` Alan Cox
2005-12-13 13:13           ` Matthew Wilcox
2005-12-13 14:04             ` Alan Cox
2005-12-13 13:24           ` Oliver Neukum
2005-12-14  1:00   ` Nick Piggin
2005-12-14 10:54   ` David Howells
2005-12-14 11:17     ` Nick Piggin
2005-12-14 11:46     ` David Howells
2005-12-14 21:23       ` Nick Piggin
2005-12-16 12:00       ` David Howells
2005-12-16 13:16         ` Nick Piggin
2005-12-16 15:53         ` David Howells
2005-12-16 23:41           ` Nick Piggin
2005-12-16 16:02         ` David Howells
2005-12-13 10:48 ` David Howells
2005-12-13 12:39   ` Matthew Wilcox
2005-12-13 10:54 ` Ingo Molnar
2005-12-13 11:23 ` David Howells
2005-12-13 11:24 ` David Howells
2005-12-13 13:45   ` Ingo Molnar
2005-12-13 11:34 ` David Howells
2005-12-13 13:05 ` Alan Cox
2005-12-13 13:15   ` Alan Cox
2005-12-13 23:21     ` Nikita Danilov
2005-12-13 13:32 ` David Howells
2005-12-13 14:00   ` Alan Cox
2005-12-13 14:35   ` Christopher Friesen
2005-12-13 14:44     ` Arjan van de Ven
2005-12-13 14:59       ` Christopher Friesen
2005-12-13 15:23   ` David Howells
2005-12-15  5:24     ` Miles Bader
2005-12-13 15:39   ` David Howells
2005-12-13 16:10     ` Alan Cox
2005-12-14 10:29       ` Arjan van de Ven
2005-12-14 11:03         ` Arjan van de Ven
2005-12-14 11:03         ` Alan Cox
2005-12-14 11:08           ` Arjan van de Ven
2005-12-14 11:24             ` Alan Cox
2005-12-14 11:35               ` Andrew Morton
2005-12-14 11:44                 ` Arjan van de Ven
2005-12-14 11:52                   ` Andi Kleen
2005-12-14 11:55                     ` Arjan van de Ven
2005-12-14 11:57                 ` David Howells
2005-12-14 12:19                   ` Jakub Jelinek
2005-12-16  1:54                   ` Nick Piggin
2005-12-16 11:02                   ` David Howells
2005-12-16 13:01                     ` Nick Piggin
2005-12-16 13:21                       ` Russell King
2005-12-16 13:41                         ` Nick Piggin
2005-12-16 13:46                         ` Linh Dang
2005-12-16 14:31                           ` Russell King
2005-12-16 15:24                             ` Linh Dang
2005-12-16 15:35                               ` Nick Piggin
2005-12-16 15:40                               ` Kyle Moffett
2005-12-16 15:49                             ` Linh Dang
2005-12-16 15:46                           ` David Howells
2005-12-16 15:58                             ` Russell King
2005-12-17 15:57                       ` Nikita Danilov
2005-12-16 16:28                     ` Linus Torvalds
2005-12-16 11:30                   ` David Howells
2005-12-16 16:33                     ` Linus Torvalds
2005-12-16 22:23                       ` David S. Miller
2005-12-16 22:38                         ` Linus Torvalds
2005-12-16 22:53                           ` David S. Miller
2005-12-17  0:41                             ` Jesse Barnes
2005-12-17  7:10                               ` David S. Miller
2005-12-17  7:40                                 ` Linus Torvalds
2005-12-17 17:22                                   ` Jesse Barnes
2005-12-17 17:19                                 ` Jesse Barnes
2005-12-17 22:38                             ` Richard Henderson
2005-12-17 23:05                               ` David S. Miller
2005-12-14 12:17                 ` Christoph Hellwig
2005-12-14 11:42               ` Arjan van de Ven
2005-12-14  8:31     ` Ingo Molnar
2005-12-13 20:04   ` Steven Rostedt
2005-12-13 21:03 ` David Howells
2005-12-15 13:58 linux
2005-12-15 16:15 ` Linus Torvalds
2005-12-15 16:52   ` Erik Mouw
2005-12-15 17:23     ` Dick Streefland
2005-12-16 12:17     ` Erik Mouw
2005-12-17 10:59       ` Sander
2005-12-17 14:14         ` Douglas McNaught
2005-12-17 15:09           ` Sander
2005-12-19 10:44         ` Erik Mouw
2005-12-15 19:02   ` Nikita Danilov
2005-12-15 19:09   ` linux
2005-12-15 19:52     ` Linus Torvalds
2005-12-16  1:33       ` linux
2005-12-15 21:18     ` Steven Rostedt
2005-12-15 20:52   ` Steven Rostedt
2005-12-15 17:45 Luck, Tony
2005-12-15 18:00 ` David Howells
2005-12-15 18:48 ` James Bottomley
2005-12-15 20:38 ` Jeff Dike
2005-12-15 23:45   ` Stephen Rothwell
2005-12-16 12:49 linux
2005-12-16 15:24 ` David Howells
2005-12-16 18:03   ` linux

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).