atomic.cc revision 5ea047b386c5dac78eda62305d14dedf7b5611a8
15ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes/* 25ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes * Copyright (C) 2010 The Android Open Source Project 35ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes * 45ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 55ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes * you may not use this file except in compliance with the License. 65ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes * You may obtain a copy of the License at 75ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes * 85ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 95ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes * 105ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes * Unless required by applicable law or agreed to in writing, software 115ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 125ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes * See the License for the specific language governing permissions and 145ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes * limitations under the License. 155ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes */ 165ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 175ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes#include "atomic.h" 185ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 195ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes#include <sched.h> 205ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 215ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughesnamespace art { 225ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 235ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes/* 245ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes * Quasi-atomic 64-bit operations, for platforms that lack the real thing. 255ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes * 265ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes * TODO: unify ARMv6/x86/sh implementations using the to-be-written 275ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes * spin lock implementation. We don't want to rely on mutex innards, 285ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes * and it would be great if all platforms were running the same code. 295ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes */ 305ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 315ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes#if defined(HAVE_MACOSX_IPC) 325ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 335ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes#include <libkern/OSAtomic.h> 345ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 355ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes#if defined(__ppc__) \ 365ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes || defined(__PPC__) \ 375ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes || defined(__powerpc__) \ 385ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes || defined(__powerpc) \ 395ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes || defined(__POWERPC__) \ 405ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes || defined(_M_PPC) \ 415ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes || defined(__PPC) 425ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes#define NEED_QUASIATOMICS 1 435ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes#else 445ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 455ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughesint QuasiAtomicCas64(int64_t old_value, int64_t new_value, volatile int64_t* addr) { 465ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes return OSAtomicCompareAndSwap64Barrier(old_value, new_value, (int64_t*)addr) == 0; 475ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes} 485ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 495ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughesint64_t QuasiAtomicSwap64(int64_t value, volatile int64_t* addr) { 505ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes int64_t oldValue; 515ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes do { 525ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes oldValue = *addr; 535ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes } while (QuasiAtomicCas64(oldValue, value, addr)); 545ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes return oldValue; 555ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes} 565ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 575ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughesint64_t QuasiAtomicRead64(volatile const int64_t* addr) { 585ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes return OSAtomicAdd64Barrier(0, addr); 595ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes} 605ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes#endif 615ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 625ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes#elif defined(__i386__) || defined(__x86_64__) 635ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes#define NEED_QUASIATOMICS 1 645ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 655ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes#elif __arm__ 665ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes#include <machine/cpu-features.h> 675ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 685ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes#ifdef __ARM_HAVE_LDREXD 695ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughesint64_t QuasiAtomicSwap64(int64_t new_value, volatile int64_t* addr) { 705ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes int64_t prev; 715ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes int status; 725ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes do { 735ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes __asm__ __volatile__ ("@ QuasiAtomicSwap64\n" 745ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes "ldrexd %0, %H0, [%3]\n" 755ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes "strexd %1, %4, %H4, [%3]" 765ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes : "=&r" (prev), "=&r" (status), "+m"(*addr) 775ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes : "r" (addr), "r" (new_value) 785ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes : "cc"); 795ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes } while (__builtin_expect(status != 0, 0)); 805ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes return prev; 815ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes} 825ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 835ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughesint QuasiAtomicCas64(int64_t old_value, int64_t new_value, volatile int64_t* addr) { 845ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes int64_t prev; 855ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes int status; 865ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes do { 875ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes __asm__ __volatile__ ("@ QuasiAtomicCas64\n" 885ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes "ldrexd %0, %H0, [%3]\n" 895ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes "mov %1, #0\n" 905ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes "teq %0, %4\n" 915ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes "teqeq %H0, %H4\n" 925ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes "strexdeq %1, %5, %H5, [%3]" 935ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes : "=&r" (prev), "=&r" (status), "+m"(*addr) 945ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes : "r" (addr), "Ir" (old_value), "r" (new_value) 955ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes : "cc"); 965ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes } while (__builtin_expect(status != 0, 0)); 975ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes return prev != old_value; 985ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes} 995ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 1005ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughesint64_t QuasiAtomicRead64(volatile const int64_t* addr) { 1015ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes int64_t value; 1025ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes __asm__ __volatile__ ("@ QuasiAtomicRead64\n" 1035ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes "ldrexd %0, %H0, [%1]" 1045ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes : "=&r" (value) 1055ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes : "r" (addr)); 1065ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes return value; 1075ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes} 1085ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 1095ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes#else 1105ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 1115ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes// on the device, we implement the 64-bit atomic operations through 1125ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes// mutex locking. normally, this is bad because we must initialize 1135ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes// a pthread_mutex_t before being able to use it, and this means 1145ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes// having to do an initialization check on each function call, and 1155ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes// that's where really ugly things begin... 1165ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes// 1175ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes// BUT, as a special twist, we take advantage of the fact that in our 1185ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes// pthread library, a mutex is simply a volatile word whose value is always 1195ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes// initialized to 0. In other words, simply declaring a static mutex 1205ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes// object initializes it ! 1215ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes// 1225ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes// another twist is that we use a small array of mutexes to dispatch 1235ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes// the contention locks from different memory addresses 1245ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes// 1255ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 1265ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes#include <pthread.h> 1275ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 1285ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes#define SWAP_LOCK_COUNT 32U 1295ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughesstatic pthread_mutex_t _swap_locks[SWAP_LOCK_COUNT]; 1305ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 1315ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes#define SWAP_LOCK(addr) &_swap_locks[((unsigned)(void*)(addr) >> 3U) % SWAP_LOCK_COUNT] 1325ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 1335ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughesint64_t QuasiAtomicSwap64(int64_t value, volatile int64_t* addr) { 1345ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes pthread_mutex_t* lock = SWAP_LOCK(addr); 1355ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 1365ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes pthread_mutex_lock(lock); 1375ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 1385ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes int64_t oldValue = *addr; 1395ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes *addr = value; 1405ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 1415ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes pthread_mutex_unlock(lock); 1425ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes return oldValue; 1435ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes} 1445ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 1455ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughesint QuasiAtomicCas64(int64_t old_value, int64_t new_value, volatile int64_t* addr) { 1465ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes int result; 1475ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes pthread_mutex_t* lock = SWAP_LOCK(addr); 1485ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 1495ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes pthread_mutex_lock(lock); 1505ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 1515ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes if (*addr == old_value) { 1525ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes *addr = new_value; 1535ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes result = 0; 1545ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes } else { 1555ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes result = 1; 1565ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes } 1575ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes pthread_mutex_unlock(lock); 1585ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes return result; 1595ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes} 1605ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 1615ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughesint64_t QuasiAtomicRead64(volatile const int64_t* addr) { 1625ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes int64_t result; 1635ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes pthread_mutex_t* lock = SWAP_LOCK(addr); 1645ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 1655ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes pthread_mutex_lock(lock); 1665ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes result = *addr; 1675ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes pthread_mutex_unlock(lock); 1685ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes return result; 1695ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes} 1705ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 1715ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes#endif /*__ARM_HAVE_LDREXD*/ 1725ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 1735ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes/*****************************************************************************/ 1745ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes#elif __sh__ 1755ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes#define NEED_QUASIATOMICS 1 1765ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 1775ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes#else 1785ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes#error "Unsupported atomic operations for this platform" 1795ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes#endif 1805ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 1815ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 1825ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes#if NEED_QUASIATOMICS 1835ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 1845ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes/* Note that a spinlock is *not* a good idea in general 1855ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes * since they can introduce subtle issues. For example, 1865ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes * a real-time thread trying to acquire a spinlock already 1875ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes * acquired by another thread will never yeld, making the 1885ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes * CPU loop endlessly! 1895ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes * 1905ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes * However, this code is only used on the Linux simulator 1915ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes * so it's probably ok for us. 1925ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes * 1935ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes * The alternative is to use a pthread mutex, but 1945ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes * these must be initialized before being used, and 1955ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes * then you have the problem of lazily initializing 1965ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes * a mutex without any other synchronization primitive. 1975ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes * 1985ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes * TODO: these currently use sched_yield(), which is not guaranteed to 1995ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes * do anything at all. We need to use dvmIterativeSleep or a wait / 2005ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes * notify mechanism if the initial attempt fails. 2015ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes */ 2025ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 2035ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes/* global spinlock for all 64-bit quasiatomic operations */ 2045ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughesstatic int32_t quasiatomic_spinlock = 0; 2055ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 2065ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughesint QuasiAtomicCas64(int64_t old_value, int64_t new_value, volatile int64_t* addr) { 2075ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes int result; 2085ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 2095ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes while (android_atomic_acquire_cas(0, 1, &quasiatomic_spinlock)) { 2105ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes#ifdef HAVE_WIN32_THREADS 2115ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes Sleep(0); 2125ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes#else 2135ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes sched_yield(); 2145ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes#endif 2155ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes } 2165ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 2175ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes if (*addr == old_value) { 2185ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes *addr = new_value; 2195ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes result = 0; 2205ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes } else { 2215ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes result = 1; 2225ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes } 2235ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 2245ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes android_atomic_release_store(0, &quasiatomic_spinlock); 2255ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 2265ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes return result; 2275ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes} 2285ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 2295ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughesint64_t QuasiAtomicRead64(volatile const int64_t* addr) { 2305ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes int64_t result; 2315ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 2325ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes while (android_atomic_acquire_cas(0, 1, &quasiatomic_spinlock)) { 2335ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes#ifdef HAVE_WIN32_THREADS 2345ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes Sleep(0); 2355ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes#else 2365ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes sched_yield(); 2375ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes#endif 2385ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes } 2395ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 2405ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes result = *addr; 2415ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes android_atomic_release_store(0, &quasiatomic_spinlock); 2425ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 2435ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes return result; 2445ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes} 2455ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 2465ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughesint64_t QuasiAtomicSwap64(int64_t value, volatile int64_t* addr) { 2475ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes int64_t result; 2485ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 2495ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes while (android_atomic_acquire_cas(0, 1, &quasiatomic_spinlock)) { 2505ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes#ifdef HAVE_WIN32_THREADS 2515ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes Sleep(0); 2525ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes#else 2535ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes sched_yield(); 2545ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes#endif 2555ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes } 2565ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 2575ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes result = *addr; 2585ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes *addr = value; 2595ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes android_atomic_release_store(0, &quasiatomic_spinlock); 2605ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 2615ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes return result; 2625ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes} 2635ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 2645ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes#endif /*NEED_QUASIATOMICS*/ 2655ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 2665ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes} // namespace art 267