about summary refs log tree commit diff
path: root/linuxthreads
diff options
context:
space:
mode:
Diffstat (limited to 'linuxthreads')
-rw-r--r--linuxthreads/ChangeLog6
-rw-r--r--linuxthreads/sysdeps/mips/pspinlock.c49
-rw-r--r--linuxthreads/sysdeps/mips/pt-machine.h91
3 files changed, 91 insertions, 55 deletions
diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog
index 88549fd534..3366f8ca10 100644
--- a/linuxthreads/ChangeLog
+++ b/linuxthreads/ChangeLog
@@ -1,3 +1,9 @@
+2000-07-12  Maciej W. Rozycki  <macro@ds2.pg.gda.pl>
+
+	* sysdeps/mips/pspinlock.c (__pthread_spin_lock): Implement for
+	R3K.
+	* sysdeps/mips/pt-machine.h (testandset): Likewise.
+
 2000-07-26  Andreas Jaeger  <aj@suse.de>
 
 	* pthread.c: Initialize p_sem_avail.
diff --git a/linuxthreads/sysdeps/mips/pspinlock.c b/linuxthreads/sysdeps/mips/pspinlock.c
index 906fb4ae60..7df3040bda 100644
--- a/linuxthreads/sysdeps/mips/pspinlock.c
+++ b/linuxthreads/sysdeps/mips/pspinlock.c
@@ -19,8 +19,12 @@
 
 #include <errno.h>
 #include <pthread.h>
+#include <sgidefs.h>
+#include <sys/tas.h>
 
 
+#if (_MIPS_ISA >= _MIPS_ISA_MIPS2)
+
 /* This implementation is similar to the one used in the Linux kernel.  */
 int
 __pthread_spin_lock (pthread_spinlock_t *lock)
@@ -28,22 +32,34 @@ __pthread_spin_lock (pthread_spinlock_t *lock)
   unsigned int tmp;
 
   asm volatile
-    (".set\tnoreorder\t\t\t# spin_lock\n"
-     ".set\tpush\n"
-     ".set\tmips2\n"
-     "1:\tll\t%1, %2\n\t"
-     "bnez\t%1, 1b\n\t"
-     " li\t%1, 1\n\t"
-     "sc\t%1, %0\n\t"
-     "beqz\t%1, 1b\n\t"
-     ".set\tpop\n"
-     ".set\treorder"
-     : "=o" (*lock), "=&r" (tmp)
-     : "o" (*lock)
+    ("\t\t\t# spin_lock\n\t"
+     "1:\n\t"
+     "ll	%1,%2\n\t"
+     ".set	push\n\t"
+     ".set	noreorder\n\t"
+     "bnez	%1,1b\n\t"
+     " li	%1,1\n\t"
+     ".set	pop\n\t"
+     "sc	%1,%0\n\t"
+     "beqz	%1,1b"
+     : "=m" (*lock), "=&r" (tmp)
+     : "m" (*lock)
      : "memory");
 
   return 0;
 }
+
+#else /* !(_MIPS_ISA >= _MIPS_ISA_MIPS2) */
+
+int
+__pthread_spin_lock (pthread_spinlock_t *lock)
+{
+  while (_test_and_set (lock, 1));
+  return 0;
+}
+
+#endif /* !(_MIPS_ISA >= _MIPS_ISA_MIPS2) */
+
 weak_alias (__pthread_spin_lock, pthread_spin_lock)
 
 
@@ -60,11 +76,10 @@ int
 __pthread_spin_unlock (pthread_spinlock_t *lock)
 {
   asm volatile
-    (".set\tnoreorder\t\t\t# spin_unlock\n\t"
-     "sw\t$0, %0\n\t"
-     ".set\treorder" 
-     : "=o" (*lock)
-     : "o" (*lock)
+    ("\t\t\t# spin_unlock\n\t"
+     "sw	$0,%0"
+     : "=m" (*lock)
+     :
      : "memory");
   return 0;
 }
diff --git a/linuxthreads/sysdeps/mips/pt-machine.h b/linuxthreads/sysdeps/mips/pt-machine.h
index 50765b183c..16e264017d 100644
--- a/linuxthreads/sysdeps/mips/pt-machine.h
+++ b/linuxthreads/sysdeps/mips/pt-machine.h
@@ -18,13 +18,10 @@
    You should have received a copy of the GNU Library General Public
    License along with the GNU C Library; see the file COPYING.LIB.  If
    not, write to the Free Software Foundation, Inc.,
-   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
-   TODO: This version makes use of MIPS ISA 2 features.  It won't
-   work on ISA 1.  These machines will have to take the overhead of
-   a sysmips(MIPS_ATOMIC_SET, ...) syscall which isn't implemented
-   yet correctly.  There is however a better solution for R3000
-   uniprocessor machines possible.  */
+#include <sgidefs.h>
+#include <sys/tas.h>
 
 #ifndef PT_EI
 # define PT_EI extern inline
@@ -35,30 +32,43 @@
 
 
 /* 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"
-	".set\tmips2\n"
-	"1:\tll\t%0,%3\n\t"
-	"bnez\t%0,2f\n\t"
-	".set\tnoreorder\n\t"
-	"li\t%1,1\n\t"
-	".set\treorder\n\t"
-	"sc\t%1,%2\n\t"
-	"beqz\t%1,1b\n"
-	"2:\t.set\tmips0\n\t"
-	"/* End spinlock test & set */"
-	: "=&r"(ret), "=&r" (temp), "=m"(*spinlock)
-	: "m"(*spinlock)
-	: "memory");
+  __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
    of the stack, just something somewhere in the current frame.  */
@@ -68,27 +78,32 @@ register char * stack_pointer __asm__ ("$29");
 
 /* Compare-and-swap for semaphores. */
 
+#if (_MIPS_ISA >= _MIPS_ISA_MIPS2)
+
 #define HAS_COMPARE_AND_SWAP
 PT_EI int
 __compare_and_swap (long int *p, long int oldval, long int newval)
 {
-  long ret;
-
-  __asm__ __volatile__ (
-	"/* Inline compare & swap */\n\t"
-	".set\tmips2\n"
-	"1:\tll\t%0,%4\n\t"
-	".set\tnoreorder\n\t"
-	"bne\t%0,%2,2f\n\t"
-	"move\t%0,%3\n\t"
-	".set\treorder\n\t"
-	"sc\t%0,%1\n\t"
-	"beqz\t%0,1b\n"
-	"2:\t.set\tmips0\n\t"
-	"/* End compare & swap */"
-	: "=&r"(ret), "=m"(*p)
-	: "r"(oldval), "r"(newval), "m"(*p)
-	: "memory");
+  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;
 }
+
+#endif /* (_MIPS_ISA >= _MIPS_ISA_MIPS2) */