linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Nicolas Pitre <nico@cam.org>
To: Ingo Molnar <mingo@elte.hu>
Cc: Linus Torvalds <torvalds@osdl.org>,
	lkml <linux-kernel@vger.kernel.org>,
	Andrew Morton <akpm@osdl.org>,
	Arjan van de Ven <arjanv@infradead.org>,
	Jes Sorensen <jes@trained-monkey.org>,
	Zwane Mwaikambo <zwane@arm.linux.org.uk>,
	Oleg Nesterov <oleg@tv-sign.ru>,
	David Howells <dhowells@redhat.com>,
	Alan Cox <alan@lxorguk.ukuu.org.uk>,
	Benjamin LaHaise <bcrl@kvack.org>,
	Steven Rostedt <rostedt@goodmis.org>,
	Christoph Hellwig <hch@infradead.org>, Andi Kleen <ak@suse.de>,
	Russell King <rmk+lkml@arm.linux.org.uk>
Subject: [patch 2/3] mutex subsystem: add new atomic primitives
Date: Wed, 21 Dec 2005 17:44:28 -0500 (EST)	[thread overview]
Message-ID: <Pine.LNX.4.64.0512211715490.26663@localhost.localdomain> (raw)
In-Reply-To: <20051221155411.GA7243@elte.hu>

While atomic_dec_call_if_negative() and atomic_inc_call_if_nonpositive() 
are certainly really nice and probably a good starting point for some 
consolidation of the different semaphore implementations, they still 
have stricter semantics than necessary for mutex usage.

This patch adds 3 new helpers that allows for greater flexibility in 
their implementation while preserving the mutex semantics:

  atomic_lock_call_if_contended()
  atomic_unlock_call_if_contended()
  atomic_contended_unlock_fixup()

In particular, they can be implemented in terms of a single atomic swap 
which most architectures can do natively without any locking. With this 
the mutex optimizations only have to be done in those atomic helpers 
while everything else may be generic common code.

On i386 and x86_64 those new helpers are simply defined in terms of the 
existing atomic_dec_call_if_negative() and 
atomic_inc_call_if_nonpositive() since they already provide the best 
that can be done.

Signed-off-by: Nicolas Pitre <nico@cam.org>

---

Index: linux-2.6/include/asm-generic/atomic-call-if.h
===================================================================
--- linux-2.6.orig/include/asm-generic/atomic-call-if.h
+++ linux-2.6/include/asm-generic/atomic-call-if.h
@@ -34,4 +34,51 @@ do {									\
 		fn_name(v);						\
 } while (0)
 
+/**
+ * atomic_lock_call_if_contended - lock and call function if already locked
+ * @v: pointer of type atomic_t
+ * @fn: function to call if v was already locked
+ *
+ * Atomically locks @v and calls a function if @v was already locked.
+ * When @v == 1 it is unlocked, <= 0 means locked.
+ */
+#define atomic_lock_call_if_contended(v, fn_name)			\
+do {									\
+	if (atomic_xchg(v, 0) != 1)					\
+		fn_name(v);						\
+} while (0)
+
+/**
+ * atomic_unlock_call_if_contended - unlock and call function if contended
+ * @v: pointer of type atomic_t
+ * @fn: function to call if the value was contended
+ *
+ * Atomically unlocks @v and calls a function if @v was contended.
+ * When @v == 1 it is unlocked, 0 it is locked, any negative value means
+ * locked with contention. When @v is contended, it is undefined whether @v
+ * is locked or not (implementation dependent) after this call until the @fn
+ * function uses atomic_contended_unlock_fixup() to apply the necessary
+ * fixup (if any).
+ */
+#define atomic_unlock_call_if_contended(v, fn_name)			\
+do {									\
+	if (atomic_xchg(v, 1) != 0)					\
+		fn_name(v);						\
+} while (0)
+
+/**
+ * atomic_contended_unlock_fixup - apply any needed fixup for contended unlock
+ *
+ * @v: pointer of type atomic_t
+ *
+ * This is meant to be called unconditionally from any function passed to
+ * atomic_unlock_call_if_contended. Provides any needed fixup for unlocking
+ * @v if the implementation of atomic_unlock_call_if_contended didn't manage
+ * to unlock it in the contended case.
+ */
+#define atomic_contended_unlock_fixup(v)				\
+do {									\
+	/* the xchg-based unlock doesn't need any fixup */		\
+} while (0)
+
 #endif
Index: linux-2.6/include/asm-i386/atomic.h
===================================================================
--- linux-2.6.orig/include/asm-i386/atomic.h
+++ linux-2.6/include/asm-i386/atomic.h
@@ -294,6 +294,46 @@ do {									\
 		:"memory","cx","dx");					\
 } while (0)
 
+/**
+ * atomic_lock_call_if_contended - lock and call function if already locked
+ * @v: pointer of type atomic_t
+ * @fn: function to call if v was already locked
+ *
+ * Atomically locks @v and calls a function if @v was already locked.
+ * When @v == 1 it is unlocked, <= 0 means locked.
+ */
+#define atomic_lock_call_if_contended(v, fn_name)			\
+	atomic_dec_call_if_negative(v, fn_name)
+
+/**
+ * atomic_unlock_call_if_contended - unlock and call function if contended
+ * @v: pointer of type atomic_t
+ * @fn: function to call if the value was contended
+ *
+ * Atomically unlocks @v and calls a function if @v was contended.
+ * When @v == 1 it is unlocked, 0 it is locked, any negative value means
+ * locked with contention. When @v is contended, it is undefined whether @v
+ * is locked or not (implementation dependent) after this call until the @fn
+ * function uses atomic_contended_unlock_fixup() to apply the necessary
+ * fixup (if any).
+ */
+#define atomic_unlock_call_if_contended(v, fn_name)			\
+	atomic_inc_call_if_nonpositive(v, fn_name)
+
+/**
+ * atomic_contended_unlock_fixup - apply any needed fixup for contended unlock
+ *
+ * @v: pointer of type atomic_t
+ *
+ * This is meant to be called unconditionally from any function passed to
+ * atomic_unlock_call_if_contended. Provides any needed fixup for unlocking
+ * @v if the implementation of atomic_unlock_call_if_contended didn't manage
+ * to unlock it in the contended case.
+ */
+#define atomic_contended_unlock_fixup(v)				\
+do {									\
+	atomic_set(v, 1);						\
+} while (0)
 
 /* These are x86-specific, used by some header files */
 #define atomic_clear_mask(mask, addr) \
Index: linux-2.6/include/asm-x86_64/atomic.h
===================================================================
--- linux-2.6.orig/include/asm-x86_64/atomic.h
+++ linux-2.6/include/asm-x86_64/atomic.h
@@ -259,6 +259,47 @@ do {									\
 		 "r8", "r9", "r10", "r11", "memory");			\
 } while (0)
 
+/**
+ * atomic_lock_call_if_contended - lock and call function if already locked
+ * @v: pointer of type atomic_t
+ * @fn: function to call if v was already locked
+ *
+ * Atomically locks @v and calls a function if @v was already locked.
+ * When @v == 1 it is unlocked, <= 0 means locked.
+ */
+#define atomic_lock_call_if_contended(v, fn_name)			\
+	atomic_dec_call_if_negative(v, fn_name)
+
+/**
+ * atomic_unlock_call_if_contended - unlock and call function if contended
+ * @v: pointer of type atomic_t
+ * @fn: function to call if the value was contended
+ *
+ * Atomically unlocks @v and calls a function if @v was contended.
+ * When @v == 1 it is unlocked, 0 it is locked, any negative value means
+ * locked with contention. When @v is contended, it is undefined whether @v
+ * is locked or not (implementation dependent) after this call until the @fn
+ * function uses atomic_contended_unlock_fixup() to apply the necessary
+ * fixup (if any).
+ */
+#define atomic_unlock_call_if_contended(v, fn_name)			\
+	atomic_inc_call_if_nonpositive(v, fn_name)
+
+/**
+ * atomic_contended_unlock_fixup - apply any needed fixup for contended unlock
+ *
+ * @v: pointer of type atomic_t
+ *
+ * This is meant to be called unconditionally from any function passed to
+ * atomic_unlock_call_if_contended. Provides any needed fixup for unlocking
+ * @v if the implementation of atomic_unlock_call_if_contended didn't manage
+ * to unlock it in the contended case.
+ */
+#define atomic_contended_unlock_fixup(v)				\
+do {									\
+	atomic_set(v, 1);						\
+} while (0)
+
 /* An 64bit atomic type */
 
 typedef struct { volatile long counter; } atomic64_t;

  parent reply	other threads:[~2005-12-21 22:44 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-12-21 15:54 [patch 0/8] mutex subsystem, ANNOUNCE Ingo Molnar
2005-12-21 16:04 ` Arjan van de Ven
2005-12-21 18:07 ` Jes Sorensen
2005-12-22  2:36   ` Nick Piggin
2005-12-22  2:57     ` Nick Piggin
2005-12-22  7:19     ` Ingo Molnar
2005-12-22  7:56       ` Nick Piggin
2005-12-22  8:00         ` Arjan van de Ven
2005-12-22  8:10           ` Nick Piggin
2005-12-22  8:21             ` Arjan van de Ven
2005-12-22  8:32               ` Nick Piggin
2005-12-22  8:24         ` Ingo Molnar
2005-12-22  8:37           ` Nick Piggin
2005-12-21 22:43 ` Nicolas Pitre
2005-12-21 22:43 ` [patch 1/3] mutex subsystem: fix additions to the ARM atomic.h Nicolas Pitre
2005-12-21 22:44 ` Nicolas Pitre [this message]
2005-12-21 22:44 ` [patch 3/3] mutex subsystem: move the core to the new atomic helpers Nicolas Pitre
2005-12-21 23:12   ` Ingo Molnar
2005-12-22  1:16     ` Matt Mackall
2005-12-22  6:50     ` Nicolas Pitre
2005-12-22  6:51     ` [patch 2/5] mutex subsystem: add architecture specific mutex primitives Nicolas Pitre
2005-12-22  7:44       ` Nick Piggin
2005-12-22  8:03         ` Nick Piggin
2005-12-22  6:52     ` [patch 1/5] mutex subsystem: fix asm-arm/atomic.h Nicolas Pitre
2005-12-22  6:53     ` [patch 3/5] mutex subsystem: move the core to the new atomic helpers Nicolas Pitre
2005-12-22  6:53     ` [patch 4/5] mutex subsystem: allow architecture defined fast path for mutex_lock_interruptible Nicolas Pitre
2005-12-22  6:53     ` [patch 5/5] mutex subsystem: allow for the fast path to be inlined Nicolas Pitre

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=Pine.LNX.4.64.0512211715490.26663@localhost.localdomain \
    --to=nico@cam.org \
    --cc=ak@suse.de \
    --cc=akpm@osdl.org \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=arjanv@infradead.org \
    --cc=bcrl@kvack.org \
    --cc=dhowells@redhat.com \
    --cc=hch@infradead.org \
    --cc=jes@trained-monkey.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@elte.hu \
    --cc=oleg@tv-sign.ru \
    --cc=rmk+lkml@arm.linux.org.uk \
    --cc=rostedt@goodmis.org \
    --cc=torvalds@osdl.org \
    --cc=zwane@arm.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;
as well as URLs for NNTP newsgroup(s).