diff options
author | brianp <brianp@13f79535-47bb-0310-9956-ffa450edef68> | 2002-08-31 22:56:18 +0000 |
---|---|---|
committer | brianp <brianp@13f79535-47bb-0310-9956-ffa450edef68> | 2002-08-31 22:56:18 +0000 |
commit | b3e7bfec4df6d8ccb2b657b5bbdf8f167e60a53d (patch) | |
tree | 88af6c656eab418b5732dd3037c661dd15f4515e | |
parent | dbff1f163f68c21dff1e62ce71606ece45731c96 (diff) | |
download | libapr-b3e7bfec4df6d8ccb2b657b5bbdf8f167e60a53d.tar.gz |
Cleaner mechanism for using platform-specific atomics on platforms
that override some of the default atomic functions but not others
git-svn-id: http://svn.apache.org/repos/asf/apr/apr/trunk@63842 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | atomic/unix/apr_atomic.c | 60 | ||||
-rw-r--r-- | include/apr_atomic.h | 86 |
2 files changed, 102 insertions, 44 deletions
diff --git a/atomic/unix/apr_atomic.c b/atomic/unix/apr_atomic.c index a17e1adaa..e28d0f94c 100644 --- a/atomic/unix/apr_atomic.c +++ b/atomic/unix/apr_atomic.c @@ -56,17 +56,18 @@ #include "apr_atomic.h" #include "apr_thread_mutex.h" -#if APR_HAS_THREADS - -#if defined(APR_ATOMIC_NEED_DEFAULT) || defined(APR_ATOMIC_NEED_CAS_DEFAULT) +#if !defined(apr_atomic_init) && !defined(APR_OVERRIDE_ATOMIC_INIT) +#if APR_HAS_THREADS #define NUM_ATOMIC_HASH 7 /* shift by 2 to get rid of alignment issues */ #define ATOMIC_HASH(x) (unsigned int)(((unsigned long)(x)>>2)%(unsigned int)NUM_ATOMIC_HASH) static apr_thread_mutex_t **hash_mutex; +#endif /* APR_HAS_THREADS */ apr_status_t apr_atomic_init(apr_pool_t *p) { +#if APR_HAS_THREADS int i; apr_status_t rv; hash_mutex = apr_palloc(p, sizeof(apr_thread_mutex_t*) * NUM_ATOMIC_HASH); @@ -78,13 +79,15 @@ apr_status_t apr_atomic_init(apr_pool_t *p) return rv; } } +#endif /* APR_HAS_THREADS */ return APR_SUCCESS; } -#endif /* APR_ATOMIC_NEED_DEFAULT || APR_ATOMIC_NEED_CAS_DEFAULT */ +#endif /*!defined(apr_atomic_init) && !defined(APR_OVERRIDE_ATOMIC_INIT) */ -#if defined(APR_ATOMIC_NEED_DEFAULT) +#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; @@ -93,10 +96,16 @@ void apr_atomic_add(volatile apr_atomic_t *mem, apr_uint32_t val) *mem += val; apr_thread_mutex_unlock(lock); } +#else + *mem += val; +#endif /* APR_HAS_THREADS */ } +#endif /*!defined(apr_atomic_add) && !defined(APR_OVERRIDE_ATOMIC_ADD) */ +#if !defined(apr_atomic_set) && !defined(APR_OVERRIDE_ATOMIC_SET) void apr_atomic_set(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; @@ -105,10 +114,16 @@ void apr_atomic_set(volatile apr_atomic_t *mem, apr_uint32_t val) *mem = val; apr_thread_mutex_unlock(lock); } +#else + *mem = val; +#endif /* APR_HAS_THREADS */ } +#endif /*!defined(apr_atomic_set) && !defined(APR_OVERRIDE_ATOMIC_SET) */ +#if !defined(apr_atomic_inc) && !defined(APR_OVERRIDE_ATOMIC_INC) void apr_atomic_inc(volatile apr_uint32_t *mem) { +#if APR_HAS_THREADS apr_thread_mutex_t *lock = hash_mutex[ATOMIC_HASH(mem)]; apr_uint32_t prev; @@ -117,10 +132,16 @@ void apr_atomic_inc(volatile apr_uint32_t *mem) (*mem)++; apr_thread_mutex_unlock(lock); } +#else + (*mem)++; +#endif /* APR_HAS_THREADS */ } +#endif /*!defined(apr_atomic_inc) && !defined(APR_OVERRIDE_ATOMIC_INC) */ +#if !defined(apr_atomic_dec) && !defined(APR_OVERRIDE_ATOMIC_DEC) int apr_atomic_dec(volatile apr_atomic_t *mem) { +#if APR_HAS_THREADS apr_thread_mutex_t *lock = hash_mutex[ATOMIC_HASH(mem)]; apr_uint32_t new; @@ -130,14 +151,17 @@ int apr_atomic_dec(volatile apr_atomic_t *mem) apr_thread_mutex_unlock(lock); return new; } +#else + (*mem)--; +#endif /* APR_HAS_THREADS */ return *mem; } +#endif /*!defined(apr_atomic_dec) && !defined(APR_OVERRIDE_ATOMIC_DEC) */ -#endif /* APR_ATOMIC_NEED_DEFAULT */ -#if defined(APR_ATOMIC_NEED_CAS_DEFAULT) - +#if !defined(apr_atomic_cas) && !defined(APR_OVERRIDE_ATOMIC_CASE) apr_uint32_t apr_atomic_cas(volatile apr_uint32_t *mem, long with, long cmp) { +#if APR_HAS_THREADS apr_thread_mutex_t *lock = hash_mutex[ATOMIC_HASH(mem)]; long prev; @@ -150,16 +174,12 @@ apr_uint32_t apr_atomic_cas(volatile apr_uint32_t *mem, long with, long cmp) return prev; } return *(long*)mem; -} -#endif /* APR_ATOMIC_NEED_CAS_DEFAULT */ - -#else /* !APR_HAS_THREADS */ - -#if !defined(apr_atomic_init) -apr_status_t apr_atomic_init(apr_pool_t *p) -{ - return APR_SUCCESS; -} -#endif /* !defined(apr_atomic_init) */ - +#else + prev = *(long*)mem; + if ( prev == cmp) { + *(long*)mem = with; + } + return prev; #endif /* APR_HAS_THREADS */ +} +#endif /*!defined(apr_atomic_dec) && !defined(APR_OVERRIDE_ATOMIC_DEC) */ diff --git a/include/apr_atomic.h b/include/apr_atomic.h index 9277658cf..e9189aa56 100644 --- a/include/apr_atomic.h +++ b/include/apr_atomic.h @@ -136,13 +136,14 @@ int apr_atomic_dec(volatile apr_atomic_t *mem); apr_uint32_t apr_atomic_cas(volatile apr_uint32_t *mem,long with,long cmp); #else /* !DOXYGEN */ -#if APR_FORCE_ATOMIC_GENERIC -#if APR_HAS_THREADS -#define APR_ATOMIC_NEED_DEFAULT 1 -#define APR_ATOMIC_NEED_CAS_DEFAULT 1 -#endif /* APR_HAS_THREADS */ +/* The following definitions provide optimized, OS-specific + * implementations of the APR atomic functions on various + * platforms. Any atomic operation that isn't redefined as + * a macro here will be declared as a function later, and + * apr_atomic.c will provide a mutex-based default implementation. + */ -#elif defined(WIN32) +#if defined(WIN32) typedef LONG apr_atomic_t; @@ -161,6 +162,7 @@ typedef LONG apr_atomic_t; #define apr_atomic_add(mem, val) atomic_add(mem,val) APR_DECLARE(int) apr_atomic_dec(apr_atomic_t *mem); +#define APR_OVERRIDE_ATOMIC_DEC 1 #define apr_atomic_inc(mem) atomic_inc(mem) #define apr_atomic_set(mem, val) (*mem = val) #define apr_atomic_read(mem) (*mem) @@ -178,9 +180,8 @@ APR_DECLARE(int) apr_atomic_dec(apr_atomic_t *mem); #define apr_atomic_set(mem, val) atomic_set_int(mem, val) #define apr_atomic_read(mem) (*mem) -#define APR_ATOMIC_NEED_CAS_DEFAULT 1 +#elif defined(__linux__) && defined(__i386__) && !APR_FORCE_ATOMIC_GENERIC -#elif defined(__linux__) && defined(__i386__) #define apr_atomic_t apr_uint32_t #define apr_atomic_cas(mem,with,cmp) \ ({ apr_atomic_t prev; \ @@ -190,12 +191,8 @@ APR_DECLARE(int) apr_atomic_dec(apr_atomic_t *mem); : "memory"); \ prev;}) -#define APR_ATOMIC_NEED_DEFAULT 1 -#if defined(APR_ATOMIC_NEED_CAS_DEFAULT) -#undef APR_ATOMIC_NEED_CAS_DEFAULT -#endif +#elif defined(__sparc__) || defined(sparc) && !APR_FORCE_ATOMIC_GENERIC -#elif defined(__sparc__) || defined(sparc) #define apr_atomic_t apr_uint32_t #define apr_atomic_read(p) *p @@ -217,6 +214,8 @@ apr_uint32_t apr_atomic_cas_sparc(volatile apr_uint32_t *mem, long with, long cm apr_int32_t apr_atomic_add(volatile apr_atomic_t *mem, apr_int32_t val); apr_uint32_t apr_atomic_cas(volatile apr_atomic_t *mem, apr_uint32_t swap, apr_uint32_t cmp); +#define APR_OVERRIDE_ATOMIC_ADD 1 +#define APR_OVERRIDE_ATOMIC_CAS 1 #define apr_atomic_inc(mem) apr_atomic_add(mem, 1) #define apr_atomic_dec(mem) apr_atomic_add(mem, -1) @@ -234,30 +233,69 @@ apr_uint32_t apr_atomic_cas(volatile apr_atomic_t *mem, apr_uint32_t swap, #define apr_atomic_read(p) (*p) #define apr_atomic_set(mem, val) (*mem = val) -#else -#if APR_HAS_THREADS -#define APR_ATOMIC_NEED_DEFAULT 1 -#define APR_ATOMIC_NEED_CAS_DEFAULT 1 -#endif /* APR_HAS_THREADS */ +#endif /* end big if-elseif switch for platform-specifics */ + -#endif /* !defined(WIN32) */ +/* Default implementation of the atomic API + * The definitions above may override some or all of the + * atomic functions with optimized, platform-specific versions. + * Any operation that hasn't been overridden as a macro above + * is declared as a function here, unless APR_OVERRIDE_ATOMIC_[OPERATION] + * is defined. (The purpose of the APR_OVERRIDE_ATOMIC_* is + * to allow a platform to declare an apr_atomic_*() function + * with a different signature than the default.) + */ + +#define APR_ATOMIC_NEED_DEFAULT_INIT 0 -#if defined(APR_ATOMIC_NEED_DEFAULT) +#if !defined(apr_atomic_t) #define apr_atomic_t apr_uint32_t -#define apr_atomic_read(p) *p +#endif + +#if !defined(apr_atomic_init) && !defined(APR_OVERRIDE_ATOMIC_INIT) apr_status_t apr_atomic_init(apr_pool_t *p); +#endif + +#if !defined(apr_atomic_read) && !defined(APR_OVERRIDE_ATOMIC_READ) +#define apr_atomic_read(p) *p +#endif + +#if !defined(apr_atomic_set) && !defined(APR_OVERRIDE_ATOMIC_SET) void apr_atomic_set(volatile apr_atomic_t *mem, apr_uint32_t val); +#define APR_ATOMIC_NEED_DEFAULT_INIT 1 +#endif + +#if !defined(apr_atomic_add) && !defined(APR_OVERRIDE_ATOMIC_ADD) void apr_atomic_add(volatile apr_atomic_t *mem, apr_uint32_t val); +#define APR_ATOMIC_NEED_DEFAULT_INIT 1 +#endif + +#if !defined(apr_atomic_inc) && !defined(APR_OVERRIDE_ATOMIC_INC) void apr_atomic_inc(volatile apr_atomic_t *mem); +#define APR_ATOMIC_NEED_DEFAULT_INIT 1 +#endif + +#if !defined(apr_atomic_dec) && !defined(APR_OVERRIDE_ATOMIC_DEC) int apr_atomic_dec(volatile apr_atomic_t *mem); +#define APR_ATOMIC_NEED_DEFAULT_INIT 1 #endif -#if defined(APR_ATOMIC_NEED_CAS_DEFAULT) -apr_status_t apr_atomic_init(apr_pool_t *p); +#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); +#define APR_ATOMIC_NEED_DEFAULT_INIT 1 +#endif + +/* If we're using the default versions of any of the atomic functions, + * we'll need the atomic init to set up mutexes. If a platform-specific + * override above has replaced the atomic_init with a macro, it's an error. + */ +#if APR_ATOMIC_NEED_DEFAULT_INIT +#if defined(apr_atomic_init) || defined(APR_OVERRIDE_ATOMIC_INIT) +#error Platform has redefined apr_atomic_init, but other default default atomics require a default apr_atomic_init #endif +#endif /* APR_ATOMIC_NEED_DEFAULT_INIT */ -#endif /* DOXYGEN */ +#endif /* !DOXYGEN */ #ifdef __cplusplus } #endif |