1e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner/* 2e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner * Copyright (C) 2011 The Android Open Source Project 3e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner * 4e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner * Licensed under the Apache License, Version 2.0 (the "License"); 5e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner * you may not use this file except in compliance with the License. 6e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner * You may obtain a copy of the License at 7e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner * 8e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner * http://www.apache.org/licenses/LICENSE-2.0 9e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner * 10e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner * Unless required by applicable law or agreed to in writing, software 11e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner * distributed under the License is distributed on an "AS IS" BASIS, 12e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner * See the License for the specific language governing permissions and 14e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner * limitations under the License. 15e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner */ 16e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner#ifndef BIONIC_ATOMIC_ARM_H 17e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner#define BIONIC_ATOMIC_ARM_H 18e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner 19845c778fa6ebb3ff3feaac0c268d93f4017c0cdaSerban Constantinescu__ATOMIC_INLINE__ void __bionic_memory_barrier() { 202b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes#if defined(ANDROID_SMP) && ANDROID_SMP == 1 21845c778fa6ebb3ff3feaac0c268d93f4017c0cdaSerban Constantinescu __asm__ __volatile__ ( "dmb ish" : : : "memory" ); 22e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner#else 232b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes /* A simple compiler barrier. */ 242b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes __asm__ __volatile__ ( "" : : : "memory" ); 25e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner#endif 26e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner} 27e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner 284c186ffb837a2bd852e7983f217a945d415cefbcElliott Hughes/* Compare-and-swap, without any explicit barriers. Note that this function 29e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner * returns 0 on success, and 1 on failure. The opposite convention is typically 30e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner * used on other platforms. 31e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner */ 322b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes__ATOMIC_INLINE__ int __bionic_cmpxchg(int32_t old_value, int32_t new_value, volatile int32_t* ptr) { 332b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes int32_t prev, status; 342b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes do { 352b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes __asm__ __volatile__ ( 362b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes "ldrex %0, [%3]\n" 372b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes "mov %1, #0\n" 382b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes "teq %0, %4\n" 39e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner#ifdef __thumb2__ 402b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes "it eq\n" 41e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner#endif 422b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes "strexeq %1, %5, [%3]" 432b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes : "=&r" (prev), "=&r" (status), "+m"(*ptr) 442b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes : "r" (ptr), "Ir" (old_value), "r" (new_value) 452b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes : "cc"); 462b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes } while (__builtin_expect(status != 0, 0)); 472b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes return prev != old_value; 48e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner} 49e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner 502b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes/* Swap, without any explicit barriers. */ 512b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes__ATOMIC_INLINE__ int32_t __bionic_swap(int32_t new_value, volatile int32_t* ptr) { 522b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes int32_t prev, status; 532b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes do { 542b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes __asm__ __volatile__ ( 552b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes "ldrex %0, [%3]\n" 562b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes "strex %1, %4, [%3]" 572b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes : "=&r" (prev), "=&r" (status), "+m" (*ptr) 582b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes : "r" (ptr), "r" (new_value) 592b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes : "cc"); 602b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes } while (__builtin_expect(status != 0, 0)); 612b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes return prev; 62e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner} 63e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner 642b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes/* Atomic decrement, without explicit barriers. */ 652b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes__ATOMIC_INLINE__ int32_t __bionic_atomic_dec(volatile int32_t* ptr) { 662b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes int32_t prev, tmp, status; 672b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes do { 682b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes __asm__ __volatile__ ( 692b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes "ldrex %0, [%4]\n" 702b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes "sub %1, %0, #1\n" 712b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes "strex %2, %1, [%4]" 722b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes : "=&r" (prev), "=&r" (tmp), "=&r" (status), "+m"(*ptr) 732b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes : "r" (ptr) 742b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes : "cc"); 752b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes } while (__builtin_expect(status != 0, 0)); 762b333b97a241eec63d531874e28f2a894bc06aa0Elliott Hughes return prev; 77e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner} 78e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner 79e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner#endif /* SYS_ATOMICS_ARM_H */ 80