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" 1876b6167407c2b6f5d40ad895b2793a6b037f54b2Elliott Hughes#include "base/mutex.h" 191aa246dec5abe212f699de1413a0c4a191ca364aElliott Hughes#include "base/stl_util.h" 20784639608387602e0c9e448e88db7809577f1667Brian Carlstrom#include "thread-inl.h" 217c6169de901fd0a39c8e0c078874dc25207f5b59Elliott Hughes 227c6169de901fd0a39c8e0c078874dc25207f5b59Elliott Hughesnamespace art { 235ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 24b122a4bbed34ab22b4c1541ee25e5cf22f12a926Ian Rogersstd::vector<Mutex*>* QuasiAtomic::gSwapMutexes = nullptr; 255ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 26b122a4bbed34ab22b4c1541ee25e5cf22f12a926Ian RogersMutex* QuasiAtomic::GetSwapMutex(const volatile int64_t* addr) { 27ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers return (*gSwapMutexes)[(reinterpret_cast<uintptr_t>(addr) >> 3U) % kSwapMutexCount]; 289adbff5b85fcae2b3e2443344415f6c17ea3ba0aIan Rogers} 295ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 309adbff5b85fcae2b3e2443344415f6c17ea3ba0aIan Rogersvoid QuasiAtomic::Startup() { 31b122a4bbed34ab22b4c1541ee25e5cf22f12a926Ian Rogers if (kNeedSwapMutexes) { 32b122a4bbed34ab22b4c1541ee25e5cf22f12a926Ian Rogers gSwapMutexes = new std::vector<Mutex*>; 33b122a4bbed34ab22b4c1541ee25e5cf22f12a926Ian Rogers for (size_t i = 0; i < kSwapMutexCount; ++i) { 347de77dd4f2d3cbb0615ee001589eb99ae82c3dccRaghu Gandham gSwapMutexes->push_back(new Mutex("QuasiAtomic stripe", kSwapMutexesLock)); 35b122a4bbed34ab22b4c1541ee25e5cf22f12a926Ian Rogers } 369adbff5b85fcae2b3e2443344415f6c17ea3ba0aIan Rogers } 379adbff5b85fcae2b3e2443344415f6c17ea3ba0aIan Rogers} 385ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 399adbff5b85fcae2b3e2443344415f6c17ea3ba0aIan Rogersvoid QuasiAtomic::Shutdown() { 40b122a4bbed34ab22b4c1541ee25e5cf22f12a926Ian Rogers if (kNeedSwapMutexes) { 41b122a4bbed34ab22b4c1541ee25e5cf22f12a926Ian Rogers STLDeleteElements(gSwapMutexes); 42b122a4bbed34ab22b4c1541ee25e5cf22f12a926Ian Rogers delete gSwapMutexes; 43b122a4bbed34ab22b4c1541ee25e5cf22f12a926Ian Rogers } 449adbff5b85fcae2b3e2443344415f6c17ea3ba0aIan Rogers} 45557e027f86d86f801e1b48055f8116f2d83d3d5cElliott Hughes 46b122a4bbed34ab22b4c1541ee25e5cf22f12a926Ian Rogersint64_t QuasiAtomic::SwapMutexRead64(volatile const int64_t* addr) { 47b122a4bbed34ab22b4c1541ee25e5cf22f12a926Ian Rogers MutexLock mu(Thread::Current(), *GetSwapMutex(addr)); 48b122a4bbed34ab22b4c1541ee25e5cf22f12a926Ian Rogers return *addr; 499adbff5b85fcae2b3e2443344415f6c17ea3ba0aIan Rogers} 505ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 51b122a4bbed34ab22b4c1541ee25e5cf22f12a926Ian Rogersvoid QuasiAtomic::SwapMutexWrite64(volatile int64_t* addr, int64_t value) { 52b122a4bbed34ab22b4c1541ee25e5cf22f12a926Ian Rogers MutexLock mu(Thread::Current(), *GetSwapMutex(addr)); 530fed328fc9dd21a0b0da3e9b39ee2ce6a4d07117Ian Rogers *addr = value; 54557e027f86d86f801e1b48055f8116f2d83d3d5cElliott Hughes} 55557e027f86d86f801e1b48055f8116f2d83d3d5cElliott Hughes 56557e027f86d86f801e1b48055f8116f2d83d3d5cElliott Hughes 57b122a4bbed34ab22b4c1541ee25e5cf22f12a926Ian Rogersbool QuasiAtomic::SwapMutexCas64(int64_t old_value, int64_t new_value, volatile int64_t* addr) { 58b122a4bbed34ab22b4c1541ee25e5cf22f12a926Ian Rogers MutexLock mu(Thread::Current(), *GetSwapMutex(addr)); 590fed328fc9dd21a0b0da3e9b39ee2ce6a4d07117Ian Rogers if (*addr == old_value) { 600fed328fc9dd21a0b0da3e9b39ee2ce6a4d07117Ian Rogers *addr = new_value; 610fed328fc9dd21a0b0da3e9b39ee2ce6a4d07117Ian Rogers return true; 620fed328fc9dd21a0b0da3e9b39ee2ce6a4d07117Ian Rogers } 630fed328fc9dd21a0b0da3e9b39ee2ce6a4d07117Ian Rogers return false; 649adbff5b85fcae2b3e2443344415f6c17ea3ba0aIan Rogers} 655ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes 665ea047b386c5dac78eda62305d14dedf7b5611a8Elliott Hughes} // namespace art 67