CINXE.COM
LKML: David Howells: [PATCH 1/19] MUTEX: Introduce simple mutex implementation
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>LKML: David Howells: [PATCH 1/19] MUTEX: Introduce simple mutex implementation</title><link href="/css/message.css" rel="stylesheet" type="text/css" /><link href="/css/wrap.css" rel="alternate stylesheet" type="text/css" title="wrap" /><link href="/css/nowrap.css" rel="stylesheet" type="text/css" title="nowrap" /><link href="/favicon.ico" rel="shortcut icon" /><script src="/js/simple-calendar.js" type="text/javascript"></script><script src="/js/styleswitcher.js" type="text/javascript"></script><link rel="alternate" type="application/rss+xml" title="lkml.org : last 100 messages" href="/rss.php" /><link rel="alternate" type="application/rss+xml" title="lkml.org : last messages by David Howells" href="/groupie.php?aid=345" /><!--Matomo--><script> var _paq = window._paq = window._paq || []; /* tracker methods like "setCustomDimension" should be called before "trackPageView" */ _paq.push(["setDoNotTrack", true]); _paq.push(["disableCookies"]); _paq.push(['trackPageView']); _paq.push(['enableLinkTracking']); (function() { var u="//m.lkml.org/"; _paq.push(['setTrackerUrl', u+'matomo.php']); _paq.push(['setSiteId', '1']); var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s); })(); </script><!--End Matomo Code--></head><body onload="es.jasper.simpleCalendar.init();" itemscope="itemscope" itemtype="http://schema.org/BlogPosting"><table border="0" cellpadding="0" cellspacing="0"><tr><td width="180" align="center"><a href="/"><img style="border:0;width:135px;height:32px" src="/images/toprowlk.gif" alt="lkml.org" /></a></td><td width="32">聽</td><td class="nb"><div><a class="nb" href="/lkml"> [lkml]</a> 聽 <a class="nb" href="/lkml/2005"> [2005]</a> 聽 <a class="nb" href="/lkml/2005/12"> [Dec]</a> 聽 <a class="nb" href="/lkml/2005/12/12"> [12]</a> 聽 <a class="nb" href="/lkml/last100"> [last100]</a> 聽 <a href="/rss.php"><img src="/images/rss-or.gif" border="0" alt="RSS Feed" /></a></div><div>Views: <a href="#" class="nowrap" onclick="setActiveStyleSheet('wrap');return false;">[wrap]</a><a href="#" class="wrap" onclick="setActiveStyleSheet('nowrap');return false;">[no wrap]</a> 聽 <a class="nb" href="/lkml/mheaders/2005/12/12/244" onclick="this.href='/lkml/headers'+'/2005/12/12/244';">[headers]</a>聽 <a href="/lkml/bounce/2005/12/12/244">[forward]</a>聽 </div></td><td width="32">聽</td></tr><tr><td valign="top"><div class="es-jasper-simpleCalendar" baseurl="/lkml/"></div><div class="threadlist">Messages in this thread</div><ul class="threadlist"><li class="root"><a href="/lkml/2005/12/12/244">First message in thread</a></li><li class="origin"><a href="/lkml/2005/12/12/241">David Howells</a><ul><li><a href="/lkml/2005/12/12/241">David Howells</a></li><li><a href="/lkml/2005/12/12/242">David Howells</a></li><li><a href="/lkml/2005/12/12/243">David Howells</a></li><li><a href="/lkml/2005/12/12/245">David Howells</a></li><li><a href="/lkml/2005/12/12/246">David Howells</a></li><li><a href="/lkml/2005/12/12/247">David Howells</a></li><li><a href="/lkml/2005/12/12/248">David Howells</a></li><li><a href="/lkml/2005/12/12/249">David Howells</a></li><li><a href="/lkml/2005/12/12/250">David Howells</a></li><li><a href="/lkml/2005/12/12/251">David Howells</a></li><li><a href="/lkml/2005/12/12/252">David Howells</a></li><li><a href="/lkml/2005/12/12/253">David Howells</a></li><li><a href="/lkml/2005/12/12/254">David Howells</a></li><li><a href="/lkml/2005/12/12/255">David Howells</a></li><li><a href="/lkml/2005/12/12/256">David Howells</a></li><li><a href="/lkml/2005/12/12/257">David Howells</a></li><li><a href="/lkml/2005/12/12/259">David Howells</a></li><li><a href="/lkml/2005/12/12/260">David Howells</a></li><li><a href="/lkml/2005/12/12/266">Nick Piggin</a><ul><li><a href="/lkml/2005/12/13/107">David Howells</a><ul><li><a href="/lkml/2005/12/13/114">Ingo Molnar</a><ul><li><a href="/lkml/2005/12/13/125">Ingo Molnar</a></li></ul></li><li><a href="/lkml/2005/12/13/431">Nick Piggin</a><ul><li><a href="/lkml/2005/12/14/82">David Howells</a></li></ul></li></ul></li></ul></li><li><a href="/lkml/2005/12/12/268">Andrew Morton</a><ul><li><a href="/lkml/2005/12/13/30">Ingo Molnar</a><ul><li><a href="/lkml/2005/12/13/32">Andi Kleen</a><ul><li><a href="/lkml/2005/12/13/74">Andrew Morton</a></li></ul></li><li><a href="/lkml/2005/12/13/33">Arjan van de Ven</a><ul><li><a href="/lkml/2005/12/13/83">Ingo Molnar</a></li></ul></li><li><a href="/lkml/2005/12/13/78">Christoph Hellwig</a><ul><li><a href="/lkml/2005/12/13/102">Ingo Molnar</a></li></ul></li><li><a href="/lkml/2005/12/13/108">Ingo Molnar</a></li></ul></li><li><a href="/lkml/2005/12/13/127">David Howells</a><ul><li><a href="/lkml/2005/12/13/139">Matthew Wilcox</a></li></ul></li></ul></li><li><a href="/lkml/2005/12/12/269">Nick Piggin</a><ul><li><a href="/lkml/2005/12/13/131">David Howells</a><ul><li><a href="/lkml/2005/12/13/133">David Howells</a></li></ul></li></ul></li><li><a href="/lkml/2005/12/12/272">Arnd Bergmann</a><ul><li><a href="/lkml/2005/12/13/323">David Howells</a></li></ul></li><li><a href="/lkml/2005/12/12/276">Daniel Walker</a><ul><li><a href="/lkml/2005/12/12/311">Steven Rostedt</a></li></ul></li><li><a href="/lkml/2005/12/12/296">Mark Lord</a><ul><li><a href="/lkml/2005/12/12/310">Steven Rostedt</a></li><li><a href="/lkml/2005/12/13/85">Christoph Hellwig</a></li></ul></li><li><a href="/lkml/2005/12/13/128">Ingo Molnar</a><ul><li><a href="/lkml/2005/12/13/132">David Howells</a><ul><li><a href="/lkml/2005/12/13/166">Ingo Molnar</a></li></ul></li></ul></li><li><a href="/lkml/2005/12/13/142">Alan Cox</a><ul><li><a href="/lkml/2005/12/13/147">Alan Cox</a><ul><li><a href="/lkml/2005/12/13/406">Nikita Danilov</a></li></ul></li><li><a href="/lkml/2005/12/13/151">David Howells</a><ul><li><a href="/lkml/2005/12/13/172">Alan Cox</a><ul><li><a href="/lkml/2005/12/13/205">David Howells</a></li></ul></li><li><a href="/lkml/2005/12/13/187">"Christopher Friesen"</a><ul><li><a href="/lkml/2005/12/13/188">Arjan van de Ven</a></li><li><a href="/lkml/2005/12/13/213">David Howells</a></li></ul></li><li><a href="/lkml/2005/12/13/306">Steven Rostedt</a></li></ul></li></ul></li></ul></li></ul><div class="threadlist">Patch in this message</div><ul class="threadlist"><li><a href="/lkml/diff/2005/12/12/244/1">Get diff 1</a></li></ul></td><td width="32" rowspan="2" class="c" valign="top"><img src="/images/icornerl.gif" width="32" height="32" alt="/" /></td><td class="c" rowspan="2" valign="top" style="padding-top: 1em"><table><tr><td><table><tr><td class="lp">Date</td><td class="rp" itemprop="datePublished">Mon, 12 Dec 2005 23:45:45 GMT</td></tr><tr><td class="lp">From</td><td class="rp" itemprop="author">David Howells <></td></tr><tr><td class="lp">Subject</td><td class="rp" itemprop="name">[PATCH 1/19] MUTEX: Introduce simple mutex implementation</td></tr></table></td><td></td></tr></table><pre itemprop="articleBody">The attached patch introduces a simple mutex implementation as an alternative<br />to the usual semaphore implementation where simple mutex functionality is all<br />that is required.<br /><br />This is useful in two ways:<br /><br /> (1) A number of archs only provide very simple atomic instructions (such as<br /> XCHG on i386, TAS on M68K, SWAP on FRV) which aren't sufficient to<br /> implement full semaphore support directly. Instead spinlocks must be<br /> employed to implement fuller functionality.<br /><br /> (2) This makes it obvious in what way the semaphore is being used: whether<br /> it's being used as a mutex or being used as a counter.<br /><br />This patch set does the following:<br /><br /> (1) Provides a simple xchg() based semaphore as a default for all<br /> architectures that don't wish to override it and provide their own.<br /><br /> Overriding is possible by setting CONFIG_ARCH_IMPLEMENTS_MUTEX and<br /> supplying asm/mutex.h<br /><br /> Partial overriding is possible by #defining mutex_grab(), mutex_release()<br /> and is_mutex_locked() to perform the appropriate optimised functions.<br /><br /> (2) Provides linux/mutex.h as a common include for gaining access to mutex<br /> semaphores.<br /><br /> (3) Provides linux/semaphore.h as a common include for gaining access to all<br /> the different types of semaphore that may be used from within the kernel.<br /><br /> (4) Renames down*() to down_sem*() and up() to up_sem() for the traditional<br /> semaphores, and removes init_MUTEX*() and DECLARE_MUTEX*() from<br /> asm/semaphore.h<br /><br /> (5) Redirects the following to apply to the new mutexes rather than the<br /> traditional semaphores:<br /><br /> down()<br /> down_trylock()<br /> down_interruptible()<br /> up()<br /> init_MUTEX()<br /> init_MUTEX_LOCKED()<br /> DECLARE_MUTEX()<br /> DECLARE_MUTEX_LOCKED()<br /><br /> On the basis that most usages of semaphores are as mutexes, this makes<br /> sense for in most cases it's just then a matter of changing the type from<br /> struct semaphore to struct mutex. In some cases, sema_init() has to be<br /> changed to init_MUTEX*() also.<br /><br /> (6) Generally include linux/semaphore.h in place of asm/semaphore.h.<br /><br /> (7) Provides a debugging config option CONFIG_DEBUG_MUTEX_OWNER by which the<br /> mutex owner can be tracked and by which over-upping can be detected.<br /><br />Signed-Off-By: David Howells <dhowells@redhat.com><br />---<br />warthog>diffstat -p1 mutex-simple-2615rc5.diff<br /> include/linux/mutex-simple.h | 194 +++++++++++++++++++++++++++++++++++++++++++<br /> include/linux/mutex.h | 32 +++++++<br /> include/linux/semaphore.h | 30 ++++++<br /> lib/Kconfig.debug | 8 +<br /> lib/Makefile | 4 <br /> lib/mutex-simple.c | 178 +++++++++++++++++++++++++++++++++++++++<br /> lib/semaphore-sleepers.c | 8 -<br /> 7 files changed, 450 insertions(+), 4 deletions(-)<br /><br />diff -uNrp /warthog/kernels/linux-2.6.15-rc5/include/linux/semaphore.h linux-2.6.15-rc5-mutex/include/linux/semaphore.h<br />--- /warthog/kernels/linux-2.6.15-rc5/include/linux/semaphore.h 1970-01-01 01:00:00.000000000 +0100<br />+++ linux-2.6.15-rc5-mutex/include/linux/semaphore.h 2005-12-12 22:03:53.000000000 +0000<br />@@ -0,0 +1,30 @@<br />+/* semaphore.h: include the various types of semaphore in one package<br />+ *<br />+ * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.<br />+ * Written by David Howells (dhowells@redhat.com)<br />+ *<br />+ * This program is free software; you can redistribute it and/or<br />+ * modify it under the terms of the GNU General Public License<br />+ * as published by the Free Software Foundation; either version<br />+ * 2 of the License, or (at your option) any later version.<br />+ */<br />+<br />+#ifndef _LINUX_SEMAPHORE_H<br />+#define _LINUX_SEMAPHORE_H<br />+<br />+/*<br />+ * simple mutex semaphores<br />+ */<br />+#include <linux/mutex.h><br />+<br />+/*<br />+ * multiple-count semaphores<br />+ */<br />+#include <asm/semaphore.h><br />+<br />+/*<br />+ * read/write semaphores<br />+ */<br />+#include <linux/rwsem.h><br />+<br />+#endif /* _LINUX_SEMAPHORE_H */<br />diff -uNrp /warthog/kernels/linux-2.6.15-rc5/include/linux/mutex.h linux-2.6.15-rc5-mutex/include/linux/mutex.h<br />--- /warthog/kernels/linux-2.6.15-rc5/include/linux/mutex.h 1970-01-01 01:00:00.000000000 +0100<br />+++ linux-2.6.15-rc5-mutex/include/linux/mutex.h 2005-12-12 22:13:30.000000000 +0000<br />@@ -0,0 +1,32 @@<br />+/* mutex.h: mutex semaphore implementation base<br />+ *<br />+ * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.<br />+ * Written by David Howells (dhowells@redhat.com)<br />+ *<br />+ * This program is free software; you can redistribute it and/or<br />+ * modify it under the terms of the GNU General Public License<br />+ * as published by the Free Software Foundation; either version<br />+ * 2 of the License, or (at your option) any later version.<br />+ */<br />+#ifndef _LINUX_MUTEX_H<br />+#define _LINUX_MUTEX_H<br />+<br />+#include <linux/config.h><br />+<br />+#ifdef CONFIG_ARCH_IMPLEMENTS_MUTEX<br />+<br />+/*<br />+ * the arch wants to implement the whole mutex itself<br />+ */<br />+#include <asm/mutex.h><br />+#else<br />+<br />+/*<br />+ * simple exchange-based mutex<br />+ * - the arch may override mutex_grab(), mutex_release() and is_mutex_locked()<br />+ * to use something other than xchg() by #defining mutex_grab<br />+ */<br />+#include <linux/mutex-simple.h><br />+#endif<br />+<br />+#endif /* _LINUX_MUTEX_H */<br />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<br />--- /warthog/kernels/linux-2.6.15-rc5/include/linux/mutex-simple.h 1970-01-01 01:00:00.000000000 +0100<br />+++ linux-2.6.15-rc5-mutex/include/linux/mutex-simple.h 2005-12-12 22:26:11.000000000 +0000<br />@@ -0,0 +1,194 @@<br />+/* mutex-simple.h: simple exchange-based mutexes<br />+ *<br />+ * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.<br />+ * Written by David Howells (dhowells@redhat.com)<br />+ *<br />+ * This program is free software; you can redistribute it and/or<br />+ * modify it under the terms of the GNU General Public License<br />+ * as published by the Free Software Foundation; either version<br />+ * 2 of the License, or (at your option) any later version.<br />+ *<br />+ *<br />+ * This doesn't require the arch to do anything for straightforward xchg()<br />+ * based mutexes<br />+ *<br />+ * If the sets CONFIG_ARCH_IMPLEMENTS_MUTEX then this implementation will not<br />+ * be used, and the arch should supply asm/mutex.h.<br />+ *<br />+ * If the arch defines mutex_grab(), mutex_release() and is_mutex_locked() for<br />+ * itself, then those will be used to provide the appropriate functionality<br />+ *<br />+ * See lib/mutex-simple.c for the slow-path implementation.<br />+ */<br />+#ifndef _LINUX_MUTEX_SIMPLE_H<br />+#define _LINUX_MUTEX_SIMPLE_H<br />+<br />+#ifndef _LINUX_MUTEX_H<br />+#error linux/mutex-xchg.h should not be included directly; use linux/mutex.h instead<br />+#endif<br />+<br />+#ifndef __ASSEMBLY__<br />+<br />+#include <linux/linkage.h><br />+#include <linux/wait.h><br />+#include <linux/spinlock.h><br />+#include <asm/system.h><br />+<br />+/*<br />+ * the mutex semaphore definition<br />+ * - if state is 0, then the mutex is available<br />+ * - if state is non-zero, then the mutex is busy<br />+ * - if wait_list is not empty, then there are processes waiting for the mutex<br />+ */<br />+struct mutex {<br />+ int state;<br />+ spinlock_t wait_lock;<br />+ struct list_head wait_list;<br />+#ifdef CONFIG_DEBUG_MUTEX_OWNER<br />+ struct task_struct *__owner;<br />+#endif<br />+};<br />+<br />+#ifndef mutex_grab<br />+/*<br />+ * mutex_grab() attempts to grab the mutex and returns true if successful<br />+ */<br />+#define mutex_grab(mutex) (xchg(&(mutex)->state, 1) == 0)<br />+<br />+/*<br />+ * mutex_release() releases the mutex<br />+ */<br />+#define mutex_release(mutex) do { (mutex)->state = 0; } while(0)<br />+<br />+/*<br />+ * is_mutex_locked() returns non-zero if the mutex is locked<br />+ */<br />+#define is_mutex_locked(mutex) ((mutex)->state)<br />+#endif<br />+<br />+#ifdef CONFIG_DEBUG_MUTEX_OWNER<br />+# define __MUTEX_OWNER_INIT(owner) , .__owner = (owner)<br />+#else<br />+# define __MUTEX_OWNER_INIT(owner)<br />+#endif<br />+<br />+#define __MUTEX_INITIALISER(name,_state,owner) \<br />+{ \<br />+ .state = (_state), \<br />+ .wait_lock = SPIN_LOCK_UNLOCKED, \<br />+ .wait_list = LIST_HEAD_INIT((name).wait_list) \<br />+ __MUTEX_OWNER_INIT(owner) \<br />+}<br />+<br />+#define __DECLARE_MUTEX_GENERIC(name, owner, state) \<br />+ struct mutex name = __MUTEX_INITIALISER(name, owner, state)<br />+<br />+#define DECLARE_MUTEX(name) \<br />+ __DECLARE_MUTEX_GENERIC(name, 0, NULL)<br />+<br />+#define DECLARE_MUTEX_LOCKED(name, owner) \<br />+ __DECLARE_MUTEX_GENERIC(name, 1, (owner))<br />+<br />+static inline void mutex_init(struct mutex *mutex,<br />+ unsigned state,<br />+ struct task_struct *owner)<br />+{<br />+ mutex->state = state;<br />+ spin_lock_init(&mutex->wait_lock);<br />+ INIT_LIST_HEAD(&mutex->wait_list);<br />+#ifdef CONFIG_DEBUG_MUTEX_OWNER<br />+ mutex->__owner = owner;<br />+#endif<br />+}<br />+<br />+static inline void init_MUTEX(struct mutex *mutex)<br />+{<br />+ mutex_init(mutex, 0, NULL);<br />+}<br />+<br />+static inline void init_MUTEX_LOCKED (struct mutex *mutex)<br />+{<br />+ mutex_init(mutex, 1, current);<br />+}<br />+<br />+extern void __down(struct mutex *mutex);<br />+extern int __down_interruptible(struct mutex *mutex);<br />+extern void __up(struct mutex *mutex);<br />+<br />+#ifdef CONFIG_DEBUG_MUTEX_OWNER<br />+extern void __up_bad(struct mutex *mutex);<br />+#endif<br />+<br />+/*<br />+ * sleep until we get the mutex<br />+ */<br />+static inline void down(struct mutex *mutex)<br />+{<br />+ if (mutex_grab(mutex)) {<br />+#ifdef CONFIG_DEBUG_MUTEX_OWNER<br />+ mutex->__owner = current;<br />+#endif<br />+ }<br />+ else {<br />+ __down(mutex);<br />+ }<br />+}<br />+<br />+/*<br />+ * sleep interruptibly until we get the mutex<br />+ * - return 0 if successful, -EINTR if interrupted<br />+ */<br />+static inline int down_interruptible(struct mutex *mutex)<br />+{<br />+ if (mutex_grab(mutex)) {<br />+#ifdef CONFIG_DEBUG_MUTEX_OWNER<br />+ mutex->__owner = current;<br />+#endif<br />+ return 0;<br />+ }<br />+<br />+ return __down_interruptible(mutex);<br />+}<br />+<br />+/*<br />+ * attempt to grab the mutex without waiting for it to become available<br />+ * - returns zero if we acquired it<br />+ */<br />+static inline int down_trylock(struct mutex *mutex)<br />+{<br />+ if (mutex_grab(mutex)) {<br />+ /* success */<br />+#ifdef CONFIG_DEBUG_MUTEX_OWNER<br />+ mutex->__owner = current;<br />+#endif<br />+ return 0;<br />+ }<br />+<br />+ /* failure */<br />+ return 1;<br />+}<br />+<br />+/*<br />+ * release the mutex<br />+ */<br />+static inline void up(struct mutex *mutex)<br />+{<br />+ unsigned long flags;<br />+<br />+#ifdef CONFIG_DEBUG_MUTEX_OWNER<br />+ if (mutex->__owner != current)<br />+ __up_bad(mutex);<br />+ mutex->__owner = NULL;<br />+#endif<br />+<br />+ /* must prevent a race */<br />+ spin_lock_irqsave(&mutex->wait_lock, flags);<br />+ if (!list_empty(&mutex->wait_list))<br />+ __up(mutex);<br />+ else<br />+ mutex_release(mutex);<br />+ spin_unlock_irqrestore(&mutex->wait_lock, flags);<br />+}<br />+<br />+#endif /* __ASSEMBLY__ */<br />+#endif /* _LINUX_MUTEX_SIMPLE_H */<br />diff -uNrp /warthog/kernels/linux-2.6.15-rc5/lib/Kconfig.debug linux-2.6.15-rc5-mutex/lib/Kconfig.debug<br />--- /warthog/kernels/linux-2.6.15-rc5/lib/Kconfig.debug 2005-12-08 16:23:56.000000000 +0000<br />+++ linux-2.6.15-rc5-mutex/lib/Kconfig.debug 2005-12-12 16:59:35.000000000 +0000<br />@@ -111,6 +111,14 @@ config DEBUG_SPINLOCK_SLEEP<br /> If you say Y here, various routines which may sleep will become very<br /> noisy if they are called with a spinlock held.<br /> <br />+config DEBUG_MUTEX_OWNER<br />+ bool "Mutex owner tracking and checking"<br />+ depends on DEBUG_KERNEL<br />+ help<br />+ If you say Y here, the process currently owning a mutex will be<br />+ remembered, and a warning will be issued if anyone other than that<br />+ process releases it.<br />+<br /> config DEBUG_KOBJECT<br /> bool "kobject debugging"<br /> depends on DEBUG_KERNEL<br />diff -uNrp /warthog/kernels/linux-2.6.15-rc5/lib/Makefile linux-2.6.15-rc5-mutex/lib/Makefile<br />--- /warthog/kernels/linux-2.6.15-rc5/lib/Makefile 2005-12-08 16:23:56.000000000 +0000<br />+++ linux-2.6.15-rc5-mutex/lib/Makefile 2005-12-12 18:59:21.000000000 +0000<br />@@ -28,6 +28,10 @@ ifneq ($(CONFIG_HAVE_DEC_LOCK),y)<br /> lib-y += dec_and_lock.o<br /> endif<br /> <br />+ifneq ($(CONFIG_ARCH_IMPLEMENTS_MUTEX),y)<br />+ lib-y += mutex-simple.o<br />+endif<br />+<br /> obj-$(CONFIG_CRC_CCITT) += crc-ccitt.o<br /> obj-$(CONFIG_CRC16) += crc16.o<br /> obj-$(CONFIG_CRC32) += crc32.o<br />diff -uNrp /warthog/kernels/linux-2.6.15-rc5/lib/mutex-simple.c linux-2.6.15-rc5-mutex/lib/mutex-simple.c<br />--- /warthog/kernels/linux-2.6.15-rc5/lib/mutex-simple.c 1970-01-01 01:00:00.000000000 +0100<br />+++ linux-2.6.15-rc5-mutex/lib/mutex-simple.c 2005-12-12 22:27:00.000000000 +0000<br />@@ -0,0 +1,178 @@<br />+/* mutex-simple.c: simple mutex slow paths<br />+ *<br />+ * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.<br />+ * Written by David Howells (dhowells@redhat.com)<br />+ *<br />+ * This program is free software; you can redistribute it and/or<br />+ * modify it under the terms of the GNU General Public License<br />+ * as published by the Free Software Foundation; either version<br />+ * 2 of the License, or (at your option) any later version.<br />+ */<br />+<br />+#include <linux/config.h><br />+#include <linux/sched.h><br />+#include <linux/module.h><br />+#include <linux/mutex.h><br />+<br />+struct mutex_waiter {<br />+ struct list_head list;<br />+ struct task_struct *task;<br />+};<br />+<br />+/*<br />+ * wait for a token to be granted from a mutex<br />+ */<br />+void __down(struct mutex *mutex)<br />+{<br />+ struct mutex_waiter waiter;<br />+ struct task_struct *tsk = current;<br />+ unsigned long flags;<br />+<br />+ /* set up my own style of waitqueue */<br />+ waiter.task = tsk;<br />+<br />+ spin_lock_irqsave(&mutex->wait_lock, flags);<br />+<br />+ if (mutex_grab(mutex)) {<br />+ /* we got the mutex anyway */<br />+ spin_unlock_irqrestore(&mutex->wait_lock, flags);<br />+ return;<br />+ }<br />+<br />+ /* need to sleep */<br />+ get_task_struct(tsk);<br />+ list_add_tail(&waiter.list, &mutex->wait_list);<br />+<br />+ /* we don't need to touch the mutex struct anymore */<br />+ spin_unlock_irqrestore(&mutex->wait_lock, flags);<br />+<br />+ /* wait to be given the mutex */<br />+ set_task_state(tsk, TASK_UNINTERRUPTIBLE);<br />+<br />+ for (;;) {<br />+ if (list_empty(&waiter.list))<br />+ break;<br />+ schedule();<br />+ set_task_state(tsk, TASK_UNINTERRUPTIBLE);<br />+ }<br />+<br />+ tsk->state = TASK_RUNNING;<br />+}<br />+<br />+EXPORT_SYMBOL(__down);<br />+<br />+/*<br />+ * interruptibly wait for a token to be granted from a mutex<br />+ */<br />+int __down_interruptible(struct mutex *mutex)<br />+{<br />+ struct mutex_waiter waiter;<br />+ struct task_struct *tsk = current;<br />+ unsigned long flags;<br />+ int ret;<br />+<br />+ /* set up my own style of waitqueue */<br />+ waiter.task = tsk;<br />+<br />+ spin_lock_irqsave(&mutex->wait_lock, flags);<br />+<br />+ if (mutex_grab(mutex)) {<br />+ /* we got the mutex anyway */<br />+ spin_unlock_irqrestore(&mutex->wait_lock, flags);<br />+ return 0;<br />+ }<br />+<br />+ /* need to sleep */<br />+ get_task_struct(tsk);<br />+ list_add_tail(&waiter.list, &mutex->wait_list);<br />+<br />+ /* we don't need to touch the mutex struct anymore */<br />+ set_task_state(tsk, TASK_INTERRUPTIBLE);<br />+<br />+ spin_unlock_irqrestore(&mutex->wait_lock, flags);<br />+<br />+ /* wait to be given the mutex */<br />+ for (;;) {<br />+ if (list_empty(&waiter.list))<br />+ break;<br />+ if (unlikely(signal_pending(current)))<br />+ goto interrupted;<br />+ schedule();<br />+ set_task_state(tsk, TASK_INTERRUPTIBLE);<br />+ }<br />+<br />+ tsk->state = TASK_RUNNING;<br />+ return 0;<br />+<br />+interrupted:<br />+ spin_lock_irqsave(&mutex->wait_lock, flags);<br />+<br />+ /* we may still have been given the mutex */<br />+ ret = 0;<br />+ if (!list_empty(&waiter.list)) {<br />+ list_del(&waiter.list);<br />+ ret = -EINTR;<br />+ }<br />+<br />+ spin_unlock_irqrestore(&mutex->wait_lock, flags);<br />+ if (ret == -EINTR)<br />+ put_task_struct(current);<br />+ return ret;<br />+}<br />+<br />+EXPORT_SYMBOL(__down_interruptible);<br />+<br />+/*<br />+ * release a single token back to a mutex<br />+ * - entered with lock held and interrupts disabled<br />+ * - the queue will not be empty<br />+ */<br />+void __up(struct mutex *mutex)<br />+{<br />+ struct mutex_waiter *waiter;<br />+ struct task_struct *tsk;<br />+<br />+ /* grant the token to the process at the front of the queue */<br />+ waiter = list_entry(mutex->wait_list.next, struct mutex_waiter, list);<br />+<br />+ /* we must be careful not to touch 'waiter' after we set ->task = NULL.<br />+ * - it is an allocated on the waiter's stack and may become invalid at<br />+ * any time after that point (due to a wakeup from another source).<br />+ */<br />+ list_del_init(&waiter->list);<br />+ tsk = waiter->task;<br />+#ifdef CONFIG_DEBUG_MUTEX_OWNER<br />+ mutex->__owner = tsk;<br />+#endif<br />+ mb();<br />+ waiter->task = NULL;<br />+ wake_up_process(tsk);<br />+ put_task_struct(tsk);<br />+}<br />+<br />+EXPORT_SYMBOL(__up);<br />+<br />+/*<br />+ * report an up() that doesn't match a down()<br />+ */<br />+#ifdef CONFIG_DEBUG_MUTEX_OWNER<br />+void __up_bad(struct mutex *mutex)<br />+{<br />+ if (!mutex->__owner) {<br />+ printk(KERN_ERR<br />+ "BUG: process %d [%s] releasing unowned mutex\n",<br />+ current->pid,<br />+ current->comm);<br />+ }<br />+ else {<br />+ printk(KERN_ERR<br />+ "BUG: process %d [%s] releasing mutex owned by %d [%s]\n",<br />+ current->pid,<br />+ current->comm,<br />+ mutex->__owner->pid,<br />+ mutex->__owner->comm);<br />+ }<br />+}<br />+<br />+EXPORT_SYMBOL(__up_bad);<br />+#endif<br />diff -uNrp /warthog/kernels/linux-2.6.15-rc5/lib/semaphore-sleepers.c linux-2.6.15-rc5-mutex/lib/semaphore-sleepers.c<br />--- /warthog/kernels/linux-2.6.15-rc5/lib/semaphore-sleepers.c 2005-11-01 13:19:22.000000000 +0000<br />+++ linux-2.6.15-rc5-mutex/lib/semaphore-sleepers.c 2005-12-12 17:58:35.000000000 +0000<br />@@ -49,12 +49,12 @@<br /> * we cannot lose wakeup events.<br /> */<br /> <br />-fastcall void __up(struct semaphore *sem)<br />+fastcall void __up_sem(struct semaphore *sem)<br /> {<br /> wake_up(&sem->wait);<br /> }<br /> <br />-fastcall void __sched __down(struct semaphore * sem)<br />+fastcall void __sched __down_sem(struct semaphore * sem)<br /> {<br /> struct task_struct *tsk = current;<br /> DECLARE_WAITQUEUE(wait, tsk);<br />@@ -91,7 +91,7 @@ fastcall void __sched __down(struct sema<br /> tsk->state = TASK_RUNNING;<br /> }<br /> <br />-fastcall int __sched __down_interruptible(struct semaphore * sem)<br />+fastcall int __sched __down_sem_interruptible(struct semaphore * sem)<br /> {<br /> int retval = 0;<br /> struct task_struct *tsk = current;<br />@@ -154,7 +154,7 @@ fastcall int __sched __down_interruptibl<br /> * single "cmpxchg" without failure cases,<br /> * but then it wouldn't work on a 386.<br /> */<br />-fastcall int __down_trylock(struct semaphore * sem)<br />+fastcall int __down_sem_trylock(struct semaphore * sem)<br /> {<br /> int sleepers;<br /> unsigned long flags;<br />-<br />To unsubscribe from this list: send the line "unsubscribe linux-kernel" in<br />the body of a message to majordomo@vger.kernel.org<br />More majordomo info at <a href="http://vger.kernel.org/majordomo-info.html">http://vger.kernel.org/majordomo-info.html</a><br />Please read the FAQ at <a href="http://www.tux.org/lkml/">http://www.tux.org/lkml/</a><br /></pre></td><td width="32" rowspan="2" class="c" valign="top"><img src="/images/icornerr.gif" width="32" height="32" alt="\" /></td></tr><tr><td align="right" valign="bottom"> 聽 </td></tr><tr><td align="right" valign="bottom">聽</td><td class="c" valign="bottom" style="padding-bottom: 0px"><img src="/images/bcornerl.gif" width="32" height="32" alt="\" /></td><td class="c">聽</td><td class="c" valign="bottom" style="padding-bottom: 0px"><img src="/images/bcornerr.gif" width="32" height="32" alt="/" /></td></tr><tr><td align="right" valign="top" colspan="2"> 聽 </td><td class="lm">Last update: 2005-12-13 00:51 聽聽 [from the cache]<br />漏2003-2020 <a href="http://blog.jasper.es/"><span itemprop="editor">Jasper Spaans</span></a>|hosted at <a href="https://www.digitalocean.com/?refcode=9a8e99d24cf9">Digital Ocean</a> and my Meterkast|<a href="http://blog.jasper.es/categories.html#lkml-ref">Read the blog</a></td><td>聽</td></tr></table><script language="javascript" src="/js/styleswitcher.js" type="text/javascript"></script></body></html>