All of lore.kernel.org
 help / color / mirror / Atom feed
From: Johannes Stezenbach <js@convergence.de>
To: "Kevin D. Kissell" <kevink@mips.com>
Cc: linux-mips@oss.sgi.com
Subject: LL/SC benchmarking [was: Mipsel libc with LL/SC online anywhere?]
Date: Fri, 19 Jul 2002 14:38:29 +0200	[thread overview]
Message-ID: <20020719123828.GA5521@convergence.de> (raw)
In-Reply-To: <00ce01c229a4$a7d4ed40$10eca8c0@grendel>

On Fri, Jul 12, 2002 at 03:04:07PM +0200, Kevin D. Kissell wrote:
> I'm benchmarking some code that does lots of
> semaphores, and with the libc from the "standard"
> MIPS/SGI RH 7.1 distribution, those are done using
> sysmips, in the interest of universality.

I'm working on a platform without LL/SC, an embedded system/SOC
with a NEC VR4120A CPU core. To find out the effect of sysmips
vs. emulated LL/SC vs. the branch-likely trick posted by
Kevin D. Kissell <kevink@mips.com> on Tue, 22 Jan 2002 18:16:25 +0100
I created an experimental patch for glibc-2.2.5 which allows
run-time switching of the _test_and_set() and __compare_and_swap()
implementation based on the presence of two "switch files" in /etc/.

Despite its ugliness, I include the patch below for those interested.
(Note: I built my glibc with -mips2, so the patch lacks .set mips2
directives.)

One thing that caused me some headaches was that the __compare_and_swap()
implementation in glibc-2.2.5 is broken (but fixed in glibc CVS and H.J.Lu's
patch).

For lack of a better benchmark I used some of the examples from
glibc-2.2.5/linuxthreads/Examples. The numbers are from the third
of three successive runs of 'time exN >/dev/null'.

sysmips:
  ex1	real    0m0.273s 	user    0m0.040s 	sys     0m0.230s
  ex2	real    0m10.911s 	user    0m2.730s 	sys     0m8.180s
  ex3	real    0m3.648s 	user    0m3.400s 	sys     0m0.250s
  ex5	real    0m4.539s 	user    0m1.830s 	sys     0m2.710s

ll/sc emulation:
  ex1	real    0m0.272s 	user    0m0.020s 	sys     0m0.250s
  ex2	real    0m4.726s 	user    0m1.660s 	sys     0m3.060s
  ex3	real    0m3.968s 	user    0m3.750s 	sys     0m0.220s
  ex5	real    0m4.069s 	user    0m1.710s 	sys     0m2.360s

beql-hack:
  ex1	real    0m0.268s 	user    0m0.010s 	sys     0m0.260s
  ex2	real    0m3.988s 	user    0m1.620s 	sys     0m2.360s
  ex3	real    0m3.965s 	user    0m3.740s 	sys     0m0.220s
  ex5	real    0m2.606s 	user    0m1.000s 	sys     0m1.600s

I think the poor performance of sysmips is caused by the absence of
__compare_and_swap(), which forces libpthread to use less efficient
implementations for semaphore and lock functions.

Running each of the four tests three times yields around one million
LL/SC emulations in /proc/cpuinfo.

I think the beql-hack needs a kernel patch to guarantee k1 !=
MAGIC_COOKIE after each eret, but for a those few tests I was just
taking my chance.

Next, I'm trying to run the pthread tests from LTP. If someone
has a better benchmark code for pthread performance, I'm interested.


Regards,
Johannes



diff -uarN glibc-2.2.5.orig/linuxthreads/sysdeps/mips/pspinlock.c glibc-2.2.5/linuxthreads/sysdeps/mips/pspinlock.c
--- glibc-2.2.5.orig/linuxthreads/sysdeps/mips/pspinlock.c	Thu Jul 18 14:28:07 2002
+++ glibc-2.2.5/linuxthreads/sysdeps/mips/pspinlock.c	Thu Jul 18 18:35:46 2002
@@ -23,7 +23,93 @@
 #include <sys/tas.h>
 #include "internals.h"
 
-#if (_MIPS_ISA >= _MIPS_ISA_MIPS2)
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+static int
+_compare_and_swap_mips2 (long int *p, long int oldval, long int newval)
+{
+  long int ret;
+
+  __asm__ __volatile__
+    ("/* Inline compare & swap */\n\t"
+     "1:\n\t"
+     "ll	%0,%4\n\t"
+     ".set	push\n"
+     ".set	noreorder\n\t"
+     "bne	%0,%2,2f\n\t"
+     "move	%0,$0\n\t"
+     "move	%0,%3\n\t"
+     ".set	pop\n\t"
+     "sc	%0,%1\n\t"
+     "beqz	%0,1b\n"
+     "2:\n\t"
+     "/* End compare & swap */"
+     : "=&r" (ret), "=m" (*p)
+     : "r" (oldval), "r" (newval), "m" (*p)
+     : "memory");
+
+  return ret;
+}
+
+static int
+_compare_and_swap_mips2_nollsc (long int *p, long int oldval, long int newval)
+{
+  long int r, t;
+
+  __asm__ __volatile__
+    (".set	push\n\t"
+     ".set	noreorder\n\t"
+     "li	%1,0xffaaffaa\n\t"	/* MAGIC_COOKIE */
+     "1:\n\t"
+     "move	$27,%1\n\t"		/* set k1 */
+     "lw	%0,%5\n\t"		/* r = *p */
+     "bne	%0,%3,3f\n\t"		/* if (r != oldval) return 0 */
+     "move	%0,$0\n\t"		/* r = 0 */
+     "move	%0,%4\n\t"		/* r = newval */
+     "beql	$27,%1,2f\n\t"		/* test k1 for change */
+     "sw	%0,%2\n\t"		/* *p = r; return 1 */
+     "b		1b\n\t"			/* k1 changed, retry */
+     "nop\n\t"
+     ".set	pop\n\t"
+     "2:\n"
+     "li	%0,1\n\t"		/* r = 1 */
+     "3:\n"
+     : "=&r" (r), "=&r" (t), "=m" (*p)
+     : "r" (oldval), "r" (newval), "m" (*p)
+     : "memory");
+
+  return r;
+}
+
+int
+compare_and_swap_is_available (void)
+{
+  int fp;
+  /* FIXME: write real test */
+  if ((fp =open ("/etc/mips2_cpu_without_llsc", O_RDONLY)) != -1)
+    {
+      close(fp);
+      _mips_compare_and_swap = _compare_and_swap_mips2_nollsc;
+      return 1;
+    }
+  if ((fp =open ("/etc/mips2_cpu_with_llsc", O_RDONLY)) != -1)
+    {
+      close(fp);
+      _mips_compare_and_swap = _compare_and_swap_mips2;
+      return 1;
+    }
+  return 0;
+}
+
+int (* _mips_compare_and_swap) (long int *p, long int oldval, long int newval)
+  = NULL;
+
+
+#if 0 && (_MIPS_ISA >= _MIPS_ISA_MIPS2)
+  /* don't nother, no one uses this... */
 
 /* This implementation is similar to the one used in the Linux kernel.  */
 int
diff -uarN glibc-2.2.5.orig/linuxthreads/sysdeps/mips/pt-machine.h glibc-2.2.5/linuxthreads/sysdeps/mips/pt-machine.h
--- glibc-2.2.5.orig/linuxthreads/sysdeps/mips/pt-machine.h	Thu Jul 18 14:28:13 2002
+++ glibc-2.2.5/linuxthreads/sysdeps/mips/pt-machine.h	Thu Jul 18 16:27:15 2002
@@ -33,41 +33,11 @@
 
 /* Spinlock implementation; required.  */
 
-#if (_MIPS_ISA >= _MIPS_ISA_MIPS2)
-
-PT_EI long int
-testandset (int *spinlock)
-{
-  long int ret, temp;
-
-  __asm__ __volatile__
-    ("/* Inline spinlock test & set */\n\t"
-     "1:\n\t"
-     "ll	%0,%3\n\t"
-     ".set	push\n\t"
-     ".set	noreorder\n\t"
-     "bnez	%0,2f\n\t"
-     " li	%1,1\n\t"
-     ".set	pop\n\t"
-     "sc	%1,%2\n\t"
-     "beqz	%1,1b\n"
-     "2:\n\t"
-     "/* End spinlock test & set */"
-     : "=&r" (ret), "=&r" (temp), "=m" (*spinlock)
-     : "m" (*spinlock)
-     : "memory");
-
-  return ret;
-}
-
-#else /* !(_MIPS_ISA >= _MIPS_ISA_MIPS2) */
-
 PT_EI long int
 testandset (int *spinlock)
 {
   return _test_and_set (spinlock, 1);
 }
-#endif /* !(_MIPS_ISA >= _MIPS_ISA_MIPS2) */
 
 
 /* Get some notion of the current stack.  Need not be exactly the top
@@ -78,32 +48,13 @@
 
 /* Compare-and-swap for semaphores. */
 
-#if (_MIPS_ISA >= _MIPS_ISA_MIPS2)
-
 #define HAS_COMPARE_AND_SWAP
+#define TEST_FOR_COMPARE_AND_SWAP
+extern int (* _mips_compare_and_swap) (long int *p, long int oldval, long int newval);
+extern int compare_and_swap_is_available (void);
+
 PT_EI int
 __compare_and_swap (long int *p, long int oldval, long int newval)
 {
-  long int ret;
-
-  __asm__ __volatile__
-    ("/* Inline compare & swap */\n\t"
-     "1:\n\t"
-     "ll	%0,%4\n\t"
-     ".set	push\n"
-     ".set	noreorder\n\t"
-     "bne	%0,%2,2f\n\t"
-     " move	%0,%3\n\t"
-     ".set	pop\n\t"
-     "sc	%0,%1\n\t"
-     "beqz	%0,1b\n"
-     "2:\n\t"
-     "/* End compare & swap */"
-     : "=&r" (ret), "=m" (*p)
-     : "r" (oldval), "r" (newval), "m" (*p)
-     : "memory");
-
-  return ret;
+  return _mips_compare_and_swap (p, oldval, newval);
 }
-
-#endif /* (_MIPS_ISA >= _MIPS_ISA_MIPS2) */
diff -uarN glibc-2.2.5.orig/sysdeps/unix/sysv/linux/mips/_test_and_set.c glibc-2.2.5/sysdeps/unix/sysv/linux/mips/_test_and_set.c
--- glibc-2.2.5.orig/sysdeps/unix/sysv/linux/mips/_test_and_set.c	Thu Jul 18 00:21:15 2002
+++ glibc-2.2.5/sysdeps/unix/sysv/linux/mips/_test_and_set.c	Thu Jul 18 14:39:01 2002
@@ -21,6 +21,12 @@
    defined in sys/tas.h  */
 
 #include <features.h>
+#include <sgidefs.h>
+#include <sys/sysmips.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
 
 #define _EXTERN_INLINE
 #ifndef __USE_EXTERN_INLINES
@@ -28,3 +34,80 @@
 #endif
 
 #include "sys/tas.h"
+
+
+static int
+_test_and_set_mips2_nollsc (int *p, int v) __THROW
+{
+  int r, t;
+
+  __asm__ __volatile__
+    (".set	push\n\t"
+     ".set	noreorder\n\t"
+     "li	%1,0xffaaffaa\n\t"	/* MAGIC_COOKIE */
+     "1:\n\t"
+     "move	$27,%1\n\t"		/* set k1 */
+     "lw	%0,%3\n\t"		/* r = *p */
+     "beq	%0,%4,2f\n\t"		/* if (*p == v) return r */
+     "beql	$27,%1,2f\n\t"		/* test k1 for change */
+     "sw	%4,%2\n\t"		/* *p = v; return r */
+     "b		1b\n\t"			/* retry */
+     "nop\n\t"
+     ".set	pop\n\t"
+     "2:\n"
+     : "=&r" (r), "=&r" (t), "=m" (*p)
+     : "m" (*p), "r" (v)
+     : "memory");
+
+  return r;
+}
+
+static int
+_test_and_set_mips2 (int *p, int v) __THROW
+{
+  int r, t;
+
+  __asm__ __volatile__
+    ("1:\n\t"
+     "ll	%0,%3\n\t"
+     ".set	push\n\t"
+     ".set	noreorder\n\t"
+     "beq	%0,%4,2f\n\t"
+     " move	%1,%4\n\t"
+     ".set	pop\n\t"
+     "sc	%1,%2\n\t"
+     "beqz	%1,1b\n"
+     "2:\n"
+     : "=&r" (r), "=&r" (t), "=m" (*p)
+     : "m" (*p), "r" (v)
+     : "memory");
+
+  return r;
+}
+
+static int
+_test_and_set_mips1 (int *p, int v) __THROW
+{
+  return sysmips (MIPS_ATOMIC_SET, (int) p, v, 0);
+}
+
+static int
+_mips_test_and_set_init (int *p, int v) __THROW
+{
+  int fp;
+  _mips_test_and_set = _test_and_set_mips1;
+  /* FIXME: write real test */
+  if ((fp =open ("/etc/mips2_cpu_without_llsc", O_RDONLY)) != -1)
+    {
+      close(fp);
+      _mips_test_and_set = _test_and_set_mips2_nollsc;
+    }
+  else if ((fp =open ("/etc/mips2_cpu_with_llsc", O_RDONLY)) != -1)
+    {
+      close(fp);
+      _mips_test_and_set = _test_and_set_mips2;
+    }
+  return _mips_test_and_set (p, v);
+}
+
+int (* _mips_test_and_set) (int *p, int v) __THROW = _mips_test_and_set_init;
diff -uarN glibc-2.2.5.orig/sysdeps/unix/sysv/linux/mips/sys/tas.h glibc-2.2.5/sysdeps/unix/sysv/linux/mips/sys/tas.h
--- glibc-2.2.5.orig/sysdeps/unix/sysv/linux/mips/sys/tas.h	Thu Jul 18 00:13:21 2002
+++ glibc-2.2.5/sysdeps/unix/sysv/linux/mips/sys/tas.h	Thu Jul 18 00:26:54 2002
@@ -27,6 +27,7 @@
 __BEGIN_DECLS
 
 extern int _test_and_set (int *p, int v) __THROW;
+extern int (* _mips_test_and_set) (int *p, int v) __THROW;
 
 #ifdef __USE_EXTERN_INLINES
 
@@ -34,40 +35,11 @@
 #  define _EXTERN_INLINE extern __inline
 # endif
 
-# if (_MIPS_ISA >= _MIPS_ISA_MIPS2)
-
-_EXTERN_INLINE int
-_test_and_set (int *p, int v) __THROW
-{
-  int r, t;
-
-  __asm__ __volatile__
-    ("1:\n\t"
-     "ll	%0,%3\n\t"
-     ".set	push\n\t"
-     ".set	noreorder\n\t"
-     "beq	%0,%4,2f\n\t"
-     " move	%1,%4\n\t"
-     ".set	pop\n\t"
-     "sc	%1,%2\n\t"
-     "beqz	%1,1b\n"
-     "2:\n"
-     : "=&r" (r), "=&r" (t), "=m" (*p)
-     : "m" (*p), "r" (v)
-     : "memory");
-
-  return r;
-}
-
-# else /* !(_MIPS_ISA >= _MIPS_ISA_MIPS2) */
-
 _EXTERN_INLINE int
 _test_and_set (int *p, int v) __THROW
 {
-  return sysmips (MIPS_ATOMIC_SET, (int) p, v, 0);
+  return _mips_test_and_set (p, v);
 }
-
-# endif /* !(_MIPS_ISA >= _MIPS_ISA_MIPS2) */
 
 #endif /* __USE_EXTERN_INLINES */
 

  reply	other threads:[~2002-07-19 12:39 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-07-12 13:04 Mipsel libc with LL/SC online anywhere? Kevin D. Kissell
2002-07-12 13:04 ` Kevin D. Kissell
2002-07-19 12:38 ` Johannes Stezenbach [this message]
2002-07-19 15:54   ` LL/SC benchmarking [was: Mipsel libc with LL/SC online anywhere?] Richard Hodges
2002-07-22 10:35     ` Johannes Stezenbach
2002-07-25 16:25   ` Johannes Stezenbach
2002-07-25 17:06     ` Jun Sun
2002-07-25 18:45       ` Johannes Stezenbach
2002-07-25 18:56         ` Jun Sun
2002-07-25 19:24           ` Johannes Stezenbach
2002-07-25 21:49         ` Kevin D. Kissell
2002-07-26 19:35           ` Kevin D. Kissell

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=20020719123828.GA5521@convergence.de \
    --to=js@convergence.de \
    --cc=kevink@mips.com \
    --cc=linux-mips@oss.sgi.com \
    /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.