From 5206d5971208fab8208669dabc98bbb9f7e4a45a Mon Sep 17 00:00:00 2001 From: Ben Cheng Date: Fri, 7 Dec 2012 10:54:09 -0800 Subject: [PATCH] Fail-proof the inline directives for SMP atomic operations. The various atomic operations are declared as inline in the header files to cut the function call overhead. However, the plain inline keyword is just a suggestion to the compiler which makes its own decision on whether to inline them or not. Worst, if they are not inlined, the -fvisibility-inlines-hidden compiler flag will render them as hidden symbols in the object file. If they are picked up by the linker over the ones supplied in libcutils.so the following warning will be reported: warning: hidden symbol 'android_atomic_inc' in foo.o is referenced by DSO bar.so One way is to add __attribute__((visibility("default"))) to those inline functions to suppress the linker warnings. A better way is to force inlining as with this patch. Change-Id: Ie4fcfdfaaf06f42d351619a0d89671a9df15ca2f --- include/cutils/atomic-arm.h | 82 +++++++++++++++++++++--------------- include/cutils/atomic-mips.h | 66 +++++++++++++++++------------ include/cutils/atomic-x86.h | 63 +++++++++++++++------------ libcutils/atomic.c | 2 +- 4 files changed, 124 insertions(+), 89 deletions(-) diff --git a/include/cutils/atomic-arm.h b/include/cutils/atomic-arm.h index 16fe51242..795afd39a 100644 --- a/include/cutils/atomic-arm.h +++ b/include/cutils/atomic-arm.h @@ -20,72 +20,78 @@ #include #include -extern inline void android_compiler_barrier(void) +#ifndef ANDROID_ATOMIC_INLINE +#define ANDROID_ATOMIC_INLINE inline __attribute__((always_inline)) +#endif + +extern ANDROID_ATOMIC_INLINE void android_compiler_barrier(void) { __asm__ __volatile__ ("" : : : "memory"); } #if ANDROID_SMP == 0 -extern inline void android_memory_barrier(void) +extern ANDROID_ATOMIC_INLINE void android_memory_barrier(void) { android_compiler_barrier(); } -extern inline void android_memory_store_barrier(void) +extern ANDROID_ATOMIC_INLINE void android_memory_store_barrier(void) { android_compiler_barrier(); } #elif defined(__ARM_HAVE_DMB) -extern inline void android_memory_barrier(void) +extern ANDROID_ATOMIC_INLINE void android_memory_barrier(void) { __asm__ __volatile__ ("dmb" : : : "memory"); } -extern inline void android_memory_store_barrier(void) +extern ANDROID_ATOMIC_INLINE void android_memory_store_barrier(void) { __asm__ __volatile__ ("dmb st" : : : "memory"); } #elif defined(__ARM_HAVE_LDREX_STREX) -extern inline void android_memory_barrier(void) +extern ANDROID_ATOMIC_INLINE void android_memory_barrier(void) { __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" : : "r" (0) : "memory"); } -extern inline void android_memory_store_barrier(void) +extern ANDROID_ATOMIC_INLINE void android_memory_store_barrier(void) { android_memory_barrier(); } #else -extern inline void android_memory_barrier(void) +extern ANDROID_ATOMIC_INLINE void android_memory_barrier(void) { typedef void (kuser_memory_barrier)(void); (*(kuser_memory_barrier *)0xffff0fa0)(); } -extern inline void android_memory_store_barrier(void) +extern ANDROID_ATOMIC_INLINE void android_memory_store_barrier(void) { android_memory_barrier(); } #endif -extern inline int32_t android_atomic_acquire_load(volatile const int32_t *ptr) +extern ANDROID_ATOMIC_INLINE +int32_t android_atomic_acquire_load(volatile const int32_t *ptr) { int32_t value = *ptr; android_memory_barrier(); return value; } -extern inline int32_t android_atomic_release_load(volatile const int32_t *ptr) +extern ANDROID_ATOMIC_INLINE +int32_t android_atomic_release_load(volatile const int32_t *ptr) { android_memory_barrier(); return *ptr; } -extern inline void android_atomic_acquire_store(int32_t value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE void +android_atomic_acquire_store(int32_t value, volatile int32_t *ptr) { *ptr = value; android_memory_barrier(); } -extern inline void android_atomic_release_store(int32_t value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE void +android_atomic_release_store(int32_t value, volatile int32_t *ptr) { android_memory_barrier(); *ptr = value; @@ -95,8 +101,8 @@ extern inline void android_atomic_release_store(int32_t value, extern int android_atomic_cas(int32_t old_value, int32_t new_value, volatile int32_t *ptr); #elif defined(__ARM_HAVE_LDREX_STREX) -extern inline int android_atomic_cas(int32_t old_value, int32_t new_value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int +android_atomic_cas(int32_t old_value, int32_t new_value, volatile int32_t *ptr) { int32_t prev, status; do { @@ -111,8 +117,8 @@ extern inline int android_atomic_cas(int32_t old_value, int32_t new_value, return prev != old_value; } #else -extern inline int android_atomic_cas(int32_t old_value, int32_t new_value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int +android_atomic_cas(int32_t old_value, int32_t new_value, volatile int32_t *ptr) { typedef int (kuser_cmpxchg)(int32_t, int32_t, volatile int32_t *); int32_t prev, status; @@ -127,18 +133,20 @@ extern inline int android_atomic_cas(int32_t old_value, int32_t new_value, } #endif -extern inline int android_atomic_acquire_cas(int32_t old_value, - int32_t new_value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int +android_atomic_acquire_cas(int32_t old_value, + int32_t new_value, + volatile int32_t *ptr) { int status = android_atomic_cas(old_value, new_value, ptr); android_memory_barrier(); return status; } -extern inline int android_atomic_release_cas(int32_t old_value, - int32_t new_value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int +android_atomic_release_cas(int32_t old_value, + int32_t new_value, + volatile int32_t *ptr) { android_memory_barrier(); return android_atomic_cas(old_value, new_value, ptr); @@ -149,8 +157,8 @@ extern inline int android_atomic_release_cas(int32_t old_value, extern int32_t android_atomic_add(int32_t increment, volatile int32_t *ptr); #elif defined(__ARM_HAVE_LDREX_STREX) -extern inline int32_t android_atomic_add(int32_t increment, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_add(int32_t increment, volatile int32_t *ptr) { int32_t prev, tmp, status; android_memory_barrier(); @@ -166,8 +174,8 @@ extern inline int32_t android_atomic_add(int32_t increment, return prev; } #else -extern inline int32_t android_atomic_add(int32_t increment, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_add(int32_t increment, volatile int32_t *ptr) { int32_t prev, status; android_memory_barrier(); @@ -179,12 +187,12 @@ extern inline int32_t android_atomic_add(int32_t increment, } #endif -extern inline int32_t android_atomic_inc(volatile int32_t *addr) +extern ANDROID_ATOMIC_INLINE int32_t android_atomic_inc(volatile int32_t *addr) { return android_atomic_add(1, addr); } -extern inline int32_t android_atomic_dec(volatile int32_t *addr) +extern ANDROID_ATOMIC_INLINE int32_t android_atomic_dec(volatile int32_t *addr) { return android_atomic_add(-1, addr); } @@ -192,7 +200,8 @@ extern inline int32_t android_atomic_dec(volatile int32_t *addr) #if defined(__thumb__) extern int32_t android_atomic_and(int32_t value, volatile int32_t *ptr); #elif defined(__ARM_HAVE_LDREX_STREX) -extern inline int32_t android_atomic_and(int32_t value, volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_and(int32_t value, volatile int32_t *ptr) { int32_t prev, tmp, status; android_memory_barrier(); @@ -208,7 +217,8 @@ extern inline int32_t android_atomic_and(int32_t value, volatile int32_t *ptr) return prev; } #else -extern inline int32_t android_atomic_and(int32_t value, volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_and(int32_t value, volatile int32_t *ptr) { int32_t prev, status; android_memory_barrier(); @@ -223,7 +233,8 @@ extern inline int32_t android_atomic_and(int32_t value, volatile int32_t *ptr) #if defined(__thumb__) extern int32_t android_atomic_or(int32_t value, volatile int32_t *ptr); #elif defined(__ARM_HAVE_LDREX_STREX) -extern inline int32_t android_atomic_or(int32_t value, volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_or(int32_t value, volatile int32_t *ptr) { int32_t prev, tmp, status; android_memory_barrier(); @@ -239,7 +250,8 @@ extern inline int32_t android_atomic_or(int32_t value, volatile int32_t *ptr) return prev; } #else -extern inline int32_t android_atomic_or(int32_t value, volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_or(int32_t value, volatile int32_t *ptr) { int32_t prev, status; android_memory_barrier(); diff --git a/include/cutils/atomic-mips.h b/include/cutils/atomic-mips.h index 49144a374..f9d3e253e 100644 --- a/include/cutils/atomic-mips.h +++ b/include/cutils/atomic-mips.h @@ -19,60 +19,66 @@ #include -extern inline void android_compiler_barrier(void) +#ifndef ANDROID_ATOMIC_INLINE +#define ANDROID_ATOMIC_INLINE inline __attribute__((always_inline)) +#endif + +extern ANDROID_ATOMIC_INLINE void android_compiler_barrier(void) { __asm__ __volatile__ ("" : : : "memory"); } #if ANDROID_SMP == 0 -extern inline void android_memory_barrier(void) +extern ANDROID_ATOMIC_INLINE void android_memory_barrier(void) { android_compiler_barrier(); } -extern inline void android_memory_store_barrier(void) +extern ANDROID_ATOMIC_INLINE void android_memory_store_barrier(void) { android_compiler_barrier(); } #else -extern inline void android_memory_barrier(void) +extern ANDROID_ATOMIC_INLINE void android_memory_barrier(void) { __asm__ __volatile__ ("sync" : : : "memory"); } -extern inline void android_memory_store_barrier(void) +extern ANDROID_ATOMIC_INLINE void android_memory_store_barrier(void) { __asm__ __volatile__ ("sync" : : : "memory"); } #endif -extern inline int32_t android_atomic_acquire_load(volatile const int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_acquire_load(volatile const int32_t *ptr) { int32_t value = *ptr; android_memory_barrier(); return value; } -extern inline int32_t android_atomic_release_load(volatile const int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_release_load(volatile const int32_t *ptr) { android_memory_barrier(); return *ptr; } -extern inline void android_atomic_acquire_store(int32_t value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE void +android_atomic_acquire_store(int32_t value, volatile int32_t *ptr) { *ptr = value; android_memory_barrier(); } -extern inline void android_atomic_release_store(int32_t value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE void +android_atomic_release_store(int32_t value, volatile int32_t *ptr) { android_memory_barrier(); *ptr = value; } -extern inline int android_atomic_cas(int32_t old_value, int32_t new_value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int +android_atomic_cas(int32_t old_value, int32_t new_value, volatile int32_t *ptr) { int32_t prev, status; do { @@ -90,26 +96,28 @@ extern inline int android_atomic_cas(int32_t old_value, int32_t new_value, return prev != old_value; } -extern inline int android_atomic_acquire_cas(int32_t old_value, - int32_t new_value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int +android_atomic_acquire_cas(int32_t old_value, + int32_t new_value, + volatile int32_t *ptr) { int status = android_atomic_cas(old_value, new_value, ptr); android_memory_barrier(); return status; } -extern inline int android_atomic_release_cas(int32_t old_value, - int32_t new_value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int +android_atomic_release_cas(int32_t old_value, + int32_t new_value, + volatile int32_t *ptr) { android_memory_barrier(); return android_atomic_cas(old_value, new_value, ptr); } -extern inline int32_t android_atomic_swap(int32_t new_value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_swap(int32_t new_value, volatile int32_t *ptr) { int32_t prev, status; do { @@ -125,8 +133,8 @@ extern inline int32_t android_atomic_swap(int32_t new_value, return prev; } -extern inline int32_t android_atomic_add(int32_t increment, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_add(int32_t increment, volatile int32_t *ptr) { int32_t prev, status; android_memory_barrier(); @@ -142,17 +150,20 @@ extern inline int32_t android_atomic_add(int32_t increment, return prev; } -extern inline int32_t android_atomic_inc(volatile int32_t *addr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_inc(volatile int32_t *addr) { return android_atomic_add(1, addr); } -extern inline int32_t android_atomic_dec(volatile int32_t *addr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_dec(volatile int32_t *addr) { return android_atomic_add(-1, addr); } -extern inline int32_t android_atomic_and(int32_t value, volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_and(int32_t value, volatile int32_t *ptr) { int32_t prev, status; android_memory_barrier(); @@ -168,7 +179,8 @@ extern inline int32_t android_atomic_and(int32_t value, volatile int32_t *ptr) return prev; } -extern inline int32_t android_atomic_or(int32_t value, volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_or(int32_t value, volatile int32_t *ptr) { int32_t prev, status; android_memory_barrier(); diff --git a/include/cutils/atomic-x86.h b/include/cutils/atomic-x86.h index 438012e50..9480f57fe 100644 --- a/include/cutils/atomic-x86.h +++ b/include/cutils/atomic-x86.h @@ -19,60 +19,66 @@ #include -extern inline void android_compiler_barrier(void) +#ifndef ANDROID_ATOMIC_INLINE +#define ANDROID_ATOMIC_INLINE inline __attribute__((always_inline)) +#endif + +extern ANDROID_ATOMIC_INLINE void android_compiler_barrier(void) { __asm__ __volatile__ ("" : : : "memory"); } #if ANDROID_SMP == 0 -extern inline void android_memory_barrier(void) +extern ANDROID_ATOMIC_INLINE void android_memory_barrier(void) { android_compiler_barrier(); } -extern inline void android_memory_store_barrier(void) +extern ANDROID_ATOMIC_INLINE void android_memory_store_barrier(void) { android_compiler_barrier(); } #else -extern inline void android_memory_barrier(void) +extern ANDROID_ATOMIC_INLINE void android_memory_barrier(void) { __asm__ __volatile__ ("mfence" : : : "memory"); } -extern inline void android_memory_store_barrier(void) +extern ANDROID_ATOMIC_INLINE void android_memory_store_barrier(void) { android_compiler_barrier(); } #endif -extern inline int32_t android_atomic_acquire_load(volatile const int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_acquire_load(volatile const int32_t *ptr) { int32_t value = *ptr; android_compiler_barrier(); return value; } -extern inline int32_t android_atomic_release_load(volatile const int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_release_load(volatile const int32_t *ptr) { android_memory_barrier(); return *ptr; } -extern inline void android_atomic_acquire_store(int32_t value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE void +android_atomic_acquire_store(int32_t value, volatile int32_t *ptr) { *ptr = value; android_memory_barrier(); } -extern inline void android_atomic_release_store(int32_t value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE void +android_atomic_release_store(int32_t value, volatile int32_t *ptr) { android_compiler_barrier(); *ptr = value; } -extern inline int android_atomic_cas(int32_t old_value, int32_t new_value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int +android_atomic_cas(int32_t old_value, int32_t new_value, volatile int32_t *ptr) { int32_t prev; __asm__ __volatile__ ("lock; cmpxchgl %1, %2" @@ -82,24 +88,26 @@ extern inline int android_atomic_cas(int32_t old_value, int32_t new_value, return prev != old_value; } -extern inline int android_atomic_acquire_cas(int32_t old_value, - int32_t new_value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int +android_atomic_acquire_cas(int32_t old_value, + int32_t new_value, + volatile int32_t *ptr) { /* Loads are not reordered with other loads. */ return android_atomic_cas(old_value, new_value, ptr); } -extern inline int android_atomic_release_cas(int32_t old_value, - int32_t new_value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int +android_atomic_release_cas(int32_t old_value, + int32_t new_value, + volatile int32_t *ptr) { /* Stores are not reordered with other stores. */ return android_atomic_cas(old_value, new_value, ptr); } -extern inline int32_t android_atomic_add(int32_t increment, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_add(int32_t increment, volatile int32_t *ptr) { __asm__ __volatile__ ("lock; xaddl %0, %1" : "+r" (increment), "+m" (*ptr) @@ -108,18 +116,20 @@ extern inline int32_t android_atomic_add(int32_t increment, return increment; } -extern inline int32_t android_atomic_inc(volatile int32_t *addr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_inc(volatile int32_t *addr) { return android_atomic_add(1, addr); } -extern inline int32_t android_atomic_dec(volatile int32_t *addr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_dec(volatile int32_t *addr) { return android_atomic_add(-1, addr); } -extern inline int32_t android_atomic_and(int32_t value, - volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_and(int32_t value, volatile int32_t *ptr) { int32_t prev, status; do { @@ -129,7 +139,8 @@ extern inline int32_t android_atomic_and(int32_t value, return prev; } -extern inline int32_t android_atomic_or(int32_t value, volatile int32_t *ptr) +extern ANDROID_ATOMIC_INLINE int32_t +android_atomic_or(int32_t value, volatile int32_t *ptr) { int32_t prev, status; do { diff --git a/libcutils/atomic.c b/libcutils/atomic.c index f6cd8b0e7..1484ef890 100644 --- a/libcutils/atomic.c +++ b/libcutils/atomic.c @@ -14,6 +14,6 @@ * limitations under the License. */ -#define inline +#define ANDROID_ATOMIC_INLINE #include