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