From: Ashwin Chaugule <ashwinc@codeaurora.org>
To: linux-arm-kernel <linux-arm-kernel@lists.infradead.org>,
linux-arm-msm@vger.kernel.org, dhowells@redhat.com,
catalin.marinas@arm.com
Subject: [RFC] [PATCH] XCHGADD ARM implementation
Date: Tue, 05 Oct 2010 17:05:55 -0400 [thread overview]
Message-ID: <4CAB9333.50400@codeaurora.org> (raw)
[-- Attachment #1: Type: text/plain, Size: 497 bytes --]
The following patch is the ARM implementation for RWSEM_XCHGADD_ALGORITHM.
Based on David's rwsem benchmark from http://lwn.net/Articles/89191/ ,
I see a consistent 5-6% increase in the number of reads and writes taken as
compared to RWSEM_GENERIC_SPINLOCK on a dual core ARMv7. So far I have tested
numrd=1 numwr=1 numdg=1 do_sched=1
numrd=10 numwr=10 numdg=1 do_sched=1
numrd=20 numwr=20 numdg=1 do_sched=1
Can anyone else help to test this patch on other ARM systems ?
Cheers,
Ashwin
[-- Attachment #2: Optimzed-ARM-RWSEM-algorithm.patch --]
[-- Type: text/x-patch, Size: 5928 bytes --]
RWSEM implementation for ARM using atomic functions.
Heavily based on sh/include/asm/rwsem.h
Signed-off-by: Ashwin Chaugule <ashwinc@codeaurora.org>
---
arch/arm/Kconfig | 3 +-
arch/arm/include/asm/rwsem.h | 192 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 193 insertions(+), 2 deletions(-)
create mode 100644 arch/arm/include/asm/rwsem.h
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 871838b..0149b9f 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -129,10 +129,9 @@ config GENERIC_LOCKBREAK
config RWSEM_GENERIC_SPINLOCK
bool
- default y
config RWSEM_XCHGADD_ALGORITHM
- bool
+ def_bool y
config ARCH_HAS_ILOG2_U32
bool
diff --git a/arch/arm/include/asm/rwsem.h b/arch/arm/include/asm/rwsem.h
new file mode 100644
index 0000000..1730ee1
--- /dev/null
+++ b/arch/arm/include/asm/rwsem.h
@@ -0,0 +1,192 @@
+/* rwsem.h: R/W semaphores implemented using ARM atomic functions.
+ *
+ * Written by Ashwin Chaugule (ashwinc@codeaurora.org).
+ *
+ * Derived from arch/sh/asm/rwsem.h
+ *
+ * include/asm-arm/rwsem.h: R/W semaphores for ARM using the stuff
+ * in lib/rwsem.c.
+ *
+ * Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_ARM_RWSEM_H
+#define _ASM_ARM_RWSEM_H
+
+#ifndef _LINUX_RWSEM_H
+#error "please don't include asm/rwsem.h directly, use linux/rwsem.h instead"
+#endif
+
+#ifdef __KERNEL__
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <asm/atomic.h>
+#include <asm/system.h>
+
+/*
+ * the semaphore definition
+ */
+struct rw_semaphore {
+ long count;
+#define RWSEM_UNLOCKED_VALUE 0x00000000
+#define RWSEM_ACTIVE_BIAS 0x00000001
+#define RWSEM_ACTIVE_MASK 0x0000ffff
+#define RWSEM_WAITING_BIAS (-0x00010000)
+#define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS
+#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
+ spinlock_t wait_lock;
+ struct list_head wait_list;
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+ struct lockdep_map dep_map;
+#endif
+};
+
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+# define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname }
+#else
+# define __RWSEM_DEP_MAP_INIT(lockname)
+#endif
+
+#define __RWSEM_INITIALIZER(name) \
+ { RWSEM_UNLOCKED_VALUE, __SPIN_LOCK_UNLOCKED((name).wait_lock), \
+ LIST_HEAD_INIT((name).wait_list) \
+ __RWSEM_DEP_MAP_INIT(name) }
+
+#define DECLARE_RWSEM(name) \
+ struct rw_semaphore name = __RWSEM_INITIALIZER(name)
+
+extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
+extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
+extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
+extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
+
+extern void __init_rwsem(struct rw_semaphore *sem, const char *name,
+ struct lock_class_key *key);
+
+#define init_rwsem(sem) \
+do { \
+ static struct lock_class_key __key; \
+ \
+ __init_rwsem((sem), #sem, &__key); \
+} while (0)
+
+/*
+ * lock for reading
+ */
+static inline void __down_read(struct rw_semaphore *sem)
+{
+ if (atomic_inc_return((atomic_t *)(&sem->count)) < 0)
+ rwsem_down_read_failed(sem);
+}
+
+static inline int __down_read_trylock(struct rw_semaphore *sem)
+{
+ int tmp;
+
+ while ((tmp = sem->count) >= 0) {
+ if (tmp == cmpxchg(&sem->count, tmp,
+ tmp + RWSEM_ACTIVE_READ_BIAS)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * lock for writing
+ */
+static inline void __down_write(struct rw_semaphore *sem)
+{
+ int tmp;
+
+ tmp = atomic_add_return(RWSEM_ACTIVE_WRITE_BIAS,
+ (atomic_t *)(&sem->count));
+ if (tmp != RWSEM_ACTIVE_WRITE_BIAS)
+ rwsem_down_write_failed(sem);
+}
+
+static inline int __down_write_trylock(struct rw_semaphore *sem)
+{
+ int tmp;
+
+ tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE,
+ RWSEM_ACTIVE_WRITE_BIAS);
+ return tmp == RWSEM_UNLOCKED_VALUE;
+}
+
+/*
+ * unlock after reading
+ */
+static inline void __up_read(struct rw_semaphore *sem)
+{
+ int tmp;
+
+ tmp = atomic_dec_return((atomic_t *)(&sem->count));
+ if (tmp < -1 && (tmp & RWSEM_ACTIVE_MASK) == 0)
+ rwsem_wake(sem);
+}
+
+/*
+ * unlock after writing
+ */
+static inline void __up_write(struct rw_semaphore *sem)
+{
+ if (atomic_sub_return(RWSEM_ACTIVE_WRITE_BIAS,
+ (atomic_t *)(&sem->count)) < 0)
+ rwsem_wake(sem);
+}
+
+/*
+ * implement atomic add functionality
+ */
+static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem)
+{
+ atomic_add(delta, (atomic_t *)(&sem->count));
+}
+
+/*
+ * downgrade write lock to read lock
+ */
+static inline void __downgrade_write(struct rw_semaphore *sem)
+{
+ int tmp;
+
+ tmp = atomic_add_return(-RWSEM_WAITING_BIAS, (atomic_t *)(&sem->count));
+ if (tmp < 0)
+ rwsem_downgrade_wake(sem);
+}
+
+static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
+{
+ __down_write(sem);
+}
+
+/*
+ * implement exchange and add functionality
+ */
+static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem)
+{
+ return atomic_add_return(delta, (atomic_t *)(&sem->count));
+}
+
+static inline int rwsem_is_locked(struct rw_semaphore *sem)
+{
+ return (sem->count != 0);
+}
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_ARM_RWSEM_H */
--
1.7.1
WARNING: multiple messages have this Message-ID (diff)
From: ashwinc@codeaurora.org (Ashwin Chaugule)
To: linux-arm-kernel@lists.infradead.org
Subject: [RFC] [PATCH] XCHGADD ARM implementation
Date: Tue, 05 Oct 2010 17:05:55 -0400 [thread overview]
Message-ID: <4CAB9333.50400@codeaurora.org> (raw)
The following patch is the ARM implementation for RWSEM_XCHGADD_ALGORITHM.
Based on David's rwsem benchmark from http://lwn.net/Articles/89191/ ,
I see a consistent 5-6% increase in the number of reads and writes taken as
compared to RWSEM_GENERIC_SPINLOCK on a dual core ARMv7. So far I have tested
numrd=1 numwr=1 numdg=1 do_sched=1
numrd=10 numwr=10 numdg=1 do_sched=1
numrd=20 numwr=20 numdg=1 do_sched=1
Can anyone else help to test this patch on other ARM systems ?
Cheers,
Ashwin
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Optimzed-ARM-RWSEM-algorithm.patch
Type: text/x-patch
Size: 5928 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20101005/12e3b202/attachment.bin>
next reply other threads:[~2010-10-05 21:05 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-10-05 21:05 Ashwin Chaugule [this message]
2010-10-05 21:05 ` [RFC] [PATCH] XCHGADD ARM implementation Ashwin Chaugule
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=4CAB9333.50400@codeaurora.org \
--to=ashwinc@codeaurora.org \
--cc=catalin.marinas@arm.com \
--cc=dhowells@redhat.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-arm-msm@vger.kernel.org \
/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.