|
|
@@ -12,38 +12,17 @@
|
|
|
|
|
|
#include "slap.h"
|
|
|
|
|
|
-#ifdef SOLARIS
|
|
|
-PRUint64 _sparcv9_AtomicSet(PRUint64 *address, PRUint64 newval);
|
|
|
-PRUint64 _sparcv9_AtomicAdd(PRUint64 *address, PRUint64 val);
|
|
|
-PRUint64 _sparcv9_AtomicSub(PRUint64 *address, PRUint64 val);
|
|
|
-#endif
|
|
|
-
|
|
|
#ifdef HPUX
|
|
|
#ifdef ATOMIC_64BIT_OPERATIONS
|
|
|
#include <machine/sys/inline.h>
|
|
|
#endif
|
|
|
#endif
|
|
|
|
|
|
-#ifdef ATOMIC_64BIT_OPERATIONS
|
|
|
-#if defined(LINUX) && !HAVE_64BIT_ATOMIC_OP_FUNCS
|
|
|
-/* On systems that don't have the 64-bit GCC atomic builtins, we need to
|
|
|
- * implement our own atomic functions using inline assembly code. */
|
|
|
-PRUint64 __sync_add_and_fetch_8(PRUint64 *ptr, PRUint64 addval);
|
|
|
-PRUint64 __sync_sub_and_fetch_8(PRUint64 *ptr, PRUint64 subval);
|
|
|
-#define __sync_add_and_fetch __sync_add_and_fetch_8
|
|
|
-#define __sync_sub_and_fetch __sync_sub_and_fetch_8
|
|
|
-#endif
|
|
|
-#endif /* ATOMIC_64BIT_OPERATIONS */
|
|
|
-
|
|
|
-
|
|
|
/*
|
|
|
* Counter Structure
|
|
|
*/
|
|
|
typedef struct slapi_counter {
|
|
|
- PRUint64 value;
|
|
|
-#ifndef ATOMIC_64BIT_OPERATIONS
|
|
|
- Slapi_Mutex *lock;
|
|
|
-#endif
|
|
|
+ uint64_t value;
|
|
|
} slapi_counter;
|
|
|
|
|
|
/*
|
|
|
@@ -72,13 +51,6 @@ Slapi_Counter *slapi_counter_new()
|
|
|
void slapi_counter_init(Slapi_Counter *counter)
|
|
|
{
|
|
|
if (counter != NULL) {
|
|
|
-#ifndef ATOMIC_64BIT_OPERATIONS
|
|
|
- /* Create the lock if necessary. */
|
|
|
- if (counter->lock == NULL) {
|
|
|
- counter->lock = slapi_new_mutex();
|
|
|
- }
|
|
|
-#endif
|
|
|
-
|
|
|
/* Set the value to 0. */
|
|
|
slapi_counter_set_value(counter, 0);
|
|
|
}
|
|
|
@@ -93,9 +65,6 @@ void slapi_counter_init(Slapi_Counter *counter)
|
|
|
void slapi_counter_destroy(Slapi_Counter **counter)
|
|
|
{
|
|
|
if ((counter != NULL) && (*counter != NULL)) {
|
|
|
-#ifndef ATOMIC_64BIT_OPERATIONS
|
|
|
- slapi_destroy_mutex((*counter)->lock);
|
|
|
-#endif
|
|
|
slapi_ch_free((void **)counter);
|
|
|
}
|
|
|
}
|
|
|
@@ -105,7 +74,7 @@ void slapi_counter_destroy(Slapi_Counter **counter)
|
|
|
*
|
|
|
* Atomically increments a Slapi_Counter.
|
|
|
*/
|
|
|
-PRUint64 slapi_counter_increment(Slapi_Counter *counter)
|
|
|
+uint64_t slapi_counter_increment(Slapi_Counter *counter)
|
|
|
{
|
|
|
return slapi_counter_add(counter, 1);
|
|
|
}
|
|
|
@@ -117,7 +86,7 @@ PRUint64 slapi_counter_increment(Slapi_Counter *counter)
|
|
|
* that this will not prevent you from wrapping
|
|
|
* around 0.
|
|
|
*/
|
|
|
-PRUint64 slapi_counter_decrement(Slapi_Counter *counter)
|
|
|
+uint64_t slapi_counter_decrement(Slapi_Counter *counter)
|
|
|
{
|
|
|
return slapi_counter_subtract(counter, 1);
|
|
|
}
|
|
|
@@ -127,28 +96,20 @@ PRUint64 slapi_counter_decrement(Slapi_Counter *counter)
|
|
|
*
|
|
|
* Atomically add a value to a Slapi_Counter.
|
|
|
*/
|
|
|
-PRUint64 slapi_counter_add(Slapi_Counter *counter, PRUint64 addvalue)
|
|
|
+uint64_t slapi_counter_add(Slapi_Counter *counter, uint64_t addvalue)
|
|
|
{
|
|
|
- PRUint64 newvalue = 0;
|
|
|
+ uint64_t newvalue = 0;
|
|
|
#ifdef HPUX
|
|
|
- PRUint64 prev = 0;
|
|
|
+ uint64_t prev = 0;
|
|
|
#endif
|
|
|
|
|
|
if (counter == NULL) {
|
|
|
return newvalue;
|
|
|
}
|
|
|
|
|
|
-#ifndef ATOMIC_64BIT_OPERATIONS
|
|
|
- slapi_lock_mutex(counter->lock);
|
|
|
- counter->value += addvalue;
|
|
|
- newvalue = counter->value;
|
|
|
- slapi_unlock_mutex(counter->lock);
|
|
|
+#ifndef HPUX
|
|
|
+ newvalue = __atomic_add_fetch_8(&(counter->value), addvalue, __ATOMIC_SEQ_CST);
|
|
|
#else
|
|
|
-#ifdef LINUX
|
|
|
- newvalue = __sync_add_and_fetch(&(counter->value), addvalue);
|
|
|
-#elif defined(SOLARIS)
|
|
|
- newvalue = _sparcv9_AtomicAdd(&(counter->value), addvalue);
|
|
|
-#elif defined(HPUX)
|
|
|
/* fetchadd only works with values of 1, 4, 8, and 16. In addition, it requires
|
|
|
* it's argument to be an integer constant. */
|
|
|
if (addvalue == 1) {
|
|
|
@@ -173,7 +134,6 @@ PRUint64 slapi_counter_add(Slapi_Counter *counter, PRUint64 addvalue)
|
|
|
} while (prev != _Asm_cmpxchg(_FASZ_D, _SEM_ACQ, &(counter->value), newvalue, _LDHINT_NONE));
|
|
|
}
|
|
|
#endif
|
|
|
-#endif /* ATOMIC_64BIT_OPERATIONS */
|
|
|
|
|
|
return newvalue;
|
|
|
}
|
|
|
@@ -184,28 +144,20 @@ PRUint64 slapi_counter_add(Slapi_Counter *counter, PRUint64 addvalue)
|
|
|
* Atomically subtract a value from a Slapi_Counter. Note
|
|
|
* that this will not prevent you from wrapping around 0.
|
|
|
*/
|
|
|
-PRUint64 slapi_counter_subtract(Slapi_Counter *counter, PRUint64 subvalue)
|
|
|
+uint64_t slapi_counter_subtract(Slapi_Counter *counter, uint64_t subvalue)
|
|
|
{
|
|
|
- PRUint64 newvalue = 0;
|
|
|
+ uint64_t newvalue = 0;
|
|
|
#ifdef HPUX
|
|
|
- PRUint64 prev = 0;
|
|
|
+ uint64_t prev = 0;
|
|
|
#endif
|
|
|
|
|
|
if (counter == NULL) {
|
|
|
return newvalue;
|
|
|
}
|
|
|
|
|
|
-#ifndef ATOMIC_64BIT_OPERATIONS
|
|
|
- slapi_lock_mutex(counter->lock);
|
|
|
- counter->value -= subvalue;
|
|
|
- newvalue = counter->value;
|
|
|
- slapi_unlock_mutex(counter->lock);
|
|
|
+#ifndef HPUX
|
|
|
+ newvalue = __atomic_sub_fetch_8(&(counter->value), subvalue, __ATOMIC_SEQ_CST);
|
|
|
#else
|
|
|
-#ifdef LINUX
|
|
|
- newvalue = __sync_sub_and_fetch(&(counter->value), subvalue);
|
|
|
-#elif defined(SOLARIS)
|
|
|
- newvalue = _sparcv9_AtomicSub(&(counter->value), subvalue);
|
|
|
-#elif defined(HPUX)
|
|
|
/* fetchadd only works with values of -1, -4, -8, and -16. In addition, it requires
|
|
|
* it's argument to be an integer constant. */
|
|
|
if (subvalue == 1) {
|
|
|
@@ -230,7 +182,6 @@ PRUint64 slapi_counter_subtract(Slapi_Counter *counter, PRUint64 subvalue)
|
|
|
} while (prev != _Asm_cmpxchg(_FASZ_D, _SEM_ACQ, &(counter->value), newvalue, _LDHINT_NONE));
|
|
|
}
|
|
|
#endif
|
|
|
-#endif /* ATOMIC_64BIT_OPERATIONS */
|
|
|
|
|
|
return newvalue;
|
|
|
}
|
|
|
@@ -240,21 +191,15 @@ PRUint64 slapi_counter_subtract(Slapi_Counter *counter, PRUint64 subvalue)
|
|
|
*
|
|
|
* Atomically sets the value of a Slapi_Counter.
|
|
|
*/
|
|
|
-PRUint64 slapi_counter_set_value(Slapi_Counter *counter, PRUint64 newvalue)
|
|
|
+uint64_t slapi_counter_set_value(Slapi_Counter *counter, uint64_t newvalue)
|
|
|
{
|
|
|
- PRUint64 value = 0;
|
|
|
+ uint64_t value = 0;
|
|
|
|
|
|
if (counter == NULL) {
|
|
|
return value;
|
|
|
}
|
|
|
|
|
|
-#ifndef ATOMIC_64BIT_OPERATIONS
|
|
|
- slapi_lock_mutex(counter->lock);
|
|
|
- counter->value = newvalue;
|
|
|
- slapi_unlock_mutex(counter->lock);
|
|
|
- return newvalue;
|
|
|
-#else
|
|
|
-#ifdef LINUX
|
|
|
+#ifndef HPUX
|
|
|
/* Use our own inline assembly for an atomic set if
|
|
|
* the builtins aren't available. */
|
|
|
#if !HAVE_64BIT_ATOMIC_CAS_FUNC
|
|
|
@@ -290,18 +235,15 @@ PRUint64 slapi_counter_set_value(Slapi_Counter *counter, PRUint64 newvalue)
|
|
|
#endif
|
|
|
|
|
|
return newvalue;
|
|
|
-#else
|
|
|
+#else /* HAVE_64BIT_ATOMIC_CAS_FUNC */
|
|
|
while (1) {
|
|
|
- value = counter->value;
|
|
|
- if (__sync_bool_compare_and_swap(&(counter->value), value, newvalue)) {
|
|
|
+ value = __atomic_load_8(&(counter->value), __ATOMIC_SEQ_CST);
|
|
|
+ if (__atomic_compare_exchange_8(&(counter->value), &value, newvalue, PR_FALSE, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)){
|
|
|
return newvalue;
|
|
|
}
|
|
|
}
|
|
|
-#endif /* CPU_x86 || !HAVE_DECL___SYNC_ADD_AND_FETCH */
|
|
|
-#elif defined(SOLARIS)
|
|
|
- _sparcv9_AtomicSet(&(counter->value), newvalue);
|
|
|
- return newvalue;
|
|
|
-#elif defined(HPUX)
|
|
|
+#endif
|
|
|
+#else /* HPUX */
|
|
|
do {
|
|
|
value = counter->value;
|
|
|
/* Put value in a register for cmpxchg to compare against */
|
|
|
@@ -309,7 +251,6 @@ PRUint64 slapi_counter_set_value(Slapi_Counter *counter, PRUint64 newvalue)
|
|
|
} while (value != _Asm_cmpxchg(_FASZ_D, _SEM_ACQ, &(counter->value), newvalue, _LDHINT_NONE));
|
|
|
return newvalue;
|
|
|
#endif
|
|
|
-#endif /* ATOMIC_64BIT_OPERATIONS */
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
@@ -317,20 +258,15 @@ PRUint64 slapi_counter_set_value(Slapi_Counter *counter, PRUint64 newvalue)
|
|
|
*
|
|
|
* Returns the value of a Slapi_Counter.
|
|
|
*/
|
|
|
-PRUint64 slapi_counter_get_value(Slapi_Counter *counter)
|
|
|
+uint64_t slapi_counter_get_value(Slapi_Counter *counter)
|
|
|
{
|
|
|
- PRUint64 value = 0;
|
|
|
+ uint64_t value = 0;
|
|
|
|
|
|
if (counter == NULL) {
|
|
|
return value;
|
|
|
}
|
|
|
|
|
|
-#ifndef ATOMIC_64BIT_OPERATIONS
|
|
|
- slapi_lock_mutex(counter->lock);
|
|
|
- value = counter->value;
|
|
|
- slapi_unlock_mutex(counter->lock);
|
|
|
-#else
|
|
|
-#ifdef LINUX
|
|
|
+#ifndef HPUX
|
|
|
/* Use our own inline assembly for an atomic get if
|
|
|
* the builtins aren't available. */
|
|
|
#if !HAVE_64BIT_ATOMIC_CAS_FUNC
|
|
|
@@ -367,124 +303,22 @@ PRUint64 slapi_counter_get_value(Slapi_Counter *counter)
|
|
|
#else
|
|
|
: "memory", "eax", "ebx", "ecx", "edx", "cc");
|
|
|
#endif
|
|
|
-#else
|
|
|
+#else /* HAVE_64BIT_ATOMIC_CAS_FUNC */
|
|
|
while (1) {
|
|
|
- value = counter->value;
|
|
|
- if (__sync_bool_compare_and_swap(&(counter->value), value, value)) {
|
|
|
+ value = __atomic_load_8(&(counter->value), __ATOMIC_SEQ_CST);
|
|
|
+ if (__atomic_compare_exchange_8(&(counter->value), &value, value, PR_FALSE, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)){
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
-#endif /* CPU_x86 || !HAVE_DECL___SYNC_ADD_AND_FETCH */
|
|
|
-#elif defined(SOLARIS)
|
|
|
- while (1) {
|
|
|
- value = counter->value;
|
|
|
- if (value == _sparcv9_AtomicSet(&(counter->value), value)) {
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-#elif defined(HPUX)
|
|
|
+#endif
|
|
|
+#else /* HPUX */
|
|
|
do {
|
|
|
value = counter->value;
|
|
|
/* Put value in a register for cmpxchg to compare against */
|
|
|
_Asm_mov_to_ar(_AREG_CCV, value);
|
|
|
} while (value != _Asm_cmpxchg(_FASZ_D, _SEM_ACQ, &(counter->value), value, _LDHINT_NONE));
|
|
|
#endif
|
|
|
-#endif /* ATOMIC_64BIT_OPERATIONS */
|
|
|
|
|
|
return value;
|
|
|
}
|
|
|
|
|
|
-#ifdef ATOMIC_64BIT_OPERATIONS
|
|
|
-#if defined(LINUX) && !HAVE_64BIT_ATOMIC_OP_FUNCS
|
|
|
-/* On systems that don't have the 64-bit GCC atomic builtins, we need to
|
|
|
- * implement our own atomic add and subtract functions using inline
|
|
|
- * assembly code. */
|
|
|
-PRUint64 __sync_add_and_fetch_8(PRUint64 *ptr, PRUint64 addval)
|
|
|
-{
|
|
|
- PRUint64 retval = 0;
|
|
|
-
|
|
|
- /*
|
|
|
- * %0 = *ptr
|
|
|
- * %1 = retval
|
|
|
- * %2 = addval
|
|
|
- */
|
|
|
- __asm__ __volatile__(
|
|
|
-#ifdef CPU_x86
|
|
|
- /* Save the PIC register */
|
|
|
- " pushl %%ebx;"
|
|
|
-#endif /* CPU_x86 */
|
|
|
- /* Put value of *ptr in EDX:EAX */
|
|
|
- "retryadd: movl %0, %%eax;"
|
|
|
- " movl 4%0, %%edx;"
|
|
|
- /* Put addval in ECX:EBX */
|
|
|
- " movl %2, %%ebx;"
|
|
|
- " movl 4+%2, %%ecx;"
|
|
|
- /* Add value from EDX:EAX to value in ECX:EBX */
|
|
|
- " addl %%eax, %%ebx;"
|
|
|
- " adcl %%edx, %%ecx;"
|
|
|
- /* If EDX:EAX and *ptr are the same, replace ptr with ECX:EBX */
|
|
|
- " lock; cmpxchg8b %0;"
|
|
|
- " jnz retryadd;"
|
|
|
- /* Put new value into retval */
|
|
|
- " movl %%ebx, %1;"
|
|
|
- " movl %%ecx, 4%1;"
|
|
|
-#ifdef CPU_x86
|
|
|
- /* Restore the PIC register */
|
|
|
- " popl %%ebx"
|
|
|
-#endif /* CPU_x86 */
|
|
|
- : "+o" (*ptr), "=m" (retval)
|
|
|
- : "m" (addval)
|
|
|
-#ifdef CPU_x86
|
|
|
- : "memory", "eax", "ecx", "edx", "cc");
|
|
|
-#else
|
|
|
- : "memory", "eax", "ebx", "ecx", "edx", "cc");
|
|
|
-#endif
|
|
|
-
|
|
|
- return retval;
|
|
|
-}
|
|
|
-
|
|
|
-PRUint64 __sync_sub_and_fetch_8(PRUint64 *ptr, PRUint64 subval)
|
|
|
-{
|
|
|
- PRUint64 retval = 0;
|
|
|
-
|
|
|
- /*
|
|
|
- * %0 = *ptr
|
|
|
- * %1 = retval
|
|
|
- * %2 = subval
|
|
|
- */
|
|
|
- __asm__ __volatile__(
|
|
|
-#ifdef CPU_x86
|
|
|
- /* Save the PIC register */
|
|
|
- " pushl %%ebx;"
|
|
|
-#endif /* CPU_x86 */
|
|
|
- /* Put value of *ptr in EDX:EAX */
|
|
|
- "retrysub: movl %0, %%eax;"
|
|
|
- " movl 4%0, %%edx;"
|
|
|
- /* Copy EDX:EAX to ECX:EBX */
|
|
|
- " movl %%eax, %%ebx;"
|
|
|
- " movl %%edx, %%ecx;"
|
|
|
- /* Subtract subval from value in ECX:EBX */
|
|
|
- " subl %2, %%ebx;"
|
|
|
- " sbbl 4+%2, %%ecx;"
|
|
|
- /* If EDX:EAX and ptr are the same, replace *ptr with ECX:EBX */
|
|
|
- " lock; cmpxchg8b %0;"
|
|
|
- " jnz retrysub;"
|
|
|
- /* Put new value into retval */
|
|
|
- " movl %%ebx, %1;"
|
|
|
- " movl %%ecx, 4%1;"
|
|
|
-#ifdef CPU_x86
|
|
|
- /* Restore the PIC register */
|
|
|
- " popl %%ebx"
|
|
|
-#endif /* CPU_x86 */
|
|
|
- : "+o" (*ptr), "=m" (retval)
|
|
|
- : "m" (subval)
|
|
|
-#ifdef CPU_x86
|
|
|
- : "memory", "eax", "ecx", "edx", "cc");
|
|
|
-#else
|
|
|
- : "memory", "eax", "ebx", "ecx", "edx", "cc");
|
|
|
-#endif
|
|
|
-
|
|
|
- return retval;
|
|
|
-}
|
|
|
-#endif /* LINUX && !HAVE_64BIT_ATOMIC_OP_FUNCS */
|
|
|
-#endif /* ATOMIC_64BIT_OPERATIONS */
|