about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuo Yixuan <culu.gyx@gmail.com>2014-06-03 16:19:11 -0700
committerDavid S. Miller <davem@davemloft.net>2014-06-03 16:19:58 -0700
commit02b1a8f86665320e961c2d12882ca0ba6112540a (patch)
treee9dcb29376f5b7a1f9bf0e2ce202460b5505741a
parentc3e44c48727747659e313f09bc5557b6c1007e49 (diff)
downloadglibc-release/2.16/master.tar.gz
glibc-release/2.16/master.tar.xz
glibc-release/2.16/master.zip
Fixed pthread_spin_lock on sparc32/64 (bug 16882) release/2.16/master
	[BZ #16882]
	* nptl/sysdeps/sparc/sparc32/pthread_spin_lock.S
	(pthread_spin_lock): Branch out of spin loop to proper location.
	* nptl/sysdeps/sparc/sparc64/pthread_spin_lock.S
	(pthread_spin_lock): Likewise.

	* nptl/tst-spin4.c: New test.
	* nptl/Makefile (tests): Add tst-spin4.
-rw-r--r--ChangeLog11
-rw-r--r--NEWS2
-rw-r--r--nptl/Makefile2
-rw-r--r--nptl/sysdeps/sparc/sparc32/pthread_spin_lock.S4
-rw-r--r--nptl/sysdeps/sparc/sparc64/pthread_spin_lock.S4
-rw-r--r--nptl/tst-spin4.c109
6 files changed, 126 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index 16ff227392..aa09ea1fdd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2014-06-03  Guo Yixuan  <culu.gyx@gmail.com>
+
+	[BZ #16882]
+	* nptl/sysdeps/sparc/sparc32/pthread_spin_lock.S
+	(pthread_spin_lock): Branch out of spin loop to proper location.
+	* nptl/sysdeps/sparc/sparc64/pthread_spin_lock.S
+	(pthread_spin_lock): Likewise.
+
+	* nptl/tst-spin4.c: New test.
+	* nptl/Makefile (tests): Add tst-spin4.
+
 2014-05-16  Aurelien Jarno  <aurelien@aurel32.net>
 
 	[BZ #16943]
diff --git a/NEWS b/NEWS
index 8702a3a51f..2ffc962242 100644
--- a/NEWS
+++ b/NEWS
@@ -38,7 +38,7 @@ Version 2.16
   14040, 14043, 14044, 14048, 14049, 14050, 14053, 14055, 14059, 14064,
   14075, 14080, 14083, 14103, 14104, 14109, 14112, 14117, 14122, 14123,
   14134, 14153, 14183, 14188, 14199, 14210, 14218, 14229, 14241, 14273,
-  14277, 14278
+  14277, 14278, 16882
 
 * Support for the x32 ABI on x86-64 added.  The x32 target is selected by
   configuring glibc with:
diff --git a/nptl/Makefile b/nptl/Makefile
index ef8e874cd8..1a9a676c76 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -202,7 +202,7 @@ tests = tst-typesizes \
 	tst-mutexpi1 tst-mutexpi2 tst-mutexpi3 tst-mutexpi4 tst-mutexpi5 \
 	tst-mutexpi5a tst-mutexpi6 tst-mutexpi7 tst-mutexpi7a tst-mutexpi8 \
 	tst-mutexpi9 \
-	tst-spin1 tst-spin2 tst-spin3 \
+	tst-spin1 tst-spin2 tst-spin3 tst-spin4 \
 	tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 \
 	tst-cond8 tst-cond9 tst-cond10 tst-cond11 tst-cond12 tst-cond13 \
 	tst-cond14 tst-cond15 tst-cond16 tst-cond17 tst-cond18 tst-cond19 \
diff --git a/nptl/sysdeps/sparc/sparc32/pthread_spin_lock.S b/nptl/sysdeps/sparc/sparc32/pthread_spin_lock.S
index 3155121700..703dbca69d 100644
--- a/nptl/sysdeps/sparc/sparc32/pthread_spin_lock.S
+++ b/nptl/sysdeps/sparc/sparc32/pthread_spin_lock.S
@@ -19,11 +19,11 @@
 
 	.text
 ENTRY(pthread_spin_lock)
-	ldstub		[%o0], %g1
+1:	ldstub		[%o0], %g1
 	orcc		%g1, 0x0, %g0
 	bne,a		2f
 	 ldub		[%o0], %g1
-1:	retl
+	retl
 	 mov		0, %o0
 2:	orcc		%g1, 0x0, %g0
 	bne,a		2b
diff --git a/nptl/sysdeps/sparc/sparc64/pthread_spin_lock.S b/nptl/sysdeps/sparc/sparc64/pthread_spin_lock.S
index cd3b01fcb0..d52c4a6b41 100644
--- a/nptl/sysdeps/sparc/sparc64/pthread_spin_lock.S
+++ b/nptl/sysdeps/sparc/sparc64/pthread_spin_lock.S
@@ -19,10 +19,10 @@
 
 	.text
 ENTRY(pthread_spin_lock)
-	ldstub		[%o0], %g1
+1:	ldstub		[%o0], %g1
 	brnz,pn		%g1, 2f
 	 membar		#StoreLoad | #StoreStore
-1:	retl
+	retl
 	 mov		0, %o0
 2:	ldub		[%o0], %g1
 	brnz,pt		%g1, 2b
diff --git a/nptl/tst-spin4.c b/nptl/tst-spin4.c
new file mode 100644
index 0000000000..5b23a172ca
--- /dev/null
+++ b/nptl/tst-spin4.c
@@ -0,0 +1,109 @@
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static int count = 0;
+
+static void *
+thread_add_one (void *arg)
+{
+  int tmp;
+  pthread_spinlock_t *lock = (pthread_spinlock_t *) arg;
+
+  /* When do_test holds the lock for 1 sec, the two thread will be
+     in contention for the lock. */
+  if (pthread_spin_lock (lock) != 0)
+    {
+      puts ("thread_add_one(): spin_lock failed");
+      pthread_exit ((void *) 1l);
+    }
+
+  /* sleep 1s before modifying count */
+  tmp = count;
+  sleep (1);
+  count = tmp + 1;
+
+  if (pthread_spin_unlock (lock) != 0)
+    {
+      puts ("thread_add_one(): spin_unlock failed");
+      pthread_exit ((void *) 1l);
+    }
+
+  return NULL;
+}
+
+static int
+do_test (void)
+{
+  pthread_t thr1, thr2;
+  pthread_spinlock_t lock;
+  int tmp;
+
+  if (pthread_spin_init (&lock, PTHREAD_PROCESS_PRIVATE) != 0)
+    {
+      puts ("spin_init failed");
+      return 1;
+    }
+
+  if (pthread_spin_lock (&lock) != 0)
+    {
+      puts ("1st spin_lock failed");
+      return 1;
+    }
+
+  if (pthread_create (&thr1, NULL, thread_add_one, (void *) &lock) != 0)
+    {
+      puts ("1st pthread_create failed");
+      return 1;
+    }
+
+  if (pthread_create (&thr2, NULL, thread_add_one, (void *) &lock) != 0)
+    {
+      puts ("2nd pthread_create failed");
+      return 1;
+    }
+
+  /* sleep 1s before modifying count */
+  tmp = count;
+  sleep (1);
+  count = tmp + 1;
+
+  if (pthread_spin_unlock (&lock) != 0)
+    {
+      puts ("1st spin_unlock failed");
+      return 1;
+    }
+
+  void *status;
+  if (pthread_join (thr1, &status) != 0)
+    {
+      puts ("1st pthread_join failed");
+      return 1;
+    }
+  if (status != NULL)
+    {
+      puts ("failure in the 1st thread");
+      return 1;
+    }
+  if (pthread_join (thr2, &status) != 0)
+    {
+      puts ("2nd pthread_join failed");
+      return 1;
+    }
+  if (status != NULL)
+    {
+      puts ("failure in the 2nd thread");
+      return 1;
+    }
+
+  if (count != 3)
+    {
+      printf ("count is %d, should be 3\n", count);
+      return 1;
+    }
+  return 0;
+}
+
+#define TIMEOUT 5
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"