Bugzilla bug #39696: implemented the NSPR atomic routines in
authorwtc%netscape.com
Wed, 31 May 2000 00:33:48 +0000
changeset 1396 5292295526b6f5f4a5212d5a0f45effb9a6b55b0
parent 1395 3b32a6650609cbcf71362b8b3244d882190bc80c
child 1397 6e331da334c4edbd1f2afab59c6b2d94397891cc
push idunknown
push userunknown
push dateunknown
bugs39696
Bugzilla bug #39696: implemented the NSPR atomic routines in assembly language for Solaris/x86. Modified files: _solaris.h, solaris.c, os_SunOS_x86.s
pr/include/md/_solaris.h
pr/src/md/unix/os_SunOS_x86.s
pr/src/md/unix/solaris.c
--- a/pr/include/md/_solaris.h
+++ b/pr/include/md/_solaris.h
@@ -40,25 +40,27 @@
 #endif
 
 #undef	HAVE_WEAK_MALLOC_SYMBOLS
 #define	HAVE_DLL
 #define	USE_DLFCN
 #define NEED_STRFTIME_LOCK
 
 /*
+ * Intel x86 has atomic instructions.
+ *
  * Sparc v8 does not have instructions to efficiently implement
  * atomic increment/decrement operations.  In the local threads
  * only and pthreads versions, we use the default atomic routine
  * implementation in pratom.c.  The obsolete global threads only
  * version uses a global mutex_t to implement the atomic routines
  * in solaris.c, which is actually equivalent to the default
  * implementation.
  */
-#ifdef _PR_GLOBAL_THREADS_ONLY
+#if defined(i386) || defined(_PR_GLOBAL_THREADS_ONLY)
 #define _PR_HAVE_ATOMIC_OPS
 #endif
 
 #if defined(_PR_GLOBAL_THREADS_ONLY) || defined(_PR_PTHREADS)
 /*
  * We have assembly language implementation of atomic
  * stacks for the 32-bit sparc and x86 architectures only.
  */
--- a/pr/src/md/unix/os_SunOS_x86.s
+++ b/pr/src/md/unix/os_SunOS_x86.s
@@ -54,16 +54,94 @@ sol_getsp:
 /
 / Return a unique identifier for the currently active thread.
 /
 	.globl sol_curthread
 sol_curthread:
 	movl	%ecx, %eax
 	ret
 
+/ PRInt32 _MD_AtomicIncrement(PRInt32 *val)
+/
+/ Atomically increment the integer pointed to by 'val' and return
+/ the result of the increment.
+/
+    .text
+    .globl _MD_AtomicIncrement
+    .align 4
+_MD_AtomicIncrement:
+    movl 4(%esp), %ecx
+    movl $1, %eax
+    lock
+    xaddl %eax, (%ecx)
+    incl %eax
+    ret
+
+/ PRInt32 _MD_AtomicDecrement(PRInt32 *val)
+/
+/ Atomically decrement the integer pointed to by 'val' and return
+/ the result of the decrement.
+/
+    .text
+    .globl _MD_AtomicDecrement
+    .align 4
+_MD_AtomicDecrement:
+    movl 4(%esp), %ecx
+    movl $-1, %eax
+    lock
+    xaddl %eax, (%ecx)
+    decl %eax
+    ret
+
+/ PRInt32 _MD_AtomicSet(PRInt32 *val, PRInt32 newval)
+/
+/ Atomically set the integer pointed to by 'val' to the new
+/ value 'newval' and return the old value.
+/
+/ An alternative implementation:
+/   .text
+/   .globl _MD_AtomicSet
+/   .align 4
+/_MD_AtomicSet:
+/   movl 4(%esp), %ecx
+/   movl 8(%esp), %edx
+/   movl (%ecx), %eax
+/retry:
+/   lock
+/   cmpxchgl %edx, (%ecx)
+/   jne retry
+/   ret
+/
+    .text
+    .globl _MD_AtomicSet
+    .align 4
+_MD_AtomicSet:
+    movl 4(%esp), %ecx
+    movl 8(%esp), %eax
+    lock
+    xchgl %eax, (%ecx)
+    ret
+
+/ PRInt32 _MD_AtomicAdd(PRInt32 *ptr, PRInt32 val)
+/
+/ Atomically add 'val' to the integer pointed to by 'ptr'
+/ and return the result of the addition.
+/
+    .text
+    .globl _MD_AtomicAdd
+    .align 4
+_MD_AtomicAdd:
+    movl 4(%esp), %ecx
+    movl 8(%esp), %eax
+    movl %eax, %edx
+    lock
+    xaddl %eax, (%ecx)
+    addl %edx, %eax
+    ret
+
 /
 / PR_StackPush(listp, elementp)
 /
 / Atomically push ElementP onto linked list ListP.
 /
 	.text
 	.globl	PR_StackPush
 	.align	4
--- a/pr/src/md/unix/solaris.c
+++ b/pr/src/md/unix/solaris.c
@@ -64,16 +64,17 @@ void _MD_EarlyInit(void)
 
 PRWord *_MD_HomeGCRegisters(PRThread *t, PRIntn isCurrent, PRIntn *np)
 {
 	*np = 0;
 	return NULL;
 }
 #endif /* _PR_PTHREADS */
 
+#if !defined(i386)
 #if defined(_PR_HAVE_ATOMIC_OPS)
 /* NOTE:
  * SPARC v9 (Ultras) do have an atomic test-and-set operation.  But
  * SPARC v8 doesn't.  We should detect in the init if we are running on
  * v8 or v9, and then use assembly where we can.
  *
  * This code uses the Solaris threads API.  It can be used in both the
  * pthreads and Solaris threads versions of nspr20 because "POSIX threads
@@ -142,16 +143,17 @@ PRInt32
     *val = newval;
 
     if (mutex_unlock(&_solaris_atomic) != 0)\
         PR_ASSERT(0);
 
 	return rv;
 }
 #endif  /* _PR_HAVE_ATOMIC_OPS */
+#endif  /* !defined(i386) */
 
 #if defined(_PR_GLOBAL_THREADS_ONLY)
 #include <signal.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <thread.h>
 
 #include <sys/lwp.h>