diff options
author | Jean-Baptiste Queru <jbq@google.com> | 2009-10-14 08:19:24 -0700 |
---|---|---|
committer | Jean-Baptiste Queru <jbq@google.com> | 2009-10-14 08:19:24 -0700 |
commit | b029e924285dfe5bd36d93d837eb00db1c7661fc (patch) | |
tree | 12de33569d2b5d8d06b7b422a2e16bd1b3c61993 /libcutils | |
parent | 96912ff719a506f43ad02b8f9cc741f52567cabb (diff) | |
parent | 74d7ff8cfd490852d3df1c4b9d8a21beed619caa (diff) | |
download | system_core-b029e924285dfe5bd36d93d837eb00db1c7661fc.zip system_core-b029e924285dfe5bd36d93d837eb00db1c7661fc.tar.gz system_core-b029e924285dfe5bd36d93d837eb00db1c7661fc.tar.bz2 |
merge from open-source master
Diffstat (limited to 'libcutils')
-rw-r--r-- | libcutils/Android.mk | 4 | ||||
-rw-r--r-- | libcutils/atomic-android-sh.c | 159 | ||||
-rw-r--r-- | libcutils/atomic.c | 4 |
3 files changed, 167 insertions, 0 deletions
diff --git a/libcutils/Android.mk b/libcutils/Android.mk index 1d1e576..6418590 100644 --- a/libcutils/Android.mk +++ b/libcutils/Android.mk @@ -104,7 +104,11 @@ LOCAL_SRC_FILES := $(commonSources) ashmem-dev.c mq.c ifeq ($(TARGET_ARCH),arm) LOCAL_SRC_FILES += memset32.S atomic-android-arm.S else # !arm +ifeq ($(TARGET_ARCH),sh) +LOCAL_SRC_FILES += memory.c atomic-android-sh.c +else # !sh LOCAL_SRC_FILES += memory.c +endif # !sh endif # !arm LOCAL_C_INCLUDES := $(KERNEL_HEADERS) diff --git a/libcutils/atomic-android-sh.c b/libcutils/atomic-android-sh.c new file mode 100644 index 0000000..acbea97 --- /dev/null +++ b/libcutils/atomic-android-sh.c @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed 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 <cutils/atomic.h> +#ifdef HAVE_WIN32_THREADS +#include <windows.h> +#else +#include <sched.h> +#endif + +/* + * Note : + * + * (1) SuperH does not have CMPXCHG. It has only TAS for atomic + * operations. It does not seem a good idea to implement CMPXCHG, + * with TAS. So, we choose to implemnt these operations with + * posix mutexes. Please be sure that this might cause performance + * problem for Android-SH. Using LL/SC instructions supported in SH-X3, + * best performnace would be realized. + * + * (2) Mutex initialization problem happens, which is commented for + * ARM implementation, in this file above. + * We follow the fact that the initializer for mutex is a simple zero + * value. + */ + +#include <pthread.h> + +#define SWAP_LOCK_COUNT 32U +static pthread_mutex_t _swap_locks[SWAP_LOCK_COUNT]; + +#define SWAP_LOCK(addr) \ + &_swap_locks[((unsigned)(void*)(addr) >> 3U) % SWAP_LOCK_COUNT] + + +void android_atomic_write(int32_t value, volatile int32_t* addr) { + int32_t oldValue; + do { + oldValue = *addr; + } while (android_atomic_cmpxchg(oldValue, value, addr)); +} + +int32_t android_atomic_inc(volatile int32_t* addr) { + int32_t oldValue; + do { + oldValue = *addr; + } while (android_atomic_cmpxchg(oldValue, oldValue+1, addr)); + return oldValue; +} + +int32_t android_atomic_dec(volatile int32_t* addr) { + int32_t oldValue; + do { + oldValue = *addr; + } while (android_atomic_cmpxchg(oldValue, oldValue-1, addr)); + return oldValue; +} + +int32_t android_atomic_add(int32_t value, volatile int32_t* addr) { + int32_t oldValue; + do { + oldValue = *addr; + } while (android_atomic_cmpxchg(oldValue, oldValue+value, addr)); + return oldValue; +} + +int32_t android_atomic_and(int32_t value, volatile int32_t* addr) { + int32_t oldValue; + do { + oldValue = *addr; + } while (android_atomic_cmpxchg(oldValue, oldValue&value, addr)); + return oldValue; +} + +int32_t android_atomic_or(int32_t value, volatile int32_t* addr) { + int32_t oldValue; + do { + oldValue = *addr; + } while (android_atomic_cmpxchg(oldValue, oldValue|value, addr)); + return oldValue; +} + +int32_t android_atomic_swap(int32_t value, volatile int32_t* addr) { + int32_t oldValue; + do { + oldValue = *addr; + } while (android_atomic_cmpxchg(oldValue, value, addr)); + return oldValue; +} + +int android_atomic_cmpxchg(int32_t oldvalue, int32_t newvalue, + volatile int32_t* addr) { + int result; + pthread_mutex_t* lock = SWAP_LOCK(addr); + + pthread_mutex_lock(lock); + + if (*addr == oldvalue) { + *addr = newvalue; + result = 0; + } else { + result = 1; + } + pthread_mutex_unlock(lock); + return result; +} + +int64_t android_quasiatomic_swap_64(int64_t value, volatile int64_t* addr) { + int64_t oldValue; + pthread_mutex_t* lock = SWAP_LOCK(addr); + + pthread_mutex_lock(lock); + + oldValue = *addr; + *addr = value; + + pthread_mutex_unlock(lock); + return oldValue; +} + +int android_quasiatomic_cmpxchg_64(int64_t oldvalue, int64_t newvalue, + volatile int64_t* addr) { + int result; + pthread_mutex_t* lock = SWAP_LOCK(addr); + + pthread_mutex_lock(lock); + + if (*addr == oldvalue) { + *addr = newvalue; + result = 0; + } else { + result = 1; + } + pthread_mutex_unlock(lock); + return result; +} + +int64_t android_quasiatomic_read_64(volatile int64_t* addr) { + int64_t result; + pthread_mutex_t* lock = SWAP_LOCK(addr); + + pthread_mutex_lock(lock); + result = *addr; + pthread_mutex_unlock(lock); + return result; +} diff --git a/libcutils/atomic.c b/libcutils/atomic.c index 65d7af0..41faaa2 100644 --- a/libcutils/atomic.c +++ b/libcutils/atomic.c @@ -245,6 +245,10 @@ int64_t android_quasiatomic_read_64(volatile int64_t* addr) { return result; } +/*****************************************************************************/ +#elif __sh__ +// implementation for SuperH is in atomic-android-sh.c. + #else #error "Unsupported atomic operations for this platform" |