1 /**
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "runtime/mem/gc/bitmap.h"
17
18 #include <atomic>
19
20 namespace panda::mem {
21
CopyTo(Bitmap * dest) const22 void Bitmap::CopyTo(Bitmap *dest) const
23 {
24 ASSERT(dest->bitmap_.SizeBytes() == bitmap_.SizeBytes());
25 [[maybe_unused]] auto res =
26 memmove_s(dest->bitmap_.Data(), dest->bitmap_.SizeBytes(), bitmap_.Data(), bitmap_.SizeBytes());
27 ASSERT(res == 0);
28 }
29
ClearBitsInRange(size_t begin,size_t end)30 void Bitmap::ClearBitsInRange(size_t begin, size_t end)
31 {
32 CheckBitRange(begin, end);
33 if (GetWordIdx(end) == GetWordIdx(begin)) { // [begin, end] in the same word
34 ClearRangeWithinWord(begin, end);
35 return;
36 }
37
38 auto beginRoundup = RoundUp(begin, BITSPERWORD);
39 auto fnRounddown = [](BitmapWordType val) -> BitmapWordType {
40 constexpr BitmapWordType MASK = ~((static_cast<BitmapWordType>(1) << LOG_BITSPERWORD) - 1);
41 return val & MASK;
42 };
43 auto endRounddown = fnRounddown(end);
44 ClearRangeWithinWord(begin, beginRoundup);
45 ClearWords(GetWordIdx(beginRoundup), GetWordIdx(endRounddown));
46 ClearRangeWithinWord(endRounddown, end);
47 }
48
AtomicTestAndSetBit(size_t bitOffset)49 bool Bitmap::AtomicTestAndSetBit(size_t bitOffset)
50 {
51 CheckBitOffset(bitOffset);
52 auto wordIdx = GetWordIdx(bitOffset);
53 auto *wordAddr = reinterpret_cast<std::atomic<BitmapWordType> *>(&bitmap_[wordIdx]);
54 auto mask = GetBitMask(bitOffset);
55 BitmapWordType oldWord;
56 do {
57 // Atomic with acquire order reason: data race with word_addr with dependecies on reads after the load which
58 // should become visible
59 oldWord = wordAddr->load(std::memory_order_acquire);
60 if ((oldWord & mask) != 0) {
61 return true;
62 }
63 } while (!wordAddr->compare_exchange_weak(oldWord, oldWord | mask, std::memory_order_seq_cst));
64 return false;
65 }
66
AtomicTestAndClearBit(size_t bitOffset)67 bool Bitmap::AtomicTestAndClearBit(size_t bitOffset)
68 {
69 CheckBitOffset(bitOffset);
70 auto wordIdx = GetWordIdx(bitOffset);
71 auto *wordAddr = reinterpret_cast<std::atomic<BitmapWordType> *>(&bitmap_[wordIdx]);
72 auto mask = GetBitMask(bitOffset);
73 BitmapWordType oldWord;
74 do {
75 // Atomic with acquire order reason: data race with word_addr with dependecies on reads after the load which
76 // should become visible
77 oldWord = wordAddr->load(std::memory_order_acquire);
78 if ((oldWord & mask) == 0) {
79 return false;
80 }
81 } while (!wordAddr->compare_exchange_weak(oldWord, oldWord & (~mask), std::memory_order_seq_cst));
82 return true;
83 }
84
AtomicTestBit(size_t bitOffset)85 bool Bitmap::AtomicTestBit(size_t bitOffset)
86 {
87 CheckBitOffset(bitOffset);
88 auto wordIdx = GetWordIdx(bitOffset);
89 auto *wordAddr = reinterpret_cast<std::atomic<BitmapWordType> *>(&bitmap_[wordIdx]);
90 auto mask = GetBitMask(bitOffset);
91 // Atomic with acquire order reason: data race with word_addr with dependecies on reads after the load which should
92 // become visible
93 BitmapWordType word = wordAddr->load(std::memory_order_acquire);
94 return (word & mask) != 0;
95 }
96
97 } // namespace panda::mem
98