1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * you may not use this file except in compliance with the License.
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * You may obtain a copy of the License at
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * See the License for the specific language governing permissions and
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * limitations under the License.
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifndef ANDROID_CUTILS_ATOMIC_H
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define ANDROID_CUTILS_ATOMIC_H
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdint.h>
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/types.h>
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifdef __cplusplus
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectextern "C" {
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
288dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * A handful of basic atomic operations.  The appropriate pthread
298dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * functions should be used instead of these whenever possible.
308dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden *
318dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * The "acquire" and "release" terms can be defined intuitively in terms
328dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * of the placement of memory barriers in a simple lock implementation:
338dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden *   - wait until compare-and-swap(lock-is-free --> lock-is-held) succeeds
348dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden *   - barrier
358dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden *   - [do work]
368dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden *   - barrier
378dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden *   - store(lock-is-free)
388dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * In very crude terms, the initial (acquire) barrier prevents any of the
398dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * "work" from happening before the lock is held, and the later (release)
408dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * barrier ensures that all of the work happens before the lock is released.
418dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * (Think of cached writes, cache read-ahead, and instruction reordering
428dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * around the CAS and store instructions.)
438dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden *
448dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * The barriers must apply to both the compiler and the CPU.  Note it is
458dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * legal for instructions that occur before an "acquire" barrier to be
468dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * moved down below it, and for instructions that occur after a "release"
478dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * barrier to be moved up above it.
488dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden *
498dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * The ARM-driven implementation we use here is short on subtlety,
508dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * and actually requests a full barrier from the compiler and the CPU.
518dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * The only difference between acquire and release is in whether they
528dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * are issued before or after the atomic operation with which they
538dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * are associated.  To ease the transition to C/C++ atomic intrinsics,
548dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * you should not rely on this, and instead assume that only the minimal
558dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * acquire/release protection is provided.
568dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden *
578dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * NOTE: all int32_t* values are expected to be aligned on 32-bit boundaries.
588dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * If they are not, atomicity is not guaranteed.
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
628dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * Basic arithmetic and bitwise operations.  These all provide a
638dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * barrier with "release" ordering, and return the previous value.
648dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden *
658dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * These have the same characteristics (e.g. what happens on overflow)
668dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * as the equivalent non-atomic C operations.
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint32_t android_atomic_inc(volatile int32_t* addr);
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint32_t android_atomic_dec(volatile int32_t* addr);
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint32_t android_atomic_add(int32_t value, volatile int32_t* addr);
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint32_t android_atomic_and(int32_t value, volatile int32_t* addr);
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint32_t android_atomic_or(int32_t value, volatile int32_t* addr);
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
748dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden/*
758dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * Perform an atomic load with "acquire" or "release" ordering.
768dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden *
778dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * This is only necessary if you need the memory barrier.  A 32-bit read
788dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * from a 32-bit aligned address is atomic on all supported platforms.
798dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden */
80d55f0adfb5ec4202ad5bd5d188e66c0f6a27b0aaCarl Shapiroint32_t android_atomic_acquire_load(volatile const int32_t* addr);
81d55f0adfb5ec4202ad5bd5d188e66c0f6a27b0aaCarl Shapiroint32_t android_atomic_release_load(volatile const int32_t* addr);
828dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden
838dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden/*
848dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * Perform an atomic store with "acquire" or "release" ordering.
858dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden *
868dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * This is only necessary if you need the memory barrier.  A 32-bit write
878dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * to a 32-bit aligned address is atomic on all supported platforms.
888dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden */
898dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFaddenvoid android_atomic_acquire_store(int32_t value, volatile int32_t* addr);
908dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFaddenvoid android_atomic_release_store(int32_t value, volatile int32_t* addr);
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
938dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * Compare-and-set operation with "acquire" or "release" ordering.
948dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden *
958dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * This returns zero if the new value was successfully stored, which will
968dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * only happen when *addr == oldvalue.
978dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden *
988dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * (The return value is inverted from implementations on other platforms,
998dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * but matches the ARM ldrex/strex result.)
1008dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden *
1018dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * Implementations that use the release CAS in a loop may be less efficient
1028dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * than possible, because we re-issue the memory barrier on each iteration.
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
1048dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFaddenint android_atomic_acquire_cas(int32_t oldvalue, int32_t newvalue,
1058dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden        volatile int32_t* addr);
1068dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFaddenint android_atomic_release_cas(int32_t oldvalue, int32_t newvalue,
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        volatile int32_t* addr);
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
109ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden/*
1108dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * Aliases for code using an older version of this header.  These are now
1118dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * deprecated and should not be used.  The definitions will be removed
1128dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * in a future release.
113ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden */
1148dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden#define android_atomic_write android_atomic_release_store
1158dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden#define android_atomic_cmpxchg android_atomic_release_cas
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifdef __cplusplus
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} // extern "C"
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif // ANDROID_CUTILS_ATOMIC_H
122