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