All of lore.kernel.org
 help / color / mirror / Atom feed
From: Nick Piggin <npiggin@suse.de>
To: Andreas Dilger <adilger@sun.com>
Cc: Al Viro <viro@ZenIV.linux.org.uk>,
	Frank Mayhar <fmayhar@google.com>,
	John Stultz <johnstul@us.ibm.com>,
	Andi Kleen <ak@linux.intel.com>,
	linux-fsdevel@vger.kernel.org
Subject: Re: [patch 1/2] kernel: introduce brlock
Date: Thu, 18 Mar 2010 01:18:30 +1100	[thread overview]
Message-ID: <20100317141830.GJ2869@laptop> (raw)
In-Reply-To: <20100316234440.GU2869@laptop>

On Wed, Mar 17, 2010 at 10:44:40AM +1100, Nick Piggin wrote:
> On Tue, Mar 16, 2010 at 01:01:09PM -0600, Andreas Dilger wrote:
> > On 2010-03-16, at 06:22, Nick Piggin wrote:
> > What makes these macros unpleasant is that it is no longer possible
> > to tag to the implementation to see what it does, since there is no
> > real declaration for these locks.
> > 
> > Is it possible to change the macros to take the lock name as a
> > parameter, like normal lock/unlock functions do, and then have a
> > single declaration for br_lock_init(), br_wlock(), etc. macros?
> 
> The problem is that then you can't do out of line functions, and
> things like wlock/wunlock are rather large.
> 
> What I think I can do is add macros in the brlock.h file
> 
> #define br_rlock(name) ##name_rlock()
> 
> So the macro calls the right function and your tag should take
> you pretty close to the right place.
> 
> Any better ideas how to implement this nicely would be welcome.
> It must be as light-weight as possible in the rlock path though.

It looks like this. Is it better?
--
brlock: introduce special brlocks

This patch introduces special brlocks, these can only be used as global
locks, and use some preprocessor trickery to allow us to retain a more
optimal per-cpu lock implementation. We don't bother working around
lockdep yet.

The other thing we can do in future is a really neat atomic-free
implementation like Dave M did for the old brlocks, so we might actually
be able to speed up the single-thread path for these things.

Signed-off-by: Nick Piggin <npiggin@suse.de>
---
 include/linux/brlock.h |  120 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 120 insertions(+)

Index: linux-2.6/include/linux/brlock.h
===================================================================
--- /dev/null
+++ linux-2.6/include/linux/brlock.h
@@ -0,0 +1,120 @@
+/*
+ * Specialised big-reader spinlock. Can only be declared as global variables
+ * to avoid overhead and keep things simple (and we don't want to start using
+ * these inside dynamically allocated structures).
+ *
+ * Copyright 2009, Nick Piggin, Novell Inc.
+ */
+#ifndef __LINUX_BRLOCK_H
+#define __LINUX_BRLOCK_H
+
+#include <linux/spinlock.h>
+#include <linux/percpu.h>
+#include <asm/atomic.h>
+
+#define br_lock_init(name)	name##_lock_init()
+#define br_read_lock(name)	name##_read_lock()
+#define br_read_unlock(name)	name##_read_unlock()
+#define br_write_lock(name)	name##_write_lock()
+#define br_write_unlock(name)	name##_write_unlock()
+#define atomic_dec_and_br_read_lock(atomic, name)	name##_atomic_dec_and_read_lock(atomic)
+#define atomic_dec_and_br_write_lock(atomic, name)	name##_atomic_dec_and_write_lock(atomic)
+
+#if defined(CONFIG_SMP) && !defined(CONFIG_LOCKDEP)
+#define DECLARE_BRLOCK(name)						\
+ DECLARE_PER_CPU(spinlock_t, name##_lock);				\
+ extern void name##_lock_init(void);					\
+ static inline void name##_read_lock(void) {				\
+	spinlock_t *lock;						\
+	lock = &get_cpu_var(name##_lock);				\
+	spin_lock(lock);						\
+	put_cpu_var(name##_lock);					\
+ }									\
+ static inline void name##_read_unlock(void) {				\
+	spinlock_t *lock;						\
+	lock = &__get_cpu_var(name##_lock);				\
+	spin_unlock(lock);						\
+ }									\
+ extern void name##_write_lock(void);					\
+ extern void name##_write_unlock(void);					\
+ static inline int name##_atomic_dec_and_read_lock(atomic_t *a) {	\
+	int ret;							\
+	spinlock_t *lock;						\
+	lock = &get_cpu_var(name##_lock);				\
+	ret = atomic_dec_and_lock(a, lock);				\
+	put_cpu_var(name##_lock);					\
+	return ret;							\
+ }									\
+ extern int name##_atomic_dec_and_write_lock__failed(atomic_t *a);	\
+ static inline int name##_atomic_dec_and_write_lock(atomic_t *a) {	\
+	if (atomic_add_unless(a, -1, 1))				\
+		return 0;						\
+	return name##_atomic_dec_and_write_lock__failed(a);		\
+ }
+
+#define DEFINE_BRLOCK(name)						\
+ DEFINE_PER_CPU(spinlock_t, name##_lock);				\
+ void name##_lock_init(void) {						\
+	int i;								\
+	for_each_possible_cpu(i) {					\
+		spinlock_t *lock;					\
+		lock = &per_cpu(name##_lock, i);			\
+		spin_lock_init(lock);					\
+	}								\
+ }									\
+ void name##_write_lock(void) {						\
+	int i;								\
+	for_each_online_cpu(i) {					\
+		spinlock_t *lock;					\
+		lock = &per_cpu(name##_lock, i);			\
+		spin_lock(lock);					\
+	}								\
+ }									\
+ void name##_write_unlock(void) {						\
+	int i;								\
+	for_each_online_cpu(i) {					\
+		spinlock_t *lock;					\
+		lock = &per_cpu(name##_lock, i);			\
+		spin_unlock(lock);					\
+	}								\
+ }									\
+ int name##_atomic_dec_and_write_lock__failed(atomic_t *a) {		\
+	name##_write_lock();						\
+	if (!atomic_dec_and_test(a)) {					\
+		name##_write_unlock();					\
+		return 0;						\
+	}								\
+	return 1;							\
+ }
+
+#else
+
+#define DECLARE_BRLOCK(name)						\
+ extern spinlock_t name##_lock;						\
+ static inline void name##_lock_init(void) {				\
+	spin_lock_init(&name##_lock);					\
+ }									\
+ static inline void name##_read_lock(void) {				\
+	spin_lock(&name##_lock);					\
+ }									\
+ static inline void name##_read_unlock(void) {				\
+	spin_unlock(&name##_lock);					\
+ }									\
+ static inline void name##_write_lock(void) {				\
+	spin_lock(&name##_lock);					\
+ }									\
+ static inline void name##_write_unlock(void) {				\
+	spin_unlock(&name##_lock);					\
+ }									\
+ static inline int name##_atomic_dec_and_read_lock(atomic_t *a) {	\
+	return atomic_dec_and_lock(a, &name##_lock);			\
+ }									\
+ static inline int name##_atomic_dec_and_write_lock(atomic_t *a) {	\
+	return atomic_dec_and_lock(a, &name##_lock);			\
+ }
+
+#define DEFINE_BRLOCK(name)						\
+ spinlock_t name##_lock
+#endif
+
+#endif

      reply	other threads:[~2010-03-17 14:18 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-03-16 12:22 [patch 1/2] kernel: introduce brlock Nick Piggin
2010-03-16 12:23 ` [patch 2/2] fs: scale vfsmount_lock Nick Piggin
2010-03-16 12:28   ` Nick Piggin
2010-03-17 14:20   ` Nick Piggin
2010-03-17 20:33     ` Andreas Dilger
2010-03-16 19:01 ` [patch 1/2] kernel: introduce brlock Andreas Dilger
2010-03-16 20:12   ` Frank Mayhar
2010-03-16 23:44   ` Nick Piggin
2010-03-17 14:18     ` Nick Piggin [this message]

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=20100317141830.GJ2869@laptop \
    --to=npiggin@suse.de \
    --cc=adilger@sun.com \
    --cc=ak@linux.intel.com \
    --cc=fmayhar@google.com \
    --cc=johnstul@us.ibm.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=viro@ZenIV.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.