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_X86_H 17e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner#define BIONIC_ATOMIC_X86_H 18e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner 19e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner/* Define a full memory barrier, this is only needed if we build the 20e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner * platform for a multi-core device. 21e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner */ 22e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner#if defined(ANDROID_SMP) && ANDROID_SMP == 1 23e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner__ATOMIC_INLINE__ void 24e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner__bionic_memory_barrier() 25e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner{ 26e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner __asm__ __volatile__ ( "mfence" : : : "memory" ); 27e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner} 28e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner#else 29e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner__ATOMIC_INLINE__ void 30e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner__bionic_memory_barrier() 31e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner{ 32e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner /* A simple compiler barrier */ 33e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner __asm__ __volatile__ ( "" : : : "memory" ); 34e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner} 35e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner#endif 36e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner 37e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner/* Compare-and-swap, without any explicit barriers. Note that this function 38e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner * returns 0 on success, and 1 on failure. The opposite convention is typically 39e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner * used on other platforms. 40e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner */ 41e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner__ATOMIC_INLINE__ int 42e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner__bionic_cmpxchg(int32_t old_value, int32_t new_value, volatile int32_t* ptr) 43e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner{ 44e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner int32_t prev; 45e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner __asm__ __volatile__ ("lock; cmpxchgl %1, %2" 46e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner : "=a" (prev) 47e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner : "q" (new_value), "m" (*ptr), "0" (old_value) 48e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner : "memory"); 49e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner return prev != old_value; 50e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner} 51e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner 52e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner 53e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner/* Swap, without any explicit barriers */ 54e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner__ATOMIC_INLINE__ int32_t 55e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner__bionic_swap(int32_t new_value, volatile int32_t *ptr) 56e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner{ 57e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner __asm__ __volatile__ ("xchgl %1, %0" 58e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner : "=r" (new_value) 59e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner : "m" (*ptr), "0" (new_value) 60e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner : "memory"); 61e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner return new_value; 62e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner} 63e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner 64e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner/* Atomic increment, without explicit barriers */ 65e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner__ATOMIC_INLINE__ int32_t 66e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner__bionic_atomic_inc(volatile int32_t *ptr) 67e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner{ 68e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner int increment = 1; 69e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner __asm__ __volatile__ ("lock; xaddl %0, %1" 70e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner : "+r" (increment), "+m" (*ptr) 71e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner : : "memory"); 72e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner /* increment now holds the old value of *ptr */ 73e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner return increment; 74e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner} 75e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner 76e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner/* Atomic decrement, without explicit barriers */ 77e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner__ATOMIC_INLINE__ int32_t 78e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner__bionic_atomic_dec(volatile int32_t *ptr) 79e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner{ 80e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner int increment = -1; 81e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner __asm__ __volatile__ ("lock; xaddl %0, %1" 82e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner : "+r" (increment), "+m" (*ptr) 83e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner : : "memory"); 84e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner /* increment now holds the old value of *ptr */ 85e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner return increment; 86e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner} 87e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner 88e31bfae2baa96742f998155ee26e56c826a8ce3aDavid 'Digit' Turner#endif /* BIONIC_ATOMIC_X86_H */ 89