Skip to content

Commit

Permalink
Add in Atomics for 64bit ints
Browse files Browse the repository at this point in the history
git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1841078 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
jimjag committed Sep 17, 2018
1 parent 107602a commit 2f61f96
Show file tree
Hide file tree
Showing 8 changed files with 799 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
-*- coding: utf-8 -*-
Changes for APR 2.0.0

*) Atomics: Support for 64bit ints. [Jim Jagielski]

*) apr_jose: Add support for encoding and decoding of JSON Object
Signing and Encryption messages as per RFC7515, RFC7516, RFC7517
and RFC7519. [Graham Leggett]
Expand Down
4 changes: 4 additions & 0 deletions apr.dsp

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

64 changes: 64 additions & 0 deletions atomic/unix/builtins64.c
Original file line number Diff line number Diff line change
@@ -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 */
177 changes: 177 additions & 0 deletions atomic/unix/mutex64.c
Original file line number Diff line number Diff line change
@@ -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 */
94 changes: 94 additions & 0 deletions atomic/win32/apr_atomic64.c
Original file line number Diff line number Diff line change
@@ -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
}
Loading

0 comments on commit 2f61f96

Please sign in to comment.