diff options
author | Jim Jagielski <jim@apache.org> | 2018-09-17 18:20:29 +0000 |
---|---|---|
committer | Jim Jagielski <jim@apache.org> | 2018-09-17 18:20:29 +0000 |
commit | dc82fc238131eb8bf43b955f4ef9af0943e386a1 (patch) | |
tree | 33c8c7a6e3876a1e53eea467aaa379a82df6536b /atomic | |
parent | 0c528e5b4f30b331baf45ca58287dad2c8ff11d1 (diff) | |
download | apr-dc82fc238131eb8bf43b955f4ef9af0943e386a1.tar.gz |
Merge r1841078 from trunk:
Add in Atomics for 64bit ints
Reviewed by: jim
git-svn-id: https://svn.apache.org/repos/asf/apr/apr/branches/1.7.x@1841109 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'atomic')
-rw-r--r-- | atomic/unix/builtins64.c | 64 | ||||
-rw-r--r-- | atomic/unix/mutex64.c | 177 | ||||
-rw-r--r-- | atomic/win32/apr_atomic64.c | 94 |
3 files changed, 335 insertions, 0 deletions
diff --git a/atomic/unix/builtins64.c b/atomic/unix/builtins64.c new file mode 100644 index 000000000..4a4b685c7 --- /dev/null +++ b/atomic/unix/builtins64.c @@ -0,0 +1,64 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_atomic.h" + +#ifdef USE_ATOMICS_BUILTINS + +APR_DECLARE(apr_uint64_t) apr_atomic_read64(volatile apr_uint64_t *mem) +{ + return *mem; +} + +APR_DECLARE(void) apr_atomic_set64(volatile apr_uint64_t *mem, apr_uint64_t val) +{ + *mem = val; +} + +APR_DECLARE(apr_uint64_t) apr_atomic_add64(volatile apr_uint64_t *mem, apr_uint64_t val) +{ + return __sync_fetch_and_add(mem, val); +} + +APR_DECLARE(void) apr_atomic_sub64(volatile apr_uint64_t *mem, apr_uint64_t val) +{ + __sync_fetch_and_sub(mem, val); +} + +APR_DECLARE(apr_uint64_t) apr_atomic_inc64(volatile apr_uint64_t *mem) +{ + return __sync_fetch_and_add(mem, 1); +} + +APR_DECLARE(int) apr_atomic_dec64(volatile apr_uint64_t *mem) +{ + return __sync_sub_and_fetch(mem, 1); +} + +APR_DECLARE(apr_uint64_t) apr_atomic_cas64(volatile apr_uint64_t *mem, apr_uint64_t with, + apr_uint64_t cmp) +{ + return __sync_val_compare_and_swap(mem, cmp, with); +} + +APR_DECLARE(apr_uint64_t) apr_atomic_xchg64(volatile apr_uint64_t *mem, apr_uint64_t val) +{ + __sync_synchronize(); + + return __sync_lock_test_and_set(mem, val); +} + +#endif /* USE_ATOMICS_BUILTINS */ diff --git a/atomic/unix/mutex64.c b/atomic/unix/mutex64.c new file mode 100644 index 000000000..10452413b --- /dev/null +++ b/atomic/unix/mutex64.c @@ -0,0 +1,177 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_atomic.h" + +#if defined(USE_ATOMICS_GENERIC) || defined (NEED_ATOMICS_GENERIC64) + +#include <stdlib.h> + +#if APR_HAS_THREADS +# define DECLARE_MUTEX_LOCKED(name, mem) \ + apr_thread_mutex_t *name = mutex_hash(mem) +# define MUTEX_UNLOCK(name) \ + do { \ + if (apr_thread_mutex_unlock(name) != APR_SUCCESS) \ + abort(); \ + } while (0) +#else +# define DECLARE_MUTEX_LOCKED(name, mem) +# define MUTEX_UNLOCK(name) +# warning Be warned: using stubs for all atomic operations +#endif + +#if APR_HAS_THREADS + +static apr_thread_mutex_t **hash_mutex; + +#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_status_t atomic_cleanup(void *data) +{ + if (hash_mutex == data) + hash_mutex = NULL; + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_atomic_init(apr_pool_t *p) +{ + int i; + apr_status_t rv; + + if (hash_mutex != NULL) + return APR_SUCCESS; + + hash_mutex = apr_palloc(p, sizeof(apr_thread_mutex_t*) * NUM_ATOMIC_HASH); + apr_pool_cleanup_register(p, hash_mutex, atomic_cleanup, + apr_pool_cleanup_null); + + for (i = 0; i < NUM_ATOMIC_HASH; i++) { + rv = apr_thread_mutex_create(&(hash_mutex[i]), + APR_THREAD_MUTEX_DEFAULT, p); + if (rv != APR_SUCCESS) { + return rv; + } + } + + return APR_SUCCESS; +} + +static APR_INLINE apr_thread_mutex_t *mutex_hash(volatile apr_uint64_t *mem) +{ + apr_thread_mutex_t *mutex = hash_mutex[ATOMIC_HASH(mem)]; + + if (apr_thread_mutex_lock(mutex) != APR_SUCCESS) { + abort(); + } + + return mutex; +} + +#else + +APR_DECLARE(apr_status_t) apr_atomic_init(apr_pool_t *p) +{ + return APR_SUCCESS; +} + +#endif /* APR_HAS_THREADS */ + +APR_DECLARE(apr_uint64_t) apr_atomic_read64(volatile apr_uint64_t *mem) +{ + return *mem; +} + +APR_DECLARE(void) apr_atomic_set64(volatile apr_uint64_t *mem, apr_uint64_t val) +{ + DECLARE_MUTEX_LOCKED(mutex, mem); + + *mem = val; + + MUTEX_UNLOCK(mutex); +} + +APR_DECLARE(apr_uint64_t) apr_atomic_add64(volatile apr_uint64_t *mem, apr_uint64_t val) +{ + apr_uint64_t old_value; + DECLARE_MUTEX_LOCKED(mutex, mem); + + old_value = *mem; + *mem += val; + + MUTEX_UNLOCK(mutex); + + return old_value; +} + +APR_DECLARE(void) apr_atomic_sub64(volatile apr_uint64_t *mem, apr_uint64_t val) +{ + DECLARE_MUTEX_LOCKED(mutex, mem); + *mem -= val; + MUTEX_UNLOCK(mutex); +} + +APR_DECLARE(apr_uint64_t) apr_atomic_inc64(volatile apr_uint64_t *mem) +{ + return apr_atomic_add64(mem, 1); +} + +APR_DECLARE(int) apr_atomic_dec64(volatile apr_uint64_t *mem) +{ + apr_uint64_t new; + DECLARE_MUTEX_LOCKED(mutex, mem); + + (*mem)--; + new = *mem; + + MUTEX_UNLOCK(mutex); + + return new; +} + +APR_DECLARE(apr_uint64_t) apr_atomic_cas64(volatile apr_uint64_t *mem, apr_uint64_t with, + apr_uint64_t cmp) +{ + apr_uint64_t prev; + DECLARE_MUTEX_LOCKED(mutex, mem); + + prev = *mem; + if (prev == cmp) { + *mem = with; + } + + MUTEX_UNLOCK(mutex); + + return prev; +} + +APR_DECLARE(apr_uint64_t) apr_atomic_xchg64(volatile apr_uint64_t *mem, apr_uint64_t val) +{ + apr_uint64_t prev; + DECLARE_MUTEX_LOCKED(mutex, mem); + + prev = *mem; + *mem = val; + + MUTEX_UNLOCK(mutex); + + return prev; +} + +#endif /* USE_ATOMICS_GENERIC64 */ diff --git a/atomic/win32/apr_atomic64.c b/atomic/win32/apr_atomic64.c new file mode 100644 index 000000000..a5acc945e --- /dev/null +++ b/atomic/win32/apr_atomic64.c @@ -0,0 +1,94 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_atomic.h" +#include "apr_thread_mutex.h" + +APR_DECLARE(apr_uint64_t) apr_atomic_add64(volatile apr_uint64_t *mem, apr_uint64_t val) +{ +#if (defined(_M_IA64) || defined(_M_AMD64)) + return InterlockedExchangeAdd64(mem, val); +#else + return InterlockedExchangeAdd64((long *)mem, val); +#endif +} + +/* Of course we want the 2's compliment of the unsigned value, val */ +#ifdef _MSC_VER +#pragma warning(disable: 4146) +#endif + +APR_DECLARE(void) apr_atomic_sub64(volatile apr_uint64_t *mem, apr_uint64_t val) +{ +#if (defined(_M_IA64) || defined(_M_AMD64)) + InterlockedExchangeAdd64(mem, -val); +#else + InterlockedExchangeAdd64((long *)mem, -val); +#endif +} + +APR_DECLARE(apr_uint64_t) apr_atomic_inc64(volatile apr_uint64_t *mem) +{ + /* we return old value, win64 returns new value :( */ +#if (defined(_M_IA64) || defined(_M_AMD64)) && !defined(RC_INVOKED) + return InterlockedIncrement64(mem) - 1; +#else + return InterlockedIncrement64((long *)mem) - 1; +#endif +} + +APR_DECLARE(int) apr_atomic_dec64(volatile apr_uint64_t *mem) +{ +#if (defined(_M_IA64) || defined(_M_AMD64)) && !defined(RC_INVOKED) + return InterlockedDecrement64(mem); +#else + return InterlockedDecrement64((long *)mem); +#endif +} + +APR_DECLARE(void) apr_atomic_set64(volatile apr_uint64_t *mem, apr_uint64_t val) +{ +#if (defined(_M_IA64) || defined(_M_AMD64)) && !defined(RC_INVOKED) + InterlockedExchange64(mem, val); +#else + InterlockedExchange64((long*)mem, val); +#endif +} + +APR_DECLARE(apr_uint64_t) apr_atomic_read64(volatile apr_uint64_t *mem) +{ + return *mem; +} + +APR_DECLARE(apr_uint64_t) apr_atomic_cas64(volatile apr_uint64_t *mem, apr_uint64_t with, + apr_uint64_t cmp) +{ +#if (defined(_M_IA64) || defined(_M_AMD64)) && !defined(RC_INVOKED) + return InterlockedCompareExchange64(mem, with, cmp); +#else + return InterlockedCompareExchange64((long*)mem, with, cmp); +#endif +} + +APR_DECLARE(apr_uint64_t) apr_atomic_xchg64(volatile apr_uint64_t *mem, apr_uint64_t val) +{ +#if (defined(_M_IA64) || defined(_M_AMD64)) && !defined(RC_INVOKED) + return InterlockedExchange64(mem, val); +#else + return InterlockedExchange64((long *)mem, val); +#endif +} |