Hi,
got the message ... here is a patch for apr_atomic.c that makes
some changes to the Solaris 10 specific functions; others will
follow one at a time.
Unfortunately I don't have access to a Solaris 10 machine, so
this patch is untested (I will be able to test all subsequent
patches though ;-)
Regards, Colin
Notes
- The reason given to define USE_GENERIC_ATOMICS in line 28 is
bogus wrt. Solaris 10 because no inline assembler is used.
(The same will apply to Mac OS X/Darwin where again the OS
supplies most of the required functions.)
Changes to the Solaris 10 specific functions
- Fixed atomic_set_32 by adding an appropriate memory barrier.
- Added missing implementations for atomic_read32, atomic_add32,
atomic_sub32 and atomic_casptr.
- Moved #include <atomic.h> into the Solaris 10 section;
prevents redundant include if generic implementation is used.
- Fixed atomic_dec_32 and atomic_inc_32; the old versions were
NOT actually atomic because (a) there was no guarantee that
*mem was not changed between reding the value and performing
the atomic update, and (b) the read itself was not preceeded
by an appropriate memory barrier.
colin:apr/atomic/unix> svn diff
Index: apr_atomic.c
===================================================================
--- apr_atomic.c (revision 468850)
+++ apr_atomic.c (working copy)
@@ -21,9 +21,6 @@
#include "apr_private.h"
#include <stdlib.h>
-#if (defined(SOLARIS2) && SOLARIS2 >= 10)
-#include <atomic.h>
-#endif
#if defined(__GNUC__) && defined(__STRICT_ANSI__) &&
!defined(USE_GENERIC_ATOMICS)
/* force use of generic atomics if building e.g. with -std=c89, which
@@ -168,6 +165,8 @@
#if (defined(SOLARIS2) && SOLARIS2 >= 10) \
&& !defined(USE_GENERIC_ATOMICS)
+#include <atomic.h>
+
#if !defined(APR_OVERRIDE_ATOMIC_CAS32)
APR_DECLARE(apr_uint32_t) apr_atomic_cas32(volatile apr_uint32_t *mem,
apr_uint32_t with,
@@ -181,9 +180,7 @@
#if !defined(APR_OVERRIDE_ATOMIC_DEC32)
APR_DECLARE(int) apr_atomic_dec32(volatile apr_uint32_t *mem)
{
- apr_uint32_t prev = *mem;
- atomic_dec_32(mem);
- return prev != 1;
+ return atomic_dec_32_nv(mem) ? 1 : 0
}
#define APR_OVERRIDE_ATOMIC_DEC32
#endif /* APR_OVERRIDE_ATOMIC_DEC32 */
@@ -191,17 +188,43 @@
#if !defined(APR_OVERRIDE_ATOMIC_INC32)
APR_DECLARE(apr_uint32_t) apr_atomic_inc32(volatile apr_uint32_t *mem)
{
- apr_uint32_t prev = *mem;
- atomic_inc_32(mem);
- return prev;
+ return atomic_inc_32_nv(mem) - 1;
}
#define APR_OVERRIDE_ATOMIC_INC32
#endif /* APR_OVERRIDE_ATOMIC_INC32 */
+#if !defined(APR_OVERRIDE_ATOMIC_ADD32)
+APR_DECLARE(apr_uint32_t) apr_atomic_add32(apr_uint32_t *mem,
+ apr_uint32_t val)
+{
+ return atomic_add_32_nv(mem, val) - val;
+}
+#define APR_OVERRIDE_ATOMIC_ADD32
+#endif
+
+#if !defined(APR_OVERRIDE_ATOMIC_SUB32)
+APR_DECLARE(void) apr_atomic_sub32(apr_uint32_t *mem,
+ apr_uint32_t val)
+{
+ atomic_add_32(mem, -val);
+}
+#define APR_OVERRIDE_ATOMIC_SUB32
+#endif
+
+#if !defined(APR_OVERRIDE_ATOMIC_READ32)
+APR_DECLARE(apr_uint32_t) apr_atomic_read32(apr_uint32_t *mem)
+{
+ membar_enter();
+ return *mem;
+}
+#define APR_OVERRIDE_ATOMIC_READ32
+#endif
+
#if !defined(APR_OVERRIDE_ATOMIC_SET32)
APR_DECLARE(void) apr_atomic_set32(volatile apr_uint32_t *mem, apr_uint32_t
val)
{
*mem = val;
+ membar_exit();
}
#define APR_OVERRIDE_ATOMIC_SET32
#endif /* APR_OVERRIDE_ATOMIC_SET32 */
@@ -215,6 +238,17 @@
#define APR_OVERRIDE_ATOMIC_XCHG32
#endif /* APR_OVERRIDE_ATOMIC_XCHG32 */
+#if !define(APR_OVERRIDE_ATOMIC_CASPTR)
+APR_DECLARE(void*) apr_atomic_casptr(void **mem,
+ void *with,
+ void *cmp)
+{
+ return atomic_cas_ptr(mem, cmp, with);
+}
+#define APR_OVERRIDE_ATOMIC_CASPTR
+#endif
+
+
#endif /* SOLARIS2 && SOLARIS2 >= 10 */
#if !defined(APR_OVERRIDE_ATOMIC_INIT)