atomic-inline.h revision 8dfa47da8cb33ebaf7aae6db6548e75ed86e8f1e
1ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden/* 2ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * Copyright (C) 2010 The Android Open Source Project 3ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * 4ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * Licensed under the Apache License, Version 2.0 (the "License"); 5ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * you may not use this file except in compliance with the License. 6ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * You may obtain a copy of the License at 7ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * 8ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * http://www.apache.org/licenses/LICENSE-2.0 9ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * 10ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * Unless required by applicable law or agreed to in writing, software 11ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * distributed under the License is distributed on an "AS IS" BASIS, 12ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * See the License for the specific language governing permissions and 14ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * limitations under the License. 15ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden */ 16ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden 17ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden#ifndef ANDROID_CUTILS_ATOMIC_INLINE_H 18ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden#define ANDROID_CUTILS_ATOMIC_INLINE_H 19ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden 20ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden/* 21ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * Inline declarations and macros for some special-purpose atomic 22ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * operations. These are intended for rare circumstances where a 23ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * memory barrier needs to be issued inline rather than as a function 24ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * call. 25ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * 26ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * Most code should not use these. 27ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * 28ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * Anything that does include this file must set ANDROID_SMP to either 29ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * 0 or 1, indicating compilation for UP or SMP, respectively. 308dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * 318dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * Macros defined in this header: 328dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * 338dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * void ANDROID_MEMBAR_FULL(void) 348dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * Full memory barrier. Provides a compiler reordering barrier, and 358dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden * on SMP systems emits an appropriate instruction. 36ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden */ 37ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden 38ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden#if !defined(ANDROID_SMP) 39ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden# error "Must define ANDROID_SMP before including atomic-inline.h" 40ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden#endif 41ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden 42ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden#ifdef __cplusplus 43ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFaddenextern "C" { 44ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden#endif 45ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden 46ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden/* 47ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * Define the full memory barrier for an SMP system. This is 48ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * platform-specific. 49ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden */ 50ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden 51ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden#ifdef __arm__ 52ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden#include <machine/cpu-features.h> 53ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden 54ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden/* 55ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * For ARMv6K we need to issue a specific MCR instead of the DMB, since 56ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * that wasn't added until v7. For anything older, SMP isn't relevant. 57ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * Since we don't have an ARMv6K to test with, we're not going to deal 58ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * with that now. 59ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * 60ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * The DMB instruction is found in the ARM and Thumb2 instruction sets. 61ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * This will fail on plain 16-bit Thumb. 62ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden */ 63ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden#if defined(__ARM_HAVE_DMB) 648dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden# define _ANDROID_MEMBAR_FULL_SMP() \ 65ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden do { __asm__ __volatile__ ("dmb" ::: "memory"); } while (0) 66ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden#else 678dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden# define _ANDROID_MEMBAR_FULL_SMP() ARM_SMP_defined_but_no_DMB() 68ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden#endif 69ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden 70ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden#elif defined(__i386__) || defined(__x86_64__) 71ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden/* 72ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * For recent x86, we can use the SSE2 mfence instruction. 73ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden */ 748dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden# define _ANDROID_MEMBAR_FULL_SMP() \ 75ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden do { __asm__ __volatile__ ("mfence" ::: "memory"); } while (0) 76ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden 77ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden#else 78ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden/* 79ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * Implementation not defined for this platform. Hopefully we're building 80ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * in uniprocessor mode. 81ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden */ 828dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden# define _ANDROID_MEMBAR_FULL_SMP() SMP_barrier_not_defined_for_platform() 83ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden#endif 84ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden 85ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden 86ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden/* 87ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * Full barrier. On uniprocessors this is just a compiler reorder barrier, 88ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * which ensures that the statements appearing above the barrier in the C/C++ 89ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * code will be issued after the statements appearing below the barrier. 90ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * 91ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * For SMP this also includes a memory barrier instruction. On an ARM 92ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * CPU this means that the current core will flush pending writes, wait 93ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * for pending reads to complete, and discard any cached reads that could 94ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden * be stale. Other CPUs may do less, but the end result is equivalent. 95ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden */ 96ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden#if ANDROID_SMP != 0 978dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden# define ANDROID_MEMBAR_FULL() _ANDROID_MEMBAR_FULL_SMP() 98ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden#else 998dfa47da8cb33ebaf7aae6db6548e75ed86e8f1eAndy McFadden# define ANDROID_MEMBAR_FULL() \ 100ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden do { __asm__ __volatile__ ("" ::: "memory"); } while (0) 101ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden#endif 102ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden 103ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden#ifdef __cplusplus 104ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden} // extern "C" 105ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden#endif 106ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden 107ac322da69ee48aa792baf5c48cfb719ce077f67eAndy McFadden#endif // ANDROID_CUTILS_ATOMIC_INLINE_H 108