1 /*
2 * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
3 * Copyright (c) 2020 SAP SE. All rights reserved.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 *
24 */
25
26 #include "precompiled.hpp"
27 #include "memory/metaspace/chunkHeaderPool.hpp"
28 #include "memory/metaspace/counters.hpp"
29 #include "memory/metaspace/metachunk.hpp"
30 //#define LOG_PLEASE
31 #include "metaspaceGtestCommon.hpp"
32
33 using metaspace::ChunkHeaderPool;
34 using metaspace::Metachunk;
35 using metaspace::SizeCounter;
36
37 class ChunkHeaderPoolTest {
38
39 static const size_t max_cap = 0x1000;
40
41 ChunkHeaderPool _pool;
42
43 // Array of the same size as the pool max capacity; holds the allocated elements.
44 Metachunk* _elems[max_cap];
45 SizeCounter _num_allocated;
46
attempt_free_at(size_t index)47 void attempt_free_at(size_t index) {
48
49 LOG("attempt_free_at " SIZE_FORMAT ".", index);
50
51 if (_elems[index] == NULL) {
52 return;
53 }
54
55 _pool.return_chunk_header(_elems[index]);
56 _elems[index] = NULL;
57
58 _num_allocated.decrement();
59 DEBUG_ONLY(_num_allocated.check(_pool.used());)
60
61 DEBUG_ONLY(_pool.verify();)
62
63 }
64
attempt_allocate_at(size_t index)65 void attempt_allocate_at(size_t index) {
66
67 LOG("attempt_allocate_at " SIZE_FORMAT ".", index);
68
69 if (_elems[index] != NULL) {
70 return;
71 }
72
73 Metachunk* c = _pool.allocate_chunk_header();
74 EXPECT_NOT_NULL(c);
75 _elems[index] = c;
76 c->set_free();
77
78 _num_allocated.increment();
79 DEBUG_ONLY(_num_allocated.check(_pool.used());)
80
81 DEBUG_ONLY(_pool.verify();)
82 }
83
attempt_allocate_or_free_at(size_t index)84 void attempt_allocate_or_free_at(size_t index) {
85 if (_elems[index] == NULL) {
86 attempt_allocate_at(index);
87 } else {
88 attempt_free_at(index);
89 }
90 }
91
92 // Randomly allocate from the pool and free. Slight preference for allocation.
test_random_alloc_free(int num_iterations)93 void test_random_alloc_free(int num_iterations) {
94
95 for (int iter = 0; iter < num_iterations; iter++) {
96 size_t index = (size_t)os::random() % max_cap;
97 attempt_allocate_or_free_at(index);
98 }
99
100 DEBUG_ONLY(_pool.verify();)
101
102 }
103
test_once()104 static void test_once() {
105 ChunkHeaderPoolTest test;
106 test.test_random_alloc_free(100);
107 }
108
109 public:
110
ChunkHeaderPoolTest()111 ChunkHeaderPoolTest() : _pool() {
112 memset(_elems, 0, sizeof(_elems));
113 }
114
run_tests()115 static void run_tests() {
116 for (int i = 0; i < 1000; i++) {
117 test_once();
118 }
119 }
120
121 };
122
TEST_VM(metaspace,chunk_header_pool_basics)123 TEST_VM(metaspace, chunk_header_pool_basics) {
124
125 ChunkHeaderPool pool;
126 EXPECT_EQ(pool.used(), (int)0);
127 EXPECT_EQ(pool.freelist_size(), (int)0);
128
129 Metachunk* header = pool.allocate_chunk_header();
130 EXPECT_NOT_NULL(header);
131 EXPECT_EQ(pool.used(), 1);
132 EXPECT_EQ(pool.freelist_size(), (int)0);
133
134 header->set_free();
135 pool.return_chunk_header(header);
136 EXPECT_EQ(pool.used(), (int)0);
137 EXPECT_EQ(pool.freelist_size(), 1);
138
139 header = pool.allocate_chunk_header();
140 EXPECT_NOT_NULL(header);
141 EXPECT_EQ(pool.used(), 1);
142 EXPECT_EQ(pool.freelist_size(), (int)0);
143
144 header->set_free();
145 pool.return_chunk_header(header);
146 EXPECT_EQ(pool.used(), (int)0);
147 EXPECT_EQ(pool.freelist_size(), 1);
148
149 }
150
TEST_VM(metaspace,chunk_header_pool)151 TEST_VM(metaspace, chunk_header_pool) {
152 ChunkHeaderPoolTest::run_tests();
153 }
154