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