"William A. Rowe, Jr." <[EMAIL PROTECTED]> writes: > Philip or Troy - would you care to prepare and test the backport to ensure > we can commit this for the next 0.9 release, coming within days?
The 1.2.x branch has changed the name/signature to apr_atomic_cas32 and no longer passes longs; it's not really clear what the 0.9.x branch should do with the high bits of the longs. There's another problem with the 0.9.x code, the threaded implementation provides no indication to the caller when mutex operations fail, although most mutex implementations are unlikely to fail. The 1.2.x code aborts when a mutex fails, so assuming the same should occur when high bits are set here's a patch. I don't have an IA64 but I believe the code gets used on x86: APR Atomic Test =============== Initializing the context OK Initializing the atomics OK testing apr_atomic_dec OK testing CAS OK testing CAS - match non-null OK testing CAS - no match OK testing CAS for pointers OK testing CAS for pointers - match non-null OK testing CAS for pointers - no match OK testing add OK testing add/inc OK Starting all the threads OK Waiting for threads to exit (Note that this may take a while to complete.) OK Checking if atomic worked OK Checking if nolock worked no surprise The no-locks didn't work. z = 864045 instead of 1000000 Port some of the atomic code from 1.2.x to 0.9.x, in particular make mutex operations that fail cause an abort and make the generic C implementation of apr_atomic_cas work on 64 bit platforms. Index: atomic/unix/apr_atomic.c =================================================================== --- atomic/unix/apr_atomic.c (revision 449122) +++ atomic/unix/apr_atomic.c (working copy) @@ -18,6 +18,8 @@ #include "apr_atomic.h" #include "apr_thread_mutex.h" +#include <stdlib.h> + #if !defined(apr_atomic_init) && !defined(APR_OVERRIDE_ATOMIC_INIT) #if APR_HAS_THREADS @@ -46,18 +48,18 @@ } #endif /*!defined(apr_atomic_init) && !defined(APR_OVERRIDE_ATOMIC_INIT) */ +/* abort() if 'x' does not evaluate to APR_SUCCESS. */ +#define CHECK(x) do { if ((x) != APR_SUCCESS) abort(); } while (0) + #if !defined(apr_atomic_add) && !defined(APR_OVERRIDE_ATOMIC_ADD) void apr_atomic_add(volatile apr_atomic_t *mem, apr_uint32_t val) { #if APR_HAS_THREADS apr_thread_mutex_t *lock = hash_mutex[ATOMIC_HASH(mem)]; - apr_uint32_t prev; - if (apr_thread_mutex_lock(lock) == APR_SUCCESS) { - prev = *mem; - *mem += val; - apr_thread_mutex_unlock(lock); - } + CHECK(apr_thread_mutex_lock(lock)); + *mem += val; + CHECK(apr_thread_mutex_unlock(lock)); #else *mem += val; #endif /* APR_HAS_THREADS */ @@ -69,13 +71,10 @@ { #if APR_HAS_THREADS apr_thread_mutex_t *lock = hash_mutex[ATOMIC_HASH(mem)]; - apr_uint32_t prev; - if (apr_thread_mutex_lock(lock) == APR_SUCCESS) { - prev = *mem; - *mem = val; - apr_thread_mutex_unlock(lock); - } + CHECK(apr_thread_mutex_lock(lock)); + *mem = val; + CHECK(apr_thread_mutex_unlock(lock)); #else *mem = val; #endif /* APR_HAS_THREADS */ @@ -87,13 +86,10 @@ { #if APR_HAS_THREADS apr_thread_mutex_t *lock = hash_mutex[ATOMIC_HASH(mem)]; - apr_uint32_t prev; - if (apr_thread_mutex_lock(lock) == APR_SUCCESS) { - prev = *mem; - (*mem)++; - apr_thread_mutex_unlock(lock); - } + CHECK(apr_thread_mutex_lock(lock)); + (*mem)++; + CHECK(apr_thread_mutex_unlock(lock)); #else (*mem)++; #endif /* APR_HAS_THREADS */ @@ -107,12 +103,11 @@ apr_thread_mutex_t *lock = hash_mutex[ATOMIC_HASH(mem)]; apr_uint32_t new; - if (apr_thread_mutex_lock(lock) == APR_SUCCESS) { - (*mem)--; - new = *mem; - apr_thread_mutex_unlock(lock); - return new; - } + CHECK(apr_thread_mutex_lock(lock)); + (*mem)--; + new = *mem; + CHECK(apr_thread_mutex_unlock(lock)); + return new; #else (*mem)--; #endif /* APR_HAS_THREADS */ @@ -123,26 +118,28 @@ #if !defined(apr_atomic_cas) && !defined(APR_OVERRIDE_ATOMIC_CAS) apr_uint32_t apr_atomic_cas(volatile apr_uint32_t *mem, long with, long cmp) { - long prev; + apr_uint32_t prev; #if APR_HAS_THREADS apr_thread_mutex_t *lock = hash_mutex[ATOMIC_HASH(mem)]; - if (apr_thread_mutex_lock(lock) == APR_SUCCESS) { - prev = *(long*)mem; - if (prev == cmp) { - *(long*)mem = with; - } - apr_thread_mutex_unlock(lock); - return prev; + if ((long)(apr_uint32_t)with != with || (long)(apr_uint32_t)cmp != cmp) + abort(); + CHECK(apr_thread_mutex_lock(lock)); + prev = *mem; + if (prev == (apr_uint32_t)cmp) { + *mem = (apr_uint32_t)with; } - return *(long*)mem; + CHECK(apr_thread_mutex_unlock(lock)); #else - prev = *(long*)mem; - if (prev == cmp) { - *(long*)mem = with; + if ((long)(apr_uint32_t)with != with || (long)(apr_uint32_t)cmp != cmp) { + abort(); } - return prev; + prev = *mem; + if (prev == (apr_uint32_t)cmp) { + *mem = (apr_uint32_t)with; + } #endif /* APR_HAS_THREADS */ + return prev; } #endif /*!defined(apr_atomic_cas) && !defined(APR_OVERRIDE_ATOMIC_CAS) */ @@ -153,21 +150,18 @@ #if APR_HAS_THREADS apr_thread_mutex_t *lock = hash_mutex[ATOMIC_HASH(mem)]; - if (apr_thread_mutex_lock(lock) == APR_SUCCESS) { - prev = *(void **)mem; - if (prev == cmp) { - *mem = with; - } - apr_thread_mutex_unlock(lock); - return prev; + CHECK(apr_thread_mutex_lock(lock)); + prev = *(void **)mem; + if (prev == cmp) { + *mem = with; } - return *(void **)mem; + CHECK(apr_thread_mutex_unlock(lock)); #else prev = *(void **)mem; if (prev == cmp) { *mem = with; } - return prev; #endif /* APR_HAS_THREADS */ + return prev; } #endif /*!defined(apr_atomic_cas) && !defined(APR_OVERRIDE_ATOMIC_CAS) */ -- Philip Martin -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]