diff options
author | Shin-ichiro KAWASAKI <shinichiro.kawasaki.mg@hitachi.com> | 2009-08-04 19:14:22 +0900 |
---|---|---|
committer | Tony Sim <sim.chinyeow@renesas.com> | 2009-08-04 19:14:22 +0900 |
commit | c6af9114fc63accef839c2a413e18ab058f0beff (patch) | |
tree | 80086121d642da85c76c6d10c82025ed89a75db9 /libcutils | |
parent | 1f7aceb2229e76678f9878d4682f2a7c7048ea6f (diff) | |
download | system_core-c6af9114fc63accef839c2a413e18ab058f0beff.tar.gz system_core-c6af9114fc63accef839c2a413e18ab058f0beff.tar.bz2 system_core-c6af9114fc63accef839c2a413e18ab058f0beff.zip |
added SuperH atomic support to libcutils
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 98e59eee3..30f4a49ed 100644 --- a/libcutils/Android.mk +++ b/libcutils/Android.mk @@ -98,7 +98,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 000000000..acbea976d --- /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 65d7af0af..41faaa282 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" |