This is the mail archive of the libc-hacker@sources.redhat.com mailing list for the glibc project.

Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[PATCH] Fix fastlocks on SMP


Hi!

The following patch seems to cure ex5, ex9 and ex10 on ia64/SMP. Basically, if
lock->__status had lowest bit set on spin_count 0, it would always spin
until max_count, since lock->__status was cached in a register and never
reloaded. __compare_and_swap clobbers it, but the codepath with
(__status & 1) == 1 skips that, so there is nothing which requires gcc not
to reload register caching lock->__status only inside of the conditionally
executed code.
The patch is attached in two variants, both seem to fix ex5, ex9 and ex10
(the tests which were previously failing on smp ia64), but the first results
in better code while the second one is perhaps more readable.
The assembly difference is in fact only:
ld8 r15=[r32];;
in first patch changed to
ld8.acq r15=[r32];;
in the second. I don't have ia64 manuals here at home so I cannot check, but
ld8.acq smells like it would do cache-line ping-pong which is the code
exactly trying to avoid (by only doing CAS if normal loads tells it could be
successful).

2001-02-17  Jakub Jelinek  <jakub@redhat.com>

	* spinlock.c (__pthread_lock): Force lock->__status to be read from
	memory on every spin.

	Jakub
--- linuxthreads/spinlock.c.jj	Sat Feb 17 16:09:57 2001
+++ linuxthreads/spinlock.c	Sat Feb 17 16:42:41 2001
@@ -88,6 +88,7 @@ again:
 	  return;
 	}
       }
+      __asm __volatile ("" : "=m" (lock->__status) : "0" (lock->__status));
     }
 
     lock->__spinlock += (spin_count - lock->__spinlock) / 8;
--- linuxthreads/spinlock.c.jj	Sat Feb 17 16:09:57 2001
+++ linuxthreads/spinlock.c	Sat Feb 17 16:16:20 2001
@@ -80,7 +80,7 @@ again:
     int max_count = lock->__spinlock * 2 + 10;
 
     for (spin_count = 0; spin_count < max_count; spin_count++) {
-      if (((oldstatus = lock->__status) & 1) == 0) {
+      if (((oldstatus = *(volatile long int *)&lock->__status) & 1) == 0) {
 	if(__compare_and_swap(&lock->__status, oldstatus, oldstatus | 1))
 	{
 	  if (spin_count)

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]