• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2024 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 <memory>
17 #include <vector>
18 #include <thread>
19 
20 #include "libpandabase/utils/tsan_interface.h"
21 #include "gtest/gtest.h"
22 #include "bitmap_test_base.h"
23 #include "runtime/mem/gc/bitmap.h"
24 
25 namespace ark::mem {
26 
TEST_F(BitmapTest,Init)27 TEST_F(BitmapTest, Init)
28 {
29     const size_t sz = 1_MB;
30     // NOLINTNEXTLINE(modernize-avoid-c-arrays)
31     auto bmPtr = std::make_unique<BitmapWordType[]>(sz >> MemBitmap<>::LOG_BITSPERWORD);
32     MemBitmap<> bm(ToVoidPtr(HEAP_STARTING_ADDRESS), sz, bmPtr.get());
33     EXPECT_EQ(bm.Size(), sz);
34 }
35 
TEST_F(BitmapTest,ScanRange)36 TEST_F(BitmapTest, ScanRange)
37 {
38     auto heapBegin = HEAP_STARTING_ADDRESS;
39     constexpr size_t HEAP_CAPACITY = 16_MB;
40     // NOLINTBEGIN(modernize-avoid-c-arrays)
41     auto bmPtr =
42         std::make_unique<BitmapWordType[]>((HEAP_CAPACITY >> Bitmap::LOG_BITSPERWORD) / DEFAULT_ALIGNMENT_IN_BYTES);
43     // NOLINTEND(modernize-avoid-c-arrays)
44 
45     MemBitmap<DEFAULT_ALIGNMENT_IN_BYTES> bm(ToVoidPtr(heapBegin), HEAP_CAPACITY, bmPtr.get());
46 
47     constexpr size_t BIT_SET_RANGE_END = Bitmap::BITSPERWORD * 3U;
48 
49     for (size_t j = 0; j < BIT_SET_RANGE_END; ++j) {
50         auto *obj = ToVoidPtr(heapBegin + j * DEFAULT_ALIGNMENT_IN_BYTES);
51         if ((ToUintPtr(obj) & BitmapVerify::ADDRESS_MASK_TO_SET) != 0U) {
52             bm.Set(obj);
53         }
54     }
55 
56     constexpr size_t BIT_VERIFY_RANGE_END = Bitmap::BITSPERWORD * 2;
57 
58     for (size_t i = 0; i < Bitmap::BITSPERWORD; ++i) {
59         auto *start = ToVoidPtr(heapBegin + i * DEFAULT_ALIGNMENT_IN_BYTES);
60         for (size_t j = 0; j < BIT_VERIFY_RANGE_END; ++j) {
61             auto *end = ToVoidPtr(heapBegin + (i + j) * DEFAULT_ALIGNMENT_IN_BYTES);
62             BitmapVerify(&bm, start, end);
63         }
64     }
65 }
66 
TEST_F(BitmapTest,VisitorPageAlignment)67 TEST_F(BitmapTest, VisitorPageAlignment)
68 {
69     RunTestCount<4_KB>();
70 }
71 
TEST_F(BitmapTest,OrderPageAlignment)72 TEST_F(BitmapTest, OrderPageAlignment)
73 {
74     RunTestOrder<4_KB>();
75 }
76 
77 // test check that IterateOverMarkedChunkInRange & AtomicTestAndSetBit works fine with TSAN from two threads
78 // concurrently
TEST_F(BitmapTest,TSANMultithreadingTest)79 TEST_F(BitmapTest, TSANMultithreadingTest)
80 {
81 #ifdef PANDA_TSAN_ON
82     const size_t heapCapacity = 1_MB;
83     auto bmPtr = std::make_unique<BitmapWordType[]>(heapCapacity >> MemBitmap<>::LOG_BITSPERWORD);
84     auto heapBegin = BitmapTest::HEAP_STARTING_ADDRESS;
85     MemBitmap<> bm(ToVoidPtr(heapBegin), heapCapacity, bmPtr.get());
86 
87     std::srand(0xBADDEAD);
88     size_t iterations;
89 #ifdef PANDA_NIGHTLY_TEST_ON
90     iterations = 3000U;
91 #else
92     iterations = 1000U;
93 #endif
94 
95     auto iterateThread = std::thread([&bm, &iterations] {
96         // we do less iterations for IterateOverMarkedChunks
97         for (size_t i = 0; i < iterations; i++) {
98             bm.IterateOverMarkedChunks<true>([](const void *object) { ASSERT_NE(object, nullptr); });
99         }
100     });
101 
102     auto setThread = std::thread([&bm, &heapBegin, &iterations] {
103         for (size_t i = 0; i < iterations * iterations; i++) {
104             bool value = std::rand() % 2 == 1;
105             size_t offset = FnRounddown(std::rand() % heapCapacity, 4_KB);
106 
107             if (value) {
108                 bm.AtomicTestAndSet(ToVoidPtr(heapBegin + offset));
109             } else {
110                 bm.AtomicTestAndClear(ToVoidPtr(heapBegin + offset));
111             }
112         }
113     });
114     iterateThread.join();
115     setThread.join();
116 #endif
117 }
118 
119 }  // namespace ark::mem
120